gutterpress 0.11.23-beta.1 → 0.11.23-beta.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 +1 -1
- package/dist/api/index.js +5 -5
- package/dist/{build-dg8a566j.js → build-3e18wnqj.js} +8 -8
- package/dist/{cli-vhav8g82.js → cli-0ep11b0q.js} +1 -1
- package/dist/{cli-e31jshz6.js → cli-88arpdke.js} +2 -2
- package/dist/{cli-1fy1pm9d.js → cli-9n9kg58f.js} +1 -1
- package/dist/{cli-k087gj0p.js → cli-pd2cje5b.js} +122 -11
- package/dist/{cli-989eg8jz.js → cli-pnrararp.js} +11 -10
- package/dist/{cli-ttj95aex.js → cli-tgnyvra3.js} +13 -3
- package/dist/{cli-31anr0r9.js → cli-v0evdpdf.js} +68 -28
- package/dist/{cli-s1zt779w.js → cli-x7gcdg6w.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-g4a42tcz.js → doctor-2f4s9dyn.js} +3 -3
- package/dist/engine/compiler/postprocess.d.ts +3 -0
- package/dist/engine/shared/pdf-inspect.d.ts +33 -0
- package/dist/{engine-jvkcahr1.js → engine-c4pxz79g.js} +1 -1
- package/dist/{engine-wgkaqjsc.js → engine-cs5g2ez0.js} +2 -2
- package/dist/{ext-w9d5ftcg.js → ext-70gv86v5.js} +8 -8
- package/dist/{extension-restore-5x4mj79d.js → extension-restore-chj5nx3t.js} +2 -2
- package/dist/{extension-restore-as0g38p1.js → extension-restore-pd87p8r2.js} +4 -4
- package/dist/{gutterpress-agent-d29ry3ak.js → gutterpress-agent-wyryqehx.js} +13 -4
- package/dist/{gutterpress-viewer-ze691rrd.js → gutterpress-viewer-ywkf49q5.js} +38 -153
- package/dist/{index-c6y0p7jy.js → index-0k43evt0.js} +66 -22
- package/dist/{index-fk2kpf2t.js → index-2t1gdma7.js} +121 -10
- package/dist/{index-cw03e9p4.js → index-7j3hkwya.js} +68 -28
- package/dist/{index-a4j3xcfp.js → index-80vg3ed6.js} +13 -3
- package/dist/{index-798jt0qc.js → index-swfdgn2n.js} +2 -2
- package/dist/{index-rj5vrhz6.js → index-ytjkvwy5.js} +1 -1
- package/dist/index.js +6 -6
- package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
- package/dist/lib/source-provider.d.ts +27 -0
- package/dist/lib/version-changes.d.ts +14 -4
- package/dist/{new-jtk028rf.js → new-d61n5cn0.js} +8 -8
- package/dist/{plugins-bcbe7xs8.js → plugins-0hhw6s17.js} +1 -1
- package/dist/{plugins-zsm6wv79.js → plugins-e0n46s6m.js} +3 -3
- package/dist/{preflight-cs6mj1d6.js → preflight-fjayhjr5.js} +8 -8
- package/dist/{preview-d1j1g4qf.js → preview-h815jrfb.js} +8 -8
- package/dist/{publish-7yw4jyrt.js → publish-ft39zgma.js} +8 -8
- package/dist/render.js +12 -2
- package/dist/{source-provider-n7vehh6t.js → source-provider-j1w7byeq.js} +5 -1
- package/dist/{source-provider-tgzet3j5.js → source-provider-tjaf303m.js} +5 -1
- package/dist/test-helpers/vocabulary.d.ts +12 -0
- package/dist/{validate-rkcdnzhw.js → validate-b201dbrb.js} +8 -8
- package/package.json +1 -1
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
validatePageMargin,
|
|
30
30
|
withFetchTimeout,
|
|
31
31
|
writeManifestDoc
|
|
32
|
-
} from "./index-
|
|
32
|
+
} from "./index-ytjkvwy5.js";
|
|
33
33
|
import {
|
|
34
34
|
EXTENSION_MANIFEST_FILENAME,
|
|
35
35
|
GUTTERPRESS_CSS,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
setLogLevel,
|
|
66
66
|
slugify,
|
|
67
67
|
warn
|
|
68
|
-
} from "./index-
|
|
68
|
+
} from "./index-80vg3ed6.js";
|
|
69
69
|
import {
|
|
70
70
|
blackTextToGray
|
|
71
71
|
} from "./index-ht1bcqdd.js";
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
getAssetPath,
|
|
77
77
|
lastPageMode,
|
|
78
78
|
resolvePage
|
|
79
|
-
} from "./index-
|
|
79
|
+
} from "./index-swfdgn2n.js";
|
|
80
80
|
import {
|
|
81
81
|
BuildError,
|
|
82
82
|
cssLength,
|
|
@@ -124,14 +124,16 @@ import {
|
|
|
124
124
|
hasUncommittedChanges,
|
|
125
125
|
isContained,
|
|
126
126
|
listWorkdirChanges,
|
|
127
|
+
nextInHistory,
|
|
127
128
|
readRevisionRefs,
|
|
128
129
|
resolveGitAuthor,
|
|
129
130
|
resolveLogger,
|
|
130
131
|
revisionNameFrom,
|
|
131
132
|
snapshotStagingMarkerPath,
|
|
132
133
|
snapshotWorkingTreeUnlocked,
|
|
134
|
+
startHistoryWalk,
|
|
133
135
|
withRepoLock
|
|
134
|
-
} from "./index-
|
|
136
|
+
} from "./index-7j3hkwya.js";
|
|
135
137
|
import {
|
|
136
138
|
EXTENSIONS_DIR,
|
|
137
139
|
resolveVendoredPluginInstallRoot,
|
|
@@ -5577,7 +5579,7 @@ class PdfOutput {
|
|
|
5577
5579
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
5578
5580
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
5579
5581
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
5580
|
-
const { buildNativePdf } = await import("./engine-
|
|
5582
|
+
const { buildNativePdf } = await import("./engine-cs5g2ez0.js");
|
|
5581
5583
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
5582
5584
|
title: config.title,
|
|
5583
5585
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -7406,7 +7408,7 @@ async function scaffoldProject(options) {
|
|
|
7406
7408
|
let versionHistoryError;
|
|
7407
7409
|
if (requested === "local-git") {
|
|
7408
7410
|
try {
|
|
7409
|
-
const { providerFor } = await import("./source-provider-
|
|
7411
|
+
const { providerFor } = await import("./source-provider-tjaf303m.js");
|
|
7410
7412
|
const provider = providerFor({ type: "local-folder", path: projectDir });
|
|
7411
7413
|
await provider.initVersionHistory({
|
|
7412
7414
|
projectDir,
|
|
@@ -7497,7 +7499,7 @@ styles:
|
|
|
7497
7499
|
let versionHistoryError;
|
|
7498
7500
|
if (requested === "local-git") {
|
|
7499
7501
|
try {
|
|
7500
|
-
const { providerFor } = await import("./source-provider-
|
|
7502
|
+
const { providerFor } = await import("./source-provider-tjaf303m.js");
|
|
7501
7503
|
const provider = providerFor({ type: "local-folder", path: dir });
|
|
7502
7504
|
await provider.initVersionHistory({
|
|
7503
7505
|
projectDir: dir,
|
|
@@ -9265,25 +9267,67 @@ async function describeVersions(projectDir, entries) {
|
|
|
9265
9267
|
}
|
|
9266
9268
|
return out;
|
|
9267
9269
|
}
|
|
9270
|
+
var CLOCK_SKEW_SECONDS = 10 * 60;
|
|
9268
9271
|
async function commitsAhead(dir, fromOid, baseOid, cache2 = {}, limit = 100) {
|
|
9269
9272
|
if (fromOid === baseOid)
|
|
9270
9273
|
return [];
|
|
9271
|
-
const
|
|
9272
|
-
const
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
const
|
|
9276
|
-
|
|
9277
|
-
const
|
|
9278
|
-
|
|
9279
|
-
|
|
9274
|
+
const walk = await startHistoryWalk(dir, cache2, [baseOid, fromOid]);
|
|
9275
|
+
const local = new Set([baseOid]);
|
|
9276
|
+
const online = new Set([fromOid]);
|
|
9277
|
+
const parentsOf = new Map;
|
|
9278
|
+
const listed = [];
|
|
9279
|
+
let shared = false;
|
|
9280
|
+
const mark = (oid) => {
|
|
9281
|
+
const stack = [oid];
|
|
9282
|
+
for (let next = stack.pop();next !== undefined; next = stack.pop()) {
|
|
9283
|
+
if (local.has(next))
|
|
9284
|
+
continue;
|
|
9285
|
+
local.add(next);
|
|
9286
|
+
if (online.has(next))
|
|
9287
|
+
shared = true;
|
|
9288
|
+
stack.push(...parentsOf.get(next) ?? []);
|
|
9289
|
+
}
|
|
9290
|
+
};
|
|
9291
|
+
const firstAhead = () => {
|
|
9292
|
+
const out = [];
|
|
9293
|
+
for (const c of listed) {
|
|
9294
|
+
if (out.length === limit)
|
|
9295
|
+
break;
|
|
9296
|
+
if (!local.has(c.oid))
|
|
9297
|
+
out.push(c);
|
|
9298
|
+
}
|
|
9299
|
+
return out;
|
|
9300
|
+
};
|
|
9301
|
+
const time = (c) => c.commit.committer.timestamp;
|
|
9302
|
+
for (;; ) {
|
|
9303
|
+
const searching = walk.tips.some((c2) => !local.has(c2.oid));
|
|
9304
|
+
if (!searching || shared && listed.length >= limit) {
|
|
9305
|
+
const shown = firstAhead();
|
|
9306
|
+
if (!searching || shown.length === limit) {
|
|
9307
|
+
const oldest = Math.min(...shown.map(time));
|
|
9308
|
+
const newestMarked = walk.tips.findLast((c2) => local.has(c2.oid));
|
|
9309
|
+
if (!newestMarked || time(newestMarked) < oldest - CLOCK_SKEW_SECONDS)
|
|
9310
|
+
break;
|
|
9311
|
+
}
|
|
9312
|
+
}
|
|
9313
|
+
const c = await nextInHistory(dir, walk, cache2, 1);
|
|
9314
|
+
if (!c)
|
|
9280
9315
|
break;
|
|
9281
|
-
|
|
9316
|
+
const parents = walk.shallow.has(c.oid) ? [] : c.commit.parent;
|
|
9317
|
+
parentsOf.set(c.oid, parents);
|
|
9318
|
+
if (local.has(c.oid)) {
|
|
9319
|
+
for (const p of parents)
|
|
9320
|
+
mark(p);
|
|
9282
9321
|
continue;
|
|
9283
|
-
|
|
9284
|
-
|
|
9322
|
+
}
|
|
9323
|
+
listed.push(c);
|
|
9324
|
+
for (const p of parents) {
|
|
9325
|
+
online.add(p);
|
|
9326
|
+
if (local.has(p))
|
|
9327
|
+
shared = true;
|
|
9328
|
+
}
|
|
9285
9329
|
}
|
|
9286
|
-
return
|
|
9330
|
+
return shared ? firstAhead().map(toEntry) : [];
|
|
9287
9331
|
}
|
|
9288
9332
|
async function listOnlineVersions(options) {
|
|
9289
9333
|
const http2 = options.httpClient ?? defaultGitHttp;
|
|
@@ -12761,7 +12805,7 @@ async function resolvePublishProvider(id, book) {
|
|
|
12761
12805
|
const ext = await bookExtensions(book);
|
|
12762
12806
|
const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
|
|
12763
12807
|
if (npmEntry) {
|
|
12764
|
-
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-
|
|
12808
|
+
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-chj5nx3t.js");
|
|
12765
12809
|
await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
|
|
12766
12810
|
}
|
|
12767
12811
|
const publishers = await discover(ext);
|
|
@@ -12799,7 +12843,7 @@ function infoFor(p) {
|
|
|
12799
12843
|
}
|
|
12800
12844
|
function pluginProvider(p) {
|
|
12801
12845
|
let loading;
|
|
12802
|
-
const load = () => loading ??= import("./plugins-
|
|
12846
|
+
const load = () => loading ??= import("./plugins-0hhw6s17.js").then((m) => m.loadPublishFunction(p));
|
|
12803
12847
|
return {
|
|
12804
12848
|
info: infoFor(p),
|
|
12805
12849
|
async authenticate() {
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
stringValueAt,
|
|
20
20
|
toFolioPage,
|
|
21
21
|
wantsRecto
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-swfdgn2n.js";
|
|
23
23
|
import {
|
|
24
24
|
round3
|
|
25
25
|
} from "./index-tayzfr9c.js";
|
|
@@ -312,12 +312,14 @@ function needsMeasurement(value) {
|
|
|
312
312
|
|
|
313
313
|
// src/engine/shared/pdf-inspect.ts
|
|
314
314
|
import {
|
|
315
|
+
decodePDFRawStream,
|
|
315
316
|
PDFArray,
|
|
316
317
|
PDFDict,
|
|
317
318
|
PDFDocument,
|
|
318
319
|
PDFHexString,
|
|
319
320
|
PDFName,
|
|
320
321
|
PDFNumber,
|
|
322
|
+
PDFRawStream,
|
|
321
323
|
PDFRef,
|
|
322
324
|
PDFString
|
|
323
325
|
} from "pdf-lib";
|
|
@@ -438,6 +440,52 @@ async function inspectPdf(bytes) {
|
|
|
438
440
|
walkOutline(outlines);
|
|
439
441
|
return { pageCount: pages.length, boxes, linkTargets, namedDests, outline };
|
|
440
442
|
}
|
|
443
|
+
var PROLOGUE = /^\s*(\d*\.?\d+) 0 0 -\d*\.?\d+ -?\d*\.?\d+ -?\d*\.?\d+ cm/;
|
|
444
|
+
var CLIP = /(-?\d*\.?\d+) (-?\d*\.?\d+) (\d*\.?\d+) (\d*\.?\d+) re\s+W\*? n\b/g;
|
|
445
|
+
var UNIFORM = /\bq\s+(\d*\.?\d+) 0 0 \1 (-?\d*\.?\d+) -?\d*\.?\d+ cm/g;
|
|
446
|
+
var UNSCALED_EPSILON = 0.000001;
|
|
447
|
+
function printScale(doc) {
|
|
448
|
+
const readings = new Map;
|
|
449
|
+
for (const page of doc.getPages()) {
|
|
450
|
+
const contents = page.node.Contents();
|
|
451
|
+
const streams = contents instanceof PDFArray ? contents.asArray().map((ref) => doc.context.lookup(ref)) : [contents];
|
|
452
|
+
let text = "";
|
|
453
|
+
for (const stream of streams) {
|
|
454
|
+
if (!(stream instanceof PDFRawStream))
|
|
455
|
+
continue;
|
|
456
|
+
try {
|
|
457
|
+
text += Buffer.from(decodePDFRawStream(stream).decode()).toString("latin1") + `
|
|
458
|
+
`;
|
|
459
|
+
} catch {}
|
|
460
|
+
}
|
|
461
|
+
const prologue = PROLOGUE.exec(text);
|
|
462
|
+
if (!prologue)
|
|
463
|
+
continue;
|
|
464
|
+
let area;
|
|
465
|
+
for (const m of text.matchAll(CLIP)) {
|
|
466
|
+
const size = Number(m[3]) * Number(m[4]);
|
|
467
|
+
if (!area || size > area.size)
|
|
468
|
+
area = { x: Number(m[1]), size, end: m.index + m[0].length };
|
|
469
|
+
}
|
|
470
|
+
if (!area)
|
|
471
|
+
continue;
|
|
472
|
+
UNIFORM.lastIndex = area.end;
|
|
473
|
+
for (let m;m = UNIFORM.exec(text); ) {
|
|
474
|
+
if (Math.abs(Number(m[2]) - area.x) > 0.5)
|
|
475
|
+
continue;
|
|
476
|
+
const scale = Number(m[1]) * Number(prologue[1]) * 96 / 72;
|
|
477
|
+
readings.set(scale, (readings.get(scale) ?? 0) + 1);
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
if ([...readings.values()].some((n) => n >= 3))
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
let best = null;
|
|
484
|
+
for (const [scale, n] of readings)
|
|
485
|
+
if (best === null || n > readings.get(best))
|
|
486
|
+
best = scale;
|
|
487
|
+
return best === null ? null : Math.abs(1 - best) < UNSCALED_EPSILON ? 1 : best;
|
|
488
|
+
}
|
|
441
489
|
|
|
442
490
|
// src/engine/compiler/tier2.ts
|
|
443
491
|
var DEFAULT_SLUG_PT = 18;
|
|
@@ -584,6 +632,7 @@ function round(n) {
|
|
|
584
632
|
import { PDFDocument as PDFDocument2, PDFName as PDFName2, PDFNumber as PDFNumber2, rgb } from "pdf-lib";
|
|
585
633
|
async function postprocess(input, opts) {
|
|
586
634
|
const doc = await PDFDocument2.load(input, { updateMetadata: false });
|
|
635
|
+
const scale = printScale(doc);
|
|
587
636
|
const g = opts.geometry;
|
|
588
637
|
const inset = g.bleed + g.slug;
|
|
589
638
|
const media = [0, 0, g.media.width, g.media.height];
|
|
@@ -630,7 +679,8 @@ async function postprocess(input, opts) {
|
|
|
630
679
|
bytes,
|
|
631
680
|
pageCount: doc.getPageCount(),
|
|
632
681
|
padded,
|
|
633
|
-
boxes: { media, bleed: bleedBox, trim: trimBox }
|
|
682
|
+
boxes: { media, bleed: bleedBox, trim: trimBox },
|
|
683
|
+
scale
|
|
634
684
|
};
|
|
635
685
|
}
|
|
636
686
|
function drawCropMarks(page, g) {
|
|
@@ -934,8 +984,6 @@ ${pinCss}`);
|
|
|
934
984
|
const msg = `${headline}:
|
|
935
985
|
${describe(widthOffenders.boxes)}`;
|
|
936
986
|
if (opts.allowShrink) {
|
|
937
|
-
if (scale !== null)
|
|
938
|
-
diagnose("engine.width.overflow", `${headline}.`);
|
|
939
987
|
for (const o of widthOffenders.boxes)
|
|
940
988
|
diagnose("engine.width.overflow", `${o.desc} is ${Math.round(o.px)}px wide, past the ${Math.round(widthOffenders.limitPx)}px page content box. ${o.left < -1 ? "Keep it inside the page content box." : "Give it an explicit width that fits."}`);
|
|
941
989
|
log(`WARNING: ${msg}`);
|
|
@@ -951,6 +999,54 @@ ${describe(widthOffenders.intrinsics)}`;
|
|
|
951
999
|
diagnose("engine.width.intrinsic", `${o.desc} has no width set and is naturally wider than the page — if the printed output comes out smaller than your CSS says, give it an explicit width (e.g. width: 100%).`);
|
|
952
1000
|
log(`WARNING: ${msg}`);
|
|
953
1001
|
}
|
|
1002
|
+
let unclipped = null;
|
|
1003
|
+
if (!widthOffenders.boxes.length) {
|
|
1004
|
+
const g = tier2.geometry;
|
|
1005
|
+
const ext = g.bleed + g.slug;
|
|
1006
|
+
const contentPx = (name, pseudos) => {
|
|
1007
|
+
const { width, margin } = resolvePage(model, { name: name || undefined, pseudos }).geometry;
|
|
1008
|
+
return (width + 2 * ext - bleedMargin(margin.left, g) - bleedMargin(margin.right, g)) * 96 / 72;
|
|
1009
|
+
};
|
|
1010
|
+
const pages = await page.evaluate(`(() => {
|
|
1011
|
+
const body = document.body;
|
|
1012
|
+
const named = (el) => { const p = getComputedStyle(el).page; return p && p !== "auto" ? p : ""; };
|
|
1013
|
+
if (!body) return { first: "", used: [], reason: "there is no body" };
|
|
1014
|
+
const bs = getComputedStyle(body);
|
|
1015
|
+
const r = body.getBoundingClientRect();
|
|
1016
|
+
if (
|
|
1017
|
+
Math.abs(r.left + parseFloat(bs.borderLeftWidth)) > 0.01 ||
|
|
1018
|
+
Math.abs(r.right - parseFloat(bs.borderRightWidth) - window.innerWidth) > 0.01
|
|
1019
|
+
) return { first: "", used: [], reason: "the body does not span the page content box" };
|
|
1020
|
+
// The first page's name: the root's, overridden down the chain of
|
|
1021
|
+
// first in-flow children (CSS Paged Media's start page value).
|
|
1022
|
+
let first = named(document.documentElement) || named(body);
|
|
1023
|
+
for (let el = body; el; ) {
|
|
1024
|
+
el = [...el.children].find((c) => {
|
|
1025
|
+
const cs = getComputedStyle(c);
|
|
1026
|
+
return cs.display !== "none" && cs.position !== "absolute" && cs.position !== "fixed";
|
|
1027
|
+
});
|
|
1028
|
+
if (el && named(el)) first = named(el);
|
|
1029
|
+
}
|
|
1030
|
+
const used = new Set([""]);
|
|
1031
|
+
for (const el of document.querySelectorAll("*")) used.add(named(el));
|
|
1032
|
+
return { first, used: [...used], reason: "" };
|
|
1033
|
+
})()`);
|
|
1034
|
+
const firstPx = contentPx(pages.first, ["first", "right", "recto"]);
|
|
1035
|
+
const wider = pages.used.find((name) => pseudoContexts.some((pseudos) => contentPx(name, pseudos) > firstPx + 0.01));
|
|
1036
|
+
unclipped = pages.reason || (wider !== undefined ? `${wider ? `the page "${wider}"` : "the unnamed page"} is wider than the first page` : await page.evaluate(`(() => {
|
|
1037
|
+
const hs = getComputedStyle(document.documentElement);
|
|
1038
|
+
const bs = getComputedStyle(document.body);
|
|
1039
|
+
let css;
|
|
1040
|
+
if (hs.overflowX === "visible" && hs.overflowY === "visible")
|
|
1041
|
+
css = "html { overflow-x: clip !important; } " +
|
|
1042
|
+
"body { overflow-x: clip !important; overflow-y: visible !important; }";
|
|
1043
|
+
else if (bs.overflowX === "visible") css = "body { overflow-x: clip !important; }";
|
|
1044
|
+
else return "the body clips its own overflow";
|
|
1045
|
+
window.__gp.addCss("gp-root-clip", css);
|
|
1046
|
+
return "";
|
|
1047
|
+
})()`)) || null;
|
|
1048
|
+
log(`body overflow ${unclipped ? `left as authored: ${unclipped}` : "held to the page content box"}`);
|
|
1049
|
+
}
|
|
954
1050
|
const rectoDecls = model.breaks.filter(isRectoVersoBreak);
|
|
955
1051
|
const needsMeasure = tier3Reasons.length > 0 || consumedStrings(model).size > 0 || rectoDecls.length > 0 || model.counterResets.length > 0 || furnitureRoots.length > 0 || sideRoots.length > 0;
|
|
956
1052
|
let tier = tier2.geometry.bleed > 0 || tier2.geometry.slug > 0 ? 2 : 1;
|
|
@@ -1472,6 +1568,20 @@ ${mapCss}`;
|
|
|
1472
1568
|
author: opts.author
|
|
1473
1569
|
});
|
|
1474
1570
|
log(`postprocess: ${post.pageCount} pages` + (post.padded ? ` (+${post.padded} blank${opts.lastPage ? `; last page: ${opts.lastPage}` : ""})` : ""));
|
|
1571
|
+
{
|
|
1572
|
+
const scale = post.scale;
|
|
1573
|
+
if (scale !== null && scale < 1) {
|
|
1574
|
+
const pct = (scale * 100).toPrecision(6);
|
|
1575
|
+
const overPx = widthOffenders.defaultLimitPx * (1 / scale - 1);
|
|
1576
|
+
diagnose("engine.width.overflow", `This book printed at ${pct}% of its declared size: content reaches about ` + `${overPx < 0.1 ? overPx.toFixed(3) : overPx.toFixed(2)}px past the ` + `${Math.round(widthOffenders.defaultLimitPx)}px page content box, and Chromium shrinks ` + `the WHOLE print to fit it. The preview is not shrunk, so its lines and page ` + `breaks can differ from the PDF's.` + (unclipped ? ` Gutterpress could not hold it at the page content box: ${unclipped}.` : ""));
|
|
1577
|
+
if (!widthOffenders.boxes.length) {
|
|
1578
|
+
const named = await findWidthOffenders(page, model, 2 * (tier2.geometry.bleed + tier2.geometry.slug), sheetViewport, 0);
|
|
1579
|
+
for (const o of named.boxes)
|
|
1580
|
+
diagnose("engine.width.overflow", `${o.desc} reaches ${Math.max(o.px + Math.min(0, o.left) - (o.limit ?? named.limitPx), -o.left).toFixed(2)}px ` + `past the ${Math.round(o.limit ?? named.limitPx)}px page content box. Keep it ` + `inside the page content box.`);
|
|
1581
|
+
}
|
|
1582
|
+
log(`audit: printed at ${pct}% (shrink-to-fit)`);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1475
1585
|
return {
|
|
1476
1586
|
bytes: post.bytes,
|
|
1477
1587
|
tier,
|
|
@@ -1506,7 +1616,7 @@ function shrinkScale(boxes, limitPx) {
|
|
|
1506
1616
|
return null;
|
|
1507
1617
|
return Math.max(1 / MAX_SHRINK, limitPx / maxRight);
|
|
1508
1618
|
}
|
|
1509
|
-
async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreViewport) {
|
|
1619
|
+
async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreViewport, tolerancePx = 1) {
|
|
1510
1620
|
const contexts = [
|
|
1511
1621
|
resolvePage(model),
|
|
1512
1622
|
...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--pin-")).map((n) => resolvePage(model, { name: n }))
|
|
@@ -1532,7 +1642,8 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
|
|
|
1532
1642
|
mobile: false
|
|
1533
1643
|
});
|
|
1534
1644
|
boxes.push(...JSON.parse(await page.evaluate(`(() => {
|
|
1535
|
-
const
|
|
1645
|
+
const TOL = ${tolerancePx};
|
|
1646
|
+
const LIMIT = Math.max(${widthPx} + TOL, ${Math.ceil(widthPx)});
|
|
1536
1647
|
const NAMED = ${JSON.stringify(namedLimits)};
|
|
1537
1648
|
const DEFAULT_LIMIT = ${defaultLimitPx};
|
|
1538
1649
|
// The page an element lands on: the nearest ancestor with a non-auto
|
|
@@ -1572,10 +1683,10 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
|
|
|
1572
1683
|
// pulls) AND left-edge protrusion (negative left with an ordinary
|
|
1573
1684
|
// width) — both trigger the same whole-document shrink-to-fit,
|
|
1574
1685
|
// measured: a left bleed alone cost 16%.
|
|
1575
|
-
if (right <= LIMIT && r.width <= LIMIT && r.left >= -
|
|
1686
|
+
if (right <= LIMIT && r.width <= LIMIT && r.left >= -TOL) continue;
|
|
1576
1687
|
// ...but only where it actually escapes its clipping ancestors.
|
|
1577
1688
|
const clip = clipEdges(el).edges;
|
|
1578
|
-
if (Math.min(right, clip.right) <= LIMIT && Math.max(r.left, clip.left) >= -
|
|
1689
|
+
if (Math.min(right, clip.right) <= LIMIT && Math.max(r.left, clip.left) >= -TOL) continue;
|
|
1579
1690
|
let deepest = true;
|
|
1580
1691
|
for (const c of el.children) {
|
|
1581
1692
|
if (c.getBoundingClientRect().width >= r.width - 1) { deepest = false; break; }
|
|
@@ -1612,7 +1723,7 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
|
|
|
1612
1723
|
const over = el.scrollWidth - el.clientWidth;
|
|
1613
1724
|
// clientWidth is 0 on inline/replaced boxes, where scrollWidth
|
|
1614
1725
|
// carries no overflow information -- skip rather than guess.
|
|
1615
|
-
if (el.clientWidth <= 0 || over <=
|
|
1726
|
+
if (el.clientWidth <= 0 || over <= TOL) continue;
|
|
1616
1727
|
// A descendant assigned to a DIFFERENT page is not overflowing this
|
|
1617
1728
|
// element's page -- it is laid out against its own, wider one. The
|
|
1618
1729
|
// full-bleed art plate is the standard case: it is legitimately
|
|
@@ -1666,7 +1777,7 @@ async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreView
|
|
|
1666
1777
|
}
|
|
1667
1778
|
return JSON.stringify(out);
|
|
1668
1779
|
})()`));
|
|
1669
|
-
return { limitPx, boxes, intrinsics: replaced };
|
|
1780
|
+
return { limitPx, defaultLimitPx, boxes, intrinsics: replaced };
|
|
1670
1781
|
} finally {
|
|
1671
1782
|
await page.send("Emulation.setDeviceMetricsOverride", restoreViewport);
|
|
1672
1783
|
}
|
|
@@ -423,6 +423,40 @@ class LocalFolderSourceProvider {
|
|
|
423
423
|
return Promise.reject(new Error(NO_VERSION_HISTORY));
|
|
424
424
|
}
|
|
425
425
|
}
|
|
426
|
+
var lastHistoryWalk = null;
|
|
427
|
+
async function startHistoryWalk(dir, cache, heads) {
|
|
428
|
+
const shallow = await gitFs.promises.readFile(path2.join(gitDirFor(dir), "shallow"), "utf8").catch(() => "");
|
|
429
|
+
const tips = await Promise.all(heads.map((oid) => git.readCommit({ fs: gitFs, dir, cache, oid })));
|
|
430
|
+
tips.sort((a, b) => a.commit.committer.timestamp - b.commit.committer.timestamp);
|
|
431
|
+
return {
|
|
432
|
+
tips,
|
|
433
|
+
queued: new Set(heads),
|
|
434
|
+
shallow: new Set(shallow.split(`
|
|
435
|
+
`)),
|
|
436
|
+
readAhead: new Map
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
async function nextInHistory(dir, walk, cache, needed) {
|
|
440
|
+
const commit = walk.tips.pop();
|
|
441
|
+
if (!commit || walk.shallow.has(commit.oid))
|
|
442
|
+
return commit;
|
|
443
|
+
for (const oid of commit.commit.parent) {
|
|
444
|
+
if (walk.queued.has(oid))
|
|
445
|
+
continue;
|
|
446
|
+
const oneLine = walk.tips.length === 0 && commit.commit.parent.length === 1;
|
|
447
|
+
if (needed > 1 && oneLine && !walk.readAhead.has(oid)) {
|
|
448
|
+
for (const c of await git.log({ fs: gitFs, dir, cache, ref: oid, depth: needed })) {
|
|
449
|
+
if (!walk.queued.has(c.oid))
|
|
450
|
+
walk.readAhead.set(c.oid, c);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
walk.queued.add(oid);
|
|
454
|
+
walk.tips.push(walk.readAhead.get(oid) ?? await git.readCommit({ fs: gitFs, dir, cache, oid }));
|
|
455
|
+
walk.readAhead.delete(oid);
|
|
456
|
+
}
|
|
457
|
+
walk.tips.sort((a, b) => a.commit.committer.timestamp - b.commit.committer.timestamp);
|
|
458
|
+
return commit;
|
|
459
|
+
}
|
|
426
460
|
|
|
427
461
|
class LocalGitSourceProvider {
|
|
428
462
|
source;
|
|
@@ -460,40 +494,46 @@ class LocalGitSourceProvider {
|
|
|
460
494
|
const dir = this.dir;
|
|
461
495
|
const limit = Math.min(500, Math.max(1, options.limit ?? HISTORY_PAGE_LIMIT));
|
|
462
496
|
const before = options.before;
|
|
463
|
-
|
|
497
|
+
const cache = {};
|
|
464
498
|
try {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
}
|
|
499
|
+
const head = await git.resolveRef({ fs: gitFs, dir, ref: "HEAD" });
|
|
500
|
+
let walk;
|
|
501
|
+
const saved = lastHistoryWalk;
|
|
502
|
+
if (before && saved?.dir === dir && saved.head === head && saved.last === before) {
|
|
503
|
+
walk = saved.walk;
|
|
504
|
+
lastHistoryWalk = null;
|
|
505
|
+
} else {
|
|
506
|
+
walk = await startHistoryWalk(dir, cache, [head]);
|
|
507
|
+
if (before) {
|
|
508
|
+
let c;
|
|
509
|
+
do {
|
|
510
|
+
c = await nextInHistory(dir, walk, cache, limit);
|
|
511
|
+
} while (c && c.oid !== before);
|
|
512
|
+
if (!c)
|
|
513
|
+
return { entries: [], hasMore: false };
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
const entries = [];
|
|
517
|
+
while (entries.length < limit) {
|
|
518
|
+
const c = await nextInHistory(dir, walk, cache, limit - entries.length);
|
|
519
|
+
if (!c)
|
|
520
|
+
break;
|
|
521
|
+
entries.push({
|
|
522
|
+
id: c.oid,
|
|
523
|
+
message: c.commit.message.trim(),
|
|
524
|
+
timestamp: c.commit.author.timestamp * 1000,
|
|
525
|
+
author: c.commit.author.name
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
const hasMore = walk.tips.length > 0;
|
|
529
|
+
lastHistoryWalk = hasMore ? { dir, head, last: entries.at(-1).id, walk } : null;
|
|
530
|
+
return { entries, hasMore };
|
|
472
531
|
} catch (e) {
|
|
473
532
|
if (before && e?.code === "NotFoundError") {
|
|
474
533
|
return { entries: [], hasMore: false };
|
|
475
534
|
}
|
|
476
535
|
throw e;
|
|
477
536
|
}
|
|
478
|
-
const seen = new Set;
|
|
479
|
-
let filtered = commits.filter((c) => {
|
|
480
|
-
if (c.oid === before || seen.has(c.oid))
|
|
481
|
-
return false;
|
|
482
|
-
seen.add(c.oid);
|
|
483
|
-
return true;
|
|
484
|
-
});
|
|
485
|
-
const hasMore = filtered.length > limit;
|
|
486
|
-
if (hasMore)
|
|
487
|
-
filtered = filtered.slice(0, limit);
|
|
488
|
-
return {
|
|
489
|
-
entries: filtered.map((c) => ({
|
|
490
|
-
id: c.oid,
|
|
491
|
-
message: c.commit.message.trim(),
|
|
492
|
-
timestamp: c.commit.author.timestamp * 1000,
|
|
493
|
-
author: c.commit.author.name
|
|
494
|
-
})),
|
|
495
|
-
hasMore
|
|
496
|
-
};
|
|
497
537
|
}
|
|
498
538
|
restore(options) {
|
|
499
539
|
return withRepoLock(this.dir, () => this.restoreUnlocked(options));
|
|
@@ -793,4 +833,4 @@ async function switchBranch(options) {
|
|
|
793
833
|
});
|
|
794
834
|
}
|
|
795
835
|
|
|
796
|
-
export { gitFs, errorLogData, resolveLogger, gitScopeFor, HISTORY_PAGE_LIMIT, NO_VERSION_HISTORY, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, readRevisionRefs, isContained, listRevisions, revisionNameFrom, assertFreeRevisionName, createRevision, switchBranch };
|
|
836
|
+
export { gitFs, errorLogData, resolveLogger, gitScopeFor, HISTORY_PAGE_LIMIT, NO_VERSION_HISTORY, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, startHistoryWalk, nextInHistory, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, readRevisionRefs, isContained, listRevisions, revisionNameFrom, assertFreeRevisionName, createRevision, switchBranch };
|
|
@@ -398,7 +398,7 @@ import { satisfies, validRange } from "semver";
|
|
|
398
398
|
// package.json
|
|
399
399
|
var package_default = {
|
|
400
400
|
name: "gutterpress",
|
|
401
|
-
version: "0.11.23-beta.
|
|
401
|
+
version: "0.11.23-beta.2",
|
|
402
402
|
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
403
403
|
author: "itlackey",
|
|
404
404
|
license: "MPL-2.0",
|
|
@@ -2122,8 +2122,9 @@ img.gp-shape {
|
|
|
2122
2122
|
|
|
2123
2123
|
/* Math (the bundled gutterpress-math feature, math.ts): MathJax's own rules
|
|
2124
2124
|
for the <mjx-container> SVG output it emits, from its SVG output jax's
|
|
2125
|
-
stylesheet, less the ones for its interactive menu and tooltips
|
|
2126
|
-
|
|
2125
|
+
stylesheet, less the ones for its interactive menu and tooltips, plus one
|
|
2126
|
+
bound of ours on the hidden MathML copy (#469, below). Inert in a book
|
|
2127
|
+
without formulas. */
|
|
2127
2128
|
mjx-container[jax="SVG"] { direction: ltr; }
|
|
2128
2129
|
mjx-container[jax="SVG"] > svg { overflow: visible; min-height: 1px; min-width: 1px; }
|
|
2129
2130
|
mjx-container[jax="SVG"] > svg a { fill: blue; stroke: blue; }
|
|
@@ -2140,6 +2141,15 @@ mjx-assistive-mml {
|
|
|
2140
2141
|
border: 0px !important;
|
|
2141
2142
|
display: block !important;
|
|
2142
2143
|
width: auto !important;
|
|
2144
|
+
/* Ours (#469). The browser lays the copy out in whatever math font it has,
|
|
2145
|
+
so it can be wider than the formula's SVG; ending a line, it crossed the
|
|
2146
|
+
column edge and Chromium shrank the whole print to fit. MathJax makes the
|
|
2147
|
+
container position: relative with the copy at its top left, so 100% is
|
|
2148
|
+
the formula's width. Clip and overflow still hide the copy and its MathML
|
|
2149
|
+
still reaches screen readers; only its box changes. Not the 1px
|
|
2150
|
+
visually-hidden box MathJax 2 used: its docs note VoiceOver on iOS could
|
|
2151
|
+
not reach a formula by touch in it. */
|
|
2152
|
+
max-width: 100% !important;
|
|
2143
2153
|
overflow: hidden !important;
|
|
2144
2154
|
user-select: none;
|
|
2145
2155
|
}
|
|
@@ -712,10 +712,10 @@ var preview_shell_default = "./preview-shell-wk9k3gcd.js";
|
|
|
712
712
|
var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
|
|
713
713
|
|
|
714
714
|
// src/assets/engine/gutterpress-viewer.js
|
|
715
|
-
var gutterpress_viewer_default = "./gutterpress-viewer-
|
|
715
|
+
var gutterpress_viewer_default = "./gutterpress-viewer-ywkf49q5.js";
|
|
716
716
|
|
|
717
717
|
// src/assets/engine/gutterpress-agent.js
|
|
718
|
-
var gutterpress_agent_default = "./gutterpress-agent-
|
|
718
|
+
var gutterpress_agent_default = "./gutterpress-agent-wyryqehx.js";
|
|
719
719
|
|
|
720
720
|
// src/assets/templates/book/manifest.yaml
|
|
721
721
|
var manifest_default = "./manifest-mffah3hr.yaml";
|
package/dist/index.js
CHANGED
|
@@ -122,7 +122,7 @@ import {
|
|
|
122
122
|
substituteVariables,
|
|
123
123
|
syncProject,
|
|
124
124
|
testRemoteAccess
|
|
125
|
-
} from "./index-
|
|
125
|
+
} from "./index-0k43evt0.js";
|
|
126
126
|
import {
|
|
127
127
|
DEFAULT_NPM_REGISTRY,
|
|
128
128
|
MANIFEST_FILENAMES,
|
|
@@ -152,7 +152,7 @@ import {
|
|
|
152
152
|
setExtensionEnabled,
|
|
153
153
|
updateExtensions,
|
|
154
154
|
validateProjectExtensions
|
|
155
|
-
} from "./index-
|
|
155
|
+
} from "./index-ytjkvwy5.js";
|
|
156
156
|
import {
|
|
157
157
|
BUNDLED_EXTENSIONS,
|
|
158
158
|
EXTENSION_MANIFEST_FILENAME,
|
|
@@ -169,12 +169,12 @@ import {
|
|
|
169
169
|
pathEscapesFolder,
|
|
170
170
|
readExtensionMeta,
|
|
171
171
|
resolveExtension
|
|
172
|
-
} from "./index-
|
|
172
|
+
} from "./index-80vg3ed6.js";
|
|
173
173
|
import"./index-ht1bcqdd.js";
|
|
174
174
|
import {
|
|
175
175
|
BUILD_DIAGNOSTIC_CODES
|
|
176
|
-
} from "./index-
|
|
177
|
-
import"./index-
|
|
176
|
+
} from "./index-2t1gdma7.js";
|
|
177
|
+
import"./index-swfdgn2n.js";
|
|
178
178
|
import {
|
|
179
179
|
BuildError
|
|
180
180
|
} from "./index-tayzfr9c.js";
|
|
@@ -199,7 +199,7 @@ import {
|
|
|
199
199
|
revisionNameFrom,
|
|
200
200
|
switchBranch,
|
|
201
201
|
whenGitIdle
|
|
202
|
-
} from "./index-
|
|
202
|
+
} from "./index-7j3hkwya.js";
|
|
203
203
|
import {
|
|
204
204
|
EXTENSIONS_DIR
|
|
205
205
|
} from "./index-5x42amh8.js";
|