forked from almariah/embed-code-file
-
Notifications
You must be signed in to change notification settings - Fork 0
/
code-parser.ts
110 lines (93 loc) · 2.61 KB
/
code-parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { EmbedCodeFileSettings } from "./settings";
export interface CodeParser {
parseCode: (code: string, args: string) => string | Error;
getOutputLanguage: () => string;
}
//Factory method for future complex code types
export function createCodeParser(inputLanguage: string, settings: EmbedCodeFileSettings): CodeParser {
switch (inputLanguage) {
case "ipynb":
return new IpynbParser(settings.displayIpynbAsPython, settings.showIpynbCellNumbers);
break;
default:
return new DefaultParser(inputLanguage);
}
}
export class IpynbParser implements CodeParser {
private enabled: boolean;
private cellNumbers: boolean;
constructor(enabled: boolean, cellNumbers: boolean) {
this.enabled = enabled;
this.cellNumbers = cellNumbers;
}
parseCode(src: string, args: string): string | Error {
if (!this.enabled) {
return src;
}
let keep_cells: number[] = [];
if (args.length > 0) {
const regex = /^(\d+)(,\d+)*$/;
if (regex.test(args)) {
keep_cells = args.split(",").map(value => parseInt(value));
} else {
return new Error("Cell numbers should be a list of comma-separated, 1-based numbers, with no spaces, in quotes");
}
}
let code = ""
let notebook;
try {
notebook = JSON.parse(src);
} catch (error) {
return new Error("Improperly formatted .ipynb file");
}
let codeBlocks: string[] = [];
if (Array.isArray(notebook.cells) && notebook.cells.length !== 0) {
notebook.cells.forEach((cell: any, index: number) => {
if (cell.cell_type === 'code' && Array.isArray(cell.source)
&& (keep_cells.length === 0 ||
(keep_cells.length > 0 && keep_cells.includes(index + 1)))) {
let codeBlock = cell.source.join('');
if (codeBlock.length > 0) {
codeBlocks.push(codeBlock);
}
}
});
} else {
return new Error("No cells found in the notebook");
}
if (codeBlocks.length === 0) {
return new Error("No code cells in the notebook");
}
codeBlocks.forEach((block: string, index: number) => {
if (codeBlocks.length != 1 && this.cellNumbers) {
code += `# Cell ${index + 1}:\n\n`;
}
code += block;
if (index !== codeBlocks.length - 1) {
code += "\n";
if (this.cellNumbers) {
code += "\n";
}
}
});
return code
}
getOutputLanguage(): string {
if (!this.enabled) {
return 'ipynb'
}
return 'python'
}
}
export class DefaultParser implements CodeParser {
private inputLanguage: string;
constructor(inputLanguage: string) {
this.inputLanguage = inputLanguage;
}
parseCode(src: string, args: string): string {
return src;
}
getOutputLanguage(): string {
return this.inputLanguage;
}
}