@brianmsm/quarto-bento 0.0.0-stage → 0.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.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -2
  3. package/bin/qbento-npm.mjs +62 -0
  4. package/distribution/LICENSE +21 -0
  5. package/distribution/PACKAGING.md +59 -0
  6. package/distribution/bin/qbento +5 -0
  7. package/distribution/bin/qbento.cmd +4 -0
  8. package/distribution/manifest.json +720 -0
  9. package/distribution/runtime/LICENSE +21 -0
  10. package/distribution/runtime/_extensions/qbento/_extension.yml +24 -0
  11. package/distribution/runtime/_extensions/qbento/capture.lua +21 -0
  12. package/distribution/runtime/_extensions/qbento/guard.lua +7 -0
  13. package/distribution/runtime/_extensions/qbento/post.ts +2 -0
  14. package/distribution/runtime/_extensions/qbento/pre.ts +2 -0
  15. package/distribution/runtime/_extensions/qbento/producer-activation.js +129 -0
  16. package/distribution/runtime/src/bridge/browser.js +168 -0
  17. package/distribution/runtime/src/bridge/isolation.ts +55 -0
  18. package/distribution/runtime/src/browser/chromium.ts +218 -0
  19. package/distribution/runtime/src/cli.ts +219 -0
  20. package/distribution/runtime/src/core/agent.ts +565 -0
  21. package/distribution/runtime/src/core/annotations.ts +384 -0
  22. package/distribution/runtime/src/core/capture.ts +203 -0
  23. package/distribution/runtime/src/core/component-actions.ts +550 -0
  24. package/distribution/runtime/src/core/component-frames.ts +59 -0
  25. package/distribution/runtime/src/core/component-sync.ts +290 -0
  26. package/distribution/runtime/src/core/design-diagnostics.ts +78 -0
  27. package/distribution/runtime/src/core/design-registry.ts +287 -0
  28. package/distribution/runtime/src/core/graph-relations.ts +354 -0
  29. package/distribution/runtime/src/core/graph-scope.ts +63 -0
  30. package/distribution/runtime/src/core/graph-sync.ts +228 -0
  31. package/distribution/runtime/src/core/io.ts +27 -0
  32. package/distribution/runtime/src/core/kpi-appearance.ts +205 -0
  33. package/distribution/runtime/src/core/layouts.ts +245 -0
  34. package/distribution/runtime/src/core/project.ts +759 -0
  35. package/distribution/runtime/src/core/reconcile.ts +384 -0
  36. package/distribution/runtime/src/core/recovery.ts +1255 -0
  37. package/distribution/runtime/src/core/slide-actions.ts +158 -0
  38. package/distribution/runtime/src/core/source-scope.ts +50 -0
  39. package/distribution/runtime/src/core/sync.ts +2423 -0
  40. package/distribution/runtime/src/core/widgets.ts +300 -0
  41. package/distribution/runtime/src/integration/install.ts +98 -0
  42. package/distribution/runtime/src/integration/invocation.ts +100 -0
  43. package/distribution/runtime/src/integration/quarto.ts +457 -0
  44. package/distribution/runtime/src/render/assets.ts +66 -0
  45. package/distribution/runtime/src/render/capture.lua +8 -0
  46. package/distribution/runtime/src/render/chart.ts +165 -0
  47. package/distribution/runtime/src/render/components.ts +199 -0
  48. package/distribution/runtime/src/render/design.ts +820 -0
  49. package/distribution/runtime/src/render/diagnostics.ts +36 -0
  50. package/distribution/runtime/src/render/graphs.ts +747 -0
  51. package/distribution/runtime/src/render/html.ts +82 -0
  52. package/distribution/runtime/src/render/images.ts +268 -0
  53. package/distribution/runtime/src/render/inline.ts +259 -0
  54. package/distribution/runtime/src/render/kpi.ts +385 -0
  55. package/distribution/runtime/src/render/lists.ts +183 -0
  56. package/distribution/runtime/src/render/math.ts +413 -0
  57. package/distribution/runtime/src/render/measure.ts +185 -0
  58. package/distribution/runtime/src/render/native-layout.ts +174 -0
  59. package/distribution/runtime/src/render/producer-capture.ts +319 -0
  60. package/distribution/runtime/src/render/producer-environment.R +49 -0
  61. package/distribution/runtime/src/render/producer-environment.ts +96 -0
  62. package/distribution/runtime/src/render/producer-profile.R +91 -0
  63. package/distribution/runtime/src/render/producer-site-profile.R +18 -0
  64. package/distribution/runtime/src/render/project.ts +1806 -0
  65. package/distribution/runtime/src/render/quarto.ts +127 -0
  66. package/distribution/runtime/src/render/registry.ts +233 -0
  67. package/distribution/runtime/src/render/resources.ts +292 -0
  68. package/distribution/runtime/src/render/shell.ts +110 -0
  69. package/distribution/runtime/src/render/source-inline.ts +169 -0
  70. package/distribution/runtime/src/render/table.ts +220 -0
  71. package/distribution/runtime/src/render/text-overflow.ts +208 -0
  72. package/distribution/runtime/src/render/types.ts +71 -0
  73. package/distribution/runtime/src/render/validate.ts +572 -0
  74. package/distribution/runtime/src/rich/project.ts +117 -0
  75. package/distribution/runtime/src/rich/table.ts +374 -0
  76. package/distribution/runtime/src/source/annotations.ts +490 -0
  77. package/distribution/runtime/src/source/attributes.ts +415 -0
  78. package/distribution/runtime/src/source/chart.ts +165 -0
  79. package/distribution/runtime/src/source/code-language.ts +277 -0
  80. package/distribution/runtime/src/source/component-insertion.ts +160 -0
  81. package/distribution/runtime/src/source/deletion.ts +278 -0
  82. package/distribution/runtime/src/source/graphs.ts +517 -0
  83. package/distribution/runtime/src/source/identities.ts +256 -0
  84. package/distribution/runtime/src/source/identity-id.ts +6 -0
  85. package/distribution/runtime/src/source/image.ts +50 -0
  86. package/distribution/runtime/src/source/kpi.ts +196 -0
  87. package/distribution/runtime/src/source/mod.ts +876 -0
  88. package/distribution/runtime/src/source/notes.ts +308 -0
  89. package/distribution/runtime/src/source/structure.ts +647 -0
  90. package/distribution/runtime/src/source/table.ts +290 -0
  91. package/distribution/runtime/src/source/text-conversion.ts +146 -0
  92. package/distribution/runtime/src/state/components.ts +281 -0
  93. package/distribution/runtime/src/state/graphs.ts +200 -0
  94. package/distribution/runtime/src/state/json.ts +162 -0
  95. package/distribution/runtime/src/state/merge.ts +1034 -0
  96. package/distribution/runtime/src/state/mod.ts +5 -0
  97. package/distribution/runtime/src/state/store.ts +226 -0
  98. package/distribution/runtime/src/state/types.ts +151 -0
  99. package/distribution/runtime/src/studio/client.js +790 -0
  100. package/distribution/runtime/src/studio/components.js +188 -0
  101. package/distribution/runtime/src/studio/index.html +278 -0
  102. package/distribution/runtime/src/studio/layouts.js +170 -0
  103. package/distribution/runtime/src/studio/registry.js +283 -0
  104. package/distribution/runtime/src/studio/relations.js +169 -0
  105. package/distribution/runtime/src/studio/server.ts +433 -0
  106. package/distribution/runtime/src/widgets/deck.ts +39 -0
  107. package/distribution/runtime/src/widgets/plotly.ts +354 -0
  108. package/distribution/runtime/src/widgets/presenter.ts +367 -0
  109. package/distribution/runtime/src/widgets/snapshot.ts +116 -0
  110. package/distribution/runtime/vendor/bento/FONT_NOTICES.md +49 -0
  111. package/distribution/runtime/vendor/bento/LICENSE +21 -0
  112. package/distribution/runtime/vendor/bento/THIRD_PARTY_NOTICES.md +51 -0
  113. package/distribution/runtime/vendor/bento/font-licenses/fraunces-OFL.txt +93 -0
  114. package/distribution/runtime/vendor/bento/font-licenses/instrument-sans-OFL.txt +93 -0
  115. package/distribution/runtime/vendor/bento/pin.json +69 -0
  116. package/distribution/runtime/vendor/bento/provenance/slides.package-lock.json +1928 -0
  117. package/distribution/runtime/vendor/bento/provenance/slides.package.json +28 -0
  118. package/distribution/runtime/vendor/bento/runtime-dependencies.json +244 -0
  119. package/distribution/runtime/vendor/bento/runtime-licenses.json +4038 -0
  120. package/distribution/runtime/vendor/bento/shell.html +269 -0
  121. package/distribution/runtime/vendor/bento/slides.schema.json +2379 -0
  122. package/package.json +40 -4
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env -S deno run --allow-read --allow-write --allow-run --allow-env --allow-net=127.0.0.1
2
+ import { captureProject, readProject, renderProject } from "./core/project.ts";
3
+ import { applySync, previewSync } from "./core/sync.ts";
4
+ import { recoverProject } from "./core/recovery.ts";
5
+ import { extractDocument } from "./render/html.ts";
6
+ import { startStudio } from "./studio/server.ts";
7
+ import { installQuartoProject } from "./integration/install.ts";
8
+ import { recoverQuartoRender } from "./integration/quarto.ts";
9
+ import { assertBentoContract } from "./render/validate.ts";
10
+ import { applyReconcile, previewReconcile } from "./core/reconcile.ts";
11
+ import {
12
+ getAgentDeck,
13
+ patchAgentDeck,
14
+ readAgentPatchFile,
15
+ } from "./core/agent.ts";
16
+ const help = `qbento <command> <presentation.qmd> [arguments]
17
+
18
+ render Execute Quarto and retain saved design
19
+ capture [edited.html] Explicitly capture native local HTML edits
20
+ status | diff Inspect durable pending changes
21
+ get Read the saved deck, revision, provenance and pending edits
22
+ patch <payload.json> Apply bounded structured edits to saved state; never writes QMD
23
+ sync [--apply plan.json] Preview source changes or apply an inspected plan
24
+ reconcile [--apply resolution.json] Execute conflict preview, or apply {plan,choices} to saved state
25
+ recover [inspect|finish|rollback] Inspect or explicitly recover an interrupted operation
26
+ init [--extension-only] Install the offline Quarto integration without replacing existing configuration
27
+ quarto-recover Recover an interrupted ordinary Quarto invocation
28
+ edit Start local Bento Studio
29
+ validate <deck.html> Validate the document envelope and stable IDs
30
+ doctor Report available runtime versions
31
+
32
+ Commands emit JSON. Save, sync and render are separate operations.
33
+ `;
34
+ if (import.meta.main) {
35
+ const [command, source, extra] = Deno.args;
36
+ try {
37
+ let result: unknown;
38
+ switch (command) {
39
+ case "render": {
40
+ if (!source) throw new Error("QMD path required");
41
+ const r = await renderProject(source);
42
+ result = {
43
+ output: r.output,
44
+ revision: r.state.revision,
45
+ docId: r.state.docId,
46
+ pending: r.state.pending.length,
47
+ diagnostics: r.diagnostics,
48
+ };
49
+ break;
50
+ }
51
+ case "capture": {
52
+ if (!source) throw new Error("QMD path required");
53
+ const r = await captureProject(source, extra);
54
+ result = {
55
+ revision: r.state.revision,
56
+ pending: r.pending,
57
+ overrides: r.overrides,
58
+ };
59
+ break;
60
+ }
61
+ case "status":
62
+ case "diff": {
63
+ if (!source) throw new Error("QMD path required");
64
+ const s = await readProject(source);
65
+ result = {
66
+ docId: s.docId,
67
+ revision: s.revision,
68
+ pending: s.pending,
69
+ overrides: s.overrides,
70
+ };
71
+ break;
72
+ }
73
+ case "get": {
74
+ if (!source || extra !== undefined || Deno.args.length !== 2) {
75
+ throw new Error("AGENT_USAGE: Use get source.qmd");
76
+ }
77
+ result = await getAgentDeck(source);
78
+ break;
79
+ }
80
+ case "patch": {
81
+ if (!source || !extra || Deno.args.length !== 3) {
82
+ throw new Error("AGENT_USAGE: Use patch source.qmd payload.json");
83
+ }
84
+ result = await patchAgentDeck(source, await readAgentPatchFile(extra));
85
+ break;
86
+ }
87
+ case "sync": {
88
+ if (!source) throw new Error("QMD path required");
89
+ if (extra === "--apply") {
90
+ if (!Deno.args[3]) {
91
+ throw new Error("Inspected JSON plan path required");
92
+ }
93
+ result = await applySync(
94
+ source,
95
+ JSON.parse(await Deno.readTextFile(Deno.args[3])),
96
+ );
97
+ } else if (extra === undefined) result = await previewSync(source);
98
+ else throw new Error("Use sync source.qmd [--apply plan.json]");
99
+ break;
100
+ }
101
+ case "recover": {
102
+ if (!source) throw new Error("QMD path required");
103
+ if (
104
+ extra !== undefined &&
105
+ !["inspect", "finish", "rollback"].includes(extra)
106
+ ) {
107
+ throw new Error(
108
+ "Recovery action must be inspect, finish or rollback",
109
+ );
110
+ }
111
+ result = await recoverProject(
112
+ source,
113
+ extra as "inspect" | "finish" | "rollback" | undefined,
114
+ );
115
+ break;
116
+ }
117
+ case "reconcile": {
118
+ if (!source) throw new Error("QMD path required");
119
+ if (extra === undefined) result = await previewReconcile(source);
120
+ else if (extra === "--apply" && Deno.args[3]) {
121
+ const { plan, choices } = JSON.parse(
122
+ await Deno.readTextFile(Deno.args[3]),
123
+ );
124
+ result = await applyReconcile(source, plan, choices);
125
+ } else {throw new Error(
126
+ "Use reconcile source.qmd [--apply resolution.json]",
127
+ );}
128
+ break;
129
+ }
130
+ case "validate": {
131
+ if (!source) throw new Error("HTML path required");
132
+ const d = extractDocument(await Deno.readTextFile(source));
133
+ assertBentoContract(d);
134
+ result = { valid: true, docId: d.docId, slides: d.slides.length };
135
+ break;
136
+ }
137
+ case "doctor": {
138
+ const versions: Record<string, string> = {
139
+ deno: Deno.version.deno,
140
+ os: Deno.build.os,
141
+ };
142
+ // Chromium is optional: only computed rich-table/Plotly capture needs it.
143
+ for (const executable of ["quarto", "Rscript", "chromium"]) {
144
+ try {
145
+ const r = await new Deno.Command(executable, {
146
+ args: ["--version"],
147
+ stdout: "piped",
148
+ stderr: "piped",
149
+ }).output();
150
+ versions[executable] = new TextDecoder().decode(
151
+ r.stdout.length ? r.stdout : r.stderr,
152
+ ).trim();
153
+ } catch {
154
+ versions[executable] = "unavailable";
155
+ }
156
+ }
157
+ result = versions;
158
+ break;
159
+ }
160
+ case "edit": {
161
+ if (!source) throw new Error("QMD path required");
162
+ // Existing pending edits must remain accessible even when strict rendering refuses.
163
+ try {
164
+ await readProject(source);
165
+ } catch (error) {
166
+ if (
167
+ !(error instanceof Error) ||
168
+ !error.message.startsWith("NO_BASELINE:")
169
+ ) throw error;
170
+ await renderProject(source);
171
+ }
172
+ const s = await startStudio(source);
173
+ console.log(JSON.stringify({ url: s.url }));
174
+ await s.finished;
175
+ break;
176
+ }
177
+ case "init": {
178
+ if (!source) throw new Error("QMD path required");
179
+ if (extra !== undefined && extra !== "--extension-only") {
180
+ throw new Error("Use init source.qmd [--extension-only]");
181
+ }
182
+ result = await installQuartoProject(source, {
183
+ configure: extra !== "--extension-only",
184
+ });
185
+ break;
186
+ }
187
+ case "quarto-recover": {
188
+ if (!source) throw new Error("QMD path required");
189
+ result = await recoverQuartoRender(source);
190
+ break;
191
+ }
192
+ case "help":
193
+ case "--help":
194
+ case undefined:
195
+ console.log(help);
196
+ break;
197
+ default:
198
+ throw new Error(`UNKNOWN_COMMAND: ${command}`);
199
+ }
200
+ if (result !== undefined) console.log(JSON.stringify(result, null, 2));
201
+ } catch (error) {
202
+ const e = error as Error & { code?: string; details?: unknown };
203
+ console.error(
204
+ JSON.stringify(
205
+ {
206
+ error: e.code ||
207
+ (["get", "patch"].includes(command) &&
208
+ e.message.match(/^([A-Z][A-Z_0-9]+):/)?.[1]) ||
209
+ "QBENTO_ERROR",
210
+ message: e.message,
211
+ details: e.details,
212
+ },
213
+ null,
214
+ 2,
215
+ ),
216
+ );
217
+ Deno.exitCode = 1;
218
+ }
219
+ }