gutterpress 0.11.20-alpha.4 → 0.11.20-beta.1
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/dist/api/index.js +2 -2
- package/dist/{build-epdcrm2c.js → build-3bv5hgez.js} +4 -4
- package/dist/{cli-0ey902sx.js → cli-4d25xvs2.js} +45 -32
- package/dist/{cli-61vd4ews.js → cli-cyej3p9v.js} +4 -4
- package/dist/{cli-fmksazej.js → cli-gxqxn3sf.js} +1 -1
- package/dist/{cli-h4tfmpg3.js → cli-tsdrvrff.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-78es5scm.js → doctor-x9vjqhfk.js} +2 -2
- package/dist/engine/shared/pin-edges.d.ts +5 -5
- package/dist/engine/shared/print-area.d.ts +12 -7
- package/dist/{engine-67f68bxs.js → engine-4rkhv5ga.js} +1 -1
- package/dist/{engine-7ha27n2b.js → engine-5fw55dfb.js} +2 -2
- package/dist/{ext-9mc7sr0d.js → ext-9wafdrps.js} +4 -4
- package/dist/{gutterpress-agent-mrdnwktc.js → gutterpress-agent-yvd8w8my.js} +1 -0
- package/dist/{gutterpress-viewer-jr30yw8t.js → gutterpress-viewer-w7njnkj7.js} +115 -20
- package/dist/{index-gm5xbx5w.js → index-crys9951.js} +3 -3
- package/dist/{index-t13p8y08.js → index-pjw7trb8.js} +63 -39
- package/dist/{index-ad95fws8.js → index-yw16cfm8.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/lib/markdown/assemble.d.ts +1 -1
- package/dist/lib/markdown/gutterpress-css.d.ts +8 -8
- package/dist/lib/page-size.d.ts +5 -3
- package/dist/{manifest.schema-13dfax80.json → manifest.schema-c4wfpg6g.json} +8 -2
- package/dist/{new-s4f0tnya.js → new-zwfmqf9t.js} +4 -4
- package/dist/{preflight-7ck4rbsq.js → preflight-pfhbrhdb.js} +4 -4
- package/dist/preview/file-watcher.d.ts +1 -0
- package/dist/{preview-j91sxadd.js → preview-6bc098rf.js} +4 -4
- package/dist/{publish-f12xaenm.js → publish-pev62kc6.js} +4 -4
- package/dist/render.js +22 -13
- package/dist/schema/manifest.types.d.ts +20 -6
- package/dist/{validate-pb5gysvr.js → validate-x00gjxgb.js} +4 -4
- package/package.json +1 -1
|
@@ -119,7 +119,38 @@
|
|
|
119
119
|
);
|
|
120
120
|
position: relative;
|
|
121
121
|
width: var(--gp-content-w);
|
|
122
|
-
|
|
122
|
+
/* Exactly one column tall, but DEFINITE only where print's flow root is.
|
|
123
|
+
A page root's percentage height (\`.page { height: 100% }\`) resolves
|
|
124
|
+
against its containing block. In print that is the flow root (\`body\` or
|
|
125
|
+
\`main\`), whose height is auto in an ordinary book, so the percentage
|
|
126
|
+
computes to \`auto\` and MARKER_CSS's min-height cushion sizes the root.
|
|
127
|
+
Here the strip stands in as that containing block, and a plain
|
|
128
|
+
\`height: var(--gp-content-h)\` resolved the percentage to the full column:
|
|
129
|
+
the root ended exactly on the column's edge, and the same percentage
|
|
130
|
+
reached everything else the author's rule matched (\`[data-name="x"]\`
|
|
131
|
+
selects a block AND its heading, so the heading filled the root and the
|
|
132
|
+
paragraph after it spilled into the next column). Mid-run the next root's
|
|
133
|
+
forced break absorbed the spill; a run's LAST root left a blank column —
|
|
134
|
+
a preview page the PDF does not have. Measured on
|
|
135
|
+
examples/with-print-effects with \`height: 100%\` on its page blocks: print
|
|
136
|
+
5pp, viewer 8pp (a pin root is a run of its own, so three runs ended on
|
|
137
|
+
such a root).
|
|
138
|
+
|
|
139
|
+
\`height: 100%\` asks the strip's own containing block the question the
|
|
140
|
+
root asks print's: is the flow root's height definite? Auto there (the
|
|
141
|
+
ordinary book) is auto here, and the root's percentage is auto exactly
|
|
142
|
+
as in print. A definite flow root — \`html, body { height: 100% }\`, where
|
|
143
|
+
print's percentage DOES resolve to the page area — is definite here too
|
|
144
|
+
(measured, the same 5-root book: 6pp in both renderers). Either way the
|
|
145
|
+
min/max pair pins the used height, so the column height, to the content
|
|
146
|
+
height: \`clientHeight\` is still one column.
|
|
147
|
+
|
|
148
|
+
\`decorate.ts\`'s \`.gp-run\` wrapper sizes itself with \`min-height\` for the
|
|
149
|
+
same reason — a definite wrapper would resolve the percentage after the
|
|
150
|
+
run was measured and re-fragment it under its sheets. */
|
|
151
|
+
height: 100%;
|
|
152
|
+
min-height: var(--gp-content-h);
|
|
153
|
+
max-height: var(--gp-content-h);
|
|
123
154
|
column-width: var(--gp-content-w);
|
|
124
155
|
column-gap: var(--gp-col-gap);
|
|
125
156
|
column-fill: auto;
|
|
@@ -1055,7 +1086,7 @@
|
|
|
1055
1086
|
}
|
|
1056
1087
|
function pinInsets(area, side, edges) {
|
|
1057
1088
|
const binding = side === "recto" ? "left" : "right";
|
|
1058
|
-
const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.
|
|
1089
|
+
const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.gutter : area.bleed + area.artSafe;
|
|
1059
1090
|
return { top: inset("top"), right: inset("right"), bottom: inset("bottom"), left: inset("left") };
|
|
1060
1091
|
}
|
|
1061
1092
|
var NO_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
@@ -1097,6 +1128,7 @@
|
|
|
1097
1128
|
bleed: n(v.bleed),
|
|
1098
1129
|
safe,
|
|
1099
1130
|
artSafe: typeof v.artSafe === "number" ? n(v.artSafe) : safe,
|
|
1131
|
+
gutter: typeof v.gutter === "number" ? n(v.gutter) : safe,
|
|
1100
1132
|
preset: typeof v.preset === "string" ? v.preset : undefined,
|
|
1101
1133
|
spec
|
|
1102
1134
|
};
|
|
@@ -1213,7 +1245,7 @@
|
|
|
1213
1245
|
continue;
|
|
1214
1246
|
const stripTop = strip.getBoundingClientRect().top;
|
|
1215
1247
|
const edge = prop === "break-after" ? rect.bottom : rect.top;
|
|
1216
|
-
if (columnReserve((edge - stripTop) / cssZoomOf(strip), strip.
|
|
1248
|
+
if (columnReserve((edge - stripTop) / cssZoomOf(strip), stripMetrics(strip).height) === null)
|
|
1217
1249
|
continue;
|
|
1218
1250
|
const spacer = document.createElement("div");
|
|
1219
1251
|
spacer.className = "gp-column-break-spacer";
|
|
@@ -1597,12 +1629,11 @@
|
|
|
1597
1629
|
let previous = "";
|
|
1598
1630
|
for (let pass = 0;pass < maxPasses; pass++) {
|
|
1599
1631
|
passes = Math.max(passes, pass + 1);
|
|
1600
|
-
const stride =
|
|
1632
|
+
const { stride, height: colBottom } = stripMetrics(strip.el);
|
|
1601
1633
|
const stripLeft = strip.el.getBoundingClientRect().left - strip.el.scrollLeft;
|
|
1602
1634
|
const zoom = cssZoomOf(strip.el);
|
|
1603
1635
|
const colOf = (r) => Math.floor(((r.left - stripLeft) / zoom + 1) / stride);
|
|
1604
1636
|
const stripTop = strip.el.getBoundingClientRect().top;
|
|
1605
|
-
const colBottom = strip.el.clientHeight;
|
|
1606
1637
|
const plans = [];
|
|
1607
1638
|
for (const table of tables) {
|
|
1608
1639
|
const head = repeatingHead(table);
|
|
@@ -1773,7 +1804,7 @@
|
|
|
1773
1804
|
const colGap = parseFloat(cs.columnGap) || 0;
|
|
1774
1805
|
const h = parseFloat(cs.getPropertyValue("--gp-content-h"));
|
|
1775
1806
|
const rowGap = parseFloat(cs.rowGap) || 0;
|
|
1776
|
-
return { stride: w + colGap, rowStride: h + rowGap };
|
|
1807
|
+
return { stride: w + colGap, rowStride: h + rowGap, height: h };
|
|
1777
1808
|
}
|
|
1778
1809
|
function rowStrideOf(strip) {
|
|
1779
1810
|
return stripMetrics(strip).rowStride;
|
|
@@ -2225,16 +2256,23 @@
|
|
|
2225
2256
|
const b = Math.max(0, area.bleed) * scale;
|
|
2226
2257
|
const s = Math.max(0, area.safe) * scale;
|
|
2227
2258
|
const a = Math.max(0, area.artSafe) * scale;
|
|
2228
|
-
const
|
|
2259
|
+
const g = Math.max(0, area.gutter) * scale;
|
|
2260
|
+
const [textLeft, textRight] = side === "verso" ? [s, g] : [g, s];
|
|
2261
|
+
const [artLeft, artRight] = side === "verso" ? [a, g] : [g, a];
|
|
2229
2262
|
const trim = { x: side === "verso" ? b : 0, y: b, w: Math.max(0, w - b), h: Math.max(0, h - 2 * b) };
|
|
2230
2263
|
return {
|
|
2231
2264
|
sheet: { x: 0, y: 0, w, h },
|
|
2232
2265
|
trim,
|
|
2233
|
-
safe: {
|
|
2266
|
+
safe: {
|
|
2267
|
+
x: trim.x + textLeft,
|
|
2268
|
+
y: trim.y + s,
|
|
2269
|
+
w: Math.max(0, trim.w - textLeft - textRight),
|
|
2270
|
+
h: Math.max(0, trim.h - 2 * s)
|
|
2271
|
+
},
|
|
2234
2272
|
safeArt: {
|
|
2235
|
-
x: trim.x +
|
|
2273
|
+
x: trim.x + artLeft,
|
|
2236
2274
|
y: trim.y + a,
|
|
2237
|
-
w: Math.max(0, trim.w -
|
|
2275
|
+
w: Math.max(0, trim.w - artLeft - artRight),
|
|
2238
2276
|
h: Math.max(0, trim.h - 2 * a)
|
|
2239
2277
|
},
|
|
2240
2278
|
bleed: b
|
|
@@ -2299,7 +2337,7 @@
|
|
|
2299
2337
|
};
|
|
2300
2338
|
function sheetArea(sheet) {
|
|
2301
2339
|
const px = (name) => parseFloat(sheet.style.getPropertyValue(name)) || 0;
|
|
2302
|
-
return { width: px("--gp-page-w") / PX_PER_PT, height: px("--gp-page-h") / PX_PER_PT, bleed: 0, safe: 0, artSafe: 0 };
|
|
2340
|
+
return { width: px("--gp-page-w") / PX_PER_PT, height: px("--gp-page-h") / PX_PER_PT, bleed: 0, safe: 0, artSafe: 0, gutter: 0 };
|
|
2303
2341
|
}
|
|
2304
2342
|
var OVERLAY_CSS = `
|
|
2305
2343
|
.root {
|
|
@@ -2311,12 +2349,12 @@
|
|
|
2311
2349
|
--gp-ov-bleed-color: #e5484d; /* bleed layer: the band, and (darker) the trim line */
|
|
2312
2350
|
--gp-ov-bleed-alpha: 0.45; /* opacity of the bleed band */
|
|
2313
2351
|
--gp-ov-trim-color: color-mix(in srgb, var(--gp-ov-bleed-color) 60%, #000); /* darker than the band so it reads as an edge */
|
|
2314
|
-
--gp-ov-art-color: #
|
|
2352
|
+
--gp-ov-art-color: #a855f7; /* art layer: the art line (dotted, a second cue) */
|
|
2315
2353
|
--gp-ov-margins-color: #1a9c6b; /* margins layer: the page's own content box */
|
|
2316
2354
|
--gp-ov-flag-width: 2px; /* overflow flag outline */
|
|
2317
2355
|
--gp-ov-warn: #f59e0b; /* leaves the safe area */
|
|
2318
2356
|
--gp-ov-error: #e5484d; /* crosses the trim / leaves the sheet */
|
|
2319
|
-
--gp-ov-intent: #
|
|
2357
|
+
--gp-ov-intent: #ec4899; /* placed on purpose (pink: apart from the purple art line) */
|
|
2320
2358
|
/* The overlay is scaled with the stage, so a 2px line would shrink with the
|
|
2321
2359
|
zoom; dividing by it keeps lines the same width on screen at every zoom. */
|
|
2322
2360
|
--gp-ov-w: calc(var(--gp-ov-width) / var(--gp-ov-z, 1));
|
|
@@ -2386,7 +2424,7 @@
|
|
|
2386
2424
|
.gp-ov-flag[data-kind="intended"] {
|
|
2387
2425
|
outline: var(--gp-ov-flag-w) dotted var(--gp-ov-intent);
|
|
2388
2426
|
}
|
|
2389
|
-
/* the legend: small, fixed in a corner of the viewport, and the one part that takes the pointer (its link) */
|
|
2427
|
+
/* the legend: small, fixed in a corner of the viewport, and the one part that takes the pointer (its link and its fold button) */
|
|
2390
2428
|
.gp-ov-legend {
|
|
2391
2429
|
position: fixed;
|
|
2392
2430
|
right: 12px;
|
|
@@ -2401,8 +2439,33 @@
|
|
|
2401
2439
|
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
|
|
2402
2440
|
pointer-events: auto;
|
|
2403
2441
|
}
|
|
2404
|
-
.gp-ov-
|
|
2442
|
+
.gp-ov-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
2443
|
+
.gp-ov-body { margin-top: 6px; }
|
|
2444
|
+
.gp-ov-body > div + div { margin-top: 3px; }
|
|
2405
2445
|
.gp-ov-legend a { color: #9cc2ff; }
|
|
2446
|
+
/* the fold button: a chevron made of two borders, down while the legend is open, up once it is folded to its header */
|
|
2447
|
+
.gp-ov-toggle {
|
|
2448
|
+
flex: none;
|
|
2449
|
+
display: grid;
|
|
2450
|
+
place-items: center;
|
|
2451
|
+
width: 18px;
|
|
2452
|
+
height: 18px;
|
|
2453
|
+
padding: 0;
|
|
2454
|
+
border: 0;
|
|
2455
|
+
background: none;
|
|
2456
|
+
color: inherit;
|
|
2457
|
+
cursor: pointer;
|
|
2458
|
+
}
|
|
2459
|
+
.gp-ov-toggle:focus-visible { outline: 2px solid #9cc2ff; }
|
|
2460
|
+
.gp-ov-toggle::before {
|
|
2461
|
+
content: "";
|
|
2462
|
+
width: 6px;
|
|
2463
|
+
height: 6px;
|
|
2464
|
+
border: solid currentColor;
|
|
2465
|
+
border-width: 0 2px 2px 0;
|
|
2466
|
+
transform: translateY(-2px) rotate(45deg);
|
|
2467
|
+
}
|
|
2468
|
+
.gp-ov-toggle[aria-expanded="false"]::before { transform: translateY(2px) rotate(-135deg); }
|
|
2406
2469
|
.gp-ov-row { display: flex; align-items: flex-start; gap: 6px; }
|
|
2407
2470
|
.gp-ov-swatch {
|
|
2408
2471
|
flex: none;
|
|
@@ -2550,12 +2613,19 @@
|
|
|
2550
2613
|
var ART_TAGS = new Set(["img", "svg", "video", "canvas"]);
|
|
2551
2614
|
var inches = (px) => +(Math.abs(px) / 96).toFixed(2);
|
|
2552
2615
|
var ptIn = (pt2) => `${+(pt2 / 72).toFixed(3)}in`;
|
|
2616
|
+
var LEGEND_FOLD_KEY = "gutterpress.overlay-legend-collapsed";
|
|
2617
|
+
var legendCollapsed = false;
|
|
2618
|
+
try {
|
|
2619
|
+
legendCollapsed = localStorage.getItem(LEGEND_FOLD_KEY) === "true";
|
|
2620
|
+
} catch {}
|
|
2553
2621
|
function legend(layers, area, summary) {
|
|
2554
2622
|
const el = div("gp-ov-legend");
|
|
2623
|
+
const body = div("gp-ov-body");
|
|
2624
|
+
body.id = "gp-ov-body";
|
|
2555
2625
|
const add = (cls, ...content) => {
|
|
2556
2626
|
const line = div(cls);
|
|
2557
2627
|
line.append(...content);
|
|
2558
|
-
|
|
2628
|
+
body.appendChild(line);
|
|
2559
2629
|
};
|
|
2560
2630
|
const row = (layer, name, text) => {
|
|
2561
2631
|
const swatch = div("gp-ov-swatch");
|
|
@@ -2567,14 +2637,15 @@
|
|
|
2567
2637
|
add("gp-ov-row", swatch, label);
|
|
2568
2638
|
};
|
|
2569
2639
|
const { bleedPt, safePt, artSafePt, counts } = summary;
|
|
2640
|
+
const gutterPt = area?.gutter ?? safePt;
|
|
2570
2641
|
if (layers.bleed) {
|
|
2571
2642
|
row("bleed", "Bleed", bleedPt > 0 ? ` ${ptIn(bleedPt)} — top, bottom, outside; none at the binding` : " — none set (page.bleed in manifest.yaml)");
|
|
2572
2643
|
}
|
|
2573
2644
|
if (layers.safe) {
|
|
2574
|
-
row("safe", "Safe area: text", safePt
|
|
2645
|
+
row("safe", "Safe area: text", safePt <= 0 ? " — none set (page.safe in manifest.yaml)" : gutterPt === safePt ? ` — ${ptIn(safePt)}, every edge` : ` — ${ptIn(safePt)}; ${ptIn(gutterPt)} at the binding`);
|
|
2575
2646
|
}
|
|
2576
2647
|
if (layers.art) {
|
|
2577
|
-
row("art", "Safe area: art", safePt <= 0 && artSafePt <= 0 ? " — none set (page.artSafe in manifest.yaml)" : artSafePt ===
|
|
2648
|
+
row("art", "Safe area: art", safePt <= 0 && artSafePt <= 0 ? " — none set (page.artSafe in manifest.yaml)" : artSafePt === gutterPt ? ` — ${ptIn(artSafePt)}, every edge` : ` — ${ptIn(artSafePt)} top, bottom, outside; ${ptIn(gutterPt)} at the binding`);
|
|
2578
2649
|
}
|
|
2579
2650
|
if (layers.margins)
|
|
2580
2651
|
row("margins", "Page margins", " — your stylesheet's @page margins");
|
|
@@ -2610,6 +2681,30 @@
|
|
|
2610
2681
|
const key = document.documentElement.dataset.overlayKey;
|
|
2611
2682
|
if (key)
|
|
2612
2683
|
add("gp-ov-note", `${key} hides`);
|
|
2684
|
+
const title = document.createElement("b");
|
|
2685
|
+
title.id = "gp-ov-title";
|
|
2686
|
+
title.textContent = "Print overlays";
|
|
2687
|
+
const toggle = document.createElement("button");
|
|
2688
|
+
toggle.type = "button";
|
|
2689
|
+
toggle.className = "gp-ov-toggle";
|
|
2690
|
+
toggle.setAttribute("aria-labelledby", title.id);
|
|
2691
|
+
toggle.setAttribute("aria-controls", body.id);
|
|
2692
|
+
const fold = () => {
|
|
2693
|
+
body.hidden = legendCollapsed;
|
|
2694
|
+
toggle.setAttribute("aria-expanded", String(!legendCollapsed));
|
|
2695
|
+
toggle.title = legendCollapsed ? "Show the legend" : "Hide the legend";
|
|
2696
|
+
};
|
|
2697
|
+
toggle.addEventListener("click", () => {
|
|
2698
|
+
legendCollapsed = !legendCollapsed;
|
|
2699
|
+
try {
|
|
2700
|
+
localStorage.setItem(LEGEND_FOLD_KEY, String(legendCollapsed));
|
|
2701
|
+
} catch {}
|
|
2702
|
+
fold();
|
|
2703
|
+
});
|
|
2704
|
+
fold();
|
|
2705
|
+
const head = div("gp-ov-head");
|
|
2706
|
+
head.append(title, toggle);
|
|
2707
|
+
el.append(head, body);
|
|
2613
2708
|
return el;
|
|
2614
2709
|
}
|
|
2615
2710
|
function paintOverlay(pages, strips, area, layers) {
|
|
@@ -3029,7 +3124,7 @@
|
|
|
3029
3124
|
overlayPages.push({ index: bookIndex, sheet, strip, padded: ctx.padded });
|
|
3030
3125
|
}
|
|
3031
3126
|
const rows = Math.max(1, Math.ceil((strip.pages + shift) / perRow));
|
|
3032
|
-
run.style.
|
|
3127
|
+
run.style.minHeight = `${rowStride * (rows - 1) + PX_PER_PT * g.height}px`;
|
|
3033
3128
|
run.style.width = `${stride * perRow}px`;
|
|
3034
3129
|
const composed = !!strip.wrapCols && shift === 1 && !first;
|
|
3035
3130
|
run.style.marginTop = composed ? `${-(prevPageH + sheetGap)}px` : "";
|
|
@@ -3117,7 +3212,7 @@
|
|
|
3117
3212
|
}
|
|
3118
3213
|
}
|
|
3119
3214
|
function checkOverflow(strip, out) {
|
|
3120
|
-
const h = strip.el
|
|
3215
|
+
const { height: h } = stripMetrics(strip.el);
|
|
3121
3216
|
for (const el of Array.from(strip.el.querySelectorAll("figure,table,img,pre"))) {
|
|
3122
3217
|
const r = el.getBoundingClientRect();
|
|
3123
3218
|
if (r.height > h + 1) {
|
|
@@ -148,7 +148,7 @@ import { fileURLToPath } from "node:url";
|
|
|
148
148
|
var favicon_default = "./favicon-272ga6y0.ico";
|
|
149
149
|
|
|
150
150
|
// src/assets/manifest.schema.json
|
|
151
|
-
var manifest_schema_default = "./manifest.schema-
|
|
151
|
+
var manifest_schema_default = "./manifest.schema-c4wfpg6g.json";
|
|
152
152
|
|
|
153
153
|
// src/assets/preview/scripts/preview-interface.js
|
|
154
154
|
var preview_interface_default = "./preview-interface-nnmrxyqm.js";
|
|
@@ -163,10 +163,10 @@ var preview_shell_default = "./preview-shell-wk9k3gcd.js";
|
|
|
163
163
|
var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
|
|
164
164
|
|
|
165
165
|
// src/assets/engine/gutterpress-viewer.js
|
|
166
|
-
var gutterpress_viewer_default = "./gutterpress-viewer-
|
|
166
|
+
var gutterpress_viewer_default = "./gutterpress-viewer-w7njnkj7.js";
|
|
167
167
|
|
|
168
168
|
// src/assets/engine/gutterpress-agent.js
|
|
169
|
-
var gutterpress_agent_default = "./gutterpress-agent-
|
|
169
|
+
var gutterpress_agent_default = "./gutterpress-agent-yvd8w8my.js";
|
|
170
170
|
|
|
171
171
|
// src/assets/templates/book/manifest.yaml
|
|
172
172
|
var manifest_default = "./manifest-n1gh3qw5.yaml";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
getAssetsDir,
|
|
10
10
|
lastPageMode,
|
|
11
11
|
parseSize
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-crys9951.js";
|
|
13
13
|
import {
|
|
14
14
|
countLinkAnnotations,
|
|
15
15
|
getImageResolutions,
|
|
@@ -180,7 +180,8 @@ var DTRPG_PRESET = {
|
|
|
180
180
|
tolerance: 0.5,
|
|
181
181
|
bleed: 9,
|
|
182
182
|
safe: 36,
|
|
183
|
-
artSafe: 18
|
|
183
|
+
artSafe: 18,
|
|
184
|
+
gutter: undefined
|
|
184
185
|
},
|
|
185
186
|
ink: {
|
|
186
187
|
maxTac: 240,
|
|
@@ -267,7 +268,8 @@ var BOOK_PRESET = {
|
|
|
267
268
|
tolerance: 0.5,
|
|
268
269
|
bleed: undefined,
|
|
269
270
|
safe: 18,
|
|
270
|
-
artSafe: undefined
|
|
271
|
+
artSafe: undefined,
|
|
272
|
+
gutter: undefined
|
|
271
273
|
},
|
|
272
274
|
ink: {
|
|
273
275
|
maxTac: 400,
|
|
@@ -631,7 +633,8 @@ function resolveCustomPage(c, m) {
|
|
|
631
633
|
tolerance: c.page?.tolerance ?? m.page?.tolerance ?? 0.5,
|
|
632
634
|
bleed: c.page?.bleed ?? m.page?.bleed,
|
|
633
635
|
safe: c.page?.safe ?? m.page?.safe,
|
|
634
|
-
artSafe: c.page?.artSafe ?? m.page?.artSafe
|
|
636
|
+
artSafe: c.page?.artSafe ?? m.page?.artSafe,
|
|
637
|
+
gutter: c.page?.gutter ?? m.page?.gutter
|
|
635
638
|
};
|
|
636
639
|
}
|
|
637
640
|
function resolveWithPreset(cliOverrides, manifest, preset) {
|
|
@@ -1987,11 +1990,15 @@ var GUTTERPRESS_CSS = `
|
|
|
1987
1990
|
|
|
1988
1991
|
/* sizes — AFTER the flow positions so max-width:100% lifts the floats' 50%
|
|
1989
1992
|
cap at equal specificity */
|
|
1990
|
-
.gp-
|
|
1991
|
-
.gp-
|
|
1992
|
-
.gp-
|
|
1993
|
-
.gp-
|
|
1994
|
-
.gp-
|
|
1993
|
+
.gp-size-10 { width: 10%; max-width: 100%; }
|
|
1994
|
+
.gp-size-20 { width: 20%; max-width: 100%; }
|
|
1995
|
+
.gp-size-30 { width: 30%; max-width: 100%; }
|
|
1996
|
+
.gp-size-40 { width: 40%; max-width: 100%; }
|
|
1997
|
+
.gp-size-50 { width: 50%; max-width: 100%; }
|
|
1998
|
+
.gp-size-60 { width: 60%; max-width: 100%; }
|
|
1999
|
+
.gp-size-70 { width: 70%; max-width: 100%; }
|
|
2000
|
+
.gp-size-80 { width: 80%; max-width: 100%; }
|
|
2001
|
+
.gp-size-90 { width: 90%; max-width: 100%; }
|
|
1995
2002
|
|
|
1996
2003
|
/* float clearance presets — consumed by var(--gp-gap) in the float rules
|
|
1997
2004
|
above and by .gp-shape's shape-margin below; --gp-gap itself is
|
|
@@ -2189,11 +2196,15 @@ var GP_CLASSES = new Set([
|
|
|
2189
2196
|
"gp-center",
|
|
2190
2197
|
"gp-full",
|
|
2191
2198
|
"gp-bleed",
|
|
2192
|
-
"gp-
|
|
2193
|
-
"gp-
|
|
2194
|
-
"gp-
|
|
2195
|
-
"gp-
|
|
2196
|
-
"gp-
|
|
2199
|
+
"gp-size-10",
|
|
2200
|
+
"gp-size-20",
|
|
2201
|
+
"gp-size-30",
|
|
2202
|
+
"gp-size-40",
|
|
2203
|
+
"gp-size-50",
|
|
2204
|
+
"gp-size-60",
|
|
2205
|
+
"gp-size-70",
|
|
2206
|
+
"gp-size-80",
|
|
2207
|
+
"gp-size-90",
|
|
2197
2208
|
"gp-tight",
|
|
2198
2209
|
"gp-loose",
|
|
2199
2210
|
"gp-columns",
|
|
@@ -2318,10 +2329,10 @@ import markdownItAttrs from "markdown-it-attrs";
|
|
|
2318
2329
|
import markdownItFootnote from "markdown-it-footnote";
|
|
2319
2330
|
|
|
2320
2331
|
// src/lib/markdown/gp-pin-scope.js
|
|
2321
|
-
function warn3(env, line, type, message,
|
|
2332
|
+
function warn3(env, line, type, message, severity) {
|
|
2322
2333
|
if (!env.layoutWarnings)
|
|
2323
2334
|
env.layoutWarnings = [];
|
|
2324
|
-
env.layoutWarnings.push({ line, type, message,
|
|
2335
|
+
env.layoutWarnings.push(severity ? { line, type, message, severity } : { line, type, message });
|
|
2325
2336
|
}
|
|
2326
2337
|
function editDistance2(a, b) {
|
|
2327
2338
|
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
@@ -2364,7 +2375,7 @@ function checkFlushArt(token, env, line) {
|
|
|
2364
2375
|
return;
|
|
2365
2376
|
if (!classes.some((c) => PIN_EDGES.includes(c)))
|
|
2366
2377
|
return;
|
|
2367
|
-
warn3(env, line, "flush_art", FLUSH_ART_MSG);
|
|
2378
|
+
warn3(env, line, "flush_art", FLUSH_ART_MSG, "info");
|
|
2368
2379
|
}
|
|
2369
2380
|
function elementNameFor(token) {
|
|
2370
2381
|
switch (token.type) {
|
|
@@ -3185,6 +3196,7 @@ function printAreaMeta(page) {
|
|
|
3185
3196
|
bleed: page.bleed ?? 0,
|
|
3186
3197
|
safe: page.safe ?? 0,
|
|
3187
3198
|
artSafe: page.artSafe,
|
|
3199
|
+
gutter: page.gutter,
|
|
3188
3200
|
preset: page.preset,
|
|
3189
3201
|
spec: page.spec
|
|
3190
3202
|
});
|
|
@@ -3813,7 +3825,7 @@ import { satisfies, validRange } from "semver";
|
|
|
3813
3825
|
// package.json
|
|
3814
3826
|
var package_default = {
|
|
3815
3827
|
name: "gutterpress",
|
|
3816
|
-
version: "0.11.20-
|
|
3828
|
+
version: "0.11.20-beta.1",
|
|
3817
3829
|
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
3818
3830
|
author: "itlackey",
|
|
3819
3831
|
license: "MPL-2.0",
|
|
@@ -6875,11 +6887,11 @@ var inches = (pt) => `${+(pt / 72).toFixed(2)}in`;
|
|
|
6875
6887
|
var check4 = {
|
|
6876
6888
|
id: "pdf.print.safe-margins",
|
|
6877
6889
|
name: "Safe margins",
|
|
6878
|
-
description: "Fails when text sits closer to the trim than `page.safe` (DriveThruRPG: 0.5in on every edge). Text only: art is judged in the preview's safe-area overlay, not here. Skipped when `page.safe` is not set",
|
|
6890
|
+
description: "Fails when text sits closer to the trim than `page.safe` (DriveThruRPG: 0.5in on every edge), or than `page.gutter` at the binding edge where one is set. Text only: art is judged in the preview's safe-area overlay, not here. Skipped when `page.safe` is not set",
|
|
6879
6891
|
category: "pdf",
|
|
6880
6892
|
phase: "post-build",
|
|
6881
6893
|
async run(ctx) {
|
|
6882
|
-
const { width, height, bleed = 0, safe = 0 } = ctx.config.page;
|
|
6894
|
+
const { width, height, bleed = 0, safe = 0, gutter = safe } = ctx.config.page;
|
|
6883
6895
|
if (!ctx.pdfPath || !safe)
|
|
6884
6896
|
return [];
|
|
6885
6897
|
const doc = await loadPdf(ctx.pdfPath);
|
|
@@ -6917,8 +6929,7 @@ var check4 = {
|
|
|
6917
6929
|
["bottom", Math.min(...ys) - trim.bottom],
|
|
6918
6930
|
["top", trim.top - Math.max(...ys)]
|
|
6919
6931
|
];
|
|
6920
|
-
const [edge,
|
|
6921
|
-
const shortfall = safe - gap;
|
|
6932
|
+
const [edge, shortfall] = gaps.map(([name, gap]) => [name, (name === "binding" ? gutter : safe) - gap]).reduce((worst, g) => g[1] > worst[1] ? g : worst);
|
|
6922
6933
|
if (shortfall <= TOLERANCE_PT)
|
|
6923
6934
|
continue;
|
|
6924
6935
|
const text = item.str.trim();
|
|
@@ -6926,7 +6937,7 @@ var check4 = {
|
|
|
6926
6937
|
severity: "error",
|
|
6927
6938
|
message: `Page ${pageNum}: "${text.slice(0, 40)}${text.length > 40 ? "…" : ""}" is ${inches(shortfall)} too close to the ${edge} edge.`,
|
|
6928
6939
|
file: ctx.pdfPath,
|
|
6929
|
-
detail: `${rule}: text must stay at least ${inches(safe)} inside the trim on every edge.`,
|
|
6940
|
+
detail: gutter === safe ? `${rule}: text must stay at least ${inches(safe)} inside the trim on every edge.` : `${rule}: text must stay at least ${inches(safe)} inside the trim, ${inches(gutter)} at the binding.`,
|
|
6930
6941
|
code: "text-outside-safe-margin",
|
|
6931
6942
|
data: { page: pageNum, edge, shortfallPt: +shortfall.toFixed(2) }
|
|
6932
6943
|
}));
|
|
@@ -10867,7 +10878,7 @@ class PdfOutput {
|
|
|
10867
10878
|
const rawPdf = pdfxMode ? path13.join(stage, "raw.pdf") : path13.resolve(pdfFile);
|
|
10868
10879
|
await fsp2.mkdir(path13.dirname(path13.resolve(pdfFile)), { recursive: true });
|
|
10869
10880
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
10870
|
-
const { buildNativePdf } = await import("./engine-
|
|
10881
|
+
const { buildNativePdf } = await import("./engine-5fw55dfb.js");
|
|
10871
10882
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
10872
10883
|
title: config.title,
|
|
10873
10884
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -12412,16 +12423,29 @@ import { existsSync as existsSync13 } from "node:fs";
|
|
|
12412
12423
|
import { mkdir as mkdir8, readFile as readFile29, writeFile as writeFile8 } from "node:fs/promises";
|
|
12413
12424
|
import path19 from "node:path";
|
|
12414
12425
|
import postcss5 from "postcss";
|
|
12415
|
-
import { Scalar as Scalar2 } from "yaml";
|
|
12426
|
+
import { isMap as isMap2, Scalar as Scalar2 } from "yaml";
|
|
12416
12427
|
function isPositivePoints(value) {
|
|
12417
12428
|
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
12418
12429
|
}
|
|
12419
12430
|
function writePageBounds(doc, page) {
|
|
12420
|
-
const out = { width: page.width, height: page.height };
|
|
12421
12431
|
const tolerance = page.tolerance ?? numberAt(doc, ["page", "tolerance"]);
|
|
12432
|
+
if (!isMap2(doc.get("page", true)))
|
|
12433
|
+
doc.set("page", doc.createNode({}));
|
|
12434
|
+
doc.setIn(["page", "width"], page.width);
|
|
12435
|
+
doc.setIn(["page", "height"], page.height);
|
|
12422
12436
|
if (tolerance !== undefined)
|
|
12423
|
-
|
|
12424
|
-
|
|
12437
|
+
doc.setIn(["page", "tolerance"], tolerance);
|
|
12438
|
+
}
|
|
12439
|
+
function deletePageBounds(doc) {
|
|
12440
|
+
const block = doc.get("page", true);
|
|
12441
|
+
if (!isMap2(block)) {
|
|
12442
|
+
doc.delete("page");
|
|
12443
|
+
return;
|
|
12444
|
+
}
|
|
12445
|
+
for (const key of ["width", "height", "tolerance"])
|
|
12446
|
+
block.delete(key);
|
|
12447
|
+
if (block.items.length === 0)
|
|
12448
|
+
doc.delete("page");
|
|
12425
12449
|
}
|
|
12426
12450
|
function numberAt(doc, keyPath) {
|
|
12427
12451
|
const v = doc.getIn(keyPath);
|
|
@@ -12553,7 +12577,7 @@ async function setPageSetup(projectDir, choice) {
|
|
|
12553
12577
|
if (choice.preset === "custom")
|
|
12554
12578
|
writePageBounds(doc, size);
|
|
12555
12579
|
else
|
|
12556
|
-
doc
|
|
12580
|
+
deletePageBounds(doc);
|
|
12557
12581
|
if (target === newSheet && !sheets.includes(newSheet)) {
|
|
12558
12582
|
ensureSeq(doc, "styles").add(new Scalar2("styles/book.css"));
|
|
12559
12583
|
}
|
|
@@ -12997,7 +13021,7 @@ import { cp as cp3, mkdir as mkdir11, readFile as readFile32, readdir as readdir
|
|
|
12997
13021
|
import { constants as FS3, existsSync as existsSync15 } from "node:fs";
|
|
12998
13022
|
import { access as access3 } from "node:fs/promises";
|
|
12999
13023
|
import path22 from "node:path";
|
|
13000
|
-
import { isMap as
|
|
13024
|
+
import { isMap as isMap3, isScalar as isScalar2, isSeq as isSeq3, parseDocument as parseDocument2 } from "yaml";
|
|
13001
13025
|
var BUILT_IN_TEMPLATE_IDS = [
|
|
13002
13026
|
"book",
|
|
13003
13027
|
"zine",
|
|
@@ -13063,7 +13087,7 @@ function collectEscaping(nodes, getValue, escapes) {
|
|
|
13063
13087
|
return out;
|
|
13064
13088
|
}
|
|
13065
13089
|
function extensionEntryPath(node) {
|
|
13066
|
-
const use =
|
|
13090
|
+
const use = isMap3(node) ? scalarString(node.get("use", true)) : scalarString(node);
|
|
13067
13091
|
return use !== null && isPathSpecifier(use) ? use : null;
|
|
13068
13092
|
}
|
|
13069
13093
|
function dropEscaping(doc, seq, key, escaping) {
|
|
@@ -13075,7 +13099,7 @@ function dropEscaping(doc, seq, key, escaping) {
|
|
|
13075
13099
|
doc.delete(key);
|
|
13076
13100
|
}
|
|
13077
13101
|
function rewriteEntry(node, newPath) {
|
|
13078
|
-
if (
|
|
13102
|
+
if (isMap3(node))
|
|
13079
13103
|
node.set("use", newPath);
|
|
13080
13104
|
else if (isScalar2(node))
|
|
13081
13105
|
node.value = newPath;
|
|
@@ -13871,7 +13895,7 @@ async function searchNpmExtensions(query, options = {}) {
|
|
|
13871
13895
|
return { matches, total: pages.reduce((sum, page) => sum + page.total, 0) };
|
|
13872
13896
|
}
|
|
13873
13897
|
// src/lib/manifest-config.ts
|
|
13874
|
-
import { isSeq as isSeq4, isMap as
|
|
13898
|
+
import { isSeq as isSeq4, isMap as isMap4, YAMLSeq as YAMLSeq3, Scalar as Scalar3 } from "yaml";
|
|
13875
13899
|
function hasKey(obj, key) {
|
|
13876
13900
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
13877
13901
|
}
|
|
@@ -13909,7 +13933,7 @@ async function setManifestFields(projectDir, updates) {
|
|
|
13909
13933
|
if (f === null || Array.isArray(f) && f.length === 0) {
|
|
13910
13934
|
doc.deleteIn(["source", "files"]);
|
|
13911
13935
|
const source = doc.get("source", true);
|
|
13912
|
-
if (
|
|
13936
|
+
if (isMap4(source) && source.items.length === 0) {
|
|
13913
13937
|
doc.delete("source");
|
|
13914
13938
|
}
|
|
13915
13939
|
} else {
|
|
@@ -13939,7 +13963,7 @@ async function readManifestFields(projectDir) {
|
|
|
13939
13963
|
out.sourceFiles = filesNode.items.map((i) => scalarString(i) ?? "");
|
|
13940
13964
|
} else {
|
|
13941
13965
|
const sourceNode = doc.get("source", true);
|
|
13942
|
-
if (
|
|
13966
|
+
if (isMap4(sourceNode) && sourceNode.has("files"))
|
|
13943
13967
|
out.sourceFiles = null;
|
|
13944
13968
|
}
|
|
13945
13969
|
return out;
|
|
@@ -17636,10 +17660,10 @@ function normalizeProjectKey(projectDir) {
|
|
|
17636
17660
|
return projectDir.replace(/[\\/]+$/, "");
|
|
17637
17661
|
}
|
|
17638
17662
|
// src/lib/publish/manifest-publish.ts
|
|
17639
|
-
import { isMap as
|
|
17663
|
+
import { isMap as isMap5 } from "yaml";
|
|
17640
17664
|
function settingsFromDoc(doc) {
|
|
17641
17665
|
const node = doc.get("publish", true);
|
|
17642
|
-
if (!
|
|
17666
|
+
if (!isMap5(node))
|
|
17643
17667
|
return {};
|
|
17644
17668
|
const json = node.toJSON();
|
|
17645
17669
|
const out = {};
|
|
@@ -17664,11 +17688,11 @@ async function setPublishProviderConfig(projectDir, providerId, values) {
|
|
|
17664
17688
|
}
|
|
17665
17689
|
}
|
|
17666
17690
|
const section = doc.getIn(["publish", providerId], true);
|
|
17667
|
-
if (
|
|
17691
|
+
if (isMap5(section) && section.items.length === 0) {
|
|
17668
17692
|
doc.deleteIn(["publish", providerId]);
|
|
17669
17693
|
}
|
|
17670
17694
|
const publish = doc.get("publish", true);
|
|
17671
|
-
if (
|
|
17695
|
+
if (isMap5(publish) && publish.items.length === 0) {
|
|
17672
17696
|
doc.delete("publish");
|
|
17673
17697
|
}
|
|
17674
17698
|
await writeManifestDoc(file, doc);
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
stringValueAt,
|
|
20
20
|
toFolioPage,
|
|
21
21
|
wantsRecto
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-crys9951.js";
|
|
23
23
|
import {
|
|
24
24
|
launchChromium
|
|
25
25
|
} from "./index-bt0qws5c.js";
|
|
@@ -49,7 +49,7 @@ function flushMargins(margin, edges) {
|
|
|
49
49
|
}
|
|
50
50
|
function pinInsets(area, side, edges) {
|
|
51
51
|
const binding = side === "recto" ? "left" : "right";
|
|
52
|
-
const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.
|
|
52
|
+
const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.gutter : area.bleed + area.artSafe;
|
|
53
53
|
return { top: inset("top"), right: inset("right"), bottom: inset("bottom"), left: inset("left") };
|
|
54
54
|
}
|
|
55
55
|
var NO_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
|
package/dist/index.js
CHANGED
|
@@ -154,14 +154,14 @@ import {
|
|
|
154
154
|
testRemoteAccess,
|
|
155
155
|
updateExtensions,
|
|
156
156
|
validateProjectExtensions
|
|
157
|
-
} from "./index-
|
|
157
|
+
} from "./index-pjw7trb8.js";
|
|
158
158
|
import"./index-ht1bcqdd.js";
|
|
159
159
|
import {
|
|
160
160
|
BUILD_DIAGNOSTIC_CODES
|
|
161
|
-
} from "./index-
|
|
161
|
+
} from "./index-yw16cfm8.js";
|
|
162
162
|
import {
|
|
163
163
|
BuildError
|
|
164
|
-
} from "./index-
|
|
164
|
+
} from "./index-crys9951.js";
|
|
165
165
|
import"./index-sth219v1.js";
|
|
166
166
|
import {
|
|
167
167
|
DEFAULT_PRINT_OPTS,
|
|
@@ -44,7 +44,7 @@ export interface LayoutWarning {
|
|
|
44
44
|
type: string;
|
|
45
45
|
message: string;
|
|
46
46
|
marker?: unknown;
|
|
47
|
-
/** Set
|
|
47
|
+
/** Set by a component's `validate` and by `flush_art`; absent means `"warning"`. */
|
|
48
48
|
severity?: "error" | "warning" | "info";
|
|
49
49
|
}
|
|
50
50
|
/**
|