@observablehq/notebook-kit 1.0.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.
Files changed (182) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +7 -0
  3. package/dist/bin/build.d.ts +2 -0
  4. package/dist/bin/build.js +63 -0
  5. package/dist/bin/download.d.ts +2 -0
  6. package/dist/bin/download.js +49 -0
  7. package/dist/bin/notebooks.d.ts +2 -0
  8. package/dist/bin/notebooks.js +33 -0
  9. package/dist/bin/preview.d.ts +2 -0
  10. package/dist/bin/preview.js +48 -0
  11. package/dist/package.json +73 -0
  12. package/dist/src/index.d.ts +5 -0
  13. package/dist/src/index.js +5 -0
  14. package/dist/src/javascript/assignments.d.ts +2 -0
  15. package/dist/src/javascript/assignments.js +37 -0
  16. package/dist/src/javascript/assignments.test.d.ts +1 -0
  17. package/dist/src/javascript/assignments.test.js +33 -0
  18. package/dist/src/javascript/awaits.d.ts +2 -0
  19. package/dist/src/javascript/awaits.js +23 -0
  20. package/dist/src/javascript/awaits.test.d.ts +1 -0
  21. package/dist/src/javascript/awaits.test.js +22 -0
  22. package/dist/src/javascript/declarations.d.ts +2 -0
  23. package/dist/src/javascript/declarations.js +45 -0
  24. package/dist/src/javascript/files.d.ts +3 -0
  25. package/dist/src/javascript/files.js +18 -0
  26. package/dist/src/javascript/globals.d.ts +1 -0
  27. package/dist/src/javascript/globals.js +86 -0
  28. package/dist/src/javascript/imports/jsr.d.ts +2 -0
  29. package/dist/src/javascript/imports/jsr.js +6 -0
  30. package/dist/src/javascript/imports/npm.d.ts +2 -0
  31. package/dist/src/javascript/imports/npm.js +47 -0
  32. package/dist/src/javascript/imports/npm.test.d.ts +1 -0
  33. package/dist/src/javascript/imports/npm.test.js +32 -0
  34. package/dist/src/javascript/imports/observable.d.ts +8 -0
  35. package/dist/src/javascript/imports/observable.js +64 -0
  36. package/dist/src/javascript/imports/observable.test.d.ts +1 -0
  37. package/dist/src/javascript/imports/observable.test.js +13 -0
  38. package/dist/src/javascript/imports.d.ts +21 -0
  39. package/dist/src/javascript/imports.js +146 -0
  40. package/dist/src/javascript/observable.d.ts +2 -0
  41. package/dist/src/javascript/observable.js +72 -0
  42. package/dist/src/javascript/parse.d.ts +11 -0
  43. package/dist/src/javascript/parse.js +53 -0
  44. package/dist/src/javascript/references.d.ts +8 -0
  45. package/dist/src/javascript/references.js +129 -0
  46. package/dist/src/javascript/references.test.d.ts +1 -0
  47. package/dist/src/javascript/references.test.js +38 -0
  48. package/dist/src/javascript/sourcemap.d.ts +21 -0
  49. package/dist/src/javascript/sourcemap.js +143 -0
  50. package/dist/src/javascript/sourcemap.test.d.ts +1 -0
  51. package/dist/src/javascript/sourcemap.test.js +88 -0
  52. package/dist/src/javascript/strings.d.ts +8 -0
  53. package/dist/src/javascript/strings.js +42 -0
  54. package/dist/src/javascript/strings.test.d.ts +1 -0
  55. package/dist/src/javascript/strings.test.js +31 -0
  56. package/dist/src/javascript/syntaxError.d.ts +2 -0
  57. package/dist/src/javascript/syntaxError.js +5 -0
  58. package/dist/src/javascript/template.d.ts +3 -0
  59. package/dist/src/javascript/template.js +141 -0
  60. package/dist/src/javascript/template.test.d.ts +1 -0
  61. package/dist/src/javascript/template.test.js +32 -0
  62. package/dist/src/javascript/transpile.d.ts +25 -0
  63. package/dist/src/javascript/transpile.js +42 -0
  64. package/dist/src/javascript/transpile.test.d.ts +1 -0
  65. package/dist/src/javascript/transpile.test.js +29 -0
  66. package/dist/src/javascript/walk.d.ts +5 -0
  67. package/dist/src/javascript/walk.js +13 -0
  68. package/dist/src/lib/notebook.d.ts +35 -0
  69. package/dist/src/lib/notebook.js +19 -0
  70. package/dist/src/lib/notebook.test.d.ts +1 -0
  71. package/dist/src/lib/notebook.test.js +26 -0
  72. package/dist/src/lib/serialize.d.ts +5 -0
  73. package/dist/src/lib/serialize.js +97 -0
  74. package/dist/src/lib/serialize.test.d.ts +1 -0
  75. package/dist/src/lib/serialize.test.js +125 -0
  76. package/dist/src/lib/text.d.ts +1 -0
  77. package/dist/src/lib/text.js +3 -0
  78. package/dist/src/runtime/define.d.ts +28 -0
  79. package/dist/src/runtime/define.js +62 -0
  80. package/dist/src/runtime/display.d.ts +16 -0
  81. package/dist/src/runtime/display.js +60 -0
  82. package/dist/src/runtime/index.d.ts +11 -0
  83. package/dist/src/runtime/index.js +14 -0
  84. package/dist/src/runtime/inspect.d.ts +3 -0
  85. package/dist/src/runtime/inspect.js +43 -0
  86. package/dist/src/runtime/stdlib/assets.d.ts +4 -0
  87. package/dist/src/runtime/stdlib/assets.js +110 -0
  88. package/dist/src/runtime/stdlib/assets.test.d.ts +1 -0
  89. package/dist/src/runtime/stdlib/assets.test.js +78 -0
  90. package/dist/src/runtime/stdlib/dom/canvas.d.ts +1 -0
  91. package/dist/src/runtime/stdlib/dom/canvas.js +6 -0
  92. package/dist/src/runtime/stdlib/dom/context2d.d.ts +1 -0
  93. package/dist/src/runtime/stdlib/dom/context2d.js +9 -0
  94. package/dist/src/runtime/stdlib/dom/index.d.ts +5 -0
  95. package/dist/src/runtime/stdlib/dom/index.js +5 -0
  96. package/dist/src/runtime/stdlib/dom/svg.d.ts +1 -0
  97. package/dist/src/runtime/stdlib/dom/svg.js +7 -0
  98. package/dist/src/runtime/stdlib/dom/text.d.ts +1 -0
  99. package/dist/src/runtime/stdlib/dom/text.js +3 -0
  100. package/dist/src/runtime/stdlib/dom/uid.d.ts +8 -0
  101. package/dist/src/runtime/stdlib/dom/uid.js +25 -0
  102. package/dist/src/runtime/stdlib/dot.d.ts +2 -0
  103. package/dist/src/runtime/stdlib/dot.js +34 -0
  104. package/dist/src/runtime/stdlib/duckdb.d.ts +24 -0
  105. package/dist/src/runtime/stdlib/duckdb.js +379 -0
  106. package/dist/src/runtime/stdlib/fileAttachment.d.ts +71 -0
  107. package/dist/src/runtime/stdlib/fileAttachment.js +199 -0
  108. package/dist/src/runtime/stdlib/generators/index.d.ts +5 -0
  109. package/dist/src/runtime/stdlib/generators/index.js +5 -0
  110. package/dist/src/runtime/stdlib/generators/input.d.ts +1 -0
  111. package/dist/src/runtime/stdlib/generators/input.js +45 -0
  112. package/dist/src/runtime/stdlib/generators/now.d.ts +1 -0
  113. package/dist/src/runtime/stdlib/generators/now.js +5 -0
  114. package/dist/src/runtime/stdlib/generators/observe.d.ts +1 -0
  115. package/dist/src/runtime/stdlib/generators/observe.js +31 -0
  116. package/dist/src/runtime/stdlib/generators/queue.d.ts +1 -0
  117. package/dist/src/runtime/stdlib/generators/queue.js +27 -0
  118. package/dist/src/runtime/stdlib/generators/width.d.ts +1 -0
  119. package/dist/src/runtime/stdlib/generators/width.js +13 -0
  120. package/dist/src/runtime/stdlib/highlight.d.ts +2 -0
  121. package/dist/src/runtime/stdlib/highlight.js +76 -0
  122. package/dist/src/runtime/stdlib/index.d.ts +56 -0
  123. package/dist/src/runtime/stdlib/index.js +23 -0
  124. package/dist/src/runtime/stdlib/inputs.css +15 -0
  125. package/dist/src/runtime/stdlib/inputs.d.ts +2 -0
  126. package/dist/src/runtime/stdlib/inputs.js +2 -0
  127. package/dist/src/runtime/stdlib/leaflet.d.ts +1 -0
  128. package/dist/src/runtime/stdlib/leaflet.js +7 -0
  129. package/dist/src/runtime/stdlib/mapboxgl.d.ts +1 -0
  130. package/dist/src/runtime/stdlib/mapboxgl.js +5 -0
  131. package/dist/src/runtime/stdlib/md.d.ts +5 -0
  132. package/dist/src/runtime/stdlib/md.js +72 -0
  133. package/dist/src/runtime/stdlib/mermaid.d.ts +2 -0
  134. package/dist/src/runtime/stdlib/mermaid.js +11 -0
  135. package/dist/src/runtime/stdlib/mutable.d.ts +8 -0
  136. package/dist/src/runtime/stdlib/mutable.js +30 -0
  137. package/dist/src/runtime/stdlib/observer.d.ts +16 -0
  138. package/dist/src/runtime/stdlib/observer.js +42 -0
  139. package/dist/src/runtime/stdlib/recommendedLibraries.d.ts +25 -0
  140. package/dist/src/runtime/stdlib/recommendedLibraries.js +26 -0
  141. package/dist/src/runtime/stdlib/require.d.ts +4 -0
  142. package/dist/src/runtime/stdlib/require.js +40 -0
  143. package/dist/src/runtime/stdlib/sampleDatasets.d.ts +12 -0
  144. package/dist/src/runtime/stdlib/sampleDatasets.js +31 -0
  145. package/dist/src/runtime/stdlib/sql.d.ts +5 -0
  146. package/dist/src/runtime/stdlib/sql.js +5 -0
  147. package/dist/src/runtime/stdlib/template.d.ts +7 -0
  148. package/dist/src/runtime/stdlib/template.js +2 -0
  149. package/dist/src/runtime/stdlib/tex.d.ts +7 -0
  150. package/dist/src/runtime/stdlib/tex.js +18 -0
  151. package/dist/src/runtime/stdlib/vega-lite.d.ts +1 -0
  152. package/dist/src/runtime/stdlib/vega-lite.js +4 -0
  153. package/dist/src/styles/abstract-dark.css +14 -0
  154. package/dist/src/styles/abstract-light.css +14 -0
  155. package/dist/src/styles/global.css +266 -0
  156. package/dist/src/styles/highlight.css +47 -0
  157. package/dist/src/styles/index.css +14 -0
  158. package/dist/src/styles/inspector.css +89 -0
  159. package/dist/src/styles/plot.css +7 -0
  160. package/dist/src/styles/syntax-dark.css +12 -0
  161. package/dist/src/styles/syntax-light.css +12 -0
  162. package/dist/src/styles/theme-air.css +7 -0
  163. package/dist/src/styles/theme-coffee.css +7 -0
  164. package/dist/src/styles/theme-cotton.css +7 -0
  165. package/dist/src/styles/theme-deep-space.css +16 -0
  166. package/dist/src/styles/theme-glacier.css +7 -0
  167. package/dist/src/styles/theme-ink.css +7 -0
  168. package/dist/src/styles/theme-midnight.css +7 -0
  169. package/dist/src/styles/theme-near-midnight.css +7 -0
  170. package/dist/src/styles/theme-ocean-floor.css +7 -0
  171. package/dist/src/styles/theme-parchment.css +7 -0
  172. package/dist/src/styles/theme-slate.css +7 -0
  173. package/dist/src/styles/theme-stark.css +16 -0
  174. package/dist/src/styles/theme-sun-faded.css +7 -0
  175. package/dist/src/templates/default.html +31 -0
  176. package/dist/src/vite/config.d.ts +2 -0
  177. package/dist/src/vite/config.js +30 -0
  178. package/dist/src/vite/index.d.ts +2 -0
  179. package/dist/src/vite/index.js +2 -0
  180. package/dist/src/vite/observable.d.ts +12 -0
  181. package/dist/src/vite/observable.js +176 -0
  182. package/package.json +73 -0
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2025 Observable, Inc.
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose
4
+ with or without fee is hereby granted, provided that the above copyright notice
5
+ and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
9
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
11
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
12
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
13
+ THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Observable Notebook Kit
2
+
3
+ **Observable Notebook Kit** is an open-source command-line tool for building static sites from Observable Notebooks based on an open file format. Notebook Kit also includes a Vite plugin and a low-level JavaScript interface for deep integration of Observable Notebooks with custom web applications.
4
+
5
+ Notebook Kit is available as part of [Notebooks 2.0 Technology Preview](https://observablehq.com/notebook-kit/), which includes [Observable Desktop](https://observablehq.com/notebook-kit/desktop), a notebook editor for macOS.
6
+
7
+ For more, [see the documentation](https://observablehq.com/notebook-kit/kit).
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export default function run(args?: string[]): Promise<void>;
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { build } from "vite";
4
+ import { config, observable } from "../src/vite/index.js";
5
+ if (process.argv[1] === import.meta.filename)
6
+ run();
7
+ export default async function run(args) {
8
+ const { values, positionals } = parseArgs({
9
+ args,
10
+ allowNegative: true,
11
+ allowPositionals: true,
12
+ options: {
13
+ out: {
14
+ type: "string",
15
+ short: "o",
16
+ default: ".observable/dist"
17
+ },
18
+ root: {
19
+ type: "string",
20
+ default: "."
21
+ },
22
+ base: {
23
+ type: "string",
24
+ default: "./"
25
+ },
26
+ template: {
27
+ type: "string"
28
+ },
29
+ empty: {
30
+ type: "boolean"
31
+ },
32
+ help: {
33
+ type: "boolean",
34
+ short: "h"
35
+ }
36
+ }
37
+ });
38
+ if (values.help) {
39
+ console.log(`usage: notebooks build [files]
40
+
41
+ --root <dir> path to the root directory; defaults to cwd
42
+ --template <path> path to the HTML template
43
+ -o, --out <dir> path to the output directory (relative to root)
44
+ --base <path> serving base path; defaults to ./
45
+ --empty whether to empty the output directory before building
46
+ -h, --help show this message
47
+ `);
48
+ return;
49
+ }
50
+ await build({
51
+ ...config(),
52
+ plugins: [observable({ template: values.template })],
53
+ root: values.root,
54
+ base: values.base,
55
+ build: {
56
+ outDir: values.out,
57
+ emptyOutDir: values.empty,
58
+ rollupOptions: {
59
+ input: positionals
60
+ }
61
+ }
62
+ });
63
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export default function run(args?: string[]): Promise<void>;
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { JSDOM } from "jsdom";
4
+ import { toNotebook } from "../src/lib/notebook.js";
5
+ import { serialize } from "../src/lib/serialize.js";
6
+ if (process.argv[1] === import.meta.filename)
7
+ run();
8
+ export default async function run(args) {
9
+ const { values, positionals } = parseArgs({
10
+ args,
11
+ allowPositionals: true,
12
+ options: {
13
+ help: {
14
+ type: "boolean",
15
+ short: "h"
16
+ }
17
+ }
18
+ });
19
+ if (positionals.length !== 1 && !values.help)
20
+ throw new Error("missing <url>");
21
+ if (values.help) {
22
+ console.log(`usage: notebooks download <url>
23
+
24
+ -h, --help show this message
25
+ `);
26
+ return;
27
+ }
28
+ const globalDocument = globalThis.document;
29
+ globalThis.document = new JSDOM().window.document;
30
+ try {
31
+ for (const positional of positionals) {
32
+ let url = new URL(positional, "https://observablehq.com");
33
+ if (url.origin === "https://observablehq.com") {
34
+ url = new URL(`/document${url.pathname.replace(/^\/d\//, "/")}`, "https://api.observablehq.com");
35
+ }
36
+ const response = await fetch(url);
37
+ if (!response.ok)
38
+ throw new Error(`unable to fetch: ${url}`);
39
+ const { title, nodes } = await response.json();
40
+ for (const node of nodes)
41
+ if (node.mode === "js")
42
+ node.mode = "ojs";
43
+ process.stdout.write(serialize(toNotebook({ title, cells: nodes })));
44
+ }
45
+ }
46
+ finally {
47
+ globalThis.document = globalDocument;
48
+ }
49
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ const [, , command] = process.argv;
3
+ switch (command) {
4
+ case "build": {
5
+ const { default: run } = await import("./build.js");
6
+ await run(process.argv.slice(3));
7
+ break;
8
+ }
9
+ case "download": {
10
+ const { default: run } = await import("./download.js");
11
+ await run(process.argv.slice(3));
12
+ break;
13
+ }
14
+ case "preview": {
15
+ const { default: run } = await import("./preview.js");
16
+ await run(process.argv.slice(3));
17
+ break;
18
+ }
19
+ default: {
20
+ console.log(`usage: notebooks <command>
21
+
22
+ preview start the preview server
23
+ build generate a static site
24
+ download download an Observable Notebook as HTML
25
+ help print usage information
26
+ version print the version
27
+ `);
28
+ if (command !== "help")
29
+ process.exit(1);
30
+ break;
31
+ }
32
+ }
33
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export default function run(args?: string[]): Promise<void>;
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { createServer } from "vite";
4
+ import { config, observable } from "../src/vite/index.js";
5
+ if (process.argv[1] === import.meta.filename)
6
+ run();
7
+ export default async function run(args) {
8
+ const { values } = parseArgs({
9
+ args,
10
+ allowNegative: true,
11
+ options: {
12
+ root: {
13
+ type: "string",
14
+ default: "."
15
+ },
16
+ base: {
17
+ type: "string",
18
+ default: "/"
19
+ },
20
+ template: {
21
+ type: "string"
22
+ },
23
+ help: {
24
+ type: "boolean",
25
+ short: "h"
26
+ }
27
+ }
28
+ });
29
+ if (values.help) {
30
+ console.log(`usage: notebooks preview
31
+
32
+ --root <dir> path to the root directory; defaults to cwd
33
+ --template <path> path to the HTML template
34
+ --base <path> serving base path; defaults to /
35
+ -h, --help show this message
36
+ `);
37
+ return;
38
+ }
39
+ const server = await createServer({
40
+ ...config(),
41
+ plugins: [observable({ template: values.template })],
42
+ root: values.root,
43
+ base: values.base
44
+ });
45
+ await server.listen();
46
+ server.printUrls();
47
+ server.bindCLIShortcuts({ print: true });
48
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@observablehq/notebook-kit",
3
+ "license": "ISC",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/observablehq/notebook-kit.git"
7
+ },
8
+ "version": "1.0.0",
9
+ "type": "module",
10
+ "scripts": {
11
+ "test": "vitest",
12
+ "prepublishOnly": "rm -rf dist && tsc && chmod +x dist/bin/*.js && cp -r src/styles src/templates dist/src && cp src/runtime/stdlib/*.css dist/src/runtime/stdlib",
13
+ "lint": "tsc --noEmit && eslint bin src types",
14
+ "notebooks": "tsx bin/notebooks.ts",
15
+ "download": "tsx bin/notebooks.ts download",
16
+ "docs:preview": "tsx --watch bin/notebooks.ts preview --root docs --template docs/observable.tmpl",
17
+ "docs:build": "tsx bin/notebooks.ts build --root docs --template docs/observable.tmpl -- $(find docs -path 'docs/.observable' -prune -o -name '*.html' -print)"
18
+ },
19
+ "bin": {
20
+ "notebooks": "dist/bin/notebooks.js"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/src/index.d.ts",
28
+ "import": "./dist/src/index.js"
29
+ },
30
+ "./runtime": {
31
+ "types": "./dist/src/runtime/index.d.ts",
32
+ "import": "./dist/src/runtime/index.js"
33
+ },
34
+ "./vite": {
35
+ "types": "./dist/src/vite/index.d.ts",
36
+ "import": "./dist/src/vite/index.js"
37
+ },
38
+ "./*.css": "./dist/src/styles/*.css"
39
+ },
40
+ "dependencies": {
41
+ "@fontsource/inter": "^5.2.6",
42
+ "@fontsource/source-serif-4": "^5.2.8",
43
+ "@fontsource/spline-sans-mono": "^5.2.6",
44
+ "@lezer/common": "^1.2.3",
45
+ "@lezer/css": "^1.2.1",
46
+ "@lezer/highlight": "^1.2.1",
47
+ "@lezer/html": "^1.3.10",
48
+ "@lezer/javascript": "^1.5.1",
49
+ "@lezer/markdown": "^1.4.3",
50
+ "@observablehq/inspector": "^5.0.1",
51
+ "@observablehq/parser": "^6.1.0",
52
+ "@observablehq/runtime": "^6.0.0",
53
+ "@sindresorhus/slugify": "^2.2.1",
54
+ "acorn": "^8.15.0",
55
+ "acorn-walk": "^8.3.4",
56
+ "markdown-it": "^14.1.0",
57
+ "markdown-it-anchor": "^9.2.0",
58
+ "vite": "^7.0.0"
59
+ },
60
+ "devDependencies": {
61
+ "@eslint/js": "^9.29.0",
62
+ "@types/jsdom": "^21.1.7",
63
+ "@types/markdown-it": "^14.1.2",
64
+ "eslint": "^9.29.0",
65
+ "globals": "^16.2.0",
66
+ "htl": "^0.3.1",
67
+ "jsdom": "^26.1.0",
68
+ "tsx": "^4.20.3",
69
+ "typescript": "^5.8.3",
70
+ "typescript-eslint": "^8.35.0",
71
+ "vitest": "^3.2.4"
72
+ }
73
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./javascript/parse.js";
2
+ export * from "./javascript/template.js";
3
+ export * from "./javascript/transpile.js";
4
+ export * from "./lib/notebook.js";
5
+ export * from "./lib/serialize.js";
@@ -0,0 +1,5 @@
1
+ export * from "./javascript/parse.js";
2
+ export * from "./javascript/template.js";
3
+ export * from "./javascript/transpile.js";
4
+ export * from "./lib/notebook.js";
5
+ export * from "./lib/serialize.js";
@@ -0,0 +1,2 @@
1
+ import type { Identifier, Node } from "acorn";
2
+ export declare function checkAssignments(node: Node, references: Identifier[], input: string): void;
@@ -0,0 +1,37 @@
1
+ import { defaultGlobals } from "./globals.js";
2
+ import { syntaxError } from "./syntaxError.js";
3
+ import { simple } from "./walk.js";
4
+ export function checkAssignments(node, references, input) {
5
+ function checkConst(node) {
6
+ switch (node.type) {
7
+ case "Identifier":
8
+ if (references.includes(node))
9
+ throw syntaxError(`Assignment to external variable '${node.name}'`, node, input);
10
+ if (defaultGlobals.has(node.name))
11
+ throw syntaxError(`Assignment to global '${node.name}'`, node, input);
12
+ break;
13
+ case "ObjectPattern":
14
+ node.properties.forEach((node) => checkConst(node.type === "Property" ? node.value : node));
15
+ break;
16
+ case "ArrayPattern":
17
+ node.elements.forEach((node) => node && checkConst(node));
18
+ break;
19
+ case "RestElement":
20
+ checkConst(node.argument);
21
+ break;
22
+ }
23
+ }
24
+ function checkConstLeft({ left }) {
25
+ checkConst(left);
26
+ }
27
+ function checkConstArgument({ argument }) {
28
+ checkConst(argument);
29
+ }
30
+ simple(node, {
31
+ AssignmentExpression: checkConstLeft,
32
+ AssignmentPattern: checkConstLeft,
33
+ UpdateExpression: checkConstArgument,
34
+ ForOfStatement: checkConstLeft,
35
+ ForInStatement: checkConstLeft
36
+ });
37
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ import { assert, test } from "vitest";
2
+ import { checkAssignments } from "./assignments.js";
3
+ import { parseJavaScript } from "./parse.js";
4
+ function check(input) {
5
+ const cell = parseJavaScript(input);
6
+ checkAssignments(cell.body, cell.references, input);
7
+ }
8
+ test("allows non-external assignments", () => {
9
+ assert.doesNotThrow(() => check("let foo = 1;\nfoo = 2;"));
10
+ assert.doesNotThrow(() => check("let foo = 1;\nfor (foo of []);"));
11
+ });
12
+ test("allows external references", () => {
13
+ assert.doesNotThrow(() => check("foo + 1;"));
14
+ });
15
+ test("does not allow external assignments", () => {
16
+ assert.throws(() => check("foo = 1;"), /external variable 'foo'/);
17
+ assert.throws(() => check("foo++;"), /external variable 'foo'/);
18
+ assert.throws(() => check("++foo;"), /external variable 'foo'/);
19
+ assert.throws(() => check("({foo} = {});"), /external variable 'foo'/);
20
+ assert.throws(() => check("({foo: bar} = {});"), /external variable 'bar'/);
21
+ assert.throws(() => check("([foo] = []);"), /external variable 'foo'/);
22
+ assert.throws(() => check("let foo = 1;\n({...bar} = {});"), /external variable 'bar'/);
23
+ assert.throws(() => check("let foo = 1;\n([...bar] = []);"), /external variable 'bar'/);
24
+ assert.throws(() => check("let foo = 1;\nbar = 1;"), /external variable 'bar'/);
25
+ assert.throws(() => check("function f() { foo = 1; }"), /external variable 'foo'/);
26
+ });
27
+ test("does not allow external assignments via for…of or for…in", () => {
28
+ assert.throws(() => check("for (foo of []);"), /external variable 'foo'/);
29
+ assert.throws(() => check("for (foo in {});"), /external variable 'foo'/);
30
+ });
31
+ test("does not allow global assignments", () => {
32
+ assert.throws(() => check("window = 1;"), /global 'window'/);
33
+ });
@@ -0,0 +1,2 @@
1
+ import type { Node } from "acorn";
2
+ export declare function findAwaits(node: Node): Node[];
@@ -0,0 +1,23 @@
1
+ import { recursive } from "./walk.js";
2
+ export function findAwaits(node) {
3
+ const nodes = [];
4
+ recursive(node, null, {
5
+ FunctionDeclaration() { },
6
+ FunctionExpression() { },
7
+ ArrowFunctionExpression() { },
8
+ ForOfStatement(node, state, callback) {
9
+ if (node.await)
10
+ nodes.push(node);
11
+ if (node.left)
12
+ callback(node.left, state);
13
+ if (node.right)
14
+ callback(node.right, state);
15
+ if (node.body)
16
+ callback(node.body, state);
17
+ },
18
+ AwaitExpression(node) {
19
+ nodes.push(node);
20
+ }
21
+ });
22
+ return nodes;
23
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ import { assert, expect, test } from "vitest";
2
+ import { findAwaits } from "./awaits.js";
3
+ import { parseJavaScript } from "./parse.js";
4
+ function find(input) {
5
+ return findAwaits(parseJavaScript(input).body);
6
+ }
7
+ test("finds top-level awaits", () => {
8
+ expect(find("await 1;")).toMatchSnapshot();
9
+ expect(find("(1, await 2);")).toMatchSnapshot();
10
+ expect(find("1 + await 2;")).toMatchSnapshot();
11
+ expect(find("if (true) { await 3; }")).toMatchSnapshot();
12
+ expect(find("for await (const f of []);")).toMatchSnapshot();
13
+ expect(find("for (const f of await []);")).toMatchSnapshot();
14
+ expect(find("let f, g; for ({[await f]: g} of await []);")).toMatchSnapshot();
15
+ expect(find("for (const f of []) await f;")).toMatchSnapshot();
16
+ expect(find("for (const f in await {});")).toMatchSnapshot();
17
+ });
18
+ test("ignores awaits within functions", () => {
19
+ assert.deepStrictEqual(find("async function f() { await 1; }"), []);
20
+ assert.deepStrictEqual(find("let f = (async function () { await 1; });"), []);
21
+ assert.deepStrictEqual(find("let f = (async () => { await 1; });"), []);
22
+ });
@@ -0,0 +1,2 @@
1
+ import type { Identifier, Program } from "acorn";
2
+ export declare function findDeclarations(node: Program, input: string): Identifier[];
@@ -0,0 +1,45 @@
1
+ import { defaultGlobals } from "./globals.js";
2
+ import { syntaxError } from "./syntaxError.js";
3
+ export function findDeclarations(node, input) {
4
+ const declarations = [];
5
+ function declareLocal(node) {
6
+ if (defaultGlobals.has(node.name) || node.name === "arguments") {
7
+ throw syntaxError(`Global '${node.name}' cannot be redefined`, node, input);
8
+ }
9
+ declarations.push(node);
10
+ }
11
+ function declarePattern(node) {
12
+ switch (node.type) {
13
+ case "Identifier":
14
+ declareLocal(node);
15
+ break;
16
+ case "ObjectPattern":
17
+ node.properties.forEach((node) => declarePattern(node.type === "Property" ? node.value : node));
18
+ break;
19
+ case "ArrayPattern":
20
+ node.elements.forEach((node) => node && declarePattern(node));
21
+ break;
22
+ case "RestElement":
23
+ declarePattern(node.argument);
24
+ break;
25
+ case "AssignmentPattern":
26
+ declarePattern(node.left);
27
+ break;
28
+ }
29
+ }
30
+ for (const child of node.body) {
31
+ switch (child.type) {
32
+ case "VariableDeclaration":
33
+ child.declarations.forEach((node) => declarePattern(node.id));
34
+ break;
35
+ case "ClassDeclaration":
36
+ case "FunctionDeclaration":
37
+ declareLocal(child.id);
38
+ break;
39
+ case "ImportDeclaration":
40
+ child.specifiers.forEach((node) => declareLocal(node.local));
41
+ break;
42
+ }
43
+ }
44
+ return declarations;
45
+ }
@@ -0,0 +1,3 @@
1
+ import type { Node } from "acorn";
2
+ import { Sourcemap } from "./sourcemap.js";
3
+ export declare function rewriteFileExpressions(output: Sourcemap, body: Node): void;
@@ -0,0 +1,18 @@
1
+ import { findReferences } from "./references.js";
2
+ import { simple } from "./walk.js";
3
+ export function rewriteFileExpressions(output, body) {
4
+ const files = new Set(findReferences(body, { filterReference: ({ name }) => name === "FileAttachment" }));
5
+ simple(body, {
6
+ CallExpression(node) {
7
+ const { callee } = node;
8
+ if (callee.type !== "Identifier" || !files.has(callee))
9
+ return;
10
+ const args = node.arguments;
11
+ if (args.length === 0)
12
+ return;
13
+ const [arg] = args;
14
+ output.insertLeft(arg.start, "new URL(");
15
+ output.insertRight(arg.end, ", import.meta.url).href");
16
+ }
17
+ });
18
+ }
@@ -0,0 +1 @@
1
+ export declare const defaultGlobals: Set<string>;
@@ -0,0 +1,86 @@
1
+ export const defaultGlobals = new Set([
2
+ "Array",
3
+ "ArrayBuffer",
4
+ "atob",
5
+ "AudioContext",
6
+ "Blob",
7
+ "Boolean",
8
+ "BigInt",
9
+ "btoa",
10
+ "clearInterval",
11
+ "clearTimeout",
12
+ "console",
13
+ "crypto",
14
+ "CustomEvent",
15
+ "DataView",
16
+ "Date",
17
+ "decodeURI",
18
+ "decodeURIComponent",
19
+ "devicePixelRatio",
20
+ "document",
21
+ "encodeURI",
22
+ "encodeURIComponent",
23
+ "Error",
24
+ "escape",
25
+ "eval",
26
+ "fetch",
27
+ "File",
28
+ "FileList",
29
+ "FileReader",
30
+ "Float32Array",
31
+ "Float64Array",
32
+ "Function",
33
+ "Headers",
34
+ "Image",
35
+ "ImageData",
36
+ "Infinity",
37
+ "Int16Array",
38
+ "Int32Array",
39
+ "Int8Array",
40
+ "Intl",
41
+ "isFinite",
42
+ "isNaN",
43
+ "JSON",
44
+ "Map",
45
+ "Math",
46
+ "NaN",
47
+ "Number",
48
+ "navigator",
49
+ "Object",
50
+ "observable", // for observable.params.foo
51
+ "parseFloat",
52
+ "parseInt",
53
+ "performance",
54
+ "Path2D",
55
+ "Promise",
56
+ "Proxy",
57
+ "RangeError",
58
+ "ReferenceError",
59
+ "Reflect",
60
+ "RegExp",
61
+ "cancelAnimationFrame",
62
+ "requestAnimationFrame",
63
+ "Set",
64
+ "setInterval",
65
+ "setTimeout",
66
+ "String",
67
+ "Symbol",
68
+ "SyntaxError",
69
+ "TextDecoder",
70
+ "TextEncoder",
71
+ "this",
72
+ "TypeError",
73
+ "Uint16Array",
74
+ "Uint32Array",
75
+ "Uint8Array",
76
+ "Uint8ClampedArray",
77
+ "undefined",
78
+ "unescape",
79
+ "URIError",
80
+ "URL",
81
+ "WeakMap",
82
+ "WeakSet",
83
+ "WebSocket",
84
+ "Worker",
85
+ "window"
86
+ ]);
@@ -0,0 +1,2 @@
1
+ /** If specifier is an jsr: protocol import, resolves it. */
2
+ export declare function resolveJsrImport(specifier: string): string;
@@ -0,0 +1,6 @@
1
+ /** If specifier is an jsr: protocol import, resolves it. */
2
+ export function resolveJsrImport(specifier) {
3
+ if (!specifier.startsWith("jsr:"))
4
+ return specifier;
5
+ return `https://esm.sh/jsr/${specifier.slice(4)}`;
6
+ }
@@ -0,0 +1,2 @@
1
+ /** If specifier is an npm: protocol import, resolves it. */
2
+ export declare function resolveNpmImport(specifier: string): string;