Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .cache/pip/http-v2/8/1/3/c/c/813cc7096c25ba43edba14a4ab40832db33af638c43e975795995aec.body +0 -0
- .cache/pip/http-v2/8/5/e/f/e/85efe0b09056afaed0a9932320bb2a590a03afe4bc35e3fffc1e85cd.body +0 -0
- .cache/pip/http-v2/8/f/4/1/0/8f410bbfc5d1848453018f07fdeb351a0d0ae8a3bcdc5a16f937935c.body +0 -0
- .cache/pip/http-v2/c/2/0/9/b/c209b6730b4a3a67d7d68f436a023e57f848dcba7c8db3fd04a54862 +0 -0
- .cache/pip/http-v2/c/5/4/0/3/c5403a101bbaf526810b4c472004bc3b03b96b7c8118e06c7a081e63.body +0 -0
- .cache/pip/http-v2/f/0/4/f/6/f04f619fe804fd38ac24d3bad7c02b3e6461727bd3a1ce45e316d44a +0 -0
- .cache/pip/http-v2/f/0/4/f/6/f04f619fe804fd38ac24d3bad7c02b3e6461727bd3a1ce45e316d44a.body +0 -0
- .cache/pip/http-v2/f/3/c/4/d/f3c4dedd1435641845fe96a7938402191795947fd69de9d823bd65e1.body +0 -0
- .local/share/jupyter/nbextensions/highlight_selected_word/main.js +419 -0
- .local/share/jupyter/nbextensions/highlighter/demo_highlighter.html +0 -0
- .local/share/jupyter/nbextensions/highlighter/export_highlights.ipynb +194 -0
- .local/share/jupyter/nbextensions/highlighter/export_highlights.pdf +0 -0
- .local/share/jupyter/nbextensions/highlighter/highlighter.css +98 -0
- .local/share/jupyter/nbextensions/highlighter/highlighter.yaml +7 -0
- .local/share/jupyter/nbextensions/highlighter/tst_highlights.html +0 -0
- .local/share/jupyter/nbextensions/highlighter/tst_highlights.ipynb +53 -0
- .local/share/jupyter/nbextensions/highlighter/tst_highlights.tex +279 -0
- .local/share/jupyter/nbextensions/hinterland/README.md +49 -0
- .local/share/jupyter/nbextensions/hinterland/hinterland.yaml +73 -0
- .local/share/jupyter/nbextensions/init_cell/README.md +44 -0
- .local/share/jupyter/nbextensions/init_cell/cell_toolbar_menu.png +0 -0
- .local/share/jupyter/nbextensions/init_cell/icon.png +0 -0
- .local/share/jupyter/nbextensions/init_cell/init_cell.yaml +17 -0
- .local/share/jupyter/nbextensions/init_cell/main.js +157 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/keyboard_shortcut_editor.yaml +12 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/kse_components.js +364 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/main.css +40 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/main.js +778 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/quickhelp_shim.js +207 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_add_new_select_action.png +0 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_comma.png +0 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_conflict.png +0 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_dropdown.png +0 -0
- .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_shortcut_editor_success.png +0 -0
- .local/share/jupyter/nbextensions/limit_output/icon.png +0 -0
- .local/share/jupyter/nbextensions/limit_output/limit-output.yaml +30 -0
- .local/share/jupyter/nbextensions/livemdpreview/livemdpreview.js +112 -0
- .local/share/jupyter/nbextensions/livemdpreview/livemdpreview.yml +24 -0
- .local/share/jupyter/nbextensions/load_tex_macros/icon.png +0 -0
- .local/share/jupyter/nbextensions/load_tex_macros/readme.md +17 -0
- .local/share/jupyter/nbextensions/move_selected_cells/main.js +87 -0
- .local/share/jupyter/nbextensions/navigation-hotkeys/hotkeys.yaml +25 -0
- .local/share/jupyter/nbextensions/nbTranslate/README.md +56 -0
- .local/share/jupyter/nbextensions/nbTranslate/nbTranslate.js +622 -0
- .local/share/jupyter/nbextensions/notify/notification.png +0 -0
- .local/share/jupyter/nbextensions/notify/notify.js +203 -0
- .local/share/jupyter/nbextensions/notify/notify.mp3 +0 -0
- .local/share/jupyter/nbextensions/printview/icon.png +0 -0
- .local/share/jupyter/nbextensions/printview/main.js +75 -0
- .local/share/jupyter/nbextensions/printview/printview-button.png +0 -0
.cache/pip/http-v2/8/1/3/c/c/813cc7096c25ba43edba14a4ab40832db33af638c43e975795995aec.body
ADDED
Binary file (610 kB). View file
|
|
.cache/pip/http-v2/8/5/e/f/e/85efe0b09056afaed0a9932320bb2a590a03afe4bc35e3fffc1e85cd.body
ADDED
Binary file (125 kB). View file
|
|
.cache/pip/http-v2/8/f/4/1/0/8f410bbfc5d1848453018f07fdeb351a0d0ae8a3bcdc5a16f937935c.body
ADDED
Binary file (447 kB). View file
|
|
.cache/pip/http-v2/c/2/0/9/b/c209b6730b4a3a67d7d68f436a023e57f848dcba7c8db3fd04a54862
ADDED
Binary file (1.2 kB). View file
|
|
.cache/pip/http-v2/c/5/4/0/3/c5403a101bbaf526810b4c472004bc3b03b96b7c8118e06c7a081e63.body
ADDED
Binary file (266 kB). View file
|
|
.cache/pip/http-v2/f/0/4/f/6/f04f619fe804fd38ac24d3bad7c02b3e6461727bd3a1ce45e316d44a
ADDED
Binary file (1.16 kB). View file
|
|
.cache/pip/http-v2/f/0/4/f/6/f04f619fe804fd38ac24d3bad7c02b3e6461727bd3a1ce45e316d44a.body
ADDED
Binary file (12.2 kB). View file
|
|
.cache/pip/http-v2/f/3/c/4/d/f3c4dedd1435641845fe96a7938402191795947fd69de9d823bd65e1.body
ADDED
Binary file (17.5 kB). View file
|
|
.local/share/jupyter/nbextensions/highlight_selected_word/main.js
ADDED
@@ -0,0 +1,419 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Enable highlighting of matching words in cells' CodeMirror editors.
|
3 |
+
*
|
4 |
+
* This extension was adapted from the CodeMirror addon
|
5 |
+
* codemirror/addon/search/match-highlighter.js
|
6 |
+
*/
|
7 |
+
|
8 |
+
define([
|
9 |
+
'require',
|
10 |
+
'jquery',
|
11 |
+
'base/js/namespace',
|
12 |
+
'notebook/js/cell',
|
13 |
+
'notebook/js/codecell',
|
14 |
+
'codemirror/lib/codemirror',
|
15 |
+
// The mark-selection addon is need to ensure that the highlighting styles
|
16 |
+
// are *not* applied to the actual selection, as otherwise it can become
|
17 |
+
// difficult to see which is selected vs just highlighted.
|
18 |
+
'codemirror/addon/selection/mark-selection'
|
19 |
+
], function (
|
20 |
+
requirejs,
|
21 |
+
$,
|
22 |
+
Jupyter,
|
23 |
+
cell,
|
24 |
+
codecell,
|
25 |
+
CodeMirror
|
26 |
+
) {
|
27 |
+
'use strict';
|
28 |
+
|
29 |
+
var Cell = cell.Cell;
|
30 |
+
var CodeCell = codecell.CodeCell;
|
31 |
+
|
32 |
+
var mod_name = 'highlight_selected_word';
|
33 |
+
var log_prefix = '[' + mod_name + ']';
|
34 |
+
var menu_toggle_class = 'highlight_selected_word_toggle';
|
35 |
+
|
36 |
+
// Parameters (potentially) stored in server config.
|
37 |
+
// This object gets updated on config load.
|
38 |
+
var params = {
|
39 |
+
highlight_across_all_cells: true,
|
40 |
+
enable_on_load : true,
|
41 |
+
code_cells_only: false,
|
42 |
+
delay: 100,
|
43 |
+
words_only: false,
|
44 |
+
highlight_only_whole_words: true,
|
45 |
+
min_chars: 2,
|
46 |
+
show_token: '[\\w$]',
|
47 |
+
highlight_color: '#90EE90',
|
48 |
+
highlight_color_blurred: '#BBFFBB',
|
49 |
+
highlight_style: 'matchhighlight',
|
50 |
+
trim: true,
|
51 |
+
use_toggle_hotkey: false,
|
52 |
+
toggle_hotkey: 'alt-h',
|
53 |
+
outlines_only: false,
|
54 |
+
outline_width: 2,
|
55 |
+
only_cells_in_scroll: true,
|
56 |
+
scroll_min_delay: 100,
|
57 |
+
hide_selections_in_unfocussed: false,
|
58 |
+
};
|
59 |
+
|
60 |
+
// these are set on registering the action(s)
|
61 |
+
var action_names = {
|
62 |
+
toggle: '',
|
63 |
+
};
|
64 |
+
|
65 |
+
/**
|
66 |
+
* the codemirror matchHighlighter has a separate state object for each cm
|
67 |
+
* instance, but since our state is global over all cells' editors, we can
|
68 |
+
* use a single object for simplicity, and don't need to store options
|
69 |
+
* inside the state, since we have closure-level access to the params
|
70 |
+
* object above.
|
71 |
+
*/
|
72 |
+
var globalState = {
|
73 |
+
active: false,
|
74 |
+
timeout: null, // only want one timeout
|
75 |
+
scrollTimeout: null,
|
76 |
+
overlay: null, // one overlay suffices, as all cells use the same one
|
77 |
+
};
|
78 |
+
|
79 |
+
// define a CodeMirror option for highlighting matches in all cells
|
80 |
+
CodeMirror.defineOption("highlightSelectionMatchesInJupyterCells", false, function (cm, val, old) {
|
81 |
+
if (old && old != CodeMirror.Init) {
|
82 |
+
globalState.active = false;
|
83 |
+
// remove from all relevant, this can fail gracefully if not present
|
84 |
+
get_relevant_cells().forEach(function (cell, idx, array) {
|
85 |
+
cell.code_mirror.removeOverlay(mod_name);
|
86 |
+
});
|
87 |
+
globalState.overlay = null;
|
88 |
+
clearTimeout(globalState.timeout);
|
89 |
+
globalState.timeout = null;
|
90 |
+
cm.off("cursorActivity", callbackCursorActivity);
|
91 |
+
cm.off("focus", callbackOnFocus);
|
92 |
+
}
|
93 |
+
if (val) {
|
94 |
+
if (cm.hasFocus()) {
|
95 |
+
globalState.active = true;
|
96 |
+
highlightMatchesInAllRelevantCells(cm);
|
97 |
+
}
|
98 |
+
else {
|
99 |
+
cm.on("focus", callbackOnFocus);
|
100 |
+
}
|
101 |
+
cm.on("cursorActivity", callbackCursorActivity);
|
102 |
+
}
|
103 |
+
});
|
104 |
+
|
105 |
+
/**
|
106 |
+
* The functions callbackCursorActivity, callbackOnFocus and
|
107 |
+
* scheduleHighlight are taken without major modification from cm's
|
108 |
+
* match-highlighter.
|
109 |
+
* The main difference is using our global state rather than
|
110 |
+
* match-highlighter's per-cm state, and a different highlighting function
|
111 |
+
* is scheduled.
|
112 |
+
*/
|
113 |
+
function callbackCursorActivity (cm) {
|
114 |
+
if (globalState.active || cm.hasFocus()) {
|
115 |
+
scheduleHighlight(cm);
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
function callbackOnFocus (cm) {
|
120 |
+
// unlike cm match-highlighter, we *do* want to schedule a highight on
|
121 |
+
// focussing the editor
|
122 |
+
globalState.active = true;
|
123 |
+
scheduleHighlight(cm);
|
124 |
+
}
|
125 |
+
|
126 |
+
function scheduleHighlight (cm) {
|
127 |
+
clearTimeout(globalState.timeout);
|
128 |
+
globalState.timeout = setTimeout(function () { highlightMatchesInAllRelevantCells(cm); }, params.delay);
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Adapted from cm match-highlighter's highlightMatches, but adapted to
|
133 |
+
* use our global state and parameters, plus work either for only the
|
134 |
+
* current editor, or multiple cells' editors.
|
135 |
+
*/
|
136 |
+
function highlightMatchesInAllRelevantCells (cm) {
|
137 |
+
var newOverlay = null;
|
138 |
+
|
139 |
+
var re = params.show_token === true ? /[\w$]/ : params.show_token;
|
140 |
+
var from = cm.getCursor('from');
|
141 |
+
if (!cm.somethingSelected() && params.show_token) {
|
142 |
+
var line = cm.getLine(from.line), start = from.ch, end = start;
|
143 |
+
while (start && re.test(line.charAt(start - 1))) {
|
144 |
+
--start;
|
145 |
+
}
|
146 |
+
while (end < line.length && re.test(line.charAt(end))) {
|
147 |
+
++end;
|
148 |
+
}
|
149 |
+
if (start < end) {
|
150 |
+
newOverlay = makeOverlay(line.slice(start, end), re, params.highlight_style);
|
151 |
+
}
|
152 |
+
}
|
153 |
+
else {
|
154 |
+
var to = cm.getCursor("to");
|
155 |
+
if (from.line == to.line) {
|
156 |
+
if (!params.words_only || isWord(cm, from, to)) {
|
157 |
+
var selection = cm.getRange(from, to);
|
158 |
+
if (params.trim) {
|
159 |
+
selection = selection.replace(/^\s+|\s+$/g, "");
|
160 |
+
}
|
161 |
+
if (selection.length >= params.min_chars) {
|
162 |
+
var hasBoundary = params.highlight_only_whole_words ? (re instanceof RegExp ? re : /[\w$]/) : false;
|
163 |
+
newOverlay = makeOverlay(selection, hasBoundary, params.highlight_style);
|
164 |
+
}
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
var siterect = document.getElementById('site').getBoundingClientRect();
|
170 |
+
var viewtop = siterect.top, viewbot = siterect.bottom;
|
171 |
+
var cells = params.highlight_across_all_cells ? get_relevant_cells() : [
|
172 |
+
$(cm.getWrapperElement()).closest('.cell').data('cell')
|
173 |
+
];
|
174 |
+
cells.forEach(function (cell, idx, array) {
|
175 |
+
// cm.operation to delay updating DOM until all work is done
|
176 |
+
cell.code_mirror.operation(function () {
|
177 |
+
cell.code_mirror.removeOverlay(mod_name);
|
178 |
+
if (newOverlay && is_in_view(cell.element[0], viewtop, viewbot)) {
|
179 |
+
cell.code_mirror.addOverlay(newOverlay);
|
180 |
+
}
|
181 |
+
});
|
182 |
+
});
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* isWord, boundariesAround and makeOverlay come pretty much directly from
|
187 |
+
* Codemirror/addon/search/matchHighlighter
|
188 |
+
* since they don't use state or config values.
|
189 |
+
*/
|
190 |
+
function isWord (cm, from, to) {
|
191 |
+
var str = cm.getRange(from, to);
|
192 |
+
if (str.match(/^\w+$/) !== null) {
|
193 |
+
var pos, chr;
|
194 |
+
if (from.ch > 0) {
|
195 |
+
pos = {line: from.line, ch: from.ch - 1};
|
196 |
+
chr = cm.getRange(pos, from);
|
197 |
+
if (chr.match(/\W/) === null) {
|
198 |
+
return false;
|
199 |
+
}
|
200 |
+
}
|
201 |
+
if (to.ch < cm.getLine(from.line).length) {
|
202 |
+
pos = {line: to.line, ch: to.ch + 1};
|
203 |
+
chr = cm.getRange(to, pos);
|
204 |
+
if (chr.match(/\W/) === null) {
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
return true;
|
209 |
+
}
|
210 |
+
return false;
|
211 |
+
}
|
212 |
+
function boundariesAround (stream, re) {
|
213 |
+
return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
|
214 |
+
(stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
|
215 |
+
}
|
216 |
+
function makeOverlay (query, hasBoundary, style) {
|
217 |
+
return {
|
218 |
+
name: mod_name,
|
219 |
+
token: function (stream) {
|
220 |
+
if (stream.match(query) &&
|
221 |
+
(!hasBoundary || boundariesAround(stream, hasBoundary))) {
|
222 |
+
return style;
|
223 |
+
}
|
224 |
+
stream.next();
|
225 |
+
if (!stream.skipTo(query.charAt(0))) {
|
226 |
+
stream.skipToEnd();
|
227 |
+
}
|
228 |
+
}
|
229 |
+
};
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Returns true if part of elem is visible between viewtop & viewbot
|
234 |
+
*/
|
235 |
+
var is_in_view = function (elem, viewtop, viewbot) {
|
236 |
+
var rect = elem.getBoundingClientRect();
|
237 |
+
// hidden elements show height 0
|
238 |
+
return (rect.top < viewbot) && (rect.bottom > viewtop) && rect.height;
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Return an array of cells to which match highlighting is relevant,
|
243 |
+
* dependent on the code_cells_only parameter
|
244 |
+
*/
|
245 |
+
function get_relevant_cells () {
|
246 |
+
var cells = Jupyter.notebook.get_cells();
|
247 |
+
return params.code_cells_only ? cells.filter(function (c) { return (c instanceof CodeCell); }) : cells;
|
248 |
+
}
|
249 |
+
|
250 |
+
function add_menu_item () {
|
251 |
+
if ($('#view_menu').find('.' + menu_toggle_class).length < 1) {
|
252 |
+
var menu_item = $('<li/>')
|
253 |
+
.appendTo('#view_menu');
|
254 |
+
var menu_link = $('<a/>')
|
255 |
+
.text('Highlight selected word')
|
256 |
+
.addClass(menu_toggle_class)
|
257 |
+
.attr({
|
258 |
+
title: 'Highlight all instances of the selected word in the current editor',
|
259 |
+
href: '#',
|
260 |
+
})
|
261 |
+
.on('click', function () { toggle_highlight_selected(); })
|
262 |
+
.appendTo(menu_item);
|
263 |
+
$('<i/>')
|
264 |
+
.addClass('fa menu-icon pull-right')
|
265 |
+
.css({'margin-top': '-2px', 'margin-right': '-16px'})
|
266 |
+
.prependTo(menu_link);
|
267 |
+
}
|
268 |
+
}
|
269 |
+
|
270 |
+
var throttled_highlight = (function () {
|
271 |
+
var last, throttle_timeout;
|
272 |
+
return function throttled_highlight (cm) {
|
273 |
+
var now = Number(new Date());
|
274 |
+
var do_it = function () {
|
275 |
+
last = Number(new Date());
|
276 |
+
highlightMatchesInAllRelevantCells(cm);
|
277 |
+
};
|
278 |
+
var remaining = last + params.scroll_min_delay - now;
|
279 |
+
if (last && remaining > 0) {
|
280 |
+
clearTimeout(throttle_timeout);
|
281 |
+
throttle_timeout = setTimeout(do_it, remaining);
|
282 |
+
}
|
283 |
+
else {
|
284 |
+
last = undefined; // so we will do it first time next streak
|
285 |
+
do_it();
|
286 |
+
}
|
287 |
+
}
|
288 |
+
})();
|
289 |
+
|
290 |
+
function scroll_handler (evt) {
|
291 |
+
if (globalState.active && Jupyter.notebook.mode === 'edit' && globalState.overlay) {
|
292 |
+
// add overlay to cells now in view which don't already have it.
|
293 |
+
// Don't bother removing from those no longer in view, as it would just
|
294 |
+
// cause more work for the browser, without any benefit
|
295 |
+
var siterect = document.getElementById('site').getBoundingClientRect();
|
296 |
+
get_relevant_cells().forEach(function (cell) {
|
297 |
+
var cm = cell.code_mirror;
|
298 |
+
if (is_in_view(cell.element, siterect.top, siterect.bot)) {
|
299 |
+
var need_it = !cm.state.overlays.some(function(ovr) {
|
300 |
+
return ovr.modeSpec.name === mod_name; });
|
301 |
+
if (need_it) cm.addOverlay(globalState.overlay);
|
302 |
+
}
|
303 |
+
});
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
function toggle_highlight_selected (set_on) {
|
308 |
+
set_on = (set_on !== undefined) ? set_on : !params.enable_on_load;
|
309 |
+
// update config to make changes persistent
|
310 |
+
if (set_on !== params.enable_on_load) {
|
311 |
+
params.enable_on_load = set_on;
|
312 |
+
Jupyter.notebook.config.update({highlight_selected_word: {enable_on_load: set_on}});
|
313 |
+
}
|
314 |
+
|
315 |
+
// Change defaults for new cells:
|
316 |
+
var cm_conf = (params.code_cells_only ? CodeCell : Cell).options_default.cm_config;
|
317 |
+
cm_conf.highlightSelectionMatchesInJupyterCells = cm_conf.styleSelectedText = set_on;
|
318 |
+
|
319 |
+
// And change any existing cells:
|
320 |
+
get_relevant_cells().forEach(function (cell, idx, array) {
|
321 |
+
cell.code_mirror.setOption('highlightSelectionMatchesInJupyterCells', set_on);
|
322 |
+
cell.code_mirror.setOption('styleSelectedText', set_on);
|
323 |
+
});
|
324 |
+
// update menu class
|
325 |
+
$('.' + menu_toggle_class + ' > .fa').toggleClass('fa-check', set_on);
|
326 |
+
// bind/unbind scroll handler
|
327 |
+
$('#site')[
|
328 |
+
(params.only_cells_in_scroll && params.scroll_min_delay > 0) ? 'on' : 'off'
|
329 |
+
]('scroll', scroll_handler);
|
330 |
+
console.log(log_prefix, 'toggled', set_on ? 'on' : 'off');
|
331 |
+
return set_on;
|
332 |
+
}
|
333 |
+
|
334 |
+
function register_new_actions () {
|
335 |
+
action_names.toggle = Jupyter.keyboard_manager.actions.register({
|
336 |
+
handler : function (env) { toggle_highlight_selected(); },
|
337 |
+
help : "Toggle highlighting of selected word",
|
338 |
+
icon : 'fa-language',
|
339 |
+
help_index: 'c1'
|
340 |
+
}, 'toggle', mod_name);
|
341 |
+
}
|
342 |
+
|
343 |
+
function bind_hotkeys () {
|
344 |
+
if (params.use_toggle_hotkey && params.toggle_hotkey) {
|
345 |
+
Jupyter.keyboard_manager.command_shortcuts.add_shortcut(params.toggle_hotkey, action_names.toggle);
|
346 |
+
Jupyter.keyboard_manager.edit_shortcuts.add_shortcut(params.toggle_hotkey, action_names.toggle);
|
347 |
+
}
|
348 |
+
}
|
349 |
+
|
350 |
+
function insert_css () {
|
351 |
+
var css = [// in unselected cells, matches have blurred color
|
352 |
+
// in selected cells, we keep CodeMirror highlight for the actual selection to avoid confusion
|
353 |
+
'.edit_mode .unselected .CodeMirror .cm-matchhighlight {',
|
354 |
+
' background-color: ' + params.highlight_color_blurred + ';',
|
355 |
+
'}',
|
356 |
+
|
357 |
+
// in active cell, matches which are not the current selection have focussed color
|
358 |
+
'.edit_mode .CodeMirror.CodeMirror-focused :not(.CodeMirror-selectedtext).cm-matchhighlight {',
|
359 |
+
' background-color: ' + params.highlight_color + ';',
|
360 |
+
'}',
|
361 |
+
|
362 |
+
// in all cells, outline matches have blurred color
|
363 |
+
'.edit_mode .CodeMirror .cm-matchhighlight-outline {',
|
364 |
+
' outline-style: solid;',
|
365 |
+
' outline-width: ' + params.outline_width + 'px;',
|
366 |
+
' outline-color: ' + params.highlight_color_blurred + ';',
|
367 |
+
'}',
|
368 |
+
|
369 |
+
// in active cell, outline matches have focussed color
|
370 |
+
'.edit_mode .CodeMirror.CodeMirror-focused .cm-matchhighlight-outline {',
|
371 |
+
' outline-color: ' + params.highlight_color + ';',
|
372 |
+
'}'
|
373 |
+
].join('\n');
|
374 |
+
|
375 |
+
if (params.hide_selections_in_unfocussed) {
|
376 |
+
css += [
|
377 |
+
// in unselected cells, selections which are not matches should have no background
|
378 |
+
'.unselected .CodeMirror :not(.cm-matchhighlight).CodeMirror-selected,',
|
379 |
+
'.unselected .CodeMirror :not(.cm-matchhighlight).CodeMirror-selectedtext {',
|
380 |
+
' background: initial;',
|
381 |
+
'}',
|
382 |
+
].join('\n');
|
383 |
+
}
|
384 |
+
|
385 |
+
$('<style type="text/css" id="highlight_selected_word_css">').appendTo('head').html(css);
|
386 |
+
}
|
387 |
+
|
388 |
+
function load_extension () {
|
389 |
+
// add menu item, as we need it to exist for later
|
390 |
+
// toggle_highlight_selected call to set its icon status
|
391 |
+
add_menu_item();
|
392 |
+
|
393 |
+
// load config & toggle on/off
|
394 |
+
Jupyter.notebook.config.loaded
|
395 |
+
.then(function () {
|
396 |
+
$.extend(true, params, Jupyter.notebook.config.data.highlight_selected_word);
|
397 |
+
}, function on_error (reason) {
|
398 |
+
console.warn(log_prefix, 'error loading config:', reason);
|
399 |
+
})
|
400 |
+
.then(insert_css)
|
401 |
+
.then(function () {
|
402 |
+
params.show_token = params.show_token ? new RegExp(params.show_token) : false;
|
403 |
+
if (params.outlines_only) {
|
404 |
+
params.highlight_style += '-outline'
|
405 |
+
}
|
406 |
+
// set highlight on/off
|
407 |
+
toggle_highlight_selected(params.enable_on_load);
|
408 |
+
|
409 |
+
register_new_actions();
|
410 |
+
bind_hotkeys();
|
411 |
+
})
|
412 |
+
// finally log any error we encountered
|
413 |
+
.catch(function on_error (reason) { console.warn(log_prefix, 'error loading:', reason); });
|
414 |
+
}
|
415 |
+
|
416 |
+
return {
|
417 |
+
load_ipython_extension : load_extension
|
418 |
+
};
|
419 |
+
});
|
.local/share/jupyter/nbextensions/highlighter/demo_highlighter.html
ADDED
The diff for this file is too large to render.
See raw diff
|
|
.local/share/jupyter/nbextensions/highlighter/export_highlights.ipynb
ADDED
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "markdown",
|
5 |
+
"metadata": {},
|
6 |
+
"source": [
|
7 |
+
"# Exporting the notebook\n",
|
8 |
+
"\n",
|
9 |
+
"As suggested by @juhasch, it is interesting to keep the highlights when exporting the notebook to another format. We give and explain below some possibilities:"
|
10 |
+
]
|
11 |
+
},
|
12 |
+
{
|
13 |
+
"cell_type": "markdown",
|
14 |
+
"metadata": {},
|
15 |
+
"source": [
|
16 |
+
"## Short version\n",
|
17 |
+
"- Html export:\n",
|
18 |
+
"```bash\n",
|
19 |
+
" jupyter nbconvert FILE --config JUPYTER_DATA_DIR/extensions/highlight_html_cfg.py \n",
|
20 |
+
"```\n",
|
21 |
+
"- LaTeX export:\n",
|
22 |
+
"```bash\n",
|
23 |
+
" jupyter nbconvert FILE --config JUPYTER_DATA_DIR/extensions/highlight_latex_cfg.py \n",
|
24 |
+
"```\n",
|
25 |
+
"where JUPYTER_DATA_DIR can be found from the output of\n",
|
26 |
+
"```bash\n",
|
27 |
+
" jupyter --paths\n",
|
28 |
+
"```\n",
|
29 |
+
"eg `~/.local/share/jupyter` in my case. Seems to be `c:\\users\\NAME\\AppData\\Roaming\\jupyter` under Windows. \n",
|
30 |
+
"\n",
|
31 |
+
"Examples can be found here: [initial notebook](tst_highlights.ipynb), [html version](tst_highlights.html), [pdf version](tst_highlights.pdf) (after an additional LaTeX $\\rightarrow$ pdf compilation). "
|
32 |
+
]
|
33 |
+
},
|
34 |
+
{
|
35 |
+
"cell_type": "markdown",
|
36 |
+
"metadata": {},
|
37 |
+
"source": [
|
38 |
+
"## Html export\n",
|
39 |
+
"This is quite easy. Actually, highlight formatting embedded in markdown cells is preserved while converting with the standard\n",
|
40 |
+
"```bash\n",
|
41 |
+
"jupyter nbconvert file.ipynb\n",
|
42 |
+
"```\n",
|
43 |
+
"\n",
|
44 |
+
"However, the css file is missing and must be added. Here we have several possibilities\n",
|
45 |
+
"\n",
|
46 |
+
"- Embed the css *within* the notebook. For that, consider the last cell of the present notebook. This code reads the css file `highlighter.css` in the extension directory and displays the corresponding style. So doing the `<style> ...</style>` section will be present in the cell output and interpreted by the web browser. Drawbacks of this solution is that user still have to execute this cell and that the this is not language agnostic. \n",
|
47 |
+
"- Use a **template file** to link or include the css file during conversion. Such a file is provided as `templates/highlighter.tpl`. It was choosen here to *include* the css content in the produced html file rather than linking it. This avoids the necessity to keep the css file with the html files. \n",
|
48 |
+
" - This works directly if the css resides in the same directory as the file the user is attempting to convert --thus requires the user to copy `highlighter.css` in the current directory. Then the conversion is simply \n",
|
49 |
+
"```bash\n",
|
50 |
+
" jupyter nbconvert file.ipynb --template highlighter\n",
|
51 |
+
"```\n",
|
52 |
+
"\n",
|
53 |
+
"- It still remains two problems with this approach. First, it can be annoying to have to systematically copy the css file in the current directory. Second, the data within the html tags is not converted (and thus markdown remains unmodified). A solution is to use a pair of preprocessor/postprocessor that modify the html tags and enable the subsequent markdown to html converter to operate on the included data. Also, a config file is provided which redefines the template path to enable direct inclusion of the css file in the extension directory. Unfortunately, <span class=\"mark\">it seems that the *full path* to the config file has to be provided</span>. This file resides in the extensions subdirectory of the jupyter_data_dir. The path can be found by looking at the output of\n",
|
54 |
+
"```bash\n",
|
55 |
+
" jupyter --paths\n",
|
56 |
+
"```\n",
|
57 |
+
"Then the command to issue for converting the notebook to html is\n",
|
58 |
+
"```bash\n",
|
59 |
+
" jupyter nbconvert FILE --config JUPYTER_DATA_DIR/extensions/highlight_html_cfg.py \n",
|
60 |
+
"```\n",
|
61 |
+
"\n",
|
62 |
+
"For instance\n",
|
63 |
+
"```bash\n",
|
64 |
+
"jupyter nbconvert tst_highlights.ipynb --config ~/.local/share/jupyter/extensions/highlight_html_cfg.py \n",
|
65 |
+
"```"
|
66 |
+
]
|
67 |
+
},
|
68 |
+
{
|
69 |
+
"cell_type": "markdown",
|
70 |
+
"metadata": {},
|
71 |
+
"source": [
|
72 |
+
"## LaTeX export\n",
|
73 |
+
"This is a bit more complicated since the direct conversion removes all html formatting present in markdown cells. Thus use again a **preprocessor** which runs before the markdown $\\rightarrow$ LaTeX conversion. In turn, it appears that we also need to postprocess the result. \n",
|
74 |
+
"\n",
|
75 |
+
"Three LaTeX commands, namely *highlighta, highlightb, highlightc*, and three environments *highlightA, highlightB, highlightC* are defined. Highlighting html markup is then transformed into the corresponding LaTeX commands and the text for completely highlighted cells is put in the adequate LaTeX environment. \n",
|
76 |
+
"\n",
|
77 |
+
"Pre and PostProcessor classes are defined in the file `pp_highlighter.py` located in the `extensions` directory. A LaTeX template, that includes the necessary packages and the definitions of commands/environments is provides as `highlighter.tplx` in the template directory. \n",
|
78 |
+
"The template inherits from `article.ltx`. For more complex scenarios, typically if the latex template file has be customized, the user shall modify its template or inherit from his base template rather than from article. \n",
|
79 |
+
"\n",
|
80 |
+
"Finally, a config file fixes the different options for the conversion. Then the command to issue is simply \n",
|
81 |
+
"```bash\n",
|
82 |
+
" jupyter nbconvert FILE --config JUPYTER_DATA_DIR/extensions/highlight_latex_cfg.py \n",
|
83 |
+
"```\n",
|
84 |
+
"e.g. \n",
|
85 |
+
"```bash\n",
|
86 |
+
"jupyter nbconvert tst_highlights.ipynb --config ~/.local/share/jupyter/extensions/highlight_latex_cfg.py \n",
|
87 |
+
"```\n"
|
88 |
+
]
|
89 |
+
},
|
90 |
+
{
|
91 |
+
"cell_type": "markdown",
|
92 |
+
"metadata": {},
|
93 |
+
"source": [
|
94 |
+
"## Configuring paths\n",
|
95 |
+
"\n",
|
96 |
+
"<span class=\"mark\">For those who do not have taken the extension from the `jupyter_contrib_nbextensions` repository or have not configured extensions via its `setup.py` utility,</span> a file `set_paths.py` is present in the extension directory (it is merely a verbatim copy of the relevant parts in setup.py). This file configure the paths to the `templates` and `extension` directories. It should be executed by something like\n",
|
97 |
+
"```bash\n",
|
98 |
+
"python3 set_paths.py\n",
|
99 |
+
"```\n",
|
100 |
+
"Additionaly, you may also have to execute `mv_paths.py` if you installed from the original repo via `jupyter nbextension install ..`\n",
|
101 |
+
"```bash\n",
|
102 |
+
"python3 mv_paths.py\n",
|
103 |
+
"```"
|
104 |
+
]
|
105 |
+
},
|
106 |
+
{
|
107 |
+
"cell_type": "markdown",
|
108 |
+
"metadata": {},
|
109 |
+
"source": [
|
110 |
+
"## Example for embedding the css within the notebook before conversion"
|
111 |
+
]
|
112 |
+
},
|
113 |
+
{
|
114 |
+
"cell_type": "code",
|
115 |
+
"execution_count": 18,
|
116 |
+
"metadata": {
|
117 |
+
"collapsed": false
|
118 |
+
},
|
119 |
+
"outputs": [
|
120 |
+
{
|
121 |
+
"data": {
|
122 |
+
"text/html": [
|
123 |
+
"<style>.mark {\n",
|
124 |
+
" background-color: yellow;\n",
|
125 |
+
" color: red;\n",
|
126 |
+
" display:inline-block;\n",
|
127 |
+
"}\n",
|
128 |
+
"\n",
|
129 |
+
".burk {\n",
|
130 |
+
" background-color: red;\n",
|
131 |
+
" color: yellow;\n",
|
132 |
+
" display:inline-block;\n",
|
133 |
+
"}\n",
|
134 |
+
"\n",
|
135 |
+
".girk {\n",
|
136 |
+
" background-color: lime;\n",
|
137 |
+
" color: red;\n",
|
138 |
+
" display:inline-block;\n",
|
139 |
+
"}\n",
|
140 |
+
"\n",
|
141 |
+
"\n",
|
142 |
+
".btnw{\n",
|
143 |
+
" background-color: white;\n",
|
144 |
+
"}\n",
|
145 |
+
"\n",
|
146 |
+
".ret {\n",
|
147 |
+
" margin-left: -1em;\n",
|
148 |
+
"}\n",
|
149 |
+
"</style>"
|
150 |
+
],
|
151 |
+
"text/plain": [
|
152 |
+
"<IPython.core.display.HTML object>"
|
153 |
+
]
|
154 |
+
},
|
155 |
+
"execution_count": 18,
|
156 |
+
"metadata": {},
|
157 |
+
"output_type": "execute_result"
|
158 |
+
}
|
159 |
+
],
|
160 |
+
"source": [
|
161 |
+
"from IPython.core.display import display, HTML\n",
|
162 |
+
"from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir\n",
|
163 |
+
"import os\n",
|
164 |
+
"csspath=os.path.join(jupyter_data_dir(),'nbextensions',\n",
|
165 |
+
" 'highlighter','highlighter.css')\n",
|
166 |
+
"HTML('<style>'+open(csspath, \"r\").read()+'</style>')"
|
167 |
+
]
|
168 |
+
}
|
169 |
+
],
|
170 |
+
"metadata": {
|
171 |
+
"interactive_sols": {
|
172 |
+
"cbx_id": 1
|
173 |
+
},
|
174 |
+
"kernelspec": {
|
175 |
+
"display_name": "Python 3",
|
176 |
+
"language": "python",
|
177 |
+
"name": "python3"
|
178 |
+
},
|
179 |
+
"language_info": {
|
180 |
+
"codemirror_mode": {
|
181 |
+
"name": "ipython",
|
182 |
+
"version": 3
|
183 |
+
},
|
184 |
+
"file_extension": ".py",
|
185 |
+
"mimetype": "text/x-python",
|
186 |
+
"name": "python",
|
187 |
+
"nbconvert_exporter": "python",
|
188 |
+
"pygments_lexer": "ipython3",
|
189 |
+
"version": "3.4.3+"
|
190 |
+
},
|
191 |
+
},
|
192 |
+
"nbformat": 4,
|
193 |
+
"nbformat_minor": 0
|
194 |
+
}
|
.local/share/jupyter/nbextensions/highlighter/export_highlights.pdf
ADDED
Binary file (116 kB). View file
|
|
.local/share/jupyter/nbextensions/highlighter/highlighter.css
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.mark {
|
2 |
+
background-color: #f2ee97;
|
3 |
+
color: black;
|
4 |
+
display: inline;
|
5 |
+
}
|
6 |
+
|
7 |
+
.burk {
|
8 |
+
background-color: #ff9292;
|
9 |
+
color: #f9f9f9;
|
10 |
+
display: inline;
|
11 |
+
}
|
12 |
+
|
13 |
+
.girk {
|
14 |
+
background-color: #afe5ad;
|
15 |
+
color: black;
|
16 |
+
display: inline;
|
17 |
+
}
|
18 |
+
|
19 |
+
.birk {
|
20 |
+
background-color: #83b8f4;
|
21 |
+
color: #fff;
|
22 |
+
display: inline;
|
23 |
+
}
|
24 |
+
|
25 |
+
.pirk {
|
26 |
+
background-color: #ecb3d2;
|
27 |
+
color: #000;
|
28 |
+
display: inline;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**/
|
32 |
+
|
33 |
+
button.mark {
|
34 |
+
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 297 297' style='enable-background:new 0 0 297 297;' xml:space='preserve'%3E%3Cg%3E%3Cg id='XMLID_48_'%3E%3Cg%3E%3Cpath style='fill:%23fff;' d='M63.648,169.162l71.18,71.19l-61.09,12.21c-0.93,0.19-1.78,0.65-2.45,1.32l-9.74,9.74 l-21.17-21.18l9.74-9.73c0.66-0.67,1.12-1.53,1.31-2.45L63.648,169.162z'/%3E%3Cpath style='fill:%23000;' d='M230.278,81.592c2.81,2.81,2.81,7.38,0,10.19l-73.19,73.2c-2.81,2.81-7.38,2.81-10.19,0 l-7.62-7.62c-2.81-2.81-2.81-7.38,0-10.19l73.19-73.2c1.36-1.36,3.17-2.11,5.1-2.11c1.92,0,3.73,0.75,5.09,2.11L230.278,81.592z' /%3E%3Cpolygon style='fill:%23f2ee97;' points='53.918,271.242 45.428,279.732 13.668,269.152 32.748,250.072 '/%3E%3Cpath style='fill:%23f2ee97;' d='M283.918,54.022c4.41,4.41,4.71,11.58,0.68,16.34l-140.34,165.86l-76.48-76.49l165.85-140.34 c4.76-4.02,11.94-3.73,16.34,0.68L283.918,54.022z M241.968,86.682c0-4.3-1.64-8.6-4.91-11.87l-7.61-7.62 c-3.18-3.17-7.39-4.92-11.88-4.92s-8.71,1.75-11.88,4.92l-73.19,73.2c-3.17,3.17-4.92,7.39-4.92,11.87 c0,4.49,1.75,8.71,4.92,11.88l7.62,7.62c3.27,3.27,7.57,4.91,11.87,4.91c4.3,0,8.61-1.64,11.88-4.91l73.19-73.2 C240.328,95.282,241.968,90.982,241.968,86.682z'/%3E%3Cpath d='M290.698,47.242c7.91,7.9,8.44,20.78,1.22,29.31c0,0-143.78,169.92-143.83,169.95c-0.66,0.74-1.55,1.28-2.59,1.49 l-68.46,13.69l-26.92,26.93c-0.92,0.91-2.14,1.4-3.4,1.4c-0.5,0-1.01-0.08-1.51-0.24l-41.93-13.98 c-1.58-0.53-2.77-1.83-3.15-3.45c-0.38-1.61,0.1-3.31,1.28-4.49l40.9-40.9l13.69-68.45c0.22-1.09,0.79-1.99,1.57-2.67 c0.01-0.01,169.87-143.76,169.87-143.76c8.53-7.22,21.41-6.69,29.31,1.22L290.698,47.242z M284.598,70.362 c4.03-4.76,3.73-11.93-0.68-16.34l-33.95-33.95c-4.4-4.41-11.58-4.7-16.34-0.68l-165.85,140.34l76.48,76.49L284.598,70.362z M134.828,240.352l-71.18-71.19l-12.22,61.1c-0.19,0.92-0.65,1.78-1.31,2.45l-9.74,9.73l21.17,21.18l9.74-9.74 c0.67-0.67,1.52-1.13,2.45-1.32L134.828,240.352z M45.428,279.732l8.49-8.49l-21.17-21.17l-19.08,19.08L45.428,279.732z'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E%0A");
|
35 |
+
background-repeat: no-repeat;
|
36 |
+
}
|
37 |
+
|
38 |
+
button.highlighter-btn {
|
39 |
+
height: 24px;
|
40 |
+
width: 29px;
|
41 |
+
background-size: 21px;
|
42 |
+
background-position: center;
|
43 |
+
border: none;
|
44 |
+
}
|
45 |
+
|
46 |
+
button.burk {
|
47 |
+
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 297 297' style='enable-background:new 0 0 297 297;' xml:space='preserve'%3E%3Cg%3E%3Cg id='XMLID_48_'%3E%3Cg%3E%3Cpath style='fill:%23fff;' d='M63.648,169.162l71.18,71.19l-61.09,12.21c-0.93,0.19-1.78,0.65-2.45,1.32l-9.74,9.74 l-21.17-21.18l9.74-9.73c0.66-0.67,1.12-1.53,1.31-2.45L63.648,169.162z'/%3E%3Cpath style='fill:%23000;' d='M230.278,81.592c2.81,2.81,2.81,7.38,0,10.19l-73.19,73.2c-2.81,2.81-7.38,2.81-10.19,0 l-7.62-7.62c-2.81-2.81-2.81-7.38,0-10.19l73.19-73.2c1.36-1.36,3.17-2.11,5.1-2.11c1.92,0,3.73,0.75,5.09,2.11L230.278,81.592z' /%3E%3Cpolygon style='fill:%23ff9292;' points='53.918,271.242 45.428,279.732 13.668,269.152 32.748,250.072 '/%3E%3Cpath style='fill:%23ff9292;' d='M283.918,54.022c4.41,4.41,4.71,11.58,0.68,16.34l-140.34,165.86l-76.48-76.49l165.85-140.34 c4.76-4.02,11.94-3.73,16.34,0.68L283.918,54.022z M241.968,86.682c0-4.3-1.64-8.6-4.91-11.87l-7.61-7.62 c-3.18-3.17-7.39-4.92-11.88-4.92s-8.71,1.75-11.88,4.92l-73.19,73.2c-3.17,3.17-4.92,7.39-4.92,11.87 c0,4.49,1.75,8.71,4.92,11.88l7.62,7.62c3.27,3.27,7.57,4.91,11.87,4.91c4.3,0,8.61-1.64,11.88-4.91l73.19-73.2 C240.328,95.282,241.968,90.982,241.968,86.682z'/%3E%3Cpath d='M290.698,47.242c7.91,7.9,8.44,20.78,1.22,29.31c0,0-143.78,169.92-143.83,169.95c-0.66,0.74-1.55,1.28-2.59,1.49 l-68.46,13.69l-26.92,26.93c-0.92,0.91-2.14,1.4-3.4,1.4c-0.5,0-1.01-0.08-1.51-0.24l-41.93-13.98 c-1.58-0.53-2.77-1.83-3.15-3.45c-0.38-1.61,0.1-3.31,1.28-4.49l40.9-40.9l13.69-68.45c0.22-1.09,0.79-1.99,1.57-2.67 c0.01-0.01,169.87-143.76,169.87-143.76c8.53-7.22,21.41-6.69,29.31,1.22L290.698,47.242z M284.598,70.362 c4.03-4.76,3.73-11.93-0.68-16.34l-33.95-33.95c-4.4-4.41-11.58-4.7-16.34-0.68l-165.85,140.34l76.48,76.49L284.598,70.362z M134.828,240.352l-71.18-71.19l-12.22,61.1c-0.19,0.92-0.65,1.78-1.31,2.45l-9.74,9.73l21.17,21.18l9.74-9.74 c0.67-0.67,1.52-1.13,2.45-1.32L134.828,240.352z M45.428,279.732l8.49-8.49l-21.17-21.17l-19.08,19.08L45.428,279.732z'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E%0A");
|
48 |
+
background-repeat: no-repeat;
|
49 |
+
}
|
50 |
+
|
51 |
+
button.girk {
|
52 |
+
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 297 297' style='enable-background:new 0 0 297 297;' xml:space='preserve'%3E%3Cg%3E%3Cg id='XMLID_48_'%3E%3Cg%3E%3Cpath style='fill:%23fff;' d='M63.648,169.162l71.18,71.19l-61.09,12.21c-0.93,0.19-1.78,0.65-2.45,1.32l-9.74,9.74 l-21.17-21.18l9.74-9.73c0.66-0.67,1.12-1.53,1.31-2.45L63.648,169.162z'/%3E%3Cpath style='fill:%23000;' d='M230.278,81.592c2.81,2.81,2.81,7.38,0,10.19l-73.19,73.2c-2.81,2.81-7.38,2.81-10.19,0 l-7.62-7.62c-2.81-2.81-2.81-7.38,0-10.19l73.19-73.2c1.36-1.36,3.17-2.11,5.1-2.11c1.92,0,3.73,0.75,5.09,2.11L230.278,81.592z' /%3E%3Cpolygon style='fill:%23afe5ad;' points='53.918,271.242 45.428,279.732 13.668,269.152 32.748,250.072 '/%3E%3Cpath style='fill:%23afe5ad;' d='M283.918,54.022c4.41,4.41,4.71,11.58,0.68,16.34l-140.34,165.86l-76.48-76.49l165.85-140.34 c4.76-4.02,11.94-3.73,16.34,0.68L283.918,54.022z M241.968,86.682c0-4.3-1.64-8.6-4.91-11.87l-7.61-7.62 c-3.18-3.17-7.39-4.92-11.88-4.92s-8.71,1.75-11.88,4.92l-73.19,73.2c-3.17,3.17-4.92,7.39-4.92,11.87 c0,4.49,1.75,8.71,4.92,11.88l7.62,7.62c3.27,3.27,7.57,4.91,11.87,4.91c4.3,0,8.61-1.64,11.88-4.91l73.19-73.2 C240.328,95.282,241.968,90.982,241.968,86.682z'/%3E%3Cpath d='M290.698,47.242c7.91,7.9,8.44,20.78,1.22,29.31c0,0-143.78,169.92-143.83,169.95c-0.66,0.74-1.55,1.28-2.59,1.49 l-68.46,13.69l-26.92,26.93c-0.92,0.91-2.14,1.4-3.4,1.4c-0.5,0-1.01-0.08-1.51-0.24l-41.93-13.98 c-1.58-0.53-2.77-1.83-3.15-3.45c-0.38-1.61,0.1-3.31,1.28-4.49l40.9-40.9l13.69-68.45c0.22-1.09,0.79-1.99,1.57-2.67 c0.01-0.01,169.87-143.76,169.87-143.76c8.53-7.22,21.41-6.69,29.31,1.22L290.698,47.242z M284.598,70.362 c4.03-4.76,3.73-11.93-0.68-16.34l-33.95-33.95c-4.4-4.41-11.58-4.7-16.34-0.68l-165.85,140.34l76.48,76.49L284.598,70.362z M134.828,240.352l-71.18-71.19l-12.22,61.1c-0.19,0.92-0.65,1.78-1.31,2.45l-9.74,9.73l21.17,21.18l9.74-9.74 c0.67-0.67,1.52-1.13,2.45-1.32L134.828,240.352z M45.428,279.732l8.49-8.49l-21.17-21.17l-19.08,19.08L45.428,279.732z'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E%0A");
|
53 |
+
background-repeat: no-repeat;
|
54 |
+
}
|
55 |
+
|
56 |
+
button.birk {
|
57 |
+
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 297 297' style='enable-background:new 0 0 297 297;' xml:space='preserve'%3E%3Cg%3E%3Cg id='XMLID_48_'%3E%3Cg%3E%3Cpath style='fill:%23fff;' d='M63.648,169.162l71.18,71.19l-61.09,12.21c-0.93,0.19-1.78,0.65-2.45,1.32l-9.74,9.74 l-21.17-21.18l9.74-9.73c0.66-0.67,1.12-1.53,1.31-2.45L63.648,169.162z'/%3E%3Cpath style='fill:%23000;' d='M230.278,81.592c2.81,2.81,2.81,7.38,0,10.19l-73.19,73.2c-2.81,2.81-7.38,2.81-10.19,0 l-7.62-7.62c-2.81-2.81-2.81-7.38,0-10.19l73.19-73.2c1.36-1.36,3.17-2.11,5.1-2.11c1.92,0,3.73,0.75,5.09,2.11L230.278,81.592z' /%3E%3Cpolygon style='fill:%2383b8f4;' points='53.918,271.242 45.428,279.732 13.668,269.152 32.748,250.072 '/%3E%3Cpath style='fill:%2383b8f4;' d='M283.918,54.022c4.41,4.41,4.71,11.58,0.68,16.34l-140.34,165.86l-76.48-76.49l165.85-140.34 c4.76-4.02,11.94-3.73,16.34,0.68L283.918,54.022z M241.968,86.682c0-4.3-1.64-8.6-4.91-11.87l-7.61-7.62 c-3.18-3.17-7.39-4.92-11.88-4.92s-8.71,1.75-11.88,4.92l-73.19,73.2c-3.17,3.17-4.92,7.39-4.92,11.87 c0,4.49,1.75,8.71,4.92,11.88l7.62,7.62c3.27,3.27,7.57,4.91,11.87,4.91c4.3,0,8.61-1.64,11.88-4.91l73.19-73.2 C240.328,95.282,241.968,90.982,241.968,86.682z'/%3E%3Cpath d='M290.698,47.242c7.91,7.9,8.44,20.78,1.22,29.31c0,0-143.78,169.92-143.83,169.95c-0.66,0.74-1.55,1.28-2.59,1.49 l-68.46,13.69l-26.92,26.93c-0.92,0.91-2.14,1.4-3.4,1.4c-0.5,0-1.01-0.08-1.51-0.24l-41.93-13.98 c-1.58-0.53-2.77-1.83-3.15-3.45c-0.38-1.61,0.1-3.31,1.28-4.49l40.9-40.9l13.69-68.45c0.22-1.09,0.79-1.99,1.57-2.67 c0.01-0.01,169.87-143.76,169.87-143.76c8.53-7.22,21.41-6.69,29.31,1.22L290.698,47.242z M284.598,70.362 c4.03-4.76,3.73-11.93-0.68-16.34l-33.95-33.95c-4.4-4.41-11.58-4.7-16.34-0.68l-165.85,140.34l76.48,76.49L284.598,70.362z M134.828,240.352l-71.18-71.19l-12.22,61.1c-0.19,0.92-0.65,1.78-1.31,2.45l-9.74,9.73l21.17,21.18l9.74-9.74 c0.67-0.67,1.52-1.13,2.45-1.32L134.828,240.352z M45.428,279.732l8.49-8.49l-21.17-21.17l-19.08,19.08L45.428,279.732z'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E%0A");
|
58 |
+
background-repeat: no-repeat;
|
59 |
+
}
|
60 |
+
|
61 |
+
button.pirk {
|
62 |
+
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 297 297' style='enable-background:new 0 0 297 297;' xml:space='preserve'%3E%3Cg%3E%3Cg id='XMLID_48_'%3E%3Cg%3E%3Cpath style='fill:%23fff;' d='M63.648,169.162l71.18,71.19l-61.09,12.21c-0.93,0.19-1.78,0.65-2.45,1.32l-9.74,9.74 l-21.17-21.18l9.74-9.73c0.66-0.67,1.12-1.53,1.31-2.45L63.648,169.162z'/%3E%3Cpath style='fill:%23000;' d='M230.278,81.592c2.81,2.81,2.81,7.38,0,10.19l-73.19,73.2c-2.81,2.81-7.38,2.81-10.19,0 l-7.62-7.62c-2.81-2.81-2.81-7.38,0-10.19l73.19-73.2c1.36-1.36,3.17-2.11,5.1-2.11c1.92,0,3.73,0.75,5.09,2.11L230.278,81.592z' /%3E%3Cpolygon style='fill:%23ecb3d2;' points='53.918,271.242 45.428,279.732 13.668,269.152 32.748,250.072 '/%3E%3Cpath style='fill:%23ecb3d2;' d='M283.918,54.022c4.41,4.41,4.71,11.58,0.68,16.34l-140.34,165.86l-76.48-76.49l165.85-140.34 c4.76-4.02,11.94-3.73,16.34,0.68L283.918,54.022z M241.968,86.682c0-4.3-1.64-8.6-4.91-11.87l-7.61-7.62 c-3.18-3.17-7.39-4.92-11.88-4.92s-8.71,1.75-11.88,4.92l-73.19,73.2c-3.17,3.17-4.92,7.39-4.92,11.87 c0,4.49,1.75,8.71,4.92,11.88l7.62,7.62c3.27,3.27,7.57,4.91,11.87,4.91c4.3,0,8.61-1.64,11.88-4.91l73.19-73.2 C240.328,95.282,241.968,90.982,241.968,86.682z'/%3E%3Cpath d='M290.698,47.242c7.91,7.9,8.44,20.78,1.22,29.31c0,0-143.78,169.92-143.83,169.95c-0.66,0.74-1.55,1.28-2.59,1.49 l-68.46,13.69l-26.92,26.93c-0.92,0.91-2.14,1.4-3.4,1.4c-0.5,0-1.01-0.08-1.51-0.24l-41.93-13.98 c-1.58-0.53-2.77-1.83-3.15-3.45c-0.38-1.61,0.1-3.31,1.28-4.49l40.9-40.9l13.69-68.45c0.22-1.09,0.79-1.99,1.57-2.67 c0.01-0.01,169.87-143.76,169.87-143.76c8.53-7.22,21.41-6.69,29.31,1.22L290.698,47.242z M284.598,70.362 c4.03-4.76,3.73-11.93-0.68-16.34l-33.95-33.95c-4.4-4.41-11.58-4.7-16.34-0.68l-165.85,140.34l76.48,76.49L284.598,70.362z M134.828,240.352l-71.18-71.19l-12.22,61.1c-0.19,0.92-0.65,1.78-1.31,2.45l-9.74,9.73l21.17,21.18l9.74-9.74 c0.67-0.67,1.52-1.13,2.45-1.32L134.828,240.352z M45.428,279.732l8.49-8.49l-21.17-21.17l-19.08,19.08L45.428,279.732z'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E%0A");
|
63 |
+
background-repeat: no-repeat;
|
64 |
+
}
|
65 |
+
|
66 |
+
i#menu-hgl, i.highlighter-close {
|
67 |
+
padding-left: 20px;
|
68 |
+
}
|
69 |
+
|
70 |
+
#higlighter_menu.btn:focus, #higlighter_menu.btn:active:focus, #higlighter_menu.btn.active:focus, #higlighter_menu.btn.focus, #higlighter_menu.btn:active.focus, #higlighter_menu.btn.active.focus :focus {
|
71 |
+
outline: 0 !important;
|
72 |
+
}
|
73 |
+
|
74 |
+
#higlighter_menu {
|
75 |
+
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Capa_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 512.001 512.001' style='enable-background:new 0 0 512.001 512.001;' xml:space='preserve'%3E%3Cpolygon style='fill:%23FFABCD;' points='387.375,480.658 383.919,157.034 503.991,157.034 500.535,480.658 '/%3E%3Cpolygon style='fill:%23FF6BA6;' points='382.637,161.05 419.416,90.494 468.484,90.494 505.272,161.05 '/%3E%3Cpolygon style='fill:%23FFABCD;' points='418.626,94.51 418.626,43.148 469.274,30.795 469.274,94.51 '/%3E%3Cg%3E%3Cpolygon style='fill:%23FBDF97;' points='230.672,94.51 230.672,43.148 281.33,30.795 281.33,94.51 '/%3E%3Cpolygon style='fill:%23FBDF97;' points='199.422,480.658 195.965,157.034 316.036,157.034 312.58,480.658 '/%3E%3C/g%3E%3Cpolygon style='fill:%23FBC640;' points='194.683,161.05 231.462,90.494 280.539,90.494 317.318,161.05 '/%3E%3Cg%3E%3Cpolygon style='fill:%2344C973;' points='11.466,480.658 8.011,157.034 128.083,157.034 124.626,480.658 '/%3E%3Cpolygon style='fill:%2344C973;' points='42.728,94.51 42.728,43.148 93.375,30.795 93.375,94.51 '/%3E%3C/g%3E%3Cpolygon style='fill:%23248A48;' points='6.729,161.05 43.518,90.494 92.585,90.494 129.364,161.05 '/%3E%3Cpath d='M443.734,375.969c-12.919,0-12.941,20.078,0,20.078C456.653,396.048,456.675,375.969,443.734,375.969z'/%3E%3Cpath d='M13.453,488.689H122.64c5.502,0,9.98-4.43,10.039-9.932l3.413-319.608c0.004-0.354-0.012-0.705-0.044-1.05 c-0.001-0.014-0.004-0.027-0.006-0.041c-0.037-0.382-0.1-0.758-0.18-1.127c-0.02-0.093-0.045-0.185-0.068-0.277 c-0.074-0.305-0.163-0.604-0.264-0.898c-0.031-0.09-0.061-0.181-0.095-0.27c-0.138-0.361-0.289-0.715-0.466-1.055 c-0.005-0.01-0.008-0.02-0.013-0.029l-0.008-0.015c-0.01-0.02-0.021-0.04-0.031-0.06l-33.51-64.284V33.351 c0-3.081-1.416-5.992-3.838-7.895c-2.423-1.903-5.584-2.588-8.58-1.858L42.357,34.972c-4.497,1.097-7.66,5.125-7.66,9.753v45.316 L1.176,154.325c-0.011,0.02-0.021,0.04-0.031,0.06l-0.008,0.015c-0.005,0.009-0.008,0.019-0.012,0.028 c-0.177,0.34-0.328,0.694-0.466,1.055c-0.034,0.09-0.064,0.181-0.096,0.272c-0.101,0.293-0.19,0.592-0.264,0.898 c-0.023,0.092-0.048,0.184-0.068,0.277c-0.079,0.369-0.143,0.744-0.18,1.126c-0.001,0.014-0.005,0.028-0.006,0.042 c-0.032,0.345-0.048,0.697-0.044,1.051l3.413,319.608C3.473,484.259,7.951,488.689,13.453,488.689z M23.386,468.611l-3.198-299.53 h95.719l-3.198,299.53H23.386z M54.775,52.61l26.554-6.476v36.329H54.775V52.61z M50.823,102.541h34.456l24.22,46.461H26.596 L50.823,102.541z'/%3E%3Cpath d='M68.046,215.121c-5.545,0-10.039,4.495-10.039,10.039v160.366c0,5.545,4.495,10.039,10.039,10.039 s10.039-4.495,10.039-10.039V225.16C78.086,219.615,73.591,215.121,68.046,215.121z'/%3E%3Cpath d='M188.518,155.756c-0.102,0.293-0.19,0.592-0.264,0.898c-0.023,0.092-0.048,0.184-0.068,0.277 c-0.079,0.369-0.143,0.744-0.18,1.127c-0.001,0.014-0.005,0.027-0.006,0.041c-0.032,0.345-0.048,0.696-0.044,1.05l3.413,319.608 c0.059,5.501,4.537,9.932,10.039,9.932h109.187c5.502,0,9.98-4.43,10.039-9.932l3.413-319.608c0.004-0.354-0.012-0.705-0.044-1.05 c-0.001-0.014-0.004-0.027-0.006-0.041c-0.037-0.382-0.1-0.758-0.18-1.127c-0.02-0.093-0.045-0.185-0.068-0.277 c-0.074-0.305-0.163-0.604-0.264-0.898c-0.031-0.09-0.061-0.181-0.095-0.27c-0.138-0.361-0.289-0.715-0.466-1.055 c-0.005-0.01-0.008-0.02-0.013-0.029l-0.008-0.015c-0.01-0.02-0.021-0.04-0.031-0.06l-33.511-64.284V33.351 c0-3.081-1.415-5.991-3.838-7.895c-2.422-1.903-5.585-2.588-8.579-1.858l-46.642,11.374c-4.497,1.096-7.661,5.125-7.661,9.753 v45.317l-33.509,64.283c-0.011,0.02-0.021,0.04-0.031,0.06l-0.008,0.015c-0.005,0.009-0.008,0.02-0.013,0.029 c-0.177,0.34-0.328,0.694-0.466,1.055C188.579,155.575,188.549,155.665,188.518,155.756z M211.34,468.611l-3.198-299.53h95.719 l-3.199,299.53H211.34z M242.719,52.61l26.564-6.478v36.331h-26.564L242.719,52.61L242.719,52.61z M238.768,102.541h34.466 l24.22,46.461H214.55L238.768,102.541z'/%3E%3Cpath d='M256.001,215.121c-5.545,0-10.039,4.495-10.039,10.039v160.366c0,5.545,4.495,10.039,10.039,10.039 c5.545,0,10.039-4.495,10.039-10.039V225.16C266.04,219.615,261.545,215.121,256.001,215.121z'/%3E%3Cpath d='M508.587,478.758l3.413-319.608c0.004-0.355-0.012-0.706-0.044-1.051c-0.001-0.014-0.005-0.028-0.006-0.042 c-0.037-0.382-0.1-0.758-0.18-1.126c-0.02-0.092-0.045-0.185-0.068-0.277c-0.074-0.305-0.163-0.604-0.264-0.898 c-0.031-0.091-0.062-0.182-0.096-0.272c-0.138-0.361-0.289-0.715-0.466-1.055c-0.005-0.009-0.008-0.019-0.012-0.028l-0.008-0.015 c-0.01-0.02-0.02-0.04-0.031-0.06l-33.52-64.283v-56.69c0-3.081-1.416-5.992-3.838-7.895c-2.423-1.903-5.585-2.588-8.579-1.858 l-46.632,11.374c-4.497,1.097-7.66,5.125-7.66,9.753v45.317l-33.51,64.283c-0.011,0.02-0.021,0.04-0.031,0.06l-0.008,0.015 c-0.005,0.009-0.008,0.02-0.013,0.029c-0.177,0.34-0.328,0.694-0.466,1.055c-0.034,0.089-0.064,0.18-0.095,0.27 c-0.102,0.293-0.19,0.592-0.264,0.898c-0.023,0.092-0.048,0.184-0.068,0.277c-0.079,0.369-0.143,0.744-0.18,1.127 c-0.001,0.014-0.005,0.027-0.006,0.041c-0.032,0.345-0.048,0.696-0.044,1.05l3.413,319.608c0.059,5.501,4.537,9.932,10.039,9.932 h109.186C504.051,488.689,508.528,484.259,508.587,478.758z M430.673,52.61l26.554-6.476v36.329h-26.554V52.61z M426.723,102.541 h34.456l24.227,46.461h-82.902L426.723,102.541z M399.293,468.611l-3.198-299.53h95.719l-3.199,299.53H399.293z'/%3E%3Cpath d='M443.955,215.121c-5.545,0-10.039,4.495-10.039,10.039v128.221c0,5.545,4.495,10.039,10.039,10.039 s10.039-4.495,10.039-10.039V225.16C453.994,219.615,449.5,215.121,443.955,215.121z'/%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E%0A");
|
76 |
+
background-repeat: no-repeat;
|
77 |
+
background-position-x: 6px;
|
78 |
+
padding-right: 2px !important;
|
79 |
+
background-size: 18px;
|
80 |
+
background-position-y: center;
|
81 |
+
}
|
82 |
+
|
83 |
+
.toolbar .btn-group {
|
84 |
+
margin-top: 3px !important;
|
85 |
+
}
|
86 |
+
|
87 |
+
div#hgl {
|
88 |
+
padding-top: 2px;
|
89 |
+
}
|
90 |
+
|
91 |
+
#remove_highlights {
|
92 |
+
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 297 297' style='enable-background:new 0 0 297 297;' xml:space='preserve'%3E%3Cg%3E%3Cg id='XMLID_48_'%3E%3Cg%3E%3Cpath style='fill:%23fff;' d='M63.648,169.162l71.18,71.19l-61.09,12.21c-0.93,0.19-1.78,0.65-2.45,1.32l-9.74,9.74 l-21.17-21.18l9.74-9.73c0.66-0.67,1.12-1.53,1.31-2.45L63.648,169.162z'/%3E%3Cpath style='fill:%23000;' d='M230.278,81.592c2.81,2.81,2.81,7.38,0,10.19l-73.19,73.2c-2.81,2.81-7.38,2.81-10.19,0 l-7.62-7.62c-2.81-2.81-2.81-7.38,0-10.19l73.19-73.2c1.36-1.36,3.17-2.11,5.1-2.11c1.92,0,3.73,0.75,5.09,2.11L230.278,81.592z' /%3E%3Cpolygon style='fill:%23fff;' points='53.918,271.242 45.428,279.732 13.668,269.152 32.748,250.072 '/%3E%3Cpath style='fill:%23fff;' d='M283.918,54.022c4.41,4.41,4.71,11.58,0.68,16.34l-140.34,165.86l-76.48-76.49l165.85-140.34 c4.76-4.02,11.94-3.73,16.34,0.68L283.918,54.022z M241.968,86.682c0-4.3-1.64-8.6-4.91-11.87l-7.61-7.62 c-3.18-3.17-7.39-4.92-11.88-4.92s-8.71,1.75-11.88,4.92l-73.19,73.2c-3.17,3.17-4.92,7.39-4.92,11.87 c0,4.49,1.75,8.71,4.92,11.88l7.62,7.62c3.27,3.27,7.57,4.91,11.87,4.91c4.3,0,8.61-1.64,11.88-4.91l73.19-73.2 C240.328,95.282,241.968,90.982,241.968,86.682z'/%3E%3Cpath d='M290.698,47.242c7.91,7.9,8.44,20.78,1.22,29.31c0,0-143.78,169.92-143.83,169.95c-0.66,0.74-1.55,1.28-2.59,1.49 l-68.46,13.69l-26.92,26.93c-0.92,0.91-2.14,1.4-3.4,1.4c-0.5,0-1.01-0.08-1.51-0.24l-41.93-13.98 c-1.58-0.53-2.77-1.83-3.15-3.45c-0.38-1.61,0.1-3.31,1.28-4.49l40.9-40.9l13.69-68.45c0.22-1.09,0.79-1.99,1.57-2.67 c0.01-0.01,169.87-143.76,169.87-143.76c8.53-7.22,21.41-6.69,29.31,1.22L290.698,47.242z M284.598,70.362 c4.03-4.76,3.73-11.93-0.68-16.34l-33.95-33.95c-4.4-4.41-11.58-4.7-16.34-0.68l-165.85,140.34l76.48,76.49L284.598,70.362z M134.828,240.352l-71.18-71.19l-12.22,61.1c-0.19,0.92-0.65,1.78-1.31,2.45l-9.74,9.73l21.17,21.18l9.74-9.74 c0.67-0.67,1.52-1.13,2.45-1.32L134.828,240.352z M45.428,279.732l8.49-8.49l-21.17-21.17l-19.08,19.08L45.428,279.732z'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E%0A");
|
93 |
+
background-repeat: no-repeat;
|
94 |
+
background-position-x: 6px;
|
95 |
+
padding-right: 2px !important;
|
96 |
+
background-size: 18px;
|
97 |
+
background-position-y: center;
|
98 |
+
}
|
.local/share/jupyter/nbextensions/highlighter/highlighter.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Type: IPython Notebook Extension
|
2 |
+
Name: highlighter
|
3 |
+
Description: Enable to highlight select text in a markdown cell
|
4 |
+
Link: readme.md
|
5 |
+
Icon: icon.png
|
6 |
+
Main: highlighter.js
|
7 |
+
Compatibility: 3.x, 4.x, 5.x
|
.local/share/jupyter/nbextensions/highlighter/tst_highlights.html
ADDED
The diff for this file is too large to render.
See raw diff
|
|
.local/share/jupyter/nbextensions/highlighter/tst_highlights.ipynb
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "markdown",
|
5 |
+
"metadata": {},
|
6 |
+
"source": [
|
7 |
+
"# First cell\n",
|
8 |
+
"\n",
|
9 |
+
"<span class=\"mark\">In the first cell, we highlight *some words* using the different schemes provided.</span> \n",
|
10 |
+
"\n",
|
11 |
+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus id lacus mauris. Etiam in dictum mauris. <span class=\"burk\">Morbi pharetra, **mauris a feugiat consequat**, est purus vulputate mauris, quis feugiat leo metus eu risus. Sed non luctus arcu.</span> Donec eu ipsum justo. Praesent sit amet euismod orci. Nam eu turpis quis enim pulvinar blandit in eu justo. Vivamus nec libero ipsum. Nunc tempus, mi at vestibulum congue, lacus ante faucibus dolor, quis varius elit felis id ipsum. <span class=\"girk\">Vivamus at mi lorem.</span> Integer quam massa, viverra et fermentum et, cursus faucibus nisl. Vestibulum sed est lacus. Morbi sit amet laoreet odio.\n",
|
12 |
+
"\n"
|
13 |
+
]
|
14 |
+
},
|
15 |
+
{
|
16 |
+
"cell_type": "markdown",
|
17 |
+
"metadata": {},
|
18 |
+
"source": [
|
19 |
+
"<div class=\"mark\">\n",
|
20 |
+
"# Second cell\n",
|
21 |
+
"\n",
|
22 |
+
"The second cell is completely highlighted. \n",
|
23 |
+
"\n",
|
24 |
+
"\n",
|
25 |
+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus id lacus mauris. Etiam in dictum mauris. Morbi pharetra, mauris a feugiat consequat, <span class=\"burk\">est purus vulputate mauris,</span> quis feugiat leo metus eu risus. Sed non luctus arcu. Donec eu ipsum justo. Praesent sit amet euismod orci. Nam eu turpis quis enim pulvinar blandit in eu justo. Vivamus nec libero ipsum. Nunc tempus, mi at vestibulum congue, <span class=\"girk\">lacus ante faucibus dolor</span>, quis varius elit felis id ipsum. Vivamus at mi lorem. Integer quam massa, viverra et fermentum et, cursus faucibus nisl. Vestibulum sed est lacus. Morbi sit amet laoreet odio.</div><i class=\"fa fa-lightbulb-o \"></i>"
|
26 |
+
]
|
27 |
+
}
|
28 |
+
],
|
29 |
+
"metadata": {
|
30 |
+
"interactive_sols": {
|
31 |
+
"cbx_id": 1
|
32 |
+
},
|
33 |
+
"kernelspec": {
|
34 |
+
"display_name": "Python 3",
|
35 |
+
"language": "python",
|
36 |
+
"name": "python3"
|
37 |
+
},
|
38 |
+
"language_info": {
|
39 |
+
"codemirror_mode": {
|
40 |
+
"name": "ipython",
|
41 |
+
"version": 3
|
42 |
+
},
|
43 |
+
"file_extension": ".py",
|
44 |
+
"mimetype": "text/x-python",
|
45 |
+
"name": "python",
|
46 |
+
"nbconvert_exporter": "python",
|
47 |
+
"pygments_lexer": "ipython3",
|
48 |
+
"version": "3.4.3+"
|
49 |
+
},
|
50 |
+
},
|
51 |
+
"nbformat": 4,
|
52 |
+
"nbformat_minor": 0
|
53 |
+
}
|
.local/share/jupyter/nbextensions/highlighter/tst_highlights.tex
ADDED
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
% Default to the notebook output style
|
3 |
+
|
4 |
+
|
5 |
+
% Inherit from the specified cell style.
|
6 |
+
|
7 |
+
|
8 |
+
|
9 |
+
|
10 |
+
|
11 |
+
|
12 |
+
\documentclass{article}
|
13 |
+
|
14 |
+
|
15 |
+
|
16 |
+
|
17 |
+
\usepackage{graphicx} % Used to insert images
|
18 |
+
\usepackage{adjustbox} % Used to constrain images to a maximum size
|
19 |
+
\usepackage{color} % Allow colors to be defined
|
20 |
+
\usepackage{enumerate} % Needed for markdown enumerations to work
|
21 |
+
\usepackage{geometry} % Used to adjust the document margins
|
22 |
+
\usepackage{amsmath} % Equations
|
23 |
+
\usepackage{amssymb} % Equations
|
24 |
+
\usepackage{eurosym} % defines \euro
|
25 |
+
\usepackage[mathletters]{ucs} % Extended unicode (utf-8) support
|
26 |
+
\usepackage[utf8x]{inputenc} % Allow utf-8 characters in the tex document
|
27 |
+
\usepackage{fancyvrb} % verbatim replacement that allows latex
|
28 |
+
\usepackage{grffile} % extends the file name processing of package graphics
|
29 |
+
% to support a larger range
|
30 |
+
% The hyperref package gives us a pdf with properly built
|
31 |
+
% internal navigation ('pdf bookmarks' for the table of contents,
|
32 |
+
% internal cross-reference links, web links for URLs, etc.)
|
33 |
+
\usepackage{hyperref}
|
34 |
+
\usepackage{longtable} % longtable support required by pandoc >1.10
|
35 |
+
\usepackage{booktabs} % table support for pandoc > 1.12.2
|
36 |
+
|
37 |
+
\usepackage{color}
|
38 |
+
\usepackage{soul}
|
39 |
+
\usepackage[framemethod=tikz]{mdframed}
|
40 |
+
|
41 |
+
|
42 |
+
|
43 |
+
|
44 |
+
\definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
|
45 |
+
\definecolor{darkorange}{rgb}{.71,0.21,0.01}
|
46 |
+
\definecolor{darkgreen}{rgb}{.12,.54,.11}
|
47 |
+
\definecolor{myteal}{rgb}{.26, .44, .56}
|
48 |
+
\definecolor{gray}{gray}{0.45}
|
49 |
+
\definecolor{lightgray}{gray}{.95}
|
50 |
+
\definecolor{mediumgray}{gray}{.8}
|
51 |
+
\definecolor{inputbackground}{rgb}{.95, .95, .85}
|
52 |
+
\definecolor{outputbackground}{rgb}{.95, .95, .95}
|
53 |
+
\definecolor{traceback}{rgb}{1, .95, .95}
|
54 |
+
% ansi colors
|
55 |
+
\definecolor{red}{rgb}{.6,0,0}
|
56 |
+
\definecolor{green}{rgb}{0,.65,0}
|
57 |
+
\definecolor{brown}{rgb}{0.6,0.6,0}
|
58 |
+
\definecolor{blue}{rgb}{0,.145,.698}
|
59 |
+
\definecolor{purple}{rgb}{.698,.145,.698}
|
60 |
+
\definecolor{cyan}{rgb}{0,.698,.698}
|
61 |
+
\definecolor{lightgray}{gray}{0.5}
|
62 |
+
|
63 |
+
% bright ansi colors
|
64 |
+
\definecolor{darkgray}{gray}{0.25}
|
65 |
+
\definecolor{lightred}{rgb}{1.0,0.39,0.28}
|
66 |
+
\definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
|
67 |
+
\definecolor{lightblue}{rgb}{0.53,0.81,0.92}
|
68 |
+
\definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
|
69 |
+
\definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
|
70 |
+
|
71 |
+
% commands and environments needed by pandoc snippets
|
72 |
+
% extracted from the output of `pandoc -s`
|
73 |
+
\providecommand{\tightlist}{%
|
74 |
+
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
75 |
+
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
|
76 |
+
% Add ',fontsize=\small' for more characters per line
|
77 |
+
\newenvironment{Shaded}{}{}
|
78 |
+
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}}
|
79 |
+
\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}}
|
80 |
+
\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
|
81 |
+
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
|
82 |
+
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
|
83 |
+
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}}
|
84 |
+
\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}}
|
85 |
+
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}}
|
86 |
+
\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}}
|
87 |
+
\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}}
|
88 |
+
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}}
|
89 |
+
\newcommand{\RegionMarkerTok}[1]{{#1}}
|
90 |
+
\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}}
|
91 |
+
\newcommand{\NormalTok}[1]{{#1}}
|
92 |
+
|
93 |
+
% Define a nice break command that doesn't care if a line doesn't already
|
94 |
+
% exist.
|
95 |
+
\def\br{\hspace*{\fill} \\* }
|
96 |
+
% Math Jax compatability definitions
|
97 |
+
\def\gt{>}
|
98 |
+
\def\lt{<}
|
99 |
+
% Document parameters
|
100 |
+
\title{tst\_highlights}
|
101 |
+
|
102 |
+
|
103 |
+
\author{}
|
104 |
+
|
105 |
+
|
106 |
+
|
107 |
+
% Pygments definitions
|
108 |
+
|
109 |
+
\makeatletter
|
110 |
+
\def\PY@reset{\let\PY@it=\relax \let\PY@bf=\relax%
|
111 |
+
\let\PY@ul=\relax \let\PY@tc=\relax%
|
112 |
+
\let\PY@bc=\relax \let\PY@ff=\relax}
|
113 |
+
\def\PY@tok#1{\csname PY@tok@#1\endcsname}
|
114 |
+
\def\PY@toks#1+{\ifx\relax#1\empty\else%
|
115 |
+
\PY@tok{#1}\expandafter\PY@toks\fi}
|
116 |
+
\def\PY@do#1{\PY@bc{\PY@tc{\PY@ul{%
|
117 |
+
\PY@it{\PY@bf{\PY@ff{#1}}}}}}}
|
118 |
+
\def\PY#1#2{\PY@reset\PY@toks#1+\relax+\PY@do{#2}}
|
119 |
+
|
120 |
+
\expandafter\def\csname PY@tok@mo\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
121 |
+
\expandafter\def\csname PY@tok@sc\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
|
122 |
+
\expandafter\def\csname PY@tok@nl\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.63,0.63,0.00}{##1}}}
|
123 |
+
\expandafter\def\csname PY@tok@nn\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
|
124 |
+
\expandafter\def\csname PY@tok@nv\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
|
125 |
+
\expandafter\def\csname PY@tok@vc\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
|
126 |
+
\expandafter\def\csname PY@tok@se\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.73,0.40,0.13}{##1}}}
|
127 |
+
\expandafter\def\csname PY@tok@gh\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
|
128 |
+
\expandafter\def\csname PY@tok@k\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
129 |
+
\expandafter\def\csname PY@tok@kn\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
130 |
+
\expandafter\def\csname PY@tok@sb\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
|
131 |
+
\expandafter\def\csname PY@tok@no\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.53,0.00,0.00}{##1}}}
|
132 |
+
\expandafter\def\csname PY@tok@gu\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}}
|
133 |
+
\expandafter\def\csname PY@tok@o\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
134 |
+
\expandafter\def\csname PY@tok@gd\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}}
|
135 |
+
\expandafter\def\csname PY@tok@vi\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
|
136 |
+
\expandafter\def\csname PY@tok@s2\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
|
137 |
+
\expandafter\def\csname PY@tok@il\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
138 |
+
\expandafter\def\csname PY@tok@nd\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
|
139 |
+
\expandafter\def\csname PY@tok@cs\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
|
140 |
+
\expandafter\def\csname PY@tok@ge\endcsname{\let\PY@it=\textit}
|
141 |
+
\expandafter\def\csname PY@tok@go\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
|
142 |
+
\expandafter\def\csname PY@tok@mb\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
143 |
+
\expandafter\def\csname PY@tok@sh\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
|
144 |
+
\expandafter\def\csname PY@tok@w\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}}
|
145 |
+
\expandafter\def\csname PY@tok@gr\endcsname{\def\PY@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}}
|
146 |
+
\expandafter\def\csname PY@tok@ss\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
|
147 |
+
\expandafter\def\csname PY@tok@cm\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
|
148 |
+
\expandafter\def\csname PY@tok@gs\endcsname{\let\PY@bf=\textbf}
|
149 |
+
\expandafter\def\csname PY@tok@kd\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
150 |
+
\expandafter\def\csname PY@tok@bp\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
151 |
+
\expandafter\def\csname PY@tok@si\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.73,0.40,0.53}{##1}}}
|
152 |
+
\expandafter\def\csname PY@tok@ni\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.60,0.60,0.60}{##1}}}
|
153 |
+
\expandafter\def\csname PY@tok@c\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
|
154 |
+
\expandafter\def\csname PY@tok@kr\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
155 |
+
\expandafter\def\csname PY@tok@nb\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
156 |
+
\expandafter\def\csname PY@tok@ow\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
|
157 |
+
\expandafter\def\csname PY@tok@s\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
|
158 |
+
\expandafter\def\csname PY@tok@nf\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
|
159 |
+
\expandafter\def\csname PY@tok@mh\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
160 |
+
\expandafter\def\csname PY@tok@na\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.49,0.56,0.16}{##1}}}
|
161 |
+
\expandafter\def\csname PY@tok@gp\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
|
162 |
+
\expandafter\def\csname PY@tok@gi\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.63,0.00}{##1}}}
|
163 |
+
\expandafter\def\csname PY@tok@err\endcsname{\def\PY@bc##1{\setlength{\fboxsep}{0pt}\fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}
|
164 |
+
\expandafter\def\csname PY@tok@gt\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
|
165 |
+
\expandafter\def\csname PY@tok@cp\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.74,0.48,0.00}{##1}}}
|
166 |
+
\expandafter\def\csname PY@tok@kc\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
167 |
+
\expandafter\def\csname PY@tok@sr\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.40,0.53}{##1}}}
|
168 |
+
\expandafter\def\csname PY@tok@vg\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
|
169 |
+
\expandafter\def\csname PY@tok@kt\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.69,0.00,0.25}{##1}}}
|
170 |
+
\expandafter\def\csname PY@tok@nt\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
171 |
+
\expandafter\def\csname PY@tok@ne\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.82,0.25,0.23}{##1}}}
|
172 |
+
\expandafter\def\csname PY@tok@sd\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
|
173 |
+
\expandafter\def\csname PY@tok@c1\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
|
174 |
+
\expandafter\def\csname PY@tok@s1\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
|
175 |
+
\expandafter\def\csname PY@tok@sx\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
176 |
+
\expandafter\def\csname PY@tok@mf\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
177 |
+
\expandafter\def\csname PY@tok@mi\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
178 |
+
\expandafter\def\csname PY@tok@m\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
179 |
+
\expandafter\def\csname PY@tok@nc\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
|
180 |
+
\expandafter\def\csname PY@tok@kp\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
|
181 |
+
|
182 |
+
\def\PYZbs{\char`\\}
|
183 |
+
\def\PYZus{\char`\_}
|
184 |
+
\def\PYZob{\char`\{}
|
185 |
+
\def\PYZcb{\char`\}}
|
186 |
+
\def\PYZca{\char`\^}
|
187 |
+
\def\PYZam{\char`\&}
|
188 |
+
\def\PYZlt{\char`\<}
|
189 |
+
\def\PYZgt{\char`\>}
|
190 |
+
\def\PYZsh{\char`\#}
|
191 |
+
\def\PYZpc{\char`\%}
|
192 |
+
\def\PYZdl{\char`\$}
|
193 |
+
\def\PYZhy{\char`\-}
|
194 |
+
\def\PYZsq{\char`\'}
|
195 |
+
\def\PYZdq{\char`\"}
|
196 |
+
\def\PYZti{\char`\~}
|
197 |
+
% for compatibility with earlier versions
|
198 |
+
\def\PYZat{@}
|
199 |
+
\def\PYZlb{[}
|
200 |
+
\def\PYZrb{]}
|
201 |
+
\makeatother
|
202 |
+
|
203 |
+
|
204 |
+
|
205 |
+
|
206 |
+
|
207 |
+
|
208 |
+
% Prevent overflowing lines due to hard-to-break entities
|
209 |
+
\sloppy
|
210 |
+
% Setup hyperref package
|
211 |
+
\hypersetup{
|
212 |
+
breaklinks=true, % so long urls are correctly broken across lines
|
213 |
+
colorlinks=true,
|
214 |
+
urlcolor=blue,
|
215 |
+
linkcolor=darkorange,
|
216 |
+
citecolor=darkgreen,
|
217 |
+
}
|
218 |
+
% Slightly bigger margins than the latex defaults
|
219 |
+
|
220 |
+
\geometry{verbose,tmargin=1in,bmargin=1in,lmargin=1in,rmargin=1in}
|
221 |
+
|
222 |
+
|
223 |
+
\newcommand{\highlighta}[1]{{\sethlcolor{yellow} \textcolor{red}{\hl{#1}}}}
|
224 |
+
\newcommand{\highlightb}[1]{{\sethlcolor{red} \textcolor{yellow}{\hl{#1}}}}
|
225 |
+
\newcommand{\highlightc}[1]{{\sethlcolor{green} \textcolor{yellow}{\hl{#1}}}}
|
226 |
+
\newenvironment{highlightA}{\begin{mdframed}[hidealllines=true,backgroundcolor=yellow!20]}{\end{mdframed}}
|
227 |
+
\newenvironment{highlightB}{\begin{mdframed}[hidealllines=true,backgroundcolor=red!20]}{\end{mdframed}}
|
228 |
+
\newenvironment{highlightC}{\begin{mdframed}[hidealllines=true,backgroundcolor=green!20]}{\end{mdframed}}
|
229 |
+
|
230 |
+
|
231 |
+
%\usepackage{foo}
|
232 |
+
|
233 |
+
\begin{document}
|
234 |
+
|
235 |
+
|
236 |
+
\maketitle
|
237 |
+
|
238 |
+
|
239 |
+
|
240 |
+
|
241 |
+
\section{First cell}\label{first-cell}
|
242 |
+
|
243 |
+
\highlighta{In the first cell, we highlight \emph{some words}
|
244 |
+
using the different schemes provided.}
|
245 |
+
|
246 |
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus id
|
247 |
+
lacus mauris. Etiam in dictum mauris. \highlightb{Morbi pharetra,
|
248 |
+
\textbf{mauris a feugiat consequat}, est purus vulputate mauris, quis
|
249 |
+
feugiat leo metus eu risus. Sed non luctus arcu.} Donec eu ipsum
|
250 |
+
justo. Praesent sit amet euismod orci. Nam eu turpis quis enim pulvinar
|
251 |
+
blandit in eu justo. Vivamus nec libero ipsum. Nunc tempus, mi at
|
252 |
+
vestibulum congue, lacus ante faucibus dolor, quis varius elit felis id
|
253 |
+
ipsum. \highlightc{Vivamus at mi lorem.} Integer quam massa,
|
254 |
+
viverra et fermentum et, cursus faucibus nisl. Vestibulum sed est lacus.
|
255 |
+
Morbi sit amet laoreet odio.
|
256 |
+
|
257 |
+
\begin{highlightA}
|
258 |
+
|
259 |
+
\section{Second cell}\label{second-cell}
|
260 |
+
|
261 |
+
The second cell is completely highlighted.
|
262 |
+
|
263 |
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus id
|
264 |
+
lacus mauris. Etiam in dictum mauris. Morbi pharetra, mauris a feugiat
|
265 |
+
consequat, \highlightb{est purus vulputate mauris,} quis
|
266 |
+
feugiat leo metus eu risus. Sed non luctus arcu. Donec eu ipsum justo.
|
267 |
+
Praesent sit amet euismod orci. Nam eu turpis quis enim pulvinar blandit
|
268 |
+
in eu justo. Vivamus nec libero ipsum. Nunc tempus, mi at vestibulum
|
269 |
+
congue, \highlightc{lacus ante faucibus dolor}, quis varius
|
270 |
+
elit felis id ipsum. Vivamus at mi lorem. Integer quam massa, viverra et
|
271 |
+
fermentum et, cursus faucibus nisl. Vestibulum sed est lacus. Morbi sit
|
272 |
+
amet laoreet odio. \end{highlightA}
|
273 |
+
|
274 |
+
|
275 |
+
% Add a bibliography block to the postdoc
|
276 |
+
|
277 |
+
|
278 |
+
|
279 |
+
\end{document}
|
.local/share/jupyter/nbextensions/hinterland/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Hinterland
|
2 |
+
==========
|
3 |
+
|
4 |
+
Enable code autocompletion menu for every keypress in a code cell, instead of
|
5 |
+
only calling it with tab.
|
6 |
+
|
7 |
+
The nbextension adds an item to the help menu to turn auto-hinting on and off,
|
8 |
+
and offers some options for configuration:
|
9 |
+
|
10 |
+
|
11 |
+
Options
|
12 |
+
-------
|
13 |
+
|
14 |
+
* `hinterland.hint_delay`:
|
15 |
+
delay in milliseconds between keypress & hint request. This is used to help
|
16 |
+
ensure that the character from the keypress is added to the CodeMirror editor
|
17 |
+
*before* the hint request checks the character preceding the cursor against
|
18 |
+
the regexes below.
|
19 |
+
|
20 |
+
* `hinterland.enable_at_start`:
|
21 |
+
Whether to enable hinterland's continuous hinting when notebook is first
|
22 |
+
opened, or if false, only when selected from the help-menu item.
|
23 |
+
|
24 |
+
* `hinterland.hint_inside_comments`:
|
25 |
+
Whether to request hints while typing code comments. Defaults to false.
|
26 |
+
|
27 |
+
* `hinterland.exclude_regexp`:
|
28 |
+
A regular expression tested against the character before the cursor, which,
|
29 |
+
if a match occurs, prevents autocompletion from being triggered. This is
|
30 |
+
useful, for example, to prevent triggering autocomplete on a colon, which is
|
31 |
+
included by the default Completer.reinvoke pattern. If blank, no test is
|
32 |
+
performed. Note that the regex will be created without any flags, making it
|
33 |
+
case sensitive.
|
34 |
+
|
35 |
+
* `hinterland.include_regexp`:
|
36 |
+
A regular expression tested against the character before the cursor, which
|
37 |
+
must match in order for autocompletion to be triggered. If left blank, the
|
38 |
+
value of the notebook's `Completer.reinvoke_re` parameter is used, which can
|
39 |
+
be modified by kernels, but defaults to `/[%0-9a-z._/\\:~-]/i`. Note that
|
40 |
+
although the `Completer.reinvoke_re` default is case insensitive by virtue of
|
41 |
+
its `/i` flag, any regex specified by the user will be created without any
|
42 |
+
flags, making it case sensitive.
|
43 |
+
|
44 |
+
* `hinterland.tooltip_regexp`:
|
45 |
+
A regular expression tested against the character before the cursor, which if
|
46 |
+
it matches, causes a tooltip to be triggered, instead of regular
|
47 |
+
autocompletion. For python, this is useful for example for function calls, so
|
48 |
+
the default regex matches opening parentheses. Note that the regex will be
|
49 |
+
created without any flags, making it case sensitive.
|
.local/share/jupyter/nbextensions/hinterland/hinterland.yaml
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Type: Jupyter Notebook Extension
|
2 |
+
Main: hinterland.js
|
3 |
+
Name: Hinterland
|
4 |
+
Link: README.md
|
5 |
+
Description: |
|
6 |
+
Enable code autocompletion menu for every keypress in a code cell, instead of
|
7 |
+
only enabling it with tab
|
8 |
+
Compatibility: 4.x, 5.x
|
9 |
+
Parameters:
|
10 |
+
- name: hinterland.hint_delay
|
11 |
+
description: |
|
12 |
+
delay in milliseconds between keypress & hint request. This is used to help
|
13 |
+
ensure that the character from the keypress is added to the CodeMirror
|
14 |
+
editor *before* the hint request checks the character preceding the cursor
|
15 |
+
against the regexes below.
|
16 |
+
input_type: number
|
17 |
+
min: 1
|
18 |
+
step: 1
|
19 |
+
default: 20
|
20 |
+
- name: hinterland.enable_at_start
|
21 |
+
description: |
|
22 |
+
Enable hinterland's continuous hinting when notebook is first opened, or
|
23 |
+
if false, only when selected from the help-menu item.
|
24 |
+
input_type: checkbox
|
25 |
+
default: true
|
26 |
+
- name: hinterland.hint_inside_comments
|
27 |
+
description: |
|
28 |
+
Whether to request hints while typing code comments.
|
29 |
+
input_type: checkbox
|
30 |
+
default: false
|
31 |
+
- name: hinterland.exclude_regexp
|
32 |
+
description: |
|
33 |
+
exclude_regexp:
|
34 |
+
A regular expression tested against the character before the cursor, which,
|
35 |
+
if a match occurs, prevents autocompletion from being triggered.
|
36 |
+
This is useful, for example, to prevent triggering autocomplete on a colon,
|
37 |
+
which is included by the default Completer.reinvoke pattern.
|
38 |
+
If blank, no test is performed.
|
39 |
+
Note that the regex will be created without any flags, making it case
|
40 |
+
sensitive.
|
41 |
+
input_type: text
|
42 |
+
# note that the YAML single-quoted string allows us to use the \ character
|
43 |
+
# without escaping it, similar to python's raw string syntax
|
44 |
+
default: ':'
|
45 |
+
- name: hinterland.include_regexp
|
46 |
+
description: |
|
47 |
+
include_regexp:
|
48 |
+
A regular expression tested against the character before the cursor, which
|
49 |
+
must match in order for autocompletion to be triggered.
|
50 |
+
If left blank, the value of the notebook's Completer.reinvoke_re parameter
|
51 |
+
is used, which can be modified by kernels, but defaults to
|
52 |
+
/[%0-9a-z._/\\:~-]/i.
|
53 |
+
Note that although the Completer.reinvoke_re default is case insensitive by
|
54 |
+
virtue of its /i flag, any regex specified by the user will be created
|
55 |
+
without any flags, making it case sensitive.
|
56 |
+
input_type: text
|
57 |
+
# note that the YAML single-quoted string allows us to use the \ character
|
58 |
+
# without escaping it, similar to python's raw string syntax
|
59 |
+
default: ''
|
60 |
+
- name: hinterland.tooltip_regexp
|
61 |
+
description: |
|
62 |
+
tooltip_regexp:
|
63 |
+
A regular expression tested against the character before the cursor, which
|
64 |
+
if it matches, causes a tooltip to be triggered, instead of regular
|
65 |
+
autocompletion.
|
66 |
+
For python, this is useful for example for function calls, so the default
|
67 |
+
regex matches opening parentheses.
|
68 |
+
Note that the regex will be created without any flags, making it case
|
69 |
+
sensitive.
|
70 |
+
input_type: text
|
71 |
+
# note that the YAML single-quoted string allows us to use the \ character
|
72 |
+
# without escaping it, similar to python's raw string syntax
|
73 |
+
default: '\('
|
.local/share/jupyter/nbextensions/init_cell/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
init_cell
|
2 |
+
=========
|
3 |
+
|
4 |
+
Add a cell toolbar selector to mark cells as 'initialization' cells .
|
5 |
+
Such initialization cells are run:
|
6 |
+
|
7 |
+
* on clicking the provided button in the main toolbar
|
8 |
+
![main toolabr button](icon.png)
|
9 |
+
* by default, on kernel ready notification for trusted notebooks.
|
10 |
+
This is configurable (see options section).
|
11 |
+
In untrusted notebooks, a warning is displayed if the cells would otherwise
|
12 |
+
have been run.
|
13 |
+
|
14 |
+
|
15 |
+
Options
|
16 |
+
-------
|
17 |
+
|
18 |
+
This nbextension provides option configurable using the
|
19 |
+
[jupyter_nbextensions_configurator](https://github.com/Jupyter-contrib/jupyter_nbextensions_configurator).
|
20 |
+
|
21 |
+
Once the extension is enabled, turn on the cell toolbar within your Notebook using
|
22 |
+
the "View > Cell Toolbar > Initialization Cell" menu
|
23 |
+
![Cell Toobar Menu](cell_toolbar_menu.png)
|
24 |
+
|
25 |
+
|
26 |
+
The running of initialization cells on kernel ready notification can be
|
27 |
+
frustrating if your kernel is attached to multiple frontends, or is persistent
|
28 |
+
between frontend reloads (e.g. reloading the notebook browser page without
|
29 |
+
killing the kernel).
|
30 |
+
As such, the option `init_cell.run_on_kernel_ready` in the notebook config
|
31 |
+
section controls whether this behaviour occurs.
|
32 |
+
The server's config value can also be overridden on a per-notebook basis by
|
33 |
+
setting `notebook.metadata.init_cell.run_on_kernel_ready`.
|
34 |
+
|
35 |
+
|
36 |
+
Internals
|
37 |
+
---------
|
38 |
+
|
39 |
+
Cells are marked as initialization cells in their metadata, as
|
40 |
+
|
41 |
+
cell.metadata.init_cell = true
|
42 |
+
|
43 |
+
The running of initialization cells on kernel ready is bound to the Jupyter
|
44 |
+
event `kernel_ready.Kernel`.
|
.local/share/jupyter/nbextensions/init_cell/cell_toolbar_menu.png
ADDED
.local/share/jupyter/nbextensions/init_cell/icon.png
ADDED
.local/share/jupyter/nbextensions/init_cell/init_cell.yaml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Type: Jupyter Notebook Extension
|
2 |
+
Compatibility: 3.x, 4.x, 5.x
|
3 |
+
Name: Initialization cells
|
4 |
+
Main: main.js
|
5 |
+
Icon: icon.png
|
6 |
+
Link: README.md
|
7 |
+
Description: |
|
8 |
+
Add a cell toolbar selector to mark cells as 'initialization' cells. Such
|
9 |
+
initialization cells can be run by on clicking the provided button in the
|
10 |
+
main toolbar, or configurably, run automatically on notebook load.
|
11 |
+
Parameters:
|
12 |
+
- name: init_cell.run_on_kernel_ready
|
13 |
+
description: |
|
14 |
+
Run input cells whenever a kernel_ready.Kernel event is fired. See readme
|
15 |
+
for further details.
|
16 |
+
input_type: checkbox
|
17 |
+
default: true
|
.local/share/jupyter/nbextensions/init_cell/main.js
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
define([
|
2 |
+
'jquery',
|
3 |
+
'base/js/dialog',
|
4 |
+
'base/js/events',
|
5 |
+
'base/js/namespace',
|
6 |
+
'notebook/js/celltoolbar',
|
7 |
+
'notebook/js/codecell',
|
8 |
+
], function (
|
9 |
+
$,
|
10 |
+
dialog,
|
11 |
+
events,
|
12 |
+
Jupyter,
|
13 |
+
celltoolbar,
|
14 |
+
codecell
|
15 |
+
) {
|
16 |
+
"use strict";
|
17 |
+
|
18 |
+
var CellToolbar = celltoolbar.CellToolbar;
|
19 |
+
|
20 |
+
var mod_name = 'init_cell';
|
21 |
+
var log_prefix = '[' + mod_name + ']';
|
22 |
+
var options = { // updated from server's config & nb metadata
|
23 |
+
run_on_kernel_ready: true,
|
24 |
+
};
|
25 |
+
|
26 |
+
var toolbar_preset_name = 'Initialization Cell';
|
27 |
+
var init_cell_ui_callback = CellToolbar.utils.checkbox_ui_generator(
|
28 |
+
toolbar_preset_name,
|
29 |
+
function setter (cell, value) {
|
30 |
+
if (value) {
|
31 |
+
cell.metadata.init_cell = true;
|
32 |
+
}
|
33 |
+
else {
|
34 |
+
delete cell.metadata.init_cell;
|
35 |
+
}
|
36 |
+
},
|
37 |
+
function getter (cell) {
|
38 |
+
// if init_cell is undefined, it'll be interpreted as false anyway
|
39 |
+
return cell.metadata.init_cell;
|
40 |
+
}
|
41 |
+
);
|
42 |
+
|
43 |
+
function count_init_cells () {
|
44 |
+
console.log(log_prefix, 'counting initialization cells');
|
45 |
+
var num = 0;
|
46 |
+
var cells = Jupyter.notebook.get_cells();
|
47 |
+
for (var ii = 0; ii < cells.length; ii++) {
|
48 |
+
var cell = cells[ii];
|
49 |
+
if ((cell instanceof codecell.CodeCell) && cell.metadata.init_cell === true ) {
|
50 |
+
num++;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
console.log(log_prefix, 'found ' + num + ' initialization cell' + (num !== 1 ? 's' : ''));
|
54 |
+
return num
|
55 |
+
}
|
56 |
+
|
57 |
+
function run_init_cells () {
|
58 |
+
console.log(log_prefix, 'running all initialization cells');
|
59 |
+
var num = 0;
|
60 |
+
var cells = Jupyter.notebook.get_cells();
|
61 |
+
for (var ii = 0; ii < cells.length; ii++) {
|
62 |
+
var cell = cells[ii];
|
63 |
+
if ((cell instanceof codecell.CodeCell) && cell.metadata.init_cell === true ) {
|
64 |
+
cell.execute();
|
65 |
+
num++;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
console.log(log_prefix, 'finished running ' + num + ' initialization cell' + (num !== 1 ? 's' : ''));
|
69 |
+
}
|
70 |
+
|
71 |
+
var load_ipython_extension = function() {
|
72 |
+
// register action
|
73 |
+
var prefix = 'auto';
|
74 |
+
var action_name = 'run-initialization-cells';
|
75 |
+
var action = {
|
76 |
+
icon: 'fa-calculator',
|
77 |
+
help: 'Run all initialization cells',
|
78 |
+
help_index : 'zz',
|
79 |
+
handler : run_init_cells
|
80 |
+
};
|
81 |
+
var action_full_name = Jupyter.notebook.keyboard_manager.actions.register(action, action_name, prefix);
|
82 |
+
|
83 |
+
// add toolbar button
|
84 |
+
Jupyter.toolbar.add_buttons_group([action_full_name]);
|
85 |
+
|
86 |
+
// setup things to run on loading config/notebook
|
87 |
+
Jupyter.notebook.config.loaded
|
88 |
+
.then(function update_options_from_config () {
|
89 |
+
$.extend(true, options, Jupyter.notebook.config.data[mod_name]);
|
90 |
+
}, function (reason) {
|
91 |
+
console.warn(log_prefix, 'error loading config:', reason);
|
92 |
+
})
|
93 |
+
.then(function () {
|
94 |
+
if (Jupyter.notebook._fully_loaded) {
|
95 |
+
callback_notebook_loaded();
|
96 |
+
}
|
97 |
+
events.on('notebook_loaded.Notebook', callback_notebook_loaded);
|
98 |
+
}).catch(function (reason) {
|
99 |
+
console.error(log_prefix, 'unhandled error:', reason);
|
100 |
+
});
|
101 |
+
};
|
102 |
+
|
103 |
+
function callback_notebook_loaded () {
|
104 |
+
// update from metadata
|
105 |
+
var md_opts = Jupyter.notebook.metadata[mod_name];
|
106 |
+
if (md_opts !== undefined) {
|
107 |
+
console.log(log_prefix, 'updating options from notebook metadata:', md_opts);
|
108 |
+
$.extend(true, options, md_opts);
|
109 |
+
}
|
110 |
+
|
111 |
+
// register celltoolbar presets if they haven't been already
|
112 |
+
if (CellToolbar.list_presets().indexOf(toolbar_preset_name) < 0) {
|
113 |
+
// Register a callback to create a UI element for a cell toolbar.
|
114 |
+
CellToolbar.register_callback('init_cell.is_init_cell', init_cell_ui_callback, 'code');
|
115 |
+
// Register a preset of UI elements forming a cell toolbar.
|
116 |
+
CellToolbar.register_preset(toolbar_preset_name, ['init_cell.is_init_cell'], Jupyter.notebook);
|
117 |
+
}
|
118 |
+
|
119 |
+
if (options.run_on_kernel_ready) {
|
120 |
+
var num = count_init_cells();
|
121 |
+
|
122 |
+
if (num) {
|
123 |
+
if (Jupyter.notebook.trusted) {
|
124 |
+
run_init_cells_asap()
|
125 |
+
}
|
126 |
+
else {
|
127 |
+
dialog.modal({
|
128 |
+
title : 'Untrusted notebook with initialization code',
|
129 |
+
body : num + ' initialization code cell' + (num !== 1 ? 's' : '') + ' was found but not run since this notebook is untrusted.',
|
130 |
+
buttons: {
|
131 |
+
'Trust notebook': {
|
132 |
+
'class' : 'btn-danger',
|
133 |
+
'click' : () => Jupyter.notebook.trust_notebook()
|
134 |
+
},
|
135 |
+
'Do nothing': {'class' : 'btn-primary'}
|
136 |
+
},
|
137 |
+
notebook: Jupyter.notebook,
|
138 |
+
keyboard_manager: Jupyter.keyboard_manager,
|
139 |
+
});
|
140 |
+
}
|
141 |
+
}
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
function run_init_cells_asap () {
|
146 |
+
if (Jupyter.notebook && Jupyter.notebook.kernel && Jupyter.notebook.kernel.info_reply.status === 'ok') {
|
147 |
+
// kernel is already ready
|
148 |
+
run_init_cells();
|
149 |
+
}
|
150 |
+
// whenever a (new) kernel becomes ready, run all initialization cells
|
151 |
+
events.on('kernel_ready.Kernel', run_init_cells);
|
152 |
+
}
|
153 |
+
|
154 |
+
return {
|
155 |
+
load_ipython_extension : load_ipython_extension
|
156 |
+
};
|
157 |
+
});
|
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/keyboard_shortcut_editor.yaml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Type: IPython Notebook Extension
|
2 |
+
Compatibility: 4.x, 5.x
|
3 |
+
Name: Keyboard shortcut editor
|
4 |
+
Main: main.js
|
5 |
+
Icon: icon.png
|
6 |
+
Link: README.md
|
7 |
+
Description: Edit or remove Jupyter keyboard shortcuts, or add you own new ones
|
8 |
+
Parameters:
|
9 |
+
- name: kse_show_rebinds
|
10 |
+
description: "Show shortcut editing controls in the shortcuts dialog. If this is false, shortcuts can't be edited directly from the notebook, but any existing edits are still applied. Useful essentially just to make the shortcuts dialog a bit cleaner"
|
11 |
+
input_type: checkbox
|
12 |
+
default: true
|
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/kse_components.js
ADDED
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
define([
|
2 |
+
'bootstrap', // for modals
|
3 |
+
'jquery',
|
4 |
+
'base/js/dialog',
|
5 |
+
'base/js/utils',
|
6 |
+
'base/js/keyboard',
|
7 |
+
'notebook/js/quickhelp',
|
8 |
+
'./quickhelp_shim'
|
9 |
+
], function(
|
10 |
+
bs,
|
11 |
+
$,
|
12 |
+
dialog,
|
13 |
+
utils,
|
14 |
+
keyboard,
|
15 |
+
quickhelp,
|
16 |
+
quickhelp_shim
|
17 |
+
){
|
18 |
+
"use strict";
|
19 |
+
|
20 |
+
function only_modifier_event (event) {
|
21 |
+
// adapted from base/js/keyboard
|
22 |
+
/**
|
23 |
+
* Return `true` if the event only contains modifiers keys, false
|
24 |
+
* otherwise
|
25 |
+
*/
|
26 |
+
var key = keyboard.inv_keycodes[event.which];
|
27 |
+
return ((event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) &&
|
28 |
+
(key === 'alt'|| key === 'ctrl'|| key === 'meta'|| key === 'shift'));
|
29 |
+
}
|
30 |
+
|
31 |
+
function editor_build () {
|
32 |
+
var editor = $('#kse-editor');
|
33 |
+
if (editor.length > 0) {
|
34 |
+
return editor;
|
35 |
+
}
|
36 |
+
|
37 |
+
editor = $('<div/>')
|
38 |
+
.addClass('kse-editor')
|
39 |
+
.attr('id', 'kse-editor')
|
40 |
+
.data({
|
41 |
+
'kse_sequence': [],
|
42 |
+
'kse_info': {},
|
43 |
+
'kse_mode': 'command',
|
44 |
+
'kse_undefined_key': false
|
45 |
+
});
|
46 |
+
|
47 |
+
var form = $('<form/>')
|
48 |
+
.addClass('form')
|
49 |
+
.appendTo(editor);
|
50 |
+
|
51 |
+
$('<div/>')
|
52 |
+
.addClass('form-group')
|
53 |
+
.appendTo(form);
|
54 |
+
|
55 |
+
var form_group = $('<div/>')
|
56 |
+
.addClass('form-group has-feedback')
|
57 |
+
.appendTo(form);
|
58 |
+
|
59 |
+
var input_group = $('<div/>')
|
60 |
+
.addClass('input-group')
|
61 |
+
.addClass('kse-input-group')
|
62 |
+
.appendTo(form_group);
|
63 |
+
|
64 |
+
// reset button
|
65 |
+
var btn = $('<a/>')
|
66 |
+
.addClass('btn btn-default')
|
67 |
+
.addClass('kse-input-group-reset')
|
68 |
+
.attr({
|
69 |
+
'title': 'Restart',
|
70 |
+
'type': 'button'
|
71 |
+
})
|
72 |
+
.append(
|
73 |
+
$('<i/>')
|
74 |
+
.addClass('fa fa-repeat')
|
75 |
+
)
|
76 |
+
.on('click', function () {
|
77 |
+
editor.data({
|
78 |
+
'kse_sequence': [],
|
79 |
+
'kse_undefined_key': false
|
80 |
+
});
|
81 |
+
editor_update_input_group(editor);
|
82 |
+
$(this).blur();
|
83 |
+
textcontrol.focus();
|
84 |
+
});
|
85 |
+
$('<div/>')
|
86 |
+
.addClass('input-group-btn')
|
87 |
+
.append(btn)
|
88 |
+
.appendTo(input_group);
|
89 |
+
|
90 |
+
// pretty-displayed shortcut
|
91 |
+
$('<div/>')
|
92 |
+
.addClass('input-group-addon')
|
93 |
+
.addClass('kse-input-group-pretty')
|
94 |
+
.addClass('kse-editor-to')
|
95 |
+
.appendTo(input_group);
|
96 |
+
|
97 |
+
var textcontrol = $('<input/>')
|
98 |
+
.addClass('form-control')
|
99 |
+
.addClass('kse-input-group-input')
|
100 |
+
.attr({
|
101 |
+
'type': 'text',
|
102 |
+
'placeholder': 'click here to edit the shortcut'
|
103 |
+
})
|
104 |
+
.on('keydown', editor_handle_shortcut_keydown)
|
105 |
+
.on('focus', function (evt) {
|
106 |
+
$(this).attr('placeholder', 'press keys to add to the shortcut');
|
107 |
+
})
|
108 |
+
.on('blur', function (evt) {
|
109 |
+
$(this).attr('placeholder', 'click here to edit the shortcut');
|
110 |
+
})
|
111 |
+
.appendTo(input_group);
|
112 |
+
|
113 |
+
// feedback icon
|
114 |
+
var form_fdbck = $('<i/>')
|
115 |
+
.addClass('fa fa-lg');
|
116 |
+
$('<span/>')
|
117 |
+
.addClass('form-control-feedback')
|
118 |
+
.append(form_fdbck)
|
119 |
+
.appendTo(form_group);
|
120 |
+
|
121 |
+
// help for input group
|
122 |
+
$('<span/>')
|
123 |
+
.addClass('help-block')
|
124 |
+
.appendTo(form_group);
|
125 |
+
|
126 |
+
return editor;
|
127 |
+
}
|
128 |
+
|
129 |
+
function editor_update_input_group (editor, seq) {
|
130 |
+
seq = seq || editor.data('kse_sequence');
|
131 |
+
var shortcut = seq.join(',');
|
132 |
+
var mode = editor.data('kse_mode');
|
133 |
+
var have_seq = seq.length > 0;
|
134 |
+
var valid = have_seq;
|
135 |
+
|
136 |
+
// empty help block
|
137 |
+
var feedback = editor.find('.form-group.has-feedback:first');
|
138 |
+
var help_block = feedback.find('.help-block');
|
139 |
+
help_block.empty();
|
140 |
+
|
141 |
+
var ii;
|
142 |
+
var has_comma = false;
|
143 |
+
for (ii = 0; !has_comma && (ii < seq.length); ii++) {
|
144 |
+
has_comma = seq[ii].indexOf(',') >= 0;
|
145 |
+
}
|
146 |
+
|
147 |
+
if (has_comma) {
|
148 |
+
valid = false;
|
149 |
+
// use HTML Unicode escape for a comma, to get it to look right in the pretty version
|
150 |
+
shortcut = $.map(seq, function (elem, idx) {
|
151 |
+
return elem.replace(',', ',');
|
152 |
+
}).join(',');
|
153 |
+
|
154 |
+
$('<p/>')
|
155 |
+
.html(
|
156 |
+
'Unfortunately, Jupyter\'s handling of shortcuts containing ' +
|
157 |
+
'commas (<kbd>,</kbd>) is fundamentally flawed, ' +
|
158 |
+
'as the comma is used as the key-separator character ☹. ' +
|
159 |
+
'Please try something else for your rebind!'
|
160 |
+
)
|
161 |
+
.appendTo(help_block);
|
162 |
+
}
|
163 |
+
else if (have_seq) {
|
164 |
+
var conflicts = {};
|
165 |
+
var tree;
|
166 |
+
|
167 |
+
// get existing shortcuts
|
168 |
+
if (Jupyter.keyboard_manager !== undefined) {
|
169 |
+
var startkey = seq.slice(0, 1)[0];
|
170 |
+
if (mode === 'command') {
|
171 |
+
tree = Jupyter.keyboard_manager.command_shortcuts.get_shortcut(startkey);
|
172 |
+
}
|
173 |
+
else {
|
174 |
+
tree = Jupyter.keyboard_manager.edit_shortcuts.get_shortcut(startkey);
|
175 |
+
// deal with codemirror shortcuts specially, since they're not included in kbm
|
176 |
+
for (var jj = 0; jj < quickhelp.cm_shortcuts.length; jj++) {
|
177 |
+
var cm_shrt = quickhelp.cm_shortcuts[jj];
|
178 |
+
if (keyboard.normalize_shortcut(cm_shrt.shortcut) === startkey) {
|
179 |
+
tree = cm_shrt.help;
|
180 |
+
break;
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
// check for conflicting shortcuts.
|
187 |
+
// Start at 1 because we got tree from startkey
|
188 |
+
for (ii = 1; (ii < seq.length) && (tree !== undefined); ii++) {
|
189 |
+
// check for exsiting definitions at current specificity
|
190 |
+
if (typeof(tree) === 'string') {
|
191 |
+
valid = false;
|
192 |
+
conflicts[seq.slice(0, ii).join(',')] = tree;
|
193 |
+
break;
|
194 |
+
}
|
195 |
+
tree = tree[seq[ii]];
|
196 |
+
}
|
197 |
+
|
198 |
+
// check whether any more-specific shortcuts were defined
|
199 |
+
if ((ii === seq.length) && (tree !== undefined)) {
|
200 |
+
valid = false;
|
201 |
+
var flatten_conflict_tree = function flatten_conflict_tree (obj, key) {
|
202 |
+
if (typeof(obj) === 'string') {
|
203 |
+
conflicts[key] = obj;
|
204 |
+
}
|
205 |
+
else for (var subkey in obj) {
|
206 |
+
if (obj.hasOwnProperty(subkey)) {
|
207 |
+
flatten_conflict_tree(obj[key], [key, subkey].join(','));
|
208 |
+
}
|
209 |
+
}
|
210 |
+
};
|
211 |
+
flatten_conflict_tree(tree, seq.join(','));
|
212 |
+
}
|
213 |
+
|
214 |
+
if (!valid) {
|
215 |
+
var plural = Object.keys(conflicts).length != 1;
|
216 |
+
$('<p/>')
|
217 |
+
.append(quickhelp.humanize_sequence(seq.join(',')))
|
218 |
+
.append(
|
219 |
+
' conflicts with the' + (plural ? ' following' : '') +
|
220 |
+
' existing shortcut' + (plural ? 's' : '') + ':'
|
221 |
+
)
|
222 |
+
.appendTo(help_block);
|
223 |
+
|
224 |
+
for (var conflicting_shortcut in conflicts) {
|
225 |
+
if (conflicts.hasOwnProperty(conflicting_shortcut)) {
|
226 |
+
$('<p/>')
|
227 |
+
.append(quickhelp.humanize_sequence(conflicting_shortcut))
|
228 |
+
.append($('<code/>').text(conflicts[conflicting_shortcut]))
|
229 |
+
.appendTo(help_block);
|
230 |
+
}
|
231 |
+
}
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
if (editor.data('kse_undefined_key')) {
|
236 |
+
var warning = $('<span/>')
|
237 |
+
.addClass('form-group has-feedback has-warning kse-undefined')
|
238 |
+
.append(
|
239 |
+
$('<span/>')
|
240 |
+
.addClass('help-block')
|
241 |
+
.append(
|
242 |
+
$('<p/>').text('Unrecognised key! (code ' + editor.data('kse_undefined_key' ) + ')')
|
243 |
+
)
|
244 |
+
);
|
245 |
+
|
246 |
+
var existing = editor.find('.kse-undefined');
|
247 |
+
if (existing.length > 0) {
|
248 |
+
existing.replaceWith(warning);
|
249 |
+
}
|
250 |
+
else {
|
251 |
+
warning.insertAfter(feedback);
|
252 |
+
}
|
253 |
+
setTimeout(function () {
|
254 |
+
warning.remove();
|
255 |
+
}, 2000);
|
256 |
+
}
|
257 |
+
|
258 |
+
// disable reset button if no sequence
|
259 |
+
editor.find('.kse-input-group-reset')
|
260 |
+
.toggleClass('disabled', !have_seq);
|
261 |
+
|
262 |
+
editor.find('.kse-input-group-pretty')
|
263 |
+
.html(shortcut ? quickhelp.humanize_sequence(shortcut) : '<new shortcut>');
|
264 |
+
|
265 |
+
feedback
|
266 |
+
.toggleClass('has-error', !valid && have_seq)
|
267 |
+
.toggleClass('has-success', valid && have_seq)
|
268 |
+
.find('.form-control-feedback .fa')
|
269 |
+
.toggleClass('fa-remove', !valid && have_seq)
|
270 |
+
.toggleClass('fa-check', valid && have_seq);
|
271 |
+
}
|
272 |
+
|
273 |
+
function editor_handle_shortcut_keydown (evt) {
|
274 |
+
var elem = $(evt.delegateTarget);
|
275 |
+
if (!only_modifier_event(evt)) {
|
276 |
+
var shortcut = keyboard.normalize_shortcut(keyboard.event_to_shortcut(evt));
|
277 |
+
var editor = elem.closest('#kse-editor');
|
278 |
+
var seq = editor.data('kse_sequence');
|
279 |
+
var has_undefined_key = (shortcut.toLowerCase().indexOf('undefined') !== -1);
|
280 |
+
editor.data('kse_undefined_key', has_undefined_key);
|
281 |
+
if (has_undefined_key) {
|
282 |
+
// deal with things like ~ appearing on apple alt-n, or ¨ on alt-u
|
283 |
+
editor.find('.kse-input-group-input').val('');
|
284 |
+
editor.data('kse_undefined_key', evt.which || true);
|
285 |
+
}
|
286 |
+
else {
|
287 |
+
seq.push(shortcut);
|
288 |
+
}
|
289 |
+
editor_update_input_group(editor, seq);
|
290 |
+
}
|
291 |
+
}
|
292 |
+
|
293 |
+
function modal_build (editor, modal_options) {
|
294 |
+
var modal = $('#kse-editor-modal');
|
295 |
+
if (modal.length > 0) {
|
296 |
+
return modal;
|
297 |
+
}
|
298 |
+
|
299 |
+
var default_modal_options = {
|
300 |
+
'destroy': false,
|
301 |
+
'show': false,
|
302 |
+
'title': 'Edit keyboard shortcut',
|
303 |
+
'body': editor,
|
304 |
+
'buttons': {
|
305 |
+
'OK': {'class': 'btn-primary'},
|
306 |
+
'Cancel': {}
|
307 |
+
},
|
308 |
+
'open': function (evt) {
|
309 |
+
$(this).find('.kse-input-group-input').focus();
|
310 |
+
}
|
311 |
+
};
|
312 |
+
if (Jupyter.notebook !== undefined) {
|
313 |
+
default_modal_options.notebook = Jupyter.notebook;
|
314 |
+
}
|
315 |
+
if (Jupyter.keyboard_manager !== undefined) {
|
316 |
+
default_modal_options.keyboard_manager= Jupyter.keyboard_manager;
|
317 |
+
}
|
318 |
+
modal_options = $.extend({}, default_modal_options, modal_options);
|
319 |
+
|
320 |
+
modal = dialog.modal(modal_options);
|
321 |
+
|
322 |
+
modal
|
323 |
+
.addClass('modal_stretch')
|
324 |
+
.attr('id', 'kse-editor-modal');
|
325 |
+
|
326 |
+
// Add a data-target attribute to ensure buttons only target the editor modal
|
327 |
+
modal.find('.close,.modal-footer button')
|
328 |
+
.attr('data-target', '#kse-editor-modal');
|
329 |
+
|
330 |
+
return modal;
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Pass it an option dictionary with any of the bootstrap or base/js/dialog
|
335 |
+
* modal options, plus the following optional properties:
|
336 |
+
* - description: html for the form group preceding the editor group,
|
337 |
+
* useful as a description
|
338 |
+
*/
|
339 |
+
function KSE_modal (modal_options) {
|
340 |
+
var editor = editor_build();
|
341 |
+
editor.data({'kse_sequence': [], 'kse_undefined_key': false});
|
342 |
+
editor_update_input_group(editor);
|
343 |
+
var modal = modal_build(editor, modal_options);
|
344 |
+
|
345 |
+
editor.on('keydown', '.kse-input-group-input', function (evt) {
|
346 |
+
event.preventDefault();
|
347 |
+
event.stopPropagation();
|
348 |
+
return false;
|
349 |
+
});
|
350 |
+
|
351 |
+
if (modal_options.description) {
|
352 |
+
modal.find('.modal-body .form-group:first').html(modal_options.description);
|
353 |
+
}
|
354 |
+
|
355 |
+
return modal;
|
356 |
+
}
|
357 |
+
|
358 |
+
return {
|
359 |
+
editor_build : editor_build,
|
360 |
+
editor_update_input_group: editor_update_input_group,
|
361 |
+
modal_build : modal_build,
|
362 |
+
KSE_modal : KSE_modal
|
363 |
+
};
|
364 |
+
});
|
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/main.css
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.kse-dropdown {
|
2 |
+
margin-left: 0.5em;
|
3 |
+
}
|
4 |
+
|
5 |
+
.kse-dropdown > .dropdown-menu {
|
6 |
+
min-width: 0;
|
7 |
+
top: 20px;
|
8 |
+
}
|
9 |
+
|
10 |
+
.kse-input-group-pretty {
|
11 |
+
min-width: 20ex;
|
12 |
+
}
|
13 |
+
|
14 |
+
.kse-modal-backdrop {
|
15 |
+
background-color: #fff;
|
16 |
+
}
|
17 |
+
|
18 |
+
.kse-input-group-reset,
|
19 |
+
.kse-input-group-pretty {
|
20 |
+
border-right: none;
|
21 |
+
}
|
22 |
+
|
23 |
+
.kse-input-group-pretty > kbd {
|
24 |
+
color: black;
|
25 |
+
font-weight: bold;
|
26 |
+
}
|
27 |
+
|
28 |
+
.kse-editor .help-block > p {
|
29 |
+
margin-bottom: 10px;
|
30 |
+
}
|
31 |
+
|
32 |
+
.kse-editor select {
|
33 |
+
display: inline-block;
|
34 |
+
width: auto;
|
35 |
+
margin: 0;
|
36 |
+
}
|
37 |
+
|
38 |
+
.kse-links .fa {
|
39 |
+
margin-right: 2px;
|
40 |
+
}
|
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/main.js
ADDED
@@ -0,0 +1,778 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
define([
|
2 |
+
'jquery',
|
3 |
+
'require',
|
4 |
+
'base/js/namespace',
|
5 |
+
'base/js/dialog',
|
6 |
+
'base/js/events',
|
7 |
+
'base/js/keyboard',
|
8 |
+
'notebook/js/quickhelp',
|
9 |
+
'./quickhelp_shim',
|
10 |
+
'./kse_components',
|
11 |
+
], function (
|
12 |
+
$,
|
13 |
+
requirejs,
|
14 |
+
Jupyter,
|
15 |
+
dialog,
|
16 |
+
events,
|
17 |
+
keyboard,
|
18 |
+
quickhelp,
|
19 |
+
qh_shim,
|
20 |
+
kse_comp
|
21 |
+
) {
|
22 |
+
"use strict";
|
23 |
+
|
24 |
+
var mod_name = 'keyboard_shortcut_editor';
|
25 |
+
|
26 |
+
// define default values for config parameters
|
27 |
+
var params = {
|
28 |
+
'kse_show_rebinds': true,
|
29 |
+
// mode, action name, new combo
|
30 |
+
'kse_rebinds': {
|
31 |
+
// command-mode rebindings
|
32 |
+
'command': [
|
33 |
+
// { // disable the default 'space' shortcut, which used to scroll the notebook down
|
34 |
+
// from: "space",
|
35 |
+
// action_name: "jupyter-notebook:scroll-notebook-down"
|
36 |
+
// },
|
37 |
+
// { // create a new shortcut 't,t' to trust the notebook
|
38 |
+
// action_name: "jupyter-notebook:trust-notebook",
|
39 |
+
// to: "t,t"
|
40 |
+
// },
|
41 |
+
// { // change the default save-notebook shortcut from 's' to 'shift-s'
|
42 |
+
// action_name: "jupyter-notebook:save-notebook",
|
43 |
+
// to: "shift-s",
|
44 |
+
// from: "s"
|
45 |
+
// }
|
46 |
+
],
|
47 |
+
// edit-mode rebindings:
|
48 |
+
"edit": [
|
49 |
+
// { // disable the default edit-mode binding which switches to command mode
|
50 |
+
// action_name: "jupyter-notebook:enter-command-mode",
|
51 |
+
// from: "ctrl-m"
|
52 |
+
// }
|
53 |
+
]
|
54 |
+
}
|
55 |
+
};
|
56 |
+
// function to update params with any specified in the server's config file
|
57 |
+
function update_params () {
|
58 |
+
var config = Jupyter.notebook.config;
|
59 |
+
for (var key in params) {
|
60 |
+
if (config.data.hasOwnProperty(key)) {
|
61 |
+
params[key] = config.data[key];
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
function add_css (url) {
|
67 |
+
$('<link/>')
|
68 |
+
.attr({
|
69 |
+
'rel': 'stylesheet',
|
70 |
+
'type': 'text/css',
|
71 |
+
'href': requirejs.toUrl(url)
|
72 |
+
})
|
73 |
+
.appendTo($('head'));
|
74 |
+
}
|
75 |
+
|
76 |
+
var kbm = Jupyter.keyboard_manager;
|
77 |
+
var deleted_shortcuts = {
|
78 |
+
'command': new keyboard.ShortcutManager(undefined, kbm.command_shortcuts.events, kbm.actions, kbm.env),
|
79 |
+
'edit': new keyboard.ShortcutManager(undefined, kbm.edit_shortcuts.events, kbm.actions, kbm.env)
|
80 |
+
};
|
81 |
+
|
82 |
+
var patched_quickhelp_prototype = false;
|
83 |
+
var patched_shortcut_manager_prototype = false;
|
84 |
+
|
85 |
+
function patch_shortcut_manager_prototype () {
|
86 |
+
if (!patched_shortcut_manager_prototype) {
|
87 |
+
var orig_add_shortcut = keyboard.ShortcutManager.prototype.add_shortcut;
|
88 |
+
keyboard.ShortcutManager.prototype.add_shortcut = function add_shortcut (shortcut, data, suppress_help_update, called_by_rebinder) {
|
89 |
+
if (!called_by_rebinder) {
|
90 |
+
var this_mode;
|
91 |
+
if (this === kbm.edit_shortcuts) {
|
92 |
+
this_mode = 'edit';
|
93 |
+
}
|
94 |
+
else if (this === kbm.command_shortcuts) {
|
95 |
+
this_mode = 'command';
|
96 |
+
}
|
97 |
+
if (this_mode) {
|
98 |
+
var rebind_specs = params.kse_rebinds[this_mode];
|
99 |
+
for (var ii = 0; ii < rebind_specs.length; ii++) {
|
100 |
+
var spec = rebind_specs[ii];
|
101 |
+
if (spec.from === shortcut) {
|
102 |
+
if (!spec.to) {
|
103 |
+
return;
|
104 |
+
}
|
105 |
+
shortcut = spec.to;
|
106 |
+
}
|
107 |
+
}
|
108 |
+
}
|
109 |
+
}
|
110 |
+
return orig_add_shortcut.call(this, shortcut, data, suppress_help_update);
|
111 |
+
};
|
112 |
+
console.log('[' + mod_name + '] patched ShortcutManager.prototype.add_shortcut');
|
113 |
+
patched_shortcut_manager_prototype = true;
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
function patch_quickhelp_prototype () {
|
118 |
+
if (!patched_quickhelp_prototype) {
|
119 |
+
var orig_build_command_help = quickhelp.QuickHelp.prototype.build_command_help;
|
120 |
+
quickhelp.QuickHelp.prototype.build_command_help = function () {
|
121 |
+
var div = orig_build_command_help.call(this);
|
122 |
+
return quickhelp_div_add_rebind_controls(div, 'command');
|
123 |
+
};
|
124 |
+
console.log('[' + mod_name + '] patched QuickHelp.prototype.build_command_help');
|
125 |
+
|
126 |
+
var orig_build_edit_help = quickhelp.QuickHelp.prototype.build_edit_help;
|
127 |
+
quickhelp.QuickHelp.prototype.build_edit_help = function (cm_shortcuts) {
|
128 |
+
var div = orig_build_edit_help.call(this, cm_shortcuts);
|
129 |
+
return quickhelp_div_add_rebind_controls(div, 'edit');
|
130 |
+
};
|
131 |
+
console.log('[' + mod_name + '] patched QuickHelp.prototype.build_edit_help');
|
132 |
+
|
133 |
+
patched_quickhelp_prototype = true;
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
function load_jupyter_extension () {
|
138 |
+
add_css('./main.css');
|
139 |
+
patch_shortcut_manager_prototype();
|
140 |
+
patch_quickhelp_prototype();
|
141 |
+
Jupyter.notebook.config.loaded.then(initialize);
|
142 |
+
}
|
143 |
+
|
144 |
+
function get_mode_shortcuts (mode, deleted) {
|
145 |
+
if (deleted) {
|
146 |
+
return deleted_shortcuts[mode];
|
147 |
+
}
|
148 |
+
else if (mode === 'command') {
|
149 |
+
return kbm.command_shortcuts;
|
150 |
+
}
|
151 |
+
else if (mode === 'edit') {
|
152 |
+
return kbm.edit_shortcuts;
|
153 |
+
}
|
154 |
+
return undefined;
|
155 |
+
}
|
156 |
+
|
157 |
+
function rebind (mode, spec, suppress_help_update) {
|
158 |
+
var shortcuts = get_mode_shortcuts(mode);
|
159 |
+
if (spec.action_name === undefined) {
|
160 |
+
spec.action_name = shortcuts.get_shortcut(spec.from);
|
161 |
+
}
|
162 |
+
if (!shortcuts.actions.exists(spec.action_name)) {
|
163 |
+
console.warn(
|
164 |
+
'[' + mod_name + '] ' +
|
165 |
+
'rebind specified for unrecognised action "' +
|
166 |
+
spec.action_name + '"' +
|
167 |
+
(spec.from ? ' from ' + spec.from : '') +
|
168 |
+
(spec.to ? ' to ' + spec.to : '')
|
169 |
+
);
|
170 |
+
}
|
171 |
+
else {
|
172 |
+
console.log(
|
173 |
+
'[' + mod_name + '] ' +
|
174 |
+
(spec.from ? (spec.to ? 're' : 'un') : '') + 'bound ' +
|
175 |
+
spec.action_name +
|
176 |
+
(spec.from ? ' from ' + spec.from : '') +
|
177 |
+
(spec.to ? ' to ' + spec.to : '')
|
178 |
+
);
|
179 |
+
|
180 |
+
if (spec.from) {
|
181 |
+
if (!spec.to) {
|
182 |
+
deleted_shortcuts[mode].add_shortcut(spec.from, spec.action_name, true, true);
|
183 |
+
}
|
184 |
+
shortcuts.remove_shortcut(spec.from);
|
185 |
+
}
|
186 |
+
if (spec.to) {
|
187 |
+
return shortcuts.add_shortcut(spec.to, spec.action_name, suppress_help_update, true);
|
188 |
+
}
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
function apply_config_rebinds () {
|
193 |
+
var modes = ['command', 'edit'];
|
194 |
+
for (var mm = 0; mm < modes.length; mm++) {
|
195 |
+
var mode = modes[mm];
|
196 |
+
if (params.kse_rebinds.hasOwnProperty(mode)) {
|
197 |
+
var rebind_specs = params.kse_rebinds[mode];
|
198 |
+
for (var ii = 0; ii < rebind_specs.length; ii++) {
|
199 |
+
rebind(mode, rebind_specs[ii], true);
|
200 |
+
}
|
201 |
+
}
|
202 |
+
}
|
203 |
+
events.trigger('rebuild.QuickHelp');
|
204 |
+
}
|
205 |
+
|
206 |
+
var initialize = function () {
|
207 |
+
update_params();
|
208 |
+
apply_config_rebinds();
|
209 |
+
var title = $('#keyboard_shortcuts').attr('title');
|
210 |
+
$('#keyboard_shortcuts').attr('title', title + ' & controls to edit them');
|
211 |
+
};
|
212 |
+
|
213 |
+
function reverse_spec (spec) {
|
214 |
+
var new_spec = {action_name: spec.action_name};
|
215 |
+
if (spec.from) {
|
216 |
+
new_spec.to = spec.from;
|
217 |
+
}
|
218 |
+
if (spec.to) {
|
219 |
+
new_spec.from = spec.to;
|
220 |
+
}
|
221 |
+
return new_spec;
|
222 |
+
}
|
223 |
+
|
224 |
+
function find_rebinding (rebinds, partial_spec, index_only) {
|
225 |
+
for (var ii = 0; ii < rebinds.length; ii++) {
|
226 |
+
if (((partial_spec.to === undefined) ||
|
227 |
+
(partial_spec.to === rebinds[ii].to)) &&
|
228 |
+
((partial_spec.from === undefined) ||
|
229 |
+
(partial_spec.from === rebinds[ii].from)) &&
|
230 |
+
((partial_spec.action_name === undefined) ||
|
231 |
+
(partial_spec.action_name === rebinds[ii].action_name))) {
|
232 |
+
return index_only ? ii : rebinds[ii];
|
233 |
+
}
|
234 |
+
}
|
235 |
+
return undefined;
|
236 |
+
}
|
237 |
+
|
238 |
+
function register_rebinding (mode, spec) {
|
239 |
+
var rebinds = params.kse_rebinds[mode];
|
240 |
+
rebinds.push($.extend({}, spec));
|
241 |
+
// write our private copy to the config:
|
242 |
+
Jupyter.notebook.config.update(params);
|
243 |
+
console.log('[' + mod_name + '] rebinding added:', spec);
|
244 |
+
}
|
245 |
+
|
246 |
+
function deregister_rebinding (mode, partial_spec) {
|
247 |
+
var rebinds = params.kse_rebinds[mode];
|
248 |
+
var idx = find_rebinding(rebinds, partial_spec, true);
|
249 |
+
if (idx === undefined) {
|
250 |
+
console.warn('[' + mod_name + '] attempted to delete non-exsitent shortcut:', partial_spec);
|
251 |
+
return undefined;
|
252 |
+
}
|
253 |
+
var deleted = rebinds.splice(idx, 1)[0];
|
254 |
+
// write our private copy to the config:
|
255 |
+
Jupyter.notebook.config.update(params);
|
256 |
+
console.log('[' + mod_name + '] rebinding removed:', deleted);
|
257 |
+
return deleted;
|
258 |
+
}
|
259 |
+
|
260 |
+
function action_selector (default_pair) {
|
261 |
+
var select = $('<select/>')
|
262 |
+
.append(
|
263 |
+
$('<option/>')
|
264 |
+
.attr('value', '')
|
265 |
+
.text('select an action')
|
266 |
+
)
|
267 |
+
.addClass('form-control select-xs');
|
268 |
+
|
269 |
+
var action_names = [];
|
270 |
+
$.each(kbm.actions._actions, function (key, val) {
|
271 |
+
if (key !== 'ignore') {
|
272 |
+
action_names.push(key);
|
273 |
+
}
|
274 |
+
});
|
275 |
+
action_names.sort();
|
276 |
+
|
277 |
+
for (var ii = 0; ii < action_names.length; ii++) {
|
278 |
+
select.append(
|
279 |
+
$('<option/>')
|
280 |
+
.attr('value', action_names[ii])
|
281 |
+
.append(
|
282 |
+
$('<code/>')
|
283 |
+
.text(action_names[ii])
|
284 |
+
)
|
285 |
+
// .text(kbm.actions.get(action_name).help)
|
286 |
+
);
|
287 |
+
}
|
288 |
+
return select;
|
289 |
+
}
|
290 |
+
|
291 |
+
function quickhelp_rebuild_mode_div (div) {
|
292 |
+
if ((div === undefined) || (div.data('kse_mode') === 'command')) {
|
293 |
+
div.replaceWith(Jupyter.quick_help.build_command_help());
|
294 |
+
}
|
295 |
+
if ((div === undefined) || (div.data('kse_mode') === 'edit')) {
|
296 |
+
div.replaceWith(Jupyter.quick_help.build_edit_help(quickhelp.cm_shortcuts));
|
297 |
+
}
|
298 |
+
return div;
|
299 |
+
}
|
300 |
+
|
301 |
+
function modal_update_ok_disable_status (evt) {
|
302 |
+
var editor = $(evt.delegateTarget);
|
303 |
+
if (!editor.is('#kse-editor')) {
|
304 |
+
editor = editor.closest('#kse-editor');
|
305 |
+
}
|
306 |
+
var feedback = editor.find('.has-feedback:first');
|
307 |
+
var valid = feedback.hasClass('has-success');
|
308 |
+
if (valid) {
|
309 |
+
valid = valid && editor.data('kse_sequence').length > 0;
|
310 |
+
}
|
311 |
+
var modal = editor.closest('#kse-editor-modal');
|
312 |
+
if (valid) {
|
313 |
+
var select = modal.find('select');
|
314 |
+
if (select.length > 0) {
|
315 |
+
valid = valid && select.val();
|
316 |
+
}
|
317 |
+
}
|
318 |
+
modal.find('.modal-footer button:first').prop('disabled', !valid);
|
319 |
+
}
|
320 |
+
|
321 |
+
|
322 |
+
function modal_ok_click_callback (evt) {
|
323 |
+
var editor = $('#kse-editor');
|
324 |
+
var new_shortcut = editor.data('kse_sequence').join(',');
|
325 |
+
var info = editor.data('kse_info');
|
326 |
+
var mode = editor.data('kse_mode');
|
327 |
+
var new_spec = {
|
328 |
+
'action_name': info.action_name,
|
329 |
+
'to': new_shortcut
|
330 |
+
};
|
331 |
+
if (info.rebound) {
|
332 |
+
// editing an existing rebinding
|
333 |
+
deregister_rebinding(mode, info.spec);
|
334 |
+
// rebind directly
|
335 |
+
rebind(mode, $.extend({'from': info.spec.to}, new_spec), true);
|
336 |
+
// get registration correct
|
337 |
+
new_spec.from = info.spec.from;
|
338 |
+
}
|
339 |
+
else {
|
340 |
+
if (info.spec.to) {
|
341 |
+
// editing an existing binding, so ensure there's a from
|
342 |
+
new_spec.from = info.spec.to;
|
343 |
+
}
|
344 |
+
rebind(mode, new_spec, true);
|
345 |
+
}
|
346 |
+
if (new_spec.from !== new_spec.to) {
|
347 |
+
register_rebinding(mode, new_spec);
|
348 |
+
}
|
349 |
+
quickhelp_rebuild_mode_div(info.div);
|
350 |
+
}
|
351 |
+
|
352 |
+
var modal_options_for_edit = {
|
353 |
+
backdrop: false,
|
354 |
+
buttons: {
|
355 |
+
OK: {
|
356 |
+
'class':'btn-primary',
|
357 |
+
'click': modal_ok_click_callback
|
358 |
+
},
|
359 |
+
Cancel: {}
|
360 |
+
}
|
361 |
+
};
|
362 |
+
|
363 |
+
function modal_prepare_editor(modal, editor, info) {
|
364 |
+
// ensure events are bound
|
365 |
+
if (!editor.data('kse_modal_events_bound')) {
|
366 |
+
editor.on('keydown', '.kse-input-group-input', function (evt) {
|
367 |
+
evt.preventDefault();
|
368 |
+
evt.stopPropagation();
|
369 |
+
modal_update_ok_disable_status(evt);
|
370 |
+
return false;
|
371 |
+
});
|
372 |
+
editor.on('click', '.kse-input-group-reset', modal_update_ok_disable_status);
|
373 |
+
editor.on('change', 'select', modal_update_ok_disable_status);
|
374 |
+
editor.data('kse_modal_events_bound', true);
|
375 |
+
}
|
376 |
+
// reset data
|
377 |
+
editor.data('kse_sequence', []);
|
378 |
+
editor.data('kse_info', info);
|
379 |
+
editor.data('kse_mode', info.mode);
|
380 |
+
editor.find('.kse-input-group-reset').click();
|
381 |
+
|
382 |
+
// add description
|
383 |
+
var descript_div = editor.find('.form-group:first').empty();
|
384 |
+
if (info.action_name) { // this is a rebind
|
385 |
+
descript_div
|
386 |
+
.append('Rebinding ')
|
387 |
+
.append(
|
388 |
+
$('<code/>')
|
389 |
+
.addClass('kse-action')
|
390 |
+
.text(info.spec.action_name)
|
391 |
+
)
|
392 |
+
.append(' from ')
|
393 |
+
.append(
|
394 |
+
$('<span/>')
|
395 |
+
.addClass('kse-from')
|
396 |
+
.html(quickhelp.humanize_sequence(info.spec.to || ''))
|
397 |
+
)
|
398 |
+
.append(' to:');
|
399 |
+
}
|
400 |
+
else {
|
401 |
+
// this is a nubind
|
402 |
+
var select = action_selector();
|
403 |
+
select.on('change', function (event) {
|
404 |
+
var action_name = $(this).val();
|
405 |
+
$.extend(true, info, {'action_name': action_name, 'spec': {'action_name': action_name}});
|
406 |
+
});
|
407 |
+
descript_div
|
408 |
+
.append('Bind ')
|
409 |
+
.append(select)
|
410 |
+
.append(' to:');
|
411 |
+
}
|
412 |
+
kse_comp.editor_update_input_group(editor);
|
413 |
+
}
|
414 |
+
|
415 |
+
function modal_show_above_quickhelp_modal(modal) {
|
416 |
+
// add a custom backdrop which covers the quickhelp modal.
|
417 |
+
// We do this every time, as bootstrap destroys it every time.
|
418 |
+
var backdrop = modal.data('bs.modal').$backdrop = $('<div/>')
|
419 |
+
.attr('id', 'kse-modal-backdrop')
|
420 |
+
.addClass('kse-modal-backdrop')
|
421 |
+
.addClass('modal-backdrop fade')
|
422 |
+
.appendTo(Jupyter.quick_help.shortcut_dialog.find('.modal-content'));
|
423 |
+
|
424 |
+
// get offsetWidth to force reflow, otherwise animation doesn't show
|
425 |
+
var tmp = backdrop[0].offsetWidth;
|
426 |
+
// now trigger animation by adding class
|
427 |
+
backdrop
|
428 |
+
.addClass('in');
|
429 |
+
// show the modal once the (backdrop) transition is complete
|
430 |
+
backdrop
|
431 |
+
.one('bsTransitionEnd', function () {
|
432 |
+
modal.modal('show');
|
433 |
+
})
|
434 |
+
.emulateTransitionEnd(150);
|
435 |
+
}
|
436 |
+
|
437 |
+
function build_rebind_rep_list (mode) {
|
438 |
+
var rep_list = $('<div/>')
|
439 |
+
.addClass('kse-rep-list');
|
440 |
+
|
441 |
+
var shortcuts = get_mode_shortcuts(mode);
|
442 |
+
var rebind_specs = params.kse_rebinds[mode];
|
443 |
+
|
444 |
+
for (var ii = 0; ii < rebind_specs.length; ii++) {
|
445 |
+
var spec = rebind_specs[ii];
|
446 |
+
var verb = (spec.from ? (spec.to ? 're' : 'un') : '') + 'bound';
|
447 |
+
var rep = $('<div/>')
|
448 |
+
.append(
|
449 |
+
$('<code/>')
|
450 |
+
.text(spec.action_name)
|
451 |
+
)
|
452 |
+
.append(' ' + verb)
|
453 |
+
.appendTo(rep_list);
|
454 |
+
if (spec.from) {
|
455 |
+
rep.append(' from ' + quickhelp.humanize_sequence(spec.from));
|
456 |
+
}
|
457 |
+
if (spec.to) {
|
458 |
+
rep.append(' to ' + quickhelp.humanize_sequence(spec.to));
|
459 |
+
}
|
460 |
+
}
|
461 |
+
|
462 |
+
return rep_list;
|
463 |
+
}
|
464 |
+
|
465 |
+
function btn_get_info (btn) {
|
466 |
+
/**
|
467 |
+
* get the shortcut info associated with a quickhelp button element
|
468 |
+
*/
|
469 |
+
var info = {};
|
470 |
+
btn = info.btn = $(btn);
|
471 |
+
var qh_div = info.qh_div = btn.closest('.quickhelp');
|
472 |
+
var div = info.div = qh_div.closest('.kse-div');
|
473 |
+
|
474 |
+
var mode = info.mode = div.data('kse_mode');
|
475 |
+
var unbound = info.unbound = qh_div.hasClass('kse-unbound');
|
476 |
+
var rebound = info.rebound = qh_div.hasClass('kse-rebound');
|
477 |
+
info.nubound = qh_div.hasClass('kse-nubound');
|
478 |
+
|
479 |
+
var shortcuts = info.shortcuts = get_mode_shortcuts(mode, unbound);
|
480 |
+
// Make sure we remove jupyter-notebook:ignore shortcuts.
|
481 |
+
var shortcut_help_arr = info.shortcut_help_arr = shortcuts.help().filter(
|
482 |
+
function (shortcut) {
|
483 |
+
return (shortcut.help !== 'ignore');
|
484 |
+
}
|
485 |
+
);
|
486 |
+
|
487 |
+
var idx = info.idx = div.find('.quickhelp:not(.kse-links,.kse-codemirror)')[unbound ? 'filter' : 'not']('.kse-unbound').index(qh_div);
|
488 |
+
|
489 |
+
var keycombo = info.keycombo = shortcut_help_arr[idx].shortcut;
|
490 |
+
var action_name = info.action_name = shortcuts.get_shortcut(keycombo);
|
491 |
+
var spec = info.spec = {
|
492 |
+
'to': keycombo,
|
493 |
+
'action_name': action_name
|
494 |
+
};
|
495 |
+
if (rebound) {
|
496 |
+
spec.from = find_rebinding(params.kse_rebinds[mode], spec).from;
|
497 |
+
}
|
498 |
+
return info;
|
499 |
+
}
|
500 |
+
|
501 |
+
function btn_del_callback (evt) {
|
502 |
+
evt.preventDefault(); // ignore #
|
503 |
+
|
504 |
+
var info = btn_get_info(evt.delegateTarget);
|
505 |
+
var spec = info.spec;
|
506 |
+
var rev_spec = reverse_spec(spec);
|
507 |
+
rebind(info.mode, rev_spec, true);
|
508 |
+
|
509 |
+
if (info.nubound) {
|
510 |
+
// don't want deleted new binds to show up in deleted shortcuts
|
511 |
+
deleted_shortcuts[info.mode].remove_shortcut(spec.to);
|
512 |
+
deregister_rebinding(info.mode, spec);
|
513 |
+
}
|
514 |
+
else if (info.rebound) {
|
515 |
+
// get rid of existing rebinding
|
516 |
+
deregister_rebinding(info.mode, spec);
|
517 |
+
// add a new rebinding for the deletion
|
518 |
+
delete spec.to;
|
519 |
+
rebind(info.mode, spec, true);
|
520 |
+
register_rebinding(info.mode, spec);
|
521 |
+
}
|
522 |
+
else {
|
523 |
+
register_rebinding(info.mode, rev_spec);
|
524 |
+
}
|
525 |
+
quickhelp_rebuild_mode_div(info.div);
|
526 |
+
}
|
527 |
+
|
528 |
+
function btn_rst_callback (evt) {
|
529 |
+
evt.preventDefault(); // ignore #
|
530 |
+
|
531 |
+
var info = btn_get_info(evt.delegateTarget);
|
532 |
+
var spec = info.spec;
|
533 |
+
if (info.unbound) {
|
534 |
+
spec = reverse_spec(spec);
|
535 |
+
deleted_shortcuts[info.mode].remove_shortcut(spec.from);
|
536 |
+
}
|
537 |
+
rebind(info.mode, reverse_spec(spec), true);
|
538 |
+
deregister_rebinding(info.mode, spec);
|
539 |
+
|
540 |
+
quickhelp_rebuild_mode_div(info.div);
|
541 |
+
}
|
542 |
+
|
543 |
+
function btn_edt_callback (evt) {
|
544 |
+
evt.preventDefault(); // ignore #
|
545 |
+
|
546 |
+
var info = btn_get_info(evt.delegateTarget);
|
547 |
+
var spec = reverse_spec(info.spec);
|
548 |
+
// see if the shortcut was already rebound...
|
549 |
+
var rebinds = params.kse_rebinds[info.mode];
|
550 |
+
for (var ii = 0; ii < rebinds.length; ii++) {
|
551 |
+
if (rebinds[ii].to === spec.from) {
|
552 |
+
spec = rebinds[ii];
|
553 |
+
break;
|
554 |
+
}
|
555 |
+
}
|
556 |
+
|
557 |
+
var editor = kse_comp.editor_build();
|
558 |
+
var modal = kse_comp.modal_build(editor, modal_options_for_edit);
|
559 |
+
|
560 |
+
modal_prepare_editor(modal, editor, info);
|
561 |
+
modal_show_above_quickhelp_modal(modal);
|
562 |
+
}
|
563 |
+
|
564 |
+
function btn_add_callback (evt) {
|
565 |
+
evt.preventDefault(); // don't use #
|
566 |
+
|
567 |
+
var div = $(evt.delegateTarget).closest('.kse-div');
|
568 |
+
var mode = div.data('kse_mode');
|
569 |
+
var info = {
|
570 |
+
'div': div,
|
571 |
+
'spec': {},
|
572 |
+
'shortcuts': get_mode_shortcuts(mode),
|
573 |
+
'keycombo': '',
|
574 |
+
'action_name': '',
|
575 |
+
'mode': mode
|
576 |
+
};
|
577 |
+
|
578 |
+
var editor = kse_comp.editor_build();
|
579 |
+
var modal = kse_comp.modal_build(editor, modal_options_for_edit);
|
580 |
+
|
581 |
+
modal_prepare_editor(modal, editor, info);
|
582 |
+
modal_show_above_quickhelp_modal(modal, editor, info);
|
583 |
+
}
|
584 |
+
|
585 |
+
function btn_view_callback (evt) {
|
586 |
+
evt.preventDefault(); // don't use #
|
587 |
+
|
588 |
+
var div = $(evt.delegateTarget).closest('.kse-div');
|
589 |
+
var mode = div.data('kse_mode');
|
590 |
+
var modal = dialog.modal({
|
591 |
+
backdrop: false, // a custom one gets added by modal_show_above_quickhelp_modal
|
592 |
+
show: false,
|
593 |
+
title : mode.substring(0, 1).toUpperCase() + mode.substring(1) + '-mode keyboard shortcut edits',
|
594 |
+
body : build_rebind_rep_list(mode),
|
595 |
+
buttons: {'OK': {}},
|
596 |
+
notebook: Jupyter.notebook,
|
597 |
+
keyboard_manager: Jupyter.keyboard_manager
|
598 |
+
});
|
599 |
+
|
600 |
+
modal
|
601 |
+
.addClass('modal_stretch')
|
602 |
+
.attr('id', 'kse-view-modal');
|
603 |
+
|
604 |
+
// Add a data-target attribute to ensure buttons only target this modal
|
605 |
+
modal.find('.close,.modal-footer button')
|
606 |
+
.attr('data-target', '#kse-view-modal');
|
607 |
+
modal_show_above_quickhelp_modal(modal);
|
608 |
+
}
|
609 |
+
|
610 |
+
function build_button_menu (idx, qh_div) {
|
611 |
+
qh_div = $(qh_div);
|
612 |
+
|
613 |
+
var grp = $('<div/>')
|
614 |
+
.addClass('btn-group btn-group-xs')
|
615 |
+
.addClass('kse-dropdown')
|
616 |
+
.addClass('hidden-print')
|
617 |
+
.appendTo(qh_div);
|
618 |
+
|
619 |
+
var btn = $('<button/>')
|
620 |
+
.addClass('btn btn-default')
|
621 |
+
.attr('type', 'button')
|
622 |
+
.appendTo(grp);
|
623 |
+
|
624 |
+
if (qh_div.hasClass('kse-codemirror')) {
|
625 |
+
btn
|
626 |
+
.addClass('disabled')
|
627 |
+
.attr('title', 'Editing Codemirror shortcuts is not supported')
|
628 |
+
.html('<i class="fa">cm</i>');
|
629 |
+
}
|
630 |
+
else if (qh_div.hasClass('kse-unbound')) {
|
631 |
+
btn
|
632 |
+
.on('click', btn_rst_callback)
|
633 |
+
.attr('title', 'Re-enable shortcut')
|
634 |
+
.html('<i class="fa fa-repeat"/>');
|
635 |
+
}
|
636 |
+
else if (qh_div.hasClass('kse-nubound')) {
|
637 |
+
btn
|
638 |
+
.on('click', btn_del_callback)
|
639 |
+
.attr('title', 'Delete custom shortcut')
|
640 |
+
.html('<i class="fa fa-trash"/>');
|
641 |
+
}
|
642 |
+
else {
|
643 |
+
btn
|
644 |
+
.attr({
|
645 |
+
'title': 'Edit',
|
646 |
+
'data-toggle': 'dropdown',
|
647 |
+
'aria-haspopup': 'true',
|
648 |
+
'aria-expanded': 'false'
|
649 |
+
})
|
650 |
+
.addClass('dropdown-toggle')
|
651 |
+
.html('<i class="fa fa-pencil"/> <i class="fa fa-caret-down"/>');
|
652 |
+
|
653 |
+
var mnu = $('<ul/>')
|
654 |
+
.addClass('dropdown-menu dropdown-menu-right')
|
655 |
+
.appendTo(grp);
|
656 |
+
$('<li/>')
|
657 |
+
.html('<a href="#" title="Edit shortcut"><i class="fa fa-pencil"></i> Edit</a>')
|
658 |
+
.on('click', btn_edt_callback)
|
659 |
+
.appendTo(mnu);
|
660 |
+
if (qh_div.hasClass('kse-rebound')) {
|
661 |
+
$('<li/>')
|
662 |
+
.on('click', btn_rst_callback)
|
663 |
+
.html('<a href="#" title="Reset shortcut to default key(s)"><i class="fa fa-repeat"></i> Reset</a>')
|
664 |
+
.appendTo(mnu);
|
665 |
+
}
|
666 |
+
$('<li/>')
|
667 |
+
.on('click', btn_del_callback)
|
668 |
+
.html('<a href="#" title="Disable shortcut"><i class="fa fa-ban"></i> Disable</a>')
|
669 |
+
.appendTo(mnu);
|
670 |
+
}
|
671 |
+
|
672 |
+
return grp;
|
673 |
+
}
|
674 |
+
|
675 |
+
function quickhelp_div_add_rebind_controls (div, mode) {
|
676 |
+
if (!params.kse_show_rebinds) {
|
677 |
+
return div;
|
678 |
+
}
|
679 |
+
|
680 |
+
div
|
681 |
+
.data('kse_mode', mode)
|
682 |
+
.addClass('kse-div');
|
683 |
+
|
684 |
+
var nubound_shortcuts = [];
|
685 |
+
var rebound_shortcuts = [];
|
686 |
+
for (var ii = 0; ii < params.kse_rebinds[mode].length; ii++) {
|
687 |
+
var spec = params.kse_rebinds[mode][ii];
|
688 |
+
if (spec.to) {
|
689 |
+
(spec.from ? rebound_shortcuts : nubound_shortcuts).push(spec.to);
|
690 |
+
}
|
691 |
+
}
|
692 |
+
|
693 |
+
var shortcuts = get_mode_shortcuts(mode);
|
694 |
+
var shortcut_help_arr = shortcuts.help();
|
695 |
+
// add codemirror shortcuts in edit mode
|
696 |
+
if (mode === 'edit') {
|
697 |
+
shortcut_help_arr = $.merge($.merge([], quickhelp.cm_shortcuts), shortcut_help_arr);
|
698 |
+
}
|
699 |
+
// Remove jupyter-notebook:ignore shortcuts.
|
700 |
+
shortcut_help_arr = shortcut_help_arr.filter(function(shortcut) {
|
701 |
+
return (shortcut.help !== 'ignore');
|
702 |
+
});
|
703 |
+
|
704 |
+
// label quickhelp divs with classes
|
705 |
+
div.find('.quickhelp').each(function (idx, elem) {
|
706 |
+
var keycombo = shortcut_help_arr[idx].shortcut;
|
707 |
+
var action_name = shortcuts.get_shortcut(keycombo);
|
708 |
+
if (mode === 'edit' && action_name === undefined) {
|
709 |
+
$(elem).addClass('kse-codemirror');
|
710 |
+
}
|
711 |
+
else if (nubound_shortcuts.indexOf(keycombo) >= 0) {
|
712 |
+
$(elem).addClass('kse-nubound');
|
713 |
+
}
|
714 |
+
else if (rebound_shortcuts.indexOf(keycombo) >= 0) {
|
715 |
+
$(elem).addClass('kse-rebound');
|
716 |
+
}
|
717 |
+
});
|
718 |
+
|
719 |
+
// (maybe) add a set of rebinds and deleted shortcuts
|
720 |
+
div.find('.kse-rep-list').remove();
|
721 |
+
var cont = div.find('.container-fluid:first');
|
722 |
+
|
723 |
+
var del_div = quickhelp.build_div('<h5>Disabled:<h5/>', deleted_shortcuts[mode].help());
|
724 |
+
del_div
|
725 |
+
.addClass('hidden-print')
|
726 |
+
.addClass('text-danger hidden-print');
|
727 |
+
if (del_div.find('.quickhelp').addClass('kse-unbound').length > 0) {
|
728 |
+
del_div
|
729 |
+
.insertAfter(cont);
|
730 |
+
}
|
731 |
+
|
732 |
+
// add button menus
|
733 |
+
div.find('.quickhelp').each(build_button_menu);
|
734 |
+
|
735 |
+
var link_new = $('<a/>')
|
736 |
+
.attr('href', '#')
|
737 |
+
.on('click', btn_add_callback);
|
738 |
+
|
739 |
+
$('<span/>')
|
740 |
+
.addClass('shortcut_key')
|
741 |
+
.html('<i class="fa fa-plus"></i>')
|
742 |
+
.appendTo(link_new);
|
743 |
+
|
744 |
+
$('<span/>')
|
745 |
+
.addClass('shortcut_descr')
|
746 |
+
.text(': Add a new ' + mode + '-mode shortcut')
|
747 |
+
.appendTo(link_new);
|
748 |
+
|
749 |
+
$('<div/>')
|
750 |
+
.addClass('col-xs-12 hidden-print quickhelp kse-links')
|
751 |
+
.append(link_new)
|
752 |
+
.appendTo(cont);
|
753 |
+
|
754 |
+
// add the view-rebinds and add-a-new links
|
755 |
+
if (params.kse_rebinds[mode].length > 0) {
|
756 |
+
var link_view = link_new.clone()
|
757 |
+
.off('click')
|
758 |
+
.on('click', btn_view_callback)
|
759 |
+
.appendTo(cont);
|
760 |
+
link_view.find('.shortcut_key')
|
761 |
+
.html('<i class="fa fa-eye"></i>');
|
762 |
+
link_view.find('.shortcut_descr')
|
763 |
+
.text(': View active ' + mode + '-mode shortcut edits');
|
764 |
+
|
765 |
+
$('<div/>')
|
766 |
+
.addClass('col-xs-12 hidden-print quickhelp kse-links')
|
767 |
+
.append(link_view)
|
768 |
+
.appendTo(cont);
|
769 |
+
}
|
770 |
+
|
771 |
+
return div;
|
772 |
+
}
|
773 |
+
|
774 |
+
return {
|
775 |
+
'load_jupyter_extension': load_jupyter_extension,
|
776 |
+
'load_ipython_extension': load_jupyter_extension
|
777 |
+
};
|
778 |
+
});
|
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/quickhelp_shim.js
ADDED
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
define([
|
2 |
+
'underscore',
|
3 |
+
'jquery',
|
4 |
+
'base/js/utils',
|
5 |
+
'notebook/js/quickhelp',
|
6 |
+
'codemirror/lib/codemirror'
|
7 |
+
], function(
|
8 |
+
_,
|
9 |
+
$,
|
10 |
+
utils,
|
11 |
+
quickhelp,
|
12 |
+
CodeMirror
|
13 |
+
){
|
14 |
+
"use strict";
|
15 |
+
// This is essentially a duplicate of the quickhelp module, used to
|
16 |
+
// patch the existing quickhelp with definitions which aren't exported.
|
17 |
+
|
18 |
+
var platform = utils.platform;
|
19 |
+
|
20 |
+
var cmd_ctrl = 'Ctrl-';
|
21 |
+
var platform_specific;
|
22 |
+
|
23 |
+
if (platform === 'MacOS') {
|
24 |
+
// Mac OS X specific
|
25 |
+
cmd_ctrl = 'Cmd-';
|
26 |
+
platform_specific = [
|
27 |
+
{ shortcut: "Cmd-Up", help:"go to cell start" },
|
28 |
+
{ shortcut: "Cmd-Down", help:"go to cell end" },
|
29 |
+
{ shortcut: "Alt-Left", help:"go one word left" },
|
30 |
+
{ shortcut: "Alt-Right", help:"go one word right" },
|
31 |
+
{ shortcut: "Alt-Backspace", help:"delete word before" },
|
32 |
+
{ shortcut: "Alt-Delete", help:"delete word after" },
|
33 |
+
];
|
34 |
+
} else {
|
35 |
+
// PC specific
|
36 |
+
platform_specific = [
|
37 |
+
{ shortcut: "Ctrl-Home", help:"go to cell start" },
|
38 |
+
{ shortcut: "Ctrl-Up", help:"go to cell start" },
|
39 |
+
{ shortcut: "Ctrl-End", help:"go to cell end" },
|
40 |
+
{ shortcut: "Ctrl-Down", help:"go to cell end" },
|
41 |
+
{ shortcut: "Ctrl-Left", help:"go one word left" },
|
42 |
+
{ shortcut: "Ctrl-Right", help:"go one word right" },
|
43 |
+
{ shortcut: "Ctrl-Backspace", help:"delete word before" },
|
44 |
+
{ shortcut: "Ctrl-Delete", help:"delete word after" },
|
45 |
+
];
|
46 |
+
}
|
47 |
+
|
48 |
+
var cm_shortcuts = [
|
49 |
+
{ shortcut:"Tab", help:"code completion or indent" },
|
50 |
+
{ shortcut:"Shift-Tab", help:"tooltip" },
|
51 |
+
{ shortcut: cmd_ctrl + "]", help:"indent" },
|
52 |
+
{ shortcut: cmd_ctrl + "[", help:"dedent" },
|
53 |
+
{ shortcut: cmd_ctrl + "a", help:"select all" },
|
54 |
+
{ shortcut: cmd_ctrl + "z", help:"undo" },
|
55 |
+
{ shortcut: cmd_ctrl + "Shift-z", help:"redo" },
|
56 |
+
{ shortcut: cmd_ctrl + "y", help:"redo" },
|
57 |
+
].concat( platform_specific );
|
58 |
+
|
59 |
+
var mac_humanize_map = {
|
60 |
+
// all these are unicode, will probably display badly on anything except macs.
|
61 |
+
// these are the standard symbol that are used in MacOS native menus
|
62 |
+
// cf http://apple.stackexchange.com/questions/55727/
|
63 |
+
// for htmlentities and/or unicode value
|
64 |
+
'cmd':'⌘',
|
65 |
+
'shift':'⇧',
|
66 |
+
'alt':'⌥',
|
67 |
+
'up':'↑',
|
68 |
+
'down':'↓',
|
69 |
+
'left':'←',
|
70 |
+
'right':'→',
|
71 |
+
'eject':'⏏',
|
72 |
+
'tab':'⇥',
|
73 |
+
'backtab':'⇤',
|
74 |
+
'capslock':'⇪',
|
75 |
+
'esc':'esc',
|
76 |
+
'ctrl':'⌃',
|
77 |
+
'enter':'↩',
|
78 |
+
'pageup':'⇞',
|
79 |
+
'pagedown':'⇟',
|
80 |
+
'home':'↖',
|
81 |
+
'end':'↘',
|
82 |
+
'altenter':'⌤',
|
83 |
+
'space':'␣',
|
84 |
+
'delete':'⌦',
|
85 |
+
'backspace':'⌫',
|
86 |
+
'apple':'',
|
87 |
+
};
|
88 |
+
|
89 |
+
var default_humanize_map = {
|
90 |
+
'shift':'Shift',
|
91 |
+
'alt':'Alt',
|
92 |
+
'up':'Up',
|
93 |
+
'down':'Down',
|
94 |
+
'left':'Left',
|
95 |
+
'right':'Right',
|
96 |
+
'tab':'Tab',
|
97 |
+
'capslock':'Caps Lock',
|
98 |
+
'esc':'Esc',
|
99 |
+
'ctrl':'Ctrl',
|
100 |
+
'enter':'Enter',
|
101 |
+
'pageup':'Page Up',
|
102 |
+
'pagedown':'Page Down',
|
103 |
+
'home':'Home',
|
104 |
+
'end':'End',
|
105 |
+
'space':'Space',
|
106 |
+
'backspace':'Backspace',
|
107 |
+
};
|
108 |
+
|
109 |
+
var humanize_map;
|
110 |
+
|
111 |
+
if (platform === 'MacOS'){
|
112 |
+
humanize_map = mac_humanize_map;
|
113 |
+
} else {
|
114 |
+
humanize_map = default_humanize_map;
|
115 |
+
}
|
116 |
+
|
117 |
+
var special_case = { pageup: "PageUp", pagedown: "Page Down", 'minus': '-' };
|
118 |
+
|
119 |
+
function humanize_key(key){
|
120 |
+
if (key.length === 1){
|
121 |
+
return key.toUpperCase();
|
122 |
+
}
|
123 |
+
|
124 |
+
key = humanize_map[key.toLowerCase()]||key;
|
125 |
+
|
126 |
+
if (key.indexOf(',') === -1){
|
127 |
+
return ( special_case[key] ? special_case[key] : key.charAt(0).toUpperCase() + key.slice(1) );
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
// return an **html** string of the keyboard shortcut
|
132 |
+
// for human eyes consumption.
|
133 |
+
// the sequence is a string, comma sepparated linkt of shortcut,
|
134 |
+
// where the shortcut is a list of dash-joined keys.
|
135 |
+
// Each shortcut will be wrapped in <kbd> tag, and joined by comma is in a
|
136 |
+
// sequence.
|
137 |
+
//
|
138 |
+
// Depending on the platform each shortcut will be normalized, with or without dashes.
|
139 |
+
// and replace with the corresponding unicode symbol for modifier if necessary.
|
140 |
+
function humanize_sequence(sequence){
|
141 |
+
var joinchar = ',';
|
142 |
+
var hum = _.map(sequence.replace(/meta/g, 'cmd').split(','), humanize_shortcut).join(joinchar);
|
143 |
+
return hum;
|
144 |
+
}
|
145 |
+
|
146 |
+
function humanize_shortcut(shortcut){
|
147 |
+
var joinchar = '-';
|
148 |
+
if (platform === 'MacOS'){
|
149 |
+
joinchar = '';
|
150 |
+
}
|
151 |
+
var sh = _.map(shortcut.split('-'), humanize_key ).join(joinchar);
|
152 |
+
return '<kbd>'+sh+'</kbd>';
|
153 |
+
}
|
154 |
+
|
155 |
+
var build_one = function (s) {
|
156 |
+
var help = s.help;
|
157 |
+
var shortcut = '';
|
158 |
+
if(s.shortcut){
|
159 |
+
shortcut = humanize_sequence(s.shortcut);
|
160 |
+
}
|
161 |
+
return $('<div>').addClass('quickhelp').
|
162 |
+
append($('<span/>').addClass('shortcut_key').append($(shortcut))).
|
163 |
+
append($('<span/>').addClass('shortcut_descr').text(' : ' + help));
|
164 |
+
|
165 |
+
};
|
166 |
+
|
167 |
+
var build_div = function (title, shortcuts) {
|
168 |
+
|
169 |
+
// Remove jupyter-notebook:ignore shortcuts.
|
170 |
+
shortcuts = shortcuts.filter(function(shortcut) {
|
171 |
+
if (shortcut.help === 'ignore') {
|
172 |
+
return false;
|
173 |
+
} else {
|
174 |
+
return true;
|
175 |
+
}
|
176 |
+
});
|
177 |
+
|
178 |
+
var i, half, n;
|
179 |
+
var div = $('<div/>').append($(title));
|
180 |
+
var sub_div = $('<div/>').addClass('container-fluid');
|
181 |
+
var col1 = $('<div/>').addClass('col-md-6');
|
182 |
+
var col2 = $('<div/>').addClass('col-md-6');
|
183 |
+
n = shortcuts.length;
|
184 |
+
half = ~~(n/2); // Truncate :)
|
185 |
+
for (i=0; i<half; i++) { col1.append( build_one(shortcuts[i]) ); }
|
186 |
+
for (i=half; i<n; i++) { col2.append( build_one(shortcuts[i]) ); }
|
187 |
+
sub_div.append(col1).append(col2);
|
188 |
+
div.append(sub_div);
|
189 |
+
return div;
|
190 |
+
};
|
191 |
+
|
192 |
+
var quickhelp_shiv = {
|
193 |
+
cmd_ctrl : cmd_ctrl,
|
194 |
+
platform_specific : platform_specific,
|
195 |
+
cm_shortcuts : cm_shortcuts,
|
196 |
+
mac_humanize_map : mac_humanize_map,
|
197 |
+
default_humanize_map : default_humanize_map,
|
198 |
+
humanize_map : humanize_map,
|
199 |
+
special_case : special_case,
|
200 |
+
humanize_key : humanize_key,
|
201 |
+
humanize_sequence : humanize_sequence,
|
202 |
+
humanize_shortcut : humanize_shortcut,
|
203 |
+
build_one : build_one,
|
204 |
+
build_div : build_div
|
205 |
+
};
|
206 |
+
_.defaults(quickhelp, quickhelp_shiv);
|
207 |
+
});
|
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_add_new_select_action.png
ADDED
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_comma.png
ADDED
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_conflict.png
ADDED
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_dropdown.png
ADDED
.local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_shortcut_editor_success.png
ADDED
.local/share/jupyter/nbextensions/limit_output/icon.png
ADDED
.local/share/jupyter/nbextensions/limit_output/limit-output.yaml
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Type: IPython Notebook Extension
|
2 |
+
Name: Limit Output
|
3 |
+
Description: This extension limits the number of characters that can be printed below a codecell
|
4 |
+
Link: readme.md
|
5 |
+
Icon: icon.png
|
6 |
+
Main: main.js
|
7 |
+
Compatibility: 4.x, 5.x
|
8 |
+
Parameters:
|
9 |
+
- name: limit_output
|
10 |
+
description: Number of characters to limit output to
|
11 |
+
input_type: number
|
12 |
+
default: 10000
|
13 |
+
step: 1
|
14 |
+
min: 0
|
15 |
+
- name: limit_stream
|
16 |
+
description: Enable limiting stream messages
|
17 |
+
input_type: checkbox
|
18 |
+
default: true
|
19 |
+
- name: limit_execute_result
|
20 |
+
description: Enable limiting execute_result messages
|
21 |
+
input_type: checkbox
|
22 |
+
default: true
|
23 |
+
- name: limit_display_data
|
24 |
+
description: Enable limiting display_data messages
|
25 |
+
input_type: checkbox
|
26 |
+
default: false
|
27 |
+
- name: limit_output_message
|
28 |
+
description: Message to append when output is limited
|
29 |
+
input_type: text
|
30 |
+
default: '<b>limit_output extension: Maximum message size for {message_type} of {limit_output_length} exceeded with {output_length} characters</b>'
|
.local/share/jupyter/nbextensions/livemdpreview/livemdpreview.js
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
define([
|
2 |
+
'jquery',
|
3 |
+
'require',
|
4 |
+
'base/js/namespace',
|
5 |
+
'base/js/events',
|
6 |
+
'base/js/utils',
|
7 |
+
'notebook/js/cell',
|
8 |
+
'notebook/js/textcell',
|
9 |
+
'codemirror/lib/codemirror',
|
10 |
+
], function (
|
11 |
+
$,
|
12 |
+
requirejs,
|
13 |
+
Jupyter,
|
14 |
+
events,
|
15 |
+
utils,
|
16 |
+
cell_mod,
|
17 |
+
textcell,
|
18 |
+
CodeMirror
|
19 |
+
) {
|
20 |
+
"use strict";
|
21 |
+
|
22 |
+
var LiveMdPreviewer = function(options) {
|
23 |
+
options = $.extend(true, {}, this._default_options, options);
|
24 |
+
this.show_side_by_side = options.show_side_by_side;
|
25 |
+
this.timeout = Math.max(50, options.timeout);
|
26 |
+
|
27 |
+
this.addCSS();
|
28 |
+
var lmdp = this;
|
29 |
+
// Change any existing cells:
|
30 |
+
Jupyter.notebook.get_cells().forEach(function (cell) {
|
31 |
+
lmdp.registerCell(cell);
|
32 |
+
});
|
33 |
+
// Ensure we also apply to new cells:
|
34 |
+
events.on('create.Cell', function (evt, data) { lmdp.registerCell(data.cell); });
|
35 |
+
};
|
36 |
+
|
37 |
+
LiveMdPreviewer.prototype._default_options = {
|
38 |
+
show_side_by_side: false,
|
39 |
+
timeout : 500,
|
40 |
+
};
|
41 |
+
|
42 |
+
/**
|
43 |
+
* do work of rendering the markdown cell, without triggering the rendered
|
44 |
+
* event, or altering classes on elements
|
45 |
+
*/
|
46 |
+
var previewMdCell = function(cell) {
|
47 |
+
var cached_trigger = cell.events.trigger;
|
48 |
+
cell.events.trigger = function (eventType) {
|
49 |
+
if (eventType !== "rendered.MarkdownCell") {
|
50 |
+
return cached_trigger.apply(this, arguments);
|
51 |
+
}
|
52 |
+
return this;
|
53 |
+
};
|
54 |
+
|
55 |
+
var Cell = cell_mod.Cell;
|
56 |
+
var cached_render = Cell.prototype.render;
|
57 |
+
Cell.prototype.render = function () {
|
58 |
+
return true;
|
59 |
+
};
|
60 |
+
|
61 |
+
try {
|
62 |
+
cell.render();
|
63 |
+
}
|
64 |
+
finally {
|
65 |
+
cell.events.trigger = cached_trigger;
|
66 |
+
Cell.prototype.render = cached_render;
|
67 |
+
}
|
68 |
+
};
|
69 |
+
|
70 |
+
LiveMdPreviewer.prototype.registerCell = function(cell) {
|
71 |
+
if (!(cell instanceof textcell.TextCell)) {
|
72 |
+
return;
|
73 |
+
}
|
74 |
+
var timeout = this.timeout;
|
75 |
+
cell.code_mirror.on('changes', function onCodeMirrorChanges (cm, changes) {
|
76 |
+
if (!cm.state.livemdpreview) {
|
77 |
+
cm.state.livemdpreview = setTimeout(function () {
|
78 |
+
var cell = $(cm.getWrapperElement()).closest('.cell').data('cell');
|
79 |
+
previewMdCell(cell);
|
80 |
+
delete cm.state.livemdpreview;
|
81 |
+
}, timeout);
|
82 |
+
}
|
83 |
+
});
|
84 |
+
};
|
85 |
+
|
86 |
+
LiveMdPreviewer.prototype.addCSS = function () {
|
87 |
+
var styles_elem = $('#livemdpreviewstyles');
|
88 |
+
if (styles_elem.length < 1) {
|
89 |
+
styles_elem = $('<style id="livemdpreviewstyles">').appendTo('body');
|
90 |
+
}
|
91 |
+
var styles = [
|
92 |
+
// show rendered stuff even in "unrendered" cell
|
93 |
+
'.text_cell.unrendered .text_cell_render { display: block; }',
|
94 |
+
];
|
95 |
+
if (this.show_side_by_side) {
|
96 |
+
styles.push('.text_cell.unrendered .inner_cell { flex-direction: row !important; }');
|
97 |
+
styles.push('.text_cell.unrendered .input_area, .text_cell.unrendered .text_cell_render { width: 50%; }');
|
98 |
+
}
|
99 |
+
styles_elem.html(styles.join('\n'));
|
100 |
+
};
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Export things
|
104 |
+
*/
|
105 |
+
return {
|
106 |
+
load_ipython_extension : function () {
|
107 |
+
return Jupyter.notebook.config.loaded.then(function () {
|
108 |
+
return new LiveMdPreviewer(Jupyter.notebook.config.data.livemdpreview);
|
109 |
+
});
|
110 |
+
}
|
111 |
+
};
|
112 |
+
});
|
.local/share/jupyter/nbextensions/livemdpreview/livemdpreview.yml
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Type: Jupyter Notebook Extension
|
2 |
+
Compatibility: 4.x, 5.x
|
3 |
+
Name: Live Markdown Preview
|
4 |
+
Main: livemdpreview.js
|
5 |
+
Description: |
|
6 |
+
Live-preview the rendered output of markdown cells while editing their source.
|
7 |
+
Parameters:
|
8 |
+
|
9 |
+
- name: livemdpreview.show_side_by_side
|
10 |
+
description: |
|
11 |
+
Show the input & output of markdown cells side-by-side while editing them.
|
12 |
+
Otherwise, the output appears immediately below the input while editing
|
13 |
+
input_type: checkbox
|
14 |
+
default: false
|
15 |
+
|
16 |
+
- name: livemdpreview.timeout
|
17 |
+
description: |
|
18 |
+
Minimum time in ms between editing the markdown source & its output being
|
19 |
+
updated. This throttles the rate at which consecutive renderings will take
|
20 |
+
place.
|
21 |
+
input_type: number
|
22 |
+
default: 500
|
23 |
+
min: 10
|
24 |
+
step: 10
|
.local/share/jupyter/nbextensions/load_tex_macros/icon.png
ADDED
.local/share/jupyter/nbextensions/load_tex_macros/readme.md
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
Purpose
|
3 |
+
=======
|
4 |
+
This extension loads a tex file whenever a notebook is loaded, then re-runs
|
5 |
+
mathjax. It's useful if you have several notebooks that use a common set of latex
|
6 |
+
macros, so you don't have to copy the macros to each notebook.
|
7 |
+
|
8 |
+
Usage
|
9 |
+
=====
|
10 |
+
|
11 |
+
Simply put your latex macros in a file named latexdefs.tex, in the same directory as your notebook.
|
12 |
+
|
13 |
+
|
14 |
+
Credit
|
15 |
+
======
|
16 |
+
|
17 |
+
This is derived entirely from the nbextension `jupyter_latex_envs`, with help from its author @jfbercher.
|
.local/share/jupyter/nbextensions/move_selected_cells/main.js
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright (c) Jupyter-Contrib Team.
|
2 |
+
// Distributed under the terms of the Modified BSD License.
|
3 |
+
|
4 |
+
// This is a quick (and dirty) extension - move up or down several selected cells
|
5 |
+
// Dirty because it would be better to act on dom elements and write a correct
|
6 |
+
// move_cells() function.
|
7 |
+
// Updated to Jupyter 4.2+, taking advantage of
|
8 |
+
// `Jupyter.notebook.move_selection_{down, up}` new functions
|
9 |
+
//
|
10 |
+
// Keyboard shortcuts: Alt-up and Alt-down (works with single cells also -- this is useful!)
|
11 |
+
// Cells can be selected using the rubberband (needs rubberband extension) or via Shift-up/Shift-down or Shift-K/Shift-J
|
12 |
+
|
13 |
+
|
14 |
+
define([
|
15 |
+
'base/js/namespace',
|
16 |
+
'jquery',
|
17 |
+
'require',
|
18 |
+
'base/js/events'
|
19 |
+
], function(Jupyter, $, requirejs, events, rubberband) {
|
20 |
+
"use strict";
|
21 |
+
|
22 |
+
if (parseFloat(Jupyter.version.substr(0, 3)) >= 4.2) {
|
23 |
+
var add_cmd_shortcuts = {
|
24 |
+
'Alt-down': {
|
25 |
+
help: 'Move selected cells down',
|
26 |
+
help_index: 'ht',
|
27 |
+
handler: function() { Jupyter.notebook.move_selection_down() }
|
28 |
+
},
|
29 |
+
'Alt-up': {
|
30 |
+
help: 'Move selected cells up',
|
31 |
+
help_index: 'ht',
|
32 |
+
handler: function() { Jupyter.notebook.move_selection_up() }
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
} else { // Jupyter version < 4.2
|
37 |
+
var add_cmd_shortcuts = {
|
38 |
+
'Alt-down': {
|
39 |
+
help: 'Move selected cells down',
|
40 |
+
help_index: 'ht',
|
41 |
+
handler: function(event) {
|
42 |
+
var ncells = Jupyter.notebook.ncells();
|
43 |
+
var s = Jupyter.notebook.get_selected_indices();
|
44 |
+
//ensure cells indices are reverse sorted
|
45 |
+
var ss = s.sort(function(x, y) {
|
46 |
+
return x - y }).reverse();
|
47 |
+
if (ss[0] + 1 < ncells) {
|
48 |
+
for (var k in ss) {
|
49 |
+
Jupyter.notebook.move_cell_down(ss[k]);
|
50 |
+
}; //The second loop is needed because move_cell deselect
|
51 |
+
for (var k in ss) {
|
52 |
+
Jupyter.notebook.get_cell(ss[k] + 1).select();
|
53 |
+
}
|
54 |
+
}
|
55 |
+
}
|
56 |
+
},
|
57 |
+
'Alt-up': {
|
58 |
+
help: 'Move selected cells up',
|
59 |
+
help_index: 'ht',
|
60 |
+
handler: function(event) {
|
61 |
+
var s = Jupyter.notebook.get_selected_indices();
|
62 |
+
//ensure cells indices are sorted
|
63 |
+
var ss = s.sort(function(x, y) {
|
64 |
+
return x - y });
|
65 |
+
if (ss[0] - 1 >= 0) {
|
66 |
+
for (var k in ss) {
|
67 |
+
Jupyter.notebook.move_cell_up(ss[k]);
|
68 |
+
};
|
69 |
+
for (var k in ss) {
|
70 |
+
Jupyter.notebook.get_cell(ss[k] - 1).select();
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
74 |
+
}
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
function load_ipython_extension() {
|
79 |
+
Jupyter.keyboard_manager.command_shortcuts.add_shortcuts(add_cmd_shortcuts);
|
80 |
+
console.log("[move_selected_cells] loaded")
|
81 |
+
}
|
82 |
+
|
83 |
+
return {
|
84 |
+
load_ipython_extension: load_ipython_extension,
|
85 |
+
};
|
86 |
+
|
87 |
+
});
|
.local/share/jupyter/nbextensions/navigation-hotkeys/hotkeys.yaml
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Type: IPython Notebook Extension
|
2 |
+
Name: Navigation-Hotkeys
|
3 |
+
Description: Additional hotkeys for easier navigation in the notebook
|
4 |
+
Link: readme.md
|
5 |
+
Icon: icon.png
|
6 |
+
Main: main.js
|
7 |
+
Compatibility: 4.x, 5.x
|
8 |
+
Parameters:
|
9 |
+
- name: toggle_enable_edit_shortcuts
|
10 |
+
description: Enable all edit shortcuts
|
11 |
+
input_type: checkbox
|
12 |
+
default: true
|
13 |
+
- name: toggle_enable_command_shortcuts
|
14 |
+
description: Enable all command shortcuts
|
15 |
+
input_type: checkbox
|
16 |
+
default: true
|
17 |
+
- name: toggle_enable_esc_shortcut
|
18 |
+
description: Enable Esc to enter Edit mode (so Esc toggles Edit/Command mode)
|
19 |
+
input_type: checkbox
|
20 |
+
default: true
|
21 |
+
- name: toggle_enable_enter_shortcuts
|
22 |
+
description: Enable Enter keys to remain in Edit mode when currently in Edit mode
|
23 |
+
input_type: checkbox
|
24 |
+
default: true
|
25 |
+
|
.local/share/jupyter/nbextensions/nbTranslate/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# nbTranslate -- helps translate notebooks -- provides multilanguage support
|
2 |
+
|
3 |
+
This extension
|
4 |
+
|
5 |
+
- helps convert markdown cells in a notebook from one language to another (optionally using **Google translate**),
|
6 |
+
- enables one to selectively display cells from a given language in a multilanguage notebook.
|
7 |
+
|
8 |
+
This extension allows one to copy the original cell into a new one for editing and translating. Optionally, the cell source text can be piped through `google translate` and the result inserted into a new cell. Basic markdown structures (e.g. bold, italics, lists) are preserved/restored after conversion, though this is not perfect (usually one has to correct the text and structures afterwards). Similarly, equations are extracted before conversion and restored in the result. It seems that when translating from one language to another language, the best results are obtained by using English as an intermediate language.
|
9 |
+
|
10 |
+
Metadata indicating the language used is added to each cell. This allows one to selectively display cells for a particular language and hide the other ones. Code cells remain untouched. This way, one can get a kind of multilanguage notebook. A menu is provided to select the languages to display in the notebook.
|
11 |
+
|
12 |
+
|
13 |
+
![](demo1.gif)
|
14 |
+
|
15 |
+
![](demo2.gif)
|
16 |
+
|
17 |
+
|
18 |
+
## Compatibility
|
19 |
+
|
20 |
+
The extension has been written to play nicely with
|
21 |
+
- [latex_envs]: LaTeX environments are protected before conversion and restored after. For environments with text content, e.g. theorem, remark, etc, the content is still translated. Some minor updates have been applied to `latex_envs` to ensure the best compatibilty; update if necessary via
|
22 |
+
```
|
23 |
+
pip install jupyter_latex_envs --upgrade [--user|sys-prefix]
|
24 |
+
jupyter nbextension install --py latex_envs --user
|
25 |
+
jupyter nbextension enable latex_envs --user --py
|
26 |
+
```
|
27 |
+
- [toc2]: cells of non displayed languages are hidden and not rendered so that the toc corresponds only to the selected languages. The toc is automatically updated each time a language is added or removed.
|
28 |
+
|
29 |
+
## Configuration
|
30 |
+
- Parameter values can be changed using the `nbextensions-configurator`: it is possible to choose the initial source and target language, to choose to use the google translate engine or not, and to specify the initially displayed languages, the position of the language selection menu, and a keyboard shortcut definition.
|
31 |
+
- A *configuration toolbar* is provided which allows changing the main options per notebook. One can also toggle whether to use the google translate engine, select the source and target languages, and select the language to display.
|
32 |
+
|
33 |
+
## Export
|
34 |
+
It is possible to extract one language from the multilanguage notebook. An exporter with an entry-point `selectLanguage` is provided that converts the notebook into another one as follows:
|
35 |
+
```
|
36 |
+
jupyter nbconvert --to selectLanguage --NotebookLangExporter.language=lang FILE.ipynb
|
37 |
+
```
|
38 |
+
where the `lang` parameter denotes a valid language abbreviation e.g. en, fr, ar, sp. See the full list <a href='languages.js'> here.</a>
|
39 |
+
|
40 |
+
|
41 |
+
Installation
|
42 |
+
------------
|
43 |
+
|
44 |
+
If you use [jupyter-contrib-nbextensions](https://github.com/ipython-contrib/jupyter_contrib_nbextensions), the extension is provided within the `Nbextensions` configuration.
|
45 |
+
|
46 |
+
Otherwise, you can still install the extension from my personal repo, using:
|
47 |
+
```
|
48 |
+
jupyter nbextension install https://rawgit.com/jfbercher/jupyter_nbTranslate/master/nbTranslate.zip --user
|
49 |
+
jupyter nbextension enable nbTranslate/main
|
50 |
+
```
|
51 |
+
_Note: Until further notice, installing from this repo does not install the python module and add the entry points for exporting as described above._
|
52 |
+
|
53 |
+
To uninstall:
|
54 |
+
```
|
55 |
+
jupyter nbextension uninstall nbTranslate/main
|
56 |
+
```
|
.local/share/jupyter/nbextensions/nbTranslate/nbTranslate.js
ADDED
@@ -0,0 +1,622 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright (c) Jupyter-Contrib Team.
|
2 |
+
// Distributed under the terms of the Modified BSD License.
|
3 |
+
// Author: Jean-François Bercher
|
4 |
+
|
5 |
+
|
6 |
+
//var config_toolbar_present = false;
|
7 |
+
var listOfLangsInNotebook = [];
|
8 |
+
var log_prefix = '[nbTranslate] ';
|
9 |
+
var nbTranslate_toolbarNotYetDisplayed = true;
|
10 |
+
|
11 |
+
var langs = {
|
12 |
+
'auto': 'Automatic',
|
13 |
+
'af': 'Afrikaans',
|
14 |
+
'sq': 'Albanian',
|
15 |
+
'ar': 'Arabic',
|
16 |
+
'hy': 'Armenian',
|
17 |
+
'az': 'Azerbaijani',
|
18 |
+
'eu': 'Basque',
|
19 |
+
'be': 'Belarusian',
|
20 |
+
'bn': 'Bengali',
|
21 |
+
'bs': 'Bosnian',
|
22 |
+
'bg': 'Bulgarian',
|
23 |
+
'ca': 'Catalan',
|
24 |
+
'ceb': 'Cebuano',
|
25 |
+
'ny': 'Chichewa',
|
26 |
+
'zh-cn': 'Chinese Simplified',
|
27 |
+
'zh-tw': 'Chinese Traditional',
|
28 |
+
'co': 'Corsican',
|
29 |
+
'hr': 'Croatian',
|
30 |
+
'cs': 'Czech',
|
31 |
+
'da': 'Danish',
|
32 |
+
'nl': 'Dutch',
|
33 |
+
'en': 'English',
|
34 |
+
'eo': 'Esperanto',
|
35 |
+
'et': 'Estonian',
|
36 |
+
'tl': 'Filipino',
|
37 |
+
'fi': 'Finnish',
|
38 |
+
'fr': 'French',
|
39 |
+
'fy': 'Frisian',
|
40 |
+
'gl': 'Galician',
|
41 |
+
'ka': 'Georgian',
|
42 |
+
'de': 'German',
|
43 |
+
'el': 'Greek',
|
44 |
+
'gu': 'Gujarati',
|
45 |
+
'ht': 'Haitian Creole',
|
46 |
+
'ha': 'Hausa',
|
47 |
+
'haw': 'Hawaiian',
|
48 |
+
'iw': 'Hebrew',
|
49 |
+
'hi': 'Hindi',
|
50 |
+
'hmn': 'Hmong',
|
51 |
+
'hu': 'Hungarian',
|
52 |
+
'is': 'Icelandic',
|
53 |
+
'ig': 'Igbo',
|
54 |
+
'id': 'Indonesian',
|
55 |
+
'ga': 'Irish',
|
56 |
+
'it': 'Italian',
|
57 |
+
'ja': 'Japanese',
|
58 |
+
'jw': 'Javanese',
|
59 |
+
'kn': 'Kannada',
|
60 |
+
'kk': 'Kazakh',
|
61 |
+
'km': 'Khmer',
|
62 |
+
'ko': 'Korean',
|
63 |
+
'ku': 'Kurdish (Kurmanji)',
|
64 |
+
'ky': 'Kyrgyz',
|
65 |
+
'lo': 'Lao',
|
66 |
+
'la': 'Latin',
|
67 |
+
'lv': 'Latvian',
|
68 |
+
'lt': 'Lithuanian',
|
69 |
+
'lb': 'Luxembourgish',
|
70 |
+
'mk': 'Macedonian',
|
71 |
+
'mg': 'Malagasy',
|
72 |
+
'ms': 'Malay',
|
73 |
+
'ml': 'Malayalam',
|
74 |
+
'mt': 'Maltese',
|
75 |
+
'mi': 'Maori',
|
76 |
+
'mr': 'Marathi',
|
77 |
+
'mn': 'Mongolian',
|
78 |
+
'my': 'Myanmar (Burmese)',
|
79 |
+
'ne': 'Nepali',
|
80 |
+
'no': 'Norwegian',
|
81 |
+
'ps': 'Pashto',
|
82 |
+
'fa': 'Persian',
|
83 |
+
'pl': 'Polish',
|
84 |
+
'pt': 'Portuguese',
|
85 |
+
'ma': 'Punjabi',
|
86 |
+
'ro': 'Romanian',
|
87 |
+
'ru': 'Russian',
|
88 |
+
'sm': 'Samoan',
|
89 |
+
'gd': 'Scots Gaelic',
|
90 |
+
'sr': 'Serbian',
|
91 |
+
'st': 'Sesotho',
|
92 |
+
'sn': 'Shona',
|
93 |
+
'sd': 'Sindhi',
|
94 |
+
'si': 'Sinhala',
|
95 |
+
'sk': 'Slovak',
|
96 |
+
'sl': 'Slovenian',
|
97 |
+
'so': 'Somali',
|
98 |
+
'es': 'Spanish',
|
99 |
+
'su': 'Sudanese',
|
100 |
+
'sw': 'Swahili',
|
101 |
+
'sv': 'Swedish',
|
102 |
+
'tg': 'Tajik',
|
103 |
+
'ta': 'Tamil',
|
104 |
+
'te': 'Telugu',
|
105 |
+
'th': 'Thai',
|
106 |
+
'tr': 'Turkish',
|
107 |
+
'uk': 'Ukrainian',
|
108 |
+
'ur': 'Urdu',
|
109 |
+
'uz': 'Uzbek',
|
110 |
+
'vi': 'Vietnamese',
|
111 |
+
'cy': 'Welsh',
|
112 |
+
'xh': 'Xhosa',
|
113 |
+
'yi': 'Yiddish',
|
114 |
+
'yo': 'Yoruba',
|
115 |
+
'zu': 'Zulu'
|
116 |
+
};
|
117 |
+
|
118 |
+
// test if array contains an element
|
119 |
+
function inArray(array, element){
|
120 |
+
return array.indexOf(element) > -1; // is not supported by old IE but doesn't really matter
|
121 |
+
};
|
122 |
+
|
123 |
+
/*Extend array prototype to include a contains method
|
124 |
+
Array.prototype.contains = function(element){
|
125 |
+
return this.indexOf(element) > -1; // is not supported by old IE but doesn't really matter
|
126 |
+
};
|
127 |
+
Array.prototype.addIfNotAlreadyIn = function(element){
|
128 |
+
if (this.indexOf(element) == -1){ // is not supported by old IE but doesn't really matter
|
129 |
+
this.push(element)}
|
130 |
+
};
|
131 |
+
*/
|
132 |
+
|
133 |
+
console.log(log_prefix, " Overriding run-range javascript function");
|
134 |
+
requirejs("notebook/js/notebook").Notebook.prototype.execute_cell_range = function(start, end) {
|
135 |
+
this.command_mode();
|
136 |
+
for (var i = start; i < end; i++) {
|
137 |
+
this.select(i);
|
138 |
+
var c = this.get_selected_cell();
|
139 |
+
if (c.element.is(':visible')) {
|
140 |
+
this.execute_cell();
|
141 |
+
} else {
|
142 |
+
//console.log("do nothing for cell",i);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
};
|
146 |
+
|
147 |
+
|
148 |
+
function translateCurrentCell() {
|
149 |
+
//alert(log_prefix+" run on action")
|
150 |
+
conf = Jupyter.notebook.metadata.nbTranslate
|
151 |
+
var cell = Jupyter.notebook.get_selected_cell();
|
152 |
+
var cellText = cell.get_text();
|
153 |
+
var maths_and_text = removeMaths(cellText)
|
154 |
+
var html_and_text = removeHtml(maths_and_text[1])
|
155 |
+
var sourceText = html_and_text[1];
|
156 |
+
var mdReplacements = {'*': '<*>', '**': '<**>',
|
157 |
+
'_': '<_>', '__': '<__>'}
|
158 |
+
// **, *, _, and __ in markdown are "protected" with <.>
|
159 |
+
// which seems to survive the google translation -- not always, actually
|
160 |
+
sourceText = sourceText.replace(/([\*|_]{1,2})([\s\S]*?)\1/g,
|
161 |
+
function(m0,m1,m2){return mdReplacements[m1]+m2+mdReplacements[m1]})
|
162 |
+
cell.metadata.lang = conf.sourceLang;
|
163 |
+
var translated_text = "";
|
164 |
+
if (conf.useGoogleTranslate) {
|
165 |
+
var url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" + conf.sourceLang + "&tl=" + conf.targetLang + "&dt=t&q=" + encodeURIComponent(sourceText);
|
166 |
+
var result = $.get(url)
|
167 |
+
.done(function(data, text, obj) {
|
168 |
+
if (obj.status == 200) {
|
169 |
+
var translated_text = processGoogleTranslateResponse(obj.responseJSON);
|
170 |
+
|
171 |
+
} else {
|
172 |
+
var translated_text = sourceText;
|
173 |
+
}
|
174 |
+
|
175 |
+
translated_text = restoreHtml([html_and_text[0], translated_text])
|
176 |
+
translated_text = restoreMaths([maths_and_text[0], translated_text])
|
177 |
+
translated_text =
|
178 |
+
translated_text.replace(/\\label{([\s\S]*?)}/g, function(m0,m1){return "\\label{"+m1+"-"+conf.targetLang+"}"})
|
179 |
+
.replace(/\\ref{([\s\S]*?)}/g, function(m0,m1){return "\\ref{"+m1+"-"+conf.targetLang+"}"})
|
180 |
+
insertTranslatedCell(translated_text, cell.rendered)
|
181 |
+
})
|
182 |
+
} else {
|
183 |
+
insertTranslatedCell(cellText, cell.rendered)
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
|
188 |
+
function processGoogleTranslateResponse(responseJSON) {
|
189 |
+
var translated_text = "";
|
190 |
+
|
191 |
+
var list_paragraphs = responseJSON[0]
|
192 |
+
//var list_paragraphs = data.responseText.match(/\[\"([\S\s]*?)\",/g)
|
193 |
+
|
194 |
+
list_paragraphs.forEach(
|
195 |
+
function(elt) {
|
196 |
+
translated_text += elt[0] //.substring(2, elt.length - 2)
|
197 |
+
})
|
198 |
+
translated_text = translated_text.replace(/([^\\])\\n/g, "$1\n").replace(/([^\\])\\n/g, "$1\n")
|
199 |
+
.replace(/\\\\/g, "\\") // unescape
|
200 |
+
.replace(/\\"/g, '"') // replace double quotes
|
201 |
+
.replace(/\\u003c([\*|_|@]{1,2})\\u003e\s*([\s\S]*?)\s*\\u003c\1\\u003e/g, function(m0,m1,m2){return m1+m2+m1})
|
202 |
+
.replace(/<([\*|_|@]{1,2})>\s*([\s\S]*?)\s*<\1>/g, function(m0,m1,m2){return m1+m2+m1})
|
203 |
+
|
204 |
+
/*for (item in mdReplacements) {
|
205 |
+
var pattern = new RegExp(mdReplacements[item], 'gmi');
|
206 |
+
translated_text = translated_text.replace(pattern, item);
|
207 |
+
}*/
|
208 |
+
|
209 |
+
// Remove spurious md remaining
|
210 |
+
translated_text = translated_text.replace(/\\u003c([\*|_|@]{1,2})\\u003e/g, "")
|
211 |
+
// Remove extra spaces in markdown
|
212 |
+
translated_text = translated_text.replace(/([\*|_|@]{1,2})\s*([\s\S]*?)\s*\1/g, function(m0,m1,m2){return m1+m2+m1})
|
213 |
+
return translated_text;
|
214 |
+
}
|
215 |
+
|
216 |
+
|
217 |
+
function insertTranslatedCell(translated_text, render) {
|
218 |
+
conf = Jupyter.notebook.metadata.nbTranslate
|
219 |
+
Jupyter.notebook.insert_cell_below("markdown");
|
220 |
+
Jupyter.notebook.select_next();
|
221 |
+
var new_cell = Jupyter.notebook.get_selected_cell();
|
222 |
+
new_cell.set_text(translated_text);
|
223 |
+
new_cell.metadata.lang = conf.targetLang;
|
224 |
+
if (render) new_cell.render();
|
225 |
+
}
|
226 |
+
|
227 |
+
function show_mdcells(displayLangs) {
|
228 |
+
// only show cells with lang or nothing
|
229 |
+
var ncells = Jupyter.notebook.ncells();
|
230 |
+
var cells = Jupyter.notebook.get_cells();
|
231 |
+
var MarkdownCell = requirejs('notebook/js/textcell').MarkdownCell;
|
232 |
+
var lastmd_cell;
|
233 |
+
for (var i = 0; i < ncells; i++) {
|
234 |
+
var cell = cells[i];
|
235 |
+
if (cell instanceof MarkdownCell) {
|
236 |
+
if (typeof cell.metadata.lang != "undefined") {
|
237 |
+
if (!inArray(listOfLangsInNotebook, cell.metadata.lang)){
|
238 |
+
listOfLangsInNotebook.push(cell.metadata.lang)
|
239 |
+
}
|
240 |
+
}
|
241 |
+
if (typeof cell.metadata.lang == "undefined" ||
|
242 |
+
inArray(displayLangs, cell.metadata.lang) ||
|
243 |
+
inArray(displayLangs, '*')) {
|
244 |
+
if (!cell.rendered) cell.render();
|
245 |
+
cell.element.show();
|
246 |
+
lastmd_cell = cell;
|
247 |
+
}
|
248 |
+
else {
|
249 |
+
cell.set_rendered("");
|
250 |
+
cell.rendered = false ;
|
251 |
+
cell.element.hide();
|
252 |
+
}
|
253 |
+
}
|
254 |
+
}
|
255 |
+
// this is to update toc contents.
|
256 |
+
if(typeof lastmd_cell !== "undefined") {
|
257 |
+
lastmd_cell.rendered = false;
|
258 |
+
lastmd_cell.render(); // re-render last md cell and issue rendered.MarkdownCell event
|
259 |
+
}
|
260 |
+
else { //not a single markdown cell has been rendered
|
261 |
+
// add one, render it and delete it.
|
262 |
+
if (Jupyter.notebook.ncells()>1){
|
263 |
+
var c = Jupyter.notebook.insert_cell_at_bottom('markdown');
|
264 |
+
c.render();
|
265 |
+
Jupyter.notebook.delete_cell(Jupyter.notebook.ncells()-1);
|
266 |
+
}
|
267 |
+
}
|
268 |
+
}
|
269 |
+
|
270 |
+
function translateToolbarToggle(){
|
271 |
+
if (nbTranslate_toolbarNotYetDisplayed){
|
272 |
+
buildTranslateToolbar(); //rebuild it
|
273 |
+
nbTranslate_toolbarNotYetDisplayed = false;
|
274 |
+
$("#nbTranslate_toolbar").show();
|
275 |
+
}
|
276 |
+
else
|
277 |
+
$("#nbTranslate_toolbar").toggle();
|
278 |
+
}
|
279 |
+
|
280 |
+
function buildTranslateToolbar(callback) {
|
281 |
+
|
282 |
+
conf = Jupyter.notebook.metadata.nbTranslate
|
283 |
+
var config_toolbar_present = $("#nbTranslate_toolbar").length >0;
|
284 |
+
|
285 |
+
if (config_toolbar_present) {
|
286 |
+
$("#nbTranslate_toolbar").remove();
|
287 |
+
if ($('#LangSelectionMenu').length > 0) $('#LangSelectionMenu').remove();
|
288 |
+
$(site).height($(window).height() - $('#header').height() - $('#footer').height());
|
289 |
+
}
|
290 |
+
sourceLang = conf.sourceLang;
|
291 |
+
targetLang = conf.targetLang;
|
292 |
+
|
293 |
+
//local to this function
|
294 |
+
|
295 |
+
|
296 |
+
// Defining the toolbar --------------------------------------------------------------
|
297 |
+
var nbTranslate_toolbar = $('<div id="nbTranslate_toolbar" \
|
298 |
+
class="container edit_mode" style="display: none;">')
|
299 |
+
|
300 |
+
var vertical_separator = ' <span style="display: inline-block; \
|
301 |
+
vertical-align:bottom; width: 0; height: 1.8em;border-left:2px solid #cccccc"></span> '
|
302 |
+
|
303 |
+
var extensionLabel = $('<a/>').html('<b> nbTranslate </b>')
|
304 |
+
.attr('title', 'Translate from primary to secondary language')
|
305 |
+
.on('click', function(data) {translateCurrentCell() })
|
306 |
+
var primaryLangLabel = $('<b/>').html('Primary language ')
|
307 |
+
var secondaryLangLabel = $('<b/>').html('Secondary language ')
|
308 |
+
var displayLangLabel = $('<b/>').html('Display ')
|
309 |
+
|
310 |
+
// dropdown menu for parameter selection and toggle
|
311 |
+
|
312 |
+
var sourceLangChoice = $('<ul/>').attr('id', 'sourceLangChoice')
|
313 |
+
.addClass("dropdown-menu")
|
314 |
+
.attr('min-width', '250px').css('height','300px').css('overflow', 'auto')
|
315 |
+
|
316 |
+
for (lang in langs) {
|
317 |
+
sourceLangChoice.append($('<li/>').append($('<a/>')
|
318 |
+
.attr('id', 'sourceItem_' + langs[lang])
|
319 |
+
.data('lang', lang)
|
320 |
+
.text(langs[lang])
|
321 |
+
.css('width', '175px')
|
322 |
+
.attr('href', '#')
|
323 |
+
.attr('title', 'Select ' + langs[lang] +
|
324 |
+
' as source language')
|
325 |
+
.on('click', function(data) {
|
326 |
+
sourceLang = $(this).data('lang');
|
327 |
+
conf.sourceLang = sourceLang;
|
328 |
+
$('#sourceLangConfig').text(langs[sourceLang])
|
329 |
+
$('[id^=sourceItem_]' + '>.fa').toggleClass('fa-check', false) //reset the old one if any
|
330 |
+
$('#sourceItem_' + $(this).text() + ' > .fa').toggleClass('fa-check', true)
|
331 |
+
$('#displayItem_source').data('lang', sourceLang).text(langs[sourceLang]).prepend($('<i/>').addClass('fa menu-icon pull-right')).attr('title', 'Display ' + langs[sourceLang])
|
332 |
+
})
|
333 |
+
.prepend($('<i/>').addClass('fa menu-icon pull-right'))
|
334 |
+
))
|
335 |
+
}
|
336 |
+
|
337 |
+
var sourceLangMenu = $('<div/>').attr('id', 'cfgby').addClass('btn-group')
|
338 |
+
.attr('title', 'Select source language')
|
339 |
+
.append($('<a/>')
|
340 |
+
.attr('id', "sourceLangConfig")
|
341 |
+
.addClass("btn btn-default")
|
342 |
+
.append($('<i/>')
|
343 |
+
.addClass("fa fa-wrench fa-fw"))
|
344 |
+
.text(langs[sourceLang])
|
345 |
+
)
|
346 |
+
.append($('<a/>')
|
347 |
+
.addClass("btn btn-default dropdown-toggle")
|
348 |
+
.attr('data-toggle', "dropdown")
|
349 |
+
.attr('href', "#")
|
350 |
+
.append($('<span/>').addClass("fa fa-caret-down")))
|
351 |
+
.append(sourceLangChoice)
|
352 |
+
|
353 |
+
|
354 |
+
// target language menu
|
355 |
+
|
356 |
+
var targetLangChoice = $('<ul/>').attr('id', 'targetLangChoice').addClass("dropdown-menu")
|
357 |
+
.attr('min-width', '250px').css('height','300px').css('overflow', 'auto')
|
358 |
+
|
359 |
+
var listOfLangItems = $('<li/>')
|
360 |
+
for (lang in langs) {
|
361 |
+
targetLangChoice.append($('<li/>').append($('<a/>')
|
362 |
+
.attr('id', 'targetItem_' + lang)
|
363 |
+
.data('lang', lang)
|
364 |
+
.text(langs[lang])
|
365 |
+
.css('width', '175px')
|
366 |
+
.attr('href', '#')
|
367 |
+
.attr('title', 'Select ' + langs[lang] +
|
368 |
+
' as target language')
|
369 |
+
.on('click', function(data) {
|
370 |
+
targetLang = $(this).data('lang');
|
371 |
+
conf.targetLang = targetLang;
|
372 |
+
$('#targetLangConfig').text(langs[targetLang])
|
373 |
+
$('[id^=targetItem_]' + '>.fa').toggleClass('fa-check', false) //reset the old one if any
|
374 |
+
$($(this).id + ' > .fa').toggleClass('fa-check', true)
|
375 |
+
$('#displayItem_target').data('lang', targetLang).text(langs[targetLang]).prepend($('<i/>').addClass('fa menu-icon pull-right')).attr('title', 'Display ' + langs[targetLang])
|
376 |
+
// add targetLang to display menu
|
377 |
+
// out = $('#displayLangChoice > li a').map(function (idx, elt) {return $(elt).data('lang')})
|
378 |
+
if (listOfLangsInNotebook.indexOf(targetLang)==-1){
|
379 |
+
listOfLangsInNotebook.push(targetLang);
|
380 |
+
conf.displayLangs.push(targetLang);
|
381 |
+
$('#displayLangChoice').append(addLangToDisplayLangChoice(targetLang));
|
382 |
+
}
|
383 |
+
$('#displayItem_' + targetLang + ' > .fa').toggleClass('fa-check',true)
|
384 |
+
var index = conf.displayLangs.indexOf('*');
|
385 |
+
if (index > -1) {
|
386 |
+
conf.displayLangs.splice(index, 1);
|
387 |
+
$('#displayItem_all > .fa').toggleClass('fa-check', false)
|
388 |
+
}
|
389 |
+
show_mdcells(conf.displayLangs)
|
390 |
+
})
|
391 |
+
.prepend($('<i/>').addClass('fa menu-icon pull-right'))
|
392 |
+
))
|
393 |
+
}
|
394 |
+
|
395 |
+
var targetLangMenu = $('<div/>').attr('id', 'cfgby').addClass('btn-group')
|
396 |
+
.attr('title', 'Select target language')
|
397 |
+
.append($('<a/>')
|
398 |
+
.attr('id', "targetLangConfig")
|
399 |
+
.addClass("btn btn-default")
|
400 |
+
.append($('<i/>')
|
401 |
+
.addClass("fa fa-wrench fa-fw"))
|
402 |
+
.text(langs[targetLang])
|
403 |
+
)
|
404 |
+
.append($('<a/>')
|
405 |
+
.addClass("btn btn-default dropdown-toggle")
|
406 |
+
.attr('data-toggle', "dropdown")
|
407 |
+
.attr('href', "#")
|
408 |
+
.append($('<span/>').addClass("fa fa-caret-down")))
|
409 |
+
.append(targetLangChoice
|
410 |
+
.append(listOfLangItems)
|
411 |
+
)
|
412 |
+
|
413 |
+
|
414 |
+
// Display language menu
|
415 |
+
|
416 |
+
function onClickedLangChoice(data) {
|
417 |
+
var lang = $(this).data('lang');
|
418 |
+
$('#displayItem_' + lang + ' > .fa').toggleClass('fa-check')
|
419 |
+
if ($('#displayItem_' + lang + ' > .fa').hasClass('fa-check')) {
|
420 |
+
if (conf.displayLangs.indexOf(lang) == -1) conf.displayLangs.push(lang);
|
421 |
+
$('#displayItem_all > .fa').toggleClass('fa-check', false)
|
422 |
+
var index = conf.displayLangs.indexOf('*');
|
423 |
+
if (index > -1) {
|
424 |
+
conf.displayLangs.splice(index, 1);
|
425 |
+
}
|
426 |
+
} else {
|
427 |
+
var index = conf.displayLangs.indexOf(lang);
|
428 |
+
if (index > -1) {
|
429 |
+
conf.displayLangs.splice(index, 1);
|
430 |
+
}
|
431 |
+
}
|
432 |
+
$('#displayLangConfig').text('Select')
|
433 |
+
// console.log("displayLangs", displayLangs)
|
434 |
+
show_mdcells(conf.displayLangs)
|
435 |
+
}
|
436 |
+
|
437 |
+
|
438 |
+
function addLangToDisplayLangChoice(lang){
|
439 |
+
if (typeof lang === 'string' || lang instanceof String)
|
440 |
+
return $('<li/>').append($('<a/>')
|
441 |
+
.attr('id', 'displayItem_'+lang)
|
442 |
+
.data('lang', lang)
|
443 |
+
.text(langs[lang])
|
444 |
+
.css('width', '175px')
|
445 |
+
.attr('href', '#')
|
446 |
+
.attr('title', 'Display ' + langs[lang])
|
447 |
+
.on('click', onClickedLangChoice)
|
448 |
+
.prepend($('<i/>').addClass('fa menu-icon pull-right'))
|
449 |
+
)
|
450 |
+
}
|
451 |
+
|
452 |
+
var displayLangChoice = $('<ul/>')
|
453 |
+
.attr('id', 'displayLangChoice')
|
454 |
+
.addClass("dropdown-menu")
|
455 |
+
.attr('min-width', '300px')
|
456 |
+
|
457 |
+
var allLangs = $('<li/>')
|
458 |
+
allLangs.attr('id', 'allLangs')
|
459 |
+
.append($('<a/>')
|
460 |
+
.attr('id', 'displayItem_all')
|
461 |
+
.data('lang', '*')
|
462 |
+
.text('All')
|
463 |
+
.css('width', '175px')
|
464 |
+
.attr('href', '#')
|
465 |
+
.attr('title', 'Display all languages')
|
466 |
+
.on('click', function(data) {
|
467 |
+
conf.displayLangs = ['*'];
|
468 |
+
$('#displayLangConfig').text('All')
|
469 |
+
$('[id^=displayItem_]' + '>.fa').toggleClass('fa-check', false) //reset the old one if any
|
470 |
+
$('#displayItem_all > .fa').toggleClass('fa-check', true)
|
471 |
+
show_mdcells(conf.displayLangs)
|
472 |
+
})
|
473 |
+
.prepend($('<i/>').addClass('fa menu-icon pull-right'))
|
474 |
+
)
|
475 |
+
|
476 |
+
//console.log("List of langs", listOfLangsInNotebook)
|
477 |
+
for (var langIndex in listOfLangsInNotebook) {
|
478 |
+
var lang = listOfLangsInNotebook[langIndex]
|
479 |
+
//console.log("lang",lang)
|
480 |
+
if (typeof lang === 'string' || lang instanceof String){
|
481 |
+
displayLangChoice.append(
|
482 |
+
addLangToDisplayLangChoice(listOfLangsInNotebook[langIndex]))}
|
483 |
+
}
|
484 |
+
|
485 |
+
var displayLangMenu = $('<div/>').attr('id', 'cfgby').addClass('btn-group')
|
486 |
+
.attr('title', 'Select language to display')
|
487 |
+
.append($('<a/>')
|
488 |
+
.attr('id', "displayLangConfig")
|
489 |
+
.addClass("btn btn-default")
|
490 |
+
.append($('<i/>')
|
491 |
+
.addClass("fa fa-wrench fa-fw"))
|
492 |
+
.text(inArray(conf.displayLangs, '*') ? 'All' : 'Select')
|
493 |
+
)
|
494 |
+
.append($('<a/>')
|
495 |
+
.addClass("btn btn-default dropdown-toggle")
|
496 |
+
.attr('data-toggle', "dropdown")
|
497 |
+
.attr('href', "#")
|
498 |
+
.append($('<span/>').addClass("fa fa-caret-down")))
|
499 |
+
.append(displayLangChoice.prepend(allLangs))
|
500 |
+
|
501 |
+
|
502 |
+
// Refresh display in notebook
|
503 |
+
var refresh_languages_display_button = $("<a/>")
|
504 |
+
.addClass("btn btn-default")
|
505 |
+
.attr('href', "#")
|
506 |
+
.attr('title', 'Refresh languages display in notebook')
|
507 |
+
.css('color', 'black')
|
508 |
+
.attr('id', 'refreshLanguagesDisplay')
|
509 |
+
.append($("<i/>").addClass('fa fa-refresh'))
|
510 |
+
.on('click', function() {
|
511 |
+
show_mdcells(conf.displayLangs)
|
512 |
+
})
|
513 |
+
|
514 |
+
// close button
|
515 |
+
var suicide_button = $("<a/>")
|
516 |
+
.addClass("btn btn-default")
|
517 |
+
.attr('href', "#")
|
518 |
+
.attr('title', 'Close nbTranslate toolbar')
|
519 |
+
.css('float', 'right')
|
520 |
+
.attr('id', 'suicide')
|
521 |
+
.attr('title', 'Close the nbTranslate configuration toolbar')
|
522 |
+
.append($("<i/>").addClass('fa fa-power-off'))
|
523 |
+
.on('click', function() {
|
524 |
+
translateToolbarToggle();
|
525 |
+
return
|
526 |
+
})
|
527 |
+
|
528 |
+
|
529 |
+
// translateButton
|
530 |
+
var translate_button = $("<a/>")
|
531 |
+
.addClass("btn btn-default")
|
532 |
+
.attr('href', "#")
|
533 |
+
.attr('title', 'Translate current cell')
|
534 |
+
.attr('id', 'translateButton')
|
535 |
+
.html('<b> nbTranslate </b>')
|
536 |
+
.on('click', function(data) {translateCurrentCell() })
|
537 |
+
|
538 |
+
// Enable Google Engine button
|
539 |
+
var useGoogleTranslateButton = $("<a/>")
|
540 |
+
.addClass("btn btn-default")
|
541 |
+
.attr('href', "#")
|
542 |
+
.attr('title', 'Use Google translate')
|
543 |
+
.attr('id', 'useGoogleTranslateButton')
|
544 |
+
.append($("<i/>").addClass(conf.useGoogleTranslate ? 'fa fa-check-square-o' : 'fa fa-square-o'))
|
545 |
+
.on('click', function() { $('#useGoogleTranslateButton > .fa').toggleClass("fa-square-o fa-check-square-o");
|
546 |
+
conf.useGoogleTranslate = !conf.useGoogleTranslate })
|
547 |
+
|
548 |
+
// Lang Menu
|
549 |
+
var langMenu = $('<a/>').attr('href', '#')
|
550 |
+
.addClass('dropdown-toogle')
|
551 |
+
.attr('data-toggle', "dropdown")
|
552 |
+
.attr('aria-expanded', "false")
|
553 |
+
.text("Langs")
|
554 |
+
.attr('title', 'Languages to display in notebook (nbTranslate extension)')
|
555 |
+
|
556 |
+
// Finally the toolbar itself
|
557 |
+
nbTranslate_toolbar.append(translate_button)
|
558 |
+
.append(vertical_separator)
|
559 |
+
.append(useGoogleTranslateButton)
|
560 |
+
.append(vertical_separator)
|
561 |
+
.append(primaryLangLabel)
|
562 |
+
.append(sourceLangMenu)
|
563 |
+
.append(vertical_separator)
|
564 |
+
.append(secondaryLangLabel)
|
565 |
+
.append(targetLangMenu)
|
566 |
+
if (conf.langInMainMenu) {
|
567 |
+
$('#kernel_menu').parent().after('<li id="LangSelectionMenu"/>')
|
568 |
+
$('#LangSelectionMenu').addClass('dropdown')
|
569 |
+
.append(langMenu).append(displayLangChoice)
|
570 |
+
}
|
571 |
+
else{
|
572 |
+
nbTranslate_toolbar.append(vertical_separator)
|
573 |
+
.append(displayLangLabel)
|
574 |
+
.append(displayLangMenu)
|
575 |
+
}
|
576 |
+
nbTranslate_toolbar.append(' ')
|
577 |
+
.append(refresh_languages_display_button)
|
578 |
+
.append(suicide_button)
|
579 |
+
|
580 |
+
// Appending the new toolbar to the main one
|
581 |
+
$('head').append('<style> input:focus {border-color: #66afe9;\
|
582 |
+
outline: 0; box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px \
|
583 |
+
rgba(102, 175, 233, 0.6);}</style>')
|
584 |
+
|
585 |
+
$("#maintoolbar-container").append(nbTranslate_toolbar);
|
586 |
+
$("#nbTranslate_toolbar").css({ 'padding': '5px' });
|
587 |
+
|
588 |
+
|
589 |
+
// Initializing toogles checks
|
590 |
+
$('#sourceItem_' + langs[sourceLang] + ' > .fa').toggleClass('fa-check', true)
|
591 |
+
$('#targetItem_' + langs[targetLang] + ' > .fa').toggleClass('fa-check', true)
|
592 |
+
|
593 |
+
for (var langIndex in conf.displayLangs) {
|
594 |
+
var lang = conf.displayLangs[langIndex];
|
595 |
+
if (typeof lang === 'string' || lang instanceof String){
|
596 |
+
$('#displayItem_' + lang + ' .fa')
|
597 |
+
.toggleClass('fa-check', true)
|
598 |
+
}
|
599 |
+
if (conf.displayLangs.indexOf('*')> -1)
|
600 |
+
$('#displayItem_all > .fa').toggleClass('fa-check', true)
|
601 |
+
}
|
602 |
+
}
|
603 |
+
|
604 |
+
/*
|
605 |
+
function create_lang_menu(callback) {
|
606 |
+
|
607 |
+
if ($('#LangSelectionMenu').length > 0) {
|
608 |
+
return;
|
609 |
+
}
|
610 |
+
var displayLangChoiceClone = $('#displayLangChoice').clone()
|
611 |
+
|
612 |
+
$('#help_menu').parent().before('<li id="LangSelectionMenu"/>')
|
613 |
+
$('#LangSelectionMenu').addClass('dropdown')
|
614 |
+
.append($('<a/>').attr('href', '#')
|
615 |
+
.addClass('dropdown-toogle')
|
616 |
+
.attr('data-toggle', "dropdown")
|
617 |
+
.attr('aria-expanded', "false")
|
618 |
+
.text("Langs"))
|
619 |
+
.append(displayLangChoiceClone)
|
620 |
+
}
|
621 |
+
|
622 |
+
*/
|
.local/share/jupyter/nbextensions/notify/notification.png
ADDED
.local/share/jupyter/nbextensions/notify/notify.js
ADDED
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
|
3 |
+
*************************
|
4 |
+
Display Web Notifications
|
5 |
+
*************************
|
6 |
+
|
7 |
+
Add this file to $(ipython locate)/nbextensions/
|
8 |
+
|
9 |
+
*/
|
10 |
+
|
11 |
+
define([
|
12 |
+
"jquery",
|
13 |
+
"base/js/namespace",
|
14 |
+
"require",
|
15 |
+
], function ($, Jupyter, requirejs) {
|
16 |
+
"use strict";
|
17 |
+
|
18 |
+
var params = {
|
19 |
+
sticky: false,
|
20 |
+
play_sound: false
|
21 |
+
};
|
22 |
+
var audio_file = "./notify.mp3";
|
23 |
+
|
24 |
+
var current_time = function() {
|
25 |
+
return new Date().getTime() / 1000;
|
26 |
+
};
|
27 |
+
|
28 |
+
var start_time = current_time();
|
29 |
+
var min_time = 0;
|
30 |
+
var enabled = false;
|
31 |
+
var first_start = true;
|
32 |
+
var busy_kernel = true;
|
33 |
+
|
34 |
+
var add_permissions_list = function () {
|
35 |
+
var ipython_toolbar = $('#maintoolbar-container');
|
36 |
+
var label = $('<span/>').addClass("navbar-text permissions-list").text('Notify:');
|
37 |
+
var select = $('<select/>')
|
38 |
+
.attr('id', 'permissions-select')
|
39 |
+
.attr('class', 'permissions-list form-control select-xs')
|
40 |
+
.append($('<option/>')
|
41 |
+
.attr('value', 'Disabled')
|
42 |
+
.text('Disabled'));
|
43 |
+
ipython_toolbar.append(label).append(select);
|
44 |
+
select.change(function() {
|
45 |
+
var val = $(this).val();
|
46 |
+
if (val == 'Disabled') {
|
47 |
+
enabled = false;
|
48 |
+
} else {
|
49 |
+
enabled = true;
|
50 |
+
min_time = val;
|
51 |
+
}
|
52 |
+
save_state();
|
53 |
+
});
|
54 |
+
// Add options in addition to the default, 'Disabled'
|
55 |
+
// Options give the minimum kernel busy time in seconds after which a notification is displayed
|
56 |
+
var presets = [0, 5, 10, 30];
|
57 |
+
for (var i=0; i<presets.length; i++) {
|
58 |
+
var name = presets[i];
|
59 |
+
select.append($('<option/>').attr('value', name).text(name));
|
60 |
+
}
|
61 |
+
// Finally, restore the selected option if it was saved in notebook metadata
|
62 |
+
restore_state();
|
63 |
+
};
|
64 |
+
|
65 |
+
var add_permissions_button = function () {
|
66 |
+
if ($("#permissions-button").length === 0) {
|
67 |
+
$(Jupyter.toolbar.add_buttons_group([
|
68 |
+
Jupyter.keyboard_manager.actions.register ({
|
69 |
+
'help' : 'Grant Notification Permissions',
|
70 |
+
'icon' : 'fa-check',
|
71 |
+
'handler': ask_permission,
|
72 |
+
},'grant-notifications-permission', 'notify')
|
73 |
+
])).find('.btn').attr('id', 'permissions-button');
|
74 |
+
}
|
75 |
+
};
|
76 |
+
|
77 |
+
var ensure_permission = function () {
|
78 |
+
ask_permission(); // Asks for permission on notebook load, doesn't work in Chrome
|
79 |
+
// If don't have permission now, add a button to the toolbar to let user request permission
|
80 |
+
if (Notification && Notification.permission !== "granted") {
|
81 |
+
add_permissions_button();
|
82 |
+
add_permissions_list();
|
83 |
+
$(".permissions-list").hide();
|
84 |
+
} else if (Notification && Notification.permission === "granted") {
|
85 |
+
add_permissions_list();
|
86 |
+
}
|
87 |
+
};
|
88 |
+
|
89 |
+
var ask_permission = function () {
|
90 |
+
if (Notification && Notification.permission !== "granted") {
|
91 |
+
Notification.requestPermission(function (status) {
|
92 |
+
if (Notification.permission !== status) {
|
93 |
+
Notification.permission = status;
|
94 |
+
}
|
95 |
+
// Wait for permission to be granted, then remove the permissions-button and show permissions-list
|
96 |
+
if (Notification && Notification.permission === "granted" && $("#permissions-button").length > 0) {
|
97 |
+
$("#permissions-button").remove();
|
98 |
+
$(".permissions-list").show();
|
99 |
+
}
|
100 |
+
});
|
101 |
+
}
|
102 |
+
};
|
103 |
+
|
104 |
+
var play_notification_sound = function(opts) {
|
105 |
+
/**
|
106 |
+
* NB: the Web Notification API specifies a mechanism for playing sound
|
107 |
+
* with notifications. As of 2017-08-22, it is unsupported in all browsers.
|
108 |
+
* This is a workaround. It should be updated to an implementation like
|
109 |
+
* this when browser support is available:
|
110 |
+
*
|
111 |
+
* opts["sound"] = requirejs.toUrl(audio_file);
|
112 |
+
*/
|
113 |
+
try {
|
114 |
+
var audio = new Audio(requirejs.toUrl(audio_file));
|
115 |
+
audio.play();
|
116 |
+
} catch(e) {
|
117 |
+
console.log('HTML5 Audio not supported in browser.');
|
118 |
+
}
|
119 |
+
};
|
120 |
+
|
121 |
+
var notify = function () {
|
122 |
+
var elapsed_time = current_time() - start_time;
|
123 |
+
if (enabled && !first_start && !busy_kernel && elapsed_time >= min_time) {
|
124 |
+
var opts = {
|
125 |
+
body: "Kernel is now idle\n(ran for " + Math.round(elapsed_time) + " secs)",
|
126 |
+
icon: Jupyter.notebook.base_url + "static/base/images/favicon.ico",
|
127 |
+
requireInteraction: params.sticky
|
128 |
+
};
|
129 |
+
if (params.play_sound) {
|
130 |
+
play_notification_sound(opts);
|
131 |
+
}
|
132 |
+
var n = new Notification(Jupyter.notebook.notebook_name, opts);
|
133 |
+
n.onclick = function(event){ window.focus(); }
|
134 |
+
}
|
135 |
+
if (first_start) {
|
136 |
+
first_start = false;
|
137 |
+
}
|
138 |
+
};
|
139 |
+
|
140 |
+
var load_state = function () {
|
141 |
+
if (!Jupyter.notebook) return;
|
142 |
+
|
143 |
+
if ("notify_time" in Jupyter.notebook.metadata) {
|
144 |
+
min_time = Jupyter.notebook.metadata.notify_time;
|
145 |
+
enabled = true;
|
146 |
+
}
|
147 |
+
};
|
148 |
+
|
149 |
+
var save_state = function () {
|
150 |
+
if (enabled) {
|
151 |
+
if (Jupyter.notebook.metadata.notify_time !== min_time) {
|
152 |
+
Jupyter.notebook.metadata.notify_time = min_time;
|
153 |
+
Jupyter.notebook.set_dirty();
|
154 |
+
}
|
155 |
+
} else {
|
156 |
+
if (Jupyter.notebook.metadata.hasOwnProperty('notify_time')) {
|
157 |
+
delete Jupyter.notebook.metadata.notify_time;
|
158 |
+
Jupyter.notebook.set_dirty();
|
159 |
+
}
|
160 |
+
}
|
161 |
+
};
|
162 |
+
|
163 |
+
var restore_state = function () {
|
164 |
+
load_state();
|
165 |
+
// Only proceed if the permissions selector is being shown
|
166 |
+
if ($("#permissions-select").length > 0) {
|
167 |
+
if (!enabled) {
|
168 |
+
$("#permissions-select").val("Disabled");
|
169 |
+
} else {
|
170 |
+
$("#permissions-select").val(min_time);
|
171 |
+
}
|
172 |
+
}
|
173 |
+
};
|
174 |
+
|
175 |
+
var setup_notifier = function () {
|
176 |
+
$([Jupyter.events]).on('kernel_starting.Kernel',function () {
|
177 |
+
first_start = true; // reset first_start status when restarting the kernel
|
178 |
+
});
|
179 |
+
|
180 |
+
$([Jupyter.events]).on('kernel_busy.Kernel',function () {
|
181 |
+
busy_kernel = true;
|
182 |
+
start_time = current_time(); // reset the timer
|
183 |
+
});
|
184 |
+
|
185 |
+
$([Jupyter.events]).on('kernel_idle.Kernel',function () {
|
186 |
+
busy_kernel = false; // Used to make sure that kernel doesn't go busy again within the timeout set below.
|
187 |
+
setTimeout(notify, 500);
|
188 |
+
});
|
189 |
+
};
|
190 |
+
|
191 |
+
var load_ipython_extension = function () {
|
192 |
+
return Jupyter.notebook.config.loaded.then(function() {
|
193 |
+
$.extend(true, params, Jupyter.notebook.config.data.notify);
|
194 |
+
ensure_permission();
|
195 |
+
setup_notifier();
|
196 |
+
});
|
197 |
+
};
|
198 |
+
|
199 |
+
return {
|
200 |
+
load_ipython_extension : load_ipython_extension
|
201 |
+
};
|
202 |
+
|
203 |
+
});
|
.local/share/jupyter/nbextensions/notify/notify.mp3
ADDED
Binary file (13.9 kB). View file
|
|
.local/share/jupyter/nbextensions/printview/icon.png
ADDED
.local/share/jupyter/nbextensions/printview/main.js
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// call "jupyter nbconvert" and open generated html file in new tab
|
2 |
+
|
3 |
+
define([
|
4 |
+
'base/js/namespace',
|
5 |
+
'jquery',
|
6 |
+
'base/js/events',
|
7 |
+
'base/js/utils'
|
8 |
+
], function(
|
9 |
+
IPython,
|
10 |
+
$,
|
11 |
+
events,
|
12 |
+
utils
|
13 |
+
) {
|
14 |
+
"use strict";
|
15 |
+
|
16 |
+
var nbconvert_options = '--to html';
|
17 |
+
var extension = '.html';
|
18 |
+
var open_tab = true;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Get option from config
|
22 |
+
*/
|
23 |
+
var initialize = function () {
|
24 |
+
var config = IPython.notebook.config;
|
25 |
+
if (config.data.hasOwnProperty('printview_nbconvert_options') ) {
|
26 |
+
nbconvert_options = config.data.printview_nbconvert_options;
|
27 |
+
if (nbconvert_options.search('pdf') > 0) extension = '.pdf';
|
28 |
+
if (nbconvert_options.search('slides') > 0) extension = '.slides.html';
|
29 |
+
}
|
30 |
+
if (config.data.hasOwnProperty('printview_open_tab') ) {
|
31 |
+
if (typeof(config.data.printview_open_tab) === "boolean") {
|
32 |
+
open_tab = config.data.printview_open_tab;
|
33 |
+
}
|
34 |
+
}
|
35 |
+
};
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Call nbconvert using the current notebook server profile
|
39 |
+
*
|
40 |
+
*/
|
41 |
+
var callNbconvert = function () {
|
42 |
+
events.off('notebook_saved.Notebook');
|
43 |
+
var kernel = IPython.notebook.kernel;
|
44 |
+
var name = IPython.notebook.notebook_name;
|
45 |
+
var command = 'import os; os.system(\'jupyter nbconvert ' + nbconvert_options + ' \"' + name + '\"\')';
|
46 |
+
function callback() {
|
47 |
+
if (open_tab === true) {
|
48 |
+
var url = utils.splitext(name)[0] + extension;
|
49 |
+
window.open(url, '_blank');
|
50 |
+
}
|
51 |
+
}
|
52 |
+
kernel.execute(command, { shell: { reply : callback } });
|
53 |
+
$('#doPrintView').blur();
|
54 |
+
};
|
55 |
+
|
56 |
+
var nbconvertPrintView = function () {
|
57 |
+
events.on('notebook_saved.Notebook',callNbconvert);
|
58 |
+
IPython.notebook.save_notebook(false);
|
59 |
+
};
|
60 |
+
|
61 |
+
var load_ipython_extension = function() {
|
62 |
+
$(IPython.toolbar.add_buttons_group([
|
63 |
+
IPython.keyboard_manager.actions.register ({
|
64 |
+
help : 'Create static print view',
|
65 |
+
icon : 'fa-print',
|
66 |
+
handler: nbconvertPrintView
|
67 |
+
}, 'create-static-printview', 'printview'),
|
68 |
+
])).find('.btn').attr('id', 'doPrintView');
|
69 |
+
return IPython.notebook.config.loaded.then(initialize);
|
70 |
+
};
|
71 |
+
|
72 |
+
return {
|
73 |
+
load_ipython_extension : load_ipython_extension
|
74 |
+
};
|
75 |
+
});
|
.local/share/jupyter/nbextensions/printview/printview-button.png
ADDED