gutterpress 0.11.23-beta.1 → 0.11.23-beta.3
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 +13 -3
- package/dist/api/index.d.ts +5 -5
- package/dist/api/index.js +19 -7
- package/dist/{build-dg8a566j.js → build-fq3mexhy.js} +9 -9
- package/dist/checks/asset/approved-fonts.d.ts +8 -0
- package/dist/checks/asset/extensions.d.ts +1 -1
- package/dist/checks/asset/index.d.ts +1 -0
- package/dist/{cli-e31jshz6.js → cli-5zbdb6mt.js} +296 -65
- package/dist/{cli-ttj95aex.js → cli-7mt0dftw.js} +47 -18
- package/dist/{cli-989eg8jz.js → cli-ah93yyzb.js} +163 -55
- package/dist/{cli-31anr0r9.js → cli-eymdsefg.js} +69 -29
- package/dist/{cli-1fy1pm9d.js → cli-fh685nqs.js} +1 -1
- package/dist/{cli-k087gj0p.js → cli-fsjre61x.js} +123 -12
- package/dist/{cli-s1zt779w.js → cli-q7t04gjt.js} +1 -1
- package/dist/{cli-vhav8g82.js → cli-rybz2dfs.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-g4a42tcz.js → doctor-tg9ht1n3.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-17v87vq5.js} +1 -1
- package/dist/{engine-wgkaqjsc.js → engine-y9fnarfa.js} +2 -2
- package/dist/{ext-w9d5ftcg.js → ext-esz03jz4.js} +27 -10
- package/dist/{extension-restore-5x4mj79d.js → extension-restore-91gy1e28.js} +3 -3
- package/dist/{extension-restore-as0g38p1.js → extension-restore-q70wqah5.js} +5 -5
- 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-a4j3xcfp.js → index-67g8f7r4.js} +47 -18
- package/dist/{index-798jt0qc.js → index-d9w3r89w.js} +3 -3
- package/dist/{index-rj5vrhz6.js → index-fntpr44x.js} +321 -66
- package/dist/{index-5x42amh8.js → index-g3te5ey1.js} +2 -1
- package/dist/{index-cw03e9p4.js → index-kw4tbthz.js} +69 -29
- package/dist/{index-fk2kpf2t.js → index-santcs4q.js} +121 -10
- package/dist/{index-c6y0p7jy.js → index-z6vzj3s5.js} +243 -73
- package/dist/index.js +35 -8
- package/dist/lib/check-options.d.ts +70 -0
- package/dist/lib/extension-manager.d.ts +16 -1
- package/dist/lib/extension-scaffold.d.ts +15 -2
- package/dist/lib/extension-specifier.d.ts +8 -1
- package/dist/lib/manifest-config.d.ts +3 -1
- package/dist/lib/manifest-old-spellings.d.ts +32 -9
- package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
- package/dist/lib/markdown/math.d.ts +1 -1
- package/dist/lib/markdown/typography.d.ts +1 -0
- package/dist/lib/page-size.d.ts +12 -4
- package/dist/lib/plugin-vendor.d.ts +6 -0
- package/dist/lib/presets.d.ts +2 -2
- package/dist/lib/root-tokens.d.ts +2 -1
- package/dist/lib/source-provider.d.ts +27 -0
- package/dist/lib/style-resolver.d.ts +2 -1
- package/dist/lib/version-changes.d.ts +22 -6
- package/dist/{manifest.schema-0jgj0jt1.json → manifest.schema-5cm13vr3.json} +215 -5
- package/dist/{new-jtk028rf.js → new-rmfyb7va.js} +22 -15
- package/dist/{plugins-bcbe7xs8.js → plugins-gs21xz5s.js} +2 -2
- package/dist/{plugins-zsm6wv79.js → plugins-tqv1s16f.js} +4 -4
- package/dist/{preflight-cs6mj1d6.js → preflight-bjyeeq0d.js} +9 -9
- package/dist/{preview-d1j1g4qf.js → preview-ke03fk5d.js} +9 -9
- package/dist/{publish-7yw4jyrt.js → publish-wpnz0qng.js} +9 -9
- package/dist/render.js +55 -13
- package/dist/schema/manifest.types.d.ts +45 -7
- package/dist/{source-provider-n7vehh6t.js → source-provider-3g3yrn1f.js} +6 -2
- package/dist/{source-provider-tgzet3j5.js → source-provider-azg9ywhb.js} +6 -2
- package/dist/test-helpers/vocabulary.d.ts +12 -0
- package/dist/{validate-rkcdnzhw.js → validate-zcwykb43.js} +9 -9
- package/package.json +1 -1
- /package/dist/{cli-y28j019d.js → cli-1dha1nxk.js} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
EXTENSIONS_DIR,
|
|
3
3
|
LEGACY_PLUGINS_DIR,
|
|
4
4
|
VENDORED_NPM_DIR
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-g3te5ey1.js";
|
|
6
6
|
import {
|
|
7
7
|
capabilitiesFor,
|
|
8
8
|
detectProjectSource,
|
|
@@ -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 };
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
stringValueAt,
|
|
20
20
|
toFolioPage,
|
|
21
21
|
wantsRecto
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-d9w3r89w.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
|
}
|