|
| 1 | +<!doctype html> |
| 2 | +<notebook theme="slate"> |
| 3 | + <title>Observable Notebooks 2.0 System guide</title> |
| 4 | + <script id="1" type="text/markdown"> |
| 5 | + # Observable Notebooks 2.0 <span style="color: var(--theme-foreground-faint);">System guide</span> |
| 6 | + |
| 7 | + <link rel="stylesheet" href="./style.css"> |
| 8 | + |
| 9 | + <style> |
| 10 | + |
| 11 | + figure img { |
| 12 | + border-radius: 6px; |
| 13 | + } |
| 14 | + |
| 15 | + .sans { |
| 16 | + font-family: var(--sans-serif); |
| 17 | + } |
| 18 | + |
| 19 | + </style> |
| 20 | + </script> |
| 21 | + <script id="38" type="text/markdown"> |
| 22 | + <aside>This document is itself a notebook, and this paragraph is a Markdown cell.</aside> |
| 23 | + |
| 24 | + Notebooks are interactive documents comprised of small programs called _cells_. Cells can be written in JavaScript, Markdown, HTML, and other languages. Most logic is coded in JavaScript, while prose is typically written in Markdown. |
| 25 | + </script> |
| 26 | + <script id="41" type="module" pinned=""> |
| 27 | + const language = "JavaScript"; |
| 28 | + |
| 29 | + display(`This cell is ${language}.`); |
| 30 | + </script> |
| 31 | + <script id="42" type="text/markdown" pinned=""> |
| 32 | + This cell is _Markdown_. |
| 33 | + </script> |
| 34 | + <script id="43" type="text/html" pinned=""> |
| 35 | + And this cell is <i>HTML</i>. |
| 36 | + </script> |
| 37 | + <script id="47" type="text/markdown"> |
| 38 | + Notebooks are live: code runs when you load the notebook, showing the latest output. A saved notebook only stores cells' source code, not its output. (Though you can capture and store additional data in file attachments.) |
| 39 | + </script> |
| 40 | + <script id="48" type="text/markdown" pinned=""> |
| 41 | + This cell ran at `${(new Date).toLocaleString("se")}`. |
| 42 | + </script> |
| 43 | + <script id="39" type="text/markdown"> |
| 44 | + <aside>Like hot module replacement, reactivity helps you develop faster because code re-runs automatically as you edit.</aside> |
| 45 | + |
| 46 | + Notebooks are reactive: cells run automatically like in a spreadsheet, re-running whenever referenced variables change. Reactivity makes it easier to implement interactive controls (or _inputs_), animations, and asynchronous operations such as loading data. |
| 47 | + </script> |
| 48 | + <script id="44" type="module" pinned=""> |
| 49 | + const x = view(Inputs.range([0, 100], {label: "x", step: 1})); |
| 50 | + const y = 2; |
| 51 | + </script> |
| 52 | + <script id="46" type="module" pinned=""> |
| 53 | + x ** y |
| 54 | + </script> |
| 55 | + <script id="50" type="text/markdown"> |
| 56 | + Top-level variables defined in JavaScript cells, such as `x` and `y` above, can be referenced in other cells. For Markdown, HTML, and other non-JavaScript cells, use dollar-curly expressions `$\{…}` to interpolate dynamic values. |
| 57 | + </script> |
| 58 | + <script id="51" type="text/markdown" pinned=""> |
| 59 | + The value of ${tex`${x}^${y} = ${(x ** y).toLocaleString().replace(/,/g, "\\,")}`}. |
| 60 | + </script> |
| 61 | + <script id="3" type="text/markdown"> |
| 62 | + --- |
| 63 | + |
| 64 | + ## JavaScript |
| 65 | + |
| 66 | + Use JavaScript cells to render charts, inputs, and other dynamic content. JavaScript cells can also declare top-level variables, say to load data or declare helper functions. |
| 67 | + </script> |
| 68 | + <script id="8" type="text/markdown"> |
| 69 | + JavaScript cells come in two forms: *expression* cells and *program* cells. An expression cell contains a single JavaScript expression (note the lack of semicolon) and implicitly displays its value: |
| 70 | + </script> |
| 71 | + <script id="6" type="module" pinned=""> |
| 72 | + 1 + 2 |
| 73 | + </script> |
| 74 | + <script id="9" type="text/markdown"> |
| 75 | + A program cell, in contrast, contains statements (typically with semicolons) and declarations, and doesn't display anything by default; however, you can call `display` to display something: |
| 76 | + </script> |
| 77 | + <script id="7" type="module" pinned=""> |
| 78 | + const foo = 1 + 2; |
| 79 | + |
| 80 | + display(foo); |
| 81 | + </script> |
| 82 | + <script id="15" type="text/markdown"> |
| 83 | + <aside>You can call <code>display</code> multiple times to display multiple things. When a cell re-runs, anything previously displayed will be cleared.</aside> |
| 84 | + |
| 85 | + When displaying --- either implicitly or explicitly --- if the displayed value is a DOM node, it will be inserted directly into the page. Anything else is displayed using the _inspector_, which is useful for debugging. You can use the [DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) to create content, though we recommend a library such as [Hypertext Literal](https://github.com/observablehq/htl), [Observable Plot](https://observablehq.com/plot/), or [D3](https://d3js.org). |
| 86 | + </script> |
| 87 | + <script id="16" type="module" pinned=""> |
| 88 | + function greeting(name) { |
| 89 | + return html`Hello, <i>${name}</i>!`; |
| 90 | + } |
| 91 | + </script> |
| 92 | + <script id="17" type="module" pinned=""> |
| 93 | + greeting("world") |
| 94 | + </script> |
| 95 | + <script id="19" type="module" pinned=""> |
| 96 | + Plot.lineY(aapl, {x: "Date", y: "Close"}).plot({y: {grid: true}}) |
| 97 | + </script> |
| 98 | + <script id="56" type="text/markdown"> |
| 99 | + When a top-level variable is defined as a promise, referencing cells will implicitly await the promise and only see the resolved value. |
| 100 | + </script> |
| 101 | + <script id="61" type="module" pinned=""> |
| 102 | + const delayed = new Promise((resolve) => setTimeout(() => resolve("hello"), 10000)); |
| 103 | + </script> |
| 104 | + <script id="62" type="module" pinned=""> |
| 105 | + delayed |
| 106 | + </script> |
| 107 | + <script id="63" type="text/markdown"> |
| 108 | + When a top-level variable is defined as a generator, referencing cells will see only the latest yield value and will re-run whenever the generator yields a new value. This is typically used for interaction, animation, and live data. |
| 109 | + </script> |
| 110 | + <script id="64" type="module" pinned=""> |
| 111 | + const tick = (async function* () { |
| 112 | + do { |
| 113 | + yield new Date(); |
| 114 | + await new Promise((resolve) => setTimeout(resolve, 1000)); |
| 115 | + } while (true); |
| 116 | + })(); |
| 117 | + </script> |
| 118 | + <script id="66" type="module" pinned=""> |
| 119 | + tick |
| 120 | + </script> |
| 121 | + <script id="58" type="text/markdown"> |
| 122 | + The built-in `view` function displays the given input and returns a generator that yields the current value of the input. |
| 123 | + </script> |
| 124 | + <script id="67" type="module" pinned=""> |
| 125 | + const name = view(Inputs.text({label: "Name"})); |
| 126 | + </script> |
| 127 | + <script id="68" type="text/markdown" pinned=""> |
| 128 | + Hello, ${name || "anonymous"}! |
| 129 | + </script> |
| 130 | + <script id="75" type="text/markdown"> |
| 131 | + The built-in `FileAttachment` function references a local file. It is typically used to load data. For security purposes, you can only load local files that live in the same directory, or a subdirectory, of the current notebook. |
| 132 | + </script> |
| 133 | + <script id="76" type="module" pinned=""> |
| 134 | + const AMZN = FileAttachment("ex/data/AMZN.csv").csv({typed: true}); |
| 135 | + </script> |
| 136 | + <script id="77" type="module" pinned=""> |
| 137 | + Inputs.table(AMZN) |
| 138 | + </script> |
| 139 | + <script id="78" type="text/markdown"> |
| 140 | + To load live data, you can use `fetch`, `WebSocket`, and other standard web APIs. For JSON data, you can also use an <code class="language-js">import</code> with `type: "json"`. |
| 141 | + </script> |
| 142 | + <script id="82" type="module" pinned=""> |
| 143 | + import world from "npm:world-atlas/land-110m.json" with {type: "json"}; |
| 144 | + |
| 145 | + display(world); |
| 146 | + </script> |
| 147 | + <script id="69" type="text/markdown"> |
| 148 | + The notebook standard library includes a handful of additional built-ins: |
| 149 | + |
| 150 | + - `display` - a function to display a value |
| 151 | + - `view` - a function to display an input and return its value generator |
| 152 | + - `invalidation` - a promise for disposing resources when a cell is re-run |
| 153 | + - `visibility` - a promise to wait for a cell to become visible |
| 154 | + - `width` - the current page width |
| 155 | + - `now` - the current time |
| 156 | + </script> |
| 157 | + <script id="59" type="text/markdown"> |
| 158 | + A handful of recommended libraries (and sample datasets) are also available by default, including: |
| 159 | + - `Inputs` - Observable Inputs |
| 160 | + - `htl`, `html`, `svg` - Observable Hypertext Literal |
| 161 | + - `Plot` - Observable Plot |
| 162 | + - `d3` - D3.js |
| 163 | + - `tex` - a tagged template literal for ${tex`\KaTeX`} |
| 164 | + - `md` - a tagged template literal for Markdown |
| 165 | + - `penguins` - the Palmer Archipelago penguins dataset |
| 166 | + </script> |
| 167 | + <script id="79" type="text/markdown"> |
| 168 | + You can load additional libraries from npm using an `npm:` <code class="language-js">import</code>. |
| 169 | + </script> |
| 170 | + <script id="81" type="module" pinned=""> |
| 171 | + import he from "npm:he"; |
| 172 | + |
| 173 | + display(he.encode("foo © bar ≠ baz 𝌆 qux")); |
| 174 | + </script> |
| 175 | + <script id="71" type="text/markdown"> |
| 176 | + --- |
| 177 | + |
| 178 | + ## Markdown |
| 179 | + |
| 180 | + <aside>Markdown and HTML cells are rendered statically, offering better page load performance than JavaScript cells.</aside> |
| 181 | + |
| 182 | + Markdown cells are typically used for prose, images, and other static content. Markdown is [CommonMark](https://commonmark.org/)-compliant, supports HTML in Markdown, automatic linkification, automatic typographic enhancements such as curly quotes and dashes, and automatic linking of headings. |
| 183 | + </script> |
| 184 | + <script id="83" type="text/markdown"> |
| 185 | + Use dollar-curly <code>$\{…}</code> expressions to interpolate dynamic JavaScript values into Markdown, including text, DOM nodes, and bits of dynamic Markdown. |
| 186 | + </script> |
| 187 | + <script id="5" type="text/markdown"> |
| 188 | + --- |
| 189 | + |
| 190 | + ## HTML |
| 191 | + |
| 192 | + HTML cells are used similarly to Markdown cells, and also support dollar-curly `$\{…}` interpolation. Unlike Markdown cells, HTML cells automatically escape any interpolated values, providing additional safety when handling dynamic and user-specified content. |
| 193 | + </script> |
| 194 | + <script id="73" type="text/html" pinned=""> |
| 195 | + Interpolated values are considered text, ${"not <i>HTML</i>"}. |
| 196 | + </script> |
| 197 | +</notebook> |
0 commit comments