gutterpress 0.11.17-alpha.5 → 0.11.17-alpha.6
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-jr9mqwgr.js → build-yswp3npj.js} +4 -4
- package/dist/{cli-5sg6hcqa.js → cli-0wtnw98y.js} +1 -1
- package/dist/{cli-82tvm0sg.js → cli-an3pxzzk.js} +77 -110
- package/dist/{cli-2xpwjanr.js → cli-jjbeqx94.js} +1 -1
- package/dist/{cli-c3enmb58.js → cli-ycbg7mxk.js} +4 -4
- package/dist/cli.js +12 -12
- package/dist/{components-dhgv2sm7.yaml → components-zzqdpt3m.yaml} +1 -1
- package/dist/{doctor-zxk3pamr.js → doctor-xjgxr88y.js} +2 -2
- package/dist/{engine-eactk9nn.js → engine-5d1rpxxq.js} +2 -2
- package/dist/{engine-63r7pxsy.js → engine-yf2w9hj7.js} +1 -1
- package/dist/{ext-4vapkh0p.js → ext-n664e0ka.js} +4 -4
- package/dist/{gutterpress-viewer-1n793gwd.js → gutterpress-viewer-ez7k4ha7.js} +19 -1
- package/dist/{index-mb8mzwye.js → index-09h3n36d.js} +2 -2
- package/dist/{index-5ez30g3a.js → index-2vd5b3vy.js} +76 -109
- package/dist/{index-5gp6mkmf.js → index-vmcfahe2.js} +3 -3
- package/dist/index.js +3 -3
- package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
- package/dist/lib/markdown/markers.d.ts +14 -6
- package/dist/{new-hzs75cmd.js → new-8xwac8nd.js} +4 -4
- package/dist/{page-templates-7md4ev7d.css → page-templates-tx9ryt19.css} +4 -11
- package/dist/{preflight-4k8dtsfs.js → preflight-62c2r37w.js} +4 -4
- package/dist/{preview-whg4rwg6.js → preview-qdby30fx.js} +4 -4
- package/dist/{publish-4vtd7qve.js → publish-v9tdq7kc.js} +4 -4
- package/dist/render.js +73 -106
- package/dist/{validate-c32mm2bh.js → validate-9nszbckg.js} +4 -4
- package/package.json +1 -1
package/dist/api/index.js
CHANGED
|
@@ -135,11 +135,11 @@ import {
|
|
|
135
135
|
testRemoteAccess,
|
|
136
136
|
updateExtensions,
|
|
137
137
|
validateProjectExtensions
|
|
138
|
-
} from "../index-
|
|
138
|
+
} from "../index-2vd5b3vy.js";
|
|
139
139
|
import"../index-ht1bcqdd.js";
|
|
140
140
|
import {
|
|
141
141
|
BuildError
|
|
142
|
-
} from "../index-
|
|
142
|
+
} from "../index-vmcfahe2.js";
|
|
143
143
|
import {
|
|
144
144
|
DEFAULT_PRINT_OPTS,
|
|
145
145
|
assertMilestone,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runBuild,
|
|
3
3
|
splitOutPath
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-an3pxzzk.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-0wtnw98y.js";
|
|
8
8
|
import {
|
|
9
9
|
UsageError,
|
|
10
10
|
parseFormat,
|
|
11
11
|
parsePdfxFlavor,
|
|
12
12
|
rejectExtraPositionals,
|
|
13
13
|
rejectUnknownFlags
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-jjbeqx94.js";
|
|
15
15
|
import"./cli-ht1bcqdd.js";
|
|
16
|
-
import"./cli-
|
|
16
|
+
import"./cli-ycbg7mxk.js";
|
|
17
17
|
import {
|
|
18
18
|
BuildError
|
|
19
19
|
} from "./cli-46ycxe6r.js";
|
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
stampCreator,
|
|
14
14
|
stripAnnotations,
|
|
15
15
|
warn
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-0wtnw98y.js";
|
|
17
17
|
import {
|
|
18
18
|
DEBOUNCE,
|
|
19
19
|
UsageError,
|
|
20
20
|
resolvePort
|
|
21
|
-
} from "./cli-
|
|
21
|
+
} from "./cli-jjbeqx94.js";
|
|
22
22
|
import {
|
|
23
23
|
blackTextToGray
|
|
24
24
|
} from "./cli-ht1bcqdd.js";
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
getAssetPath,
|
|
28
28
|
getAssetsDir,
|
|
29
29
|
lastPageMode
|
|
30
|
-
} from "./cli-
|
|
30
|
+
} from "./cli-ycbg7mxk.js";
|
|
31
31
|
import {
|
|
32
32
|
BuildError,
|
|
33
33
|
EXIT_CODES
|
|
@@ -1169,6 +1169,16 @@ function resolveContainerShape(name, pluginName, decl) {
|
|
|
1169
1169
|
...check
|
|
1170
1170
|
};
|
|
1171
1171
|
}
|
|
1172
|
+
function presetVariantOf(name, pluginName, rawDecl) {
|
|
1173
|
+
const preset = rawDecl.preset !== undefined ? rawDecl.preset : {};
|
|
1174
|
+
if (typeof preset !== "object" || preset === null || Array.isArray(preset)) {
|
|
1175
|
+
throw new Error(`Plugin "${pluginName}"'s marker "@${name}" has a \`preset\` that is not a plain object.`);
|
|
1176
|
+
}
|
|
1177
|
+
if (preset.variant !== undefined && typeof preset.variant !== "string") {
|
|
1178
|
+
throw new Error(`Plugin "${pluginName}"'s marker "@${name}" has a \`preset.variant\` that is not a string.`);
|
|
1179
|
+
}
|
|
1180
|
+
return preset.variant;
|
|
1181
|
+
}
|
|
1172
1182
|
function resolveMarkerDeclaration(name, rawDecl, rawRegistry, originOf) {
|
|
1173
1183
|
const pluginName = originOf.get(name);
|
|
1174
1184
|
if (typeof rawDecl !== "object" || rawDecl === null || Array.isArray(rawDecl)) {
|
|
@@ -1197,22 +1207,22 @@ function resolveMarkerDeclaration(name, rawDecl, rawRegistry, originOf) {
|
|
|
1197
1207
|
if (targetRaw.alias !== undefined) {
|
|
1198
1208
|
throw new Error(`Plugin "${pluginName}"'s marker "@${name}" aliases "@${rawDecl.alias}", which is itself an alias. ` + `Chained aliases are not supported — alias the base marker directly.`);
|
|
1199
1209
|
}
|
|
1200
|
-
const preset = rawDecl.preset !== undefined ? rawDecl.preset : {};
|
|
1201
|
-
if (typeof preset !== "object" || preset === null || Array.isArray(preset)) {
|
|
1202
|
-
throw new Error(`Plugin "${pluginName}"'s marker "@${name}" has a \`preset\` that is not a plain object.`);
|
|
1203
|
-
}
|
|
1204
|
-
if (preset.variant !== undefined && typeof preset.variant !== "string") {
|
|
1205
|
-
throw new Error(`Plugin "${pluginName}"'s marker "@${name}" has a \`preset.variant\` that is not a string.`);
|
|
1206
|
-
}
|
|
1207
1210
|
const container = resolveContainerShape(rawDecl.alias, originOf.get(rawDecl.alias), targetRaw);
|
|
1208
|
-
return { name, baseKind: rawDecl.alias, presetVariant:
|
|
1211
|
+
return { name, baseKind: rawDecl.alias, presetVariant: presetVariantOf(name, pluginName, rawDecl), ...container };
|
|
1209
1212
|
}
|
|
1210
|
-
|
|
1213
|
+
const presetVariant = presetVariantOf(name, pluginName, rawDecl);
|
|
1214
|
+
return {
|
|
1215
|
+
name,
|
|
1216
|
+
baseKind: name,
|
|
1217
|
+
...presetVariant !== undefined ? { presetVariant } : {},
|
|
1218
|
+
...resolveContainerShape(name, pluginName, rawDecl)
|
|
1219
|
+
};
|
|
1211
1220
|
}
|
|
1212
1221
|
var CORE_MARKER_OWNER = "Gutterpress";
|
|
1213
1222
|
var CORE_DECLARED_MARKERS = {
|
|
1214
1223
|
columns: {
|
|
1215
1224
|
class: "gp-columns",
|
|
1225
|
+
preset: { variant: "2" },
|
|
1216
1226
|
variants: { 1: "gp-columns-1", 2: "gp-columns-2", 3: "gp-columns-3", 4: "gp-columns-4", 5: "gp-columns-5" }
|
|
1217
1227
|
}
|
|
1218
1228
|
};
|
|
@@ -1388,20 +1398,35 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1388
1398
|
const at = declaredFrameIndex(kind);
|
|
1389
1399
|
if (at === -1)
|
|
1390
1400
|
return false;
|
|
1391
|
-
|
|
1392
|
-
const frame = declaredFrames.pop();
|
|
1393
|
-
out.push(new state.Token("layout_component_close", frame.tag, -1));
|
|
1394
|
-
}
|
|
1401
|
+
drainDeclaredFrames(at);
|
|
1395
1402
|
return true;
|
|
1396
1403
|
}
|
|
1397
|
-
function
|
|
1398
|
-
|
|
1404
|
+
function sectionAbove(length) {
|
|
1405
|
+
const section = stack.get("section");
|
|
1406
|
+
return !!section && section.inColumns && declaredFrameIndex("columns") === length - 1;
|
|
1407
|
+
}
|
|
1408
|
+
function sectionHostDepth() {
|
|
1409
|
+
const section = stack.get("section");
|
|
1410
|
+
if (section && !section.inColumns)
|
|
1411
|
+
return 0;
|
|
1412
|
+
return declaredFrameIndex("columns") + 1;
|
|
1413
|
+
}
|
|
1414
|
+
function drainDeclaredFrames(keep = 0) {
|
|
1415
|
+
while (declaredFrames.length > keep) {
|
|
1416
|
+
if (sectionAbove(declaredFrames.length)) {
|
|
1417
|
+
stack.close("section");
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1399
1420
|
const frame = declaredFrames.pop();
|
|
1400
1421
|
out.push(new state.Token("layout_component_close", frame.tag, -1));
|
|
1401
1422
|
}
|
|
1402
1423
|
}
|
|
1403
1424
|
function drainDeclaredFramesAtEof() {
|
|
1404
1425
|
while (declaredFrames.length) {
|
|
1426
|
+
if (sectionAbove(declaredFrames.length)) {
|
|
1427
|
+
stack.close("section");
|
|
1428
|
+
continue;
|
|
1429
|
+
}
|
|
1405
1430
|
const frame = declaredFrames.pop();
|
|
1406
1431
|
if (!frame.decl.autoCloseAtEof) {
|
|
1407
1432
|
warn2(state.env, frame.line || 0, "declared_marker_eof_close", `An open @${frame.kind} reached end-of-document; closing it automatically. Add ` + `@end-${frame.kind} to close it explicitly, or declare autoCloseAt: ["eof"] on this ` + `marker if running to end-of-document is expected.`, null);
|
|
@@ -1545,7 +1570,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1545
1570
|
__component: { component: meta.kind, kind: decl.baseKind, variant, attrs }
|
|
1546
1571
|
};
|
|
1547
1572
|
}
|
|
1548
|
-
function openSection(meta) {
|
|
1573
|
+
function openSection(meta, inColumns = false) {
|
|
1549
1574
|
const t = new state.Token("layout_section_open", "div", 1);
|
|
1550
1575
|
const component = meta.__component || null;
|
|
1551
1576
|
addClasses(t, "section", meta.attrs && meta.attrs.class ? meta.attrs.class : "");
|
|
@@ -1558,25 +1583,11 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1558
1583
|
kind: "section",
|
|
1559
1584
|
classes: meta.attrs && meta.attrs.class || "",
|
|
1560
1585
|
sawContent: false,
|
|
1586
|
+
...inColumns ? { inColumns: true } : {},
|
|
1561
1587
|
meta: { name: meta.name || null, attrs: { ...meta.attrs || {} }, component },
|
|
1562
1588
|
openToken: t
|
|
1563
1589
|
}, t);
|
|
1564
1590
|
}
|
|
1565
|
-
function breakHost() {
|
|
1566
|
-
return stack.get("section") || stack.get("page") || stack.get("spread");
|
|
1567
|
-
}
|
|
1568
|
-
function gridClassOf(frame) {
|
|
1569
|
-
if (!frame || !frame.classes)
|
|
1570
|
-
return null;
|
|
1571
|
-
return frame.classes.split(/\s+/).find((c) => c.startsWith("gp-grid-")) || null;
|
|
1572
|
-
}
|
|
1573
|
-
function warnBreakInsideGrid(kind, line, meta) {
|
|
1574
|
-
const host = breakHost();
|
|
1575
|
-
const gridClass = gridClassOf(host);
|
|
1576
|
-
if (!gridClass)
|
|
1577
|
-
return;
|
|
1578
|
-
warn2(state.env, line, "break_inside_grid", `@${kind} inside a grid container: the enclosing @${host.kind} carries .${gridClass}, so this break's <div> becomes a grid ITEM — it takes a cell of its own, corrupts the grid's placement, and print and the live preview then disagree about which page the content after it lands on. Move the break outside the grid @${host.kind}, or remove it — grid rows already flow and fragment across pages on their own.`, meta);
|
|
1579
|
-
}
|
|
1580
1591
|
function warnIfEmptyDecoratedSection(closingKind, closingLine) {
|
|
1581
1592
|
const sec = stack.get("section");
|
|
1582
1593
|
if (!sec || sec.sawContent)
|
|
@@ -1641,14 +1652,15 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1641
1652
|
continue;
|
|
1642
1653
|
}
|
|
1643
1654
|
if (kind === "section") {
|
|
1644
|
-
|
|
1655
|
+
const keep = sectionHostDepth();
|
|
1656
|
+
drainDeclaredFrames(keep);
|
|
1645
1657
|
warnIfEmptyDecoratedSection("section", line);
|
|
1646
1658
|
stack.close("section");
|
|
1647
1659
|
const spread = stack.get("spread");
|
|
1648
1660
|
if (spread && spread.noPagesYet) {
|
|
1649
1661
|
warn2(state.env, line, "spread_without_pages", "@section inside a spread without an explicit @page. Allowed (adhoc spread), but explicit @page markers give stronger control.", meta);
|
|
1650
1662
|
}
|
|
1651
|
-
openSection(meta);
|
|
1663
|
+
openSection(meta, keep > 0);
|
|
1652
1664
|
continue;
|
|
1653
1665
|
}
|
|
1654
1666
|
if (kind === "continue") {
|
|
@@ -1657,7 +1669,8 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1657
1669
|
warn2(state.env, line, "continue_without_section", "@continue used without an open @section; ignoring marker.", meta);
|
|
1658
1670
|
continue;
|
|
1659
1671
|
}
|
|
1660
|
-
|
|
1672
|
+
const keep = sectionHostDepth();
|
|
1673
|
+
drainDeclaredFrames(keep);
|
|
1661
1674
|
const contMeta = {
|
|
1662
1675
|
name: section.meta.name,
|
|
1663
1676
|
attrs: { ...section.meta.attrs || {} }
|
|
@@ -1672,11 +1685,10 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1672
1685
|
cls.push("gp-continued");
|
|
1673
1686
|
contMeta.attrs.class = cls.join(" ");
|
|
1674
1687
|
stack.close("section");
|
|
1675
|
-
openSection(contMeta);
|
|
1688
|
+
openSection(contMeta, keep > 0);
|
|
1676
1689
|
continue;
|
|
1677
1690
|
}
|
|
1678
1691
|
if (kind === "page-break") {
|
|
1679
|
-
warnBreakInsideGrid("page-break", line, meta);
|
|
1680
1692
|
const t = new state.Token("layout_page_break", "div", 0);
|
|
1681
1693
|
t.meta = { line };
|
|
1682
1694
|
t.attrSet("class", "gp-page-break");
|
|
@@ -1685,7 +1697,6 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1685
1697
|
continue;
|
|
1686
1698
|
}
|
|
1687
1699
|
if (kind === "column-break") {
|
|
1688
|
-
warnBreakInsideGrid("column-break", line, meta);
|
|
1689
1700
|
const t = new state.Token("layout_column_break", "div", 0);
|
|
1690
1701
|
t.meta = { line };
|
|
1691
1702
|
t.attrSet("class", "gp-column-break");
|
|
@@ -1694,7 +1705,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1694
1705
|
continue;
|
|
1695
1706
|
}
|
|
1696
1707
|
if (kind === "end-section") {
|
|
1697
|
-
drainDeclaredFrames();
|
|
1708
|
+
drainDeclaredFrames(sectionHostDepth());
|
|
1698
1709
|
warnIfEmptyDecoratedSection("end-section", line);
|
|
1699
1710
|
stack.close("section");
|
|
1700
1711
|
continue;
|
|
@@ -1792,11 +1803,20 @@ body { margin: 0; }
|
|
|
1792
1803
|
.gp-column-break { break-after: column; height: 0; font-size: 0; line-height: 0; visibility: hidden; }
|
|
1793
1804
|
|
|
1794
1805
|
:where(h1,h2,h3,h4,h5,h6) { break-after: avoid; }
|
|
1806
|
+
/* A lead-in paragraph ("**ROLL A DIE!**" above a roll table, "You will need:"
|
|
1807
|
+
above a list) stays with the table or list it introduces, the way a heading
|
|
1808
|
+
stays with what follows it -- otherwise the label can end a column or page
|
|
1809
|
+
with its table starting on the next (#370). Standard break-after; the
|
|
1810
|
+
:has() selector is Chromium's own. :where() keeps specificity at zero so an
|
|
1811
|
+
author rule such as p { break-after: auto } wins. Deliberately table/ul/ol only,
|
|
1812
|
+
also when a @section wraps it (the second rule): the lead-in then keeps with
|
|
1813
|
+
the section that opens with the table or list. */
|
|
1814
|
+
:where(p):has(+ :where(table, ul, ol)) { break-after: avoid; }
|
|
1815
|
+
:where(p):has(+ :where(.section) > :where(table, ul, ol):first-child) { break-after: avoid; }
|
|
1795
1816
|
:where(img, svg, video) { max-width: 100%; }
|
|
1796
1817
|
:where(p > img:only-child, figure > img) { width: fit-content; max-width: 100%; height: auto; vertical-align: bottom; }
|
|
1797
1818
|
:where(p) > :where(img:not([class])) { max-height: calc(var(--gp-content-h) - 4px); object-fit: contain; }
|
|
1798
1819
|
:where(figure) { break-inside: avoid; }
|
|
1799
|
-
:where(.section, figure) > :where(:first-child) { break-before: avoid; }
|
|
1800
1820
|
|
|
1801
1821
|
`;
|
|
1802
1822
|
|
|
@@ -1856,26 +1876,24 @@ var GUTTERPRESS_CSS = `
|
|
|
1856
1876
|
.gp-tight { --gp-gap: 0.5em; }
|
|
1857
1877
|
.gp-loose { --gp-gap: 2em; }
|
|
1858
1878
|
|
|
1859
|
-
/* column runs — plain CSS Multi-column,
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
every author who opens a section just to start a column run a panel they
|
|
1864
|
-
did not ask for, and the book then needs a reset rule to take it back.
|
|
1865
|
-
With a neutral primitive the author opts into columns and nothing else.
|
|
1879
|
+
/* column runs — plain CSS Multi-column, emitted by the core @columns marker
|
|
1880
|
+
(markers.js): @columns [1-5] ... @end-columns is the ONE way to lay
|
|
1881
|
+
content out in columns, and @column-break moves to the next column.
|
|
1882
|
+
The classes below are the CSS that marker emits, not author vocabulary.
|
|
1866
1883
|
|
|
1867
1884
|
Permanent vocabulary, not a shim: Chromium implements multicol natively
|
|
1868
1885
|
and these rules are the standard properties verbatim, so there is no
|
|
1869
1886
|
spec gap here to remove later. Deliberately minimal — column-fill is
|
|
1870
|
-
NOT set
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
wins because it comes later at the same specificity. */
|
|
1877
|
-
.gp-columns, .gp-columns-1, .gp-columns-2, .gp-columns-3, .gp-columns-4, .gp-columns-5 {
|
|
1887
|
+
NOT set (the CSS initial balance applies).
|
|
1888
|
+
Themes style a run through two tokens instead of writing column rules:
|
|
1889
|
+
--gp-column-gap default 1.5em
|
|
1890
|
+
--gp-column-rule default none (any column-rule shorthand value)
|
|
1891
|
+
Both hooks sit at zero specificity (:where), so any author rule wins.
|
|
1892
|
+
.gp-columns is two columns on its own; a count class (bare @columns
|
|
1893
|
+
emits gp-columns-2) wins because it comes later at the same specificity. */
|
|
1894
|
+
:where(.gp-columns, .gp-columns-1, .gp-columns-2, .gp-columns-3, .gp-columns-4, .gp-columns-5) {
|
|
1878
1895
|
column-gap: var(--gp-column-gap, 1.5em);
|
|
1896
|
+
column-rule: var(--gp-column-rule, none);
|
|
1879
1897
|
}
|
|
1880
1898
|
.gp-columns { columns: 2; }
|
|
1881
1899
|
.gp-columns-1 { columns: 1; }
|
|
@@ -1884,54 +1902,8 @@ var GUTTERPRESS_CSS = `
|
|
|
1884
1902
|
.gp-columns-4 { columns: 4; }
|
|
1885
1903
|
.gp-columns-5 { columns: 5; }
|
|
1886
1904
|
|
|
1887
|
-
/* the per-shape decisions the paragraph above deliberately leaves to the
|
|
1888
|
-
author, named instead of left as raw CSS every book was reinventing
|
|
1889
|
-
(CLAUDE.md §0: "behavior broadly useful to non-technical authors belongs
|
|
1890
|
-
in core").
|
|
1891
|
-
Permanent vocabulary, standard properties verbatim — same rationale as
|
|
1892
|
-
the column/grid runs above. One name each, no aliases:
|
|
1893
|
-
.gp-columns-all column-span: all a heading or block that
|
|
1894
|
-
spans every column in the
|
|
1895
|
-
run it sits inside.
|
|
1896
|
-
.gp-columns-flow column-fill: auto a run that FRAGMENTS across
|
|
1897
|
-
pages — every page's
|
|
1898
|
-
columns fill instead of
|
|
1899
|
-
only the last one
|
|
1900
|
-
balancing (the dead-column
|
|
1901
|
-
collapse the build's
|
|
1902
|
-
engine.multicol.dead-column
|
|
1903
|
-
warning names this fix
|
|
1904
|
-
for).
|
|
1905
|
-
.gp-columns-balanced column-fill: balance a run that fits on ONE
|
|
1906
|
-
page (the CSS initial
|
|
1907
|
-
value — ragged columns
|
|
1908
|
-
would be wrong here). */
|
|
1909
|
-
.gp-columns-all { column-span: all; }
|
|
1910
|
-
.gp-columns-flow { column-fill: auto; }
|
|
1911
|
-
.gp-columns-balanced { column-fill: balance; }
|
|
1912
|
-
|
|
1913
|
-
/* grid runs — the SLOTTED counterpart to the column runs above. Grid places
|
|
1914
|
-
each child into the next cell, across then down (deterministic slots: card
|
|
1915
|
-
layouts, stat blocks, image-plus-caption pairs); columns FLOW one text run
|
|
1916
|
-
down then across. Same neutral-primitive rationale as .gp-columns-*, and
|
|
1917
|
-
permanent vocabulary for the same reason: standard CSS Grid verbatim, no
|
|
1918
|
-
spec gap to remove later. MEASURED (Chromium 151, gp-grid evidence pack):
|
|
1919
|
-
grid rows fragment across sheets with EXACT print/viewer parity — 2- and
|
|
1920
|
-
3-col, unequal item heights, mid-row cuts, multi-sheet overflow,
|
|
1921
|
-
break-inside:avoid, gap geometry — so a grid taller than the page is safe,
|
|
1922
|
-
no fit-one-page constraint. Two things to know, not fix:
|
|
1923
|
-
- on a min-height page root (MARKER_CSS), default align-content
|
|
1924
|
-
stretches rows apart to fill the page — identically in both engines.
|
|
1925
|
-
Authors wanting packed rows set align-content: start.
|
|
1926
|
-
- a @page-break / @column-break marker DIRECTLY inside a grid container
|
|
1927
|
-
becomes a grid item and corrupts placement (the one measured parity
|
|
1928
|
-
break); markers.js diagnoses it (break_inside_grid).
|
|
1929
|
-
--gp-grid-gap is author-settable. */
|
|
1930
|
-
.gp-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gp-grid-gap, 1.5em); }
|
|
1931
|
-
.gp-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gp-grid-gap, 1.5em); }
|
|
1932
|
-
|
|
1933
1905
|
/* fragmentation controls — generic pagination utilities for any element,
|
|
1934
|
-
independent of the column
|
|
1906
|
+
independent of the column vocabulary above (a book reached for
|
|
1935
1907
|
these just as often outside a multicol run: keeping a card whole,
|
|
1936
1908
|
forcing a section to start a fresh page). Standard properties only —
|
|
1937
1909
|
this project is Chromium-only (CLAUDE.md), so there are no legacy
|
|
@@ -2089,13 +2061,8 @@ var GP_CLASSES = new Set([
|
|
|
2089
2061
|
"gp-columns-3",
|
|
2090
2062
|
"gp-columns-4",
|
|
2091
2063
|
"gp-columns-5",
|
|
2092
|
-
"gp-columns-all",
|
|
2093
|
-
"gp-columns-flow",
|
|
2094
|
-
"gp-columns-balanced",
|
|
2095
2064
|
"gp-no-break",
|
|
2096
2065
|
"gp-break-before",
|
|
2097
|
-
"gp-grid-2",
|
|
2098
|
-
"gp-grid-3",
|
|
2099
2066
|
"gp-shape",
|
|
2100
2067
|
"gp-pin",
|
|
2101
2068
|
"gp-top",
|
|
@@ -9650,7 +9617,7 @@ class PdfOutput {
|
|
|
9650
9617
|
const rawPdf = pdfxMode ? path13.join(stage, "raw.pdf") : path13.resolve(pdfFile);
|
|
9651
9618
|
await fsp2.mkdir(path13.dirname(path13.resolve(pdfFile)), { recursive: true });
|
|
9652
9619
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
9653
|
-
const { buildNativePdf } = await import("./engine-
|
|
9620
|
+
const { buildNativePdf } = await import("./engine-yf2w9hj7.js");
|
|
9654
9621
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
9655
9622
|
title: config.title,
|
|
9656
9623
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "gutterpress",
|
|
7
|
-
version: "0.11.17-alpha.
|
|
7
|
+
version: "0.11.17-alpha.6",
|
|
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",
|
|
@@ -1131,7 +1131,7 @@ var preview_shell_default = "./preview-shell-xwn84kqr.js";
|
|
|
1131
1131
|
var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
|
|
1132
1132
|
|
|
1133
1133
|
// src/assets/engine/gutterpress-viewer.js
|
|
1134
|
-
var gutterpress_viewer_default = "./gutterpress-viewer-
|
|
1134
|
+
var gutterpress_viewer_default = "./gutterpress-viewer-ez7k4ha7.js";
|
|
1135
1135
|
|
|
1136
1136
|
// src/assets/engine/gutterpress-agent.js
|
|
1137
1137
|
var gutterpress_agent_default = "./gutterpress-agent-cazqstr1.js";
|
|
@@ -1185,7 +1185,7 @@ var package_default2 = "./package-aenwjew3.json";
|
|
|
1185
1185
|
var README_default2 = "./README-3nj919rm.md";
|
|
1186
1186
|
|
|
1187
1187
|
// src/assets/extension-templates/theme/components.yaml
|
|
1188
|
-
var components_default = "./components-
|
|
1188
|
+
var components_default = "./components-zzqdpt3m.yaml";
|
|
1189
1189
|
|
|
1190
1190
|
// src/assets/extension-templates/theme/snippets/callout.md
|
|
1191
1191
|
var callout_default = "./callout-hv56m16h.md";
|
|
@@ -1200,7 +1200,7 @@ var base_default = "./base-ypqh9n7f.css";
|
|
|
1200
1200
|
var components_default2 = "./components-aam0fe2z.css";
|
|
1201
1201
|
|
|
1202
1202
|
// src/assets/extension-templates/theme/styles/page-templates.css
|
|
1203
|
-
var page_templates_default = "./page-templates-
|
|
1203
|
+
var page_templates_default = "./page-templates-tx9ryt19.css";
|
|
1204
1204
|
|
|
1205
1205
|
// src/assets/extension-templates/theme/styles/page-rules.css
|
|
1206
1206
|
var page_rules_default = "./page-rules-nsj3aw42.css";
|
|
@@ -2226,7 +2226,7 @@ ${mapCss}`;
|
|
|
2226
2226
|
if (pageBackgrounds.length)
|
|
2227
2227
|
log(`audit: ${pageBackgrounds.length} unreferenced @page background image(s)`);
|
|
2228
2228
|
for (const d of multicol)
|
|
2229
|
-
diagnose("engine.multicol.dead-column", `${d} runs over more than one page in columns, and only the last page's columns get balanced — earlier pages are left with an empty column.
|
|
2229
|
+
diagnose("engine.multicol.dead-column", `${d} runs over more than one page in columns, and only the last page's columns get balanced — earlier pages are left with an empty column. End the @columns run where the page ends and open a new @columns for the next page, or set column-fill: auto on ${d} in your stylesheet so every page's columns fill.`);
|
|
2230
2230
|
if (multicol.length)
|
|
2231
2231
|
log(`audit: ${multicol.length} fragmenting multicol warning(s)`);
|
|
2232
2232
|
}
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
UsageError,
|
|
7
7
|
package_default,
|
|
8
8
|
rejectUnknownFlags
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-jjbeqx94.js";
|
|
10
10
|
import {
|
|
11
11
|
EXIT_CODES
|
|
12
12
|
} from "./cli-46ycxe6r.js";
|
|
@@ -18,14 +18,14 @@ import {
|
|
|
18
18
|
import { defineCommand, parseArgs, runMain } from "citty";
|
|
19
19
|
import { statSync } from "node:fs";
|
|
20
20
|
var SUBCOMMANDS = {
|
|
21
|
-
new: () => import("./new-
|
|
22
|
-
preview: () => import("./preview-
|
|
23
|
-
build: () => import("./build-
|
|
24
|
-
publish: () => import("./publish-
|
|
25
|
-
validate: () => import("./validate-
|
|
26
|
-
preflight: () => import("./preflight-
|
|
27
|
-
doctor: () => import("./doctor-
|
|
28
|
-
ext: () => import("./ext-
|
|
21
|
+
new: () => import("./new-8xwac8nd.js").then((m) => m.default),
|
|
22
|
+
preview: () => import("./preview-qdby30fx.js").then((m) => m.default),
|
|
23
|
+
build: () => import("./build-yswp3npj.js").then((m) => m.default),
|
|
24
|
+
publish: () => import("./publish-v9tdq7kc.js").then((m) => m.default),
|
|
25
|
+
validate: () => import("./validate-9nszbckg.js").then((m) => m.default),
|
|
26
|
+
preflight: () => import("./preflight-62c2r37w.js").then((m) => m.default),
|
|
27
|
+
doctor: () => import("./doctor-xjgxr88y.js").then((m) => m.default),
|
|
28
|
+
ext: () => import("./ext-n664e0ka.js").then((m) => m.default)
|
|
29
29
|
};
|
|
30
30
|
var VERSION = package_default.version;
|
|
31
31
|
var main = defineCommand({
|
|
@@ -50,7 +50,7 @@ async function preflightRequiredInvocations(rawArgs) {
|
|
|
50
50
|
const [command, ...commandArgs] = rawArgs;
|
|
51
51
|
try {
|
|
52
52
|
if (command === "new") {
|
|
53
|
-
const { newArgs } = await import("./new-
|
|
53
|
+
const { newArgs } = await import("./new-8xwac8nd.js");
|
|
54
54
|
rejectUnknownFlags(commandArgs, newArgs, "new");
|
|
55
55
|
const parsed = parseArgs(commandArgs, {
|
|
56
56
|
...newArgs,
|
|
@@ -62,7 +62,7 @@ async function preflightRequiredInvocations(rawArgs) {
|
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
if (command === "preflight") {
|
|
65
|
-
const { preflightArgs } = await import("./preflight-
|
|
65
|
+
const { preflightArgs } = await import("./preflight-62c2r37w.js");
|
|
66
66
|
rejectUnknownFlags(commandArgs, preflightArgs, "preflight");
|
|
67
67
|
const parsed = parseArgs(commandArgs, {
|
|
68
68
|
...preflightArgs,
|
|
@@ -82,7 +82,7 @@ async function preflightRequiredInvocations(rawArgs) {
|
|
|
82
82
|
}
|
|
83
83
|
if (subcommand.startsWith("-"))
|
|
84
84
|
return;
|
|
85
|
-
const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-
|
|
85
|
+
const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-n664e0ka.js");
|
|
86
86
|
if (!EXT_SUBCOMMANDS.includes(subcommand)) {
|
|
87
87
|
throw new UsageError(`gutterpress ext: unknown command "${subcommand}"`);
|
|
88
88
|
}
|
|
@@ -47,5 +47,5 @@ page_templates:
|
|
|
47
47
|
- name: reference
|
|
48
48
|
recipe: "@page .{{PREFIX}}reference"
|
|
49
49
|
emits: "div.page.{{PREFIX}}reference"
|
|
50
|
-
notes: "
|
|
50
|
+
notes: "Ruled headings for a reference page. For columns, use core's @columns 2 ... @end-columns inside it."
|
|
51
51
|
status: stable
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getSystemDiagnostics,
|
|
3
3
|
log
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-0wtnw98y.js";
|
|
5
5
|
import {
|
|
6
6
|
UsageError,
|
|
7
7
|
rejectExtraPositionals,
|
|
8
8
|
rejectUnknownFlags
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-jjbeqx94.js";
|
|
10
10
|
import"./cli-46ycxe6r.js";
|
|
11
11
|
import"./cli-7fkhgtfn.js";
|
|
12
12
|
import"./cli-37x76zdn.js";
|
|
@@ -12,17 +12,17 @@ import {
|
|
|
12
12
|
searchNpmExtensions,
|
|
13
13
|
setExtensionEnabled,
|
|
14
14
|
updateExtensions
|
|
15
|
-
} from "./cli-
|
|
16
|
-
import"./cli-
|
|
15
|
+
} from "./cli-an3pxzzk.js";
|
|
16
|
+
import"./cli-0wtnw98y.js";
|
|
17
17
|
import {
|
|
18
18
|
UsageError,
|
|
19
19
|
exitForUsage,
|
|
20
20
|
rejectExtraPositionals,
|
|
21
21
|
rejectUnknownFlags,
|
|
22
22
|
resolveProjectDir
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-jjbeqx94.js";
|
|
24
24
|
import"./cli-ht1bcqdd.js";
|
|
25
|
-
import"./cli-
|
|
25
|
+
import"./cli-ycbg7mxk.js";
|
|
26
26
|
import {
|
|
27
27
|
EXIT_CODES
|
|
28
28
|
} from "./cli-46ycxe6r.js";
|
|
@@ -1415,6 +1415,18 @@
|
|
|
1415
1415
|
clearLeadingForcedBreaks(s.el);
|
|
1416
1416
|
return strips;
|
|
1417
1417
|
}
|
|
1418
|
+
var AVOID_BREAK = /^avoid(-page|-column)?$/;
|
|
1419
|
+
function keepChainHead(el) {
|
|
1420
|
+
let head = el;
|
|
1421
|
+
for (let prev = head.previousElementSibling;prev instanceof HTMLElement; prev = head.previousElementSibling) {
|
|
1422
|
+
const linked = AVOID_BREAK.test(getComputedStyle(prev).breakAfter) || AVOID_BREAK.test(getComputedStyle(head).breakBefore);
|
|
1423
|
+
if (!linked)
|
|
1424
|
+
break;
|
|
1425
|
+
head = prev;
|
|
1426
|
+
}
|
|
1427
|
+
return head;
|
|
1428
|
+
}
|
|
1429
|
+
var pushTargets = new WeakMap;
|
|
1418
1430
|
function compensateRepeatedHeaders(strips, maxPasses = 24) {
|
|
1419
1431
|
const warnings = [];
|
|
1420
1432
|
let passes = 0;
|
|
@@ -1427,6 +1439,10 @@
|
|
|
1427
1439
|
for (const shim of Array.from(table.querySelectorAll("tr.gp-thead-shim, tr.gp-tfoot-shim")))
|
|
1428
1440
|
shim.remove();
|
|
1429
1441
|
table.style.breakBefore = "";
|
|
1442
|
+
const target = pushTargets.get(table);
|
|
1443
|
+
if (target)
|
|
1444
|
+
target.style.breakBefore = "";
|
|
1445
|
+
pushTargets.delete(table);
|
|
1430
1446
|
}
|
|
1431
1447
|
const pushed = new Set;
|
|
1432
1448
|
const footClaims = new Map;
|
|
@@ -1487,7 +1503,9 @@
|
|
|
1487
1503
|
shim.remove();
|
|
1488
1504
|
if (plan.push && !pushed.has(plan.table)) {
|
|
1489
1505
|
pushed.add(plan.table);
|
|
1490
|
-
plan.table
|
|
1506
|
+
const target = keepChainHead(plan.table);
|
|
1507
|
+
target.style.breakBefore = "column";
|
|
1508
|
+
pushTargets.set(plan.table, target);
|
|
1491
1509
|
touched++;
|
|
1492
1510
|
continue;
|
|
1493
1511
|
}
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
stringValueAt,
|
|
20
20
|
toFolioPage,
|
|
21
21
|
wantsRecto
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-vmcfahe2.js";
|
|
23
23
|
import {
|
|
24
24
|
launchChromium
|
|
25
25
|
} from "./index-rzm1phg0.js";
|
|
@@ -1329,7 +1329,7 @@ ${mapCss}`;
|
|
|
1329
1329
|
if (pageBackgrounds.length)
|
|
1330
1330
|
log(`audit: ${pageBackgrounds.length} unreferenced @page background image(s)`);
|
|
1331
1331
|
for (const d of multicol)
|
|
1332
|
-
diagnose("engine.multicol.dead-column", `${d} runs over more than one page in columns, and only the last page's columns get balanced — earlier pages are left with an empty column.
|
|
1332
|
+
diagnose("engine.multicol.dead-column", `${d} runs over more than one page in columns, and only the last page's columns get balanced — earlier pages are left with an empty column. End the @columns run where the page ends and open a new @columns for the next page, or set column-fill: auto on ${d} in your stylesheet so every page's columns fill.`);
|
|
1333
1333
|
if (multicol.length)
|
|
1334
1334
|
log(`audit: ${multicol.length} fragmenting multicol warning(s)`);
|
|
1335
1335
|
}
|