@brianmsm/quarto-bento 0.0.0-stage → 0.1.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.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -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 +232 -0
  20. package/distribution/runtime/src/core/agent.ts +546 -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 +851 -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 +2557 -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 +892 -0
  100. package/distribution/runtime/src/studio/components.js +188 -0
  101. package/distribution/runtime/src/studio/index.html +283 -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 +461 -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,232 @@
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 {
4
+ applySync,
5
+ previewSelectedSync,
6
+ previewSync,
7
+ readSyncSelectionFile,
8
+ } from "./core/sync.ts";
9
+ import { recoverProject } from "./core/recovery.ts";
10
+ import { extractDocument } from "./render/html.ts";
11
+ import { startStudio } from "./studio/server.ts";
12
+ import { installQuartoProject } from "./integration/install.ts";
13
+ import { recoverQuartoRender } from "./integration/quarto.ts";
14
+ import { assertBentoContract } from "./render/validate.ts";
15
+ import { applyReconcile, previewReconcile } from "./core/reconcile.ts";
16
+ import {
17
+ getAgentDeck,
18
+ patchAgentDeck,
19
+ readAgentPatchFile,
20
+ } from "./core/agent.ts";
21
+ const help = `qbento <command> <presentation.qmd> [arguments]
22
+
23
+ render Execute Quarto and retain saved design
24
+ capture [edited.html] Explicitly capture native local HTML edits
25
+ status | diff Inspect durable pending changes
26
+ get Read the saved deck, revision, provenance and pending edits
27
+ patch <payload.json> Apply bounded structured edits to saved state; never writes QMD
28
+ sync [--select selection.json | --apply plan.json] Preview all/selected source changes or apply an inspected plan
29
+ reconcile [--apply resolution.json] Execute conflict preview, or apply {plan,choices} to saved state
30
+ recover [inspect|finish|rollback] Inspect or explicitly recover an interrupted operation
31
+ init [--extension-only] Install the offline Quarto integration without replacing existing configuration
32
+ quarto-recover Recover an interrupted ordinary Quarto invocation
33
+ edit Start local Bento Studio
34
+ validate <deck.html> Validate the document envelope and stable IDs
35
+ doctor Report available runtime versions
36
+
37
+ Commands emit JSON. Save, sync and render are separate operations.
38
+ `;
39
+ if (import.meta.main) {
40
+ const [command, source, extra] = Deno.args;
41
+ try {
42
+ let result: unknown;
43
+ switch (command) {
44
+ case "render": {
45
+ if (!source) throw new Error("QMD path required");
46
+ const r = await renderProject(source);
47
+ result = {
48
+ output: r.output,
49
+ revision: r.state.revision,
50
+ docId: r.state.docId,
51
+ pending: r.state.pending.length,
52
+ diagnostics: r.diagnostics,
53
+ };
54
+ break;
55
+ }
56
+ case "capture": {
57
+ if (!source) throw new Error("QMD path required");
58
+ const r = await captureProject(source, extra);
59
+ result = {
60
+ revision: r.state.revision,
61
+ pending: r.pending,
62
+ overrides: r.overrides,
63
+ };
64
+ break;
65
+ }
66
+ case "status":
67
+ case "diff": {
68
+ if (!source) throw new Error("QMD path required");
69
+ const s = await readProject(source);
70
+ result = {
71
+ docId: s.docId,
72
+ revision: s.revision,
73
+ pending: s.pending,
74
+ overrides: s.overrides,
75
+ };
76
+ break;
77
+ }
78
+ case "get": {
79
+ if (!source || extra !== undefined || Deno.args.length !== 2) {
80
+ throw new Error("AGENT_USAGE: Use get source.qmd");
81
+ }
82
+ result = await getAgentDeck(source);
83
+ break;
84
+ }
85
+ case "patch": {
86
+ if (!source || !extra || Deno.args.length !== 3) {
87
+ throw new Error("AGENT_USAGE: Use patch source.qmd payload.json");
88
+ }
89
+ result = await patchAgentDeck(source, await readAgentPatchFile(extra));
90
+ break;
91
+ }
92
+ case "sync": {
93
+ if (!source) throw new Error("QMD path required");
94
+ if (extra === "--apply" && Deno.args[3] && Deno.args.length === 4) {
95
+ result = await applySync(
96
+ source,
97
+ JSON.parse(await Deno.readTextFile(Deno.args[3])),
98
+ );
99
+ } else if (
100
+ extra === "--select" && Deno.args[3] && Deno.args.length === 4
101
+ ) {
102
+ result = await previewSelectedSync(
103
+ source,
104
+ await readSyncSelectionFile(Deno.args[3]),
105
+ );
106
+ } else if (extra === undefined && Deno.args.length === 2) {
107
+ result = await previewSync(source);
108
+ } else {throw new Error(
109
+ "Use sync source.qmd [--select selection.json | --apply plan.json]",
110
+ );}
111
+ break;
112
+ }
113
+ case "recover": {
114
+ if (!source) throw new Error("QMD path required");
115
+ if (
116
+ extra !== undefined &&
117
+ !["inspect", "finish", "rollback"].includes(extra)
118
+ ) {
119
+ throw new Error(
120
+ "Recovery action must be inspect, finish or rollback",
121
+ );
122
+ }
123
+ result = await recoverProject(
124
+ source,
125
+ extra as "inspect" | "finish" | "rollback" | undefined,
126
+ );
127
+ break;
128
+ }
129
+ case "reconcile": {
130
+ if (!source) throw new Error("QMD path required");
131
+ if (extra === undefined) result = await previewReconcile(source);
132
+ else if (extra === "--apply" && Deno.args[3]) {
133
+ const { plan, choices } = JSON.parse(
134
+ await Deno.readTextFile(Deno.args[3]),
135
+ );
136
+ result = await applyReconcile(source, plan, choices);
137
+ } else {throw new Error(
138
+ "Use reconcile source.qmd [--apply resolution.json]",
139
+ );}
140
+ break;
141
+ }
142
+ case "validate": {
143
+ if (!source) throw new Error("HTML path required");
144
+ const d = extractDocument(await Deno.readTextFile(source));
145
+ assertBentoContract(d);
146
+ result = { valid: true, docId: d.docId, slides: d.slides.length };
147
+ break;
148
+ }
149
+ case "doctor": {
150
+ const versions: Record<string, string> = {
151
+ deno: Deno.version.deno,
152
+ os: Deno.build.os,
153
+ };
154
+ // Chromium is optional: only computed rich-table/Plotly capture needs it.
155
+ for (const executable of ["quarto", "Rscript", "chromium"]) {
156
+ try {
157
+ const r = await new Deno.Command(executable, {
158
+ args: ["--version"],
159
+ stdout: "piped",
160
+ stderr: "piped",
161
+ }).output();
162
+ versions[executable] = new TextDecoder().decode(
163
+ r.stdout.length ? r.stdout : r.stderr,
164
+ ).trim();
165
+ } catch {
166
+ versions[executable] = "unavailable";
167
+ }
168
+ }
169
+ result = versions;
170
+ break;
171
+ }
172
+ case "edit": {
173
+ if (!source) throw new Error("QMD path required");
174
+ // Existing pending edits must remain accessible even when strict rendering refuses.
175
+ try {
176
+ await readProject(source);
177
+ } catch (error) {
178
+ if (
179
+ !(error instanceof Error) ||
180
+ ((error as { code?: string }).code !== "NO_BASELINE" &&
181
+ !error.message.startsWith("NO_BASELINE:"))
182
+ ) throw error;
183
+ await renderProject(source);
184
+ }
185
+ const s = await startStudio(source);
186
+ console.log(JSON.stringify({ url: s.url }));
187
+ await s.finished;
188
+ break;
189
+ }
190
+ case "init": {
191
+ if (!source) throw new Error("QMD path required");
192
+ if (extra !== undefined && extra !== "--extension-only") {
193
+ throw new Error("Use init source.qmd [--extension-only]");
194
+ }
195
+ result = await installQuartoProject(source, {
196
+ configure: extra !== "--extension-only",
197
+ });
198
+ break;
199
+ }
200
+ case "quarto-recover": {
201
+ if (!source) throw new Error("QMD path required");
202
+ result = await recoverQuartoRender(source);
203
+ break;
204
+ }
205
+ case "help":
206
+ case "--help":
207
+ case undefined:
208
+ console.log(help);
209
+ break;
210
+ default:
211
+ throw new Error(`UNKNOWN_COMMAND: ${command}`);
212
+ }
213
+ if (result !== undefined) console.log(JSON.stringify(result, null, 2));
214
+ } catch (error) {
215
+ const e = error as Error & { code?: string; details?: unknown };
216
+ console.error(
217
+ JSON.stringify(
218
+ {
219
+ error: e.code ||
220
+ (["get", "patch"].includes(command) &&
221
+ e.message.match(/^([A-Z][A-Z_0-9]+):/)?.[1]) ||
222
+ "QBENTO_ERROR",
223
+ message: e.message,
224
+ details: e.details,
225
+ },
226
+ null,
227
+ 2,
228
+ ),
229
+ );
230
+ Deno.exitCode = 1;
231
+ }
232
+ }