numbl 0.4.3 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +5 -1
  2. package/dist-cli/cli.js +10689 -8543
  3. package/dist-lib/graphics/figuresReducer.d.ts +14 -1
  4. package/dist-lib/graphics/types.d.ts +60 -0
  5. package/dist-lib/lib.js +24594 -22515
  6. package/dist-lib/numbl-core/executeCode.d.ts +10 -0
  7. package/dist-lib/numbl-core/executors/handleInline.d.ts +18 -2
  8. package/dist-lib/numbl-core/executors/jit/valueAdapter.d.ts +16 -9
  9. package/dist-lib/numbl-core/jit/compileSpecC.d.ts +7 -0
  10. package/dist-lib/numbl-core/jit/lowering/definiteAssign.d.ts +42 -0
  11. package/dist-lib/numbl-core/lexer/types.d.ts +62 -61
  12. package/dist-lib/numbl-core/native/ts-lapack-eig-complex.d.ts +32 -0
  13. package/dist-lib/numbl-core/runtime/plotBuiltinDispatch.d.ts +6 -0
  14. package/dist-lib/numbl-core/runtime/plotUtils.d.ts +55 -2
  15. package/dist-lib/numbl-core/runtime/runtime.d.ts +25 -0
  16. package/dist-lib/numbl-core/runtime/runtimePlot.d.ts +6 -0
  17. package/dist-lib/numbl-core/runtime/struct-access.d.ts +4 -0
  18. package/dist-lib/numbl-core/runtime/uihtmlSession.d.ts +40 -0
  19. package/dist-lib/numbl-core/version.d.ts +1 -1
  20. package/dist-plot-viewer/assets/index-CPiPZdGN.js +4504 -0
  21. package/dist-plot-viewer/index.html +1 -1
  22. package/dist-site-viewer/assets/index-Y_Z9U6zO.js +4826 -0
  23. package/dist-site-viewer/assets/numbl-worker-CdHI6Ort.js +12088 -0
  24. package/dist-site-viewer/index.html +1 -1
  25. package/dist-site-viewer/numbl-embed.js +131 -18
  26. package/package.json +1 -1
  27. package/dist-plot-viewer/assets/index-ClpZQuMR.js +0 -4426
  28. package/dist-site-viewer/assets/index-CgKjTQT7.js +0 -4748
  29. package/dist-site-viewer/assets/numbl-worker-DarsHbBe.js +0 -11993
@@ -7,7 +7,7 @@
7
7
  <title>numbl project</title>
8
8
  <!-- numbl:base -->
9
9
  <script src="./coi-serviceworker.js"></script>
10
- <script type="module" crossorigin src="./assets/index-CgKjTQT7.js"></script>
10
+ <script type="module" crossorigin src="./assets/index-Y_Z9U6zO.js"></script>
11
11
  <link rel="stylesheet" crossorigin href="./assets/index-D5YY8PKx.css">
12
12
  </head>
13
13
  <body>
@@ -5,17 +5,65 @@ Usage:
5
5
  <numbl-embed>
6
6
  <iframe width="100%" height="500" frameborder="0"></iframe>
7
7
 
8
- <script type="text/plain" class="matlab-script">
9
- ... MATLAB script ...
8
+ <script type="text/plain" class="numbl-script">
9
+ ... numbl script ...
10
10
  </script>
11
11
 
12
12
  </numbl-embed>
13
13
 
14
- You can also specify the MATLAB script URL via attribute:
15
- <numbl-embed script="relative-or-absolute-url-to-matlab-script">
14
+ Optional preamble: setup code that runs before the visible script on every Run
15
+ (e.g. installing a package with `mip load --install ...`). It is kept out of the
16
+ editor, and its console output is hidden behind a "Preparing…" message unless it
17
+ errors — in which case the output and error are shown. Override that message
18
+ per-embed with the `preparing-label` attribute (e.g. "Installing…").
19
+
20
+ <numbl-embed preparing-label="Installing…">
21
+ <iframe width="100%" height="500" frameborder="0"></iframe>
22
+
23
+ <script type="text/plain" class="numbl-preamble">
24
+ mip load --install owner/repo/package
25
+ </script>
26
+
27
+ <script type="text/plain" class="numbl-script">
28
+ ... numbl script ...
29
+ </script>
30
+
31
+ </numbl-embed>
32
+
33
+ The classes `matlab-script` / `matlab-preamble` are accepted as synonyms for
34
+ `numbl-script` / `numbl-preamble` (backward compatibility with older embeds).
35
+
36
+ You can also specify the script URL via attribute (a `numbl-preamble` block still
37
+ applies):
38
+ <numbl-embed script="relative-or-absolute-url-to-script">
16
39
  <iframe width="100%" height="500" frameborder="0"></iframe>
