@hpcc-js/observablehq-compiler 3.7.5 → 3.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +43 -43
- package/README.md +105 -105
- package/bin/ojscc.mjs +67 -67
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/runtime.js.map +1 -1
- package/package.json +3 -3
- package/src/__package__.ts +3 -3
- package/src/compiler.md +234 -234
- package/src/compiler.ts +340 -340
- package/src/cst.ts +181 -181
- package/src/index.node.ts +7 -7
- package/src/index.ts +6 -6
- package/src/kit/compiler.ts +60 -60
- package/src/kit/index.ts +2 -2
- package/src/kit/runtime.ts +85 -85
- package/src/kit/util.ts +157 -157
- package/src/observable-shim.ts +2 -2
- package/src/parse.ts +136 -136
- package/src/types.ts +179 -179
- package/src/util.md +113 -113
- package/src/util.ts +155 -155
- package/src/writer.ts +83 -83
package/src/util.md
CHANGED
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
# Utilities
|
|
2
|
-
|
|
3
|
-
Various utilities and helpers.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
<a name="download" href="#download">#</a> **download**(_impUrl_) => Promise\<ohq.Module\> · [<>](https://github.com/hpcc-systems/Visualization/blob/trunk/packages/observablehq/compiler/src/util.ts "Source")
|
|
8
|
-
|
|
9
|
-
* _impUrl_: Full url to Obaservable HQ notebook as a string.
|
|
10
|
-
* _returns_: Returns a Promise of a notebook (a JSON object).
|
|
11
|
-
|
|
12
|
-
Downloads a notebook directly from [Observable HQ](https://observablehq.com/) as a JSON object. The following example downloads the [@observablehq/plot](https://observablehq.com/@observablehq/plot) notebook as JSON:
|
|
13
|
-
|
|
14
|
-
<ClientOnly>
|
|
15
|
-
<hpcc-vitepress style="width:100%;height:600px">
|
|
16
|
-
<hpcc-codemirror id="placeholder" mode="json" theme="dark" style="width:100%;height:100%">
|
|
17
|
-
</hpcc-codemirror>
|
|
18
|
-
<script type="module">
|
|
19
|
-
import "@hpcc-js/wc-editor";
|
|
20
|
-
import { download } from "@hpcc-js/observablehq-compiler";
|
|
21
|
-
|
|
22
|
-
const notebook = await download("https://observablehq.com/@observablehq/plot");
|
|
23
|
-
const placeholder = document.getElementById("placeholder");
|
|
24
|
-
placeholder.text = JSON.stringify(notebook, undefined, 4);
|
|
25
|
-
</script>
|
|
26
|
-
</hpcc-vitepress>
|
|
27
|
-
</ClientOnly>
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
<a name="ojs2notebook" href="#ojs2notebook">#</a> **ojs2notebook**(_ojs_) => ohq.Module · [<>](https://github.com/hpcc-systems/Visualization/blob/trunk/packages/observablehq/compiler/src/util.ts "Source")
|
|
32
|
-
|
|
33
|
-
* _ojs_: String containing Observable JavaScript.
|
|
34
|
-
* _returns_: Returns the notebook as a JSON object.
|
|
35
|
-
|
|
36
|
-
Transforms Observable JavaScript to a JSON notebook.
|
|
37
|
-
|
|
38
|
-
<ClientOnly>
|
|
39
|
-
<hpcc-vitepress style="width:100%;height:600px">
|
|
40
|
-
<hpcc-codemirror id="placeholder" mode="json" theme="dark" style="width:100%;height:100%">
|
|
41
|
-
</hpcc-codemirror>
|
|
42
|
-
<script type="module">
|
|
43
|
-
import "@hpcc-js/wc-editor";
|
|
44
|
-
import { ojs2notebook } from "@hpcc-js/observablehq-compiler";
|
|
45
|
-
|
|
46
|
-
const notebook = ojs2notebook(`
|
|
47
|
-
md\`# Simple Notebook\`
|
|
48
|
-
a = 1
|
|
49
|
-
b = 2
|
|
50
|
-
c = a + b
|
|
51
|
-
d = {
|
|
52
|
-
yield 1;
|
|
53
|
-
yield 2;
|
|
54
|
-
yield 3;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
viewof e = {
|
|
58
|
-
let output = {};
|
|
59
|
-
let listeners = [];
|
|
60
|
-
output.value = 10;
|
|
61
|
-
output.addEventListener = (listener) => listeners.push(listener);;
|
|
62
|
-
output.removeEventListener = (listener) => {
|
|
63
|
-
listeners = listeners.filter(l => l !== listener);
|
|
64
|
-
};
|
|
65
|
-
return output;
|
|
66
|
-
}
|
|
67
|
-
`);
|
|
68
|
-
const placeholder = document.getElementById("placeholder");
|
|
69
|
-
placeholder.text = JSON.stringify(notebook, undefined, 4);
|
|
70
|
-
</script>
|
|
71
|
-
</hpcc-vitepress>
|
|
72
|
-
</ClientOnly>
|
|
73
|
-
|
|
74
|
-
<a name="omd2notebook" href="#omd2notebook">#</a> **omd2notebook**(_omd_) => ohq.Module · [<>](https://github.com/hpcc-systems/Visualization/blob/trunk/packages/observablehq/compiler/src/util.ts "Source")
|
|
75
|
-
|
|
76
|
-
* _omd_: String containing Observable Markdown.
|
|
77
|
-
* _returns_: Returns the notebook as a JSON object.
|
|
78
|
-
|
|
79
|
-
Transforms Observable Markdown to a JSON notebook.
|
|
80
|
-
|
|
81
|
-
<ClientOnly>
|
|
82
|
-
<hpcc-vitepress style="width:100%;height:600px">
|
|
83
|
-
<hpcc-codemirror id="placeholder" mode="json" theme="dark" style="width:100%;height:100%">
|
|
84
|
-
</hpcc-codemirror>
|
|
85
|
-
<script type="module">
|
|
86
|
-
import "@hpcc-js/wc-editor";
|
|
87
|
-
import { omd2notebook } from "@hpcc-js/observablehq-compiler";
|
|
88
|
-
|
|
89
|
-
const notebook = omd2notebook(`\
|
|
90
|
-
# Simple Notebook
|
|
91
|
-
|
|
92
|
-
* Set A
|
|
93
|
-
\`\`\`
|
|
94
|
-
a = 1
|
|
95
|
-
\`\`\`
|
|
96
|
-
|
|
97
|
-
* Set B
|
|
98
|
-
\`\`\`
|
|
99
|
-
b = 2
|
|
100
|
-
\`\`\`
|
|
101
|
-
|
|
102
|
-
* Calculate c
|
|
103
|
-
|
|
104
|
-
\`\`\`
|
|
105
|
-
c = a + b
|
|
106
|
-
\`\`\`
|
|
107
|
-
`);
|
|
108
|
-
const placeholder = document.getElementById("placeholder");
|
|
109
|
-
placeholder.text = JSON.stringify(notebook, undefined, 4);
|
|
110
|
-
</script>
|
|
111
|
-
</hpcc-vitepress>
|
|
112
|
-
</ClientOnly>
|
|
113
|
-
|
|
1
|
+
# Utilities
|
|
2
|
+
|
|
3
|
+
Various utilities and helpers.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<a name="download" href="#download">#</a> **download**(_impUrl_) => Promise\<ohq.Module\> · [<>](https://github.com/hpcc-systems/Visualization/blob/trunk/packages/observablehq/compiler/src/util.ts "Source")
|
|
8
|
+
|
|
9
|
+
* _impUrl_: Full url to Obaservable HQ notebook as a string.
|
|
10
|
+
* _returns_: Returns a Promise of a notebook (a JSON object).
|
|
11
|
+
|
|
12
|
+
Downloads a notebook directly from [Observable HQ](https://observablehq.com/) as a JSON object. The following example downloads the [@observablehq/plot](https://observablehq.com/@observablehq/plot) notebook as JSON:
|
|
13
|
+
|
|
14
|
+
<ClientOnly>
|
|
15
|
+
<hpcc-vitepress style="width:100%;height:600px">
|
|
16
|
+
<hpcc-codemirror id="placeholder" mode="json" theme="dark" style="width:100%;height:100%">
|
|
17
|
+
</hpcc-codemirror>
|
|
18
|
+
<script type="module">
|
|
19
|
+
import "@hpcc-js/wc-editor";
|
|
20
|
+
import { download } from "@hpcc-js/observablehq-compiler";
|
|
21
|
+
|
|
22
|
+
const notebook = await download("https://observablehq.com/@observablehq/plot");
|
|
23
|
+
const placeholder = document.getElementById("placeholder");
|
|
24
|
+
placeholder.text = JSON.stringify(notebook, undefined, 4);
|
|
25
|
+
</script>
|
|
26
|
+
</hpcc-vitepress>
|
|
27
|
+
</ClientOnly>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
<a name="ojs2notebook" href="#ojs2notebook">#</a> **ojs2notebook**(_ojs_) => ohq.Module · [<>](https://github.com/hpcc-systems/Visualization/blob/trunk/packages/observablehq/compiler/src/util.ts "Source")
|
|
32
|
+
|
|
33
|
+
* _ojs_: String containing Observable JavaScript.
|
|
34
|
+
* _returns_: Returns the notebook as a JSON object.
|
|
35
|
+
|
|
36
|
+
Transforms Observable JavaScript to a JSON notebook.
|
|
37
|
+
|
|
38
|
+
<ClientOnly>
|
|
39
|
+
<hpcc-vitepress style="width:100%;height:600px">
|
|
40
|
+
<hpcc-codemirror id="placeholder" mode="json" theme="dark" style="width:100%;height:100%">
|
|
41
|
+
</hpcc-codemirror>
|
|
42
|
+
<script type="module">
|
|
43
|
+
import "@hpcc-js/wc-editor";
|
|
44
|
+
import { ojs2notebook } from "@hpcc-js/observablehq-compiler";
|
|
45
|
+
|
|
46
|
+
const notebook = ojs2notebook(`
|
|
47
|
+
md\`# Simple Notebook\`
|
|
48
|
+
a = 1
|
|
49
|
+
b = 2
|
|
50
|
+
c = a + b
|
|
51
|
+
d = {
|
|
52
|
+
yield 1;
|
|
53
|
+
yield 2;
|
|
54
|
+
yield 3;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
viewof e = {
|
|
58
|
+
let output = {};
|
|
59
|
+
let listeners = [];
|
|
60
|
+
output.value = 10;
|
|
61
|
+
output.addEventListener = (listener) => listeners.push(listener);;
|
|
62
|
+
output.removeEventListener = (listener) => {
|
|
63
|
+
listeners = listeners.filter(l => l !== listener);
|
|
64
|
+
};
|
|
65
|
+
return output;
|
|
66
|
+
}
|
|
67
|
+
`);
|
|
68
|
+
const placeholder = document.getElementById("placeholder");
|
|
69
|
+
placeholder.text = JSON.stringify(notebook, undefined, 4);
|
|
70
|
+
</script>
|
|
71
|
+
</hpcc-vitepress>
|
|
72
|
+
</ClientOnly>
|
|
73
|
+
|
|
74
|
+
<a name="omd2notebook" href="#omd2notebook">#</a> **omd2notebook**(_omd_) => ohq.Module · [<>](https://github.com/hpcc-systems/Visualization/blob/trunk/packages/observablehq/compiler/src/util.ts "Source")
|
|
75
|
+
|
|
76
|
+
* _omd_: String containing Observable Markdown.
|
|
77
|
+
* _returns_: Returns the notebook as a JSON object.
|
|
78
|
+
|
|
79
|
+
Transforms Observable Markdown to a JSON notebook.
|
|
80
|
+
|
|
81
|
+
<ClientOnly>
|
|
82
|
+
<hpcc-vitepress style="width:100%;height:600px">
|
|
83
|
+
<hpcc-codemirror id="placeholder" mode="json" theme="dark" style="width:100%;height:100%">
|
|
84
|
+
</hpcc-codemirror>
|
|
85
|
+
<script type="module">
|
|
86
|
+
import "@hpcc-js/wc-editor";
|
|
87
|
+
import { omd2notebook } from "@hpcc-js/observablehq-compiler";
|
|
88
|
+
|
|
89
|
+
const notebook = omd2notebook(`\
|
|
90
|
+
# Simple Notebook
|
|
91
|
+
|
|
92
|
+
* Set A
|
|
93
|
+
\`\`\`
|
|
94
|
+
a = 1
|
|
95
|
+
\`\`\`
|
|
96
|
+
|
|
97
|
+
* Set B
|
|
98
|
+
\`\`\`
|
|
99
|
+
b = 2
|
|
100
|
+
\`\`\`
|
|
101
|
+
|
|
102
|
+
* Calculate c
|
|
103
|
+
|
|
104
|
+
\`\`\`
|
|
105
|
+
c = a + b
|
|
106
|
+
\`\`\`
|
|
107
|
+
`);
|
|
108
|
+
const placeholder = document.getElementById("placeholder");
|
|
109
|
+
placeholder.text = JSON.stringify(notebook, undefined, 4);
|
|
110
|
+
</script>
|
|
111
|
+
</hpcc-vitepress>
|
|
112
|
+
</ClientOnly>
|
|
113
|
+
|
package/src/util.ts
CHANGED
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
import { type Notebook, type Cell, toNotebook, toCell } from "./kit/index.ts";
|
|
2
|
-
|
|
3
|
-
import type { ohq } from "./observable-shim.ts";
|
|
4
|
-
import { parseCell, splitModule } from "./observable-shim.ts";
|
|
5
|
-
|
|
6
|
-
interface ParsedOJS {
|
|
7
|
-
ojs: string;
|
|
8
|
-
offset: number;
|
|
9
|
-
inlineMD: boolean;
|
|
10
|
-
cell: any;
|
|
11
|
-
error: any;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function encodeBacktick(str: string) {
|
|
15
|
-
return str
|
|
16
|
-
.split("`").join("\\`")
|
|
17
|
-
;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function createParsedOJS(ojs: string, offset: number, inlineMD: boolean): ParsedOJS {
|
|
21
|
-
let cell;
|
|
22
|
-
let error;
|
|
23
|
-
try {
|
|
24
|
-
cell = parseCell(ojs);
|
|
25
|
-
} catch (e) {
|
|
26
|
-
error = e;
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
ojs,
|
|
30
|
-
offset,
|
|
31
|
-
inlineMD,
|
|
32
|
-
cell,
|
|
33
|
-
error
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function splitOmd(_: string): ParsedOJS[] {
|
|
38
|
-
const retVal: ParsedOJS[] = [];
|
|
39
|
-
// Load Markdown ---
|
|
40
|
-
const re = /(```(?:\s|\S)[\s\S]*?```)/g;
|
|
41
|
-
let prevOffset = 0;
|
|
42
|
-
let match = re.exec(_);
|
|
43
|
-
while (match !== null) {
|
|
44
|
-
if (match.index > prevOffset) {
|
|
45
|
-
retVal.push(createParsedOJS(_.substring(prevOffset, match.index), prevOffset, true));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const outer = match[0];
|
|
49
|
-
if (outer.indexOf("``` ") === 0 || outer.indexOf("```\n") === 0 || outer.indexOf("```\r\n") === 0) {
|
|
50
|
-
const prefixLen = 3;
|
|
51
|
-
const inner = outer.substring(prefixLen, outer.length - prefixLen);
|
|
52
|
-
retVal.push(createParsedOJS(inner, match.index + prefixLen, false));
|
|
53
|
-
} else {
|
|
54
|
-
retVal.push(createParsedOJS(outer, match.index, true));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
prevOffset = match.index + match[0].length;
|
|
58
|
-
match = re.exec(_);
|
|
59
|
-
}
|
|
60
|
-
if (_.length > prevOffset) {
|
|
61
|
-
retVal.push(createParsedOJS(_.substring(prevOffset, _.length), prevOffset, true));
|
|
62
|
-
}
|
|
63
|
-
return retVal;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function notebook2ojs(_: string): ParsedOJS[] {
|
|
67
|
-
const parsed: ohq.Notebook = JSON.parse(_);
|
|
68
|
-
return parsed.nodes.map(node => createParsedOJS(node.value, 0, node.mode === "md"));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function ojs2notebook(ojs: string): ohq.Notebook {
|
|
72
|
-
const cells = splitModule(ojs);
|
|
73
|
-
return {
|
|
74
|
-
files: [],
|
|
75
|
-
nodes: cells.map((cell, idx) => {
|
|
76
|
-
return {
|
|
77
|
-
id: idx,
|
|
78
|
-
mode: "js",
|
|
79
|
-
value: cell.text,
|
|
80
|
-
start: cell.start,
|
|
81
|
-
end: cell.end
|
|
82
|
-
};
|
|
83
|
-
})
|
|
84
|
-
} as ohq.Notebook;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function ojs2notebookKit(ojs: string): Notebook {
|
|
88
|
-
const cells: Cell[] = splitModule(ojs).map((cell, idx) => {
|
|
89
|
-
return toCell({
|
|
90
|
-
id: idx,
|
|
91
|
-
mode: "ojs",
|
|
92
|
-
value: cell.text
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
return toNotebook({ cells });
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function omd2notebook(omd: string): ohq.Notebook {
|
|
99
|
-
const cells = splitOmd(omd);
|
|
100
|
-
return {
|
|
101
|
-
files: [],
|
|
102
|
-
nodes: cells.map((cell, idx) => {
|
|
103
|
-
return {
|
|
104
|
-
id: idx,
|
|
105
|
-
mode: cell.inlineMD ? "md" : "js",
|
|
106
|
-
value: cell.ojs,
|
|
107
|
-
start: cell.offset,
|
|
108
|
-
end: cell.offset + cell.ojs.length
|
|
109
|
-
};
|
|
110
|
-
})
|
|
111
|
-
} as ohq.Notebook;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function omd2notebookKit(omd: string): Notebook {
|
|
115
|
-
const cells: Cell[] = [];
|
|
116
|
-
splitOmd(omd).forEach((cell) => {
|
|
117
|
-
if (!cell.inlineMD) {
|
|
118
|
-
splitModule(cell.ojs).forEach((subCell) => {
|
|
119
|
-
cells.push(toCell({
|
|
120
|
-
id: cells.length + 1,
|
|
121
|
-
mode: "ojs",
|
|
122
|
-
value: subCell.text
|
|
123
|
-
}));
|
|
124
|
-
});
|
|
125
|
-
} else {
|
|
126
|
-
cells.push(toCell({
|
|
127
|
-
id: cells.length + 1,
|
|
128
|
-
mode: "md",
|
|
129
|
-
value: cell.ojs
|
|
130
|
-
}));
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
return toNotebook({ cells });
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function fetchEx(url: string, proxyPrefix = "https://api.codetabs.com/v1/proxy/?quest=", proxyPostfix = "") {
|
|
137
|
-
const matches = url.match(/^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n?]+)/img);
|
|
138
|
-
if (!matches || matches.length === 0) {
|
|
139
|
-
throw new Error(`Invalid URL: ${url}`);
|
|
140
|
-
}
|
|
141
|
-
return fetch(url, { headers: { origin: matches[0], referer: url } }).then(response => {
|
|
142
|
-
if (response.ok) return response;
|
|
143
|
-
throw new Error("CORS?");
|
|
144
|
-
}).catch(e => {
|
|
145
|
-
url = `${proxyPrefix}${url}${proxyPostfix}`;
|
|
146
|
-
return fetch(url, { headers: { origin: matches[0], referer: url } });
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function download(impUrl: string, proxyPrefix?: string, proxyPostfix?: string): Promise<ohq.Notebook> {
|
|
151
|
-
const isShared = impUrl.indexOf("https://observablehq.com/d") === 0;
|
|
152
|
-
return fetchEx(impUrl.replace(`https://observablehq.com/${isShared ? "d/" : ""}`, "https://api.observablehq.com/document/"), proxyPrefix, proxyPostfix)
|
|
153
|
-
.then(r => r.json())
|
|
154
|
-
;
|
|
155
|
-
}
|
|
1
|
+
import { type Notebook, type Cell, toNotebook, toCell } from "./kit/index.ts";
|
|
2
|
+
|
|
3
|
+
import type { ohq } from "./observable-shim.ts";
|
|
4
|
+
import { parseCell, splitModule } from "./observable-shim.ts";
|
|
5
|
+
|
|
6
|
+
interface ParsedOJS {
|
|
7
|
+
ojs: string;
|
|
8
|
+
offset: number;
|
|
9
|
+
inlineMD: boolean;
|
|
10
|
+
cell: any;
|
|
11
|
+
error: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function encodeBacktick(str: string) {
|
|
15
|
+
return str
|
|
16
|
+
.split("`").join("\\`")
|
|
17
|
+
;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function createParsedOJS(ojs: string, offset: number, inlineMD: boolean): ParsedOJS {
|
|
21
|
+
let cell;
|
|
22
|
+
let error;
|
|
23
|
+
try {
|
|
24
|
+
cell = parseCell(ojs);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
error = e;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
ojs,
|
|
30
|
+
offset,
|
|
31
|
+
inlineMD,
|
|
32
|
+
cell,
|
|
33
|
+
error
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function splitOmd(_: string): ParsedOJS[] {
|
|
38
|
+
const retVal: ParsedOJS[] = [];
|
|
39
|
+
// Load Markdown ---
|
|
40
|
+
const re = /(```(?:\s|\S)[\s\S]*?```)/g;
|
|
41
|
+
let prevOffset = 0;
|
|
42
|
+
let match = re.exec(_);
|
|
43
|
+
while (match !== null) {
|
|
44
|
+
if (match.index > prevOffset) {
|
|
45
|
+
retVal.push(createParsedOJS(_.substring(prevOffset, match.index), prevOffset, true));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const outer = match[0];
|
|
49
|
+
if (outer.indexOf("``` ") === 0 || outer.indexOf("```\n") === 0 || outer.indexOf("```\r\n") === 0) {
|
|
50
|
+
const prefixLen = 3;
|
|
51
|
+
const inner = outer.substring(prefixLen, outer.length - prefixLen);
|
|
52
|
+
retVal.push(createParsedOJS(inner, match.index + prefixLen, false));
|
|
53
|
+
} else {
|
|
54
|
+
retVal.push(createParsedOJS(outer, match.index, true));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
prevOffset = match.index + match[0].length;
|
|
58
|
+
match = re.exec(_);
|
|
59
|
+
}
|
|
60
|
+
if (_.length > prevOffset) {
|
|
61
|
+
retVal.push(createParsedOJS(_.substring(prevOffset, _.length), prevOffset, true));
|
|
62
|
+
}
|
|
63
|
+
return retVal;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function notebook2ojs(_: string): ParsedOJS[] {
|
|
67
|
+
const parsed: ohq.Notebook = JSON.parse(_);
|
|
68
|
+
return parsed.nodes.map(node => createParsedOJS(node.value, 0, node.mode === "md"));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function ojs2notebook(ojs: string): ohq.Notebook {
|
|
72
|
+
const cells = splitModule(ojs);
|
|
73
|
+
return {
|
|
74
|
+
files: [],
|
|
75
|
+
nodes: cells.map((cell, idx) => {
|
|
76
|
+
return {
|
|
77
|
+
id: idx,
|
|
78
|
+
mode: "js",
|
|
79
|
+
value: cell.text,
|
|
80
|
+
start: cell.start,
|
|
81
|
+
end: cell.end
|
|
82
|
+
};
|
|
83
|
+
})
|
|
84
|
+
} as ohq.Notebook;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function ojs2notebookKit(ojs: string): Notebook {
|
|
88
|
+
const cells: Cell[] = splitModule(ojs).map((cell, idx) => {
|
|
89
|
+
return toCell({
|
|
90
|
+
id: idx,
|
|
91
|
+
mode: "ojs",
|
|
92
|
+
value: cell.text
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
return toNotebook({ cells });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function omd2notebook(omd: string): ohq.Notebook {
|
|
99
|
+
const cells = splitOmd(omd);
|
|
100
|
+
return {
|
|
101
|
+
files: [],
|
|
102
|
+
nodes: cells.map((cell, idx) => {
|
|
103
|
+
return {
|
|
104
|
+
id: idx,
|
|
105
|
+
mode: cell.inlineMD ? "md" : "js",
|
|
106
|
+
value: cell.ojs,
|
|
107
|
+
start: cell.offset,
|
|
108
|
+
end: cell.offset + cell.ojs.length
|
|
109
|
+
};
|
|
110
|
+
})
|
|
111
|
+
} as ohq.Notebook;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function omd2notebookKit(omd: string): Notebook {
|
|
115
|
+
const cells: Cell[] = [];
|
|
116
|
+
splitOmd(omd).forEach((cell) => {
|
|
117
|
+
if (!cell.inlineMD) {
|
|
118
|
+
splitModule(cell.ojs).forEach((subCell) => {
|
|
119
|
+
cells.push(toCell({
|
|
120
|
+
id: cells.length + 1,
|
|
121
|
+
mode: "ojs",
|
|
122
|
+
value: subCell.text
|
|
123
|
+
}));
|
|
124
|
+
});
|
|
125
|
+
} else {
|
|
126
|
+
cells.push(toCell({
|
|
127
|
+
id: cells.length + 1,
|
|
128
|
+
mode: "md",
|
|
129
|
+
value: cell.ojs
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
return toNotebook({ cells });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function fetchEx(url: string, proxyPrefix = "https://api.codetabs.com/v1/proxy/?quest=", proxyPostfix = "") {
|
|
137
|
+
const matches = url.match(/^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n?]+)/img);
|
|
138
|
+
if (!matches || matches.length === 0) {
|
|
139
|
+
throw new Error(`Invalid URL: ${url}`);
|
|
140
|
+
}
|
|
141
|
+
return fetch(url, { headers: { origin: matches[0], referer: url } }).then(response => {
|
|
142
|
+
if (response.ok) return response;
|
|
143
|
+
throw new Error("CORS?");
|
|
144
|
+
}).catch(e => {
|
|
145
|
+
url = `${proxyPrefix}${url}${proxyPostfix}`;
|
|
146
|
+
return fetch(url, { headers: { origin: matches[0], referer: url } });
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function download(impUrl: string, proxyPrefix?: string, proxyPostfix?: string): Promise<ohq.Notebook> {
|
|
151
|
+
const isShared = impUrl.indexOf("https://observablehq.com/d") === 0;
|
|
152
|
+
return fetchEx(impUrl.replace(`https://observablehq.com/${isShared ? "d/" : ""}`, "https://api.observablehq.com/document/"), proxyPrefix, proxyPostfix)
|
|
153
|
+
.then(r => r.json())
|
|
154
|
+
;
|
|
155
|
+
}
|