@hpcc-js/observablehq-compiler 1.1.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/README.md +106 -0
- package/bin/ojscc.mjs +75 -0
- package/dist/index.css +1 -0
- package/dist/index.esm.css +1 -0
- package/dist/index.esm.js +7168 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +7176 -0
- package/dist/index.js.map +1 -0
- package/package.json +80 -0
- package/src/__package__.ts +3 -0
- package/src/__tests__/File Attachments.ts +895 -0
- package/src/__tests__/Introduction to Imports.ts +749 -0
- package/src/__tests__/Observable TimeChart.ts +772 -0
- package/src/__tests__/index.ts +13 -0
- package/src/__tests__/node.ts +177 -0
- package/src/__tests__/tsconfig.json +21 -0
- package/src/compiler.md +234 -0
- package/src/compiler.ts +264 -0
- package/src/cst.ts +172 -0
- package/src/index.css +460 -0
- package/src/index.ts +7 -0
- package/src/util.md +113 -0
- package/src/util.ts +154 -0
- package/src/writer.ts +80 -0
- package/types/__package__.d.ts +4 -0
- package/types/__package__.d.ts.map +1 -0
- package/types/__tests__/File Attachments.d.ts +110 -0
- package/types/__tests__/File Attachments.d.ts.map +1 -0
- package/types/__tests__/Introduction to Imports.d.ts +120 -0
- package/types/__tests__/Introduction to Imports.d.ts.map +1 -0
- package/types/__tests__/Observable TimeChart.d.ts +111 -0
- package/types/__tests__/Observable TimeChart.d.ts.map +1 -0
- package/types/__tests__/index.d.ts +2 -0
- package/types/__tests__/index.d.ts.map +1 -0
- package/types/__tests__/node.d.ts +2 -0
- package/types/__tests__/node.d.ts.map +1 -0
- package/types/compiler.d.ts +88 -0
- package/types/compiler.d.ts.map +1 -0
- package/types/cst.d.ts +42 -0
- package/types/cst.d.ts.map +1 -0
- package/types/index.d.ts +6 -0
- package/types/index.d.ts.map +1 -0
- package/types/util.d.ts +26 -0
- package/types/util.d.ts.map +1 -0
- package/types/writer.d.ts +19 -0
- package/types/writer.d.ts.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# @hpcc-js/observablehq-compiler
|
|
2
|
+
|
|
3
|
+
An unofficial compiler, interpreter and download tool for [Observable HQ](https://observablehq.com/) notebooks.
|
|
4
|
+
|
|
5
|
+
* [Quick Start](#quick-start)
|
|
6
|
+
* [Compiler](./src/compiler)
|
|
7
|
+
* [Utilities](./src/util)
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
This library contains a command line tool (`ojscc`) for downloading and compiling notebooks and an interpreter for rendering notebooks in the browser:
|
|
12
|
+
* [Command line interface](#command-line-interface)
|
|
13
|
+
* [JS Interpreter](#js-interpreter)
|
|
14
|
+
|
|
15
|
+
## Command line interface
|
|
16
|
+
|
|
17
|
+
To call `ojscc` without installing:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npx -p @hpcc-js/observablehq-compiler ojscc [download | compile] ...
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
To install `ojscc` as a global command:
|
|
24
|
+
```sh
|
|
25
|
+
npm install --global @hpcc-js/observablehq-compiler
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Then it can be called by:
|
|
29
|
+
```sh
|
|
30
|
+
ojscc [download | compile] ...
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Usage:
|
|
34
|
+
|
|
35
|
+
General:
|
|
36
|
+
```sh
|
|
37
|
+
ojscc [command]
|
|
38
|
+
|
|
39
|
+
Commands:
|
|
40
|
+
ojscc download Download ObservableHQ Notebook
|
|
41
|
+
ojscc compile Compile ObservableHQ Notebook
|
|
42
|
+
|
|
43
|
+
Options:
|
|
44
|
+
--version Show version number [boolean]
|
|
45
|
+
-h, --help Show help [boolean]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Download:
|
|
49
|
+
```sh
|
|
50
|
+
ohqcc download [-o myfile.ojsnb] https://observablehq.com/@user/notebook
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
--version Show version number [boolean]
|
|
54
|
+
-h, --help Show help [boolean]
|
|
55
|
+
-o, --output Optional output file path
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Compile:
|
|
59
|
+
```sh
|
|
60
|
+
ohqcc compile [-o myfile.js] myfile.ojsnb
|
|
61
|
+
|
|
62
|
+
Options:
|
|
63
|
+
--version Show version number [boolean]
|
|
64
|
+
-h, --help Show help [boolean]
|
|
65
|
+
-o, --output Optional output file path
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## JS Interpreter
|
|
69
|
+
|
|
70
|
+
To install with npm :
|
|
71
|
+
```
|
|
72
|
+
npm install --save @hpcc-js/observablehq-compiler
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The interpreter is 100% compatible with:
|
|
76
|
+
* [ObservableHQ Runtime](https://github.com/observablehq/runtime)
|
|
77
|
+
* [ObservableHQ Inspector](https://github.com/observablehq/inspector)
|
|
78
|
+
* [ObservableHQ Library](https://github.com/observablehq/library)
|
|
79
|
+
|
|
80
|
+
It also supports fetching notebooks directly from the ObservableHQ repository.
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import { Library, Runtime, Inspector } from "@observablehq/runtime";
|
|
84
|
+
import { download, compile } from "@hpcc-js/observablehq-compiler";
|
|
85
|
+
|
|
86
|
+
const placeholder = document.getElementById("placeholder");
|
|
87
|
+
|
|
88
|
+
const ohqnb = await download("https://observablehq.com/@observablehq/summary-table");
|
|
89
|
+
const compiledNB = await compile(ohqnb);
|
|
90
|
+
|
|
91
|
+
const library = new Library();
|
|
92
|
+
const runtime = new Runtime(library);
|
|
93
|
+
compiledNB(runtime, name => {
|
|
94
|
+
const div = document.createElement("div");
|
|
95
|
+
placeholder.appendChild(div);
|
|
96
|
+
return new Inspector(div);
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Which produces (screenshot):
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+

|
|
105
|
+
|
|
106
|
+
---
|
package/bin/ojscc.mjs
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-undef */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
4
|
+
|
|
5
|
+
import fetch, { Blob, blobFrom, blobFromSync, File, fileFrom, fileFromSync, FormData, Headers, Request, Response } from "node-fetch";
|
|
6
|
+
if (!globalThis.fetch) {
|
|
7
|
+
globalThis.fetch = fetch;
|
|
8
|
+
globalThis.Headers = Headers;
|
|
9
|
+
globalThis.Request = Request;
|
|
10
|
+
globalThis.Response = Response;
|
|
11
|
+
}
|
|
12
|
+
import { promises as fs } from "fs";
|
|
13
|
+
import { compile, download, Writer } from "../dist/index.js";
|
|
14
|
+
import yargsMode from "yargs/yargs";
|
|
15
|
+
|
|
16
|
+
async function doDownload(url, filePath) {
|
|
17
|
+
const nb = await download(url);
|
|
18
|
+
if (filePath) {
|
|
19
|
+
fs.writeFile(filePath, JSON.stringify(nb, undefined, 4));
|
|
20
|
+
} else {
|
|
21
|
+
console.info(nb);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function doCompile(url, filePath) {
|
|
26
|
+
const nb = await download(url);
|
|
27
|
+
const define = await compile(nb, process.cwd());
|
|
28
|
+
const w = new Writer();
|
|
29
|
+
define.write(w);
|
|
30
|
+
if (filePath) {
|
|
31
|
+
fs.writeFile(filePath, w.toString());
|
|
32
|
+
} else {
|
|
33
|
+
console.info(w.toString());
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const yargs = yargsMode(process.argv.slice(2));
|
|
38
|
+
yargs
|
|
39
|
+
.scriptName("ojscc")
|
|
40
|
+
.wrap(Math.min(90, yargs.terminalWidth()))
|
|
41
|
+
.command("download", "Download ObservableHQ Notebook",
|
|
42
|
+
function (yargs) {
|
|
43
|
+
return yargs
|
|
44
|
+
.usage("ohqcc download [-o myfile.ojsnb] https://observablehq.com/@user/notebook")
|
|
45
|
+
.demandCommand(1, "URL required")
|
|
46
|
+
.option("o", {
|
|
47
|
+
alias: "output",
|
|
48
|
+
describe: "Optional output file path"
|
|
49
|
+
})
|
|
50
|
+
;
|
|
51
|
+
}, function (argv) {
|
|
52
|
+
doDownload(argv._[1], argv.o);
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
.command("compile", "Compile ObservableHQ Notebook",
|
|
56
|
+
function (yargs) {
|
|
57
|
+
return yargs
|
|
58
|
+
.usage("ohqcc compile [-o myfile.js] myfile.ojsnb")
|
|
59
|
+
.demandCommand(1, "URL required")
|
|
60
|
+
.option("o", {
|
|
61
|
+
alias: "output",
|
|
62
|
+
describe: "Optional output file path"
|
|
63
|
+
})
|
|
64
|
+
;
|
|
65
|
+
},
|
|
66
|
+
async function (argv) {
|
|
67
|
+
doCompile(argv._[1], argv.o);
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
.help("h")
|
|
71
|
+
.alias("h", "help")
|
|
72
|
+
.epilog("https://github.com/hpcc-systems/Visualization/tree/trunk/packages/observablehq-compiler")
|
|
73
|
+
;
|
|
74
|
+
|
|
75
|
+
yargs.argv;
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Source+Serif+Pro:ital,wght@0,400;0,600;0,700;1,400;1,600;1,700&display=swap");:root{--syntax-normal:#1b1e23;--syntax-comment:#828282;--syntax-number:#20a5ba;--syntax-keyword:#c30771;--syntax-atom:#10a778;--syntax-string:#008ec4;--syntax-error:#ffbedc;--syntax-unknown-variable:#838383;--syntax-known-variable:#005f87;--syntax-matchbracket:#20bbfc;--syntax-key:#6636b4;--mono-fonts:82%/1.5 Menlo,Consolas,monospace}.observablehq--collapsed,.observablehq--expanded,.observablehq--function,.observablehq--gray,.observablehq--import,.observablehq--string:after,.observablehq--string:before{color:var(--syntax-normal)}.observablehq--collapsed,.observablehq--expanded.observablehq--inspect a{cursor:pointer}.observablehq--field{margin-left:1em;text-indent:-1em}.observablehq--empty{color:var(--syntax_comment)}.observablehq--blue,.observablehq--keyword,a[href]{color:#3182bd}.hljs-deletion,.hljs-variable,.observablehq--forbidden,.observablehq--pink{color:#e377c2}.observablehq--orange{color:#e6550d}.hljs-literal,.observablehq--boolean,.observablehq--null,.observablehq--undefined{color:var(--syntax-atom)}.hljs-bullet,.hljs-link,.hljs-number,.hljs-regexp,.observablehq--bigint,.observablehq--date,.observablehq--green,.observablehq--number,.observablehq--regexp,.observablehq--symbol{color:var(--syntax-number)}.observablehq--index,.observablehq--key{color:var(--syntax-key)}.observablehq--prototype-key{color:#aaa}.observablehq--empty{font-style:oblique}.hljs-addition,.hljs-meta,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.observablehq--purple,.observablehq--string{color:var(--syntax-string)}.observablehq--error,.observablehq--red{color:#e7040f}.observablehq--inspect,.observablehq:empty:after,.observablehq>link:only-child,.observablehq>style:only-child{display:block;font:var(--monospace-font);overflow-x:auto;padding:4px 0;white-space:pre}.observablehq--error .observablehq--inspect{white-space:pre-wrap;word-break:break-all}:root{--syntax-diff:#24292e;--syntax-diff-bg:#fff;--hr:rgba(0,0,0,.05);--monospace:Menlo,Consolas,monospace;--monospace-font:14px/1.5 var(--monospace);--serif:"Source Serif Pro","Iowan Old Style","Apple Garamond","Palatino Linotype","Times New Roman","Droid Serif",Times,serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--sans-serif:-apple-system,BlinkMacSystemFont,"avenir next",avenir,helvetica,"helvetica neue",ubuntu,roboto,noto,"segoe ui",arial,sans-serif}html{-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#1b1e23;font:17px/1.5 var(--serif)}body{margin:0 14px}body.fullscreen{margin:0}h1,h2,h3,h4,h5,h6{color:#333;font-weight:700;line-height:1.15;margin-bottom:.25rem;margin-top:0}h2~p,h2~table,h3~p,h3~table,h4~p,h4~table{margin-top:0}.observablehq:first-of-type h1+h2{font-size:20px;font-style:italic;font-weight:400;margin-bottom:1rem}a[href]{text-decoration:none}a[href]:hover{text-decoration:underline}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{font-size:90%}code,pre,tt{font-family:var(--monospace);font-size:14px;line-height:1.5}img{max-width:calc(100vw - 28px)}.katex-display,figcaption,figure,h1,h2,h3,h4,h5,h6,p,table{max-width:640px}blockquote,ol,ul{max-width:600px}blockquote{margin:1rem 1.5rem}ol,ul{padding-left:28px}hr{background:no-repeat 50%/100% 1px linear-gradient(to right,var(--hr),var(--hr));border:none;height:1px;margin:1rem 0;padding:1rem 0}pre{padding:2px 0}.observablehq--md-pre{overflow-x:auto}input:not([type]),input[type=email],input[type=number],input[type=password],input[type=range],input[type=search],input[type=tel],input[type=text],input[type=url]{width:240px}button,canvas,input{vertical-align:middle}button,input,textarea{accent-color:#3b5fc0}table{border-collapse:collapse;font:13px/1.2 var(--sans-serif);width:100%}table code,table pre,table tt{font-size:inherit;line-height:inherit}td>pre:only-child,th>pre:only-child{margin:0;padding:0}th{color:#111;text-align:left;vertical-align:bottom}td{color:#444;vertical-align:top}td,th{padding:3px 6.5px 3px 0}td:last-child,th:last-child{padding-right:0}tr:not(:last-child){border-bottom:1px solid #eee}thead tr{border-bottom:1px solid #ccc}figure,table{margin:1rem 0}figure img{max-width:100%}figcaption{color:var(--syntax-unknown-variable);font:small var(--sans-serif)}.observablehq--caret{margin-right:4px;vertical-align:baseline}.observablehq--field{margin-left:1rem;text-indent:-1rem}.hljs-comment,.observablehq--empty,.observablehq--prototype-key{color:var(--syntax-comment)}.hljs-built_in{color:var(--syntax-known-variable)}.observablehq--unknown{color:var(--syntax-unknown-variable)}.hljs-doctag,.hljs-keyword,.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-selector-tag,.hljs-strong,.hljs-tag,.hljs-type{color:var(--syntax-keyword)}.observablehq{margin:17px 0;min-height:1.5rem;position:relative}.observablehq:before{bottom:1px;content:"";left:-14px;position:absolute;top:0;transition:background-color .25s linear;width:4px}.observablehq--changed:before,.observablehq--running:before{background-color:#a9b0bc;transition:none}.observablehq--error:before{background-color:#e7040f}.observablehq:not(.observablehq--running):empty:after{color:var(--syntax-comment);content:"<detached>";font-style:oblique}.observablehq>link:only-child,.observablehq>style:only-child{color:var(--syntax-keyword);visibility:hidden;white-space:nowrap}.observablehq>link:only-child:before{content:"<link>";pointer-events:none;text-decoration:none;visibility:visible}.observablehq>style:only-child:before{content:"<style>";visibility:visible}.observablehq--inspect.observablehq--import{white-space:normal}.observablehq--inspect::-webkit-scrollbar{display:none}.observablehq--string-expand{background:#eee;border-radius:2px;color:var(--syntax-normal);cursor:pointer;font-size:80%;margin-left:6px;padding:2px 6px;position:sticky;right:0;vertical-align:middle}.observablehq--string-expand:active,.observablehq--string-expand:hover{background:#ddd}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Source+Serif+Pro:ital,wght@0,400;0,600;0,700;1,400;1,600;1,700&display=swap");:root{--syntax-normal:#1b1e23;--syntax-comment:#828282;--syntax-number:#20a5ba;--syntax-keyword:#c30771;--syntax-atom:#10a778;--syntax-string:#008ec4;--syntax-error:#ffbedc;--syntax-unknown-variable:#838383;--syntax-known-variable:#005f87;--syntax-matchbracket:#20bbfc;--syntax-key:#6636b4;--mono-fonts:82%/1.5 Menlo,Consolas,monospace}.observablehq--collapsed,.observablehq--expanded,.observablehq--function,.observablehq--gray,.observablehq--import,.observablehq--string:after,.observablehq--string:before{color:var(--syntax-normal)}.observablehq--collapsed,.observablehq--expanded.observablehq--inspect a{cursor:pointer}.observablehq--field{margin-left:1em;text-indent:-1em}.observablehq--empty{color:var(--syntax_comment)}.observablehq--blue,.observablehq--keyword,a[href]{color:#3182bd}.hljs-deletion,.hljs-variable,.observablehq--forbidden,.observablehq--pink{color:#e377c2}.observablehq--orange{color:#e6550d}.hljs-literal,.observablehq--boolean,.observablehq--null,.observablehq--undefined{color:var(--syntax-atom)}.hljs-bullet,.hljs-link,.hljs-number,.hljs-regexp,.observablehq--bigint,.observablehq--date,.observablehq--green,.observablehq--number,.observablehq--regexp,.observablehq--symbol{color:var(--syntax-number)}.observablehq--index,.observablehq--key{color:var(--syntax-key)}.observablehq--prototype-key{color:#aaa}.observablehq--empty{font-style:oblique}.hljs-addition,.hljs-meta,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.observablehq--purple,.observablehq--string{color:var(--syntax-string)}.observablehq--error,.observablehq--red{color:#e7040f}.observablehq--inspect,.observablehq:empty:after,.observablehq>link:only-child,.observablehq>style:only-child{display:block;font:var(--monospace-font);overflow-x:auto;padding:4px 0;white-space:pre}.observablehq--error .observablehq--inspect{white-space:pre-wrap;word-break:break-all}:root{--syntax-diff:#24292e;--syntax-diff-bg:#fff;--hr:rgba(0,0,0,.05);--monospace:Menlo,Consolas,monospace;--monospace-font:14px/1.5 var(--monospace);--serif:"Source Serif Pro","Iowan Old Style","Apple Garamond","Palatino Linotype","Times New Roman","Droid Serif",Times,serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--sans-serif:-apple-system,BlinkMacSystemFont,"avenir next",avenir,helvetica,"helvetica neue",ubuntu,roboto,noto,"segoe ui",arial,sans-serif}html{-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#1b1e23;font:17px/1.5 var(--serif)}body{margin:0 14px}body.fullscreen{margin:0}h1,h2,h3,h4,h5,h6{color:#333;font-weight:700;line-height:1.15;margin-bottom:.25rem;margin-top:0}h2~p,h2~table,h3~p,h3~table,h4~p,h4~table{margin-top:0}.observablehq:first-of-type h1+h2{font-size:20px;font-style:italic;font-weight:400;margin-bottom:1rem}a[href]{text-decoration:none}a[href]:hover{text-decoration:underline}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{font-size:90%}code,pre,tt{font-family:var(--monospace);font-size:14px;line-height:1.5}img{max-width:calc(100vw - 28px)}.katex-display,figcaption,figure,h1,h2,h3,h4,h5,h6,p,table{max-width:640px}blockquote,ol,ul{max-width:600px}blockquote{margin:1rem 1.5rem}ol,ul{padding-left:28px}hr{background:no-repeat 50%/100% 1px linear-gradient(to right,var(--hr),var(--hr));border:none;height:1px;margin:1rem 0;padding:1rem 0}pre{padding:2px 0}.observablehq--md-pre{overflow-x:auto}input:not([type]),input[type=email],input[type=number],input[type=password],input[type=range],input[type=search],input[type=tel],input[type=text],input[type=url]{width:240px}button,canvas,input{vertical-align:middle}button,input,textarea{accent-color:#3b5fc0}table{border-collapse:collapse;font:13px/1.2 var(--sans-serif);width:100%}table code,table pre,table tt{font-size:inherit;line-height:inherit}td>pre:only-child,th>pre:only-child{margin:0;padding:0}th{color:#111;text-align:left;vertical-align:bottom}td{color:#444;vertical-align:top}td,th{padding:3px 6.5px 3px 0}td:last-child,th:last-child{padding-right:0}tr:not(:last-child){border-bottom:1px solid #eee}thead tr{border-bottom:1px solid #ccc}figure,table{margin:1rem 0}figure img{max-width:100%}figcaption{color:var(--syntax-unknown-variable);font:small var(--sans-serif)}.observablehq--caret{margin-right:4px;vertical-align:baseline}.observablehq--field{margin-left:1rem;text-indent:-1rem}.hljs-comment,.observablehq--empty,.observablehq--prototype-key{color:var(--syntax-comment)}.hljs-built_in{color:var(--syntax-known-variable)}.observablehq--unknown{color:var(--syntax-unknown-variable)}.hljs-doctag,.hljs-keyword,.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-selector-tag,.hljs-strong,.hljs-tag,.hljs-type{color:var(--syntax-keyword)}.observablehq{margin:17px 0;min-height:1.5rem;position:relative}.observablehq:before{bottom:1px;content:"";left:-14px;position:absolute;top:0;transition:background-color .25s linear;width:4px}.observablehq--changed:before,.observablehq--running:before{background-color:#a9b0bc;transition:none}.observablehq--error:before{background-color:#e7040f}.observablehq:not(.observablehq--running):empty:after{color:var(--syntax-comment);content:"<detached>";font-style:oblique}.observablehq>link:only-child,.observablehq>style:only-child{color:var(--syntax-keyword);visibility:hidden;white-space:nowrap}.observablehq>link:only-child:before{content:"<link>";pointer-events:none;text-decoration:none;visibility:visible}.observablehq>style:only-child:before{content:"<style>";visibility:visible}.observablehq--inspect.observablehq--import{white-space:normal}.observablehq--inspect::-webkit-scrollbar{display:none}.observablehq--string-expand{background:#eee;border-radius:2px;color:var(--syntax-normal);cursor:pointer;font-size:80%;margin-left:6px;padding:2px 6px;position:sticky;right:0;vertical-align:middle}.observablehq--string-expand:active,.observablehq--string-expand:hover{background:#ddd}
|