gutterpress 0.11.20-alpha.3 → 0.11.20-alpha.4
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-a8ycsg80.js → build-epdcrm2c.js} +4 -4
- package/dist/{cli-9k2tb493.js → cli-0ey902sx.js} +90 -28
- package/dist/{cli-x4p99w8d.js → cli-61vd4ews.js} +83 -41
- package/dist/{cli-hn9pk0hp.js → cli-fmksazej.js} +1 -1
- package/dist/{cli-y9bcya7r.js → cli-h4tfmpg3.js} +2 -2
- package/dist/cli.js +12 -12
- package/dist/{doctor-wbjkrcpc.js → doctor-78es5scm.js} +2 -2
- package/dist/engine/compiler/build.d.ts +1 -1
- package/dist/engine/shared/margin-box-support.d.ts +2 -2
- package/dist/engine/shared/pin-edges.d.ts +127 -0
- package/dist/engine/shared/print-area.d.ts +68 -0
- package/dist/{engine-yxnnp3hx.js → engine-67f68bxs.js} +1 -1
- package/dist/{engine-fdtv01a2.js → engine-7ha27n2b.js} +2 -2
- package/dist/{ext-pesyrs68.js → ext-9mc7sr0d.js} +4 -4
- package/dist/{gutterpress-agent-cazqstr1.js → gutterpress-agent-mrdnwktc.js} +78 -13
- package/dist/{gutterpress-viewer-1yse8cx3.js → gutterpress-viewer-jr30yw8t.js} +143 -52
- package/dist/{index-r87y7wzw.js → index-ad95fws8.js} +82 -40
- package/dist/{index-zagagnwq.js → index-gm5xbx5w.js} +3 -3
- package/dist/{index-tjvrchxj.js → index-t13p8y08.js} +199 -137
- package/dist/index.js +3 -3
- package/dist/lib/extension-manifest.d.ts +13 -0
- package/dist/lib/markdown/assemble.d.ts +12 -2
- package/dist/lib/markdown/gutterpress-css.d.ts +46 -30
- package/dist/lib/markdown/index.d.ts +5 -0
- package/dist/{manifest.schema-c9x8912a.json → manifest.schema-13dfax80.json} +3 -3
- package/dist/{new-8yah8z91.js → new-s4f0tnya.js} +4 -4
- package/dist/{preflight-8ccx4kdc.js → preflight-7ck4rbsq.js} +4 -4
- package/dist/preview/file-watcher.d.ts +4 -10
- package/dist/{preview-w7v9w36q.js → preview-j91sxadd.js} +4 -4
- package/dist/{publish-g5nh5myh.js → publish-f12xaenm.js} +4 -4
- package/dist/render.js +57 -6
- package/dist/schema/manifest.types.d.ts +8 -6
- package/dist/{validate-1yh59x0x.js → validate-pb5gysvr.js} +4 -4
- package/package.json +1 -1
- package/dist/engine/shared/flush.d.ts +0 -59
|
@@ -1038,10 +1038,12 @@
|
|
|
1038
1038
|
`);
|
|
1039
1039
|
}
|
|
1040
1040
|
|
|
1041
|
-
// src/engine/shared/
|
|
1042
|
-
var
|
|
1043
|
-
|
|
1044
|
-
|
|
1041
|
+
// src/engine/shared/pin-edges.ts
|
|
1042
|
+
var PIN_EDGES = ["top", "right", "bottom", "left"];
|
|
1043
|
+
var EDGE_PIN_SELECTOR = PIN_EDGES.map((edge) => `.gp-pin.gp-${edge}`).join(", ");
|
|
1044
|
+
function pinEdgesIn(root) {
|
|
1045
|
+
const pins = Array.from(root.querySelectorAll(EDGE_PIN_SELECTOR)).filter((pin) => pin.offsetParent === root);
|
|
1046
|
+
return PIN_EDGES.filter((edge) => pins.some((pin) => pin.classList.contains(`gp-${edge}`)));
|
|
1045
1047
|
}
|
|
1046
1048
|
function flushMargins(margin, edges) {
|
|
1047
1049
|
return {
|
|
@@ -1051,6 +1053,57 @@
|
|
|
1051
1053
|
left: edges.includes("left") ? 0 : margin.left
|
|
1052
1054
|
};
|
|
1053
1055
|
}
|
|
1056
|
+
function pinInsets(area, side, edges) {
|
|
1057
|
+
const binding = side === "recto" ? "left" : "right";
|
|
1058
|
+
const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.safe : area.bleed + area.artSafe;
|
|
1059
|
+
return { top: inset("top"), right: inset("right"), bottom: inset("bottom"), left: inset("left") };
|
|
1060
|
+
}
|
|
1061
|
+
var NO_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
1062
|
+
function pinRootStyle(margin, area, side, edges, padding = NO_PADDING) {
|
|
1063
|
+
const px = (pt) => pt * 96 / 72;
|
|
1064
|
+
const inset = pinInsets(area, side, edges);
|
|
1065
|
+
const style = { "box-decoration-break": "clone" };
|
|
1066
|
+
for (const edge of PIN_EDGES)
|
|
1067
|
+
if (edges.includes(edge))
|
|
1068
|
+
style[`padding-${edge}`] = `${px(margin[edge]) + padding[edge]}px`;
|
|
1069
|
+
for (const edge of PIN_EDGES)
|
|
1070
|
+
style[`--gp-pin-${edge}`] = `${px(inset[edge])}px`;
|
|
1071
|
+
return style;
|
|
1072
|
+
}
|
|
1073
|
+
function paddingOf(cs) {
|
|
1074
|
+
return {
|
|
1075
|
+
top: parseFloat(cs.paddingTop) || 0,
|
|
1076
|
+
right: parseFloat(cs.paddingRight) || 0,
|
|
1077
|
+
bottom: parseFloat(cs.paddingBottom) || 0,
|
|
1078
|
+
left: parseFloat(cs.paddingLeft) || 0
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
// src/engine/shared/print-area.ts
|
|
1083
|
+
function printAreaFromMeta(doc) {
|
|
1084
|
+
const raw = doc.querySelector('meta[name="gp-print-area"]')?.getAttribute("content");
|
|
1085
|
+
if (!raw)
|
|
1086
|
+
return null;
|
|
1087
|
+
try {
|
|
1088
|
+
const v = JSON.parse(raw);
|
|
1089
|
+
const n = (x) => typeof x === "number" && Number.isFinite(x) && x > 0 ? x : 0;
|
|
1090
|
+
if (!n(v.width) || !n(v.height))
|
|
1091
|
+
return null;
|
|
1092
|
+
const safe = n(v.safe);
|
|
1093
|
+
const spec = v.spec && typeof v.spec.label === "string" && typeof v.spec.url === "string" && /^https?:\/\//i.test(v.spec.url) ? v.spec : undefined;
|
|
1094
|
+
return {
|
|
1095
|
+
width: n(v.width),
|
|
1096
|
+
height: n(v.height),
|
|
1097
|
+
bleed: n(v.bleed),
|
|
1098
|
+
safe,
|
|
1099
|
+
artSafe: typeof v.artSafe === "number" ? n(v.artSafe) : safe,
|
|
1100
|
+
preset: typeof v.preset === "string" ? v.preset : undefined,
|
|
1101
|
+
spec
|
|
1102
|
+
};
|
|
1103
|
+
} catch {
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1054
1107
|
|
|
1055
1108
|
// src/engine/viewer/fragment.ts
|
|
1056
1109
|
var PX_PER_PT = 96 / 72;
|
|
@@ -1210,13 +1263,29 @@
|
|
|
1210
1263
|
}
|
|
1211
1264
|
return false;
|
|
1212
1265
|
}
|
|
1213
|
-
function pushRun(runs, page, nodes,
|
|
1214
|
-
const key = (r) => `${r.page ?? ""}\x00${(r.
|
|
1266
|
+
function pushRun(runs, page, nodes, pin) {
|
|
1267
|
+
const key = (r) => `${r.page ?? ""}\x00${(r.pin?.edges ?? []).join(",")}`;
|
|
1215
1268
|
const last = runs[runs.length - 1];
|
|
1216
|
-
if (last && key(last) === key({ page,
|
|
1269
|
+
if (last && key(last) === key({ page, pin })) {
|
|
1217
1270
|
last.nodes.push(...nodes);
|
|
1218
|
-
|
|
1219
|
-
|
|
1271
|
+
if (pin)
|
|
1272
|
+
last.pin.roots.push(...pin.roots);
|
|
1273
|
+
} else
|
|
1274
|
+
runs.push({ page, nodes, pin: pin && { edges: pin.edges, roots: [...pin.roots] } });
|
|
1275
|
+
}
|
|
1276
|
+
var PAGE_ROOT = ".page, .spread";
|
|
1277
|
+
var ownPadding = new WeakMap;
|
|
1278
|
+
function pinRunOf(el) {
|
|
1279
|
+
if (!el.matches(PAGE_ROOT))
|
|
1280
|
+
return;
|
|
1281
|
+
const edges = pinEdgesIn(el);
|
|
1282
|
+
return edges.length ? { edges, roots: [el] } : undefined;
|
|
1283
|
+
}
|
|
1284
|
+
function holdsPinRoot(el) {
|
|
1285
|
+
return Array.from(el.querySelectorAll(EDGE_PIN_SELECTOR)).some((pin) => {
|
|
1286
|
+
const root = pin.offsetParent;
|
|
1287
|
+
return !!root && root !== el && el.contains(root) && root.matches(PAGE_ROOT);
|
|
1288
|
+
});
|
|
1220
1289
|
}
|
|
1221
1290
|
function explodeChildren(container, model) {
|
|
1222
1291
|
const runs = [];
|
|
@@ -1228,7 +1297,7 @@
|
|
|
1228
1297
|
pending = [];
|
|
1229
1298
|
const last = runs[runs.length - 1];
|
|
1230
1299
|
if (last) {
|
|
1231
|
-
pushRun(runs, last.page, held, last.
|
|
1300
|
+
pushRun(runs, last.page, held, last.pin && { edges: last.pin.edges, roots: [] });
|
|
1232
1301
|
return [];
|
|
1233
1302
|
}
|
|
1234
1303
|
if (held.some((n) => (n.textContent ?? "").trim() !== "")) {
|
|
@@ -1245,19 +1314,19 @@
|
|
|
1245
1314
|
const kid = node;
|
|
1246
1315
|
if (kid.classList.contains("gp-layer"))
|
|
1247
1316
|
continue;
|
|
1248
|
-
const
|
|
1317
|
+
const pin = pinRunOf(kid);
|
|
1249
1318
|
const own = directPageName(kid, model);
|
|
1250
1319
|
if (own !== undefined) {
|
|
1251
|
-
pushRun(runs, own, [...carry(), kid],
|
|
1320
|
+
pushRun(runs, own, [...carry(), kid], pin);
|
|
1252
1321
|
continue;
|
|
1253
1322
|
}
|
|
1254
|
-
if (!hasDescendantPageAssignment(kid, model)) {
|
|
1255
|
-
pushRun(runs, undefined, [...carry(), kid],
|
|
1323
|
+
if (!hasDescendantPageAssignment(kid, model) && !holdsPinRoot(kid)) {
|
|
1324
|
+
pushRun(runs, undefined, [...carry(), kid], pin);
|
|
1256
1325
|
continue;
|
|
1257
1326
|
}
|
|
1258
1327
|
const inner = explodeChildren(kid, model);
|
|
1259
1328
|
if (inner.length <= 1) {
|
|
1260
|
-
pushRun(runs, inner[0]?.page, [...carry(), kid]);
|
|
1329
|
+
pushRun(runs, inner[0]?.page, [...carry(), kid], pin ?? inner[0]?.pin);
|
|
1261
1330
|
continue;
|
|
1262
1331
|
}
|
|
1263
1332
|
let lead = carry();
|
|
@@ -1266,7 +1335,7 @@
|
|
|
1266
1335
|
for (const n of r.nodes)
|
|
1267
1336
|
shell.appendChild(n);
|
|
1268
1337
|
kid.before(shell);
|
|
1269
|
-
pushRun(runs, r.page, [...lead, shell],
|
|
1338
|
+
pushRun(runs, r.page, [...lead, shell], pin ? pinRunOf(shell) : r.pin);
|
|
1270
1339
|
lead = [];
|
|
1271
1340
|
}
|
|
1272
1341
|
kid.remove();
|
|
@@ -1323,6 +1392,42 @@
|
|
|
1323
1392
|
delete el.dataset.gpLeadingPageRootDisplayPriority;
|
|
1324
1393
|
}
|
|
1325
1394
|
}
|
|
1395
|
+
function fitVersoPinRoots(model, strips) {
|
|
1396
|
+
const area = printAreaFromMeta(document);
|
|
1397
|
+
const versos = [];
|
|
1398
|
+
for (const strip of strips) {
|
|
1399
|
+
if (!strip.pinEdges || !strip.pinRoots?.length)
|
|
1400
|
+
continue;
|
|
1401
|
+
const edges = strip.pinEdges;
|
|
1402
|
+
const { left, agree } = pageSides(model, strip.page);
|
|
1403
|
+
const verso = agree ? left.margin : strip.geometry.margin;
|
|
1404
|
+
const margin = { ...strip.geometry.margin, left: verso.left, right: verso.right };
|
|
1405
|
+
const shift = pt(strip.versoShift);
|
|
1406
|
+
for (const root of strip.pinRoots) {
|
|
1407
|
+
if (pageOf(root, strips) % 2 !== 1)
|
|
1408
|
+
continue;
|
|
1409
|
+
const style = pinRootStyle(margin, area, "verso", edges, ownPadding.get(root));
|
|
1410
|
+
if (shift && edges.includes("left"))
|
|
1411
|
+
style["margin-left"] = `${shift}px`;
|
|
1412
|
+
if (shift && edges.includes("right"))
|
|
1413
|
+
style["margin-right"] = `${-shift}px`;
|
|
1414
|
+
versos.push({ root, style });
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
for (const { root, style } of versos)
|
|
1418
|
+
for (const [prop, value] of Object.entries(style))
|
|
1419
|
+
root.style.setProperty(prop, value);
|
|
1420
|
+
}
|
|
1421
|
+
function restorePinRoots(doc = document) {
|
|
1422
|
+
for (const el of Array.from(doc.querySelectorAll("[data-gp-pin-style]"))) {
|
|
1423
|
+
const style = el.dataset.gpPinStyle;
|
|
1424
|
+
if (style)
|
|
1425
|
+
el.setAttribute("style", style);
|
|
1426
|
+
else
|
|
1427
|
+
el.removeAttribute("style");
|
|
1428
|
+
delete el.dataset.gpPinStyle;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1326
1431
|
var SCROLLABLE = /^(auto|scroll|hidden)$/;
|
|
1327
1432
|
function makeOverflowFragmentable(strips) {
|
|
1328
1433
|
const todo = [];
|
|
@@ -1388,21 +1493,16 @@
|
|
|
1388
1493
|
agree: Math.abs(r.w - l.w) < 0.01 && Math.abs(r.h - l.h) < 0.01
|
|
1389
1494
|
};
|
|
1390
1495
|
}
|
|
1391
|
-
function versoShiftPt(model, name
|
|
1496
|
+
function versoShiftPt(model, name) {
|
|
1392
1497
|
const { right, left, agree } = pageSides(model, name);
|
|
1393
|
-
|
|
1394
|
-
return 0;
|
|
1395
|
-
const r = flushMargins(right.margin, flushEdges);
|
|
1396
|
-
const l = flushMargins(left.margin, flushEdges);
|
|
1397
|
-
if (Math.abs(r.left + r.right - (l.left + l.right)) >= 0.01)
|
|
1398
|
-
return 0;
|
|
1399
|
-
return r.left - l.left;
|
|
1498
|
+
return agree ? right.margin.left - left.margin.left : 0;
|
|
1400
1499
|
}
|
|
1401
1500
|
function buildStrips(model, opts = {}, warnings = []) {
|
|
1402
1501
|
const doc = document;
|
|
1403
1502
|
const root = opts.root ?? doc.querySelector("main") ?? doc.body;
|
|
1404
1503
|
const gap = opts.sheetGap ?? 24;
|
|
1405
1504
|
const runs = explodeChildren(root, model);
|
|
1505
|
+
const area = printAreaFromMeta(doc);
|
|
1406
1506
|
const strips = [];
|
|
1407
1507
|
for (const run of runs) {
|
|
1408
1508
|
const geometry = runPageBox(model, run.page, warnings);
|
|
@@ -1410,7 +1510,18 @@
|
|
|
1410
1510
|
strip.className = "gp-strip";
|
|
1411
1511
|
if (run.page)
|
|
1412
1512
|
strip.dataset.page = run.page;
|
|
1413
|
-
const margin = run.
|
|
1513
|
+
const margin = run.pin ? flushMargins(geometry.margin, run.pin.edges) : geometry.margin;
|
|
1514
|
+
if (run.pin) {
|
|
1515
|
+
const { edges, roots } = run.pin;
|
|
1516
|
+
for (const pinRoot of roots)
|
|
1517
|
+
ownPadding.set(pinRoot, paddingOf(getComputedStyle(pinRoot)));
|
|
1518
|
+
for (const pinRoot of roots) {
|
|
1519
|
+
pinRoot.dataset.gpPinStyle ??= pinRoot.getAttribute("style") ?? "";
|
|
1520
|
+
const recto = pinRootStyle(geometry.margin, area, "recto", edges, ownPadding.get(pinRoot));
|
|
1521
|
+
for (const [prop, value] of Object.entries(recto))
|
|
1522
|
+
pinRoot.style.setProperty(prop, value);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1414
1525
|
const w = pt(geometry.width - margin.left - margin.right);
|
|
1415
1526
|
const h = pt(geometry.height - margin.top - margin.bottom);
|
|
1416
1527
|
strip.style.setProperty("--gp-content-w", `${w}px`);
|
|
@@ -1422,7 +1533,7 @@
|
|
|
1422
1533
|
strip.style.setProperty("--gp-margin-right", `${pt(margin.right)}px`);
|
|
1423
1534
|
strip.style.setProperty("--gp-margin-bottom", `${pt(margin.bottom)}px`);
|
|
1424
1535
|
strip.style.setProperty("--gp-margin-left", `${pt(margin.left)}px`);
|
|
1425
|
-
const rawShift = versoShiftPt(model, run.page
|
|
1536
|
+
const rawShift = versoShiftPt(model, run.page);
|
|
1426
1537
|
const versoShift = Math.abs(rawShift) >= 0.01 ? rawShift : 0;
|
|
1427
1538
|
if (versoShift)
|
|
1428
1539
|
strip.style.setProperty("--gp-verso-shift", `${pt(versoShift)}px`);
|
|
@@ -1433,7 +1544,8 @@
|
|
|
1433
1544
|
el: strip,
|
|
1434
1545
|
page: run.page,
|
|
1435
1546
|
geometry,
|
|
1436
|
-
|
|
1547
|
+
pinEdges: run.pin?.edges,
|
|
1548
|
+
pinRoots: run.pin?.roots,
|
|
1437
1549
|
versoShift,
|
|
1438
1550
|
pages: 0,
|
|
1439
1551
|
offset: 0
|
|
@@ -1805,6 +1917,7 @@
|
|
|
1805
1917
|
const headers = opts.compensateHeaders === false ? { tables: 0, passes: 0, warnings: [] } : compensateRepeatedHeaders(strips);
|
|
1806
1918
|
const contentPages = measure(strips).totalPages;
|
|
1807
1919
|
const totalPages = padToSignature(strips, contentPages);
|
|
1920
|
+
fitVersoPinRoots(model, strips);
|
|
1808
1921
|
const api = {
|
|
1809
1922
|
model,
|
|
1810
1923
|
strips,
|
|
@@ -1818,6 +1931,7 @@
|
|
|
1818
1931
|
relayout: () => {
|
|
1819
1932
|
restoreFullHeightPageRoots();
|
|
1820
1933
|
restoreScrollContainers();
|
|
1934
|
+
restorePinRoots();
|
|
1821
1935
|
unwrapStrips(strips);
|
|
1822
1936
|
for (const spacer of Array.from(document.querySelectorAll(".gp-recto-spacer, .gp-pad-spacer")))
|
|
1823
1937
|
spacer.remove();
|
|
@@ -1836,6 +1950,7 @@
|
|
|
1836
1950
|
const content = measure(strips).totalPages;
|
|
1837
1951
|
padToSignature(strips, content);
|
|
1838
1952
|
const r = measure(strips);
|
|
1953
|
+
fitVersoPinRoots(model, strips);
|
|
1839
1954
|
api.totalPages = r.totalPages;
|
|
1840
1955
|
api.blankPageIndices = blankPageIndices(strips);
|
|
1841
1956
|
api.paddedPageIndices = pagesAfter(content, r.totalPages);
|
|
@@ -2182,30 +2297,6 @@
|
|
|
2182
2297
|
artSafePt: 0,
|
|
2183
2298
|
counts: { text: 0, art: 0, bleed: 0, offPage: 0, intended: 0 }
|
|
2184
2299
|
};
|
|
2185
|
-
function printAreaFromMeta() {
|
|
2186
|
-
const raw = document.querySelector('meta[name="gp-print-area"]')?.getAttribute("content");
|
|
2187
|
-
if (!raw)
|
|
2188
|
-
return null;
|
|
2189
|
-
try {
|
|
2190
|
-
const v = JSON.parse(raw);
|
|
2191
|
-
const n = (x) => typeof x === "number" && Number.isFinite(x) && x > 0 ? x : 0;
|
|
2192
|
-
if (!n(v.width) || !n(v.height))
|
|
2193
|
-
return null;
|
|
2194
|
-
const safe = n(v.safe);
|
|
2195
|
-
const spec = v.spec && typeof v.spec.label === "string" && typeof v.spec.url === "string" && /^https?:\/\//i.test(v.spec.url) ? v.spec : undefined;
|
|
2196
|
-
return {
|
|
2197
|
-
width: n(v.width),
|
|
2198
|
-
height: n(v.height),
|
|
2199
|
-
bleed: n(v.bleed),
|
|
2200
|
-
safe,
|
|
2201
|
-
artSafe: typeof v.artSafe === "number" ? n(v.artSafe) : safe,
|
|
2202
|
-
preset: typeof v.preset === "string" ? v.preset : undefined,
|
|
2203
|
-
spec
|
|
2204
|
-
};
|
|
2205
|
-
} catch {
|
|
2206
|
-
return null;
|
|
2207
|
-
}
|
|
2208
|
-
}
|
|
2209
2300
|
function sheetArea(sheet) {
|
|
2210
2301
|
const px = (name) => parseFloat(sheet.style.getPropertyValue(name)) || 0;
|
|
2211
2302
|
return { width: px("--gp-page-w") / PX_PER_PT, height: px("--gp-page-h") / PX_PER_PT, bleed: 0, safe: 0, artSafe: 0 };
|
|
@@ -2689,7 +2780,7 @@
|
|
|
2689
2780
|
let overlayPages = [];
|
|
2690
2781
|
let overlaySummary = OVERLAY_OFF;
|
|
2691
2782
|
const paintOverlayNow = () => {
|
|
2692
|
-
overlaySummary = paintOverlay(overlayPages, layout.strips, printAreaFromMeta(), overlayLayers);
|
|
2783
|
+
overlaySummary = paintOverlay(overlayPages, layout.strips, printAreaFromMeta(document), overlayLayers);
|
|
2693
2784
|
window.dispatchEvent(new CustomEvent("gp:overlay", { detail: overlaySummary }));
|
|
2694
2785
|
};
|
|
2695
2786
|
const api = {
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
stringValueAt,
|
|
20
20
|
toFolioPage,
|
|
21
21
|
wantsRecto
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-gm5xbx5w.js";
|
|
23
23
|
import {
|
|
24
24
|
launchChromium
|
|
25
25
|
} from "./index-bt0qws5c.js";
|
|
@@ -29,14 +29,15 @@ import { readFile } from "node:fs/promises";
|
|
|
29
29
|
import { resolve } from "node:path";
|
|
30
30
|
import { pathToFileURL } from "node:url";
|
|
31
31
|
|
|
32
|
-
// src/engine/shared/
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
// src/engine/shared/pin-edges.ts
|
|
33
|
+
var PIN_EDGES = ["top", "right", "bottom", "left"];
|
|
34
|
+
var EDGE_PIN_SELECTOR = PIN_EDGES.map((edge) => `.gp-pin.gp-${edge}`).join(", ");
|
|
35
|
+
function pinKey(edges) {
|
|
36
|
+
return PIN_EDGES.filter((e) => edges.includes(e)).map((e) => e[0]).join("");
|
|
36
37
|
}
|
|
37
|
-
function
|
|
38
|
+
function pinPageName(authorPage, edges) {
|
|
38
39
|
const safe = authorPage ? authorPage.replace(/[^A-Za-z0-9_-]/g, "_") : "";
|
|
39
|
-
return `gp--
|
|
40
|
+
return `gp--pin${safe ? `-${safe}` : ""}-${pinKey(edges)}`;
|
|
40
41
|
}
|
|
41
42
|
function flushMargins(margin, edges) {
|
|
42
43
|
return {
|
|
@@ -46,6 +47,23 @@ function flushMargins(margin, edges) {
|
|
|
46
47
|
left: edges.includes("left") ? 0 : margin.left
|
|
47
48
|
};
|
|
48
49
|
}
|
|
50
|
+
function pinInsets(area, side, edges) {
|
|
51
|
+
const binding = side === "recto" ? "left" : "right";
|
|
52
|
+
const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.safe : area.bleed + area.artSafe;
|
|
53
|
+
return { top: inset("top"), right: inset("right"), bottom: inset("bottom"), left: inset("left") };
|
|
54
|
+
}
|
|
55
|
+
var NO_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
56
|
+
function pinRootStyle(margin, area, side, edges, padding = NO_PADDING) {
|
|
57
|
+
const px = (pt) => pt * 96 / 72;
|
|
58
|
+
const inset = pinInsets(area, side, edges);
|
|
59
|
+
const style = { "box-decoration-break": "clone" };
|
|
60
|
+
for (const edge of PIN_EDGES)
|
|
61
|
+
if (edges.includes(edge))
|
|
62
|
+
style[`padding-${edge}`] = `${px(margin[edge]) + padding[edge]}px`;
|
|
63
|
+
for (const edge of PIN_EDGES)
|
|
64
|
+
style[`--gp-pin-${edge}`] = `${px(inset[edge])}px`;
|
|
65
|
+
return style;
|
|
66
|
+
}
|
|
49
67
|
function marginBoxesOnEdges(edges) {
|
|
50
68
|
const owners = {
|
|
51
69
|
"top-left-corner": ["top", "left"],
|
|
@@ -723,7 +741,7 @@ var BUILD_DIAGNOSTIC_CODES = [
|
|
|
723
741
|
"engine.multicol.dead-column",
|
|
724
742
|
"engine.content.overheight",
|
|
725
743
|
"engine.image.low-dpi",
|
|
726
|
-
"engine.
|
|
744
|
+
"engine.pin.margin-box",
|
|
727
745
|
"engine.page-background.unreferenced",
|
|
728
746
|
"engine.hyphenation.unsupported"
|
|
729
747
|
];
|
|
@@ -756,25 +774,31 @@ async function build(opts) {
|
|
|
756
774
|
await page.send("Emulation.setDeviceMetricsOverride", sheetViewport);
|
|
757
775
|
await page.send("Emulation.setEmulatedMedia", { media: "print" });
|
|
758
776
|
log(`print media emulated for audits and measurement`);
|
|
759
|
-
const
|
|
760
|
-
const
|
|
761
|
-
for (const root of
|
|
762
|
-
if (
|
|
777
|
+
const pinRoots = await page.evaluate(`window.__gp.pinRoots()`);
|
|
778
|
+
const pinGroups = new Map;
|
|
779
|
+
for (const root of pinRoots) {
|
|
780
|
+
if (pinGroups.has(root.key))
|
|
763
781
|
continue;
|
|
764
782
|
const authorPage = root.page === "auto" ? undefined : root.page;
|
|
765
|
-
|
|
783
|
+
pinGroups.set(root.key, {
|
|
766
784
|
authorPage,
|
|
767
785
|
edges: root.edges,
|
|
768
|
-
|
|
786
|
+
padding: root.padding,
|
|
787
|
+
genName: pinPageName(authorPage, root.edges),
|
|
769
788
|
key: root.key
|
|
770
789
|
});
|
|
771
790
|
}
|
|
772
|
-
|
|
791
|
+
const printArea = pinRoots.length ? await page.evaluate(`window.__gp.printArea()`) : null;
|
|
792
|
+
const pinStyle = (group, pseudos) => pinRootStyle(resolvePage(model, { name: group.authorPage, pseudos }).geometry.margin, printArea, pseudos.includes("left") ? "verso" : "recto", group.edges, group.padding);
|
|
793
|
+
if (pinGroups.size) {
|
|
773
794
|
const lines = [];
|
|
774
|
-
|
|
795
|
+
const aliased = new Set;
|
|
796
|
+
for (const group of pinGroups.values()) {
|
|
797
|
+
const alias = !aliased.has(group.genName);
|
|
798
|
+
aliased.add(group.genName);
|
|
775
799
|
const relocated = new Set(marginBoxesOnEdges(group.edges));
|
|
776
800
|
const pseudoSets = [[]];
|
|
777
|
-
if (group.authorPage) {
|
|
801
|
+
if (alias && group.authorPage) {
|
|
778
802
|
for (const rule of model.pageRules) {
|
|
779
803
|
if (rule.name !== group.authorPage)
|
|
780
804
|
continue;
|
|
@@ -798,7 +822,7 @@ ${body.join(`
|
|
|
798
822
|
}`);
|
|
799
823
|
}
|
|
800
824
|
}
|
|
801
|
-
for (const pseudos of pseudoSets) {
|
|
825
|
+
for (const pseudos of alias ? pseudoSets : []) {
|
|
802
826
|
const pseudo = pseudos.length ? `:${pseudos.join(":")}` : "";
|
|
803
827
|
const body = [];
|
|
804
828
|
for (const edge of group.edges)
|
|
@@ -810,14 +834,15 @@ ${body.join(`
|
|
|
810
834
|
`)}
|
|
811
835
|
}`);
|
|
812
836
|
}
|
|
813
|
-
|
|
837
|
+
const recto = Object.entries(pinStyle(group, ["right"])).map(([prop, value]) => ` ${prop}: ${value};`).join("");
|
|
838
|
+
lines.push(`:where(.page, .spread)[data-gp-pin="${group.key}"][data-gp-pin][data-gp-pin][data-gp-pin] { page: ${group.genName};${recto} }`);
|
|
814
839
|
}
|
|
815
|
-
const
|
|
840
|
+
const pinCss = lines.join(`
|
|
816
841
|
`);
|
|
817
|
-
await page.evaluate(`window.__gp.addCss("gp-
|
|
842
|
+
await page.evaluate(`window.__gp.addCss("gp-pin-css", ${JSON.stringify(pinCss)})`);
|
|
818
843
|
model = extract(`${cssText}
|
|
819
|
-
${
|
|
820
|
-
log(
|
|
844
|
+
${pinCss}`);
|
|
845
|
+
log(`pinned art: ${pinRoots.length} page root(s) -> ${pinGroups.size} generated page context(s)`);
|
|
821
846
|
}
|
|
822
847
|
const { tier3Reasons } = classify(model);
|
|
823
848
|
const pseudoContexts = pagePseudoContexts(model);
|
|
@@ -842,11 +867,16 @@ ${flushCss}`);
|
|
|
842
867
|
return !!c && c !== "none" && c !== "normal";
|
|
843
868
|
});
|
|
844
869
|
};
|
|
845
|
-
const furnitureRoots =
|
|
846
|
-
const group =
|
|
870
|
+
const furnitureRoots = pinRoots.filter((root) => {
|
|
871
|
+
const group = pinGroups.get(root.key);
|
|
847
872
|
return pseudoContexts.some((pseudos) => relocationBoxes(group, pseudos).length > 0);
|
|
848
873
|
});
|
|
849
|
-
const
|
|
874
|
+
const relocationDiagnosed = new Set;
|
|
875
|
+
const sideRoots = pinRoots.filter((root) => {
|
|
876
|
+
const group = pinGroups.get(root.key);
|
|
877
|
+
const recto = JSON.stringify(pinStyle(group, ["right"]));
|
|
878
|
+
return [["left"], ["right", "first"]].some((pseudos) => JSON.stringify(pinStyle(group, pseudos)) !== recto);
|
|
879
|
+
});
|
|
850
880
|
const tier2 = synthesize({
|
|
851
881
|
model,
|
|
852
882
|
marks: opts.marks,
|
|
@@ -890,7 +920,7 @@ ${describe(widthOffenders.intrinsics)}`;
|
|
|
890
920
|
log(`WARNING: ${msg}`);
|
|
891
921
|
}
|
|
892
922
|
const rectoDecls = model.breaks.filter(isRectoVersoBreak);
|
|
893
|
-
const needsMeasure = tier3Reasons.length > 0 || consumedStrings(model).size > 0 || rectoDecls.length > 0 || model.counterResets.length > 0 || furnitureRoots.length > 0;
|
|
923
|
+
const needsMeasure = tier3Reasons.length > 0 || consumedStrings(model).size > 0 || rectoDecls.length > 0 || model.counterResets.length > 0 || furnitureRoots.length > 0 || sideRoots.length > 0;
|
|
894
924
|
let tier = tier2.geometry.bleed > 0 || tier2.geometry.slug > 0 ? 2 : 1;
|
|
895
925
|
let passes = 1;
|
|
896
926
|
let pageMap = {};
|
|
@@ -918,7 +948,7 @@ ${describe(widthOffenders.intrinsics)}`;
|
|
|
918
948
|
targets.add(s.id);
|
|
919
949
|
for (const s of resetSites)
|
|
920
950
|
targets.add(s.id);
|
|
921
|
-
for (const r of furnitureRoots)
|
|
951
|
+
for (const r of [...furnitureRoots, ...sideRoots])
|
|
922
952
|
targets.add(r.id);
|
|
923
953
|
await page.evaluate(`window.__gp.instrument(${JSON.stringify([...targets])})`);
|
|
924
954
|
const targetText = await page.evaluate(`window.__gp.targetTexts(${JSON.stringify([...targets])})`);
|
|
@@ -1004,8 +1034,12 @@ ${describe(widthOffenders.intrinsics)}`;
|
|
|
1004
1034
|
/* Tier 3 */
|
|
1005
1035
|
${mapCss}`;
|
|
1006
1036
|
}
|
|
1037
|
+
const pageAt = (id) => map[id] ?? predictedForResult?.pageMap[id];
|
|
1038
|
+
const pseudosAt = (physical) => [
|
|
1039
|
+
physical % 2 === 1 ? "right" : "left",
|
|
1040
|
+
...physical === 1 ? ["first"] : []
|
|
1041
|
+
];
|
|
1007
1042
|
if (furnitureRoots.length) {
|
|
1008
|
-
const pageAt = (id) => map[id] ?? predictedForResult?.pageMap[id];
|
|
1009
1043
|
const byName = new Map;
|
|
1010
1044
|
for (const s of sources) {
|
|
1011
1045
|
const p = pageAt(s.id);
|
|
@@ -1023,10 +1057,8 @@ ${mapCss}`;
|
|
|
1023
1057
|
const physical = pageAt(root.id);
|
|
1024
1058
|
if (!physical)
|
|
1025
1059
|
continue;
|
|
1026
|
-
const group =
|
|
1027
|
-
const pseudos =
|
|
1028
|
-
if (physical === 1)
|
|
1029
|
-
pseudos.push("first");
|
|
1060
|
+
const group = pinGroups.get(root.key);
|
|
1061
|
+
const pseudos = pseudosAt(physical);
|
|
1030
1062
|
const ctx = resolvePage(model, { name: group.authorPage, pseudos });
|
|
1031
1063
|
const g = ctx.geometry;
|
|
1032
1064
|
const eff = flushMargins(g.margin, group.edges);
|
|
@@ -1042,9 +1074,9 @@ ${mapCss}`;
|
|
|
1042
1074
|
}
|
|
1043
1075
|
});
|
|
1044
1076
|
if (!text) {
|
|
1045
|
-
if (!
|
|
1046
|
-
|
|
1047
|
-
diagnose("engine.
|
|
1077
|
+
if (!relocationDiagnosed.has(name)) {
|
|
1078
|
+
relocationDiagnosed.add(name);
|
|
1079
|
+
diagnose("engine.pin.margin-box", `@${name} sits on an edge a pinned image frees, and its content could not be ` + `re-homed into the page (unsupported content value: ${decls.content}). It will ` + `not print on that page — simplify the box's content, or pin the image to another edge.`);
|
|
1048
1080
|
}
|
|
1049
1081
|
continue;
|
|
1050
1082
|
}
|
|
@@ -1069,7 +1101,17 @@ ${mapCss}`;
|
|
|
1069
1101
|
items.push({ id: root.id, boxes });
|
|
1070
1102
|
}
|
|
1071
1103
|
if (items.length)
|
|
1072
|
-
await page.evaluate(`window.__gp.
|
|
1104
|
+
await page.evaluate(`window.__gp.setPinFurniture(${JSON.stringify(items)})`);
|
|
1105
|
+
}
|
|
1106
|
+
if (sideRoots.length) {
|
|
1107
|
+
const items = sideRoots.flatMap((root) => {
|
|
1108
|
+
const physical = pageAt(root.id);
|
|
1109
|
+
if (!physical)
|
|
1110
|
+
return [];
|
|
1111
|
+
return [{ id: root.id, style: pinStyle(pinGroups.get(root.key), pseudosAt(physical)) }];
|
|
1112
|
+
});
|
|
1113
|
+
if (items.length)
|
|
1114
|
+
await page.evaluate(`window.__gp.setPinGeometry(${JSON.stringify(items)})`);
|
|
1073
1115
|
}
|
|
1074
1116
|
};
|
|
1075
1117
|
const predicted = await predictPageMap(browser, url, AGENT, VIEWER, {
|
|
@@ -1432,12 +1474,12 @@ function shrinkScale(boxes, limitPx) {
|
|
|
1432
1474
|
async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreViewport) {
|
|
1433
1475
|
const contexts = [
|
|
1434
1476
|
resolvePage(model),
|
|
1435
|
-
...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--
|
|
1477
|
+
...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--pin-")).map((n) => resolvePage(model, { name: n }))
|
|
1436
1478
|
];
|
|
1437
1479
|
const contentPxOf = (c) => (c.geometry.width - c.geometry.margin.left - c.geometry.margin.right + bleedSlugExtensionPt) * 96 / 72;
|
|
1438
1480
|
const defaultLimitPx = contentPxOf(contexts[0]);
|
|
1439
1481
|
const namedLimits = {};
|
|
1440
|
-
model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--
|
|
1482
|
+
model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--pin-")).forEach((n) => {
|
|
1441
1483
|
namedLimits[n] = contentPxOf(resolvePage(model, { name: n }));
|
|
1442
1484
|
});
|
|
1443
1485
|
const widths = [...new Set([defaultLimitPx, ...Object.values(namedLimits)])].sort((a, b) => a - b);
|
|
@@ -1624,7 +1666,7 @@ async function predictPageMap(browser, url, agentScript, viewerScript, args, she
|
|
|
1624
1666
|
await page.waitForReady();
|
|
1625
1667
|
await page.evaluate(`window.__GP_MANUAL__ = true;`);
|
|
1626
1668
|
await page.evaluate(viewerScript);
|
|
1627
|
-
await page.evaluate(`window.__gp.
|
|
1669
|
+
await page.evaluate(`window.__gp.pinRoots()`);
|
|
1628
1670
|
await page.evaluate(`window.__gp.stringSources(${JSON.stringify(args.stringSets)})`);
|
|
1629
1671
|
if (args.rectoDecls.length)
|
|
1630
1672
|
await page.evaluate(`window.__gp.forcedBreakSites(${JSON.stringify(args.rectoDecls)})`);
|
|
@@ -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-13dfax80.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-jr30yw8t.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-mrdnwktc.js";
|
|
170
170
|
|
|
171
171
|
// src/assets/templates/book/manifest.yaml
|
|
172
172
|
var manifest_default = "./manifest-n1gh3qw5.yaml";
|