0-hero commited on
Commit
dd51869
·
verified ·
1 Parent(s): 9b31431

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .cache/pip/http-v2/8/1/3/c/c/813cc7096c25ba43edba14a4ab40832db33af638c43e975795995aec.body +0 -0
  2. .cache/pip/http-v2/8/5/e/f/e/85efe0b09056afaed0a9932320bb2a590a03afe4bc35e3fffc1e85cd.body +0 -0
  3. .cache/pip/http-v2/8/f/4/1/0/8f410bbfc5d1848453018f07fdeb351a0d0ae8a3bcdc5a16f937935c.body +0 -0
  4. .cache/pip/http-v2/c/2/0/9/b/c209b6730b4a3a67d7d68f436a023e57f848dcba7c8db3fd04a54862 +0 -0
  5. .cache/pip/http-v2/c/5/4/0/3/c5403a101bbaf526810b4c472004bc3b03b96b7c8118e06c7a081e63.body +0 -0
  6. .cache/pip/http-v2/f/0/4/f/6/f04f619fe804fd38ac24d3bad7c02b3e6461727bd3a1ce45e316d44a +0 -0
  7. .cache/pip/http-v2/f/0/4/f/6/f04f619fe804fd38ac24d3bad7c02b3e6461727bd3a1ce45e316d44a.body +0 -0
  8. .cache/pip/http-v2/f/3/c/4/d/f3c4dedd1435641845fe96a7938402191795947fd69de9d823bd65e1.body +0 -0
  9. .local/share/jupyter/nbextensions/highlight_selected_word/main.js +419 -0
  10. .local/share/jupyter/nbextensions/highlighter/demo_highlighter.html +0 -0
  11. .local/share/jupyter/nbextensions/highlighter/export_highlights.ipynb +194 -0
  12. .local/share/jupyter/nbextensions/highlighter/export_highlights.pdf +0 -0
  13. .local/share/jupyter/nbextensions/highlighter/highlighter.css +98 -0
  14. .local/share/jupyter/nbextensions/highlighter/highlighter.yaml +7 -0
  15. .local/share/jupyter/nbextensions/highlighter/tst_highlights.html +0 -0
  16. .local/share/jupyter/nbextensions/highlighter/tst_highlights.ipynb +53 -0
  17. .local/share/jupyter/nbextensions/highlighter/tst_highlights.tex +279 -0
  18. .local/share/jupyter/nbextensions/hinterland/README.md +49 -0
  19. .local/share/jupyter/nbextensions/hinterland/hinterland.yaml +73 -0
  20. .local/share/jupyter/nbextensions/init_cell/README.md +44 -0
  21. .local/share/jupyter/nbextensions/init_cell/cell_toolbar_menu.png +0 -0
  22. .local/share/jupyter/nbextensions/init_cell/icon.png +0 -0
  23. .local/share/jupyter/nbextensions/init_cell/init_cell.yaml +17 -0
  24. .local/share/jupyter/nbextensions/init_cell/main.js +157 -0
  25. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/keyboard_shortcut_editor.yaml +12 -0
  26. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/kse_components.js +364 -0
  27. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/main.css +40 -0
  28. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/main.js +778 -0
  29. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/quickhelp_shim.js +207 -0
  30. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_add_new_select_action.png +0 -0
  31. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_comma.png +0 -0
  32. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_conflict.png +0 -0
  33. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_dropdown.png +0 -0
  34. .local/share/jupyter/nbextensions/keyboard_shortcut_editor/readme_shortcut_editor_success.png +0 -0
  35. .local/share/jupyter/nbextensions/limit_output/icon.png +0 -0
  36. .local/share/jupyter/nbextensions/limit_output/limit-output.yaml +30 -0
  37. .local/share/jupyter/nbextensions/livemdpreview/livemdpreview.js +112 -0
  38. .local/share/jupyter/nbextensions/livemdpreview/livemdpreview.yml +24 -0
  39. .local/share/jupyter/nbextensions/load_tex_macros/icon.png +0 -0
  40. .local/share/jupyter/nbextensions/load_tex_macros/readme.md +17 -0
  41. .local/share/jupyter/nbextensions/move_selected_cells/main.js +87 -0
  42. .local/share/jupyter/nbextensions/navigation-hotkeys/hotkeys.yaml +25 -0
  43. .local/share/jupyter/nbextensions/nbTranslate/README.md +56 -0
  44. .local/share/jupyter/nbextensions/nbTranslate/nbTranslate.js +622 -0
  45. .local/share/jupyter/nbextensions/notify/notification.png +0 -0
  46. .local/share/jupyter/nbextensions/notify/notify.js +203 -0
  47. .local/share/jupyter/nbextensions/notify/notify.mp3 +0 -0
  48. .local/share/jupyter/nbextensions/printview/icon.png +0 -0
  49. .local/share/jupyter/nbextensions/printview/main.js +75 -0
  50. .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(',', '&#44;');
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 &#9785;. ' +
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) : '&lt;new shortcut&gt;');
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 = '&nbsp;&nbsp;<span style="display: inline-block; \
301
+ vertical-align:bottom; width: 0; height: 1.8em;border-left:2px solid #cccccc"></span>&nbsp;&nbsp;'
302
+
303
+ var extensionLabel = $('<a/>').html('<b> nbTranslate&nbsp;</b>')
304
+ .attr('title', 'Translate from primary to secondary language')
305
+ .on('click', function(data) {translateCurrentCell() })
306
+ var primaryLangLabel = $('<b/>').html('Primary language&nbsp;')
307
+ var secondaryLangLabel = $('<b/>').html('Secondary language&nbsp;')
308
+ var displayLangLabel = $('<b/>').html('Display&nbsp;')
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&nbsp;</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('&nbsp;&nbsp;')
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