gutterpress 0.9.0-alpha.1 → 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.
Files changed (30) hide show
  1. package/dist/api/index.js +1 -1
  2. package/dist/{audit-k16v3n98.js → audit-nhn2pjz3.js} +3 -3
  3. package/dist/{build-8tqr4gbb.js → build-san7fv2z.js} +3 -3
  4. package/dist/{cli-rkqxbnkq.js → cli-e5zhb0xs.js} +1 -1
  5. package/dist/{cli-yp0d2hp8.js → cli-k4bd06sd.js} +377 -78
  6. package/dist/{cli-v2dze8ja.js → cli-najycadg.js} +1 -1
  7. package/dist/cli.js +15 -15
  8. package/dist/{doctor-57czxy3q.js → doctor-hrk0kxxz.js} +2 -2
  9. package/dist/{index-m3pa4wyf.js → index-bynn850m.js} +379 -80
  10. package/dist/index.js +1 -1
  11. package/dist/lib/markdown/assemble.d.ts +4 -6
  12. package/dist/lib/markdown/chapter-id.d.ts +1 -1
  13. package/dist/lib/markdown/index.d.ts +1 -1
  14. package/dist/{lint-4sq0dvf6.js → lint-96j9hrj4.js} +3 -3
  15. package/dist/{new-f2nmyr5b.js → new-8p38wavc.js} +3 -3
  16. package/dist/{pagedjs-interface-80g3xa8p.js → pagedjs-interface-qxvzgwd7.js} +92 -33
  17. package/dist/{plugin-xskq3dtx.js → plugin-ees6nhkc.js} +3 -3
  18. package/dist/{preflight-epcffags.js → preflight-1q6c2edh.js} +3 -3
  19. package/dist/preview/file-watcher.d.ts +39 -17
  20. package/dist/preview/http-server.d.ts +5 -2
  21. package/dist/preview/server-context.d.ts +2 -0
  22. package/dist/preview-shell-6dqexx1m.js +581 -0
  23. package/dist/{preview-xf5dktz2.js → preview-y5a2zen1.js} +3 -3
  24. package/dist/{publish-97vdwq31.js → publish-rm9yb3wh.js} +3 -3
  25. package/dist/render.js +10 -19
  26. package/dist/{repair-cz4z4hkg.js → repair-zgq7q2g6.js} +3 -3
  27. package/dist/server.d.ts +2 -0
  28. package/dist/{validate-swzejnd8.js → validate-nr0xa6sa.js} +3 -3
  29. package/package.json +1 -1
  30. package/dist/preview-shell-rghtfmc8.js +0 -155
