@marver-design/marver 0.16.1 → 0.18.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.
- package/CHANGELOG.md +93 -0
- package/README.md +3 -2
- package/dist/bake-jr38C_pX.mjs +747 -0
- package/dist/{build-B4yPgFNF.mjs → build-ER_7T6Cw.mjs} +179 -10
- package/dist/cli.mjs +21 -13
- package/dist/{comments-oYcZ3cE-.mjs → comments-ClVgfQib.mjs} +1 -1
- package/dist/{daemon-Bbh_jmui.mjs → daemon-CKhg0zuT.mjs} +1 -1
- package/dist/{dev-DH2W7Ffw.mjs → dev-BvLbY98O.mjs} +208 -9
- package/dist/{init-B7YhcN2o.mjs → init-BWbHqVng.mjs} +2 -2
- package/dist/{manifest-CaslQIAO.mjs → manifest-DAnEL8_a.mjs} +1 -1
- package/dist/{marver-id-gate-D6By7XHj.mjs → marver-id-gate-B_idGdHm.mjs} +1 -1
- package/dist/{plugin-BeBGu3gH.mjs → plugin-Cai5C1WV.mjs} +244 -47
- package/dist/{poster-CoyobbGW.mjs → poster-CIuz_PwH.mjs} +13 -5
- package/dist/publish-bakes-D0LhbQQ3.mjs +216 -0
- package/dist/{serve-Bcwfpvhl.mjs → serve-z5qtj_wJ.mjs} +3 -3
- package/dist/{share-Gqo_Ygqw.mjs → share--bdSc4G5.mjs} +1 -1
- package/dist/shot-BFEuYbaz.mjs +86 -0
- package/dist/shot-iicees2e.mjs +933 -0
- package/dist/{work-lzC-lPY0.mjs → work-0YopuMt9.mjs} +1 -1
- package/docs/live-jam.md +20 -8
- package/docs/publish.md +27 -5
- package/package.json +1 -1
- package/src/client/frame-host/bridge.js +4 -9
- package/src/client/frame-host/main.tsx +20 -6
- package/src/client/shell/App.tsx +7 -0
- package/src/client/shell/Comments.tsx +2 -2
- package/src/client/shell/canvas/Canvas.tsx +2 -2
- package/src/client/shell/canvas/FrameNode.tsx +82 -89
- package/src/client/shell/canvas/admission.ts +70 -0
- package/src/client/shell/canvas/sleep.ts +194 -0
- package/src/client/shell/store.ts +14 -0
- package/src/client/shell/styles.css +9 -25
- package/src/shared/sleep-rule.ts +41 -0
- package/templates/AGENTS-embedded.md +4 -1
- package/templates/AGENTS-studio.md +4 -1
- package/templates/instructions/craft.md +9 -0
- package/templates/instructions/jam.md +15 -3
- package/templates/instructions/publish.md +62 -9
- package/templates/instructions/shape.md +2 -1
- package/dist/shot-By1AItpD.mjs +0 -30
- package/dist/shot-z-d-zMzf.mjs +0 -528
- package/src/client/frame-host/serialize.ts +0 -195
- package/src/client/shell/canvas/snapshots.ts +0 -233
|
@@ -1,13 +1,155 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ROUTE, r as NAME } from "./cli.mjs";
|
|
2
2
|
import { a as listBoardFiles, d as flatten, f as isBoardName, n as checkBoardsDir, s as readRegistry, t as boardFields, u as buildTree } from "./boards-BmxcT3Lc.mjs";
|
|
3
|
-
import { l as detectHost, n as scanFrames, s as loadConfig } from "./manifest-
|
|
4
|
-
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-
|
|
3
|
+
import { l as detectHost, n as scanFrames, s as loadConfig } from "./manifest-DAnEL8_a.mjs";
|
|
4
|
+
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-Cai5C1WV.mjs";
|
|
5
5
|
import { cpSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { basename, dirname, join, sep } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { createHash, randomBytes } from "node:crypto";
|
|
9
9
|
import { build } from "vite";
|
|
10
10
|
import react from "@vitejs/plugin-react";
|
|
11
|
+
//#region src/server/css-fix.ts
|
|
12
|
+
/** Every `-webkit-backdrop-filter` declaration (the property itself, never a custom property that
|
|
13
|
+
* happens to end in it) is mirrored by the standard one right after it, in order, importance and
|
|
14
|
+
* all - the standard cascade then resolves exactly as the prefixed one did - unless the declaration
|
|
15
|
+
* list it belongs to declares the standard property already. The list is the enclosing block's own
|
|
16
|
+
* declarations: nested rules, their preludes included, are blanked. Strings and comments are masked
|
|
17
|
+
* first, so a brace or a declaration inside one is content, not syntax; values come from the
|
|
18
|
+
* original text. */
|
|
19
|
+
function keepBackdropFilter(css) {
|
|
20
|
+
const masked = maskCustomProperties(maskParens(css.replace(/\/\*[\s\S]*?\*\/|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\\[\s\S]/g, (m) => " ".repeat(m.length))));
|
|
21
|
+
const PREFIXED = /(^|[^-\w])-webkit-backdrop-filter\s*:/gi;
|
|
22
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23
|
+
const edits = [];
|
|
24
|
+
for (const m of masked.matchAll(PREFIXED)) {
|
|
25
|
+
const p = m.index + m[1].length;
|
|
26
|
+
let depth = 0, open = -1;
|
|
27
|
+
for (let i = p - 1; i >= 0; i--) {
|
|
28
|
+
const c = masked[i];
|
|
29
|
+
if (c === "}") depth++;
|
|
30
|
+
else if (c === "{") {
|
|
31
|
+
if (depth === 0) {
|
|
32
|
+
open = i;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
depth--;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (open < 0 || seen.has(open)) continue;
|
|
39
|
+
seen.add(open);
|
|
40
|
+
let close = masked.length;
|
|
41
|
+
depth = 0;
|
|
42
|
+
for (let i = open + 1; i < masked.length; i++) {
|
|
43
|
+
const c = masked[i];
|
|
44
|
+
if (c === "{") depth++;
|
|
45
|
+
else if (c === "}") {
|
|
46
|
+
if (depth === 0) {
|
|
47
|
+
close = i;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
depth--;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const own = masked.slice(open + 1, close).split("");
|
|
54
|
+
depth = 0;
|
|
55
|
+
let seg = 0;
|
|
56
|
+
for (let i = 0; i < own.length; i++) {
|
|
57
|
+
const c = own[i];
|
|
58
|
+
if (depth === 0 && c === ";") {
|
|
59
|
+
seg = i + 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (c === "{") {
|
|
63
|
+
if (depth === 0) for (let k = seg; k < i; k++) own[k] = " ";
|
|
64
|
+
depth++;
|
|
65
|
+
}
|
|
66
|
+
if (depth) own[i] = " ";
|
|
67
|
+
if (c === "}") {
|
|
68
|
+
depth--;
|
|
69
|
+
if (depth === 0) seg = i + 1;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const list = own.join("");
|
|
73
|
+
const decls = [];
|
|
74
|
+
let paren = 0, from = 0;
|
|
75
|
+
for (let i = 0; i <= list.length; i++) {
|
|
76
|
+
const c = list[i];
|
|
77
|
+
if (c === "(" || c === "[") paren++;
|
|
78
|
+
else if (c === ")" || c === "]") paren = Math.max(0, paren - 1);
|
|
79
|
+
if (i === list.length || c === ";" && paren === 0) {
|
|
80
|
+
const text = list.slice(from, i), colon = text.indexOf(":");
|
|
81
|
+
if (colon > 0) decls.push({
|
|
82
|
+
prop: text.slice(0, colon).trim().toLowerCase(),
|
|
83
|
+
valueAt: from + colon + 1,
|
|
84
|
+
end: i
|
|
85
|
+
});
|
|
86
|
+
from = i + 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (decls.some((x) => x.prop === "backdrop-filter")) continue;
|
|
90
|
+
for (const x of decls) {
|
|
91
|
+
if (x.prop !== "-webkit-backdrop-filter") continue;
|
|
92
|
+
const value = css.slice(open + 1 + x.valueAt, open + 1 + x.end).trim();
|
|
93
|
+
if (value) edits.push({
|
|
94
|
+
at: open + 1 + x.end,
|
|
95
|
+
text: `;backdrop-filter:${value}`
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
let out = css;
|
|
100
|
+
for (const e of edits.sort((a, b) => b.at - a.at)) out = out.slice(0, e.at) + e.text + out.slice(e.at);
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** What sits inside parentheses is a value - `var(--f,{})`, `url(#a{b)` - never a rule: blanked,
|
|
104
|
+
* same length (values are copied from the original text). */
|
|
105
|
+
function maskParens(masked) {
|
|
106
|
+
const out = masked.split("");
|
|
107
|
+
let depth = 0;
|
|
108
|
+
for (let i = 0; i < out.length; i++) {
|
|
109
|
+
const c = out[i];
|
|
110
|
+
if (c === ")" && depth) {
|
|
111
|
+
depth--;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (depth) out[i] = " ";
|
|
115
|
+
if (c === "(") depth++;
|
|
116
|
+
}
|
|
117
|
+
return out.join("");
|
|
118
|
+
}
|
|
119
|
+
/** A custom property's value may hold anything, braces, brackets and semicolons included (CSS
|
|
120
|
+
* Variables 1): blanked, same length, so no brace or property name inside one reads as syntax. */
|
|
121
|
+
function maskCustomProperties(masked) {
|
|
122
|
+
const out = masked.split("");
|
|
123
|
+
const re = /(^|[;{\s])--[^\s:;{}]+\s*:/g;
|
|
124
|
+
for (const m of masked.matchAll(re)) {
|
|
125
|
+
let depth = 0, i = m.index + m[0].length;
|
|
126
|
+
for (; i < masked.length; i++) {
|
|
127
|
+
const c = masked[i];
|
|
128
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
129
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
130
|
+
if (depth === 0) break;
|
|
131
|
+
depth--;
|
|
132
|
+
} else if (c === ";" && depth === 0) break;
|
|
133
|
+
out[i] = " ";
|
|
134
|
+
}
|
|
135
|
+
re.lastIndex = i;
|
|
136
|
+
}
|
|
137
|
+
return out.join("");
|
|
138
|
+
}
|
|
139
|
+
function cssFixPlugin() {
|
|
140
|
+
return {
|
|
141
|
+
name: "marver:css-fix",
|
|
142
|
+
transform(code, id) {
|
|
143
|
+
if (!/\.css$/.test(id.split("?")[0])) return;
|
|
144
|
+
const fixed = keepBackdropFilter(code);
|
|
145
|
+
return fixed === code ? void 0 : {
|
|
146
|
+
code: fixed,
|
|
147
|
+
map: null
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
11
153
|
//#region src/server/build.ts
|
|
12
154
|
/**
|
|
13
155
|
* `marver build` - the static adapter.
|
|
@@ -306,7 +448,7 @@ export function layoutChain(fileKey) {
|
|
|
306
448
|
}
|
|
307
449
|
`;
|
|
308
450
|
}
|
|
309
|
-
async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
451
|
+
async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds, textures = true) {
|
|
310
452
|
const config = await loadConfig(root);
|
|
311
453
|
const host = detectHost(root);
|
|
312
454
|
const pkgDir = packageDir();
|
|
@@ -332,10 +474,11 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
332
474
|
for (const b of Object.values(boards)) for (const node of Array.isArray(b?.nodes) ? b.nodes : []) if (typeof node?.frame === "string") wanted.add(node.frame);
|
|
333
475
|
frames = manifest.frames.filter((f) => wanted.has(f.id));
|
|
334
476
|
}
|
|
335
|
-
const
|
|
477
|
+
const pubFrames = strip ? frames.map((f) => ({
|
|
336
478
|
...f,
|
|
337
479
|
file: opaquePath(f.id, f.kind === "html" ? ".html" : "")
|
|
338
|
-
})) : frames
|
|
480
|
+
})) : frames;
|
|
481
|
+
const pubManifest = publishedManifest(manifest, pubFrames, publishedNames, strip);
|
|
339
482
|
for (const n of publishedNames) {
|
|
340
483
|
const pb = policy.boards[n];
|
|
341
484
|
if (pb?.type !== "slides" && pb?.open !== "slides") continue;
|
|
@@ -367,7 +510,9 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
367
510
|
const t = boardFields(allBoards[n], isBoardName).title;
|
|
368
511
|
return t ? [[n, t]] : [];
|
|
369
512
|
}));
|
|
513
|
+
const bakeGen = textures ? Date.now() : void 0;
|
|
370
514
|
const data = {
|
|
515
|
+
bakes: bakeGen,
|
|
371
516
|
manifest: pubManifest,
|
|
372
517
|
boards,
|
|
373
518
|
names: publishedNames,
|
|
@@ -413,7 +558,7 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
413
558
|
clientDir,
|
|
414
559
|
config,
|
|
415
560
|
detectedThemeCss: host.themeCss
|
|
416
|
-
}));
|
|
561
|
+
}), cssFixPlugin());
|
|
417
562
|
process.env.NODE_ENV = "production";
|
|
418
563
|
const result = await build({
|
|
419
564
|
configFile: false,
|
|
@@ -462,7 +607,7 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
462
607
|
const page = (srcDir, entryName, outPath) => {
|
|
463
608
|
const entry = chunks.find((c) => c.isEntry && c.name === entryName);
|
|
464
609
|
const links = cssFor(entryName).map((f) => `<link rel="stylesheet" href="/${f}" />`).join("\n ");
|
|
465
|
-
const html = readFileSync(join(clientDir, srcDir, "index.html"), "utf8").replaceAll("{{ROUTE}}", ROUTE).replace("<script type=\"module\" src=\"{{ENTRY}}\"><\/script>", `${links}\n <script type="module" src="/${entry.fileName}"><\/script>`);
|
|
610
|
+
const html = readFileSync(join(clientDir, srcDir, "index.html"), "utf8").replaceAll("{{ROUTE}}", ROUTE).replace("<script type=\"module\" src=\"{{ENTRY}}\"><\/script>", `${links}\n <script type="module" src="/${entry.fileName}"><\/script>`).replace(/<head([^>]*)>/, (m) => entryName === "frame" && bakeGen ? `${m}\n <meta name="mv-bakes" content="${bakeGen}">` : m);
|
|
466
611
|
mkdirSync(dirname(join(outDir, outPath)), { recursive: true });
|
|
467
612
|
writeFileSync(join(outDir, outPath), html);
|
|
468
613
|
};
|
|
@@ -470,7 +615,7 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
470
615
|
page("frame-host", "frame", `${ROUTE.slice(1)}/frame/index.html`);
|
|
471
616
|
page("stage", "stage", `${ROUTE.slice(1)}/stage/index.html`);
|
|
472
617
|
cpSync(join(clientDir, "shell", "favicon"), join(outDir, ROUTE.slice(1), "favicon"), { recursive: true });
|
|
473
|
-
cpSync(join(clientDir, "frame-host",
|
|
618
|
+
for (const f of ["bridge.js", "inspect.js"]) cpSync(join(clientDir, "frame-host", f), join(outDir, "assets", f));
|
|
474
619
|
const frameCss = cssFor("frame").map((f) => `<link rel="stylesheet" href="/${f}" />`).join("\n");
|
|
475
620
|
for (const f of frames.filter((x) => x.kind === "html")) {
|
|
476
621
|
const src = readFileSync(join(root, f.file), "utf8");
|
|
@@ -478,6 +623,7 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
478
623
|
let html = src.includes("</head>") ? src.replace("</head>", `${inject}</head>`) : inject + src;
|
|
479
624
|
const shim = `<script>(function(){var a=Element.prototype.attachShadow;if(a)Element.prototype.attachShadow=function(i){if(i&&i.mode==='closed')window.__mvClosedShadow=1;return a.call(this,i)};})();<\/script>`;
|
|
480
625
|
html = /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (m) => m + shim) : shim + html;
|
|
626
|
+
if (bakeGen) html = /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (m) => `${m}<meta name="mv-bakes" content="${bakeGen}">`) : `<meta name="mv-bakes" content="${bakeGen}">` + html;
|
|
481
627
|
const dest = strip ? opaquePath(f.id, ".html") : f.file;
|
|
482
628
|
mkdirSync(dirname(join(outDir, dest)), { recursive: true });
|
|
483
629
|
writeFileSync(join(outDir, dest), html);
|
|
@@ -504,7 +650,7 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
504
650
|
const realAssets = existsSync(assetsDir) ? realpathSync(assetsDir) : null;
|
|
505
651
|
for (const r of refs) {
|
|
506
652
|
if (!isLocalAssetRef(r) || !r.endsWith(".poster.png") || existsSync(join(assetsDir, r))) continue;
|
|
507
|
-
const { ensurePoster } = await import("./poster-
|
|
653
|
+
const { ensurePoster } = await import("./poster-CIuz_PwH.mjs");
|
|
508
654
|
const g = await ensurePoster(assetsDir, r.slice(0, -11));
|
|
509
655
|
if (!g.ok) throw new Error(`design/assets/${r}: ${g.error}`);
|
|
510
656
|
console.log(` poster: rendered design/assets/${r} (${g.width}×${g.height})`);
|
|
@@ -569,8 +715,31 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds) {
|
|
|
569
715
|
...config.share.frontDoor === false ? { frontDoor: false } : {},
|
|
570
716
|
...config.share.notify === false ? { notify: false } : {}
|
|
571
717
|
}));
|
|
718
|
+
let textureLine = " textures: skipped (--no-textures)";
|
|
719
|
+
if (textures && bakeGen) {
|
|
720
|
+
const { bakePublished } = await import("./publish-bakes-D0LhbQQ3.mjs");
|
|
721
|
+
const pubFrameFile = new Map(pubFrames.map((f) => [f.id, f]));
|
|
722
|
+
const r = await bakePublished({
|
|
723
|
+
root,
|
|
724
|
+
outDir,
|
|
725
|
+
gen: bakeGen,
|
|
726
|
+
boards,
|
|
727
|
+
themes: config.themes,
|
|
728
|
+
log: (l) => console.log(l),
|
|
729
|
+
frames: pubFrames,
|
|
730
|
+
viewports: config.viewports,
|
|
731
|
+
allScenes: includeAll,
|
|
732
|
+
urlFor: (id, theme) => {
|
|
733
|
+
const f = pubFrameFile.get(id);
|
|
734
|
+
if (!f) return null;
|
|
735
|
+
return f.kind === "html" ? `/${f.file}?theme=${encodeURIComponent(theme)}&r=${bakeGen}` : `/__mv/frame/?id=${encodeURIComponent(id)}&theme=${encodeURIComponent(theme)}&r=${bakeGen}`;
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
textureLine = r === null ? ` textures: none - no Chrome on this machine; frames with glass will rest live (install Chrome, or ship as is)` : r.asked === 0 ? " textures: nothing to compile" : ` textures: ${r.asleep} frame view${r.asleep === 1 ? "" : "s"} asleep under certified glass, ${r.live} with live glass, ${r.plain} without effects (${r.asked} asked: every published node x ${config.themes.length || 1} theme${config.themes.length === 1 ? "" : "s"}; ${(r.bytes / 1024).toFixed(0)} KB, ${(r.ms / 1e3).toFixed(1)} s)`;
|
|
739
|
+
}
|
|
572
740
|
console.log(`\n ${NAME} build → design/.dist`);
|
|
573
741
|
console.log(` boards: ${publishedNames.map((n) => `${n} (${rights[n]})`).join(", ")}`);
|
|
742
|
+
console.log(textureLine);
|
|
574
743
|
console.log(` frames: ${frames.length}${includeAll ? "" : ` of ${manifest.frames.length} (build-time filter)`}`);
|
|
575
744
|
if (copiedAssets) console.log(` assets: ${copiedAssets} referenced file${copiedAssets === 1 ? "" : "s"} from design/assets/ (unreferenced assets never ship)`);
|
|
576
745
|
if (!includeAll && existsSync(join(root, "public"))) console.log(` note: the host public/ directory ships in full - the --boards filter covers frames, not public assets`);
|
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
3
|
import { cac } from "cac";
|
|
3
4
|
import { readFileSync, realpathSync } from "node:fs";
|
|
4
5
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -31,6 +32,13 @@ function slideSize(frame) {
|
|
|
31
32
|
return frame.slide ? SLIDE_INTRINSIC : null;
|
|
32
33
|
}
|
|
33
34
|
//#endregion
|
|
35
|
+
//#region src/cli/name.ts
|
|
36
|
+
var name_exports = /* @__PURE__ */ __exportAll({
|
|
37
|
+
NAME: () => NAME,
|
|
38
|
+
PKG: () => PKG,
|
|
39
|
+
ROUTE: () => ROUTE
|
|
40
|
+
});
|
|
41
|
+
//#endregion
|
|
34
42
|
//#region src/cli/index.ts
|
|
35
43
|
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
36
44
|
if (major < 22 || major === 22 && minor < 18) {
|
|
@@ -64,14 +72,14 @@ const resolve$1 = (dir) => {
|
|
|
64
72
|
};
|
|
65
73
|
const cli = cac(NAME);
|
|
66
74
|
cli.command("init", "Scaffold design/ in this repo").option("--mode <mode>", "studio | embedded", { default: "studio" }).option("--no-demo", "Skip the demo scene (the demo ships unless this flag is passed)").option("--root <dir>", "Host repo root", { default: "." }).action(async (opts) => {
|
|
67
|
-
const { init } = await import("./init-
|
|
75
|
+
const { init } = await import("./init-BWbHqVng.mjs");
|
|
68
76
|
init(resolve$1(opts.root), {
|
|
69
77
|
mode: opts.mode === "embedded" ? "embedded" : "studio",
|
|
70
78
|
demo: opts.demo !== false
|
|
71
79
|
});
|
|
72
80
|
});
|
|
73
81
|
for (const [name, desc] of [["dev", "Start the local canvas (everything on: hot reload, comments, Live Jam)"], ["canvas", "Start the local canvas - same as dev"]]) cli.command(name, desc).option("--root <dir>", "Host repo root", { default: "." }).option("--port <port>", "Port (default 5199)").action(async (opts) => {
|
|
74
|
-
const { dev } = await import("./dev-
|
|
82
|
+
const { dev } = await import("./dev-BvLbY98O.mjs");
|
|
75
83
|
let port;
|
|
76
84
|
if (opts.port !== void 0) {
|
|
77
85
|
const n = Number(opts.port);
|
|
@@ -80,18 +88,18 @@ for (const [name, desc] of [["dev", "Start the local canvas (everything on: hot
|
|
|
80
88
|
}
|
|
81
89
|
await dev(resolve$1(opts.root), port);
|
|
82
90
|
});
|
|
83
|
-
cli.command("build", "Static export → design/.dist (what ships comes from design/publish.json - publishing is default-closed)").option("--boards <names>", "Publish only these boards (comma-separated); overrides the publish policy").option("--all-boards", "Publish every board - the loud override for the default-closed policy").option("--embed-seeds", "Copy comment history INTO the web root (identifying - every event carries its author's email)").option("--root <dir>", "Host repo root", { default: "." }).action(async (opts) => {
|
|
84
|
-
const { buildSite } = await import("./build-
|
|
91
|
+
cli.command("build", "Static export → design/.dist (what ships comes from design/publish.json - publishing is default-closed)").option("--boards <names>", "Publish only these boards (comma-separated); overrides the publish policy").option("--all-boards", "Publish every board - the loud override for the default-closed policy").option("--embed-seeds", "Copy comment history INTO the web root (identifying - every event carries its author's email)").option("--no-textures", "Skip compiling the glass textures the published frames rest under (needs Chrome; a CI without one skips on its own)").option("--root <dir>", "Host repo root", { default: "." }).action(async (opts) => {
|
|
92
|
+
const { buildSite } = await import("./build-ER_7T6Cw.mjs");
|
|
85
93
|
try {
|
|
86
94
|
const boards = opts.boards === void 0 ? void 0 : typeof opts.boards === "string" ? opts.boards : "";
|
|
87
|
-
await buildSite(resolve$1(opts.root), boards, opts.allBoards === true, opts.embedSeeds === true);
|
|
95
|
+
await buildSite(resolve$1(opts.root), boards, opts.allBoards === true, opts.embedSeeds === true, opts.textures !== false && !process.env.MARVER_NO_TEXTURES);
|
|
88
96
|
} catch (err) {
|
|
89
97
|
console.error(`[${NAME}] build failed: ${err.message}`);
|
|
90
98
|
process.exit(1);
|
|
91
99
|
}
|
|
92
100
|
});
|
|
93
101
|
cli.command("serve", "Serve design/.dist (set MARVER_PASSWORD to gate it)").option("--root <dir>", "Host repo root", { default: "." }).option("--port <port>", "Port (default $PORT or 4199)").action(async (opts) => {
|
|
94
|
-
const { serve } = await import("./serve-
|
|
102
|
+
const { serve } = await import("./serve-z5qtj_wJ.mjs");
|
|
95
103
|
let port;
|
|
96
104
|
if (opts.port !== void 0) {
|
|
97
105
|
const n = Number(opts.port);
|
|
@@ -100,7 +108,7 @@ cli.command("serve", "Serve design/.dist (set MARVER_PASSWORD to gate it)").opti
|
|
|
100
108
|
serve(resolve$1(opts.root), port);
|
|
101
109
|
});
|
|
102
110
|
cli.command("comments <action> [value]", "Comment collaboration: connect <url> · sync · list · reply <thread> · resolve <thread> · invite <email> · revoke <email>").option("--root <dir>", "Host repo root", { default: "." }).option("--token <token>", "connect: the canvas's MARVER_CLI_TOKEN (default $MARVER_CLI_TOKEN) - the identity-mode path").option("--invite <token>", "connect: claim this invite instead of signing in").option("--canvas-password <password>", "connect: the canvas gate password (default $MARVER_PASSWORD or prompt)").option("--email <email>", "connect: account email (skips the prompt)").option("--password <password>", "connect: account password (skips the prompt - mind your shell history)").option("--name <name>", "connect --invite: display name for the new account").option("--open", "list: only unresolved threads").option("--json", "list: machine-readable output").option("--board <board>", "scope to one board").option("--body <text>", "reply: the reply text").option("--addressed-in <frame>", "resolve: the variant frame that answered the feedback").action(async (action, value, opts) => {
|
|
103
|
-
const { commentsCommand } = await import("./comments-
|
|
111
|
+
const { commentsCommand } = await import("./comments-ClVgfQib.mjs");
|
|
104
112
|
try {
|
|
105
113
|
await commentsCommand(resolve$1(opts.root), action, value, opts);
|
|
106
114
|
} catch (err) {
|
|
@@ -109,7 +117,7 @@ cli.command("comments <action> [value]", "Comment collaboration: connect <url>
|
|
|
109
117
|
}
|
|
110
118
|
});
|
|
111
119
|
cli.command("share <action> [value]", "Sharing roster (owner): add <who> · remove <who> · block/unblock <email> · general <mode> · list · requests · explain <who> · who").option("--root <dir>", "Host repo root", { default: "." }).option("--role <role>", "add / requests --approve: view (default) or comment").option("--expires <iso>", "add: expiry timestamp, e.g. 2026-12-31T00:00:00Z").option("--approve <email>", "requests: approve this pending request (canvas-wide in v1)").option("--decline <email>", "requests: decline this pending request (silent to the asker)").option("--json", "list: machine-readable output").action(async (action, value, opts) => {
|
|
112
|
-
const { shareCommand } = await import("./share
|
|
120
|
+
const { shareCommand } = await import("./share--bdSc4G5.mjs");
|
|
113
121
|
try {
|
|
114
122
|
await shareCommand(resolve$1(opts.root), action, value, opts);
|
|
115
123
|
} catch (err) {
|
|
@@ -118,7 +126,7 @@ cli.command("share <action> [value]", "Sharing roster (owner): add <who> · remo
|
|
|
118
126
|
}
|
|
119
127
|
});
|
|
120
128
|
cli.command("work <action> [...frames]", "Working state on the canvas: start <scene/frame ...> · done <scene/frame ...> | --all · list").option("--root <dir>", "Host repo root", { default: "." }).option("--ttl <minutes>", "start: minutes before the glow self-expires (default 10, max 30)").option("--all", "done: clear every working frame").action(async (action, frames, opts) => {
|
|
121
|
-
const { workCommand } = await import("./work-
|
|
129
|
+
const { workCommand } = await import("./work-0YopuMt9.mjs");
|
|
122
130
|
try {
|
|
123
131
|
await workCommand(resolve$1(opts.root), action, frames ?? [], opts);
|
|
124
132
|
} catch (err) {
|
|
@@ -135,10 +143,10 @@ cli.command("boards", "The sidebar as files: every folder and board in reading o
|
|
|
135
143
|
process.exit(1);
|
|
136
144
|
}
|
|
137
145
|
});
|
|
138
|
-
cli.command("shot
|
|
139
|
-
const { shotCommand } = await import("./shot-
|
|
146
|
+
cli.command("shot [...frames]", "Render frames headless and print the PNG paths (needs `dev` running): ids, --scene <name> or --all").option("--root <dir>", "Host repo root", { default: "." }).option("--scene <name>", "Every frame of one scene").option("--all", "Every frame of the canvas").option("--theme <name>", "Theme to render (default: light)").option("--scale <n>", "Device pixels per CSS px, 1-4 (default: 2; 4 for print-quality stills)").option("--json", "Print the results as JSON ({ results: [...] }) instead of paths").action(async (frames, opts) => {
|
|
147
|
+
const { shotCommand } = await import("./shot-BFEuYbaz.mjs");
|
|
140
148
|
try {
|
|
141
|
-
await shotCommand(resolve$1(opts.root),
|
|
149
|
+
await shotCommand(resolve$1(opts.root), frames, opts);
|
|
142
150
|
} catch (err) {
|
|
143
151
|
console.error(`[${NAME}] ${err.message}`);
|
|
144
152
|
process.exit(1);
|
|
@@ -148,4 +156,4 @@ cli.help();
|
|
|
148
156
|
cli.version(version());
|
|
149
157
|
cli.parse();
|
|
150
158
|
//#endregion
|
|
151
|
-
export {
|
|
159
|
+
export { ROUTE as a, PKG as i, CONTENT_WIDTH as n, slideSize as o, NAME as r, name_exports as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as NAME } from "./cli.mjs";
|
|
2
2
|
import { n as replay } from "./events-B3LBn74P.mjs";
|
|
3
3
|
import { i as readLog, r as listBoards, t as appendEvents } from "./comments-DZyobpxG.mjs";
|
|
4
4
|
import { a as syncOnce, i as loadCollab, n as connectClaim, r as connectToken, t as connect } from "./sync-BZaCWqK-.mjs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as replay } from "./events-B3LBn74P.mjs";
|
|
2
2
|
import { i as readLog, r as listBoards, t as appendEvents } from "./comments-DZyobpxG.mjs";
|
|
3
3
|
import { n as localProfile } from "./profile-BjAPAJSb.mjs";
|
|
4
|
-
import { i as toFrameId } from "./manifest-
|
|
4
|
+
import { i as toFrameId } from "./manifest-DAnEL8_a.mjs";
|
|
5
5
|
import { workActivity } from "./work-CLrmY-vQ.mjs";
|
|
6
6
|
import { r as deviceId, t as has } from "./ledger-Bu0BjqIe.mjs";
|
|
7
7
|
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, watch, writeFileSync, writeSync } from "node:fs";
|
|
@@ -1,12 +1,205 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { l as detectHost, s as loadConfig } from "./manifest-
|
|
3
|
-
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-
|
|
4
|
-
import { realpathSync } from "node:fs";
|
|
1
|
+
import { i as PKG, r as NAME } from "./cli.mjs";
|
|
2
|
+
import { l as detectHost, s as loadConfig } from "./manifest-DAnEL8_a.mjs";
|
|
3
|
+
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-Cai5C1WV.mjs";
|
|
4
|
+
import { readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { createLogger, createServer, searchForWorkspaceRoot } from "vite";
|
|
7
|
+
import { createLogger, createServer, parseAst, searchForWorkspaceRoot } from "vite";
|
|
8
8
|
import react from "@vitejs/plugin-react";
|
|
9
9
|
import { createServer as createServer$1 } from "node:net";
|
|
10
|
+
//#region src/server/icons.ts
|
|
11
|
+
/**
|
|
12
|
+
* Icon barrels, unrolled.
|
|
13
|
+
*
|
|
14
|
+
* `import { Truck } from '@phosphor-icons/react'` makes Vite hand the frame the WHOLE prebundled
|
|
15
|
+
* package - 3000 icons, 6.5 MB of JavaScript - and every frame on a board is its own realm, so every
|
|
16
|
+
* frame parses and evaluates all of it: ~400 ms, the whole boot of a lo-fi frame (measured,
|
|
17
|
+
* research/hifi/frameres.ts: the scene import is 530 of a 550 ms boot; a board of 128 frames spends
|
|
18
|
+
* 50 s on it). The packages ship one module per icon and their barrel says which: this reads the
|
|
19
|
+
* INSTALLED barrel once (every alias, whatever the version), rewrites the import declarations of
|
|
20
|
+
* design sources to the per-icon modules, one line for one line, and names those modules to the
|
|
21
|
+
* dependency optimizer at server start so nothing is discovered - and reloaded for - on first use.
|
|
22
|
+
* A name the barrel does not map, a default or namespace import, a re-export: left as it is.
|
|
23
|
+
*/
|
|
24
|
+
const LIBS = [{
|
|
25
|
+
barrel: "@phosphor-icons/react",
|
|
26
|
+
spec: (rel) => {
|
|
27
|
+
const m = rel.match(/^\.\/csr\/([\w-]+)\.es\.js$/);
|
|
28
|
+
return m ? `@phosphor-icons/react/dist/csr/${m[1]}` : null;
|
|
29
|
+
}
|
|
30
|
+
}, {
|
|
31
|
+
barrel: "lucide-react",
|
|
32
|
+
spec: (rel) => {
|
|
33
|
+
const m = rel.match(/^\.\/icons\/([\w-]+\.m?js)$/);
|
|
34
|
+
return m ? `lucide-react/dist/esm/icons/${m[1]}` : null;
|
|
35
|
+
}
|
|
36
|
+
}];
|
|
37
|
+
/** The map read from a barrel's source: `import { A as x } from './f'` + `export { x as Name }`
|
|
38
|
+
* (phosphor) and `export { default as Name } from './f'` (lucide). */
|
|
39
|
+
function parseBarrel(source, lib) {
|
|
40
|
+
const map = /* @__PURE__ */ new Map();
|
|
41
|
+
const locals = /* @__PURE__ */ new Map();
|
|
42
|
+
for (const m of source.matchAll(/import\s*\{([^}]*)\}\s*from\s*["']([^"']+)["']/g)) {
|
|
43
|
+
const spec = lib.spec(m[2]);
|
|
44
|
+
if (!spec) continue;
|
|
45
|
+
for (const s of m[1].split(",")) {
|
|
46
|
+
const [name, local = name] = s.trim().split(/\s+as\s+/);
|
|
47
|
+
if (name) locals.set(local, {
|
|
48
|
+
spec,
|
|
49
|
+
name
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const m of source.matchAll(/export\s*\{([^}]*)\}(?:\s*from\s*["']([^"']+)["'])?/g)) {
|
|
54
|
+
const spec = m[2] ? lib.spec(m[2]) : null;
|
|
55
|
+
if (m[2] && !spec) continue;
|
|
56
|
+
for (const s of m[1].split(",")) {
|
|
57
|
+
const [name, exported = name] = s.trim().split(/\s+as\s+/);
|
|
58
|
+
if (!name) continue;
|
|
59
|
+
if (spec) map.set(exported, {
|
|
60
|
+
spec,
|
|
61
|
+
name
|
|
62
|
+
});
|
|
63
|
+
else {
|
|
64
|
+
const l = locals.get(name);
|
|
65
|
+
if (l) map.set(exported, l);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return map;
|
|
70
|
+
}
|
|
71
|
+
const maps = /* @__PURE__ */ new Map();
|
|
72
|
+
/** The maps for every icon package installed under `root` (read once per server). */
|
|
73
|
+
function iconMaps(root) {
|
|
74
|
+
let m = maps.get(root);
|
|
75
|
+
if (m) return m;
|
|
76
|
+
m = /* @__PURE__ */ new Map();
|
|
77
|
+
for (const lib of LIBS) {
|
|
78
|
+
const dir = join(root, "node_modules", lib.barrel);
|
|
79
|
+
try {
|
|
80
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
81
|
+
const dot = pkg.exports?.["."];
|
|
82
|
+
const entry = (typeof dot === "object" ? dot.import : typeof dot === "string" ? dot : void 0) ?? pkg.module;
|
|
83
|
+
if (!entry) continue;
|
|
84
|
+
const map = parseBarrel(readFileSync(join(dir, entry), "utf8"), lib);
|
|
85
|
+
if (map.size) m.set(lib.barrel, map);
|
|
86
|
+
} catch {}
|
|
87
|
+
}
|
|
88
|
+
maps.set(root, m);
|
|
89
|
+
return m;
|
|
90
|
+
}
|
|
91
|
+
/** The code with every mapped icon import unrolled and the per-icon specifiers it now imports;
|
|
92
|
+
* null when nothing changed. Real import declarations only (a template literal is content). */
|
|
93
|
+
function unrollIcons(code, maps) {
|
|
94
|
+
if (![...maps.keys()].some((b) => code.includes(b))) return null;
|
|
95
|
+
let ast;
|
|
96
|
+
try {
|
|
97
|
+
ast = parseAst(code);
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const edits = [];
|
|
102
|
+
const modules = [];
|
|
103
|
+
for (const node of ast.body) {
|
|
104
|
+
if (node.type !== "ImportDeclaration" || !node.source) continue;
|
|
105
|
+
const map = maps.get(node.source.value);
|
|
106
|
+
if (!map || !node.specifiers?.length) continue;
|
|
107
|
+
const lines = [], keep = [];
|
|
108
|
+
let icons = 0;
|
|
109
|
+
for (const s of node.specifiers) {
|
|
110
|
+
const imported = s.type === "ImportSpecifier" ? s.imported?.name ?? s.imported?.value : void 0;
|
|
111
|
+
const hit = imported ? map.get(imported) : void 0;
|
|
112
|
+
if (!hit) {
|
|
113
|
+
if (s.type !== "ImportSpecifier") {
|
|
114
|
+
lines.length = 0;
|
|
115
|
+
icons = 0;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
keep.push(imported === s.local.name ? imported : `${imported} as ${s.local.name}`);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
icons++;
|
|
122
|
+
modules.push(hit.spec);
|
|
123
|
+
lines.push(hit.name === "default" ? `import ${s.local.name} from '${hit.spec}';` : `import { ${hit.name === s.local.name ? hit.name : `${hit.name} as ${s.local.name}`} } from '${hit.spec}';`);
|
|
124
|
+
}
|
|
125
|
+
if (!icons) continue;
|
|
126
|
+
if (keep.length) lines.push(`import { ${keep.join(", ")} } from '${node.source.value}';`);
|
|
127
|
+
const original = code.slice(node.start, node.end);
|
|
128
|
+
edits.push({
|
|
129
|
+
start: node.start,
|
|
130
|
+
end: node.end,
|
|
131
|
+
text: lines.join(" ") + "\n".repeat((original.match(/\n/g) ?? []).length)
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (!edits.length) return null;
|
|
135
|
+
let out = "", at = 0;
|
|
136
|
+
for (const e of edits) {
|
|
137
|
+
out += code.slice(at, e.start) + e.text;
|
|
138
|
+
at = e.end;
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
code: out + code.slice(at),
|
|
142
|
+
modules
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Every per-icon module the design sources import (for the optimizer, at server start). Raw
|
|
146
|
+
* TypeScript is scanned by a plain pattern; only names the barrel maps count. */
|
|
147
|
+
function iconModules(root) {
|
|
148
|
+
const m = iconMaps(root);
|
|
149
|
+
if (!m.size) return [];
|
|
150
|
+
const found = /* @__PURE__ */ new Set();
|
|
151
|
+
const walk = (dir) => {
|
|
152
|
+
let names;
|
|
153
|
+
try {
|
|
154
|
+
names = readdirSync(dir);
|
|
155
|
+
} catch {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
for (const n of names) {
|
|
159
|
+
if (n === "node_modules" || n.startsWith(".")) continue;
|
|
160
|
+
const p = join(dir, n);
|
|
161
|
+
let st;
|
|
162
|
+
try {
|
|
163
|
+
st = statSync(p);
|
|
164
|
+
} catch {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (st.isDirectory()) walk(p);
|
|
168
|
+
else if (/\.[jt]sx?$/.test(n)) {
|
|
169
|
+
const src = readFileSync(p, "utf8").replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, (c) => " ".repeat(c.length));
|
|
170
|
+
for (const im of src.matchAll(/import\s*\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g)) {
|
|
171
|
+
const map = m.get(im[2]);
|
|
172
|
+
if (!map) continue;
|
|
173
|
+
for (const s of im[1].split(",")) {
|
|
174
|
+
const name = s.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0];
|
|
175
|
+
const hit = map.get(name);
|
|
176
|
+
if (hit) found.add(hit.spec);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
walk(join(root, "design"));
|
|
183
|
+
return [...found].sort();
|
|
184
|
+
}
|
|
185
|
+
/** The Vite plugin: design sources only, after the TS/JSX transform (a normal plugin runs after
|
|
186
|
+
* the core ones), before import analysis resolves the specifiers. The rewrite keeps every line
|
|
187
|
+
* where it was, so the file's map still lands (no map of its own). */
|
|
188
|
+
function iconsPlugin(root) {
|
|
189
|
+
const design = join(root, "design") + "/";
|
|
190
|
+
return {
|
|
191
|
+
name: "marver:icons",
|
|
192
|
+
transform(code, id) {
|
|
193
|
+
if (!id.startsWith(design) || !/\.[jt]sx?(\?|$)/.test(id)) return;
|
|
194
|
+
const r = unrollIcons(code, iconMaps(root));
|
|
195
|
+
return r ? {
|
|
196
|
+
code: r.code,
|
|
197
|
+
map: null
|
|
198
|
+
} : void 0;
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
//#endregion
|
|
10
203
|
//#region src/server/dev.ts
|
|
11
204
|
/** packageDir = the installed marver package root (dist/cli.js lives one level down). */
|
|
12
205
|
function packageDir() {
|
|
@@ -174,7 +367,7 @@ async function dev(root, portFlag) {
|
|
|
174
367
|
clientDir,
|
|
175
368
|
config,
|
|
176
369
|
detectedThemeCss: host.themeCss
|
|
177
|
-
}));
|
|
370
|
+
}), iconsPlugin(root));
|
|
178
371
|
const logger = createLogger("info");
|
|
179
372
|
const noise = (msg) => /Sourcemap for .*node_modules.*points to/.test(msg);
|
|
180
373
|
const warnBase = logger.warn.bind(logger);
|
|
@@ -244,7 +437,8 @@ async function dev(root, portFlag) {
|
|
|
244
437
|
"react/jsx-dev-runtime",
|
|
245
438
|
`${PKG} > marked`,
|
|
246
439
|
`${PKG} > mermaid`,
|
|
247
|
-
`${PKG} > html-to-image
|
|
440
|
+
`${PKG} > html-to-image`,
|
|
441
|
+
...iconModules(root)
|
|
248
442
|
],
|
|
249
443
|
entries: [join(clientDir, "frame-host", "index.html"), "design/**/*.{tsx,jsx}"]
|
|
250
444
|
},
|
|
@@ -255,9 +449,14 @@ async function dev(root, portFlag) {
|
|
|
255
449
|
const port = typeof addr === "object" && addr ? addr.port : picked.port;
|
|
256
450
|
if (picked.fellBack) console.log(`\n port ${desiredPort} is in use - serving "${projectName}" on ${port} instead`);
|
|
257
451
|
console.log(`\n ${NAME} · ${projectName} → http://localhost:${port}/\n`);
|
|
452
|
+
setTimeout(async () => {
|
|
453
|
+
try {
|
|
454
|
+
await (await import("./shot-iicees2e.mjs")).sweepGhosts((m) => console.log(` ${m}`));
|
|
455
|
+
} catch {}
|
|
456
|
+
}, 0);
|
|
258
457
|
try {
|
|
259
458
|
const { staleManagedInstructions } = await import("./managed-HwHVNI3h.mjs");
|
|
260
|
-
const { installedVersion } = await import("./plugin-
|
|
459
|
+
const { installedVersion } = await import("./plugin-Cai5C1WV.mjs").then((n) => n.i);
|
|
261
460
|
const stale = staleManagedInstructions(root);
|
|
262
461
|
if (stale.length) {
|
|
263
462
|
const shown = stale.slice(0, 4).join(", ") + (stale.length > 4 ? `, +${stale.length - 4} more` : "");
|
|
@@ -295,7 +494,7 @@ async function dev(root, portFlag) {
|
|
|
295
494
|
});
|
|
296
495
|
}
|
|
297
496
|
if (config.jam) {
|
|
298
|
-
const { startJam } = await import("./daemon-
|
|
497
|
+
const { startJam } = await import("./daemon-CKhg0zuT.mjs");
|
|
299
498
|
const jam = startJam(root, config.jam, (m) => console.log(m), (board) => server.ws.send("sh:jam-comment", { board }));
|
|
300
499
|
if (jam) {
|
|
301
500
|
const close = server.close.bind(server);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as writeManifest, c as detectAgent, l as detectHost, n as scanFrames, o as DEFAULTS, u as readJson } from "./manifest-
|
|
1
|
+
import { r as NAME } from "./cli.mjs";
|
|
2
|
+
import { a as writeManifest, c as detectAgent, l as detectHost, n as scanFrames, o as DEFAULTS, u as readJson } from "./manifest-DAnEL8_a.mjs";
|
|
3
3
|
import { MANAGED_PREFIX, enumerateInstructionTemplates, hashBody, managedFile, pkgDir } from "./managed-HwHVNI3h.mjs";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, join, relative } from "node:path";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as PKG, n as CONTENT_WIDTH } from "./cli.mjs";
|
|
2
2
|
import { a as listBoardFiles, d as flatten, f as isBoardName, g as hash, m as readTitle, n as checkBoardsDir, p as readDescription, r as checkRealDirs, s as readRegistry, t as boardFields, u as buildTree } from "./boards-BmxcT3Lc.mjs";
|
|
3
3
|
import { accessSync, constants, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { delimiter, isAbsolute, join, relative, sep } from "node:path";
|