gutterpress 0.11.20-alpha.3 → 0.11.20-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/api/index.js +2 -2
  2. package/dist/{build-a8ycsg80.js → build-8ffhvydf.js} +4 -4
  3. package/dist/{cli-hn9pk0hp.js → cli-553ce1d4.js} +1 -1
  4. package/dist/{cli-y9bcya7r.js → cli-6xym15vm.js} +2 -2
  5. package/dist/{cli-x4p99w8d.js → cli-cyej3p9v.js} +83 -41
  6. package/dist/{cli-9k2tb493.js → cli-sc5t7c74.js} +116 -43
  7. package/dist/cli.js +12 -12
  8. package/dist/{doctor-wbjkrcpc.js → doctor-gyes0hxt.js} +2 -2
  9. package/dist/engine/compiler/build.d.ts +1 -1
  10. package/dist/engine/shared/margin-box-support.d.ts +2 -2
  11. package/dist/engine/shared/pin-edges.d.ts +127 -0
  12. package/dist/engine/shared/print-area.d.ts +73 -0
  13. package/dist/{engine-yxnnp3hx.js → engine-4rkhv5ga.js} +1 -1
  14. package/dist/{engine-fdtv01a2.js → engine-5fw55dfb.js} +2 -2
  15. package/dist/{ext-pesyrs68.js → ext-x61yptd1.js} +4 -4
  16. package/dist/{gutterpress-agent-cazqstr1.js → gutterpress-agent-yvd8w8my.js} +79 -13
  17. package/dist/{gutterpress-viewer-1yse8cx3.js → gutterpress-viewer-w7njnkj7.js} +257 -71
  18. package/dist/{index-tjvrchxj.js → index-bta8hc2q.js} +225 -152
  19. package/dist/{index-zagagnwq.js → index-crys9951.js} +3 -3
  20. package/dist/{index-r87y7wzw.js → index-yw16cfm8.js} +82 -40
  21. package/dist/index.js +3 -3
  22. package/dist/lib/extension-manifest.d.ts +13 -0
  23. package/dist/lib/markdown/assemble.d.ts +13 -3
  24. package/dist/lib/markdown/gutterpress-css.d.ts +49 -33
  25. package/dist/lib/markdown/index.d.ts +5 -0
  26. package/dist/{manifest.schema-c9x8912a.json → manifest.schema-c4wfpg6g.json} +9 -3
  27. package/dist/{new-8yah8z91.js → new-87dqcxtn.js} +4 -4
  28. package/dist/{preflight-8ccx4kdc.js → preflight-nb4wndqf.js} +4 -4
  29. package/dist/preview/file-watcher.d.ts +5 -10
  30. package/dist/{preview-w7v9w36q.js → preview-7bcr5j2p.js} +4 -4
  31. package/dist/{publish-g5nh5myh.js → publish-4qfm5ch9.js} +4 -4
  32. package/dist/render.js +73 -13
  33. package/dist/schema/manifest.types.d.ts +25 -9
  34. package/dist/{validate-1yh59x0x.js → validate-dzht9qxk.js} +4 -4
  35. package/package.json +1 -1
  36. package/dist/engine/shared/flush.d.ts +0 -59
package/dist/api/index.js CHANGED
@@ -137,11 +137,11 @@ import {
137
137
  testRemoteAccess,
138
138
  updateExtensions,
139
139
  validateProjectExtensions
140
- } from "../index-tjvrchxj.js";
140
+ } from "../index-bta8hc2q.js";
141
141
  import"../index-ht1bcqdd.js";
142
142
  import {
143
143
  BuildError
144
- } from "../index-zagagnwq.js";
144
+ } from "../index-crys9951.js";
145
145
  import"../index-sth219v1.js";
146
146
  import {
147
147
  DEFAULT_PRINT_OPTS,
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  runBuild,
3
3
  splitOutPath
4
- } from "./cli-9k2tb493.js";
4
+ } from "./cli-sc5t7c74.js";
5
5
  import {
6
6
  log
7
- } from "./cli-y9bcya7r.js";
7
+ } from "./cli-6xym15vm.js";
8
8
  import {
9
9
  UsageError,
10
10
  parseFormat,
11
11
  parsePdfxFlavor,
12
12
  rejectExtraPositionals,
13
13
  rejectUnknownFlags
14
- } from "./cli-hn9pk0hp.js";
14
+ } from "./cli-553ce1d4.js";
15
15
  import"./cli-ht1bcqdd.js";