@@ -0,0 +1,581 @@
1
+ // Gutterpress preview shell controller (shared by the CLI preview and Electron).
2
+ // A Markdown edit paginates only that source file and replaces its live pages;
3
+ // geometry-wide changes paginate and atomically swap a fresh full document.
4
+ (function () {
5
+ 'use strict';
6
+ var active = document.getElementById('gutterpress-active');
7
+ var building = null;
8
+ var hotReloadFrame = null;
9
+ var retiring = null;
10
+ var initialInstance = window.__GUTTERPRESS_INSTANCE;
11
+ var initialRevision = Number(window.__GUTTERPRESS_REVISION);
12
+ var appliedInstance = typeof initialInstance === 'string' ? initialInstance : '';
13
+ var appliedRevision = Number.isSafeInteger(initialRevision) && initialRevision >= 0 ? initialRevision : 0;
14
+ var desiredInstance = appliedInstance;
15
+ var desiredRevision = appliedRevision;
16
+ var reportAppliedState = function () {};
17
+ var activeReady = false;
18
+ if (!active) return;
19
+
20
+ // Transparent bridge relay: forward host-toolbar commands to the active book
21
+ // iframe and relay its replies/events back to the host.
22
+ window.addEventListener('message', function (e) {
23
+ try {
24
+ if (window.parent !== window && e.source === window.parent) {
25
+ if (active && active.contentWindow) active.contentWindow.postMessage(e.data, '*');
26
+ } else if (active && e.source === active.contentWindow && window.parent !== window) {
27
+ var data = e.data;
28
+ if (active === hotReloadFrame && data && data.type === 'gutterpress:event' && data.name === 'ready') return;
29
+ if (active === hotReloadFrame && data && data.type === 'gutterpress:event' && data.name === 'renderingComplete') {
30
+ var detail = {}, sourceDetail = data.detail || {};
31
+ for (var key in sourceDetail) {
32
+ if (Object.prototype.hasOwnProperty.call(sourceDetail, key)) detail[key] = sourceDetail[key];
33
+ }
34
+ detail.hotReload = true;
35
+ var startedAt = hotReloadFrame.__gutterpressReloadStartedAt;
36
+ detail.hotReloadMs = typeof startedAt === 'number' ? Math.max(0, Date.now() - startedAt) : 0;
37
+ detail.revision = hotReloadFrame.__gutterpressRevision;
38
+ detail.updateMode = 'full-reload';
39
+ data = { type: data.type, name: data.name, detail: detail };
40
+ hotReloadFrame = null;
41
+ }
42
+ window.parent.postMessage(data, '*');
43
+ } else if (retiring && e.source === retiring.contentWindow && window.parent !== window) {
44
+ var retiringData = e.data;
45
+ if (
46
+ retiringData &&
47
+ (retiringData.type === 'gutterpress:reply' ||
48
+ (retiringData.type === 'gutterpress:event' &&
49
+ retiringData.name === 'sourceLineChanged'))
50
+ ) window.parent.postMessage(retiringData, '*');
51
+ }
52
+ } catch (_) {}
53
+ });
54
+
55
+ function fdoc(f) { try { return f.contentDocument; } catch (_) { return null; } }
56
+ function fwin(f) { try { return f.contentWindow; } catch (_) { return null; } }
57
+ function chapterOf(el) {
58
+ var chapter = el.closest && el.closest('[data-chapter-src]');
59
+ return chapter ? chapter.getAttribute('data-chapter-src') : null;
60
+ }
61
+ function blocksInChapter(d, chapter) {
62
+ var all = d.querySelectorAll('[data-source-line]');
63
+ if (!chapter) return all;
64
+ var matched = [];
65
+ for (var i = 0; i < all.length; i++) {
66
+ if (chapterOf(all[i]) === chapter) matched.push(all[i]);
67
+ }
68
+ return matched;
69
+ }
70
+
71
+ function capture(f) {
72
+ var d = fdoc(f); if (!d) return null;
73
+ var els = d.querySelectorAll('[data-source-line]'), best = null, bestTop = -Infinity;
74
+ for (var i = 0; i < els.length; i++) {
75
+ var r = els[i].getBoundingClientRect();
76
+ if (r.bottom < 0 || r.height === 0) continue;
77
+ if (r.top <= 80 && r.top > bestTop) { bestTop = r.top; best = els[i]; }
78
+ }
79
+ if (!best) {
80
+ for (var j = 0; j < els.length; j++) {
81
+ var rr = els[j].getBoundingClientRect();
82
+ if (rr.bottom > 0 && rr.height > 0) { best = els[j]; break; }
83
+ }
84
+ }
85
+ if (!best) return null;
86
+ return {
87
+ chapter: chapterOf(best),
88
+ line: best.getAttribute('data-source-line'),
89
+ offset: best.getBoundingClientRect().top
90
+ };
91
+ }
92
+
93
+ function restore(f, anchor) {
94
+ if (!anchor) return;
95
+ var w = fwin(f), d = fdoc(f); if (!w || !d) return;
96
+ var els = blocksInChapter(d, anchor.chapter);
97
+ var wanted = parseInt(anchor.line, 10), el = null, bestDiff = Infinity;
98
+ for (var i = 0; i < els.length; i++) {
99
+ var line = parseInt(els[i].getAttribute('data-source-line'), 10);
100
+ if (String(els[i].getAttribute('data-source-line')) === String(anchor.line)) {
101
+ el = els[i];
102
+ break;
103
+ }
104
+ var diff = Math.abs(line - wanted);
105
+ if (diff < bestDiff) { bestDiff = diff; el = els[i]; }
106
+ }
107
+ if (el) w.scrollBy({
108
+ top: el.getBoundingClientRect().top - anchor.offset,
109
+ behavior: 'instant'
110
+ });
111
+ }
112
+
113
+ // Paged.js preserves source wrappers on cloned flow fragments. Record every
114
+ // source represented on each page so an edit can locate its live range.
115
+ function tagPages(frame) {
116
+ var d = fdoc(frame); if (!d) return;
117
+ var pages = d.querySelectorAll('.pagedjs_page');
118
+ for (var i = 0; i < pages.length; i++) {
119
+ if (pages[i].getAttribute('data-chapter-srcs')) continue;
120
+ var nodes = pages[i].querySelectorAll('.gutterpress-chapter[data-chapter-src]');
121
+ var chapters = [];
122
+ for (var j = 0; j < nodes.length; j++) {
123
+ var chapter = nodes[j].getAttribute('data-chapter-src');
124
+ if (chapter && chapters.indexOf(chapter) === -1) chapters.push(chapter);
125
+ }
126
+ if (!chapters.length) continue;
127
+ pages[i].setAttribute('data-chapter-src', chapters[0]);
128
+ pages[i].setAttribute('data-chapter-srcs', chapters.join('\n'));
129
+ }
130
+ }
131
+
132
+ function pageChapters(page) {
133
+ var value = page.getAttribute('data-chapter-srcs') ||
134
+ page.getAttribute('data-chapter-src') || '';
135
+ return value ? value.split('\n') : [];
136
+ }
137
+
138
+ function normId(value) {
139
+ var result = String(value || '').replace(/\\/g, '/').replace(/\/{2,}/g, '/');
140
+ while (result.indexOf('./') === 0) result = result.slice(2);
141
+ return result;
142
+ }
143
+
144
+ function liveChapterIds(d) {
145
+ var pages = d.querySelectorAll('.pagedjs_page'), ids = [];
146
+ for (var i = 0; i < pages.length; i++) {
147
+ var chapters = pageChapters(pages[i]);
148
+ for (var j = 0; j < chapters.length; j++) {
149
+ if (ids.indexOf(chapters[j]) === -1) ids.push(chapters[j]);
150
+ }
151
+ }
152
+ return ids;
153
+ }
154
+
155
+ function resolveChapterId(d, file) {
156
+ var ids = liveChapterIds(d);
157
+ if (ids.indexOf(file) !== -1) return file;
158
+ var wanted = normId(file), matches = [];
159
+ for (var i = 0; i < ids.length; i++) {
160
+ if (normId(ids[i]) === wanted) matches.push(ids[i]);
161
+ }
162
+ return matches.length === 1 ? matches[0] : null;
163
+ }
164
+
165
+ function pagesFor(d, file) {
166
+ var pages = d.querySelectorAll('.pagedjs_page');
167
+ var owned = [], shared = [], first = -1, last = -1;
168
+ for (var i = 0; i < pages.length; i++) {
169
+ var chapters = pageChapters(pages[i]);
170
+ if (chapters.indexOf(file) === -1) continue;
171
+ if (first === -1) first = i;
172
+ last = i;
173
+ if (chapters.length > 1) shared.push(pages[i]);
174
+ }
175
+ for (i = first; i !== -1 && i <= last; i++) {
176
+ var pageIds = pageChapters(pages[i]);
177
+ // Blank pages generated inside a source range carry no source element.
178
+ // Keep them with the range so an incremental replacement cannot move a
179
+ // recto/verso blank from the middle to the end of the chapter.
180
+ if (pageIds.indexOf(file) !== -1 || pageIds.length === 0) owned.push(pages[i]);
181
+ }
182
+ return { owned: owned, shared: shared };
183
+ }
184
+
185
+ // Remove only top-level fragments for this source. Ignoring nested matches
186
+ // avoids removing a parent and then attempting to remove its descendants.
187
+ function removeChapterFragments(page, file) {
188
+ var nodes = page.querySelectorAll('.gutterpress-chapter[data-chapter-src]');
189
+ for (var i = 0; i < nodes.length; i++) {
190
+ if (nodes[i].getAttribute('data-chapter-src') !== file) continue;
191
+ var ancestor = nodes[i].parentElement, nested = false;
192
+ while (ancestor && ancestor !== page) {
193
+ if (ancestor.getAttribute('data-chapter-src') === file) { nested = true; break; }
194
+ ancestor = ancestor.parentElement;
195
+ }
196
+ if (!nested && nodes[i].parentNode) nodes[i].parentNode.removeChild(nodes[i]);
197
+ }
198
+ }
199
+
200
+ function reportIncrementalComplete(instance, revision, startedAt) {
201
+ appliedInstance = instance;
202
+ appliedRevision = revision;
203
+ activeReady = true;
204
+ reportAppliedState(appliedInstance, appliedRevision);
205
+ if (window.parent === window) return;
206
+ var api = fwin(active) && fwin(active).previewAPI;
207
+ window.parent.postMessage({
208
+ type: 'gutterpress:event',
209
+ name: 'renderingComplete',
210
+ detail: {
211
+ totalPages: api && typeof api.getTotalPages === 'function' ? api.getTotalPages() : 0,
212
+ hotReload: true,
213
+ hotReloadMs: Math.max(0, Date.now() - startedAt),
214
+ revision: revision,
215
+ updateMode: 'chapter-splice'
216
+ }
217
+ }, '*');
218
+ }
219
+
220
+ // Carry desktop canvas/debug CSS and view state into the hidden replacement
221
+ // so its first visible paint matches the frame it replaces.
222
+ function copyPresentation(from, to) {
223
+ var source = fdoc(from), target = fdoc(to), targetWindow = fwin(to);
224
+ if (!source || !target || !targetWindow) return;
225
+ var styles = source.querySelectorAll(
226
+ 'style[data-gutterpress-desktop-canvas],style[data-gutterpress-debug]'
227
+ );
228
+ for (var i = 0; i < styles.length; i++) {
229
+ (target.head || target.documentElement).appendChild(styles[i].cloneNode(true));
230
+ }
231
+ var api = targetWindow.previewAPI;
232
+ var sourceBody = source.body;
233
+ if (api && sourceBody) {
234
+ if (sourceBody.classList.contains('view-single')) api.setViewMode('single', true);
235
+ else if (sourceBody.classList.contains('view-spread')) api.setViewMode('spread', true);
236
+ else if (sourceBody.classList.contains('view-two-column')) api.setViewMode('two-column', true);
237
+ if (sourceBody.classList.contains('debug')) api.toggleDebugMode();
238
+ }
239
+ var zoom = source.documentElement.style.getPropertyValue('--gutterpress-zoom');
240
+ if (api && zoom) api.setZoom(zoom, true);
241
+ }
242
+
243
+ function onReady(frame, callback, onTimeout, timeoutMs) {
244
+ var w = fwin(frame), d = fdoc(frame);
245
+ if (!w || !d) { callback(); return function () {}; }
246
+ var done = false, timer = null;
247
+ function cleanup() {
248
+ if (timer !== null) clearTimeout(timer);
249
+ w.removeEventListener('renderingComplete', finish);
250
+ }
251
+ function finish() {
252
+ if (done) return;
253
+ done = true;
254
+ cleanup();
255
+ callback();
256
+ }
257
+ var hasPaged = !!d.querySelector('script[src*="paged.polyfill"]');
258
+ if (hasPaged) {
259
+ w.addEventListener('renderingComplete', finish);
260
+ if (w.__PAGED_RENDERED__ === true) setTimeout(finish, 0);
261
+ timer = setTimeout(function () {
262
+ if (done) return;
263
+ done = true;
264
+ cleanup();
265
+ if (onTimeout) onTimeout();
266
+ }, timeoutMs || 180000);
267
+ } else {
268
+ var attempts = 0;
269
+ (function poll() {
270
+ var current = fdoc(frame);
271
+ if (current && current.querySelectorAll('.pagedjs_page').length > 0) { finish(); return; }
272
+ if (attempts++ < 800 && !done) timer = setTimeout(poll, 25);
273
+ else if (!done) {
274
+ done = true;
275
+ cleanup();
276
+ if (onTimeout) onTimeout();
277
+ }
278
+ })();
279
+ }
280
+ return function () { done = true; cleanup(); };
281
+ }
282
+
283
+ function discardBuilding() {
284
+ if (!building) return;
285
+ if (typeof building.__gutterpressCancelReady === 'function') {
286
+ building.__gutterpressCancelReady();
287
+ }
288
+ if (building.parentNode) building.parentNode.removeChild(building);
289
+ building = null;
290
+ }
291
+
292
+ function swap(instance, revision) {
293
+ discardBuilding();
294
+ var frame = document.createElement('iframe');
295
+ frame.style.visibility = 'hidden';
296
+ frame.setAttribute('aria-hidden', 'true');
297
+ frame.title = active.title || 'preview';
298
+ frame.__gutterpressReloadStartedAt = Date.now();
299
+ frame.__gutterpressInstance = instance;
300
+ frame.__gutterpressRevision = revision;
301
+ frame.src = '/book.html?gutterpressshell=1&instance=' + encodeURIComponent(instance)
302
+ + '&revision=' + revision + '&bust=' + Date.now();
303
+ building = frame;
304
+
305
+ var finished = false;
306
+ function finish() {
307
+ if (finished || building !== frame) return;
308
+ finished = true;
309
+ frame.__gutterpressCancelReady = null;
310
+ var activeApi = fwin(active) && fwin(active).previewAPI;
311
+ var pendingSource = activeApi && typeof activeApi.flushScroll === 'function'
312
+ ? activeApi.flushScroll(true)
313
+ : null;
314
+ if (pendingSource && window.parent !== window) {
315
+ window.parent.postMessage({
316
+ type: 'gutterpress:event',
317
+ name: 'sourceLineChanged',
318
+ detail: pendingSource
319
+ }, '*');
320
+ }
321
+ var anchor = capture(active);
322
+ copyPresentation(active, frame);
323
+ restore(frame, anchor);
324
+ var old = active;
325
+ old.removeAttribute('id');
326
+ frame.id = 'gutterpress-active';
327
+ retiring = old;
328
+ active = frame;
329
+ hotReloadFrame = frame;
330
+ building = null;
331
+ tagPages(frame);
332
+ var api = fwin(frame) && fwin(frame).previewAPI;
333
+ if (api && typeof api.refresh === 'function') api.refresh();
334
+ frame.style.visibility = 'visible';
335
+ frame.removeAttribute('aria-hidden');
336
+ appliedInstance = instance;
337
+ appliedRevision = revision;
338
+ activeReady = true;
339
+ reportAppliedState(appliedInstance, appliedRevision);
340
+ requestAnimationFrame(function () {
341
+ requestAnimationFrame(function () {
342
+ if (old && old.parentNode) old.parentNode.removeChild(old);
343
+ if (retiring === old) retiring = null;
344
+ });
345
+ });
346
+ }
347
+
348
+ frame.addEventListener('load', function () {
349
+ frame.__gutterpressCancelReady = onReady(frame, finish, function () {
350
+ if (building !== frame) return;
351
+ discardBuilding();
352
+ if (window.console) console.warn('[gutterpress] replacement pagination timed out');
353
+ });
354
+ });
355
+ document.body.appendChild(frame);
356
+ }
357
+
358
+ function spliceChapter(file, instance, revision) {
359
+ discardBuilding();
360
+ tagPages(active);
361
+ var activeDocument = fdoc(active);
362
+ var liveId = activeDocument ? resolveChapterId(activeDocument, file) : null;
363
+ if (!liveId) {
364
+ if (window.console) {
365
+ console.warn('[gutterpress] chapter not found in live pages; using full reload:', file);
366
+ }
367
+ swap(instance, revision);
368
+ return;
369
+ }
370
+
371
+ var startedAt = Date.now();
372
+ var frame = document.createElement('iframe');
373
+ frame.style.visibility = 'hidden';
374
+ frame.setAttribute('aria-hidden', 'true');
375
+ frame.title = 'updated chapter';
376
+ frame.src = '/__chapter?file=' + encodeURIComponent(file) + '&revision=' + revision +
377
+ '&bust=' + Date.now();
378
+ building = frame;
379
+
380
+ function finish() {
381
+ if (building !== frame) return;
382
+ frame.__gutterpressCancelReady = null;
383
+ try {
384
+ var ad = fdoc(active), sourceDocument = fdoc(frame);
385
+ if (!ad || !sourceDocument) throw new Error('chapter frame is unavailable');
386
+ var activeApi = fwin(active) && fwin(active).previewAPI;
387
+ var pendingSource = activeApi && typeof activeApi.flushScroll === 'function'
388
+ ? activeApi.flushScroll(true)
389
+ : null;
390
+ if (pendingSource && window.parent !== window) {
391
+ window.parent.postMessage({
392
+ type: 'gutterpress:event',
393
+ name: 'sourceLineChanged',
394
+ detail: pendingSource
395
+ }, '*');
396
+ }
397
+ var anchor = capture(active);
398
+ var container = ad.querySelector('.pagedjs_pages') || ad.body;
399
+ var found = pagesFor(ad, liveId);
400
+ var allNewPages = Array.prototype.slice.call(
401
+ sourceDocument.querySelectorAll('.pagedjs_page')
402
+ );
403
+ var firstContentPage = -1, lastContentPage = -1;
404
+ for (var pageIndex = 0; pageIndex < allNewPages.length; pageIndex++) {
405
+ if (!allNewPages[pageIndex].querySelector('[data-chapter-src]')) continue;
406
+ if (firstContentPage === -1) firstContentPage = pageIndex;
407
+ lastContentPage = pageIndex;
408
+ }
409
+ var newPages = firstContentPage === -1
410
+ ? []
411
+ : allNewPages.slice(firstContentPage, lastContentPage + 1);
412
+ if (!found.owned.length) throw new Error('chapter is absent from the live page range');
413
+ if (!newPages.length) throw new Error('chapter pagination produced no pages');
414
+
415
+ var first = found.owned[0];
416
+ var firstIsShared = found.shared.indexOf(first) !== -1;
417
+ var firstOrder = pageChapters(first);
418
+ var at = firstIsShared && firstOrder.indexOf(liveId) > 0
419
+ ? first.nextElementSibling
420
+ : first;
421
+ var exclusive = [];
422
+ for (var i = 0; i < found.owned.length; i++) {
423
+ if (found.shared.indexOf(found.owned[i]) === -1) exclusive.push(found.owned[i]);
424
+ }
425
+
426
+ for (i = 0; i < found.shared.length; i++) {
427
+ removeChapterFragments(found.shared[i], liveId);
428
+ var remaining = pageChapters(found.shared[i]).filter(function (chapter) {
429
+ return chapter !== liveId;
430
+ });
431
+ if (remaining.length) {
432
+ found.shared[i].setAttribute('data-chapter-src', remaining[0]);
433
+ found.shared[i].setAttribute('data-chapter-srcs', remaining.join('\n'));
434
+ } else {
435
+ found.shared[i].removeAttribute('data-chapter-src');
436
+ found.shared[i].removeAttribute('data-chapter-srcs');
437
+ }
438
+ }
439
+
440
+ for (i = 0; i < newPages.length; i++) {
441
+ var imported = ad.importNode(newPages[i], true);
442
+ imported.setAttribute('data-chapter-src', liveId);
443
+ imported.setAttribute('data-chapter-srcs', liveId);
444
+ container.insertBefore(imported, at);
445
+ }
446
+ for (i = 0; i < exclusive.length; i++) {
447
+ if (exclusive[i].parentNode) exclusive[i].parentNode.removeChild(exclusive[i]);
448
+ }
449
+
450
+ restore(active, anchor);
451
+ var api = fwin(active) && fwin(active).previewAPI;
452
+ if (api && typeof api.refresh === 'function') api.refresh();
453
+ building = null;
454
+ if (frame.parentNode) frame.parentNode.removeChild(frame);
455
+ reportIncrementalComplete(instance, revision, startedAt);
456
+ } catch (error) {
457
+ building = null;
458
+ if (frame.parentNode) frame.parentNode.removeChild(frame);
459
+ if (window.console) console.warn('[gutterpress] chapter splice failed; using full reload:', error);
460
+ swap(instance, revision);
461
+ }
462
+ }
463
+
464
+ frame.addEventListener('load', function () {
465
+ if (building !== frame) return;
466
+ var loadedDocument = fdoc(frame);
467
+ if (!loadedDocument || (
468
+ !loadedDocument.querySelector('script[src*="paged.polyfill"]') &&
469
+ !loadedDocument.querySelector('.pagedjs_page')
470
+ )) {
471
+ discardBuilding();
472
+ swap(instance, revision);
473
+ return;
474
+ }
475
+ frame.__gutterpressCancelReady = onReady(frame, finish, function () {
476
+ if (building !== frame) return;
477
+ discardBuilding();
478
+ if (window.console) console.warn('[gutterpress] chapter pagination timed out; using full reload');
479
+ swap(instance, revision);
480
+ }, 15000);
481
+ });
482
+ document.body.appendChild(frame);
483
+ }
484
+
485
+ function tagInitialPages() {
486
+ onReady(active, function () {
487
+ tagPages(active);
488
+ activeReady = true;
489
+ reportAppliedState(appliedInstance, appliedRevision);
490
+ });
491
+ }
492
+ if (active.contentDocument && active.contentDocument.readyState === 'complete') tagInitialPages();
493
+ active.addEventListener('load', tagInitialPages);
494
+
495
+ function connectChanges(onMessage) {
496
+ var source = window.__GUTTERPRESS_CHANGE_SOURCE;
497
+ if (source && typeof source.subscribe === 'function') {
498
+ reportAppliedState = function (instance, revision) {
499
+ if (typeof source.acknowledge === 'function') source.acknowledge(instance, revision);
500
+ };
501
+ var unsubscribe = source.subscribe(onMessage);
502
+ return typeof unsubscribe === 'function' ? unsubscribe : function () {};
503
+ }
504
+ var wsPath = window.__GUTTERPRESS_HMR || '/__gutterpress-hmr';
505
+ var ws = null;
506
+ var reconnectTimer = null;
507
+ var reconnectDelay = 250;
508
+ var stopped = false;
509
+
510
+ reportAppliedState = function (instance, revision) {
511
+ if (!ws || ws.readyState !== 1) return;
512
+ try {
513
+ ws.send(JSON.stringify({ type: 'reload-applied', instance: instance, revision: revision }));
514
+ } catch (_) {}
515
+ };
516
+
517
+ function connect() {
518
+ if (stopped) return;
519
+ ws = new WebSocket(location.origin.replace(/^http/, 'ws') + wsPath);
520
+ ws.onopen = function () {
521
+ reconnectDelay = 250;
522
+ if (activeReady) reportAppliedState(appliedInstance, appliedRevision);
523
+ };
524
+ ws.onmessage = function (event) {
525
+ var message;
526
+ try { message = JSON.parse(event.data); } catch (_) { return; }
527
+ onMessage(message);
528
+ };
529
+ ws.onclose = function () {
530
+ ws = null;
531
+ if (stopped || reconnectTimer !== null) return;
532
+ reconnectTimer = setTimeout(function () {
533
+ reconnectTimer = null;
534
+ connect();
535
+ }, reconnectDelay);
536
+ reconnectDelay = Math.min(reconnectDelay * 2, 5000);
537
+ };
538
+ ws.onerror = function () { try { ws.close(); } catch (_) {} };
539
+ }
540
+
541
+ connect();
542
+ return function () {
543
+ stopped = true;
544
+ if (reconnectTimer !== null) clearTimeout(reconnectTimer);
545
+ try { if (ws) ws.close(); } catch (_) {}
546
+ };
547
+ }
548
+
549
+ var disconnectChanges = connectChanges(function (message) {
550
+ if (!message || (
551
+ message.type !== 'reload-state' &&
552
+ message.type !== 'full-reload' &&
553
+ message.type !== 'content-update'
554
+ )) return;
555
+ var instance = typeof message.instance === 'string' ? message.instance : null;
556
+ var revision = Number(message.revision);
557
+ if (!instance || !Number.isSafeInteger(revision) || revision < 0) return;
558
+ if (instance === appliedInstance && revision <= appliedRevision) {
559
+ if (activeReady) reportAppliedState(appliedInstance, appliedRevision);
560
+ return;
561
+ }
562
+ if (
563
+ instance === desiredInstance &&
564
+ (revision < desiredRevision || (revision === desiredRevision && building))
565
+ ) return;
566
+ var updateOverlaps = !!building;
567
+ desiredInstance = instance;
568
+ desiredRevision = revision;
569
+ if (
570
+ message.type === 'content-update' &&
571
+ typeof message.file === 'string' &&
572
+ message.file &&
573
+ !updateOverlaps
574
+ ) {
575
+ spliceChapter(message.file, instance, revision);
576
+ } else {
577
+ swap(instance, revision);
578
+ }
579
+ });
580
+ window.addEventListener('beforeunload', disconnectChanges);
581
+ })();
@@ -6,10 +6,10 @@ import {
6
6
  runBuild,
7
7
  splitOutPath,
8
8
  startPreviewServer
9
- } from "./cli-yp0d2hp8.js";
9
+ } from "./cli-k4bd06sd.js";
10
10
  import {
11
11
  log
12
- } from "./cli-v2dze8ja.js";
12
+ } from "./cli-najycadg.js";
13
13
  import {
14
14
  BuildError,
15
15
  UsageError,
@@ -18,7 +18,7 @@ import {
18
18
  rejectExtraPositionals,
19
19
  rejectUnknownFlags,
20
20
  resolvePort
21
- } from "./cli-rkqxbnkq.js";
21
+ } from "./cli-e5zhb0xs.js";
22
22
  import"./cli-yzrh708h.js";
