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
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* Also ships the author-facing `gp-*` image/block vocabulary (CLAUDE.md §0 —
|
|
19
19
|
* a behavior broadly useful to non-technical authors belongs in core, not a
|
|
20
20
|
* project layer). markdown-it-attrs is bundled by
|
|
21
|
-
* default (renderer.ts), so `{.gp-right .gp-
|
|
21
|
+
* default (renderer.ts), so `{.gp-right .gp-size-30}` already
|
|
22
22
|
* attaches the classes to the rendered `<img>` — these rules are what make
|
|
23
23
|
* them actually do something print-safe. One vocabulary, no aliases: there
|
|
24
24
|
* is no duplicate way to spell each layout (the desktop editor rewrites the
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
* .gp-right — floats right, text wraps.
|
|
30
30
|
* .gp-center — centers a block element.
|
|
31
31
|
* .gp-full — fills the page's content width.
|
|
32
|
-
* .gp-
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
32
|
+
* .gp-size-10 … .gp-size-90
|
|
33
|
+
* — width 10% … 90% of the column, in 10% steps. Sizes
|
|
34
|
+
* compose with any position (including .gp-pin, where
|
|
35
|
+
* the % resolves against the page root: the page box,
|
|
36
|
+
* reaching the paper on an edge a pin uses).
|
|
37
37
|
* There is no 100% step: that is .gp-full, a position.
|
|
38
38
|
* .gp-tight — float/shape clearance 0.5em (sets --gp-gap; default 1em).
|
|
39
39
|
* .gp-loose — float/shape clearance 2em (sets --gp-gap).
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
* is pinned. The pin's containing
|
|
133
133
|
* block is the root's padding box, and the engine sets `--gp-pin-<edge>` on
|
|
134
134
|
* the root to the art-safe line's distance from the sheet edge (the bleed
|
|
135
|
-
* plus page.artSafe on the top, bottom and outside edge; page.
|
|
135
|
+
* plus page.artSafe on the top, bottom and outside edge; page.gutter at the
|
|
136
136
|
* binding, from the manifest); `.gp-pin` reads them as its four insets.
|
|
137
137
|
* `.gp-flush` zeroes them on the pin: the paper's edge. Under plain
|
|
138
138
|
* markdown-it nothing sets them and every inset is 0.
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
* carrying gp-left could start shifting; that is standards-tracking per
|
|
152
152
|
* CLAUDE.md ("Chrome wins once it ships"), not a bug in the author's book.
|
|
153
153
|
*/
|
|
154
|
-
export declare const GUTTERPRESS_CSS = "\n/* gp-* author image/block vocabulary. One vocabulary, gp-* only \u2014 the\n pre-vocabulary utility names (.center/.float-left/.float-right/\n .full-width/.full-bleed) were REMOVED when gp-* shipped; books rename\n the classes in their markdown (see the migration note). Source ORDER is\n the contract \u2014 see the doctrine comment above. */\n\n/* flow positions */\n.gp-left {\n float: left;\n margin: 0 var(--gp-gap, 1em) var(--gp-gap, 1em) 0;\n max-width: 50%;\n}\n.gp-right {\n float: right;\n margin: 0 0 var(--gp-gap, 1em) var(--gp-gap, 1em);\n max-width: 50%;\n}\n.gp-center {\n display: block;\n float: none;\n margin-left: auto;\n margin-right: auto;\n max-width: 100%;\n}\n.gp-full {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n@page gp-full-bleed { margin-left: 0; margin-right: 0; }\n.gp-bleed {\n display: block;\n float: none;\n break-before: page;\n page: gp-full-bleed;\n max-width: none;\n width: 100%;\n margin-left: 0;\n margin-right: 0;\n}\n\n/* sizes \u2014 AFTER the flow positions so max-width:100% lifts the floats' 50%\n cap at equal specificity */\n.gp-small { width: 25%; max-width: 100%; }\n.gp-medium { width: 50%; max-width: 100%; }\n.gp-large { width: 60%; max-width: 100%; }\n.gp-xl { width: 80%; max-width: 100%; }\n.gp-xxl { width: 90%; max-width: 100%; }\n\n/* float clearance presets \u2014 consumed by var(--gp-gap) in the float rules\n above and by .gp-shape's shape-margin below; --gp-gap itself is\n author-settable CSS */\n.gp-tight { --gp-gap: 0.5em; }\n.gp-loose { --gp-gap: 2em; }\n\n/* column runs \u2014 plain CSS Multi-column, emitted by the core @columns marker\n (markers.js): @columns [1-5] ... @end-columns is the ONE way to lay\n content out in columns, and @column-break moves to the next column.\n The classes below are the CSS that marker emits, not author vocabulary.\n\n Permanent vocabulary, not a shim: Chromium implements multicol natively\n and these rules are the standard properties verbatim, so there is no\n spec gap here to remove later. Deliberately minimal \u2014 column-fill is\n NOT set (the CSS initial balance applies).\n Themes style a run through two tokens instead of writing column rules:\n --gp-column-gap default 1.5em\n --gp-column-rule default none (any column-rule shorthand value)\n Both hooks sit at zero specificity (:where), so any author rule wins.\n .gp-columns is two columns on its own; a count class (bare @columns\n emits gp-columns-2) wins because it comes later at the same specificity. */\n:where(.gp-columns, .gp-columns-1, .gp-columns-2, .gp-columns-3, .gp-columns-4, .gp-columns-5) {\n column-gap: var(--gp-column-gap, 1.5em);\n column-rule: var(--gp-column-rule, none);\n}\n.gp-columns { columns: 2; }\n.gp-columns-1 { columns: 1; }\n.gp-columns-2 { columns: 2; }\n.gp-columns-3 { columns: 3; }\n.gp-columns-4 { columns: 4; }\n.gp-columns-5 { columns: 5; }\n\n/* fragmentation controls \u2014 generic pagination utilities for any element,\n independent of the column vocabulary above (a book reached for\n these just as often outside a multicol run: keeping a card whole,\n forcing a section to start a fresh page). Standard properties only \u2014\n this project is Chromium-only (CLAUDE.md), so there are no legacy\n page-break-* twins to also emit. One name each. */\n.gp-no-break { break-inside: avoid; }\n.gp-break-before { break-before: page; }\n\n/* shape wrap \u2014 text follows the image's alpha silhouette instead of its\n rectangular box. shape-outside only applies to floats, so this is inert\n without .gp-left/.gp-right (and under .gp-pin, which un-floats). The\n shape URL cannot be written in CSS (url() contexts can't read attr()),\n so the image renderer rule (images.ts) mirrors the src into an inline\n --gp-shape:url(...) custom property whenever it sees this class --\n authors only ever type the class. threshold 0.2 ignores near-transparent\n anti-aliasing halos; shape-margin shares the float-gap vocabulary. */\nimg.gp-shape {\n shape-outside: var(--gp-shape);\n shape-image-threshold: 0.2;\n shape-margin: var(--gp-gap, 1em);\n}\n\n/* pin \u2014 within the nearest positioned ancestor (.page/.spread, rule above).\n The four insets are the pin box: 0 (the text block's edge) unless an\n engine set --gp-pin-<edge> on the page root for an edge a pin uses (the\n art-safe line). Non-auto insets and the explicit centers are\n load-bearing; see doctrine comment. */\n.gp-pin {\n position: absolute;\n top: var(--gp-pin-top, 0px);\n right: var(--gp-pin-right, 0px);\n bottom: var(--gp-pin-bottom, 0px);\n left: var(--gp-pin-left, 0px);\n align-self: center;\n justify-self: center;\n margin: 0;\n max-width: 100%;\n}\n\n/* pin edge modifiers \u2014 AFTER .gp-pin to beat its center defaults;\n justify-self is inert on in-flow floats, so gp-left/gp-right safely do\n double duty as flow float + pin edge */\n.gp-top { align-self: start; }\n.gp-bottom { align-self: end; }\n.gp-left { justify-self: start; }\n.gp-right { justify-self: end; }\n\n/* the escape hatch \u2014 the paper's edge, past the printer's safe area: the\n pin box loses its art-safe insets. Set on the pin itself, so it beats the\n values the page root hands down. */\n.gp-pin.gp-flush {\n --gp-pin-top: 0px;\n --gp-pin-right: 0px;\n --gp-pin-bottom: 0px;\n --gp-pin-left: 0px;\n}\n\n/* wrapper-margin neutralization (same pattern and rationale as the\n .gp-bleed paragraph-margin note in the doctrine comment; for pin, the\n emptied paragraph would otherwise leave a phantom margin gap in flow) */\n:where(p:has(> img.gp-bleed:only-child)) { margin: 0; }\n:where(p:has(> img.gp-pin:only-child)) { margin: 0; }\n\n/* depth \u2014 a named ladder for z-index, so books stop hand-tuning bare\n integers. A real book measured 21 z-index declarations using only four\n distinct values (-1, 0, 1, 2), each written literally at its use site.\n The custom properties are the author-settable surface (a book needing a\n deeper stack raises them once); the classes are the shorthand.\n\n NOT named \"layer\": CSS Paged Media 3 \u00A73.1 already defines \"page layers\"\n (page background, canvas, borders, contents, margin boxes) and those are\n parts of the PAGE BOX, not a z-ladder for content. Reusing the word for a\n different concept would collide with the spec vocabulary this project\n tracks. The pin EDGE modifiers already own .gp-top/.gp-bottom, so the\n ladder avoids those words too.\n\n .gp-behind is the one that earns its place: it puts a pinned image UNDER\n the page's text, which is otherwise impossible to express without a bare\n negative z-index. \"Above\" needs no class \u2014 an out-of-flow pin already\n paints above in-flow content.\n\n Two things silently defeat .gp-behind, neither visible at the use site:\n - a stacking context on the .page/.spread ancestor (z-index, isolation,\n opacity, filter, transform on it traps the negative layer inside).\n Core keeps .page/.spread at 'position: relative; z-index: auto'\n precisely so they are not stacking contexts.\n - a clipping ancestor (overflow other than visible) \u2014 but only where\n the art actually overhangs that ancestor's clip box on a clipped\n axis: the overhang is cut off, the same mechanism that clips a\n .gp-bleed plate back to the wrapper's width. Clipping never reorders\n layers \u2014 within-bounds art under a clipping .page prints whole and\n still behind (measured; see the build audit's comment in\n engine/compiler/build.ts), and a static wrapper's overflow never\n binds an abspos .gp-pin at all.\n The build-time engine.layer.trapped audit reports both against the live\n ancestor chain. printsafe/page-containment is only an early source hint for\n declarations written directly on .page/.spread. */\n:root {\n --gp-z-behind: -1;\n --gp-z-base: 0;\n --gp-z-raised: 1;\n --gp-z-front: 2;\n}\n.gp-behind { z-index: var(--gp-z-behind); }\n.gp-base { z-index: var(--gp-z-base); }\n.gp-raised { z-index: var(--gp-z-raised); }\n.gp-front { z-index: var(--gp-z-front); }\n\n/* GFM-style alert/callout boxes (#237) \u2014 the DOM gfm-alerts.ts emits from\n \"> [!TYPE]\" blockquote syntax when a project opts into the bundled\n gutterpress-gfm-alerts feature (BUILTIN_OPTIONAL_PLUGINS, renderer.ts).\n The plugin is optional and inert by default; these rules are equally\n inert wherever the classes never appear, exactly like every other\n utility above, so shipping them costs nothing to a book that has not\n turned the feature on.\n\n This is authored-COMPONENT vocabulary, not the @marker structural family\n (markers.js/MARKER_CSS) \u2014 CLAUDE.md \u00A76 splits the two core CSS blocks by\n ROLE, and an author-facing box an author invokes via inline syntax is the\n same role as every other gp-* utility here, not page/chapter/section DOM.\n\n Deliberately minimal (CLAUDE.md \"thin over capable\" / the issue's own\n \"a rule and a label\"): a left border plus a bold label, :where()'d to\n zero specificity so a theme's own (unlayered) rule for any of these\n classes wins outright regardless of selector weight \u2014 see the\n cascade-layers note atop this file. Five semantic accent colors (the same\n NOTE/TIP/IMPORTANT/WARNING/CAUTION hues GitHub's own alerts use \u2014 a\n long-established, non-proprietary convention, not DC branding) are\n exposed as :root custom properties, the same author-settable-surface\n pattern as the --gp-z-* ladder above: a book retints every alert of one\n type by overriding a single property, no specificity fight required.\n --gp-alert-color cascades from the type modifier down to .gp-alert-title\n through ordinary CSS inheritance (the title is always a DOM descendant of\n the box), so it is set in exactly five places, not ten. */\n:root {\n --gp-alert-note-color: #0969da;\n --gp-alert-tip-color: #1a7f37;\n --gp-alert-important-color: #8250df;\n --gp-alert-warning-color: #9a6700;\n --gp-alert-caution-color: #cf222e;\n}\n:where(.gp-alert) {\n margin: 1em 0;\n padding: 0.5em 1em;\n border-left: 0.25em solid var(--gp-alert-color, currentColor);\n}\n:where(.gp-alert-title) {\n margin: 0 0 0.5em;\n font-weight: bold;\n color: var(--gp-alert-color, inherit);\n}\n:where(.gp-alert-note) { --gp-alert-color: var(--gp-alert-note-color); }\n:where(.gp-alert-tip) { --gp-alert-color: var(--gp-alert-tip-color); }\n:where(.gp-alert-important) { --gp-alert-color: var(--gp-alert-important-color); }\n:where(.gp-alert-warning) { --gp-alert-color: var(--gp-alert-warning-color); }\n:where(.gp-alert-caution) { --gp-alert-color: var(--gp-alert-caution-color); }\n";
|
|
154
|
+
export declare const GUTTERPRESS_CSS = "\n/* gp-* author image/block vocabulary. One vocabulary, gp-* only \u2014 the\n pre-vocabulary utility names (.center/.float-left/.float-right/\n .full-width/.full-bleed) were REMOVED when gp-* shipped; books rename\n the classes in their markdown (see the migration note). Source ORDER is\n the contract \u2014 see the doctrine comment above. */\n\n/* flow positions */\n.gp-left {\n float: left;\n margin: 0 var(--gp-gap, 1em) var(--gp-gap, 1em) 0;\n max-width: 50%;\n}\n.gp-right {\n float: right;\n margin: 0 0 var(--gp-gap, 1em) var(--gp-gap, 1em);\n max-width: 50%;\n}\n.gp-center {\n display: block;\n float: none;\n margin-left: auto;\n margin-right: auto;\n max-width: 100%;\n}\n.gp-full {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n@page gp-full-bleed { margin-left: 0; margin-right: 0; }\n.gp-bleed {\n display: block;\n float: none;\n break-before: page;\n page: gp-full-bleed;\n max-width: none;\n width: 100%;\n margin-left: 0;\n margin-right: 0;\n}\n\n/* sizes \u2014 AFTER the flow positions so max-width:100% lifts the floats' 50%\n cap at equal specificity */\n.gp-size-10 { width: 10%; max-width: 100%; }\n.gp-size-20 { width: 20%; max-width: 100%; }\n.gp-size-30 { width: 30%; max-width: 100%; }\n.gp-size-40 { width: 40%; max-width: 100%; }\n.gp-size-50 { width: 50%; max-width: 100%; }\n.gp-size-60 { width: 60%; max-width: 100%; }\n.gp-size-70 { width: 70%; max-width: 100%; }\n.gp-size-80 { width: 80%; max-width: 100%; }\n.gp-size-90 { width: 90%; max-width: 100%; }\n\n/* float clearance presets \u2014 consumed by var(--gp-gap) in the float rules\n above and by .gp-shape's shape-margin below; --gp-gap itself is\n author-settable CSS */\n.gp-tight { --gp-gap: 0.5em; }\n.gp-loose { --gp-gap: 2em; }\n\n/* column runs \u2014 plain CSS Multi-column, emitted by the core @columns marker\n (markers.js): @columns [1-5] ... @end-columns is the ONE way to lay\n content out in columns, and @column-break moves to the next column.\n The classes below are the CSS that marker emits, not author vocabulary.\n\n Permanent vocabulary, not a shim: Chromium implements multicol natively\n and these rules are the standard properties verbatim, so there is no\n spec gap here to remove later. Deliberately minimal \u2014 column-fill is\n NOT set (the CSS initial balance applies).\n Themes style a run through two tokens instead of writing column rules:\n --gp-column-gap default 1.5em\n --gp-column-rule default none (any column-rule shorthand value)\n Both hooks sit at zero specificity (:where), so any author rule wins.\n .gp-columns is two columns on its own; a count class (bare @columns\n emits gp-columns-2) wins because it comes later at the same specificity. */\n:where(.gp-columns, .gp-columns-1, .gp-columns-2, .gp-columns-3, .gp-columns-4, .gp-columns-5) {\n column-gap: var(--gp-column-gap, 1.5em);\n column-rule: var(--gp-column-rule, none);\n}\n.gp-columns { columns: 2; }\n.gp-columns-1 { columns: 1; }\n.gp-columns-2 { columns: 2; }\n.gp-columns-3 { columns: 3; }\n.gp-columns-4 { columns: 4; }\n.gp-columns-5 { columns: 5; }\n\n/* fragmentation controls \u2014 generic pagination utilities for any element,\n independent of the column vocabulary above (a book reached for\n these just as often outside a multicol run: keeping a card whole,\n forcing a section to start a fresh page). Standard properties only \u2014\n this project is Chromium-only (CLAUDE.md), so there are no legacy\n page-break-* twins to also emit. One name each. */\n.gp-no-break { break-inside: avoid; }\n.gp-break-before { break-before: page; }\n\n/* shape wrap \u2014 text follows the image's alpha silhouette instead of its\n rectangular box. shape-outside only applies to floats, so this is inert\n without .gp-left/.gp-right (and under .gp-pin, which un-floats). The\n shape URL cannot be written in CSS (url() contexts can't read attr()),\n so the image renderer rule (images.ts) mirrors the src into an inline\n --gp-shape:url(...) custom property whenever it sees this class --\n authors only ever type the class. threshold 0.2 ignores near-transparent\n anti-aliasing halos; shape-margin shares the float-gap vocabulary. */\nimg.gp-shape {\n shape-outside: var(--gp-shape);\n shape-image-threshold: 0.2;\n shape-margin: var(--gp-gap, 1em);\n}\n\n/* pin \u2014 within the nearest positioned ancestor (.page/.spread, rule above).\n The four insets are the pin box: 0 (the text block's edge) unless an\n engine set --gp-pin-<edge> on the page root for an edge a pin uses (the\n art-safe line). Non-auto insets and the explicit centers are\n load-bearing; see doctrine comment. */\n.gp-pin {\n position: absolute;\n top: var(--gp-pin-top, 0px);\n right: var(--gp-pin-right, 0px);\n bottom: var(--gp-pin-bottom, 0px);\n left: var(--gp-pin-left, 0px);\n align-self: center;\n justify-self: center;\n margin: 0;\n max-width: 100%;\n}\n\n/* pin edge modifiers \u2014 AFTER .gp-pin to beat its center defaults;\n justify-self is inert on in-flow floats, so gp-left/gp-right safely do\n double duty as flow float + pin edge */\n.gp-top { align-self: start; }\n.gp-bottom { align-self: end; }\n.gp-left { justify-self: start; }\n.gp-right { justify-self: end; }\n\n/* the escape hatch \u2014 the paper's edge, past the printer's safe area: the\n pin box loses its art-safe insets. Set on the pin itself, so it beats the\n values the page root hands down. */\n.gp-pin.gp-flush {\n --gp-pin-top: 0px;\n --gp-pin-right: 0px;\n --gp-pin-bottom: 0px;\n --gp-pin-left: 0px;\n}\n\n/* wrapper-margin neutralization (same pattern and rationale as the\n .gp-bleed paragraph-margin note in the doctrine comment; for pin, the\n emptied paragraph would otherwise leave a phantom margin gap in flow) */\n:where(p:has(> img.gp-bleed:only-child)) { margin: 0; }\n:where(p:has(> img.gp-pin:only-child)) { margin: 0; }\n\n/* depth \u2014 a named ladder for z-index, so books stop hand-tuning bare\n integers. A real book measured 21 z-index declarations using only four\n distinct values (-1, 0, 1, 2), each written literally at its use site.\n The custom properties are the author-settable surface (a book needing a\n deeper stack raises them once); the classes are the shorthand.\n\n NOT named \"layer\": CSS Paged Media 3 \u00A73.1 already defines \"page layers\"\n (page background, canvas, borders, contents, margin boxes) and those are\n parts of the PAGE BOX, not a z-ladder for content. Reusing the word for a\n different concept would collide with the spec vocabulary this project\n tracks. The pin EDGE modifiers already own .gp-top/.gp-bottom, so the\n ladder avoids those words too.\n\n .gp-behind is the one that earns its place: it puts a pinned image UNDER\n the page's text, which is otherwise impossible to express without a bare\n negative z-index. \"Above\" needs no class \u2014 an out-of-flow pin already\n paints above in-flow content.\n\n Two things silently defeat .gp-behind, neither visible at the use site:\n - a stacking context on the .page/.spread ancestor (z-index, isolation,\n opacity, filter, transform on it traps the negative layer inside).\n Core keeps .page/.spread at 'position: relative; z-index: auto'\n precisely so they are not stacking contexts.\n - a clipping ancestor (overflow other than visible) \u2014 but only where\n the art actually overhangs that ancestor's clip box on a clipped\n axis: the overhang is cut off, the same mechanism that clips a\n .gp-bleed plate back to the wrapper's width. Clipping never reorders\n layers \u2014 within-bounds art under a clipping .page prints whole and\n still behind (measured; see the build audit's comment in\n engine/compiler/build.ts), and a static wrapper's overflow never\n binds an abspos .gp-pin at all.\n The build-time engine.layer.trapped audit reports both against the live\n ancestor chain. printsafe/page-containment is only an early source hint for\n declarations written directly on .page/.spread. */\n:root {\n --gp-z-behind: -1;\n --gp-z-base: 0;\n --gp-z-raised: 1;\n --gp-z-front: 2;\n}\n.gp-behind { z-index: var(--gp-z-behind); }\n.gp-base { z-index: var(--gp-z-base); }\n.gp-raised { z-index: var(--gp-z-raised); }\n.gp-front { z-index: var(--gp-z-front); }\n\n/* GFM-style alert/callout boxes (#237) \u2014 the DOM gfm-alerts.ts emits from\n \"> [!TYPE]\" blockquote syntax when a project opts into the bundled\n gutterpress-gfm-alerts feature (BUILTIN_OPTIONAL_PLUGINS, renderer.ts).\n The plugin is optional and inert by default; these rules are equally\n inert wherever the classes never appear, exactly like every other\n utility above, so shipping them costs nothing to a book that has not\n turned the feature on.\n\n This is authored-COMPONENT vocabulary, not the @marker structural family\n (markers.js/MARKER_CSS) \u2014 CLAUDE.md \u00A76 splits the two core CSS blocks by\n ROLE, and an author-facing box an author invokes via inline syntax is the\n same role as every other gp-* utility here, not page/chapter/section DOM.\n\n Deliberately minimal (CLAUDE.md \"thin over capable\" / the issue's own\n \"a rule and a label\"): a left border plus a bold label, :where()'d to\n zero specificity so a theme's own (unlayered) rule for any of these\n classes wins outright regardless of selector weight \u2014 see the\n cascade-layers note atop this file. Five semantic accent colors (the same\n NOTE/TIP/IMPORTANT/WARNING/CAUTION hues GitHub's own alerts use \u2014 a\n long-established, non-proprietary convention, not DC branding) are\n exposed as :root custom properties, the same author-settable-surface\n pattern as the --gp-z-* ladder above: a book retints every alert of one\n type by overriding a single property, no specificity fight required.\n --gp-alert-color cascades from the type modifier down to .gp-alert-title\n through ordinary CSS inheritance (the title is always a DOM descendant of\n the box), so it is set in exactly five places, not ten. */\n:root {\n --gp-alert-note-color: #0969da;\n --gp-alert-tip-color: #1a7f37;\n --gp-alert-important-color: #8250df;\n --gp-alert-warning-color: #9a6700;\n --gp-alert-caution-color: #cf222e;\n}\n:where(.gp-alert) {\n margin: 1em 0;\n padding: 0.5em 1em;\n border-left: 0.25em solid var(--gp-alert-color, currentColor);\n}\n:where(.gp-alert-title) {\n margin: 0 0 0.5em;\n font-weight: bold;\n color: var(--gp-alert-color, inherit);\n}\n:where(.gp-alert-note) { --gp-alert-color: var(--gp-alert-note-color); }\n:where(.gp-alert-tip) { --gp-alert-color: var(--gp-alert-tip-color); }\n:where(.gp-alert-important) { --gp-alert-color: var(--gp-alert-important-color); }\n:where(.gp-alert-warning) { --gp-alert-color: var(--gp-alert-warning-color); }\n:where(.gp-alert-caution) { --gp-alert-color: var(--gp-alert-caution-color); }\n";
|
|
155
155
|
/**
|
|
156
156
|
* GP_CLASSES — every class an author may legitimately write with a `gp-`
|
|
157
157
|
* prefix: the `.gp-*` selectors in `GUTTERPRESS_CSS` above, the two
|
package/dist/lib/page-size.d.ts
CHANGED
|
@@ -37,7 +37,8 @@ export declare function isPositivePoints(value: unknown): value is number;
|
|
|
37
37
|
/**
|
|
38
38
|
* Write the manifest's `page:` bounds. `tolerance` defaults to whatever the
|
|
39
39
|
* block already carries, so re-sizing a book never silently resets a
|
|
40
|
-
* hand-tuned tolerance.
|
|
40
|
+
* hand-tuned tolerance. The block's other keys stay as written; a `page:`
|
|
41
|
+
* that is not a map is replaced.
|
|
41
42
|
*/
|
|
42
43
|
export declare function writePageBounds(doc: Document, page: CustomPageOptions): void;
|
|
43
44
|
/** The size (points) a choice means: `custom` brings its own, the others are the preset's. */
|
|
@@ -59,8 +60,9 @@ export declare function readPageSetup(projectDir: string): Promise<PageSetup>;
|
|
|
59
60
|
/**
|
|
60
61
|
* Change a book's page size: the manifest's `preset:` + `page:` bounds and the
|
|
61
62
|
* stylesheet's `@page` size, together. Mirrors what the wizard records —
|
|
62
|
-
* `dtrpg` / `book` carry their own bounds (
|
|
63
|
-
*
|
|
63
|
+
* `dtrpg` / `book` carry their own bounds (the `page:` block's width, height
|
|
64
|
+
* and tolerance are removed so they cannot shadow them; its print-area keys
|
|
65
|
+
* stay), `custom` records the typed trim. Nothing is written
|
|
64
66
|
* unless the whole choice validates and the stylesheet parses.
|
|
65
67
|
*/
|
|
66
68
|
export declare function setPageSetup(projectDir: string, choice: PageSizeChoice): Promise<PageSetup>;
|
|
@@ -228,15 +228,21 @@
|
|
|
228
228
|
},
|
|
229
229
|
"safe": {
|
|
230
230
|
"type": "number",
|
|
231
|
-
"description": "The TEXT rule, in points: how far inside the trim glyphs must stay, on every edge. For DriveThruRPG it is the \"text at least 0.5in inside the trim\" rule. The preview's overlay outlines it (dashed) and flags text outside it, and the `pdf.print.safe-margins` check fails a PDF whose text is closer. An image pinned to
|
|
231
|
+
"description": "The TEXT rule, in points: how far inside the trim glyphs must stay, on every edge (the binding edge too, unless `gutter` is set). For DriveThruRPG it is the \"text at least 0.5in inside the trim\" rule. The preview's overlay outlines it (dashed) and flags text outside it, and the `pdf.print.safe-margins` check fails a PDF whose text is closer. An image pinned to an edge (`.gp-pin`) where `artSafe` is not set sits on it; no book CSS moves it. Preset default: dtrpg 36 (0.5in), book 18 (0.25in); custom none.",
|
|
232
232
|
"minimum": 0,
|
|
233
233
|
"examples": [18, 36]
|
|
234
234
|
},
|
|
235
235
|
"artSafe": {
|
|
236
236
|
"type": "number",
|
|
237
|
-
"description": "The ART rule, in points: how far inside the trim art that does not bleed (images, backgrounds, borders, rules) must stay on the top, bottom and OUTER edge; at the binding edge art uses `
|
|
237
|
+
"description": "The ART rule, in points: how far inside the trim art that does not bleed (images, backgrounds, borders, rules) must stay on the top, bottom and OUTER edge; at the binding edge art uses `gutter`. For DriveThruRPG it is the \"non-bleeding art at least 0.25in from the outside edges (0.5in at the binding)\" rule. Art that runs out to the page's edge is a bleed and is not judged on that edge. The preview's overlay outlines it (dotted) and flags art outside it, and an image pinned to the top, bottom or outer edge (`.gp-pin`) sits on it unless it carries `.gp-flush`. Absent = the same as `safe`. Preset default: dtrpg 18 (0.25in); book and custom none.",
|
|
238
238
|
"minimum": 0,
|
|
239
239
|
"examples": [18]
|
|
240
|
+
},
|
|
241
|
+
"gutter": {
|
|
242
|
+
"type": "number",
|
|
243
|
+
"description": "The binding allowance, in points: how far content stays from the spine, measured from the trim at the binding edge (the left edge of a right-hand page, the right edge of a left-hand one). It stands in for `safe` there, for text and for art alike: the preview's overlay draws and judges that edge against it, the `pdf.print.safe-margins` check fails text closer to the spine than it, and an image pinned to the binding edge (`.gp-pin`) sits on it. The other edges keep `safe` and `artSafe`. Use it when your book keeps its text further from the spine than the printer's minimum: the Field Guide keeps 0.75in (54) where DriveThruRPG asks for 0.5in. Absent = the same as `safe`. Presets leave it unset.",
|
|
244
|
+
"minimum": 0,
|
|
245
|
+
"examples": [54]
|
|
240
246
|
}
|
|
241
247
|
}
|
|
242
248
|
},
|
|
@@ -7,17 +7,17 @@ import {
|
|
|
7
7
|
TARGET_IDS,
|
|
8
8
|
scaffoldExtension,
|
|
9
9
|
scaffoldProject
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-4d25xvs2.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveGhostscript
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-tsdrvrff.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError,
|
|
16
16
|
rejectExtraPositionals,
|
|
17
17
|
rejectUnknownFlags
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-gxqxn3sf.js";
|
|
19
19
|
import"./cli-ht1bcqdd.js";
|
|
20
|
-
import"./cli-
|
|
20
|
+
import"./cli-cyej3p9v.js";
|
|
21
21
|
import {
|
|
22
22
|
EXIT_CODES
|
|
23
23
|
} from "./cli-46ycxe6r.js";
|
|
@@ -2,17 +2,17 @@ import {
|
|
|
2
2
|
executeValidation,
|
|
3
3
|
publishTargetFor,
|
|
4
4
|
reportMissingTools
|
|
5
|
-
} from "./cli-
|
|
5
|
+
} from "./cli-4d25xvs2.js";
|
|
6
6
|
import {
|
|
7
7
|
log
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-tsdrvrff.js";
|
|
9
9
|
import {
|
|
10
10
|
UsageError,
|
|
11
11
|
rejectExtraPositionals,
|
|
12
12
|
rejectUnknownFlags
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-gxqxn3sf.js";
|
|
14
14
|
import"./cli-ht1bcqdd.js";
|
|
15
|
-
import"./cli-
|
|
15
|
+
import"./cli-cyej3p9v.js";
|
|
16
16
|
import {
|
|
17
17
|
BuildError,
|
|
18
18
|
EXIT_CODES
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
runBuild,
|
|
7
7
|
splitOutPath,
|
|
8
8
|
startPreviewServer
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-4d25xvs2.js";
|
|
10
10
|
import {
|
|
11
11
|
log
|
|
12
|
-
} from "./cli-
|
|
12
|
+
} from "./cli-tsdrvrff.js";
|
|
13
13
|
import {
|
|
14
14
|
UsageError,
|
|
15
15
|
parseFormat,
|
|
@@ -17,9 +17,9 @@ import {
|
|
|
17
17
|
rejectExtraPositionals,
|
|
18
18
|
rejectUnknownFlags,
|
|
19
19
|
resolvePort
|
|
20
|
-
} from "./cli-
|
|
20
|
+
} from "./cli-gxqxn3sf.js";
|
|
21
21
|
import"./cli-ht1bcqdd.js";
|
|
22
|
-
import"./cli-
|
|
22
|
+
import"./cli-cyej3p9v.js";
|
|
23
23
|
import {
|
|
24
24
|
BuildError
|
|
25
25
|
} from "./cli-46ycxe6r.js";
|
|
@@ -11,18 +11,18 @@ import {
|
|
|
11
11
|
publishProviderFor,
|
|
12
12
|
resolvePublishFormat,
|
|
13
13
|
runPublish
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-4d25xvs2.js";
|
|
15
15
|
import {
|
|
16
16
|
FileTokenStore,
|
|
17
17
|
log
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-tsdrvrff.js";
|
|
19
19
|
import {
|
|
20
20
|
UsageError,
|
|
21
21
|
rejectExtraPositionals,
|
|
22
22
|
rejectUnknownFlags
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-gxqxn3sf.js";
|
|
24
24
|
import"./cli-ht1bcqdd.js";
|
|
25
|
-
import"./cli-
|
|
25
|
+
import"./cli-cyej3p9v.js";
|
|
26
26
|
import {
|
|
27
27
|
EXIT_CODES
|
|
28
28
|
} from "./cli-46ycxe6r.js";
|
package/dist/render.js
CHANGED
|
@@ -1229,11 +1229,15 @@ var GUTTERPRESS_CSS = `
|
|
|
1229
1229
|
|
|
1230
1230
|
/* sizes — AFTER the flow positions so max-width:100% lifts the floats' 50%
|
|
1231
1231
|
cap at equal specificity */
|
|
1232
|
-
.gp-
|
|
1233
|
-
.gp-
|
|
1234
|
-
.gp-
|
|
1235
|
-
.gp-
|
|
1236
|
-
.gp-
|
|
1232
|
+
.gp-size-10 { width: 10%; max-width: 100%; }
|
|
1233
|
+
.gp-size-20 { width: 20%; max-width: 100%; }
|
|
1234
|
+
.gp-size-30 { width: 30%; max-width: 100%; }
|
|
1235
|
+
.gp-size-40 { width: 40%; max-width: 100%; }
|
|
1236
|
+
.gp-size-50 { width: 50%; max-width: 100%; }
|
|
1237
|
+
.gp-size-60 { width: 60%; max-width: 100%; }
|
|
1238
|
+
.gp-size-70 { width: 70%; max-width: 100%; }
|
|
1239
|
+
.gp-size-80 { width: 80%; max-width: 100%; }
|
|
1240
|
+
.gp-size-90 { width: 90%; max-width: 100%; }
|
|
1237
1241
|
|
|
1238
1242
|
/* float clearance presets — consumed by var(--gp-gap) in the float rules
|
|
1239
1243
|
above and by .gp-shape's shape-margin below; --gp-gap itself is
|
|
@@ -1431,11 +1435,15 @@ var GP_CLASSES = new Set([
|
|
|
1431
1435
|
"gp-center",
|
|
1432
1436
|
"gp-full",
|
|
1433
1437
|
"gp-bleed",
|
|
1434
|
-
"gp-
|
|
1435
|
-
"gp-
|
|
1436
|
-
"gp-
|
|
1437
|
-
"gp-
|
|
1438
|
-
"gp-
|
|
1438
|
+
"gp-size-10",
|
|
1439
|
+
"gp-size-20",
|
|
1440
|
+
"gp-size-30",
|
|
1441
|
+
"gp-size-40",
|
|
1442
|
+
"gp-size-50",
|
|
1443
|
+
"gp-size-60",
|
|
1444
|
+
"gp-size-70",
|
|
1445
|
+
"gp-size-80",
|
|
1446
|
+
"gp-size-90",
|
|
1439
1447
|
"gp-tight",
|
|
1440
1448
|
"gp-loose",
|
|
1441
1449
|
"gp-columns",
|
|
@@ -1537,10 +1545,10 @@ import markdownItAttrs from "markdown-it-attrs";
|
|
|
1537
1545
|
import markdownItFootnote from "markdown-it-footnote";
|
|
1538
1546
|
|
|
1539
1547
|
// src/lib/markdown/gp-pin-scope.js
|
|
1540
|
-
function warn2(env, line, type, message,
|
|
1548
|
+
function warn2(env, line, type, message, severity) {
|
|
1541
1549
|
if (!env.layoutWarnings)
|
|
1542
1550
|
env.layoutWarnings = [];
|
|
1543
|
-
env.layoutWarnings.push({ line, type, message,
|
|
1551
|
+
env.layoutWarnings.push(severity ? { line, type, message, severity } : { line, type, message });
|
|
1544
1552
|
}
|
|
1545
1553
|
function editDistance2(a, b) {
|
|
1546
1554
|
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
@@ -1583,7 +1591,7 @@ function checkFlushArt(token, env, line) {
|
|
|
1583
1591
|
return;
|
|
1584
1592
|
if (!classes.some((c) => PIN_EDGES.includes(c)))
|
|
1585
1593
|
return;
|
|
1586
|
-
warn2(env, line, "flush_art", FLUSH_ART_MSG);
|
|
1594
|
+
warn2(env, line, "flush_art", FLUSH_ART_MSG, "info");
|
|
1587
1595
|
}
|
|
1588
1596
|
function elementNameFor(token) {
|
|
1589
1597
|
switch (token.type) {
|
|
@@ -2387,6 +2395,7 @@ function printAreaMeta(page) {
|
|
|
2387
2395
|
bleed: page.bleed ?? 0,
|
|
2388
2396
|
safe: page.safe ?? 0,
|
|
2389
2397
|
artSafe: page.artSafe,
|
|
2398
|
+
gutter: page.gutter,
|
|
2390
2399
|
preset: page.preset,
|
|
2391
2400
|
spec: page.spec
|
|
2392
2401
|
});
|
|
@@ -178,22 +178,34 @@ export interface GutterpressManifest {
|
|
|
178
178
|
bleed?: number;
|
|
179
179
|
/**
|
|
180
180
|
* The TEXT rule (pt): glyphs stay at least this far inside the trim on
|
|
181
|
-
* EVERY edge
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* `artSafe` is not set
|
|
181
|
+
* EVERY edge, the binding edge too unless the book sets a `gutter` —
|
|
182
|
+
* DriveThruRPG's "keep text 0.5in inside the trim" (`dtrpg` sets 36). The
|
|
183
|
+
* preview's overlay outlines it and flags text outside it, and
|
|
184
|
+
* `pdf.print.safe-margins` fails a built PDF whose text is closer. An
|
|
185
|
+
* image pinned to an edge where `artSafe` is not set sits on it; nothing
|
|
186
|
+
* in a book's CSS moves it.
|
|
186
187
|
*/
|
|
187
188
|
safe?: number;
|
|
188
189
|
/**
|
|
189
190
|
* The ART rule (pt): art that does not bleed — images, backgrounds,
|
|
190
191
|
* borders, rules — stays at least this far inside the trim on the top,
|
|
191
|
-
* bottom and OUTER edge; at the binding edge it uses `
|
|
192
|
+
* bottom and OUTER edge; at the binding edge it uses `gutter`. DriveThruRPG's
|
|
192
193
|
* "keep non-bleeding art 0.25in from the outside edges" (`dtrpg` sets 18).
|
|
193
194
|
* An image pinned to the top, bottom or outer edge (`.gp-pin`) sits on this
|
|
194
195
|
* line unless it carries `.gp-flush`. Absent = the same as `safe`.
|
|
195
196
|
*/
|
|
196
197
|
artSafe?: number;
|
|
198
|
+
/**
|
|
199
|
+
* The binding allowance (pt): how far content stays from the spine — the
|
|
200
|
+
* binding edge, the left of a right-hand page and the right of a left-hand
|
|
201
|
+
* one — measured from the trim. It stands in for `safe` at the binding
|
|
202
|
+
* edge, for text and for art alike, so a book that keeps its text further
|
|
203
|
+
* from the spine than the printer's minimum says so here, not in its CSS
|
|
204
|
+
* (the Field Guide keeps 0.75in = 54 where DriveThruRPG asks for 0.5in).
|
|
205
|
+
* An image pinned to the binding edge sits on it. The other edges keep
|
|
206
|
+
* `safe` and `artSafe`. Absent = the same as `safe`; presets leave it unset.
|
|
207
|
+
*/
|
|
208
|
+
gutter?: number;
|
|
197
209
|
};
|
|
198
210
|
ink?: {
|
|
199
211
|
maxTac?: number;
|
|
@@ -327,6 +339,8 @@ export interface ResolvedConfig {
|
|
|
327
339
|
safe?: number;
|
|
328
340
|
/** The art rule's inset from the trim in pt, top/bottom/outer edge (see the manifest field); absent = same as `safe`. */
|
|
329
341
|
artSafe?: number;
|
|
342
|
+
/** The binding edge's inset from the trim in pt, text and art alike (see the manifest field); absent = same as `safe`. */
|
|
343
|
+
gutter?: number;
|
|
330
344
|
};
|
|
331
345
|
ink: {
|
|
332
346
|
maxTac: number;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
executeAndReport
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-4d25xvs2.js";
|
|
4
4
|
import {
|
|
5
5
|
log
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-tsdrvrff.js";
|
|
7
7
|
import {
|
|
8
8
|
UsageError,
|
|
9
9
|
rejectExtraPositionals,
|
|
10
10
|
rejectUnknownFlags
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-gxqxn3sf.js";
|
|
12
12
|
import"./cli-ht1bcqdd.js";
|
|
13
|
-
import"./cli-
|
|
13
|
+
import"./cli-cyej3p9v.js";
|
|
14
14
|
import {
|
|
15
15
|
BuildError,
|
|
16
16
|
EXIT_CODES
|
package/package.json
CHANGED