16
- import"./cli-x4p99w8d.js";
16
+ import"./cli-cyej3p9v.js";
17
17
  import {
18
18
  BuildError
19
19
  } from "./cli-46ycxe6r.js";
@@ -4,7 +4,7 @@ import {
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "gutterpress",
7
- version: "0.11.20-alpha.3",
7
+ version: "0.11.20-alpha.5",
8
8
  description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
9
9
  author: "itlackey",
10
10
  license: "MPL-2.0",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./cli-hn9pk0hp.js";
3
+ } from "./cli-553ce1d4.js";
4
4
  import {
5
5
  enhancedPath,
6
6
  execCapture,
@@ -685,4 +685,4 @@ async function getSystemDiagnostics() {
685
685
  };
686
686
  }
687
687
 
688
- export { setLogLevel, debug, info, warn, error, log, resolveGhostscript, transparentPages, findPostScriptShadingPages, stripAnnotations, planTransparentPages, flattenTransparentPages, stampCreator, convertToPdfxCmyk, PACKAGE_META, PACKAGE_VERSION, defaultConfigDir, FileTokenStore, getSystemDiagnostics };
688
+ export { setLogLevel, debug, info, warn, error, log, PACKAGE_META, PACKAGE_VERSION, resolveGhostscript, transparentPages, findPostScriptShadingPages, stripAnnotations, planTransparentPages, flattenTransparentPages, stampCreator, convertToPdfxCmyk, defaultConfigDir, FileTokenStore, getSystemDiagnostics };
@@ -567,14 +567,15 @@ function specificity(r) {
567
567
  return (r.name ? 2 : 0) + r.pseudos.length;
568
568
  }
569
569
 