23
23
  import"./cli-wchtvxvw.js";
24
24
  import"./cli-yja077f6.js";
@@ -7,17 +7,17 @@ import {
7
7
  publishCredentialKey,
8
8
  publishProviderFor,
9
9
  runPublish
10
- } from "./cli-yp0d2hp8.js";
10
+ } from "./cli-k4bd06sd.js";
11
11
  import {
12
12
  FileTokenStore,
13
13
  log
14
- } from "./cli-v2dze8ja.js";
14
+ } from "./cli-najycadg.js";
15
15
  import {
16
16
  EXIT_CODES,
17
17
  UsageError,
18
18
  rejectExtraPositionals,
19
19
  rejectUnknownFlags
20
- } from "./cli-rkqxbnkq.js";
20
+ } from "./cli-e5zhb0xs.js";
21
21
  import"./cli-yzrh708h.js";
22
22
  import"./cli-wchtvxvw.js";
23
23
  import"./cli-yja077f6.js";
package/dist/render.js CHANGED
@@ -600,17 +600,6 @@ async function assembleBookHtml(opts) {
600
600
  throw new Error("No markdown files to render");
601
601
  }
602
602
  const md = createMarkdownRenderer(opts.plugins);
603
- let sourceChapter = null;
604
- if (opts.wrapChapters) {
605
- const renderToken = md.renderer.renderToken.bind(md.renderer);
606
- md.renderer.renderToken = (tokens, idx, options) => {
607
- const token = tokens[idx];
608
- if (sourceChapter !== null && token.level === 0 && token.map !== null && token.type.endsWith("_open")) {
609
- token.attrSet("data-chapter-src", sourceChapter);
610
- }
611
- return renderToken(tokens, idx, options);
612
- };
613
- }
614
603
  let bodyContent = "";
