@hpcc-js/observablehq-compiler 3.3.9 → 3.4.0

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/src/compiler.ts CHANGED
@@ -1,7 +1,10 @@
1
+
2
+ import { type Notebook, transpile } from "@observablehq/notebook-kit";
3
+ import { type Definition } from "@observablehq/notebook-kit/runtime";
1
4
  import { ohq, splitModule } from "./observable-shim.ts";
2
5
  import { parseCell, ParsedImportCell } from "./cst.ts";
3
6
  import { Writer } from "./writer.ts";
4
- import { fixRelativeUrl, isRelativePath, encodeBacktick, fetchEx, obfuscatedImport, ojs2notebook, omd2notebook } from "./util.ts";
7
+ import { fixRelativeUrl, isRelativePath, encodeBacktick, fetchEx, obfuscatedImport, ojs2notebook, omd2notebook, constructFunction } from "./util.ts";
5
8
 
6
9
  // Inspector Factory ---
7
10
  export type InspectorFactoryEx = (name: string | undefined, id: string | number) => Inspector;
@@ -314,10 +317,38 @@ export function notebook(_files: ohq.File[] = [], _cells: CellFunc[] = [], { bas
314
317
  };
315
318
  return retVal;
316
319
  }
320
+ type NotebookFunc = ReturnType<typeof notebook>;
321
+
322
+ export function compileKit(notebook: Notebook): Definition[] {
323
+ const retVal: Definition[] = [];
324
+ for (const cell of notebook.cells) {
325
+ const compiled = transpile(cell);
326
+ retVal.push({
327
+ id: cell.id,
328
+ ...compiled,
329
+ body: constructFunction(compiled.body)
330
+ });
331
+ }
332
+ return retVal;
333
+ }
334
+
335
+ export function isNotebookKit(value: any): value is Notebook {
336
+ return !!value && Array.isArray(value.cells);
337
+ }
317
338
 
