gutterpress 0.0.0 → 0.9.0-alpha.2
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/README.md +21 -16
- package/dist/api/index.d.ts +6 -2
- package/dist/api/index.js +15 -3
- package/dist/{audit-1jrwwacz.js → audit-nhn2pjz3.js} +5 -5
- package/dist/{build-5s92kgpc.js → build-san7fv2z.js} +5 -5
- package/dist/checks/types.d.ts +6 -0
- package/dist/{cli-hvqjs342.js → cli-e5zhb0xs.js} +2 -2
- package/dist/{cli-7ykx7pp0.js → cli-k4bd06sd.js} +982 -331
- package/dist/{cli-h7phg3ka.js → cli-najycadg.js} +258 -258
- package/dist/{index-1tyj4bk3.js → cli-wchtvxvw.js} +4 -1
- package/dist/{cli-5bxx0c4y.js → cli-yzrh708h.js} +2 -2
- package/dist/cli.js +15 -15
- package/dist/{doctor-25zjt8dz.js → doctor-hrk0kxxz.js} +2 -2
- package/dist/{index-3h3fef7r.js → index-bynn850m.js} +1200 -410
- package/dist/{cli-1tyj4bk3.js → index-wchtvxvw.js} +4 -1
- package/dist/{index-5bxx0c4y.js → index-yzrh708h.js} +2 -2
- package/dist/index.js +15 -3
- package/dist/lib/asset-inline.d.ts +19 -0
- package/dist/lib/build-error.d.ts +0 -1
- package/dist/lib/build-fingerprint.d.ts +14 -0
- package/dist/lib/build-runner.d.ts +21 -1
- package/dist/lib/ghostscript.d.ts +0 -9
- package/dist/lib/manifest-config.d.ts +7 -0
- package/dist/lib/manifest.d.ts +8 -0
- package/dist/lib/markdown/assemble.d.ts +4 -6
- package/dist/lib/markdown/chapter-id.d.ts +1 -1
- package/dist/lib/markdown/index.d.ts +1 -2
- package/dist/lib/npm-plugin-installer.d.ts +1 -1
- package/dist/lib/output-paths.d.ts +0 -1
- package/dist/lib/pagination.d.ts +0 -20
- package/dist/lib/pdf-inspect.d.ts +2 -2
- package/dist/lib/pdf-parse.d.ts +2 -1
- package/dist/lib/plugin-manager.d.ts +0 -2
- package/dist/lib/presets.d.ts +36 -7
- package/dist/lib/project-scaffold.d.ts +39 -2
- package/dist/lib/project-source.d.ts +11 -9
- package/dist/lib/project-templates.d.ts +45 -7
- package/dist/lib/publish/providers/azure-swa.d.ts +0 -1
- package/dist/lib/publish/providers/itch.d.ts +0 -1
- package/dist/lib/publish/providers/shopify.d.ts +0 -1
- package/dist/lib/remote-auth/github-repos.d.ts +0 -2
- package/dist/lib/remote-auth/recovery/dispatch.d.ts +0 -5
- package/dist/lib/remote-auth/recovery/outcome-mapping.d.ts +3 -2
- package/dist/lib/remote-auth/recovery/recover-stale-lock.d.ts +0 -8
- package/dist/lib/remote-auth/sync.d.ts +2 -10
- package/dist/lib/remote-auth/test-access.d.ts +0 -2
- package/dist/lib/remote-auth/test-support/git-http-server.d.ts +0 -37
- package/dist/lib/source-provider.d.ts +0 -14
- package/dist/lib/static-serve.d.ts +39 -0
- package/dist/lib/style-resolver.d.ts +10 -1
- package/dist/lib/targets.d.ts +84 -0
- package/dist/lib/theme-import.d.ts +0 -2
- package/dist/lib/theme-manager.d.ts +1 -1
- package/dist/lib/validation-exec.d.ts +4 -3
- package/dist/{lint-f63nxjfj.js → lint-96j9hrj4.js} +5 -5
- package/dist/{manifest.schema-rn1dpdpn.json → manifest.schema-z61rzw44.json} +12 -6
- package/dist/new-8p38wavc.js +185 -0
- package/dist/{pagedjs-interface-80g3xa8p.js → pagedjs-interface-qxvzgwd7.js} +92 -33
- package/dist/{plugin-wf2cbmwc.js → plugin-ees6nhkc.js} +5 -5
- package/dist/{preflight-tg4mpz1h.js → preflight-1q6c2edh.js} +24 -29
- package/dist/preview/file-watcher.d.ts +48 -39
- package/dist/preview/http-server.d.ts +5 -2
- package/dist/preview/server-context.d.ts +24 -0
- package/dist/preview-shell-6dqexx1m.js +581 -0
- package/dist/{preview-h2bwbb2x.js → preview-y5a2zen1.js} +5 -5
- package/dist/{project-source-0tg0r6vm.js → project-source-p0gn1wd5.js} +3 -3
- package/dist/{publish-ztaet53r.js → publish-rm9yb3wh.js} +5 -5
- package/dist/render.js +10 -19
- package/dist/{repair-jkp4n3j8.js → repair-zgq7q2g6.js} +5 -5
- package/dist/schema/manifest.types.d.ts +14 -3
- package/dist/server.d.ts +2 -0
- package/dist/{source-provider-hp96b5jf.js → source-provider-c1rjm2c0.js} +2 -8
- package/dist/types.d.ts +0 -1
- package/dist/{validate-k2drs19j.js → validate-nr0xa6sa.js} +8 -8
- package/package.json +2 -2
- package/dist/chapter-01-jj8ftn4c.md +0 -29
- package/dist/lib/validation-profile.d.ts +0 -18
- package/dist/manifest-ryyg71nf.yaml +0 -9
- package/dist/new-7b08a42h.js +0 -105
- package/dist/preview-shell-rghtfmc8.js +0 -155
- package/dist/theme-0yzvthe8.css +0 -65
- package/dist/theme-6a2fngc8.json +0 -6
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
var debugMode = false;
|
|
11
11
|
var currentViewMode = 'two-column';
|
|
12
12
|
var ignoreScrollUntil = 0;
|
|
13
|
+
var lastSourceLine = -1;
|
|
14
|
+
var lastSourceChapter = null;
|
|
13
15
|
|
|
14
16
|
function refreshPages() {
|
|
15
17
|
pages = Array.from(document.querySelectorAll('.pagedjs_page'));
|
|
@@ -51,6 +53,7 @@
|
|
|
51
53
|
currentPage = page;
|
|
52
54
|
ignoreScrollUntil = Date.now() + 300;
|
|
53
55
|
pages[page - 1].scrollIntoView({ behavior: 'instant', block: 'start', inline: 'nearest' });
|
|
56
|
+
recordVisibleSource();
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
function pageStep(mode) {
|
|
@@ -129,11 +132,13 @@
|
|
|
129
132
|
var top = el.getBoundingClientRect().top;
|
|
130
133
|
if (top < ref) {
|
|
131
134
|
// Find the next annotated sibling-in-flow (document order, higher line —
|
|
132
|
-
//
|
|
133
|
-
//
|
|
135
|
+
// explicitly constrained to this chapter because source lines restart per
|
|
136
|
+
// file and a following chapter may begin at any line after front matter).
|
|
134
137
|
var blocks = sourcedBlocks();
|
|
135
138
|
var idx = blocks.indexOf(el);
|
|
139
|
+
var chapter = chapterOf(el);
|
|
136
140
|
for (var i = idx + 1; i < blocks.length; i++) {
|
|
141
|
+
if (chapterOf(blocks[i]) !== chapter) break;
|
|
137
142
|
var nl = lineOf(blocks[i]);
|
|
138
143
|
if (nl == null) continue;
|
|
139
144
|
if (nl <= line) break;
|
|
@@ -148,6 +153,34 @@
|
|
|
148
153
|
return { el: el, line: line };
|
|
149
154
|
}
|
|
150
155
|
|
|
156
|
+
function recordVisibleSource() {
|
|
157
|
+
var pos = visibleSourcePosition();
|
|
158
|
+
lastSourceLine = pos && pos.line != null ? pos.line : -1;
|
|
159
|
+
lastSourceChapter = pos ? chapterOf(pos.el) : null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function preserveViewport(change) {
|
|
163
|
+
refreshPages();
|
|
164
|
+
var position = visibleSourcePosition();
|
|
165
|
+
var anchor = position ? {
|
|
166
|
+
el: position.el,
|
|
167
|
+
top: position.el.getBoundingClientRect().top
|
|
168
|
+
} : null;
|
|
169
|
+
change();
|
|
170
|
+
refreshPages();
|
|
171
|
+
if (!anchor) {
|
|
172
|
+
scrollToCurrentPage();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
ignoreScrollUntil = Date.now() + 300;
|
|
176
|
+
var delta = anchor.el.getBoundingClientRect().top - anchor.top;
|
|
177
|
+
if (delta) {
|
|
178
|
+
window.scrollBy({ top: delta, behavior: 'instant' });
|
|
179
|
+
}
|
|
180
|
+
currentPage = detectVisiblePage();
|
|
181
|
+
recordVisibleSource();
|
|
182
|
+
}
|
|
183
|
+
|
|
151
184
|
// Resolve a {line, chapter?} target to its enclosing annotated block PLUS the
|
|
152
185
|
// following annotated block, so callers can interpolate within long blocks
|
|
153
186
|
// (markdown-it-source-map only annotates top-level *_open tokens, so a target
|
|
@@ -205,16 +238,19 @@
|
|
|
205
238
|
prevPage: function (mode) { return api.goToPage(currentPage - pageStep(mode)); },
|
|
206
239
|
nextPage: function (mode) { return api.goToPage(currentPage + pageStep(mode)); },
|
|
207
240
|
lastPage: function () { refreshPages(); return api.goToPage(pages.length); },
|
|
208
|
-
setViewMode: function (mode) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return api.notifyPageChange();
|
|
241
|
+
setViewMode: function (mode, silent) {
|
|
242
|
+
preserveViewport(function () {
|
|
243
|
+
currentViewMode = mode || 'two-column';
|
|
244
|
+
document.body.classList.remove('view-single', 'view-spread', 'view-two-column');
|
|
245
|
+
if (mode) document.body.classList.add('view-' + mode);
|
|
246
|
+
});
|
|
247
|
+
if (!silent) return api.notifyPageChange();
|
|
215
248
|
},
|
|
216
|
-
setZoom: function (z) {
|
|
217
|
-
|
|
249
|
+
setZoom: function (z, silent) {
|
|
250
|
+
preserveViewport(function () {
|
|
251
|
+
document.documentElement.style.setProperty('--gutterpress-zoom', z);
|
|
252
|
+
});
|
|
253
|
+
if (!silent) api.notifyPageChange();
|
|
218
254
|
},
|
|
219
255
|
toggleDebugMode: function () {
|
|
220
256
|
debugMode = !debugMode;
|
|
@@ -237,13 +273,23 @@
|
|
|
237
273
|
refresh: function () {
|
|
238
274
|
refreshPages();
|
|
239
275
|
currentPage = detectVisiblePage();
|
|
276
|
+
recordVisibleSource();
|
|
240
277
|
return api.notifyPageChange();
|
|
241
278
|
},
|
|
242
279
|
|
|
243
280
|
// ── ADR 0005 generic primitives ─────────────────────────────────────────
|
|
244
281
|
// Bumped whenever a command/event is added so a hot-updated SPA can
|
|
245
282
|
// feature-detect against an older bundled lib.
|
|
246
|
-
getProtocolVersion: function () { return
|
|
283
|
+
getProtocolVersion: function () { return 3; },
|
|
284
|
+
|
|
285
|
+
// Publish any debounced reader movement before a host atomically replaces
|
|
286
|
+
// this frame. `silent` lets the shell relay the returned event itself so a
|
|
287
|
+
// queued postMessage from the outgoing frame cannot arrive after the swap.
|
|
288
|
+
flushScroll: function (silent) {
|
|
289
|
+
if (scrollTimer) clearTimeout(scrollTimer);
|
|
290
|
+
scrollTimer = null;
|
|
291
|
+
return publishScrollPosition(true, silent === true);
|
|
292
|
+
},
|
|
247
293
|
|
|
248
294
|
// Heading tree with page + source line — powers chapter jump (UX-013), TOC,
|
|
249
295
|
// minimap, scrollspy. Page math needs same-origin paged.js access, so it
|
|
@@ -313,6 +359,7 @@
|
|
|
313
359
|
}
|
|
314
360
|
var page = pageIndexOf(el);
|
|
315
361
|
if (page) currentPage = page;
|
|
362
|
+
if (!opts.smooth) recordVisibleSource();
|
|
316
363
|
return { page: page || currentPage, sourceLine: lineOf(el) };
|
|
317
364
|
},
|
|
318
365
|
|
|
@@ -369,6 +416,7 @@
|
|
|
369
416
|
if (spec.scroll && els[0]) {
|
|
370
417
|
ignoreScrollUntil = Date.now() + 350;
|
|
371
418
|
els[0].scrollIntoView({ behavior: 'instant', block: 'center', inline: 'nearest' });
|
|
419
|
+
recordVisibleSource();
|
|
372
420
|
}
|
|
373
421
|
if (spec.transient && els.length) {
|
|
374
422
|
setTimeout(function () {
|
|
@@ -458,28 +506,38 @@
|
|
|
458
506
|
|
|
459
507
|
// Scroll tracking
|
|
460
508
|
var scrollTimer = null;
|
|
461
|
-
|
|
462
|
-
|
|
509
|
+
function publishScrollPosition(force, silent) {
|
|
510
|
+
scrollTimer = null;
|
|
511
|
+
var remainingGuard = ignoreScrollUntil - Date.now();
|
|
512
|
+
if (!force && remainingGuard > 0) {
|
|
513
|
+
scrollTimer = setTimeout(publishScrollPosition, remainingGuard);
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
463
516
|
if (pages.length === 0) refreshPages();
|
|
464
|
-
if (pages.length === 0) return;
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}));
|
|
517
|
+
if (pages.length === 0) return null;
|
|
518
|
+
var page = detectVisiblePage();
|
|
519
|
+
if (page !== currentPage) {
|
|
520
|
+
currentPage = page;
|
|
521
|
+
if (!silent) api.notifyPageChange();
|
|
522
|
+
}
|
|
523
|
+
// Emit finer-grained source position for editor sync (ADR 0005).
|
|
524
|
+
var pos = visibleSourcePosition();
|
|
525
|
+
var sl = pos ? pos.line : null;
|
|
526
|
+
var chapter = pos ? chapterOf(pos.el) : null;
|
|
527
|
+
if (sl != null && (sl !== lastSourceLine || chapter !== lastSourceChapter)) {
|
|
528
|
+
lastSourceLine = sl;
|
|
529
|
+
lastSourceChapter = chapter;
|
|
530
|
+
var detail = { sourceLine: sl, chapter: chapter, page: pageIndexOf(pos.el) };
|
|
531
|
+
if (!silent) {
|
|
532
|
+
window.dispatchEvent(new CustomEvent('sourceLineChanged', { detail: detail }));
|
|
481
533
|
}
|
|
482
|
-
|
|
534
|
+
return detail;
|
|
535
|
+
}
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
window.addEventListener('scroll', function () {
|
|
539
|
+
if (scrollTimer) clearTimeout(scrollTimer);
|
|
540
|
+
scrollTimer = setTimeout(publishScrollPosition, 150);
|
|
483
541
|
});
|
|
484
542
|
|
|
485
543
|
// Paged.js calls this when rendering is complete
|
|
@@ -490,7 +548,8 @@
|
|
|
490
548
|
pageObserver.disconnect();
|
|
491
549
|
currentPage = 1;
|
|
492
550
|
ignoreScrollUntil = Date.now() + 300;
|
|
493
|
-
window.scrollTo(0, 0);
|
|
551
|
+
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
|
|
552
|
+
recordVisibleSource();
|
|
494
553
|
console.log('Paged.js rendered ' + pages.length + ' pages');
|
|
495
554
|
api.notifyRenderingComplete();
|
|
496
555
|
setTimeout(api.notifyPageChange, 0);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
addNpmPlugin,
|
|
3
3
|
parseNpmPluginSpec
|
|
4
|
-
} from "./cli-
|
|
5
|
-
import"./cli-
|
|
4
|
+
} from "./cli-k4bd06sd.js";
|
|
5
|
+
import"./cli-najycadg.js";
|
|
6
6
|
import {
|
|
7
7
|
EXIT_CODES,
|
|
8
8
|
UsageError,
|
|
9
9
|
rejectExtraPositionals,
|
|
10
10
|
rejectUnknownFlags
|
|
11
|
-
} from "./cli-
|
|
12
|
-
import"./cli-
|
|
13
|
-
import"./cli-
|
|
11
|
+
} from "./cli-e5zhb0xs.js";
|
|
12
|
+
import"./cli-yzrh708h.js";
|
|
13
|
+
import"./cli-wchtvxvw.js";
|
|
14
14
|
import"./cli-yja077f6.js";
|
|
15
15
|
import"./cli-37x76zdn.js";
|
|
16
16
|
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
executeValidation,
|
|
3
|
+
publishTargetFor,
|
|
3
4
|
reportMissingTools
|
|
4
|
-
} from "./cli-
|
|
5
|
+
} from "./cli-k4bd06sd.js";
|
|
5
6
|
import {
|
|
6
7
|
log
|
|
7
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-najycadg.js";
|
|
8
9
|
import {
|
|
9
10
|
EXIT_CODES,
|
|
10
11
|
UsageError,
|
|
11
12
|
rejectExtraPositionals,
|
|
12
13
|
rejectUnknownFlags
|
|
13
|
-
} from "./cli-
|
|
14
|
-
import"./cli-
|
|
15
|
-
import"./cli-
|
|
14
|
+
} from "./cli-e5zhb0xs.js";
|
|
15
|
+
import"./cli-yzrh708h.js";
|
|
16
|
+
import"./cli-wchtvxvw.js";
|
|
16
17
|
import"./cli-yja077f6.js";
|
|
17
18
|
import"./cli-37x76zdn.js";
|
|
18
19
|
|
|
@@ -35,25 +36,19 @@ function severityRank(severity) {
|
|
|
35
36
|
return 2;
|
|
36
37
|
}
|
|
37
38
|
function buildRequiredChecks(execution) {
|
|
38
|
-
if (execution.profile !== "dtrpg")
|
|
39
|
-
return [];
|
|
40
|
-
const requiredIds = [
|
|
41
|
-
"pdf.structure.qpdf",
|
|
42
|
-
"pdf.print.pdfx-markers",
|
|
43
|
-
"pdf.print.pdfx-metadata",
|
|
44
|
-
"pdf.print.embedded-fonts"
|
|
45
|
-
];
|
|
46
39
|
const skipped = new Set(execution.tools.skippedChecks);
|
|
47
|
-
const failed = new Set(execution.report.errors.map((item) => item.checkId));
|
|
48
40
|
const passed = new Set(execution.report.passed);
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
return execution.targets.flatMap((targetId) => {
|
|
42
|
+
const failed = new Set(execution.report.errors.filter((item) => item.target === undefined || item.target === targetId).map((item) => item.checkId));
|
|
43
|
+
return publishTargetFor(targetId).requiredChecks.map((id) => {
|
|
44
|
+
if (skipped.has(id))
|
|
45
|
+
return { target: targetId, id, status: "skipped" };
|
|
46
|
+
if (failed.has(id))
|
|
47
|
+
return { target: targetId, id, status: "fail" };
|
|
48
|
+
if (passed.has(id))
|
|
49
|
+
return { target: targetId, id, status: "pass" };
|
|
50
|
+
return { target: targetId, id, status: "fail" };
|
|
51
|
+
});
|
|
57
52
|
});
|
|
58
53
|
}
|
|
59
54
|
function buildPreflightPayload(execution) {
|
|
@@ -85,8 +80,8 @@ function buildPreflightPayload(execution) {
|
|
|
85
80
|
const requiredChecks = buildRequiredChecks(execution);
|
|
86
81
|
const skippedRequired = requiredChecks.some((check) => check.status === "skipped");
|
|
87
82
|
return {
|
|
88
|
-
schemaVersion:
|
|
89
|
-
|
|
83
|
+
schemaVersion: 2,
|
|
84
|
+
targets: [...execution.targets],
|
|
90
85
|
status: computeStatus(execution.report.summary.errors, execution.report.summary.warnings, execution.tools.missing.length, skippedRequired),
|
|
91
86
|
pdf: execution.context.pdfPath ?? "",
|
|
92
87
|
summary: { ...execution.report.summary },
|
|
@@ -103,7 +98,7 @@ function toPreflightMarkdown(payload) {
|
|
|
103
98
|
lines.push("# gutterpress preflight");
|
|
104
99
|
lines.push("");
|
|
105
100
|
lines.push(`- Status: **${payload.status}**`);
|
|
106
|
-
lines.push(`-
|
|
101
|
+
lines.push(`- Targets: ${payload.targets.length > 0 ? payload.targets.join(", ") : "none"}`);
|
|
107
102
|
lines.push(`- PDF: ${payload.pdf}`);
|
|
108
103
|
lines.push(`- Summary: ${payload.summary.errors} error(s), ${payload.summary.warnings} warning(s), ${payload.summary.passed}/${payload.summary.total} checks passed`);
|
|
109
104
|
if (payload.tools.missing.length > 0) {
|
|
@@ -117,7 +112,7 @@ function toPreflightMarkdown(payload) {
|
|
|
117
112
|
lines.push("");
|
|
118
113
|
lines.push("## Required Checks");
|
|
119
114
|
for (const check of payload.requiredChecks) {
|
|
120
|
-
lines.push(`- ${check.id}: ${check.status}`);
|
|
115
|
+
lines.push(`- [${check.target}] ${check.id}: ${check.status}`);
|
|
121
116
|
}
|
|
122
117
|
}
|
|
123
118
|
if (payload.issues.length > 0) {
|
|
@@ -155,9 +150,9 @@ var preflightArgs = {
|
|
|
155
150
|
type: "string",
|
|
156
151
|
description: "Path to manifest.yaml"
|
|
157
152
|
},
|
|
158
|
-
|
|
153
|
+
target: {
|
|
159
154
|
type: "string",
|
|
160
|
-
description: "
|
|
155
|
+
description: "Publish targets to preflight against (comma-separated, e.g. dtrpg,itch), overriding the manifest's `targets:`"
|
|
161
156
|
},
|
|
162
157
|
"report-dir": {
|
|
163
158
|
type: "string",
|
|
@@ -187,7 +182,7 @@ var preflight_default = defineCommand({
|
|
|
187
182
|
pdf: typeof args.pdf === "string" ? args.pdf : undefined,
|
|
188
183
|
input,
|
|
189
184
|
phase: "post-build",
|
|
190
|
-
|
|
185
|
+
target: typeof args.target === "string" ? args.target : undefined
|
|
191
186
|
});
|
|
192
187
|
} catch (error) {
|
|
193
188
|
log.error(error instanceof Error ? error.message : String(error));
|
|
@@ -8,31 +8,11 @@ import { type FSWatcher } from 'chokidar';
|
|
|
8
8
|
import type { ServerState } from './server-context';
|
|
9
9
|
import type { ResolvedPluginConfig } from '../schema/manifest.types';
|
|
10
10
|
/**
|
|
11
|
-
* Whether the
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Whether the incremental preview shell is active. The historical env name is
|
|
12
|
+
* retained because users may already set it. A single Markdown edit paginates
|
|
13
|
+
* only that source file; geometry-wide changes still swap a full document.
|
|
14
14
|
*/
|
|
15
15
|
export declare function incrementalPreviewEnabled(): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Shared preview render path. renderChapters() does all Markdown, CSS, and
|
|
18
|
-
* Paged.js-slot work.
|
|
19
|
-
*
|
|
20
|
-
* Named `renderPreviewBook` (ARCH finding #53) to distinguish it from
|
|
21
|
-
* build-runner.ts's `renderBook` — same name, different module, and a
|
|
22
|
-
* genuinely different contract: this one is degrade-and-report (a plugin the
|
|
23
|
-
* author enabled but hasn't installed yet is skipped with a loud warning so
|
|
24
|
-
* the rest of the live preview still renders); build-runner.ts's is
|
|
25
|
-
* fail-fast, because a final artifact must never silently drop a plugin.
|
|
26
|
-
* Both preambles now share {@link loadPluginsWithCss}.
|
|
27
|
-
*/
|
|
28
|
-
export declare function renderPreviewBook(inputPath: string, config: {
|
|
29
|
-
title?: string;
|
|
30
|
-
styles?: string[];
|
|
31
|
-
plugins?: ResolvedPluginConfig[];
|
|
32
|
-
}, opts: {
|
|
33
|
-
files: string[] | null;
|
|
34
|
-
wrapChapters: boolean;
|
|
35
|
-
}): Promise<string>;
|
|
36
16
|
/**
|
|
37
17
|
* Rewrite rendered book HTML for the live preview. Injects, in order:
|
|
38
18
|
* 1. pagedjs-interface.js — defines window.previewAPI for in-iframe controls
|
|
@@ -48,21 +28,12 @@ export declare function renderPreviewBook(inputPath: string, config: {
|
|
|
48
28
|
* serving it from a stable disk path lets the OS file-cache
|
|
49
29
|
* and Defender hash-cache stay warm across sessions.
|
|
50
30
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* in lib/markdown/assemble.ts concatenates source files flat into <body> and
|
|
56
|
-
* breaks only where project CSS or a markdown-it-paged marker says to — so any
|
|
57
|
-
* project that splits one chapter across several source files previewed with
|
|
58
|
-
* different page boundaries than the PDF it built. Preview and build now take
|
|
59
|
-
* their breaks from exactly the same rules.
|
|
60
|
-
*
|
|
61
|
-
* Chapter identity is attached to existing source-mapped blocks. No wrapper or
|
|
62
|
-
* preview-only CSS is emitted, so selectors see exactly the same document tree
|
|
63
|
-
* as the build.
|
|
31
|
+
* With `pageIsolateChapters`, each source wrapper starts on a fresh page. This
|
|
32
|
+
* is the v0.8.3 incremental-preview invariant: a standalone source render owns
|
|
33
|
+
* the same page boundary as that source in the live preview and can be spliced
|
|
34
|
+
* without paginating the full document.
|
|
64
35
|
*/
|
|
65
|
-
export declare function injectPreviewScripts(html: string): string;
|
|
36
|
+
export declare function injectPreviewScripts(html: string, pageIsolateChapters: boolean): string;
|
|
66
37
|
/**
|
|
67
38
|
* Generate HTML from markdown and write book.html to the temp directory.
|
|
68
39
|
* The desktop's iframe loads `book.html` via a relative URL — same name in
|
|
@@ -70,6 +41,12 @@ export declare function injectPreviewScripts(html: string): string;
|
|
|
70
41
|
*
|
|
71
42
|
* Empty `inputPath` writes a static placeholder — the desktop app (packages/desktop)
|
|
72
43
|
* supplies a real path via its own folder picker.
|
|
44
|
+
*
|
|
45
|
+
* `cssAssets` is REQUIRED, not optional: it is the map the HTTP server resolves
|
|
46
|
+
* the inliner's rewritten asset URLs against (see {@link ServerState.cssAssets}),
|
|
47
|
+
* so a caller that skipped it would render a book.html whose shared-art URLs
|
|
48
|
+
* 404 — the exact bug this parameter exists to fix, reintroduced silently.
|
|
49
|
+
* Every render replaces its contents.
|
|
73
50
|
*/
|
|
74
51
|
export declare function generateAndWriteHtml(inputPath: string, tempDir: string, config: {
|
|
75
52
|
title?: string;
|
|
@@ -78,7 +55,38 @@ export declare function generateAndWriteHtml(inputPath: string, tempDir: string,
|
|
|
78
55
|
files?: string[] | null;
|
|
79
56
|
};
|
|
80
57
|
plugins?: ResolvedPluginConfig[];
|
|
81
|
-
}): Promise<void>;
|
|
58
|
+
}, cssAssets: Map<string, string>): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Render one source file with the same CSS, plugins, source metadata, and
|
|
61
|
+
* preview scripts as the full book. The shell paginates this small document in
|
|
62
|
+
* a hidden iframe and replaces only the edited source file's pages.
|
|
63
|
+
*/
|
|
64
|
+
export declare function renderChapterPreviewHtml(inputPath: string, file: string, config: {
|
|
65
|
+
title?: string;
|
|
66
|
+
styles?: string[];
|
|
67
|
+
plugins?: ResolvedPluginConfig[];
|
|
68
|
+
}): Promise<string>;
|
|
69
|
+
/** One changed project file, named for the preview broadcast decision. */
|
|
70
|
+
export interface ChangedFile {
|
|
71
|
+
relativePath: string;
|
|
72
|
+
ext: string;
|
|
73
|
+
event: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Describe in-project changes using the same canonical path form emitted in
|
|
77
|
+
* `data-chapter-src`. Declared external dependencies intentionally drop out;
|
|
78
|
+
* their presence in the original change count forces a full reload.
|
|
79
|
+
*/
|
|
80
|
+
export declare function describeChanges(changes: [filePath: string, event: string][], inputResolved: string): ChangedFile[];
|
|
81
|
+
export type BroadcastDecision = {
|
|
82
|
+
kind: 'chapter-splice';
|
|
83
|
+
chapterId: string;
|
|
84
|
+
relativePath: string;
|
|
85
|
+
} | {
|
|
86
|
+
kind: 'full-reload';
|
|
87
|
+
};
|
|
88
|
+
/** A single surviving Markdown edit can be paginated independently. */
|
|
89
|
+
export declare function decideBroadcast(files: ChangedFile[], changeCount: number, incremental: boolean): BroadcastDecision;
|
|
82
90
|
/**
|
|
83
91
|
* Chokidar 5's `ignored` matcher (regex or function) is tested against the
|
|
84
92
|
* fully-qualified, forward-slash-normalized ABSOLUTE path — never a path
|
|
@@ -102,7 +110,8 @@ export declare function isDotPathUnderRoot(candidatePath: string, root: string):
|
|
|
102
110
|
* Whether the watcher should ignore a path.
|
|
103
111
|
*
|
|
104
112
|
* IN-PROJECT paths get the dotfile rule ({@link isDotPathUnderRoot}) — a
|
|
105
|
-
* project's own `.git/`, `.DS_Store`, editor swap files, and so on are noise
|
|
113
|
+
* project's own `.git/`, `.DS_Store`, editor swap files, and so on are noise —
|
|
114
|
+
* plus the generated/vendored-subtree rule ({@link isGeneratedProjectPath}).
|
|
106
115
|
*
|
|
107
116
|
* A path OUTSIDE the project is only ever seen because it is a DECLARED
|
|
108
117
|
* external dependency the manifest named explicitly (see
|
|
@@ -17,10 +17,13 @@ export interface PreviewServer {
|
|
|
17
17
|
/** Stop the server and close all connections. */
|
|
18
18
|
close(): Promise<void>;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
20
|
+
* Advance the rendered revision and notify every connected HMR client.
|
|
21
|
+
* Disconnected clients reconcile to the latest revision when they reconnect.
|
|
22
|
+
* Safe to call after `close()` (no-op).
|
|
22
23
|
*/
|
|
23
24
|
broadcastReload(): void;
|
|
25
|
+
/** Paginate and replace one edited Markdown source in connected shells. */
|
|
26
|
+
broadcastContentUpdate(file: string): void;
|
|
24
27
|
}
|
|
25
28
|
export declare function isPortAvailable(port: number, host?: string): Promise<boolean>;
|
|
26
29
|
/**
|
|
@@ -19,6 +19,8 @@ export interface ServerState {
|
|
|
19
19
|
isRebuilding: boolean;
|
|
20
20
|
/** Active rebuild, awaited before a project restart closes its watcher. */
|
|
21
21
|
rebuildPromise?: Promise<void> | null;
|
|
22
|
+
/** Bypass watcher settling for a host write that has already completed. */
|
|
23
|
+
notifySettledWrite?: ((filePath: string, writtenContent: string) => void) | null;
|
|
22
24
|
/** node:http + `ws` preview HTTP/WebSocket server instance */
|
|
23
25
|
previewServer: PreviewServer | null;
|
|
24
26
|
/** Is server shutting down? (prevents multiple shutdown calls) */
|
|
@@ -29,6 +31,28 @@ export interface ServerState {
|
|
|
29
31
|
config: ResolvedConfig;
|
|
30
32
|
/** Server options */
|
|
31
33
|
options: PreviewServerOptions;
|
|
34
|
+
/**
|
|
35
|
+
* Files the inlined CSS references but could not embed, as
|
|
36
|
+
* `book.html`-relative URL path → absolute source path.
|
|
37
|
+
*
|
|
38
|
+
* `asset-inline.ts` embeds fonts and images up to
|
|
39
|
+
* `IMAGE_INLINE_MAX_BYTES`; anything larger keeps its project-relative path
|
|
40
|
+
* (if it lives in the book) or becomes `assets/<contentHash><ext>` (if it
|
|
41
|
+
* does not — e.g. art referenced from a repo-root shared stylesheet, the
|
|
42
|
+
* normative multi-book layout). Either way the inliner returns a COPY PLAN,
|
|
43
|
+
* which the build executes into its output dir.
|
|
44
|
+
*
|
|
45
|
+
* The preview serves the project in place and has no output dir, so a
|
|
46
|
+
* rewritten `assets/<hash>` URL had nothing behind it and shared art
|
|
47
|
+
* rendered broken in the live preview while building correctly. Keeping the
|
|
48
|
+
* plan here lets the server resolve those URLs straight from their real
|
|
49
|
+
* location — same URL as the build, still nothing copied.
|
|
50
|
+
*
|
|
51
|
+
* Rebuilt from scratch on every render, so a stylesheet edit that drops an
|
|
52
|
+
* image drops its URL too. Exact-match lookups only: never a path-traversal
|
|
53
|
+
* surface.
|
|
54
|
+
*/
|
|
55
|
+
cssAssets: Map<string, string>;
|
|
32
56
|
}
|
|
33
57
|
/**
|
|
34
58
|
* Create initial server state
|