570
- // src/engine/shared/flush.ts
571
- var FLUSH_EDGES = ["top", "right", "bottom", "left"];
572
- function flushKey(edges) {
573
- return FLUSH_EDGES.filter((e) => edges.includes(e)).map((e) => e[0]).join("");
570
+ // src/engine/shared/pin-edges.ts
571
+ var PIN_EDGES = ["top", "right", "bottom", "left"];
572
+ var EDGE_PIN_SELECTOR = PIN_EDGES.map((edge) => `.gp-pin.gp-${edge}`).join(", ");
573
+ function pinKey(edges) {
574
+ return PIN_EDGES.filter((e) => edges.includes(e)).map((e) => e[0]).join("");
574
575
  }
575
- function flushPageName(authorPage, edges) {
576
+ function pinPageName(authorPage, edges) {
576
577
  const safe = authorPage ? authorPage.replace(/[^A-Za-z0-9_-]/g, "_") : "";
577
- return `gp--flush${safe ? `-${safe}` : ""}-${flushKey(edges)}`;
578
+ return `gp--pin${safe ? `-${safe}` : ""}-${pinKey(edges)}`;
578
579
  }
579
580
  function flushMargins(margin, edges) {
580
581
  return {
@@ -584,6 +585,23 @@ function flushMargins(margin, edges) {
584
585
  left: edges.includes("left") ? 0 : margin.left
585
586
  };
586
587
  }
588
+ function pinInsets(area, side, edges) {
589
+ const binding = side === "recto" ? "left" : "right";
590
+ const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.gutter : area.bleed + area.artSafe;
591
+ return { top: inset("top"), right: inset("right"), bottom: inset("bottom"), left: inset("left") };
592
+ }
593
+ var NO_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
594
+ function pinRootStyle(margin, area, side, edges, padding = NO_PADDING) {
595
+ const px = (pt) => pt * 96 / 72;
596
+ const inset = pinInsets(area, side, edges);
597
+ const style = { "box-decoration-break": "clone" };
598
+ for (const edge of PIN_EDGES)
599
+ if (edges.includes(edge))
600
+ style[`padding-${edge}`] = `${px(margin[edge]) + padding[edge]}px`;
601
+ for (const edge of PIN_EDGES)
602
+ style[`--gp-pin-${edge}`] = `${px(inset[edge])}px`;
603
+ return style;
604
+ }
587
605
  function marginBoxesOnEdges(edges) {
588
606
  const owners = {
589
607
  "top-left-corner": ["top", "left"],
@@ -1116,7 +1134,7 @@ import { fileURLToPath } from "node:url";
1116
1134
  var favicon_default = "./favicon-272ga6y0.ico";
1117
1135
 
1118
1136
  // src/assets/manifest.schema.json
1119
- var manifest_schema_default = "./manifest.schema-c9x8912a.json";
1137
+ var manifest_schema_default = "./manifest.schema-c4wfpg6g.json";
1120
1138
 
1121
1139
  // src/assets/preview/scripts/preview-interface.js
1122
1140
  var preview_interface_default = "./preview-interface-nnmrxyqm.js";
@@ -1131,10 +1149,10 @@ var preview_shell_default = "./preview-shell-wk9k3gcd.js";
1131
1149
  var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
1132
1150
 
1133
1151
  // src/assets/engine/gutterpress-viewer.js
1134
- var gutterpress_viewer_default = "./gutterpress-viewer-1yse8cx3.js";
1152
+ var gutterpress_viewer_default = "./gutterpress-viewer-w7njnkj7.js";
1135
1153
 
1136
1154
  // src/assets/engine/gutterpress-agent.js
1137
- var gutterpress_agent_default = "./gutterpress-agent-cazqstr1.js";
1155
+ var gutterpress_agent_default = "./gutterpress-agent-yvd8w8my.js";
1138
1156
 
1139
1157
  // src/assets/templates/book/manifest.yaml
1140
1158
  var manifest_default = "./manifest-n1gh3qw5.yaml";
@@ -1652,25 +1670,31 @@ async function build(opts) {
1652
1670
  await page.send("Emulation.setDeviceMetricsOverride", sheetViewport);
1653
1671
  await page.send("Emulation.setEmulatedMedia", { media: "print" });
1654
1672
  log(`print media emulated for audits and measurement`);
1655
- const flushRoots = await page.evaluate(`window.__gp.flushRoots()`);
1656
- const flushGroups = new Map;
1657
- for (const root of flushRoots) {
1658
- if (flushGroups.has(root.key))
1673
+ const pinRoots = await page.evaluate(`window.__gp.pinRoots()`);
1674
+ const pinGroups = new Map;
1675
+ for (const root of pinRoots) {
1676
+ if (pinGroups.has(root.key))
1659
1677
  continue;
1660
1678
  const authorPage = root.page === "auto" ? undefined : root.page;
1661
- flushGroups.set(root.key, {
1679
+ pinGroups.set(root.key, {
1662
1680
  authorPage,
1663
1681
  edges: root.edges,
1664
- genName: flushPageName(authorPage, root.edges),
1682
+ padding: root.padding,
1683
+ genName: pinPageName(authorPage, root.edges),
1665
1684
  key: root.key
1666
1685
  });
1667
1686
  }
1668
- if (flushGroups.size) {
1687
+ const printArea = pinRoots.length ? await page.evaluate(`window.__gp.printArea()`) : null;
1688
+ const pinStyle = (group, pseudos) => pinRootStyle(resolvePage(model, { name: group.authorPage, pseudos }).geometry.margin, printArea, pseudos.includes("left") ? "verso" : "recto", group.edges, group.padding);
1689
+ if (pinGroups.size) {
1669
1690
  const lines = [];
1670
- for (const group of flushGroups.values()) {
1691
+ const aliased = new Set;
1692
+ for (const group of pinGroups.values()) {
1693
+ const alias = !aliased.has(group.genName);
1694
+ aliased.add(group.genName);
1671
1695
  const relocated = new Set(marginBoxesOnEdges(group.edges));
1672
1696
  const pseudoSets = [[]];
1673
- if (group.authorPage) {
1697
+ if (alias && group.authorPage) {
1674
1698
  for (const rule of model.pageRules) {
1675
1699
  if (rule.name !== group.authorPage)
1676
1700
  continue;
@@ -1694,7 +1718,7 @@ ${body.join(`
1694
1718
  }`);
1695
1719
  }
1696
1720
  }
1697
- for (const pseudos of pseudoSets) {
1721
+ for (const pseudos of alias ? pseudoSets : []) {
1698
1722
  const pseudo = pseudos.length ? `:${pseudos.join(":")}` : "";
1699
1723
  const body = [];
1700
1724
  for (const edge of group.edges)
@@ -1706,14 +1730,15 @@ ${body.join(`
1706
1730
  `)}
1707
1731
  }`);
1708
1732
  }
1709
- lines.push(`:where(.page, .spread)[data-gp-flush="${group.key}"][data-gp-flush][data-gp-flush][data-gp-flush] { page: ${group.genName}; }`);
1733
+ const recto = Object.entries(pinStyle(group, ["right"])).map(([prop, value]) => ` ${prop}: ${value};`).join("");
1734
+ lines.push(`:where(.page, .spread)[data-gp-pin="${group.key}"][data-gp-pin][data-gp-pin][data-gp-pin] { page: ${group.genName};${recto} }`);
1710
1735
  }
1711
- const flushCss = lines.join(`
1736
+ const pinCss = lines.join(`
1712
1737
  `);
1713
- await page.evaluate(`window.__gp.addCss("gp-flush-css", ${JSON.stringify(flushCss)})`);
1738
+ await page.evaluate(`window.__gp.addCss("gp-pin-css", ${JSON.stringify(pinCss)})`);
1714
1739
  model = extract(`${cssText}
1715
- ${flushCss}`);
1716
- log(`.gp-flush: ${flushRoots.length} pinned root(s) -> ${flushGroups.size} generated page context(s)`);
1740
+ ${pinCss}`);
1741
+ log(`pinned art: ${pinRoots.length} page root(s) -> ${pinGroups.size} generated page context(s)`);
1717
1742
  }
1718
1743
  const { tier3Reasons } = classify(model);
1719
1744
  const pseudoContexts = pagePseudoContexts(model);
@@ -1738,11 +1763,16 @@ ${flushCss}`);
1738
1763
  return !!c && c !== "none" && c !== "normal";
1739
1764
  });
1740
1765
  };
1741
- const furnitureRoots = flushRoots.filter((root) => {
1742
- const group = flushGroups.get(root.key);
1766
+ const furnitureRoots = pinRoots.filter((root) => {
1767
+ const group = pinGroups.get(root.key);
1743
1768
  return pseudoContexts.some((pseudos) => relocationBoxes(group, pseudos).length > 0);
1744
1769
  });
1745
- const flushDiagnosed = new Set;
1770
+ const relocationDiagnosed = new Set;
1771
+ const sideRoots = pinRoots.filter((root) => {
1772
+ const group = pinGroups.get(root.key);
1773
+ const recto = JSON.stringify(pinStyle(group, ["right"]));
1774
+ return [["left"], ["right", "first"]].some((pseudos) => JSON.stringify(pinStyle(group, pseudos)) !== recto);
1775
+ });
1746
1776
  const tier2 = synthesize({
1747
1777
  model,
1748
1778
  marks: opts.marks,
@@ -1786,7 +1816,7 @@ ${describe(widthOffenders.intrinsics)}`;
1786
1816
  log(`WARNING: ${msg}`);
1787
1817
  }
1788
1818
  const rectoDecls = model.breaks.filter(isRectoVersoBreak);
1789
- const needsMeasure = tier3Reasons.length > 0 || consumedStrings(model).size > 0 || rectoDecls.length > 0 || model.counterResets.length > 0 || furnitureRoots.length > 0;
1819
+ const needsMeasure = tier3Reasons.length > 0 || consumedStrings(model).size > 0 || rectoDecls.length > 0 || model.counterResets.length > 0 || furnitureRoots.length > 0 || sideRoots.length > 0;
1790
1820
  let tier = tier2.geometry.bleed > 0 || tier2.geometry.slug > 0 ? 2 : 1;
1791
1821
  let passes = 1;
1792
1822
  let pageMap = {};
@@ -1814,7 +1844,7 @@ ${describe(widthOffenders.intrinsics)}`;
1814
1844
  targets.add(s.id);
1815
1845
  for (const s of resetSites)
1816
1846
  targets.add(s.id);
1817
- for (const r of furnitureRoots)
1847
+ for (const r of [...furnitureRoots, ...sideRoots])
1818
1848
  targets.add(r.id);
1819
1849
  await page.evaluate(`window.__gp.instrument(${JSON.stringify([...targets])})`);
1820
1850
  const targetText = await page.evaluate(`window.__gp.targetTexts(${JSON.stringify([...targets])})`);
@@ -1900,8 +1930,12 @@ ${describe(widthOffenders.intrinsics)}`;
1900
1930
  /* Tier 3 */
1901
1931
  ${mapCss}`;
1902
1932
  }
1933
+ const pageAt = (id) => map[id] ?? predictedForResult?.pageMap[id];
1934
+ const pseudosAt = (physical) => [
1935
+ physical % 2 === 1 ? "right" : "left",
1936
+ ...physical === 1 ? ["first"] : []
1937
+ ];
1903
1938
  if (furnitureRoots.length) {
1904
- const pageAt = (id) => map[id] ?? predictedForResult?.pageMap[id];
1905
1939
  const byName = new Map;
1906
1940
  for (const s of sources) {
1907
1941
  const p = pageAt(s.id);
@@ -1919,10 +1953,8 @@ ${mapCss}`;
1919
1953
  const physical = pageAt(root.id);
1920
1954
  if (!physical)
1921
1955
  continue;
1922
- const group = flushGroups.get(root.key);
1923
- const pseudos = [physical % 2 === 1 ? "right" : "left"];
1924
- if (physical === 1)
1925
- pseudos.push("first");
1956
+ const group = pinGroups.get(root.key);
1957
+ const pseudos = pseudosAt(physical);
1926
1958
  const ctx = resolvePage(model, { name: group.authorPage, pseudos });
1927
1959
  const g = ctx.geometry;
1928
1960
  const eff = flushMargins(g.margin, group.edges);
@@ -1938,9 +1970,9 @@ ${mapCss}`;
1938
1970
  }
1939
1971
  });
1940
1972
  if (!text) {
1941
- if (!flushDiagnosed.has(name)) {
1942
- flushDiagnosed.add(name);
1943
- diagnose("engine.flush.margin-box", `@${name} sits on an edge a .gp-flush pin 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 drop .gp-flush there.`);
1973
+ if (!relocationDiagnosed.has(name)) {
1974
+ relocationDiagnosed.add(name);
1975
+ 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.`);
1944
1976
  }
1945
1977
  continue;
1946
1978
  }
@@ -1965,7 +1997,17 @@ ${mapCss}`;
1965
1997
  items.push({ id: root.id, boxes });
1966
1998
  }
1967
1999
  if (items.length)
1968
- await page.evaluate(`window.__gp.setFlushFurniture(${JSON.stringify(items)})`);
2000
+ await page.evaluate(`window.__gp.setPinFurniture(${JSON.stringify(items)})`);
2001
+ }
2002
+ if (sideRoots.length) {
2003
+ const items = sideRoots.flatMap((root) => {
2004
+ const physical = pageAt(root.id);
2005
+ if (!physical)
2006
+ return [];
2007
+ return [{ id: root.id, style: pinStyle(pinGroups.get(root.key), pseudosAt(physical)) }];
2008
+ });
2009
+ if (items.length)
2010
+ await page.evaluate(`window.__gp.setPinGeometry(${JSON.stringify(items)})`);
1969
2011
  }
1970
2012
  };
1971
2013
  const predicted = await predictPageMap(browser, url, AGENT, VIEWER, {
@@ -2328,12 +2370,12 @@ function shrinkScale(boxes, limitPx) {
2328
2370
  async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreViewport) {
2329
2371
  const contexts = [
2330
2372
  resolvePage(model),
2331
- ...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--flush-")).map((n) => resolvePage(model, { name: n }))
2373
+ ...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--pin-")).map((n) => resolvePage(model, { name: n }))
2332
2374
  ];
2333
2375
  const contentPxOf = (c) => (c.geometry.width - c.geometry.margin.left - c.geometry.margin.right + bleedSlugExtensionPt) * 96 / 72;
2334
2376
  const defaultLimitPx = contentPxOf(contexts[0]);
2335
2377
  const namedLimits = {};
2336
- model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--flush-")).forEach((n) => {
2378
+ model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--pin-")).forEach((n) => {
2337
2379
  namedLimits[n] = contentPxOf(resolvePage(model, { name: n }));
2338
2380
  });
2339
2381
  const widths = [...new Set([defaultLimitPx, ...Object.values(namedLimits)])].sort((a, b) => a - b);
@@ -2520,7 +2562,7 @@ async function predictPageMap(browser, url, agentScript, viewerScript, args, she
2520
2562
  await page.waitForReady();
2521
2563
  await page.evaluate(`window.__GP_MANUAL__ = true;`);
2522
2564
  await page.evaluate(viewerScript);
2523
- await page.evaluate(`window.__gp.flushRoots()`);
2565
+ await page.evaluate(`window.__gp.pinRoots()`);
2524
2566
  await page.evaluate(`window.__gp.stringSources(${JSON.stringify(args.stringSets)})`);
2525
2567
  if (args.rectoDecls.length)
2526
2568
  await page.evaluate(`window.__gp.forcedBreakSites(${JSON.stringify(args.rectoDecls)})`);