17
40
  </numbl-embed>
41
+
42
+ Lazy mode (recommended when many embeds share a page, e.g. documentation):
43
+ add the `lazy` attribute and the iframe is not loaded until the reader clicks
44
+ an "Edit & run" button. This keeps the page light — no worker, editor, or
45
+ package download boots until the reader asks for it. Customize the button text
46
+ with the `label` attribute.
47
+
48
+ <numbl-embed lazy label="▶ Edit & run this example"
49
+ script="https://example.com/snippet.m">
50
+ <iframe width="100%" height="560" frameborder="0"></iframe>
51
+ </numbl-embed>
18
52
  */
53
+ // Base64-encode a string as UTF-8. Plain btoa() throws on any character
54
+ // outside Latin-1 (e.g. an em dash or a Greek letter in a comment/title), so
55
+ // we go through the UTF-8 bytes. For pure-ASCII input this is byte-identical
56
+ // to btoa(), so it stays compatible with older /embed decoders.
57
+ function utf8ToBase64(text) {
58
+ const bytes = new TextEncoder().encode(text);
59
+ let binary = "";
60
+ const chunk = 0x8000;
61
+ for (let i = 0; i < bytes.length; i += chunk) {
62
+ binary += String.fromCharCode.apply(null, bytes.subarray(i, i + chunk));
63
+ }
64
+ return btoa(binary);
65
+ }
66
+
19
67
  class NumblEmbed extends HTMLElement {
20
68
  constructor() {
21
69
  super();
@@ -23,19 +71,65 @@ class NumblEmbed extends HTMLElement {
23
71
 
24
72
  connectedCallback() {
25
73
  if (document.readyState === "loading") {
26
- document.addEventListener("DOMContentLoaded", () => this.initialize());
74
+ document.addEventListener("DOMContentLoaded", () => this.setup());
27
75
  } else {
28
- this.initialize();
76
+ this.setup();
29
77
  }
30
78
  }
31
79
 
32
- initialize() {
80
+ setup() {
33
81
  this.iframe = this.querySelector("iframe");
34
82
  if (!this.iframe) {
35
83
  console.error("Missing iframe element in numbl-embed");
36
84
  return;
37
85
  }
38
86
 
87
+ // Lazy mode: defer all loading until the reader opts in by clicking.
88
+ if (this.hasAttribute("lazy")) {
89
+ this.renderActivateButton();
90
+ } else {
91
+ this.activate();
92
+ }
93
+ }
94
+
95
+ renderActivateButton() {
96
+ this.iframe.style.display = "none";
97
+
98
+ const button = document.createElement("button");
99
+ button.type = "button";
100
+ button.className = "numbl-embed-activate";
101
+ button.textContent = this.getAttribute("label") || "▶ Edit & run in numbl";
102
+ // Inline styles so the button looks reasonable even without external CSS;
103
+ // a page may override via the .numbl-embed-activate class.
104
+ button.style.cssText = [
105
+ "display:inline-flex",
106
+ "align-items:center",
107
+ "gap:0.4em",
108
+ "padding:0.45em 0.9em",
109
+ "font-size:0.85rem",
110
+ "font-family:inherit",
111
+ "color:#fff",
112
+ "background:#2e7d32",
113
+ "border:none",
114
+ "border-radius:4px",
115
+ "cursor:pointer",
116
+ ].join(";");
117
+
118
+ button.addEventListener(
119
+ "click",
120
+ () => {
121
+ button.remove();
122
+ this.iframe.style.display = "";
123
+ this.activate();
124
+ },
125
+ { once: true }
126
+ );
127
+
128
+ this.activateButton = button;
129
+ this.insertBefore(button, this.iframe);
130
+ }
131
+
132
+ activate() {
39
133
  const defaultNumblUrl = "https://numbl.org";
40
134
  const numblUrl = this.attributes["numbl-url"]?.value || defaultNumblUrl;
41
135
  const cacheBust = `_cb=${Date.now()}`;
@@ -49,31 +143,50 @@ class NumblEmbed extends HTMLElement {
49
143
 
50
144
  const encodePlain = text => {
51
145
  const text2 = text.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
52
- return btoa(text2);
146
+ return utf8ToBase64(text2);
53
147
  };
54
148
 
55
- const scriptElement = this.querySelector("script.matlab-script");
149
+ // Optional preamble: setup code that runs (hidden) before the visible
150
+ // script. `numbl-preamble` is preferred; `matlab-preamble` is a synonym.
151
+ const preambleElement = this.querySelector(
152
+ "script.numbl-preamble, script.matlab-preamble"
153
+ );
154
+ let preambleParam = preambleElement
155
+ ? `&preamble=${encodePlain(preambleElement.textContent.trim())}`
156
+ : "";
157
+
158
+ // Message shown while the preamble runs (defaults to "Preparing..." in the
159
+ // embed page). Override per-embed with the `preparing-label` attribute,
160
+ // e.g. preparing-label="Installing...".
161
+ const preparingLabel = this.getAttribute("preparing-label");
162
+ if (preambleParam && preparingLabel) {
163
+ preambleParam += `&preparing=${utf8ToBase64(preparingLabel)}`;
164
+ }
165
+
166
+ // `numbl-script` is preferred; `matlab-script` is a synonym.
167
+ const scriptElement = this.querySelector(
168
+ "script.numbl-script, script.matlab-script"
169
+ );
56
170
 
57
171
  let scriptBase64;
58
172
  if (scriptElement) {
59
- const matlabScript = scriptElement.textContent.trim();
60
- scriptBase64 = encodePlain(matlabScript);
173
+ scriptBase64 = encodePlain(scriptElement.textContent.trim());
61
174
  } else if (this.attributes.script) {
62
175
  const scriptUrl = this.attributes.script.value;
63
- this.loadScriptFromUrl(scriptUrl);
176
+ this.loadScriptFromUrl(scriptUrl, preambleParam);
64
177
  return;
65
178
  } else {
66
179
  scriptBase64 = null;
67
180
  }
68
181
 
69
182
  if (scriptBase64) {
70
- this.iframe.src = `${numblUrl}/embed?script=${scriptBase64}&${cacheBust}`;
183
+ this.iframe.src = `${numblUrl}/embed?script=${scriptBase64}${preambleParam}&${cacheBust}`;
71
184
  } else {
72
- this.iframe.src = `${numblUrl}/embed?${cacheBust}`;
185
+ this.iframe.src = `${numblUrl}/embed?${cacheBust}${preambleParam}`;
73
186
  }
74
187
  }
75
188
 
76
- async loadScriptFromUrl(url) {
189
+ async loadScriptFromUrl(url, preambleParam = "") {
77
190
  try {
78
191
  let absoluteUrl = url;
79
192
  if (url.startsWith("./") || url.startsWith("../")) {
@@ -87,15 +200,15 @@ class NumblEmbed extends HTMLElement {
87
200
  }
88
201
 
89
202
  const scriptContent = await response.text();
90
- const scriptBase64 = btoa(scriptContent);
203
+ const scriptBase64 = utf8ToBase64(scriptContent);
91
204
 
92
205
  const defaultNumblUrl = "https://numbl.org";
93
206
  const numblUrl = this.attributes["numbl-url"]?.value || defaultNumblUrl;
94
207
 
95
208
  const cacheBust = `_cb=${Date.now()}`;
96
- this.iframe.src = `${numblUrl}/embed?script=${scriptBase64}&${cacheBust}`;
209
+ this.iframe.src = `${numblUrl}/embed?script=${scriptBase64}${preambleParam}&${cacheBust}`;
97
210
  } catch (error) {
98
- console.error("Error loading MATLAB script:", error);
211
+ console.error("Error loading script:", error);
99
212
  this.iframe.srcdoc = `
100
213
  <html>
101
214
  <body style="font-family: Arial; padding: 20px;">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numbl",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Run .m source files in the browser and on the command line by compiling to JavaScript",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",