318
- export async function compile(notebookOrOjs: ohq.Notebook | string, { baseUrl = ".", importMode = "precompiled" }: CompileOptions = {}) {
319
- const ojsNotebook = typeof notebookOrOjs === "string" ? ojs2notebook(notebookOrOjs) : notebookOrOjs;
320
- const _cells: CellFunc[] = await Promise.all(ojsNotebook.nodes.map(n => createCell(n, { baseUrl, importMode })));
321
- return notebook(ojsNotebook.files, _cells, { baseUrl, importMode });
339
+ export function isOhqNotebook(value: any): value is ohq.Notebook {
340
+ return !!value && Array.isArray(value.nodes);
341
+ }
342
+ export async function compile(notebookOrOjs: Notebook): Promise<Definition[]>;
343
+ export async function compile(notebookOrOjs: ohq.Notebook, options?: CompileOptions): Promise<NotebookFunc>;
344
+ export async function compile(notebookOrOjs: string, options?: CompileOptions): Promise<NotebookFunc>;
345
+ export async function compile(notebookOrOjs: Notebook | ohq.Notebook | string, { baseUrl = ".", importMode = "precompiled" }: CompileOptions = {}) {
346
+ if (isNotebookKit(notebookOrOjs)) {
347
+ return compileKit(notebookOrOjs);
348
+ } else if (typeof notebookOrOjs === "string") {
349
+ notebookOrOjs = ojs2notebook(notebookOrOjs);
350
+ }
351
+ const _cells: CellFunc[] = await Promise.all(notebookOrOjs.nodes.map(n => createCell(n, { baseUrl, importMode })));
352
+ return notebook(notebookOrOjs.files, _cells, { baseUrl, importMode });
322
353
  }
323
- export type compileFunc = Awaited<ReturnType<typeof compile>>;
354
+ export type CompileFunc = Awaited<ReturnType<typeof compile>>;
@@ -0,0 +1,7 @@
1
+ import { JSDOM } from "jsdom";
2
+
3
+ const { window } = new JSDOM();
4
+ globalThis.document = window.document;
5
+ globalThis.DOMParser = window.DOMParser;
6
+
7
+ export * from "./index.ts";
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type { ohq } from "./observable-shim.ts";
2
2
 
3
3
  export * from "./compiler.ts";
4
- export { ojs2notebook, omd2notebook, download } from "./util.ts";
4
+ export { ojs2notebook, omd2notebook, omd2notebookKit, ojs2notebookKit, download, html2notebook, notebook2html } from "./util.ts";
5
5
  export * from "./writer.ts";
6
6
 
7
7
  import "../src/index.css";
package/src/util.ts CHANGED
@@ -1,18 +1,57 @@
1
+ import { type Notebook, type Cell, toCell, toNotebook, parseJavaScript, serialize, deserialize } from "@observablehq/notebook-kit";
2
+
1
3
  import type { ohq } from "./observable-shim.ts";
2
4
  import { parseCell, splitModule } from "./observable-shim.ts";
3
5
 
4
- const FuncTypes = {
5
- functionType: Object.getPrototypeOf(function () { }).constructor,
6
- asyncFunctionType: Object.getPrototypeOf(async function () { }).constructor,
7
- generatorFunctionType: Object.getPrototypeOf(function* () { }).constructor,
8
- asyncGeneratorFunctionType: Object.getPrototypeOf(async function* () { }).constructor
6
+ // Shared function constructor utilities to avoid duplication between util modules.
7
+
8
+ export type RegularFunction = (...args: any[]) => any;
9
+ interface RegularFunctionConstructor {
10
+ new(...args: string[]): RegularFunction;
11
+ (...args: string[]): RegularFunction;
12
+ readonly prototype: RegularFunction;
13
+ }
14
+
15
+ export type AsyncFunction = (...args: any[]) => Promise<any>;
16
+ interface AsyncFunctionConstructor {
17
+ new(...args: string[]): AsyncFunction;
18
+ (...args: string[]): AsyncFunction;
19
+ readonly prototype: AsyncFunction;
20
+ }
21
+
22
+ export type GeneratorFunction = (...args: any[]) => Generator<any, any, any>;
23
+ interface GeneratorFunctionConstructor {
24
+ new(...args: string[]): GeneratorFunction;
25
+ (...args: string[]): GeneratorFunction;
26
+ readonly prototype: GeneratorFunction;
27
+ }
28
+
29
+ export type AsyncGeneratorFunction = (...args: any[]) => AsyncGenerator<any, any, any>;
30
+ interface AsyncGeneratorFunctionConstructor {
31
+ new(...args: string[]): AsyncGeneratorFunction;
32
+ (...args: string[]): AsyncGeneratorFunction;
33
+ readonly prototype: AsyncGeneratorFunction;
34
+ }
35
+
36
+ export type AnyFunction = RegularFunction | AsyncFunction | GeneratorFunction | AsyncGeneratorFunction;
37
+
38
+ export const FunctionConstructors: {
39
+ regular: RegularFunctionConstructor;
40
+ async: AsyncFunctionConstructor;
41
+ generator: GeneratorFunctionConstructor;
42
+ asyncGenerator: AsyncGeneratorFunctionConstructor;
43
+ } = {
44
+ regular: Object.getPrototypeOf(function () { }).constructor as RegularFunctionConstructor,
45
+ async: Object.getPrototypeOf(async function () { }).constructor as AsyncFunctionConstructor,
46
+ generator: Object.getPrototypeOf(function* () { }).constructor as GeneratorFunctionConstructor,
47
+ asyncGenerator: Object.getPrototypeOf(async function* () { }).constructor as AsyncGeneratorFunctionConstructor,
9
48
  };
10
49
 
11
50
  function funcType(async: boolean = false, generator: boolean = false) {
12
- if (!async && !generator) return FuncTypes.functionType;
13
- if (async && !generator) return FuncTypes.asyncFunctionType;
14
- if (!async && generator) return FuncTypes.generatorFunctionType;
15
- return FuncTypes.asyncGeneratorFunctionType;
51
+ if (!async && !generator) return FunctionConstructors.regular;
52
+ if (async && !generator) return FunctionConstructors.async;
53
+ if (!async && generator) return FunctionConstructors.generator;
54
+ return FunctionConstructors.asyncGenerator;
16
55
  }
17
56
 
18
57
  interface Ref {
@@ -56,8 +95,9 @@ export const fixRelativeUrl = (path: string, basePath: string) => {
56
95
  };
57
96
 
58
97
  // Hide "import" from bundlers as they have a habit of replacing "import" with "require"
98
+ const obfuscatedImportFunction = new FunctionConstructors.async("url", "return import(url)");
59
99
  export async function obfuscatedImport(url: string) {
60
- return new FuncTypes.asyncFunctionType("url", "return import(url)")(url);
100
+ return obfuscatedImportFunction(url);
61
101
  }
62
102
 
63
103
  interface ParsedOJS {
@@ -141,6 +181,17 @@ export function ojs2notebook(ojs: string): ohq.Notebook {
141
181
  } as ohq.Notebook;
142
182
  }
143
183
 
184
+ export function ojs2notebookKit(ojs: string): Notebook {
185
+ const cells: Cell[] = splitModule(ojs).map((cell, idx) => {
186
+ return toCell({
187
+ id: idx,
188
+ mode: "ojs",
189
+ value: cell.text
190
+ });
191
+ });
192
+ return toNotebook({ cells });
193
+ }
194
+
144
195
  export function omd2notebook(omd: string): ohq.Notebook {
145
196
  const cells = splitOmd(omd);
146
197
  return {
@@ -157,6 +208,28 @@ export function omd2notebook(omd: string): ohq.Notebook {
157
208
  } as ohq.Notebook;
158
209
  }
159
210
 
211
+ export function omd2notebookKit(omd: string): Notebook {
212
+ const cells: Cell[] = [];
213
+ splitOmd(omd).forEach((cell) => {
214
+ if (!cell.inlineMD) {
215
+ splitModule(cell.ojs).forEach((subCell) => {
216
+ cells.push(toCell({
217
+ id: cells.length + 1,
218
+ mode: "ojs",
219
+ value: subCell.text
220
+ }));
221
+ });
222
+ } else {
223
+ cells.push(toCell({
224
+ id: cells.length + 1,
225
+ mode: "md",
226
+ value: cell.ojs
227
+ }));
228
+ }
229
+ });
230
+ return toNotebook({ cells });
231
+ }
232
+
160
233
  export function fetchEx(url: string, proxyPrefix = "https://api.codetabs.com/v1/proxy/?quest=", proxyPostfix = "") {
161
234
  const matches = url.match(/^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n?]+)/img);
162
235
  if (!matches || matches.length === 0) {
@@ -176,4 +249,40 @@ export function download(impUrl: string, proxyPrefix?: string, proxyPostfix?: st
176
249
  return fetchEx(impUrl.replace(`https://observablehq.com/${isShared ? "d/" : ""}`, "https://api.observablehq.com/document/"), proxyPrefix, proxyPostfix)
177
250
  .then(r => r.json())
178
251
  ;
179
- }
252
+ }
253
+
254
+ function _constructFunction(body, bodyStr: string) {
255
+ if (body.type !== "FunctionExpression" && body.type !== "FunctionDeclaration" && body.type !== "ArrowFunctionExpression") {
256
+ throw new Error(`Unsupported function type: ${body.type}`);
257
+ }
258
+ const func = body.async && body.generator ?
259
+ FunctionConstructors.asyncGenerator :
260
+ body.async ?
261
+ FunctionConstructors.async :
262
+ body.generator ?
263
+ FunctionConstructors.generator :
264
+ FunctionConstructors.regular;
265
+
266
+ const params = body.params?.map((param) => bodyStr.slice(param.start, param.end)).join(", ") ?? "";
267
+ const isBlock = body.body.type === "BlockStatement";
268
+ const { start, end } = body.body;
269
+ const inner = isBlock
270
+ ? bodyStr.slice(start + 1, end - 1)
271
+ : `return ${bodyStr.slice(start, end)}`;
272
+ return func(params, inner);
273
+ }
274
+
275
+ export function constructFunction(bodyStr: string) {
276
+ const { body } = parseJavaScript(bodyStr);
277
+ if (body.type === "Program") {
278
+ if (body.body.length !== 1) {
279
+ throw new Error(`Expected a single function, but found ${body.body.length} statements`);
280
+ }
281
+ return _constructFunction(body.body[0], bodyStr);
282
+ }
283
+ return _constructFunction(body, bodyStr);
284
+ }
285
+
286
+ export const html2notebook = (html: string): Notebook => deserialize(html);
287
+ export const notebook2html = (notebook: Notebook): string => serialize(notebook);
288
+
@@ -1,3 +1,5 @@
1
+ import { type Notebook } from "@observablehq/notebook-kit";
2
+ import { type Definition } from "@observablehq/notebook-kit/runtime";
1
3
  import { ohq } from "./observable-shim.ts";
2
4
  import { Writer } from "./writer.ts";
3
5
  export type InspectorFactoryEx = (name: string | undefined, id: string | number) => Inspector;
@@ -72,40 +74,12 @@ export declare function notebook(_files?: ohq.File[], _cells?: CellFunc[], { bas
72
74
  write(w: Writer): void;
73
75
  toString(w?: Writer): string;
74
76
  };
75
- export declare function compile(notebookOrOjs: ohq.Notebook | string, { baseUrl, importMode }?: CompileOptions): Promise<{
76
- (runtime: ohq.Runtime, inspector?: InspectorFactoryEx): ohq.Module;
77
- fileAttachments: Map<string, any>;
78
- cells: Map<string | number, {
79
- (runtime: ohq.Runtime, main: ohq.Module, inspector?: InspectorFactoryEx): void;
80
- id: string | number;
81
- modules: {
82
- (runtime: ohq.Runtime, main: ohq.Module, inspector?: InspectorFactoryEx): ohq.Module;
83
- importVariables: {
84
- (main: ohq.Module, otherModule: ohq.Module): void;
85
- delete(): void;
86
- }[];
87
- variables: {
88
- (module: ohq.Module, inspector?: InspectorFactoryEx): ohq.Variable;
89
- delete(): void;
90
- write(w: Writer): void;
91
- }[];
92
- delete(): void;
93
- write(w: Writer): void;
94
- }[];
95
- variables: {
96
- (module: ohq.Module, inspector?: InspectorFactoryEx): ohq.Variable;
97
- delete(): void;
98
- write(w: Writer): void;
99
- }[];
100
- delete(): void;
101
- write(w: Writer): void;
102
- }>;
103
- set(n: ohq.Node): Promise<CellFunc>;
104
- get(id: string | number): CellFunc | undefined;
105
- delete(id: string | number): boolean;
106
- clear(): void;
107
- write(w: Writer): void;
108
- toString(w?: Writer): string;
109
- }>;
110
- export type compileFunc = Awaited<ReturnType<typeof compile>>;
77
+ type NotebookFunc = ReturnType<typeof notebook>;
78
+ export declare function compileKit(notebook: Notebook): Definition[];
79
+ export declare function isNotebookKit(value: any): value is Notebook;
80
+ export declare function isOhqNotebook(value: any): value is ohq.Notebook;
81
+ export declare function compile(notebookOrOjs: Notebook): Promise<Definition[]>;
82
+ export declare function compile(notebookOrOjs: ohq.Notebook, options?: CompileOptions): Promise<NotebookFunc>;
83
+ export declare function compile(notebookOrOjs: string, options?: CompileOptions): Promise<NotebookFunc>;
84
+ export type CompileFunc = Awaited<ReturnType<typeof compile>>;
111
85
  export {};
package/types/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type { ohq } from "./observable-shim.ts";
2
2
  export * from "./compiler.ts";
3
- export { ojs2notebook, omd2notebook, download } from "./util.ts";
3
+ export { ojs2notebook, omd2notebook, omd2notebookKit, ojs2notebookKit, download, html2notebook, notebook2html } from "./util.ts";
4
4
  export * from "./writer.ts";
5
5
  import "../src/index.css";
package/types/util.d.ts CHANGED
@@ -1,4 +1,36 @@
1
+ import { type Notebook } from "@observablehq/notebook-kit";
1
2
  import type { ohq } from "./observable-shim.ts";
3
+ export type RegularFunction = (...args: any[]) => any;
4
+ interface RegularFunctionConstructor {
5
+ new (...args: string[]): RegularFunction;
6
+ (...args: string[]): RegularFunction;
7
+ readonly prototype: RegularFunction;
8
+ }
9
+ export type AsyncFunction = (...args: any[]) => Promise<any>;
10
+ interface AsyncFunctionConstructor {
11
+ new (...args: string[]): AsyncFunction;
12
+ (...args: string[]): AsyncFunction;
13
+ readonly prototype: AsyncFunction;
14
+ }
15
+ export type GeneratorFunction = (...args: any[]) => Generator<any, any, any>;
16
+ interface GeneratorFunctionConstructor {
17
+ new (...args: string[]): GeneratorFunction;
18
+ (...args: string[]): GeneratorFunction;
19
+ readonly prototype: GeneratorFunction;
20
+ }
21
+ export type AsyncGeneratorFunction = (...args: any[]) => AsyncGenerator<any, any, any>;
22
+ interface AsyncGeneratorFunctionConstructor {
23
+ new (...args: string[]): AsyncGeneratorFunction;
24
+ (...args: string[]): AsyncGeneratorFunction;
25
+ readonly prototype: AsyncGeneratorFunction;
26
+ }
27
+ export type AnyFunction = RegularFunction | AsyncFunction | GeneratorFunction | AsyncGeneratorFunction;
28
+ export declare const FunctionConstructors: {
29
+ regular: RegularFunctionConstructor;
30
+ async: AsyncFunctionConstructor;
31
+ generator: GeneratorFunctionConstructor;
32
+ asyncGenerator: AsyncGeneratorFunctionConstructor;
33
+ };
2
34
  interface Ref {
3
35
  start: number;
4
36
  end: number;
@@ -9,7 +41,7 @@ export interface Refs {
9
41
  args: string[];
10
42
  patches: Ref[];
11
43
  }
12
- export declare function createFunction(refs: Refs, async?: boolean, generator?: boolean, blockStatement?: boolean, body?: string): any;
44
+ export declare function createFunction(refs: Refs, async?: boolean, generator?: boolean, blockStatement?: boolean, body?: string): RegularFunction | undefined;
13
45
  export declare const isRelativePath: (path: string) => boolean;
14
46
  export declare const fixRelativeUrl: (path: string, basePath: string) => string;
15
47
  export declare function obfuscatedImport(url: string): Promise<any>;
@@ -23,7 +55,12 @@ interface ParsedOJS {
23
55
  export declare function encodeBacktick(str: string): string;
24
56
  export declare function notebook2ojs(_: string): ParsedOJS[];
25
57
  export declare function ojs2notebook(ojs: string): ohq.Notebook;
58
+ export declare function ojs2notebookKit(ojs: string): Notebook;
26
59
  export declare function omd2notebook(omd: string): ohq.Notebook;
60
+ export declare function omd2notebookKit(omd: string): Notebook;
27
61
  export declare function fetchEx(url: string, proxyPrefix?: string, proxyPostfix?: string): Promise<Response>;
28
62
  export declare function download(impUrl: string, proxyPrefix?: string, proxyPostfix?: string): Promise<ohq.Notebook>;
63
+ export declare function constructFunction(bodyStr: string): RegularFunction;
64
+ export declare const html2notebook: (html: string) => Notebook;
65
+ export declare const notebook2html: (notebook: Notebook) => string;
29
66
  export {};