@hpcc-js/observablehq-compiler 1.5.0 → 1.5.1
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 +73 -73
- package/dist/index.esm.js +49 -49
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/index.js +49 -49
- package/dist/index.js.map +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +3 -3
- package/src/__package__.ts +3 -3
- package/src/__tests__/File Attachments.ts +894 -894
- package/src/__tests__/Introduction to Imports.ts +748 -748
- package/src/__tests__/Observable TimeChart.ts +771 -771
- package/src/__tests__/index.ts +13 -13
- package/src/__tests__/m1.mjs +3 -3
- package/src/__tests__/node.ts +199 -199
- package/src/compiler.md +234 -234
- package/src/compiler.ts +311 -311
- package/src/cst.ts +178 -178
- package/src/index.css +459 -459
- package/src/index.ts +6 -6
- package/src/util.md +113 -113
- package/src/util.ts +175 -175
- package/src/writer.ts +80 -80
|
@@ -1,749 +1,749 @@
|
|
|
1
|
-
export const imports = {
|
|
2
|
-
"id": "3e394e3abf678985",
|
|
3
|
-
"slug": "import",
|
|
4
|
-
"trashed": false,
|
|
5
|
-
"description": "",
|
|
6
|
-
"likes": 115,
|
|
7
|
-
"publish_level": "public",
|
|
8
|
-
"forks": 7,
|
|
9
|
-
"fork_of": null,
|
|
10
|
-
"update_time": "2022-08-11T18:11:51.547Z",
|
|
11
|
-
"publish_time": "2018-04-26T20:01:08.133Z",
|
|
12
|
-
"publish_version": 796,
|
|
13
|
-
"latest_version": 796,
|
|
14
|
-
"thumbnail": "5bbc18097b07937c03b02d8f432774f3032c622b113b49b007925799dde862ce",
|
|
15
|
-
"default_thumbnail": "5bbc18097b07937c03b02d8f432774f3032c622b113b49b007925799dde862ce",
|
|
16
|
-
"roles": [],
|
|
17
|
-
"sharing": null,
|
|
18
|
-
"owner": {
|
|
19
|
-
"id": "f35c755083683fe5",
|
|
20
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e",
|
|
21
|
-
"login": "observablehq",
|
|
22
|
-
"name": "Observable",
|
|
23
|
-
"bio": "Use data to think, together.",
|
|
24
|
-
"home_url": "https://observablehq.com",
|
|
25
|
-
"type": "team",
|
|
26
|
-
"tier": "enterprise"
|
|
27
|
-
},
|
|
28
|
-
"creator": {
|
|
29
|
-
"id": "074c414ad1d825f5",
|
|
30
|
-
"github_login": "mbostock",
|
|
31
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/82811927da99f8938001b2ef1f552ad2c47083e46ebc55a3a146a5a5848c4519",
|
|
32
|
-
"login": "mbostock",
|
|
33
|
-
"name": "Mike Bostock",
|
|
34
|
-
"bio": "Building a better computational medium. Founder @observablehq. Creator @d3. Former @nytgraphics. Pronounced BOSS-tock.",
|
|
35
|
-
"home_url": "https://bost.ocks.org/mike/",
|
|
36
|
-
"tier": "basic"
|
|
37
|
-
},
|
|
38
|
-
"authors": [],
|
|
39
|
-
"collections": [
|
|
40
|
-
{
|
|
41
|
-
"id": "dd678f7d96fe6dd0",
|
|
42
|
-
"type": "public",
|
|
43
|
-
"slug": "notebook-fundamentals",
|
|
44
|
-
"title": "Notebook fundamentals",
|
|
45
|
-
"description": "Understand the fundamental concepts & techniques for working with Observable notebooks.",
|
|
46
|
-
"update_time": "2020-11-18T19:20:59.733Z",
|
|
47
|
-
"pinned": false,
|
|
48
|
-
"ordered": true,
|
|
49
|
-
"custom_thumbnail": null,
|
|
50
|
-
"default_thumbnail": "2bc0308d7a3170f415db37d448684f8bb3a09825059f0b45f7b90b3a9bc56344",
|
|
51
|
-
"thumbnail": "2bc0308d7a3170f415db37d448684f8bb3a09825059f0b45f7b90b3a9bc56344",
|
|
52
|
-
"listing_count": 9,
|
|
53
|
-
"parent_collection_count": 1,
|
|
54
|
-
"owner": {
|
|
55
|
-
"id": "f35c755083683fe5",
|
|
56
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e",
|
|
57
|
-
"login": "observablehq",
|
|
58
|
-
"name": "Observable",
|
|
59
|
-
"bio": "Use data to think, together.",
|
|
60
|
-
"home_url": "https://observablehq.com",
|
|
61
|
-
"type": "team",
|
|
62
|
-
"tier": "enterprise"
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"id": "0b7a49725d3ab0c0",
|
|
67
|
-
"type": "public",
|
|
68
|
-
"slug": "introduction",
|
|
69
|
-
"title": "Introduction",
|
|
70
|
-
"description": "Welcome to Observable! Get started with these tutorials.",
|
|
71
|
-
"update_time": "2019-05-06T19:48:56.772Z",
|
|
72
|
-
"pinned": true,
|
|
73
|
-
"ordered": false,
|
|
74
|
-
"custom_thumbnail": "d0ff809470432afdb2269a0e1a572a12d617f2d91aa07fca5ec6fdf13e4a1a9d",
|
|
75
|
-
"default_thumbnail": "04435c346f534d9f1d0b22f03a9b2ab313891893d0dccc956d6530f60f22c081",
|
|
76
|
-
"thumbnail": "d0ff809470432afdb2269a0e1a572a12d617f2d91aa07fca5ec6fdf13e4a1a9d",
|
|
77
|
-
"listing_count": 33,
|
|
78
|
-
"parent_collection_count": 1,
|
|
79
|
-
"owner": {
|
|
80
|
-
"id": "f35c755083683fe5",
|
|
81
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e",
|
|
82
|
-
"login": "observablehq",
|
|
83
|
-
"name": "Observable",
|
|
84
|
-
"bio": "Use data to think, together.",
|
|
85
|
-
"home_url": "https://observablehq.com",
|
|
86
|
-
"type": "team",
|
|
87
|
-
"tier": "enterprise"
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
|
-
"files": [
|
|
92
|
-
{
|
|
93
|
-
"id": "f1f1344c5afd87a7d173bcfc688ba86da5588220c84ca31d62db89d871459beb953cc9b864301a350744e637e9caff4107edebe51f88687fec6bf96903bde65e",
|
|
94
|
-
"url": "https://static.observableusercontent.com/files/f1f1344c5afd87a7d173bcfc688ba86da5588220c84ca31d62db89d871459beb953cc9b864301a350744e637e9caff4107edebe51f88687fec6bf96903bde65e",
|
|
95
|
-
"download_url": "https://static.observableusercontent.com/files/f1f1344c5afd87a7d173bcfc688ba86da5588220c84ca31d62db89d871459beb953cc9b864301a350744e637e9caff4107edebe51f88687fec6bf96903bde65e?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27d3.json",
|
|
96
|
-
"name": "d3.json",
|
|
97
|
-
"create_time": "2019-10-29T23:18:36.658Z",
|
|
98
|
-
"status": "public",
|
|
99
|
-
"size": 21848,
|
|
100
|
-
"mime_type": null,
|
|
101
|
-
"content_encoding": "gzip"
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
"id": "73ddce2cd17424eb0f4ea8b4518d0970ce88543512a0bf818f26187a44960ce1b786eabc874e6b565f3bd1f16b5f5a99f4623b145bb38504c9176a8d8c94d165",
|
|
105
|
-
"url": "https://static.observableusercontent.com/files/73ddce2cd17424eb0f4ea8b4518d0970ce88543512a0bf818f26187a44960ce1b786eabc874e6b565f3bd1f16b5f5a99f4623b145bb38504c9176a8d8c94d165",
|
|
106
|
-
"download_url": "https://static.observableusercontent.com/files/73ddce2cd17424eb0f4ea8b4518d0970ce88543512a0bf818f26187a44960ce1b786eabc874e6b565f3bd1f16b5f5a99f4623b145bb38504c9176a8d8c94d165?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27cellNamingMarkdown.png",
|
|
107
|
-
"name": "cellNamingMarkdown.png",
|
|
108
|
-
"create_time": "2022-06-07T16:12:00.983Z",
|
|
109
|
-
"status": "public",
|
|
110
|
-
"size": 24514,
|
|
111
|
-
"mime_type": "image/png",
|
|
112
|
-
"content_encoding": null
|
|
113
|
-
}
|
|
114
|
-
],
|
|
115
|
-
"comments": [
|
|
116
|
-
{
|
|
117
|
-
"id": "cb75c0828cef336e",
|
|
118
|
-
"content": "Where do you go to get the address of a page to import? ie How do I get the \"@name/page\" info?\n\nSeems like an \"Copy Import Link\" in the ellipses menu at top of page would be helpful.",
|
|
119
|
-
"node_id": 0,
|
|
120
|
-
"create_time": "2021-06-15T22:15:22.393Z",
|
|
121
|
-
"update_time": null,
|
|
122
|
-
"resolved": true,
|
|
123
|
-
"user": {
|
|
124
|
-
"id": "bc77e0cd5faff006",
|
|
125
|
-
"github_login": "kalmdown",
|
|
126
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/814a7bacd30761488bdf6c656b5f3b344a25453cf8e845fdffdc2b15c37937b4",
|
|
127
|
-
"login": "kalmdown",
|
|
128
|
-
"name": "kalmdown",
|
|
129
|
-
"bio": "Learning...",
|
|
130
|
-
"home_url": "",
|
|
131
|
-
"tier": "basic"
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
"id": "89d17a59374df195",
|
|
136
|
-
"content": "Added an explanation of where to get the address of a page.",
|
|
137
|
-
"node_id": 0,
|
|
138
|
-
"create_time": "2021-07-20T23:47:53.138Z",
|
|
139
|
-
"update_time": null,
|
|
140
|
-
"resolved": true,
|
|
141
|
-
"user": {
|
|
142
|
-
"id": "e32d6575f6e25235",
|
|
143
|
-
"github_login": null,
|
|
144
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/d1b0236c0308413347626db6ebcfcddf7584a1e67d1e99546fdcc01e7fd19549",
|
|
145
|
-
"login": "justinting",
|
|
146
|
-
"name": "Justin Ting",
|
|
147
|
-
"bio": "",
|
|
148
|
-
"home_url": "",
|
|
149
|
-
"tier": "basic"
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
"id": "78053a2ed3d518f7",
|
|
154
|
-
"content": "this is out of date since we have pinning now. I am actually looking for documentation on pinning to show a user.... can't find it.",
|
|
155
|
-
"node_id": 314,
|
|
156
|
-
"create_time": "2022-08-11T08:07:57.576Z",
|
|
157
|
-
"update_time": null,
|
|
158
|
-
"resolved": true,
|
|
159
|
-
"user": {
|
|
160
|
-
"id": "5215f6ec4a999d40",
|
|
161
|
-
"github_login": "tomlarkworthy",
|
|
162
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/47327a8bc1966f2186dcb3ebf4b7ee6e4e7ab9a5c2a07405aff57200ea778f71",
|
|
163
|
-
"login": "tomlarkworthy",
|
|
164
|
-
"name": "Tom Larkworthy",
|
|
165
|
-
"bio": "Building webcode.run to provide an ergonomic serverless for Observable. Cloud consultant. Formerly Firebase, Google",
|
|
166
|
-
"home_url": "https://webcode.run",
|
|
167
|
-
"tier": "basic"
|
|
168
|
-
}
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"id": "5f675633434998c7",
|
|
172
|
-
"content": "here is is https://observablehq.com/@observablehq/version-locking-for-notebook-imports",
|
|
173
|
-
"node_id": 314,
|
|
174
|
-
"create_time": "2022-08-11T09:11:56.106Z",
|
|
175
|
-
"update_time": null,
|
|
176
|
-
"resolved": true,
|
|
177
|
-
"user": {
|
|
178
|
-
"id": "5215f6ec4a999d40",
|
|
179
|
-
"github_login": "tomlarkworthy",
|
|
180
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/47327a8bc1966f2186dcb3ebf4b7ee6e4e7ab9a5c2a07405aff57200ea778f71",
|
|
181
|
-
"login": "tomlarkworthy",
|
|
182
|
-
"name": "Tom Larkworthy",
|
|
183
|
-
"bio": "Building webcode.run to provide an ergonomic serverless for Observable. Cloud consultant. Formerly Firebase, Google",
|
|
184
|
-
"home_url": "https://webcode.run",
|
|
185
|
-
"tier": "basic"
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
"id": "a0b3a8df67bcfde7",
|
|
190
|
-
"content": "Thanks, Tom--revised paragraph to describe version locking and added link to notebook.",
|
|
191
|
-
"node_id": 314,
|
|
192
|
-
"create_time": "2022-08-11T18:11:47.225Z",
|
|
193
|
-
"update_time": null,
|
|
194
|
-
"resolved": true,
|
|
195
|
-
"user": {
|
|
196
|
-
"id": "e32d6575f6e25235",
|
|
197
|
-
"github_login": null,
|
|
198
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/d1b0236c0308413347626db6ebcfcddf7584a1e67d1e99546fdcc01e7fd19549",
|
|
199
|
-
"login": "justinting",
|
|
200
|
-
"name": "Justin Ting",
|
|
201
|
-
"bio": "",
|
|
202
|
-
"home_url": "",
|
|
203
|
-
"tier": "basic"
|
|
204
|
-
}
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
"id": "70b8922e14f167bc",
|
|
208
|
-
"content": "It’s probably worth noting that, now that the D3 examples are importable as functions, there’s no need to use import-with for this use case and that it’s preferable to import the Treemap function and pass the desired data and options. There are likely still some useful applications for import-with but it’s fairly niche.",
|
|
209
|
-
"node_id": 317,
|
|
210
|
-
"create_time": "2021-10-21T05:12:10.552Z",
|
|
211
|
-
"update_time": null,
|
|
212
|
-
"resolved": false,
|
|
213
|
-
"user": {
|
|
214
|
-
"id": "074c414ad1d825f5",
|
|
215
|
-
"github_login": "mbostock",
|
|
216
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/82811927da99f8938001b2ef1f552ad2c47083e46ebc55a3a146a5a5848c4519",
|
|
217
|
-
"login": "mbostock",
|
|
218
|
-
"name": "Mike Bostock",
|
|
219
|
-
"bio": "Building a better computational medium. Founder @observablehq. Creator @d3. Former @nytgraphics. Pronounced BOSS-tock.",
|
|
220
|
-
"home_url": "https://bost.ocks.org/mike/",
|
|
221
|
-
"tier": "basic"
|
|
222
|
-
}
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
"id": "43a7825d3f473ac6",
|
|
226
|
-
"content": "Please clarify the Markdown cell naming & import thru an example.",
|
|
227
|
-
"node_id": 739,
|
|
228
|
-
"create_time": "2022-06-05T23:01:14.136Z",
|
|
229
|
-
"update_time": null,
|
|
230
|
-
"resolved": false,
|
|
231
|
-
"user": {
|
|
232
|
-
"id": "c522b6e3c699beb9",
|
|
233
|
-
"github_login": "vvivanloc",
|
|
234
|
-
"avatar_url": "https://avatars.observableusercontent.com/avatar/3805f5966b13c10af07bad51a9da6491b27c8d208657dce68a8cfb60a9ab85db",
|
|
235
|
-
"login": "vvivanloc",
|
|
236
|
-
"name": "Vincent VIVANLOC",
|
|
237
|
-
"bio": "Hacking SPAs in TypeScript and Angular/React/your framework here, some Linux devops and C#, in a previous life writing GPU intensive apps in OpenGL/C++",
|
|
238
|
-
"home_url": "https://vvivanloc.github.io/",
|
|
239
|
-
"tier": "basic"
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
],
|
|
243
|
-
"commenting_lock": null,
|
|
244
|
-
"suggestion_from": null,
|
|
245
|
-
"suggestions_to": [],
|
|
246
|
-
"version": 796,
|
|
247
|
-
"title": "Introduction to Imports",
|
|
248
|
-
"license": null,
|
|
249
|
-
"copyright": "",
|
|
250
|
-
"nodes": [
|
|
251
|
-
{
|
|
252
|
-
"id": 0,
|
|
253
|
-
"value": "md`# Introduction to Imports\n\nObservable lets you quickly reuse code by importing named cells from other notebooks.\n`",
|
|
254
|
-
"pinned": false,
|
|
255
|
-
"mode": "js",
|
|
256
|
-
"data": null,
|
|
257
|
-
"name": null
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
"id": 772,
|
|
261
|
-
"value": "## Example of Importing a Function",
|
|
262
|
-
"pinned": false,
|
|
263
|
-
"mode": "md",
|
|
264
|
-
"data": null,
|
|
265
|
-
"name": ""
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
"id": 771,
|
|
269
|
-
"value": "md`Let’s say you saw Mike Bostock's notebook of [color scales](https://observablehq.com/@mbostock/color-ramp) used to visualize quantitative data. That notebook defines a \\`ramp\\` function that returns a canvas for a given \\`color\\` function, where the \\`color\\` function returns a color for a given ${tex`t \\in [0,1]`} from left to right. To create the dreaded angry rainbow yourself, import and call \\`ramp\\`:`",
|
|
270
|
-
"pinned": false,
|
|
271
|
-
"mode": "js",
|
|
272
|
-
"data": null,
|
|
273
|
-
"name": null
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
"id": 74,
|
|
277
|
-
"value": "import {ramp} from \"@mbostock/color-ramp\"",
|
|
278
|
-
"pinned": true,
|
|
279
|
-
"mode": "js",
|
|
280
|
-
"data": null,
|
|
281
|
-
"name": null
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
"id": 77,
|
|
285
|
-
"value": "ramp(t => `hsl(${t * 360}, 100%, 50%)`)",
|
|
286
|
-
"pinned": true,
|
|
287
|
-
"mode": "js",
|
|
288
|
-
"data": null,
|
|
289
|
-
"name": null
|
|
290
|
-
},
|
|
291
|
-
{
|
|
292
|
-
"id": 770,
|
|
293
|
-
"value": "**Note**: For the source of the `import` statement, use the Observable username and notebook name; that is:\n\n`from` @_username_/_notebookName_\n\nYou can get these from the URL of the notebook from which you are importing.",
|
|
294
|
-
"pinned": false,
|
|
295
|
-
"mode": "md",
|
|
296
|
-
"data": null,
|
|
297
|
-
"name": ""
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
"id": 769,
|
|
301
|
-
"value": "## Why Import vs. Copy-Paste?",
|
|
302
|
-
"pinned": false,
|
|
303
|
-
"mode": "md",
|
|
304
|
-
"data": null,
|
|
305
|
-
"name": ""
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
"id": 89,
|
|
309
|
-
"value": "md`You could instead copy-paste the \\`ramp\\` function from that notebook into this one—it’s only a few lines of code. But imports have a few advantages.\n`",
|
|
310
|
-
"pinned": false,
|
|
311
|
-
"mode": "js",
|
|
312
|
-
"data": null,
|
|
313
|
-
"name": null
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
"id": 767,
|
|
317
|
-
"value": "### Cell Dependencies",
|
|
318
|
-
"pinned": false,
|
|
319
|
-
"mode": "md",
|
|
320
|
-
"data": null,
|
|
321
|
-
"name": ""
|
|
322
|
-
},
|
|
323
|
-
{
|
|
324
|
-
"id": 766,
|
|
325
|
-
"value": "First, the cell you want to reuse may depend on other cells. If you copy-paste, you have to copy-paste those other cells too, and make sure that they don’t conflict with existing cells in your notebook. If you import, the dependencies are loaded automatically, so you don’t have to think about it.\n\nFor example, consider a notebook on an interrupted Sinu–Mollweide map projection that requires the D3 and TopoJSON libraries, along with geometry representing the Earth’s landmasses. You can import the map and display it without worrying about how the sausage is made.",
|
|
326
|
-
"pinned": false,
|
|
327
|
-
"mode": "md",
|
|
328
|
-
"data": null,
|
|
329
|
-
"name": ""
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
"id": 93,
|
|
333
|
-
"value": "import {map} from \"@d3/interrupted-sinu-mollweide\"",
|
|
334
|
-
"pinned": true,
|
|
335
|
-
"mode": "js",
|
|
336
|
-
"data": null,
|
|
337
|
-
"name": null
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
"id": 97,
|
|
341
|
-
"value": "map",
|
|
342
|
-
"pinned": true,
|
|
343
|
-
"mode": "js",
|
|
344
|
-
"data": null,
|
|
345
|
-
"name": null
|
|
346
|
-
},
|
|
347
|
-
{
|
|
348
|
-
"id": 765,
|
|
349
|
-
"value": "### Re-used Code Stays Up-to-Date",
|
|
350
|
-
"pinned": false,
|
|
351
|
-
"mode": "md",
|
|
352
|
-
"data": null,
|
|
353
|
-
"name": ""
|
|
354
|
-
},
|
|
355
|
-
{
|
|
356
|
-
"id": 314,
|
|
357
|
-
"value": "Second, by importing, it’s easier to keep the reused code up-to-date. Imports target the latest published version, so if Mike improves his map notebook, the new map will automatically appear here.\n\n(The risk of importing the latest version is that your notebook may break if the imported notebook changes in a non-backwards-compatible way. Observable has version locking, which allows you to \"lock\" the version of the notebook you are importing. See [Version Locking for Notebook Imports](https://observablehq.com/@observablehq/version-locking-for-notebook-imports?collection=@observablehq/introduction) for more details.)",
|
|
358
|
-
"pinned": false,
|
|
359
|
-
"mode": "md",
|
|
360
|
-
"data": null,
|
|
361
|
-
"name": ""
|
|
362
|
-
},
|
|
363
|
-
{
|
|
364
|
-
"id": 763,
|
|
365
|
-
"value": "### \"Rewrite\" Code Using `import` - `with`",
|
|
366
|
-
"pinned": false,
|
|
367
|
-
"mode": "md",
|
|
368
|
-
"data": null,
|
|
369
|
-
"name": ""
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
"id": 317,
|
|
373
|
-
"value": "md`Third, and most excitingly, Observable imports let you inject dependencies using \\`import\\`-\\`with\\`! This lets you “rewrite” imported code as you might do when copy-pasting, without the problems of code duplication.\n\nConsider Mike Bostock's D3 treemap notebook that visualizes the Flare dataset. To reuse this treemap implementation to visualize a different dataset, inject a new definition of \\`data\\` in the \\`with\\` clause on import:`",
|
|
374
|
-
"pinned": false,
|
|
375
|
-
"mode": "js",
|
|
376
|
-
"data": null,
|
|
377
|
-
"name": null
|
|
378
|
-
},
|
|
379
|
-
{
|
|
380
|
-
"id": 380,
|
|
381
|
-
"value": "import {chart as treemap}\nwith {treemap_data as data}\nfrom \"@d3/treemap@164\"",
|
|
382
|
-
"pinned": true,
|
|
383
|
-
"mode": "js",
|
|
384
|
-
"data": null,
|
|
385
|
-
"name": null
|
|
386
|
-
},
|
|
387
|
-
{
|
|
388
|
-
"id": 386,
|
|
389
|
-
"value": "treemap",
|
|
390
|
-
"pinned": true,
|
|
391
|
-
"mode": "js",
|
|
392
|
-
"data": null,
|
|
393
|
-
"name": null
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
"id": 383,
|
|
397
|
-
"value": "treemap_data = FileAttachment(\"d3.json\").json()",
|
|
398
|
-
"pinned": true,
|
|
399
|
-
"mode": "js",
|
|
400
|
-
"data": null,
|
|
401
|
-
"name": null
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
"id": 761,
|
|
405
|
-
"value": "As long as the new data conforms to the same shape as the old data (here, a tree of objects with *children* and *value* properties), you can reuse the existing code without copy-paste and the terrible challenge of designing a reusable chart abstraction!",
|
|
406
|
-
"pinned": false,
|
|
407
|
-
"mode": "md",
|
|
408
|
-
"data": null,
|
|
409
|
-
"name": ""
|
|
410
|
-
},
|
|
411
|
-
{
|
|
412
|
-
"id": 760,
|
|
413
|
-
"value": "### Adding Dynamic Definitions to Previously Static Code",
|
|
414
|
-
"pinned": false,
|
|
415
|
-
"mode": "md",
|
|
416
|
-
"data": null,
|
|
417
|
-
"name": ""
|
|
418
|
-
},
|
|
419
|
-
{
|
|
420
|
-
"id": 389,
|
|
421
|
-
"value": "md`\nBest of all, because [Observable is reactive](/@observablehq/how-observable-runs), you can even inject dynamic definitions into code that was previously static!\n\nFor example, below is a histogram of a synthetic beta distribution using ${tex`\\alpha`} and ${tex`\\beta`} values that are controlled by sliders. Whenever ${tex`\\alpha`} or ${tex`\\beta`} change, Observable automatically updates the histogram—even though the implementation is reused from a static histogram of unemployment rates.`",
|
|
422
|
-
"pinned": false,
|
|
423
|
-
"mode": "js",
|
|
424
|
-
"data": null,
|
|
425
|
-
"name": null
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
"id": 391,
|
|
429
|
-
"value": "import {chart as histogram}\nwith {histogram_data as data}\nfrom \"@d3/histogram@261\"",
|
|
430
|
-
"pinned": true,
|
|
431
|
-
"mode": "js",
|
|
432
|
-
"data": null,
|
|
433
|
-
"name": null
|
|
434
|
-
},
|
|
435
|
-
{
|
|
436
|
-
"id": 697,
|
|
437
|
-
"value": "viewof alphabeta = {\n const form = html`<form style=\"font: 12px var(--sans-serif);\">\n <label style=\"display: block;\">\n <input name=a type=range min=0 max=5 step=0.01 style=\"width:180px;\">\n ${tex`\\alpha`} = <output name=oa></output>\n </label>\n <label style=\"display: block;\">\n <input name=b type=range min=0 max=5 step=0.01 style=\"width:180px;\">\n ${tex`\\beta`} = <output name=ob></output>\n </label>\n</form>`;\n form.oninput = () => {\n form.value = [form.a.valueAsNumber, form.b.valueAsNumber];\n form.oa.value = form.a.valueAsNumber;\n form.ob.value = form.b.valueAsNumber;\n };\n form.oninput();\n return form;\n}",
|
|
438
|
-
"pinned": false,
|
|
439
|
-
"mode": "js",
|
|
440
|
-
"data": null,
|
|
441
|
-
"name": null
|
|
442
|
-
},
|
|
443
|
-
{
|
|
444
|
-
"id": 394,
|
|
445
|
-
"value": "histogram",
|
|
446
|
-
"pinned": true,
|
|
447
|
-
"mode": "js",
|
|
448
|
-
"data": null,
|
|
449
|
-
"name": null
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
"id": 397,
|
|
453
|
-
"value": "histogram_data = new Array(10000).fill().map(() => randb(...alphabeta))",
|
|
454
|
-
"pinned": true,
|
|
455
|
-
"mode": "js",
|
|
456
|
-
"data": null,
|
|
457
|
-
"name": null
|
|
458
|
-
},
|
|
459
|
-
{
|
|
460
|
-
"id": 758,
|
|
461
|
-
"value": "### Nuances When Using Imports",
|
|
462
|
-
"pinned": false,
|
|
463
|
-
"mode": "md",
|
|
464
|
-
"data": null,
|
|
465
|
-
"name": ""
|
|
466
|
-
},
|
|
467
|
-
{
|
|
468
|
-
"id": 113,
|
|
469
|
-
"value": "md`Here are a few additional nuances of imports:\n\n- Like [ES imports](http://exploringjs.com/es6/ch_modules.html), Observable imports are live bindings. If you import a value that changes over time ([a generator cell](/@mbostock/generator-cells-functions-and-objects)), such as a countdown to a certain date in the future, the imported value will change over time, too.`",
|
|
470
|
-
"pinned": false,
|
|
471
|
-
"mode": "js",
|
|
472
|
-
"data": null,
|
|
473
|
-
"name": null
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
"id": 115,
|
|
477
|
-
"value": "import {interval} from \"@observablehq/firstcontactcountdown\"",
|
|
478
|
-
"pinned": true,
|
|
479
|
-
"mode": "js",
|
|
480
|
-
"data": null,
|
|
481
|
-
"name": null
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
"id": 118,
|
|
485
|
-
"value": "interval",
|
|
486
|
-
"pinned": true,
|
|
487
|
-
"mode": "js",
|
|
488
|
-
"data": null,
|
|
489
|
-
"name": null
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
"id": 3,
|
|
493
|
-
"value": "md`\n- You can only import named cells, and you must name each cell you want to import explicitly. No anonymous cells allowed; if a notebook uses side effects, as is sometimes common with anonymous cells, you must name and import the cells with side effects, too. (See [Naming Cells](#howToNameCells) for a refresher on naming cells.)\n\n- Imported cells are lazily evaluated: if you import a cell but you don’t reference it anywhere, the code won’t run. Try uncommenting the cell below and then hit Shift-Enter. Notice that the generator *i* begins at zero—it doesn’t start until referenced.`",
|
|
494
|
-
"pinned": false,
|
|
495
|
-
"mode": "js",
|
|
496
|
-
"data": null,
|
|
497
|
-
"name": null
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
"id": 20,
|
|
501
|
-
"value": "// i",
|
|
502
|
-
"pinned": true,
|
|
503
|
-
"mode": "js",
|
|
504
|
-
"data": null,
|
|
505
|
-
"name": null
|
|
506
|
-
},
|
|
507
|
-
{
|
|
508
|
-
"id": 11,
|
|
509
|
-
"value": "import {i} from \"@observablehq/generator-cells-functions-and-objects\"",
|
|
510
|
-
"pinned": true,
|
|
511
|
-
"mode": "js",
|
|
512
|
-
"data": null,
|
|
513
|
-
"name": null
|
|
514
|
-
},
|
|
515
|
-
{
|
|
516
|
-
"id": 47,
|
|
517
|
-
"value": "md`\n- Also like ES imports, only the cells you import are available (*bound*) in the local notebook, even if those cells depend on other cells. Those dependent cells are *run*—they’re just not exposed in the scope of the local notebook.\n\n- You can use circular imports, but only if you don’t use the *with* clause when importing. Import-with effectively creates a local copy of the imported module with your overrides, so a circular import-with would create an infinitely recursive module, a bit like seeing your reflection in a mirrored room.\n\n- You can import the same notebook multiple times and references will resolve exactly. (Note, however, that the versions of the imported notebooks must also match, or they are considered different notebooks.)`",
|
|
518
|
-
"pinned": false,
|
|
519
|
-
"mode": "js",
|
|
520
|
-
"data": null,
|
|
521
|
-
"name": null
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
"id": 561,
|
|
525
|
-
"value": "import {map as map2} from \"@d3/interrupted-sinu-mollweide\"",
|
|
526
|
-
"pinned": true,
|
|
527
|
-
"mode": "js",
|
|
528
|
-
"data": null,
|
|
529
|
-
"name": null
|
|
530
|
-
},
|
|
531
|
-
{
|
|
532
|
-
"id": 564,
|
|
533
|
-
"value": "map === map2",
|
|
534
|
-
"pinned": true,
|
|
535
|
-
"mode": "js",
|
|
536
|
-
"data": null,
|
|
537
|
-
"name": null
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
"id": 753,
|
|
541
|
-
"value": "### Import Visualizer for Debugging",
|
|
542
|
-
"pinned": false,
|
|
543
|
-
"mode": "md",
|
|
544
|
-
"data": null,
|
|
545
|
-
"name": ""
|
|
546
|
-
},
|
|
547
|
-
{
|
|
548
|
-
"id": 718,
|
|
549
|
-
"value": "md`If you find yourself using lots of imports in your notebooks, you might find our [import visualizer](/@observablehq/notebook-import-visualizer) helpful for debugging. For example, here are the imports used by this notebook. *So meta!*`",
|
|
550
|
-
"pinned": false,
|
|
551
|
-
"mode": "js",
|
|
552
|
-
"data": null,
|
|
553
|
-
"name": null
|
|
554
|
-
},
|
|
555
|
-
{
|
|
556
|
-
"id": 725,
|
|
557
|
-
"value": "graph",
|
|
558
|
-
"pinned": false,
|
|
559
|
-
"mode": "js",
|
|
560
|
-
"data": null,
|
|
561
|
-
"name": null
|
|
562
|
-
},
|
|
563
|
-
{
|
|
564
|
-
"id": 668,
|
|
565
|
-
"value": "shared = md`### Public, Unlisted, and Private imports\n\nThe examples so far have imported from publicly shared notebooks. But you can import from unlisted notebooks, too:`",
|
|
566
|
-
"pinned": false,
|
|
567
|
-
"mode": "js",
|
|
568
|
-
"data": null,
|
|
569
|
-
"name": null
|
|
570
|
-
},
|
|
571
|
-
{
|
|
572
|
-
"id": 751,
|
|
573
|
-
"value": "import {functionFromUnlistedNotebook} from \"00ff3ac693572256\"",
|
|
574
|
-
"pinned": true,
|
|
575
|
-
"mode": "js",
|
|
576
|
-
"data": null,
|
|
577
|
-
"name": null
|
|
578
|
-
},
|
|
579
|
-
{
|
|
580
|
-
"id": 750,
|
|
581
|
-
"value": "functionFromUnlistedNotebook",
|
|
582
|
-
"pinned": true,
|
|
583
|
-
"mode": "js",
|
|
584
|
-
"data": null,
|
|
585
|
-
"name": null
|
|
586
|
-
},
|
|
587
|
-
{
|
|
588
|
-
"id": 556,
|
|
589
|
-
"value": "md`You can even import from private notebooks; however, if you publish a notebook that imports a private notebook, the imported private notebook won’t be accessible to your readers, which may prevent your notebook from functioning as intended. Don’t forget to share or publish your imports before you publish.\n\nLastly, imports aren’t intended to replace libraries (like [lodash](https://lodash.com) or [D3](https://d3js.org)); if you want to design, build and support a reusable library, go for it and publish to npm! But if you want a lightweight way to reuse code across notebooks without resorting to copy-paste, reach for import.\n\n---`",
|
|
590
|
-
"pinned": false,
|
|
591
|
-
"mode": "js",
|
|
592
|
-
"data": null,
|
|
593
|
-
"name": null
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
"id": 749,
|
|
597
|
-
"value": "howToNameCells = md `## Naming Cells`",
|
|
598
|
-
"pinned": false,
|
|
599
|
-
"mode": "js",
|
|
600
|
-
"data": null,
|
|
601
|
-
"name": null
|
|
602
|
-
},
|
|
603
|
-
{
|
|
604
|
-
"id": 748,
|
|
605
|
-
"value": "You can assign a name to a JavaScript cell in one of the four following ways:",
|
|
606
|
-
"pinned": false,
|
|
607
|
-
"mode": "md",
|
|
608
|
-
"data": null,
|
|
609
|
-
"name": ""
|
|
610
|
-
},
|
|
611
|
-
{
|
|
612
|
-
"id": 747,
|
|
613
|
-
"value": "Naming a cell expression:",
|
|
614
|
-
"pinned": false,
|
|
615
|
-
"mode": "md",
|
|
616
|
-
"data": null,
|
|
617
|
-
"name": ""
|
|
618
|
-
},
|
|
619
|
-
{
|
|
620
|
-
"id": 746,
|
|
621
|
-
"value": "expressionName = 8",
|
|
622
|
-
"pinned": true,
|
|
623
|
-
"mode": "js",
|
|
624
|
-
"data": null,
|
|
625
|
-
"name": null
|
|
626
|
-
},
|
|
627
|
-
{
|
|
628
|
-
"id": 745,
|
|
629
|
-
"value": "Naming a block:",
|
|
630
|
-
"pinned": false,
|
|
631
|
-
"mode": "md",
|
|
632
|
-
"data": null,
|
|
633
|
-
"name": ""
|
|
634
|
-
},
|
|
635
|
-
{
|
|
636
|
-
"id": 744,
|
|
637
|
-
"value": "blockName = { return 80; }",
|
|
638
|
-
"pinned": true,
|
|
639
|
-
"mode": "js",
|
|
640
|
-
"data": null,
|
|
641
|
-
"name": null
|
|
642
|
-
},
|
|
643
|
-
{
|
|
644
|
-
"id": 743,
|
|
645
|
-
"value": "Naming a function declaration:",
|
|
646
|
-
"pinned": false,
|
|
647
|
-
"mode": "md",
|
|
648
|
-
"data": null,
|
|
649
|
-
"name": ""
|
|
650
|
-
},
|
|
651
|
-
{
|
|
652
|
-
"id": 742,
|
|
653
|
-
"value": "function functionName() {return 800;}",
|
|
654
|
-
"pinned": true,
|
|
655
|
-
"mode": "js",
|
|
656
|
-
"data": null,
|
|
657
|
-
"name": null
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
"id": 741,
|
|
661
|
-
"value": "Naming a class:",
|
|
662
|
-
"pinned": false,
|
|
663
|
-
"mode": "md",
|
|
664
|
-
"data": null,
|
|
665
|
-
"name": ""
|
|
666
|
-
},
|
|
667
|
-
{
|
|
668
|
-
"id": 740,
|
|
669
|
-
"value": "class className {}",
|
|
670
|
-
"pinned": true,
|
|
671
|
-
"mode": "js",
|
|
672
|
-
"data": null,
|
|
673
|
-
"name": null
|
|
674
|
-
},
|
|
675
|
-
{
|
|
676
|
-
"id": 793,
|
|
677
|
-
"value": "To name a Markdown cell, enter the name of the cell in the following area (visible at the bottom of your browser window when you are editing the cell):",
|
|
678
|
-
"pinned": false,
|
|
679
|
-
"mode": "md",
|
|
680
|
-
"data": null,
|
|
681
|
-
"name": ""
|
|
682
|
-
},
|
|
683
|
-
{
|
|
684
|
-
"id": 792,
|
|
685
|
-
"value": "<figure>\n <img\n style=\"border-radius:2px;box-shadow:0 4px 12px rgba(0,0,0,0.15), 0 0 0 1px rgba(0, 0, 0, 0.1);margin-left:27px;margin-bottom:40px;max-width: width\"\n src=${await FileAttachment(\"cellNamingMarkdown.png\").url()}\n />\n <figcaption>Use the highlighted area to name Markdown cells (or any other type of cell).</figcaption>\n</figure>",
|
|
686
|
-
"pinned": false,
|
|
687
|
-
"mode": "html",
|
|
688
|
-
"data": null,
|
|
689
|
-
"name": ""
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
"id": 430,
|
|
693
|
-
"value": "md`## Appendix`",
|
|
694
|
-
"pinned": false,
|
|
695
|
-
"mode": "js",
|
|
696
|
-
"data": null,
|
|
697
|
-
"name": null
|
|
698
|
-
},
|
|
699
|
-
{
|
|
700
|
-
"id": 721,
|
|
701
|
-
"value": "url = \"https://api.observablehq.com/@observablehq/introduction-to-imports.js?v=3\"",
|
|
702
|
-
"pinned": false,
|
|
703
|
-
"mode": "js",
|
|
704
|
-
"data": null,
|
|
705
|
-
"name": null
|
|
706
|
-
},
|
|
707
|
-
{
|
|
708
|
-
"id": 728,
|
|
709
|
-
"value": "orient = \"LR\"",
|
|
710
|
-
"pinned": false,
|
|
711
|
-
"mode": "js",
|
|
712
|
-
"data": null,
|
|
713
|
-
"name": null
|
|
714
|
-
},
|
|
715
|
-
{
|
|
716
|
-
"id": 724,
|
|
717
|
-
"value": "import {graphic as graph} with {url, orient} from \"@observablehq/notebook-import-visualizer\"",
|
|
718
|
-
"pinned": false,
|
|
719
|
-
"mode": "js",
|
|
720
|
-
"data": null,
|
|
721
|
-
"name": null
|
|
722
|
-
},
|
|
723
|
-
{
|
|
724
|
-
"id": 442,
|
|
725
|
-
"value": "function randb(alpha, beta) {\n const u = randg(alpha);\n return u / (u + randg(beta));\n}",
|
|
726
|
-
"pinned": false,
|
|
727
|
-
"mode": "js",
|
|
728
|
-
"data": null,
|
|
729
|
-
"name": null
|
|
730
|
-
},
|
|
731
|
-
{
|
|
732
|
-
"id": 443,
|
|
733
|
-
"value": "// Returns a gamma deviate by the method of Marsaglia and Tsang.\nfunction randg(shape) {\n let oalph = shape, a1, a2, u, v, x, mat;\n if (!shape) shape = 1;\n if (shape < 1) shape += 1;\n a1 = shape - 1 / 3;\n a2 = 1 / Math.sqrt(9 * a1);\n do {\n do {\n x = randn();\n v = 1 + a2 * x;\n } while (v <= 0);\n v = v * v * v;\n u = Math.random();\n } while (\n u > 1 - 0.331 * Math.pow(x, 4) &&\n Math.log(u) > 0.5 * x * x + a1 * (1 - v + Math.log(v))\n );\n if (shape === oalph) return a1 * v; // alpha > 1\n do u = Math.random(); while (u === 0); // alpha < 1\n return Math.pow(u, 1 / oalph) * a1 * v;\n}",
|
|
734
|
-
"pinned": false,
|
|
735
|
-
"mode": "js",
|
|
736
|
-
"data": null,
|
|
737
|
-
"name": null
|
|
738
|
-
},
|
|
739
|
-
{
|
|
740
|
-
"id": 445,
|
|
741
|
-
"value": "// Returns a normal deviate (mu=0, sigma=1).\nfunction randn() {\n let u, v, x, y, q;\n do {\n u = Math.random();\n v = 1.7156 * (Math.random() - 0.5);\n x = u - 0.449871;\n y = Math.abs(v) + 0.386595;\n q = x * x + y * (0.19600 * y - 0.25472 * x);\n } while (q > 0.27597 && (q > 0.27846 || v * v > -4 * Math.log(u) * u * u));\n return v / u;\n}",
|
|
742
|
-
"pinned": false,
|
|
743
|
-
"mode": "js",
|
|
744
|
-
"data": null,
|
|
745
|
-
"name": null
|
|
746
|
-
}
|
|
747
|
-
],
|
|
748
|
-
"resolutions": []
|
|
1
|
+
export const imports = {
|
|
2
|
+
"id": "3e394e3abf678985",
|
|
3
|
+
"slug": "import",
|
|
4
|
+
"trashed": false,
|
|
5
|
+
"description": "",
|
|
6
|
+
"likes": 115,
|
|
7
|
+
"publish_level": "public",
|
|
8
|
+
"forks": 7,
|
|
9
|
+
"fork_of": null,
|
|
10
|
+
"update_time": "2022-08-11T18:11:51.547Z",
|
|
11
|
+
"publish_time": "2018-04-26T20:01:08.133Z",
|
|
12
|
+
"publish_version": 796,
|
|
13
|
+
"latest_version": 796,
|
|
14
|
+
"thumbnail": "5bbc18097b07937c03b02d8f432774f3032c622b113b49b007925799dde862ce",
|
|
15
|
+
"default_thumbnail": "5bbc18097b07937c03b02d8f432774f3032c622b113b49b007925799dde862ce",
|
|
16
|
+
"roles": [],
|
|
17
|
+
"sharing": null,
|
|
18
|
+
"owner": {
|
|
19
|
+
"id": "f35c755083683fe5",
|
|
20
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e",
|
|
21
|
+
"login": "observablehq",
|
|
22
|
+
"name": "Observable",
|
|
23
|
+
"bio": "Use data to think, together.",
|
|
24
|
+
"home_url": "https://observablehq.com",
|
|
25
|
+
"type": "team",
|
|
26
|
+
"tier": "enterprise"
|
|
27
|
+
},
|
|
28
|
+
"creator": {
|
|
29
|
+
"id": "074c414ad1d825f5",
|
|
30
|
+
"github_login": "mbostock",
|
|
31
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/82811927da99f8938001b2ef1f552ad2c47083e46ebc55a3a146a5a5848c4519",
|
|
32
|
+
"login": "mbostock",
|
|
33
|
+
"name": "Mike Bostock",
|
|
34
|
+
"bio": "Building a better computational medium. Founder @observablehq. Creator @d3. Former @nytgraphics. Pronounced BOSS-tock.",
|
|
35
|
+
"home_url": "https://bost.ocks.org/mike/",
|
|
36
|
+
"tier": "basic"
|
|
37
|
+
},
|
|
38
|
+
"authors": [],
|
|
39
|
+
"collections": [
|
|
40
|
+
{
|
|
41
|
+
"id": "dd678f7d96fe6dd0",
|
|
42
|
+
"type": "public",
|
|
43
|
+
"slug": "notebook-fundamentals",
|
|
44
|
+
"title": "Notebook fundamentals",
|
|
45
|
+
"description": "Understand the fundamental concepts & techniques for working with Observable notebooks.",
|
|
46
|
+
"update_time": "2020-11-18T19:20:59.733Z",
|
|
47
|
+
"pinned": false,
|
|
48
|
+
"ordered": true,
|
|
49
|
+
"custom_thumbnail": null,
|
|
50
|
+
"default_thumbnail": "2bc0308d7a3170f415db37d448684f8bb3a09825059f0b45f7b90b3a9bc56344",
|
|
51
|
+
"thumbnail": "2bc0308d7a3170f415db37d448684f8bb3a09825059f0b45f7b90b3a9bc56344",
|
|
52
|
+
"listing_count": 9,
|
|
53
|
+
"parent_collection_count": 1,
|
|
54
|
+
"owner": {
|
|
55
|
+
"id": "f35c755083683fe5",
|
|
56
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e",
|
|
57
|
+
"login": "observablehq",
|
|
58
|
+
"name": "Observable",
|
|
59
|
+
"bio": "Use data to think, together.",
|
|
60
|
+
"home_url": "https://observablehq.com",
|
|
61
|
+
"type": "team",
|
|
62
|
+
"tier": "enterprise"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "0b7a49725d3ab0c0",
|
|
67
|
+
"type": "public",
|
|
68
|
+
"slug": "introduction",
|
|
69
|
+
"title": "Introduction",
|
|
70
|
+
"description": "Welcome to Observable! Get started with these tutorials.",
|
|
71
|
+
"update_time": "2019-05-06T19:48:56.772Z",
|
|
72
|
+
"pinned": true,
|
|
73
|
+
"ordered": false,
|
|
74
|
+
"custom_thumbnail": "d0ff809470432afdb2269a0e1a572a12d617f2d91aa07fca5ec6fdf13e4a1a9d",
|
|
75
|
+
"default_thumbnail": "04435c346f534d9f1d0b22f03a9b2ab313891893d0dccc956d6530f60f22c081",
|
|
76
|
+
"thumbnail": "d0ff809470432afdb2269a0e1a572a12d617f2d91aa07fca5ec6fdf13e4a1a9d",
|
|
77
|
+
"listing_count": 33,
|
|
78
|
+
"parent_collection_count": 1,
|
|
79
|
+
"owner": {
|
|
80
|
+
"id": "f35c755083683fe5",
|
|
81
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e",
|
|
82
|
+
"login": "observablehq",
|
|
83
|
+
"name": "Observable",
|
|
84
|
+
"bio": "Use data to think, together.",
|
|
85
|
+
"home_url": "https://observablehq.com",
|
|
86
|
+
"type": "team",
|
|
87
|
+
"tier": "enterprise"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"files": [
|
|
92
|
+
{
|
|
93
|
+
"id": "f1f1344c5afd87a7d173bcfc688ba86da5588220c84ca31d62db89d871459beb953cc9b864301a350744e637e9caff4107edebe51f88687fec6bf96903bde65e",
|
|
94
|
+
"url": "https://static.observableusercontent.com/files/f1f1344c5afd87a7d173bcfc688ba86da5588220c84ca31d62db89d871459beb953cc9b864301a350744e637e9caff4107edebe51f88687fec6bf96903bde65e",
|
|
95
|
+
"download_url": "https://static.observableusercontent.com/files/f1f1344c5afd87a7d173bcfc688ba86da5588220c84ca31d62db89d871459beb953cc9b864301a350744e637e9caff4107edebe51f88687fec6bf96903bde65e?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27d3.json",
|
|
96
|
+
"name": "d3.json",
|
|
97
|
+
"create_time": "2019-10-29T23:18:36.658Z",
|
|
98
|
+
"status": "public",
|
|
99
|
+
"size": 21848,
|
|
100
|
+
"mime_type": null,
|
|
101
|
+
"content_encoding": "gzip"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "73ddce2cd17424eb0f4ea8b4518d0970ce88543512a0bf818f26187a44960ce1b786eabc874e6b565f3bd1f16b5f5a99f4623b145bb38504c9176a8d8c94d165",
|
|
105
|
+
"url": "https://static.observableusercontent.com/files/73ddce2cd17424eb0f4ea8b4518d0970ce88543512a0bf818f26187a44960ce1b786eabc874e6b565f3bd1f16b5f5a99f4623b145bb38504c9176a8d8c94d165",
|
|
106
|
+
"download_url": "https://static.observableusercontent.com/files/73ddce2cd17424eb0f4ea8b4518d0970ce88543512a0bf818f26187a44960ce1b786eabc874e6b565f3bd1f16b5f5a99f4623b145bb38504c9176a8d8c94d165?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27cellNamingMarkdown.png",
|
|
107
|
+
"name": "cellNamingMarkdown.png",
|
|
108
|
+
"create_time": "2022-06-07T16:12:00.983Z",
|
|
109
|
+
"status": "public",
|
|
110
|
+
"size": 24514,
|
|
111
|
+
"mime_type": "image/png",
|
|
112
|
+
"content_encoding": null
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"comments": [
|
|
116
|
+
{
|
|
117
|
+
"id": "cb75c0828cef336e",
|
|
118
|
+
"content": "Where do you go to get the address of a page to import? ie How do I get the \"@name/page\" info?\n\nSeems like an \"Copy Import Link\" in the ellipses menu at top of page would be helpful.",
|
|
119
|
+
"node_id": 0,
|
|
120
|
+
"create_time": "2021-06-15T22:15:22.393Z",
|
|
121
|
+
"update_time": null,
|
|
122
|
+
"resolved": true,
|
|
123
|
+
"user": {
|
|
124
|
+
"id": "bc77e0cd5faff006",
|
|
125
|
+
"github_login": "kalmdown",
|
|
126
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/814a7bacd30761488bdf6c656b5f3b344a25453cf8e845fdffdc2b15c37937b4",
|
|
127
|
+
"login": "kalmdown",
|
|
128
|
+
"name": "kalmdown",
|
|
129
|
+
"bio": "Learning...",
|
|
130
|
+
"home_url": "",
|
|
131
|
+
"tier": "basic"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "89d17a59374df195",
|
|
136
|
+
"content": "Added an explanation of where to get the address of a page.",
|
|
137
|
+
"node_id": 0,
|
|
138
|
+
"create_time": "2021-07-20T23:47:53.138Z",
|
|
139
|
+
"update_time": null,
|
|
140
|
+
"resolved": true,
|
|
141
|
+
"user": {
|
|
142
|
+
"id": "e32d6575f6e25235",
|
|
143
|
+
"github_login": null,
|
|
144
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/d1b0236c0308413347626db6ebcfcddf7584a1e67d1e99546fdcc01e7fd19549",
|
|
145
|
+
"login": "justinting",
|
|
146
|
+
"name": "Justin Ting",
|
|
147
|
+
"bio": "",
|
|
148
|
+
"home_url": "",
|
|
149
|
+
"tier": "basic"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"id": "78053a2ed3d518f7",
|
|
154
|
+
"content": "this is out of date since we have pinning now. I am actually looking for documentation on pinning to show a user.... can't find it.",
|
|
155
|
+
"node_id": 314,
|
|
156
|
+
"create_time": "2022-08-11T08:07:57.576Z",
|
|
157
|
+
"update_time": null,
|
|
158
|
+
"resolved": true,
|
|
159
|
+
"user": {
|
|
160
|
+
"id": "5215f6ec4a999d40",
|
|
161
|
+
"github_login": "tomlarkworthy",
|
|
162
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/47327a8bc1966f2186dcb3ebf4b7ee6e4e7ab9a5c2a07405aff57200ea778f71",
|
|
163
|
+
"login": "tomlarkworthy",
|
|
164
|
+
"name": "Tom Larkworthy",
|
|
165
|
+
"bio": "Building webcode.run to provide an ergonomic serverless for Observable. Cloud consultant. Formerly Firebase, Google",
|
|
166
|
+
"home_url": "https://webcode.run",
|
|
167
|
+
"tier": "basic"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"id": "5f675633434998c7",
|
|
172
|
+
"content": "here is is https://observablehq.com/@observablehq/version-locking-for-notebook-imports",
|
|
173
|
+
"node_id": 314,
|
|
174
|
+
"create_time": "2022-08-11T09:11:56.106Z",
|
|
175
|
+
"update_time": null,
|
|
176
|
+
"resolved": true,
|
|
177
|
+
"user": {
|
|
178
|
+
"id": "5215f6ec4a999d40",
|
|
179
|
+
"github_login": "tomlarkworthy",
|
|
180
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/47327a8bc1966f2186dcb3ebf4b7ee6e4e7ab9a5c2a07405aff57200ea778f71",
|
|
181
|
+
"login": "tomlarkworthy",
|
|
182
|
+
"name": "Tom Larkworthy",
|
|
183
|
+
"bio": "Building webcode.run to provide an ergonomic serverless for Observable. Cloud consultant. Formerly Firebase, Google",
|
|
184
|
+
"home_url": "https://webcode.run",
|
|
185
|
+
"tier": "basic"
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"id": "a0b3a8df67bcfde7",
|
|
190
|
+
"content": "Thanks, Tom--revised paragraph to describe version locking and added link to notebook.",
|
|
191
|
+
"node_id": 314,
|
|
192
|
+
"create_time": "2022-08-11T18:11:47.225Z",
|
|
193
|
+
"update_time": null,
|
|
194
|
+
"resolved": true,
|
|
195
|
+
"user": {
|
|
196
|
+
"id": "e32d6575f6e25235",
|
|
197
|
+
"github_login": null,
|
|
198
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/d1b0236c0308413347626db6ebcfcddf7584a1e67d1e99546fdcc01e7fd19549",
|
|
199
|
+
"login": "justinting",
|
|
200
|
+
"name": "Justin Ting",
|
|
201
|
+
"bio": "",
|
|
202
|
+
"home_url": "",
|
|
203
|
+
"tier": "basic"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"id": "70b8922e14f167bc",
|
|
208
|
+
"content": "It’s probably worth noting that, now that the D3 examples are importable as functions, there’s no need to use import-with for this use case and that it’s preferable to import the Treemap function and pass the desired data and options. There are likely still some useful applications for import-with but it’s fairly niche.",
|
|
209
|
+
"node_id": 317,
|
|
210
|
+
"create_time": "2021-10-21T05:12:10.552Z",
|
|
211
|
+
"update_time": null,
|
|
212
|
+
"resolved": false,
|
|
213
|
+
"user": {
|
|
214
|
+
"id": "074c414ad1d825f5",
|
|
215
|
+
"github_login": "mbostock",
|
|
216
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/82811927da99f8938001b2ef1f552ad2c47083e46ebc55a3a146a5a5848c4519",
|
|
217
|
+
"login": "mbostock",
|
|
218
|
+
"name": "Mike Bostock",
|
|
219
|
+
"bio": "Building a better computational medium. Founder @observablehq. Creator @d3. Former @nytgraphics. Pronounced BOSS-tock.",
|
|
220
|
+
"home_url": "https://bost.ocks.org/mike/",
|
|
221
|
+
"tier": "basic"
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "43a7825d3f473ac6",
|
|
226
|
+
"content": "Please clarify the Markdown cell naming & import thru an example.",
|
|
227
|
+
"node_id": 739,
|
|
228
|
+
"create_time": "2022-06-05T23:01:14.136Z",
|
|
229
|
+
"update_time": null,
|
|
230
|
+
"resolved": false,
|
|
231
|
+
"user": {
|
|
232
|
+
"id": "c522b6e3c699beb9",
|
|
233
|
+
"github_login": "vvivanloc",
|
|
234
|
+
"avatar_url": "https://avatars.observableusercontent.com/avatar/3805f5966b13c10af07bad51a9da6491b27c8d208657dce68a8cfb60a9ab85db",
|
|
235
|
+
"login": "vvivanloc",
|
|
236
|
+
"name": "Vincent VIVANLOC",
|
|
237
|
+
"bio": "Hacking SPAs in TypeScript and Angular/React/your framework here, some Linux devops and C#, in a previous life writing GPU intensive apps in OpenGL/C++",
|
|
238
|
+
"home_url": "https://vvivanloc.github.io/",
|
|
239
|
+
"tier": "basic"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
],
|
|
243
|
+
"commenting_lock": null,
|
|
244
|
+
"suggestion_from": null,
|
|
245
|
+
"suggestions_to": [],
|
|
246
|
+
"version": 796,
|
|
247
|
+
"title": "Introduction to Imports",
|
|
248
|
+
"license": null,
|
|
249
|
+
"copyright": "",
|
|
250
|
+
"nodes": [
|
|
251
|
+
{
|
|
252
|
+
"id": 0,
|
|
253
|
+
"value": "md`# Introduction to Imports\n\nObservable lets you quickly reuse code by importing named cells from other notebooks.\n`",
|
|
254
|
+
"pinned": false,
|
|
255
|
+
"mode": "js",
|
|
256
|
+
"data": null,
|
|
257
|
+
"name": null
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"id": 772,
|
|
261
|
+
"value": "## Example of Importing a Function",
|
|
262
|
+
"pinned": false,
|
|
263
|
+
"mode": "md",
|
|
264
|
+
"data": null,
|
|
265
|
+
"name": ""
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"id": 771,
|
|
269
|
+
"value": "md`Let’s say you saw Mike Bostock's notebook of [color scales](https://observablehq.com/@mbostock/color-ramp) used to visualize quantitative data. That notebook defines a \\`ramp\\` function that returns a canvas for a given \\`color\\` function, where the \\`color\\` function returns a color for a given ${tex`t \\in [0,1]`} from left to right. To create the dreaded angry rainbow yourself, import and call \\`ramp\\`:`",
|
|
270
|
+
"pinned": false,
|
|
271
|
+
"mode": "js",
|
|
272
|
+
"data": null,
|
|
273
|
+
"name": null
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"id": 74,
|
|
277
|
+
"value": "import {ramp} from \"@mbostock/color-ramp\"",
|
|
278
|
+
"pinned": true,
|
|
279
|
+
"mode": "js",
|
|
280
|
+
"data": null,
|
|
281
|
+
"name": null
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"id": 77,
|
|
285
|
+
"value": "ramp(t => `hsl(${t * 360}, 100%, 50%)`)",
|
|
286
|
+
"pinned": true,
|
|
287
|
+
"mode": "js",
|
|
288
|
+
"data": null,
|
|
289
|
+
"name": null
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"id": 770,
|
|
293
|
+
"value": "**Note**: For the source of the `import` statement, use the Observable username and notebook name; that is:\n\n`from` @_username_/_notebookName_\n\nYou can get these from the URL of the notebook from which you are importing.",
|
|
294
|
+
"pinned": false,
|
|
295
|
+
"mode": "md",
|
|
296
|
+
"data": null,
|
|
297
|
+
"name": ""
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"id": 769,
|
|
301
|
+
"value": "## Why Import vs. Copy-Paste?",
|
|
302
|
+
"pinned": false,
|
|
303
|
+
"mode": "md",
|
|
304
|
+
"data": null,
|
|
305
|
+
"name": ""
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
"id": 89,
|
|
309
|
+
"value": "md`You could instead copy-paste the \\`ramp\\` function from that notebook into this one—it’s only a few lines of code. But imports have a few advantages.\n`",
|
|
310
|
+
"pinned": false,
|
|
311
|
+
"mode": "js",
|
|
312
|
+
"data": null,
|
|
313
|
+
"name": null
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"id": 767,
|
|
317
|
+
"value": "### Cell Dependencies",
|
|
318
|
+
"pinned": false,
|
|
319
|
+
"mode": "md",
|
|
320
|
+
"data": null,
|
|
321
|
+
"name": ""
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"id": 766,
|
|
325
|
+
"value": "First, the cell you want to reuse may depend on other cells. If you copy-paste, you have to copy-paste those other cells too, and make sure that they don’t conflict with existing cells in your notebook. If you import, the dependencies are loaded automatically, so you don’t have to think about it.\n\nFor example, consider a notebook on an interrupted Sinu–Mollweide map projection that requires the D3 and TopoJSON libraries, along with geometry representing the Earth’s landmasses. You can import the map and display it without worrying about how the sausage is made.",
|
|
326
|
+
"pinned": false,
|
|
327
|
+
"mode": "md",
|
|
328
|
+
"data": null,
|
|
329
|
+
"name": ""
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"id": 93,
|
|
333
|
+
"value": "import {map} from \"@d3/interrupted-sinu-mollweide\"",
|
|
334
|
+
"pinned": true,
|
|
335
|
+
"mode": "js",
|
|
336
|
+
"data": null,
|
|
337
|
+
"name": null
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"id": 97,
|
|
341
|
+
"value": "map",
|
|
342
|
+
"pinned": true,
|
|
343
|
+
"mode": "js",
|
|
344
|
+
"data": null,
|
|
345
|
+
"name": null
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"id": 765,
|
|
349
|
+
"value": "### Re-used Code Stays Up-to-Date",
|
|
350
|
+
"pinned": false,
|
|
351
|
+
"mode": "md",
|
|
352
|
+
"data": null,
|
|
353
|
+
"name": ""
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"id": 314,
|
|
357
|
+
"value": "Second, by importing, it’s easier to keep the reused code up-to-date. Imports target the latest published version, so if Mike improves his map notebook, the new map will automatically appear here.\n\n(The risk of importing the latest version is that your notebook may break if the imported notebook changes in a non-backwards-compatible way. Observable has version locking, which allows you to \"lock\" the version of the notebook you are importing. See [Version Locking for Notebook Imports](https://observablehq.com/@observablehq/version-locking-for-notebook-imports?collection=@observablehq/introduction) for more details.)",
|
|
358
|
+
"pinned": false,
|
|
359
|
+
"mode": "md",
|
|
360
|
+
"data": null,
|
|
361
|
+
"name": ""
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"id": 763,
|
|
365
|
+
"value": "### \"Rewrite\" Code Using `import` - `with`",
|
|
366
|
+
"pinned": false,
|
|
367
|
+
"mode": "md",
|
|
368
|
+
"data": null,
|
|
369
|
+
"name": ""
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"id": 317,
|
|
373
|
+
"value": "md`Third, and most excitingly, Observable imports let you inject dependencies using \\`import\\`-\\`with\\`! This lets you “rewrite” imported code as you might do when copy-pasting, without the problems of code duplication.\n\nConsider Mike Bostock's D3 treemap notebook that visualizes the Flare dataset. To reuse this treemap implementation to visualize a different dataset, inject a new definition of \\`data\\` in the \\`with\\` clause on import:`",
|
|
374
|
+
"pinned": false,
|
|
375
|
+
"mode": "js",
|
|
376
|
+
"data": null,
|
|
377
|
+
"name": null
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"id": 380,
|
|
381
|
+
"value": "import {chart as treemap}\nwith {treemap_data as data}\nfrom \"@d3/treemap@164\"",
|
|
382
|
+
"pinned": true,
|
|
383
|
+
"mode": "js",
|
|
384
|
+
"data": null,
|
|
385
|
+
"name": null
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"id": 386,
|
|
389
|
+
"value": "treemap",
|
|
390
|
+
"pinned": true,
|
|
391
|
+
"mode": "js",
|
|
392
|
+
"data": null,
|
|
393
|
+
"name": null
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
"id": 383,
|
|
397
|
+
"value": "treemap_data = FileAttachment(\"d3.json\").json()",
|
|
398
|
+
"pinned": true,
|
|
399
|
+
"mode": "js",
|
|
400
|
+
"data": null,
|
|
401
|
+
"name": null
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"id": 761,
|
|
405
|
+
"value": "As long as the new data conforms to the same shape as the old data (here, a tree of objects with *children* and *value* properties), you can reuse the existing code without copy-paste and the terrible challenge of designing a reusable chart abstraction!",
|
|
406
|
+
"pinned": false,
|
|
407
|
+
"mode": "md",
|
|
408
|
+
"data": null,
|
|
409
|
+
"name": ""
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"id": 760,
|
|
413
|
+
"value": "### Adding Dynamic Definitions to Previously Static Code",
|
|
414
|
+
"pinned": false,
|
|
415
|
+
"mode": "md",
|
|
416
|
+
"data": null,
|
|
417
|
+
"name": ""
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"id": 389,
|
|
421
|
+
"value": "md`\nBest of all, because [Observable is reactive](/@observablehq/how-observable-runs), you can even inject dynamic definitions into code that was previously static!\n\nFor example, below is a histogram of a synthetic beta distribution using ${tex`\\alpha`} and ${tex`\\beta`} values that are controlled by sliders. Whenever ${tex`\\alpha`} or ${tex`\\beta`} change, Observable automatically updates the histogram—even though the implementation is reused from a static histogram of unemployment rates.`",
|
|
422
|
+
"pinned": false,
|
|
423
|
+
"mode": "js",
|
|
424
|
+
"data": null,
|
|
425
|
+
"name": null
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"id": 391,
|
|
429
|
+
"value": "import {chart as histogram}\nwith {histogram_data as data}\nfrom \"@d3/histogram@261\"",
|
|
430
|
+
"pinned": true,
|
|
431
|
+
"mode": "js",
|
|
432
|
+
"data": null,
|
|
433
|
+
"name": null
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"id": 697,
|
|
437
|
+
"value": "viewof alphabeta = {\n const form = html`<form style=\"font: 12px var(--sans-serif);\">\n <label style=\"display: block;\">\n <input name=a type=range min=0 max=5 step=0.01 style=\"width:180px;\">\n ${tex`\\alpha`} = <output name=oa></output>\n </label>\n <label style=\"display: block;\">\n <input name=b type=range min=0 max=5 step=0.01 style=\"width:180px;\">\n ${tex`\\beta`} = <output name=ob></output>\n </label>\n</form>`;\n form.oninput = () => {\n form.value = [form.a.valueAsNumber, form.b.valueAsNumber];\n form.oa.value = form.a.valueAsNumber;\n form.ob.value = form.b.valueAsNumber;\n };\n form.oninput();\n return form;\n}",
|
|
438
|
+
"pinned": false,
|
|
439
|
+
"mode": "js",
|
|
440
|
+
"data": null,
|
|
441
|
+
"name": null
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"id": 394,
|
|
445
|
+
"value": "histogram",
|
|
446
|
+
"pinned": true,
|
|
447
|
+
"mode": "js",
|
|
448
|
+
"data": null,
|
|
449
|
+
"name": null
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"id": 397,
|
|
453
|
+
"value": "histogram_data = new Array(10000).fill().map(() => randb(...alphabeta))",
|
|
454
|
+
"pinned": true,
|
|
455
|
+
"mode": "js",
|
|
456
|
+
"data": null,
|
|
457
|
+
"name": null
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"id": 758,
|
|
461
|
+
"value": "### Nuances When Using Imports",
|
|
462
|
+
"pinned": false,
|
|
463
|
+
"mode": "md",
|
|
464
|
+
"data": null,
|
|
465
|
+
"name": ""
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"id": 113,
|
|
469
|
+
"value": "md`Here are a few additional nuances of imports:\n\n- Like [ES imports](http://exploringjs.com/es6/ch_modules.html), Observable imports are live bindings. If you import a value that changes over time ([a generator cell](/@mbostock/generator-cells-functions-and-objects)), such as a countdown to a certain date in the future, the imported value will change over time, too.`",
|
|
470
|
+
"pinned": false,
|
|
471
|
+
"mode": "js",
|
|
472
|
+
"data": null,
|
|
473
|
+
"name": null
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"id": 115,
|
|
477
|
+
"value": "import {interval} from \"@observablehq/firstcontactcountdown\"",
|
|
478
|
+
"pinned": true,
|
|
479
|
+
"mode": "js",
|
|
480
|
+
"data": null,
|
|
481
|
+
"name": null
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
"id": 118,
|
|
485
|
+
"value": "interval",
|
|
486
|
+
"pinned": true,
|
|
487
|
+
"mode": "js",
|
|
488
|
+
"data": null,
|
|
489
|
+
"name": null
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
"id": 3,
|
|
493
|
+
"value": "md`\n- You can only import named cells, and you must name each cell you want to import explicitly. No anonymous cells allowed; if a notebook uses side effects, as is sometimes common with anonymous cells, you must name and import the cells with side effects, too. (See [Naming Cells](#howToNameCells) for a refresher on naming cells.)\n\n- Imported cells are lazily evaluated: if you import a cell but you don’t reference it anywhere, the code won’t run. Try uncommenting the cell below and then hit Shift-Enter. Notice that the generator *i* begins at zero—it doesn’t start until referenced.`",
|
|
494
|
+
"pinned": false,
|
|
495
|
+
"mode": "js",
|
|
496
|
+
"data": null,
|
|
497
|
+
"name": null
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"id": 20,
|
|
501
|
+
"value": "// i",
|
|
502
|
+
"pinned": true,
|
|
503
|
+
"mode": "js",
|
|
504
|
+
"data": null,
|
|
505
|
+
"name": null
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"id": 11,
|
|
509
|
+
"value": "import {i} from \"@observablehq/generator-cells-functions-and-objects\"",
|
|
510
|
+
"pinned": true,
|
|
511
|
+
"mode": "js",
|
|
512
|
+
"data": null,
|
|
513
|
+
"name": null
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
"id": 47,
|
|
517
|
+
"value": "md`\n- Also like ES imports, only the cells you import are available (*bound*) in the local notebook, even if those cells depend on other cells. Those dependent cells are *run*—they’re just not exposed in the scope of the local notebook.\n\n- You can use circular imports, but only if you don’t use the *with* clause when importing. Import-with effectively creates a local copy of the imported module with your overrides, so a circular import-with would create an infinitely recursive module, a bit like seeing your reflection in a mirrored room.\n\n- You can import the same notebook multiple times and references will resolve exactly. (Note, however, that the versions of the imported notebooks must also match, or they are considered different notebooks.)`",
|
|
518
|
+
"pinned": false,
|
|
519
|
+
"mode": "js",
|
|
520
|
+
"data": null,
|
|
521
|
+
"name": null
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
"id": 561,
|
|
525
|
+
"value": "import {map as map2} from \"@d3/interrupted-sinu-mollweide\"",
|
|
526
|
+
"pinned": true,
|
|
527
|
+
"mode": "js",
|
|
528
|
+
"data": null,
|
|
529
|
+
"name": null
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"id": 564,
|
|
533
|
+
"value": "map === map2",
|
|
534
|
+
"pinned": true,
|
|
535
|
+
"mode": "js",
|
|
536
|
+
"data": null,
|
|
537
|
+
"name": null
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
"id": 753,
|
|
541
|
+
"value": "### Import Visualizer for Debugging",
|
|
542
|
+
"pinned": false,
|
|
543
|
+
"mode": "md",
|
|
544
|
+
"data": null,
|
|
545
|
+
"name": ""
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
"id": 718,
|
|
549
|
+
"value": "md`If you find yourself using lots of imports in your notebooks, you might find our [import visualizer](/@observablehq/notebook-import-visualizer) helpful for debugging. For example, here are the imports used by this notebook. *So meta!*`",
|
|
550
|
+
"pinned": false,
|
|
551
|
+
"mode": "js",
|
|
552
|
+
"data": null,
|
|
553
|
+
"name": null
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
"id": 725,
|
|
557
|
+
"value": "graph",
|
|
558
|
+
"pinned": false,
|
|
559
|
+
"mode": "js",
|
|
560
|
+
"data": null,
|
|
561
|
+
"name": null
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
"id": 668,
|
|
565
|
+
"value": "shared = md`### Public, Unlisted, and Private imports\n\nThe examples so far have imported from publicly shared notebooks. But you can import from unlisted notebooks, too:`",
|
|
566
|
+
"pinned": false,
|
|
567
|
+
"mode": "js",
|
|
568
|
+
"data": null,
|
|
569
|
+
"name": null
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
"id": 751,
|
|
573
|
+
"value": "import {functionFromUnlistedNotebook} from \"00ff3ac693572256\"",
|
|
574
|
+
"pinned": true,
|
|
575
|
+
"mode": "js",
|
|
576
|
+
"data": null,
|
|
577
|
+
"name": null
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
"id": 750,
|
|
581
|
+
"value": "functionFromUnlistedNotebook",
|
|
582
|
+
"pinned": true,
|
|
583
|
+
"mode": "js",
|
|
584
|
+
"data": null,
|
|
585
|
+
"name": null
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"id": 556,
|
|
589
|
+
"value": "md`You can even import from private notebooks; however, if you publish a notebook that imports a private notebook, the imported private notebook won’t be accessible to your readers, which may prevent your notebook from functioning as intended. Don’t forget to share or publish your imports before you publish.\n\nLastly, imports aren’t intended to replace libraries (like [lodash](https://lodash.com) or [D3](https://d3js.org)); if you want to design, build and support a reusable library, go for it and publish to npm! But if you want a lightweight way to reuse code across notebooks without resorting to copy-paste, reach for import.\n\n---`",
|
|
590
|
+
"pinned": false,
|
|
591
|
+
"mode": "js",
|
|
592
|
+
"data": null,
|
|
593
|
+
"name": null
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
"id": 749,
|
|
597
|
+
"value": "howToNameCells = md `## Naming Cells`",
|
|
598
|
+
"pinned": false,
|
|
599
|
+
"mode": "js",
|
|
600
|
+
"data": null,
|
|
601
|
+
"name": null
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"id": 748,
|
|
605
|
+
"value": "You can assign a name to a JavaScript cell in one of the four following ways:",
|
|
606
|
+
"pinned": false,
|
|
607
|
+
"mode": "md",
|
|
608
|
+
"data": null,
|
|
609
|
+
"name": ""
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
"id": 747,
|
|
613
|
+
"value": "Naming a cell expression:",
|
|
614
|
+
"pinned": false,
|
|
615
|
+
"mode": "md",
|
|
616
|
+
"data": null,
|
|
617
|
+
"name": ""
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
"id": 746,
|
|
621
|
+
"value": "expressionName = 8",
|
|
622
|
+
"pinned": true,
|
|
623
|
+
"mode": "js",
|
|
624
|
+
"data": null,
|
|
625
|
+
"name": null
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
"id": 745,
|
|
629
|
+
"value": "Naming a block:",
|
|
630
|
+
"pinned": false,
|
|
631
|
+
"mode": "md",
|
|
632
|
+
"data": null,
|
|
633
|
+
"name": ""
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"id": 744,
|
|
637
|
+
"value": "blockName = { return 80; }",
|
|
638
|
+
"pinned": true,
|
|
639
|
+
"mode": "js",
|
|
640
|
+
"data": null,
|
|
641
|
+
"name": null
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
"id": 743,
|
|
645
|
+
"value": "Naming a function declaration:",
|
|
646
|
+
"pinned": false,
|
|
647
|
+
"mode": "md",
|
|
648
|
+
"data": null,
|
|
649
|
+
"name": ""
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
"id": 742,
|
|
653
|
+
"value": "function functionName() {return 800;}",
|
|
654
|
+
"pinned": true,
|
|
655
|
+
"mode": "js",
|
|
656
|
+
"data": null,
|
|
657
|
+
"name": null
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
"id": 741,
|
|
661
|
+
"value": "Naming a class:",
|
|
662
|
+
"pinned": false,
|
|
663
|
+
"mode": "md",
|
|
664
|
+
"data": null,
|
|
665
|
+
"name": ""
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
"id": 740,
|
|
669
|
+
"value": "class className {}",
|
|
670
|
+
"pinned": true,
|
|
671
|
+
"mode": "js",
|
|
672
|
+
"data": null,
|
|
673
|
+
"name": null
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"id": 793,
|
|
677
|
+
"value": "To name a Markdown cell, enter the name of the cell in the following area (visible at the bottom of your browser window when you are editing the cell):",
|
|
678
|
+
"pinned": false,
|
|
679
|
+
"mode": "md",
|
|
680
|
+
"data": null,
|
|
681
|
+
"name": ""
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
"id": 792,
|
|
685
|
+
"value": "<figure>\n <img\n style=\"border-radius:2px;box-shadow:0 4px 12px rgba(0,0,0,0.15), 0 0 0 1px rgba(0, 0, 0, 0.1);margin-left:27px;margin-bottom:40px;max-width: width\"\n src=${await FileAttachment(\"cellNamingMarkdown.png\").url()}\n />\n <figcaption>Use the highlighted area to name Markdown cells (or any other type of cell).</figcaption>\n</figure>",
|
|
686
|
+
"pinned": false,
|
|
687
|
+
"mode": "html",
|
|
688
|
+
"data": null,
|
|
689
|
+
"name": ""
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
"id": 430,
|
|
693
|
+
"value": "md`## Appendix`",
|
|
694
|
+
"pinned": false,
|
|
695
|
+
"mode": "js",
|
|
696
|
+
"data": null,
|
|
697
|
+
"name": null
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
"id": 721,
|
|
701
|
+
"value": "url = \"https://api.observablehq.com/@observablehq/introduction-to-imports.js?v=3\"",
|
|
702
|
+
"pinned": false,
|
|
703
|
+
"mode": "js",
|
|
704
|
+
"data": null,
|
|
705
|
+
"name": null
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
"id": 728,
|
|
709
|
+
"value": "orient = \"LR\"",
|
|
710
|
+
"pinned": false,
|
|
711
|
+
"mode": "js",
|
|
712
|
+
"data": null,
|
|
713
|
+
"name": null
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"id": 724,
|
|
717
|
+
"value": "import {graphic as graph} with {url, orient} from \"@observablehq/notebook-import-visualizer\"",
|
|
718
|
+
"pinned": false,
|
|
719
|
+
"mode": "js",
|
|
720
|
+
"data": null,
|
|
721
|
+
"name": null
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
"id": 442,
|
|
725
|
+
"value": "function randb(alpha, beta) {\n const u = randg(alpha);\n return u / (u + randg(beta));\n}",
|
|
726
|
+
"pinned": false,
|
|
727
|
+
"mode": "js",
|
|
728
|
+
"data": null,
|
|
729
|
+
"name": null
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
"id": 443,
|
|
733
|
+
"value": "// Returns a gamma deviate by the method of Marsaglia and Tsang.\nfunction randg(shape) {\n let oalph = shape, a1, a2, u, v, x, mat;\n if (!shape) shape = 1;\n if (shape < 1) shape += 1;\n a1 = shape - 1 / 3;\n a2 = 1 / Math.sqrt(9 * a1);\n do {\n do {\n x = randn();\n v = 1 + a2 * x;\n } while (v <= 0);\n v = v * v * v;\n u = Math.random();\n } while (\n u > 1 - 0.331 * Math.pow(x, 4) &&\n Math.log(u) > 0.5 * x * x + a1 * (1 - v + Math.log(v))\n );\n if (shape === oalph) return a1 * v; // alpha > 1\n do u = Math.random(); while (u === 0); // alpha < 1\n return Math.pow(u, 1 / oalph) * a1 * v;\n}",
|
|
734
|
+
"pinned": false,
|
|
735
|
+
"mode": "js",
|
|
736
|
+
"data": null,
|
|
737
|
+
"name": null
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
"id": 445,
|
|
741
|
+
"value": "// Returns a normal deviate (mu=0, sigma=1).\nfunction randn() {\n let u, v, x, y, q;\n do {\n u = Math.random();\n v = 1.7156 * (Math.random() - 0.5);\n x = u - 0.449871;\n y = Math.abs(v) + 0.386595;\n q = x * x + y * (0.19600 * y - 0.25472 * x);\n } while (q > 0.27597 && (q > 0.27846 || v * v > -4 * Math.log(u) * u * u));\n return v / u;\n}",
|
|
742
|
+
"pinned": false,
|
|
743
|
+
"mode": "js",
|
|
744
|
+
"data": null,
|
|
745
|
+
"name": null
|
|
746
|
+
}
|
|
747
|
+
],
|
|
748
|
+
"resolutions": []
|
|
749
749
|
};
|