@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.
- package/LICENSE +21 -0
- package/README.md +93 -2
- package/bin/qbento-npm.mjs +62 -0
- package/distribution/LICENSE +21 -0
- package/distribution/PACKAGING.md +59 -0
- package/distribution/bin/qbento +5 -0
- package/distribution/bin/qbento.cmd +4 -0
- package/distribution/manifest.json +720 -0
- package/distribution/runtime/LICENSE +21 -0
- package/distribution/runtime/_extensions/qbento/_extension.yml +24 -0
- package/distribution/runtime/_extensions/qbento/capture.lua +21 -0
- package/distribution/runtime/_extensions/qbento/guard.lua +7 -0
- package/distribution/runtime/_extensions/qbento/post.ts +2 -0
- package/distribution/runtime/_extensions/qbento/pre.ts +2 -0
- package/distribution/runtime/_extensions/qbento/producer-activation.js +129 -0
- package/distribution/runtime/src/bridge/browser.js +168 -0
- package/distribution/runtime/src/bridge/isolation.ts +55 -0
- package/distribution/runtime/src/browser/chromium.ts +218 -0
- package/distribution/runtime/src/cli.ts +232 -0
- package/distribution/runtime/src/core/agent.ts +546 -0
- package/distribution/runtime/src/core/annotations.ts +384 -0
- package/distribution/runtime/src/core/capture.ts +203 -0
- package/distribution/runtime/src/core/component-actions.ts +550 -0
- package/distribution/runtime/src/core/component-frames.ts +59 -0
- package/distribution/runtime/src/core/component-sync.ts +290 -0
- package/distribution/runtime/src/core/design-diagnostics.ts +78 -0
- package/distribution/runtime/src/core/design-registry.ts +287 -0
- package/distribution/runtime/src/core/graph-relations.ts +354 -0
- package/distribution/runtime/src/core/graph-scope.ts +63 -0
- package/distribution/runtime/src/core/graph-sync.ts +228 -0
- package/distribution/runtime/src/core/io.ts +27 -0
- package/distribution/runtime/src/core/kpi-appearance.ts +205 -0
- package/distribution/runtime/src/core/layouts.ts +245 -0
- package/distribution/runtime/src/core/project.ts +851 -0
- package/distribution/runtime/src/core/reconcile.ts +384 -0
- package/distribution/runtime/src/core/recovery.ts +1255 -0
- package/distribution/runtime/src/core/slide-actions.ts +158 -0
- package/distribution/runtime/src/core/source-scope.ts +50 -0
- package/distribution/runtime/src/core/sync.ts +2557 -0
- package/distribution/runtime/src/core/widgets.ts +300 -0
- package/distribution/runtime/src/integration/install.ts +98 -0
- package/distribution/runtime/src/integration/invocation.ts +100 -0
- package/distribution/runtime/src/integration/quarto.ts +457 -0
- package/distribution/runtime/src/render/assets.ts +66 -0
- package/distribution/runtime/src/render/capture.lua +8 -0
- package/distribution/runtime/src/render/chart.ts +165 -0
- package/distribution/runtime/src/render/components.ts +199 -0
- package/distribution/runtime/src/render/design.ts +820 -0
- package/distribution/runtime/src/render/diagnostics.ts +36 -0
- package/distribution/runtime/src/render/graphs.ts +747 -0
- package/distribution/runtime/src/render/html.ts +82 -0
- package/distribution/runtime/src/render/images.ts +268 -0
- package/distribution/runtime/src/render/inline.ts +259 -0
- package/distribution/runtime/src/render/kpi.ts +385 -0
- package/distribution/runtime/src/render/lists.ts +183 -0
- package/distribution/runtime/src/render/math.ts +413 -0
- package/distribution/runtime/src/render/measure.ts +185 -0
- package/distribution/runtime/src/render/native-layout.ts +174 -0
- package/distribution/runtime/src/render/producer-capture.ts +319 -0
- package/distribution/runtime/src/render/producer-environment.R +49 -0
- package/distribution/runtime/src/render/producer-environment.ts +96 -0
- package/distribution/runtime/src/render/producer-profile.R +91 -0
- package/distribution/runtime/src/render/producer-site-profile.R +18 -0
- package/distribution/runtime/src/render/project.ts +1806 -0
- package/distribution/runtime/src/render/quarto.ts +127 -0
- package/distribution/runtime/src/render/registry.ts +233 -0
- package/distribution/runtime/src/render/resources.ts +292 -0
- package/distribution/runtime/src/render/shell.ts +110 -0
- package/distribution/runtime/src/render/source-inline.ts +169 -0
- package/distribution/runtime/src/render/table.ts +220 -0
- package/distribution/runtime/src/render/text-overflow.ts +208 -0
- package/distribution/runtime/src/render/types.ts +71 -0
- package/distribution/runtime/src/render/validate.ts +572 -0
- package/distribution/runtime/src/rich/project.ts +117 -0
- package/distribution/runtime/src/rich/table.ts +374 -0
- package/distribution/runtime/src/source/annotations.ts +490 -0
- package/distribution/runtime/src/source/attributes.ts +415 -0
- package/distribution/runtime/src/source/chart.ts +165 -0
- package/distribution/runtime/src/source/code-language.ts +277 -0
- package/distribution/runtime/src/source/component-insertion.ts +160 -0
- package/distribution/runtime/src/source/deletion.ts +278 -0
- package/distribution/runtime/src/source/graphs.ts +517 -0
- package/distribution/runtime/src/source/identities.ts +256 -0
- package/distribution/runtime/src/source/identity-id.ts +6 -0
- package/distribution/runtime/src/source/image.ts +50 -0
- package/distribution/runtime/src/source/kpi.ts +196 -0
- package/distribution/runtime/src/source/mod.ts +876 -0
- package/distribution/runtime/src/source/notes.ts +308 -0
- package/distribution/runtime/src/source/structure.ts +647 -0
- package/distribution/runtime/src/source/table.ts +290 -0
- package/distribution/runtime/src/source/text-conversion.ts +146 -0
- package/distribution/runtime/src/state/components.ts +281 -0
- package/distribution/runtime/src/state/graphs.ts +200 -0
- package/distribution/runtime/src/state/json.ts +162 -0
- package/distribution/runtime/src/state/merge.ts +1034 -0
- package/distribution/runtime/src/state/mod.ts +5 -0
- package/distribution/runtime/src/state/store.ts +226 -0
- package/distribution/runtime/src/state/types.ts +151 -0
- package/distribution/runtime/src/studio/client.js +892 -0
- package/distribution/runtime/src/studio/components.js +188 -0
- package/distribution/runtime/src/studio/index.html +283 -0
- package/distribution/runtime/src/studio/layouts.js +170 -0
- package/distribution/runtime/src/studio/registry.js +283 -0
- package/distribution/runtime/src/studio/relations.js +169 -0
- package/distribution/runtime/src/studio/server.ts +461 -0
- package/distribution/runtime/src/widgets/deck.ts +39 -0
- package/distribution/runtime/src/widgets/plotly.ts +354 -0
- package/distribution/runtime/src/widgets/presenter.ts +367 -0
- package/distribution/runtime/src/widgets/snapshot.ts +116 -0
- package/distribution/runtime/vendor/bento/FONT_NOTICES.md +49 -0
- package/distribution/runtime/vendor/bento/LICENSE +21 -0
- package/distribution/runtime/vendor/bento/THIRD_PARTY_NOTICES.md +51 -0
- package/distribution/runtime/vendor/bento/font-licenses/fraunces-OFL.txt +93 -0
- package/distribution/runtime/vendor/bento/font-licenses/instrument-sans-OFL.txt +93 -0
- package/distribution/runtime/vendor/bento/pin.json +69 -0
- package/distribution/runtime/vendor/bento/provenance/slides.package-lock.json +1928 -0
- package/distribution/runtime/vendor/bento/provenance/slides.package.json +28 -0
- package/distribution/runtime/vendor/bento/runtime-dependencies.json +244 -0
- package/distribution/runtime/vendor/bento/runtime-licenses.json +4038 -0
- package/distribution/runtime/vendor/bento/shell.html +269 -0
- package/distribution/runtime/vendor/bento/slides.schema.json +2379 -0
- 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
|
+
}
|