Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Project: topocm
Views: 386
1
/**
2
* Calico Jupyter Notebooks Extensions
3
*
4
* Copyright (c) The Calico Project
5
* http://calicoproject.org/ICalico
6
*
7
* Released under the BSD Simplified License
8
*
9
**/
10
11
function ip_version() {
12
if (IPython.version[0] === "2")
13
return 2;
14
else if (IPython.version[0] === "3")
15
return 3;
16
else
17
throw "IPython version not supported";
18
}
19
20
function break_into_sections(index) {
21
if (ip_version() === 2)
22
return 0;
23
var cells = IPython.notebook.get_cells();
24
var count = 0; // count below index, or -1
25
// go in reverse order to keep index accurate
26
for (var i = cells.length - 1; i > -1; i--) {
27
var cell = cells[i];
28
var rendered = cell.rendered;
29
// consider it for breaking:
30
if (cell.cell_type === "markdown") {
31
var text = cell.get_text();
32
if (text.match(/^#+Table of Contents/))
33
continue;
34
var lines = text.split(/\n/g);
35
if (lines.length > 1) {
36
// possibly break up
37
var state = "ok";
38
var current = "";
39
var cell_texts = [];
40
for (var line_no in lines) {
41
var line = lines[line_no];
42
if (state === "ok") {
43
if (line.indexOf('```') === 0) {
44
// set state to fence: allows for longer fences
45
state = line.substr(0, line.search("[^`]"));
46
current += line + "\n";
47
} else if (line.indexOf('#') === 0) {
48
if (current !== "") {
49
cell_texts.push(current.trim());
50
}
51
current = "";
52
cell_texts.push(line);
53
} else {
54
current += line + "\n";
55
}
56
} else { // in block
57
if (line.indexOf(state) === 0) {
58
state = "ok";
59
current += line + "\n";
60
cell_texts.push(current.trim());
61
current = "";
62
} else {
63
current += line + "\n";
64
}
65
}
66
} // for
67
// anything left over:
68
if (current.trim() !== "") {
69
cell_texts.push(current.trim());
70
}
71
if (cell_texts.length > 1) {
72
var current_cell = IPython.notebook.get_cell(i);
73
var added = 0;
74
for (var j = 0; j < cell_texts.length; j++) {
75
if (cell_texts[j].trim() !== "") {
76
if (added === 0) {
77
current_cell.set_text(cell_texts[j]);
78
if (rendered) {
79
current_cell.render();
80
}
81
} else {
82
if (i === index) {
83
count = -1; // nope, can't do it
84
} else if (i < index && count !== -1) {
85
count++;
86
}
87
var new_cell = IPython.notebook.insert_cell_below("markdown", i + added - 1);
88
new_cell.set_text(cell_texts[j]);
89
if (rendered) {
90
new_cell.render();
91
}
92
}
93
added++;
94
}
95
}
96
}
97
}
98
}
99
}
100
return count;
101
}
102
103
function is_heading(cell) {
104
if (ip_version() === 2)
105
return (cell.cell_type === "heading");
106
else
107
return (cell.cell_type === "markdown" && cell.get_text().indexOf("#") === 0)
108
}
109
110
function get_heading_text(cell) {
111
if (ip_version() === 2)
112
return cell.get_text();
113
else if (cell.get_text().indexOf("######") === 0)
114
return cell.get_text().substring(6).trim();
115
else if (cell.get_text().indexOf("#####") === 0)
116
return cell.get_text().substring(5).trim();
117
else if (cell.get_text().indexOf("####") === 0)
118
return cell.get_text().substring(4).trim();
119
else if (cell.get_text().indexOf("###") === 0)
120
return cell.get_text().substring(3).trim();
121
else if (cell.get_text().indexOf("##") === 0)
122
return cell.get_text().substring(2).trim();
123
else if (cell.get_text().indexOf("#") === 0)
124
return cell.get_text().substring(1).trim();
125
else return "";
126
}
127
128
function repeat(pattern, count) {
129
if (count < 1) return '';
130
var result = '';
131
while (count > 1) {
132
if (count & 1) result += pattern;
133
count >>= 1, pattern += pattern;
134
}
135
return result + pattern;
136
}
137
138
function set_heading_text(cell, text) {
139
var rendered = cell.rendered;
140
cell.unrender();
141
if (ip_version() === 2)
142
cell.set_text(text);
143
else {
144
var level = get_level(cell);
145
cell.set_text( repeat("#", level) + " " + text)
146
}
147
if (rendered) {
148
cell.render();
149
}
150
}
151
152
function get_level(cell) {
153
if (ip_version() === 2)
154
return cell.level;
155
else if (cell.get_text().indexOf("######") === 0)
156
return 6;
157
else if (cell.get_text().indexOf("#####") === 0)
158
return 5;
159
else if (cell.get_text().indexOf("####") === 0)
160
return 4;
161
else if (cell.get_text().indexOf("###") === 0)
162
return 3;
163
else if (cell.get_text().indexOf("##") === 0)
164
return 2;
165
else if (cell.get_text().indexOf("#") === 0)
166
return 1;
167
else return 0;
168
}
169
170
function get_last_cell_index_in_section(level, index) {
171
var current = index;
172
while (IPython.notebook.is_valid_cell_index(current + 1)) {
173
var cell = IPython.notebook.get_cell(current + 1);
174
if (is_heading(cell) && get_level(cell) <= level) {
175
return current;
176
}
177
current++;
178
}
179
return current;
180
}
181
182
function get_index_level_above(level, index) {
183
var current = current = index - 1;
184
while (IPython.notebook.is_valid_cell_index(current)) {
185
var cell = IPython.notebook.get_cell(current);
186
if (is_heading(cell) && get_level(cell) <= level) {
187
return current;
188
}
189
current--;
190
}
191
return undefined;
192
}
193
194
function get_index_level_below(level, index) {
195
var current = current = index + 1;
196
while (IPython.notebook.is_valid_cell_index(current)) {
197
var cell = IPython.notebook.get_cell(current);
198
if (is_heading(cell) && get_level(cell) <= level) {
199
return current;
200
}
201
current++;
202
}
203
return undefined;
204
}
205
206
function section_label() {
207
// Label headings with numbers, or toggle them off
208
// If there is a table of contents, re-do it
209
break_into_sections();
210
var cells = IPython.notebook.get_cells();
211
var levels = [0,0,0,0,0,0];
212
var current_level = 1;
213
var flag = false;
214
var alert_text = "";
215
var alert_flag = false;
216
var remove_numbering = true;
217
218
for (var i = 0; i < cells.length; i++) {
219
var cell = cells[i];
220
if (is_heading(cell)) {
221
if (cell.get_text().match(/^#+Table of Contents/))
222
continue;
223
if (cell.get_text().match(/^#+References/))
224
continue;
225
var level = get_level(cell);
226
227
if (level >= current_level) { //just keep incrementing
228
current_level = level;
229
levels[level-1]++;
230
} else { //went back a level
231
levels[current_level-1] = 0;
232
233
if (current_level-level > 1) { //Skipped levels in between
234
for (var j = 1; j < current_level-level; j++) { //back-prop the zeros
235
levels[current_level - 1 - j] = 0;
236
}
237
}
238
239
levels[level -1]++;
240
current_level = level;
241
}
242
243
var error = false;
244
var error_no_begin = 0;
245
var error_no_end = 0;
246
var error_heading_label = "";
247
var heading_label = ""; //Generate the appropriate number for the heading
248
for (var k = 0; k < level; k++) {
249
if (levels[k] == 0) {
250
if (!error) {
251
error_heading_label = heading_label;
252
error = true;
253
error_no_begin = k;
254
} else {
255
error_no_end = k + 2;
256
}
257
}
258
heading_label += levels[k];
259
if (level-k == 1 && level > 1) {
260
break;
261
}
262
heading_label += ".";
263
}
264
265
if (error) {
266
if (error_no_end == 0) {
267
error_no_end = error_no_begin + 2;
268
}
269
if (error_heading_label == "") {
270
if (!flag) {
271
var temp1 = "Notebook begins with a Header " + error_no_end + " cell." + "\n";
272
alert_text += temp1;
273
alert_flag = true;
274
flag = true;
275
}
276
} else{
277
var temp = "You placed a Header " + error_no_end + " cell under a Header " + error_no_begin + " cell in section " + error_heading_label +"\n";
278
alert_text += temp;
279
alert_flag = true;
280
}
281
}
282
283
var heading_text = get_heading_text(cell);
284
var old_header = heading_text;
285
var re = /(?:\d*\.*)*\s*(.*)/;
286
var match = heading_text.match(re);
287
288
if (match) {
289
heading_text = heading_label + " " + match[1];
290
} else {
291
heading_text = heading_label;
292
}
293
294
if (old_header != heading_text) {
295
remove_numbering = false;
296
replace_links(old_header, heading_text);
297
}
298
299
heading_text = heading_text.trim();
300
set_heading_text(cell, heading_text);
301
}
302
}
303
304
if (alert_flag) {
305
alert(alert_text);
306
}
307
308
if (remove_numbering) {
309
for (var i = 0; i < cells.length; i++) {
310
var cell = cells[i];
311
if (is_heading(cell)) {
312
if (cell.get_text().match(/^#+Table of Contents/))
313
continue;
314
if (cell.get_text().match(/^#+References/))
315
continue;
316
var heading_text = get_heading_text(cell);
317
old_header = heading_text;
318
var re = /(?:\d*\.*)*\s*(.*)/;
319
var match = heading_text.match(re);
320
if (match) {
321
heading_text = match[1];
322
}
323
set_heading_text(cell, heading_text);
324
replace_links(old_header, heading_text);
325
}
326
}
327
}
328
329
// If there is a Table of Contents, replace it:
330
var cells = IPython.notebook.get_cells();
331
for (var i = 0; i < cells.length; i++) {
332
var cell = cells[i];
333
if (cell.cell_type == "markdown") {
334
var cell_text = cell.get_text();
335
var match = cell_text.match(/^#+Table of Contents/);
336
if (match) {
337
table_of_contents();
338
break;
339
}
340
}
341
}
342
}
343
344
function replace_links(old_header, new_header) {
345
// Replace an old internal link with new link
346
new_header = new_header.trim();
347
var cells = IPython.notebook.get_cells();
348
for (var i = 0; i < cells.length; i++) {
349
var cell = cells[i];
350
if (cell.cell_type == "markdown") {
351
var cell_text = cell.get_text();
352
// Skip over table of contents:
353
if (cell_text.match(/^#+Table of Contents/)) {
354
continue;
355
}
356
var re_string = old_header;
357
re_string = re_string.replace(/\\/g, "\\\\");
358
re_string = re_string.replace(/\//g, "\\/");
359
re_string = re_string.replace(/\^/g, "\\^");
360
re_string = re_string.replace(/\$/g, "\\$");
361
re_string = re_string.replace(/\*/g, "\\*");
362
re_string = re_string.replace(/\+/g, "\\+");
363
re_string = re_string.replace(/\?/g, "\\?");
364
re_string = re_string.replace(/\./g, "\\.");
365
re_string = re_string.replace(/\)/g, "%29");
366
re_string = re_string.replace(/\|/g, "\\|");
367
re_string = re_string.replace(/\[/g, "\\[");
368
re_string = re_string.replace(/\]/g, "\\]");
369
re_string = re_string.replace(/\(/g, "?:\\(|%28");
370
re_string = re_string.replace(/\s/g, "-");
371
re_string = "(\\[.*\\](?::\\s*|\\()#)" + re_string + "(.*\\)|(.*)$)";
372
373
var re = new RegExp(re_string, "gm");
374
var link_text = new_header.replace(/\s+$/g, ""); //Delete trailing spaces before they become "-"
375
link_text = link_text.replace(/\(/g, "%28"); //Replace left parentheses with their encoding
376
link_text = link_text.replace(/\)/g, "%29"); //Replace right parentheses with their encoding
377
link_text = link_text.replace(/ /g, "-"); //Replace all spaces with dashes to create links
378
379
var match = cell_text.match(re);
380
if (match) {
381
var new_text = cell_text.replace(re, "$1" + link_text + "$2");
382
cell.unrender();
383
cell.set_text(new_text);
384
cell.render();
385
}
386
}
387
}
388
}
389
390
function find_cell(cell_type, text) {
391
// Finds first cell of cell_type that starts with text
392
// cell_type and text are interpreted as a regular expression
393
var cell = undefined;
394
var cells = IPython.notebook.get_cells();
395
for (var x = 0; x < cells.length; x++) {
396
var temp = cells[x];
397
if (temp.cell_type.match(cell_type) != undefined) {
398
var temp_text = temp.get_text();
399
var re = new RegExp("^" + text);
400
if (re.test(temp_text)) {
401
cell = cells[x];
402
break;
403
}
404
}
405
}
406
return cell;
407
}
408
409
function table_of_contents() {
410
break_into_sections();
411
// Create and/or replace Table of Contents
412
var cells = IPython.notebook.get_cells();
413
var toc_cell = find_cell("markdown", "#+Table of Contents");
414
// Default to top-level heading
415
var toc_text = "#Table of Contents\n";
416
if (toc_cell == undefined) {
417
//Create a new markdown cell at the top of the Notebook
418
toc_cell = IPython.notebook.select(0).insert_cell_below("markdown");
419
} else {
420
// already exists:
421
toc_text = toc_cell.get_text().match(/^#+Table of Contents/)[0] + "\n";
422
}
423
var prev_lev = 0;
424
for (var i = 0; i < cells.length; i++) {
425
var cell = cells[i];
426
if (is_heading(cell)) {
427
if (cell.get_text().match(/^#+Table of Contents/))
428
continue;
429
if (cell.get_text().match(/^#+References/))
430
continue;
431
if (get_level(cell) - prev_lev > 1) { //Skipped levels. Enter Dummy levels
432
for (var x = 0; x < ((get_level(cell) - prev_lev) - 1); x++) {
433
for (var y = 0; y < (prev_lev + x); y++) {
434
toc_text += "\t";
435
}
436
toc_text += "* &nbsp;\n";
437
}
438
}
439
var cell_text = get_heading_text(cell);
440
for (var j = 0; j < get_level(cell) -1; j++) { //Loop to add the proper amount of tabs based on header level
441
toc_text += "\t";
442
}
443
toc_text += "* [";
444
toc_text += cell_text;
445
toc_text += "](#";
446
var link_text = cell_text.replace(/\s+$/g, ""); //Delete trailing spaces before they become "-"
447
link_text = link_text.replace(/\(/g, "%28"); //Replace left parentheses with their encoding
448
link_text = link_text.replace(/\)/g, "%29"); //Replace right parentheses with their encoding
449
link_text = link_text.replace(/ /g, "-"); //Replace all spaces with dashes to create links
450
toc_text += link_text;
451
toc_text += ")\n";
452
prev_lev = get_level(cell);
453
}
454
}
455
toc_cell.unrender();
456
toc_cell.set_text(toc_text);
457
toc_cell.render();
458
}
459
460