615
604
  const imageRefs = new Set;
616
605
  for (const file of files) {
@@ -623,20 +612,22 @@ async function assembleBookHtml(opts) {
623
612
  throw new Error(`Failed to read file ${file}: ${errorMsg}`);
624
613
  }
625
614
  const env = {};
626
- sourceChapter = opts.wrapChapters ? chapterId : null;
627
- let rendered;
628
- try {
629
- rendered = md.render(content, env);
630
- } finally {
631
- sourceChapter = null;
632
- }
615
+ const rendered = md.render(content, env);
633
616
  if (env.layoutWarnings && env.layoutWarnings.length > 0) {
634
617
  opts.onChapterWarnings?.(chapterId, env.layoutWarnings);
635
618
  }
636
619
  for (const ref of env.imageRefs ?? [])
637
620
  imageRefs.add(ref);
638
- bodyContent += rendered + `
621
+ if (opts.wrapChapters) {
622
+ const safe = chapterId.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
623
+ bodyContent += `<div class="gutterpress-chapter" data-chapter-src="${safe}">
624
+ ${rendered}
625
+ </div>
626
+ `;
627
+ } else {
628
+ bodyContent += rendered + `
639
629
  `;
630
+ }
640
631
  }
641
632
  if (opts.onImageRefs) {
642
633
  for (const ref of collectHtmlImageRefs(bodyContent))
@@ -8,16 +8,16 @@ import {
8
8
  makeManualGuidance,
9
9
  recover,
10
10
  verifyRepoReadable
11
- } from "./cli-yp0d2hp8.js";
11
+ } from "./cli-k4bd06sd.js";
12
12
  import {
13
13
  FileTokenStore,
14
14
  defaultConfigDir
15
- } from "./cli-v2dze8ja.js";
15
+ } from "./cli-najycadg.js";
16
16
  import {
17
17
  UsageError,
18
18
  rejectExtraPositionals,
19
19
  rejectUnknownFlags
20
- } from "./cli-rkqxbnkq.js";
20
+ } from "./cli-e5zhb0xs.js";
21
21
  import"./cli-yzrh708h.js";
22
22
  import"./cli-wchtvxvw.js";
23
23
  import"./cli-yja077f6.js";