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
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
getAssetsDir,
|
|
10
10
|
lastPageMode,
|
|
11
11
|
parseSize
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-gm5xbx5w.js";
|
|
13
13
|
import {
|
|
14
14
|
countLinkAnnotations,
|
|
15
15
|
getImageResolutions,
|
|
@@ -1989,7 +1989,9 @@ var GUTTERPRESS_CSS = `
|
|
|
1989
1989
|
cap at equal specificity */
|
|
1990
1990
|
.gp-small { width: 25%; max-width: 100%; }
|
|
1991
1991
|
.gp-medium { width: 50%; max-width: 100%; }
|
|
1992
|
-
.gp-large { width:
|
|
1992
|
+
.gp-large { width: 60%; max-width: 100%; }
|
|
1993
|
+
.gp-xl { width: 80%; max-width: 100%; }
|
|
1994
|
+
.gp-xxl { width: 90%; max-width: 100%; }
|
|
1993
1995
|
|
|
1994
1996
|
/* float clearance presets — consumed by var(--gp-gap) in the float rules
|
|
1995
1997
|
above and by .gp-shape's shape-margin below; --gp-gap itself is
|
|
@@ -2047,10 +2049,16 @@ img.gp-shape {
|
|
|
2047
2049
|
}
|
|
2048
2050
|
|
|
2049
2051
|
/* pin — within the nearest positioned ancestor (.page/.spread, rule above).
|
|
2050
|
-
|
|
2052
|
+
The four insets are the pin box: 0 (the text block's edge) unless an
|
|
2053
|
+
engine set --gp-pin-<edge> on the page root for an edge a pin uses (the
|
|
2054
|
+
art-safe line). Non-auto insets and the explicit centers are
|
|
2055
|
+
load-bearing; see doctrine comment. */
|
|
2051
2056
|
.gp-pin {
|
|
2052
2057
|
position: absolute;
|
|
2053
|
-
|
|
2058
|
+
top: var(--gp-pin-top, 0px);
|
|
2059
|
+
right: var(--gp-pin-right, 0px);
|
|
2060
|
+
bottom: var(--gp-pin-bottom, 0px);
|
|
2061
|
+
left: var(--gp-pin-left, 0px);
|
|
2054
2062
|
align-self: center;
|
|
2055
2063
|
justify-self: center;
|
|
2056
2064
|
margin: 0;
|
|
@@ -2065,6 +2073,16 @@ img.gp-shape {
|
|
|
2065
2073
|
.gp-left { justify-self: start; }
|
|
2066
2074
|
.gp-right { justify-self: end; }
|
|
2067
2075
|
|
|
2076
|
+
/* the escape hatch — the paper's edge, past the printer's safe area: the
|
|
2077
|
+
pin box loses its art-safe insets. Set on the pin itself, so it beats the
|
|
2078
|
+
values the page root hands down. */
|
|
2079
|
+
.gp-pin.gp-flush {
|
|
2080
|
+
--gp-pin-top: 0px;
|
|
2081
|
+
--gp-pin-right: 0px;
|
|
2082
|
+
--gp-pin-bottom: 0px;
|
|
2083
|
+
--gp-pin-left: 0px;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2068
2086
|
/* wrapper-margin neutralization (same pattern and rationale as the
|
|
2069
2087
|
.gp-bleed paragraph-margin note in the doctrine comment; for pin, the
|
|
2070
2088
|
emptied paragraph would otherwise leave a phantom margin gap in flow) */
|
|
@@ -2174,6 +2192,8 @@ var GP_CLASSES = new Set([
|
|
|
2174
2192
|
"gp-small",
|
|
2175
2193
|
"gp-medium",
|
|
2176
2194
|
"gp-large",
|
|
2195
|
+
"gp-xl",
|
|
2196
|
+
"gp-xxl",
|
|
2177
2197
|
"gp-tight",
|
|
2178
2198
|
"gp-loose",
|
|
2179
2199
|
"gp-columns",
|
|
@@ -2190,6 +2210,7 @@ var GP_CLASSES = new Set([
|
|
|
2190
2210
|
"gp-pin",
|
|
2191
2211
|
"gp-top",
|
|
2192
2212
|
"gp-bottom",
|
|
2213
|
+
"gp-flush",
|
|
2193
2214
|
"gp-behind",
|
|
2194
2215
|
"gp-base",
|
|
2195
2216
|
"gp-raised",
|
|
@@ -2203,8 +2224,7 @@ var GP_CLASSES = new Set([
|
|
|
2203
2224
|
"gp-alert-caution",
|
|
2204
2225
|
"gp-page-break",
|
|
2205
2226
|
"gp-column-break",
|
|
2206
|
-
"gp-continued"
|
|
2207
|
-
"gp-flush"
|
|
2227
|
+
"gp-continued"
|
|
2208
2228
|
]);
|
|
2209
2229
|
|
|
2210
2230
|
// src/lib/markdown/table-align.ts
|
|
@@ -2331,6 +2351,21 @@ function hasPinClass(token) {
|
|
|
2331
2351
|
const cls = token.attrGet && token.attrGet("class");
|
|
2332
2352
|
return typeof cls === "string" && cls.split(/\s+/).includes("gp-pin");
|
|
2333
2353
|
}
|
|
2354
|
+
var PIN_EDGES = ["gp-top", "gp-right", "gp-bottom", "gp-left"];
|
|
2355
|
+
var FLUSH_ART_MSG = "`.gp-flush` puts this image on the paper's edge, past the printer's safe area. Printers trim up to 0.125in there, so keep it for art that is meant to bleed off the page.";
|
|
2356
|
+
function checkFlushArt(token, env, line) {
|
|
2357
|
+
if (token.type !== "image")
|
|
2358
|
+
return;
|
|
2359
|
+
const cls = token.attrGet && token.attrGet("class");
|
|
2360
|
+
if (typeof cls !== "string")
|
|
2361
|
+
return;
|
|
2362
|
+
const classes = cls.split(/\s+/);
|
|
2363
|
+
if (!classes.includes("gp-pin") || !classes.includes("gp-flush"))
|
|
2364
|
+
return;
|
|
2365
|
+
if (!classes.some((c) => PIN_EDGES.includes(c)))
|
|
2366
|
+
return;
|
|
2367
|
+
warn3(env, line, "flush_art", FLUSH_ART_MSG);
|
|
2368
|
+
}
|
|
2334
2369
|
function elementNameFor(token) {
|
|
2335
2370
|
switch (token.type) {
|
|
2336
2371
|
case "layout_chapter_open":
|
|
@@ -2390,6 +2425,7 @@ function gpPinScope(md) {
|
|
|
2390
2425
|
if (token.type === "inline" && token.children) {
|
|
2391
2426
|
for (const child of token.children) {
|
|
2392
2427
|
checkUnknownGpClasses(child, state.env, line);
|
|
2428
|
+
checkFlushArt(child, state.env, line);
|
|
2393
2429
|
}
|
|
2394
2430
|
}
|
|
2395
2431
|
}
|
|
@@ -3141,6 +3177,20 @@ function layerSlug(name) {
|
|
|
3141
3177
|
return /^[a-z]/.test(slug) ? slug : `x${slug}`;
|
|
3142
3178
|
}
|
|
3143
3179
|
|
|
3180
|
+
// src/engine/shared/print-area.ts
|
|
3181
|
+
function printAreaMeta(page) {
|
|
3182
|
+
const area = JSON.stringify({
|
|
3183
|
+
width: page.width,
|
|
3184
|
+
height: page.height,
|
|
3185
|
+
bleed: page.bleed ?? 0,
|
|
3186
|
+
safe: page.safe ?? 0,
|
|
3187
|
+
artSafe: page.artSafe,
|
|
3188
|
+
preset: page.preset,
|
|
3189
|
+
spec: page.spec
|
|
3190
|
+
});
|
|
3191
|
+
return `<meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>`;
|
|
3192
|
+
}
|
|
3193
|
+
|
|
3144
3194
|
// src/lib/markdown/assemble.ts
|
|
3145
3195
|
async function assembleBookHtml(opts) {
|
|
3146
3196
|
const title = opts.title ?? "Document";
|
|
@@ -3206,7 +3256,8 @@ ${projectCss.trim()}` : null
|
|
|
3206
3256
|
<html lang="en"${printAttrs}>
|
|
3207
3257
|
<head>
|
|
3208
3258
|
<meta charset="UTF-8">
|
|
3209
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"
|
|
3259
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">${opts.printArea ? `
|
|
3260
|
+
${printAreaMeta(opts.printArea)}` : ""}
|
|
3210
3261
|
<title>${title}</title>${preloadTags}
|
|
3211
3262
|
<style data-project-css>
|
|
3212
3263
|
${inlineCss}
|
|
@@ -3663,6 +3714,7 @@ ${css.trim()}
|
|
|
3663
3714
|
preloadImages: cssAssetCopies.map((c) => c.to),
|
|
3664
3715
|
title: opts.title,
|
|
3665
3716
|
print: opts.print,
|
|
3717
|
+
printArea: opts.printArea,
|
|
3666
3718
|
plugins: opts.plugins,
|
|
3667
3719
|
pluginCss,
|
|
3668
3720
|
annotateSourceChapters: opts.annotateSourceChapters,
|
|
@@ -3675,6 +3727,7 @@ async function renderChaptersToFile(inputDir, outDir, opts = {}) {
|
|
|
3675
3727
|
const html = await renderChapters(inputDir, {
|
|
3676
3728
|
title: opts.title,
|
|
3677
3729
|
print: opts.print,
|
|
3730
|
+
printArea: opts.printArea,
|
|
3678
3731
|
styles: opts.styles,
|
|
3679
3732
|
files: opts.files,
|
|
3680
3733
|
plugins: opts.plugins,
|
|
@@ -3756,6 +3809,118 @@ function resolveDeclaredStyles(rawStyles, baseDir, subject) {
|
|
|
3756
3809
|
// src/lib/extension-manifest.ts
|
|
3757
3810
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
3758
3811
|
import path3 from "node:path";
|
|
3812
|
+
import { satisfies, validRange } from "semver";
|
|
3813
|
+
// package.json
|
|
3814
|
+
var package_default = {
|
|
3815
|
+
name: "gutterpress",
|
|
3816
|
+
version: "0.11.20-alpha.4",
|
|
3817
|
+
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
3818
|
+
author: "itlackey",
|
|
3819
|
+
license: "MPL-2.0",
|
|
3820
|
+
keywords: [
|
|
3821
|
+
"markdown",
|
|
3822
|
+
"pdf",
|
|
3823
|
+
"print",
|
|
3824
|
+
"ghostscript",
|
|
3825
|
+
"book",
|
|
3826
|
+
"publishing",
|
|
3827
|
+
"zine"
|
|
3828
|
+
],
|
|
3829
|
+
repository: {
|
|
3830
|
+
type: "git",
|
|
3831
|
+
url: "https://github.com/dimm-city/gutterpress.git"
|
|
3832
|
+
},
|
|
3833
|
+
homepage: "https://github.com/dimm-city/gutterpress#readme",
|
|
3834
|
+
bugs: {
|
|
3835
|
+
url: "https://github.com/dimm-city/gutterpress/issues"
|
|
3836
|
+
},
|
|
3837
|
+
type: "module",
|
|
3838
|
+
main: "./dist/index.js",
|
|
3839
|
+
types: "./dist/index.d.ts",
|
|
3840
|
+
bin: {
|
|
3841
|
+
gutterpress: "./dist/cli.js"
|
|
3842
|
+
},
|
|
3843
|
+
exports: {
|
|
3844
|
+
".": {
|
|
3845
|
+
types: "./dist/index.d.ts",
|
|
3846
|
+
default: "./dist/index.js"
|
|
3847
|
+
},
|
|
3848
|
+
"./api": {
|
|
3849
|
+
types: "./dist/api/index.d.ts",
|
|
3850
|
+
default: "./dist/api/index.js"
|
|
3851
|
+
},
|
|
3852
|
+
"./render": {
|
|
3853
|
+
types: "./dist/render.d.ts",
|
|
3854
|
+
default: "./dist/render.js"
|
|
3855
|
+
}
|
|
3856
|
+
},
|
|
3857
|
+
files: [
|
|
3858
|
+
"dist/",
|
|
3859
|
+
"README.md",
|
|
3860
|
+
"LICENSE"
|
|
3861
|
+
],
|
|
3862
|
+
scripts: {
|
|
3863
|
+
"build:library": "bun scripts/build-engine-bundles.mjs && rimraf dist && bun build src/index.ts src/api/index.ts --target=node --packages=external --splitting --outdir=dist && bun build src/render.ts --target=node --packages=external --outdir=dist && node scripts/check-render-pure.mjs && tsc -p tsconfig.build.json",
|
|
3864
|
+
build: "bun run build:library && bun build src/cli.ts --target=node --packages=external --splitting --outdir=dist",
|
|
3865
|
+
prepublishOnly: "bun run build",
|
|
3866
|
+
test: "bun test",
|
|
3867
|
+
typecheck: "tsc --noEmit",
|
|
3868
|
+
"typecheck:engine-browser": "tsc --noEmit -p src/engine/browser.tsconfig.json",
|
|
3869
|
+
"parity:gate": "bun scripts/native-parity-gate.ts"
|
|
3870
|
+
},
|
|
3871
|
+
engines: {
|
|
3872
|
+
bun: ">=1.0.0",
|
|
3873
|
+
node: ">=22.0.0"
|
|
3874
|
+
},
|
|
3875
|
+
dependencies: {
|
|
3876
|
+
chokidar: "^5.0.0",
|
|
3877
|
+
citty: "^0.2.0",
|
|
3878
|
+
diff3: "0.0.3",
|
|
3879
|
+
fflate: "0.8.3",
|
|
3880
|
+
glob: "^13.0.0",
|
|
3881
|
+
htmlhint: "^1.9.2",
|
|
3882
|
+
ignore: "^5.3.2",
|
|
3883
|
+
"isomorphic-git": "^1.38.4",
|
|
3884
|
+
"markdown-it": "^14.3.2",
|
|
3885
|
+
"markdown-it-abbr": "^2.0.0",
|
|
3886
|
+
"markdown-it-attrs": "^4.3.0",
|
|
3887
|
+
"markdown-it-deflist": "^3.0.1",
|
|
3888
|
+
"markdown-it-footnote": "^4.0.0",
|
|
3889
|
+
"markdown-it-mark": "^4.0.0",
|
|
3890
|
+
"markdown-it-source-map": "^0.1.1",
|
|
3891
|
+
"markdown-it-sub": "^2.0.0",
|
|
3892
|
+
"markdown-it-sup": "^2.0.0",
|
|
3893
|
+
markdownlint: "^0.40.0",
|
|
3894
|
+
"pdf-lib": "^1.17.1",
|
|
3895
|
+
postcss: "^8.5.18",
|
|
3896
|
+
"resolve.exports": "2.0.3",
|
|
3897
|
+
semver: "7.8.0",
|
|
3898
|
+
tar: "7.5.22",
|
|
3899
|
+
unpdf: "^1.6.2",
|
|
3900
|
+
ws: "^8.21.0",
|
|
3901
|
+
yaml: "^2.8.2"
|
|
3902
|
+
},
|
|
3903
|
+
devDependencies: {
|
|
3904
|
+
"@types/bun": "1.3.14",
|
|
3905
|
+
"@types/markdown-it": "^14.1.2",
|
|
3906
|
+
"@types/node": "^22.0.0",
|
|
3907
|
+
"@types/semver": "^7.7.1",
|
|
3908
|
+
"@types/ws": "^8.5.13",
|
|
3909
|
+
playwright: "^1.60.0",
|
|
3910
|
+
rimraf: "^6.0.0",
|
|
3911
|
+
typescript: "^5"
|
|
3912
|
+
}
|
|
3913
|
+
};
|
|
3914
|
+
|
|
3915
|
+
// src/lib/version.ts
|
|
3916
|
+
var PACKAGE_META = {
|
|
3917
|
+
version: package_default.version ?? "unknown",
|
|
3918
|
+
dependencies: package_default.dependencies ?? {},
|
|
3919
|
+
devDependencies: package_default.devDependencies ?? {}
|
|
3920
|
+
};
|
|
3921
|
+
var PACKAGE_VERSION = PACKAGE_META.version;
|
|
3922
|
+
|
|
3923
|
+
// src/lib/extension-manifest.ts
|
|
3759
3924
|
var EXTENSION_MANIFEST_FILENAME = "package.json";
|
|
3760
3925
|
var GUTTERPRESS_KEY = "gutterpress";
|
|
3761
3926
|
function object(value) {
|
|
@@ -3779,6 +3944,7 @@ function metaFromPackageJson(raw) {
|
|
|
3779
3944
|
...str(pkg.description) ? { description: str(pkg.description) } : {},
|
|
3780
3945
|
...keywords ? { keywords } : {},
|
|
3781
3946
|
...str(pkg.main) ? { main: str(pkg.main) } : {},
|
|
3947
|
+
...str(object(pkg.engines)?.gutterpress) ? { gutterpressRange: str(object(pkg.engines)?.gutterpress) } : {},
|
|
3782
3948
|
..."preview" in gp ? { preview: str(gp.preview) ?? null } : {},
|
|
3783
3949
|
...Array.isArray(gp.styles) ? { styles: declaredList(gp.styles) } : {},
|
|
3784
3950
|
...str(gp.tokensFile) ? { tokensFile: str(gp.tokensFile) } : {},
|
|
@@ -3815,6 +3981,17 @@ function extensionCarries(meta) {
|
|
|
3815
3981
|
function pathEscapesFolder(rel) {
|
|
3816
3982
|
return path3.isAbsolute(rel) || rel.split(/[\\/]/).includes("..");
|
|
3817
3983
|
}
|
|
3984
|
+
function assertSupportsThisGutterpress(meta, ref) {
|
|
3985
|
+
const range = meta.gutterpressRange;
|
|
3986
|
+
if (range === undefined)
|
|
3987
|
+
return;
|
|
3988
|
+
if (!validRange(range)) {
|
|
3989
|
+
throw new Error(`Extension "${ref}" has an invalid engines.gutterpress range "${range}".`);
|
|
3990
|
+
}
|
|
3991
|
+
if (!satisfies(PACKAGE_VERSION, range, { includePrerelease: true })) {
|
|
3992
|
+
throw new Error(`Extension "${ref}" needs Gutterpress ${range} (its package.json engines.gutterpress); ` + `this is Gutterpress ${PACKAGE_VERSION}. Update Gutterpress, or pin an older version of the extension.`);
|
|
3993
|
+
}
|
|
3994
|
+
}
|
|
3818
3995
|
function assertExtensionContained(meta) {
|
|
3819
3996
|
if (meta.engineStyles !== undefined) {
|
|
3820
3997
|
throw new Error("The extension's metadata declares `engineStyles`, which was removed — " + "move its entries to the end of `styles`.");
|
|
@@ -4103,6 +4280,7 @@ This folder still has a ${stale}. Gutterpress no longer reads it — ` + `descri
|
|
|
4103
4280
|
async function loadExtensionFromDir(extensionDir, config, pluginRef) {
|
|
4104
4281
|
const meta = await readExtensionMeta(extensionDir);
|
|
4105
4282
|
assertExtensionContained(meta);
|
|
4283
|
+
assertSupportsThisGutterpress(meta, pluginRef);
|
|
4106
4284
|
const resolved = resolveExtension(extensionDir, meta, `Plugin "${pluginRef}"`);
|
|
4107
4285
|
const extensionStyles = resolved.styles ?? [];
|
|
4108
4286
|
const name = config.name ?? meta.name ?? pluginRef;
|
|
@@ -4177,6 +4355,7 @@ async function loadPlugin(config, baseDir) {
|
|
|
4177
4355
|
if (loaded.packageDir) {
|
|
4178
4356
|
const meta = await readExtensionMeta(loaded.packageDir);
|
|
4179
4357
|
assertExtensionContained(meta);
|
|
4358
|
+
assertSupportsThisGutterpress(meta, pluginRef);
|
|
4180
4359
|
const resolved = resolveExtension(loaded.packageDir, { ...meta, main: undefined }, `Plugin "${pluginRef}"`);
|
|
4181
4360
|
if (resolved.markdown && loaded.entryPath && resolve3(resolved.markdown) !== resolve3(loaded.entryPath)) {
|
|
4182
4361
|
throw new Error(`its package.json declares gutterpress.markdown "${meta.markdown}" but the package entry is "${relative(loaded.packageDir, loaded.entryPath)}" — an npm extension's ` + "markdown-it plugin is its package entry, so declare that file or drop the field.");
|
|
@@ -4307,7 +4486,7 @@ import path5 from "node:path";
|
|
|
4307
4486
|
import { Transform } from "node:stream";
|
|
4308
4487
|
import { pipeline } from "node:stream/promises";
|
|
4309
4488
|
import { createGunzip } from "node:zlib";
|
|
4310
|
-
import { maxSatisfying, satisfies, validRange } from "semver";
|
|
4489
|
+
import { maxSatisfying, satisfies as satisfies2, validRange as validRange2 } from "semver";
|
|
4311
4490
|
|
|
4312
4491
|
// src/lib/npm-registry.ts
|
|
4313
4492
|
var DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
|
|
@@ -4515,7 +4694,7 @@ async function selectPackage(ctx, name, selector) {
|
|
|
4515
4694
|
version = selector;
|
|
4516
4695
|
} else if (typeof tags[selector] === "string") {
|
|
4517
4696
|
version = tags[selector];
|
|
4518
|
-
} else if (
|
|
4697
|
+
} else if (validRange2(selector)) {
|
|
4519
4698
|
version = maxSatisfying(Object.keys(versions), selector) ?? undefined;
|
|
4520
4699
|
}
|
|
4521
4700
|
if (!version || !isExactNpmVersion(version)) {
|
|
@@ -4733,7 +4912,7 @@ async function installPackage(ctx, name, selector, parentPackagePath, ancestors,
|
|
|
4733
4912
|
}
|
|
4734
4913
|
throw error2;
|
|
4735
4914
|
}
|
|
4736
|
-
const ancestor = ancestors.find((candidate) => candidate.name === name && (candidate.version === selected.version || (selector ?
|
|
4915
|
+
const ancestor = ancestors.find((candidate) => candidate.name === name && (candidate.version === selected.version || (selector ? satisfies2(candidate.version, selector) : false)));
|
|
4737
4916
|
if (ancestor)
|
|
4738
4917
|
return { path: ancestor.path };
|
|
4739
4918
|
if (ctx.records.length >= ctx.limits.totalPackages) {
|
|
@@ -6140,117 +6319,6 @@ import { mkdir as mkdir5, readFile as readFile10, writeFile as writeFile4 } from
|
|
|
6140
6319
|
import { createHash as createHash3 } from "node:crypto";
|
|
6141
6320
|
import path10 from "node:path";
|
|
6142
6321
|
import git from "isomorphic-git";
|
|
6143
|
-
// package.json
|
|
6144
|
-
var package_default = {
|
|
6145
|
-
name: "gutterpress",
|
|
6146
|
-
version: "0.11.20-alpha.3",
|
|
6147
|
-
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
6148
|
-
author: "itlackey",
|
|
6149
|
-
license: "MPL-2.0",
|
|
6150
|
-
keywords: [
|
|
6151
|
-
"markdown",
|
|
6152
|
-
"pdf",
|
|
6153
|
-
"print",
|
|
6154
|
-
"ghostscript",
|
|
6155
|
-
"book",
|
|
6156
|
-
"publishing",
|
|
6157
|
-
"zine"
|
|
6158
|
-
],
|
|
6159
|
-
repository: {
|
|
6160
|
-
type: "git",
|
|
6161
|
-
url: "https://github.com/dimm-city/gutterpress.git"
|
|
6162
|
-
},
|
|
6163
|
-
homepage: "https://github.com/dimm-city/gutterpress#readme",
|
|
6164
|
-
bugs: {
|
|
6165
|
-
url: "https://github.com/dimm-city/gutterpress/issues"
|
|
6166
|
-
},
|
|
6167
|
-
type: "module",
|
|
6168
|
-
main: "./dist/index.js",
|
|
6169
|
-
types: "./dist/index.d.ts",
|
|
6170
|
-
bin: {
|
|
6171
|
-
gutterpress: "./dist/cli.js"
|
|
6172
|
-
},
|
|
6173
|
-
exports: {
|
|
6174
|
-
".": {
|
|
6175
|
-
types: "./dist/index.d.ts",
|
|
6176
|
-
default: "./dist/index.js"
|
|
6177
|
-
},
|
|
6178
|
-
"./api": {
|
|
6179
|
-
types: "./dist/api/index.d.ts",
|
|
6180
|
-
default: "./dist/api/index.js"
|
|
6181
|
-
},
|
|
6182
|
-
"./render": {
|
|
6183
|
-
types: "./dist/render.d.ts",
|
|
6184
|
-
default: "./dist/render.js"
|
|
6185
|
-
}
|
|
6186
|
-
},
|
|
6187
|
-
files: [
|
|
6188
|
-
"dist/",
|
|
6189
|
-
"README.md",
|
|
6190
|
-
"LICENSE"
|
|
6191
|
-
],
|
|
6192
|
-
scripts: {
|
|
6193
|
-
"build:library": "bun scripts/build-engine-bundles.mjs && rimraf dist && bun build src/index.ts src/api/index.ts --target=node --packages=external --splitting --outdir=dist && bun build src/render.ts --target=node --packages=external --outdir=dist && node scripts/check-render-pure.mjs && tsc -p tsconfig.build.json",
|
|
6194
|
-
build: "bun run build:library && bun build src/cli.ts --target=node --packages=external --splitting --outdir=dist",
|
|
6195
|
-
prepublishOnly: "bun run build",
|
|
6196
|
-
test: "bun test",
|
|
6197
|
-
typecheck: "tsc --noEmit",
|
|
6198
|
-
"typecheck:engine-browser": "tsc --noEmit -p src/engine/browser.tsconfig.json",
|
|
6199
|
-
"parity:gate": "bun scripts/native-parity-gate.ts"
|
|
6200
|
-
},
|
|
6201
|
-
engines: {
|
|
6202
|
-
bun: ">=1.0.0",
|
|
6203
|
-
node: ">=22.0.0"
|
|
6204
|
-
},
|
|
6205
|
-
dependencies: {
|
|
6206
|
-
chokidar: "^5.0.0",
|
|
6207
|
-
citty: "^0.2.0",
|
|
6208
|
-
diff3: "0.0.3",
|
|
6209
|
-
fflate: "0.8.3",
|
|
6210
|
-
glob: "^13.0.0",
|
|
6211
|
-
htmlhint: "^1.9.2",
|
|
6212
|
-
ignore: "^5.3.2",
|
|
6213
|
-
"isomorphic-git": "^1.38.4",
|
|
6214
|
-
"markdown-it": "^14.3.2",
|
|
6215
|
-
"markdown-it-abbr": "^2.0.0",
|
|
6216
|
-
"markdown-it-attrs": "^4.3.0",
|
|
6217
|
-
"markdown-it-deflist": "^3.0.1",
|
|
6218
|
-
"markdown-it-footnote": "^4.0.0",
|
|
6219
|
-
"markdown-it-mark": "^4.0.0",
|
|
6220
|
-
"markdown-it-source-map": "^0.1.1",
|
|
6221
|
-
"markdown-it-sub": "^2.0.0",
|
|
6222
|
-
"markdown-it-sup": "^2.0.0",
|
|
6223
|
-
markdownlint: "^0.40.0",
|
|
6224
|
-
"pdf-lib": "^1.17.1",
|
|
6225
|
-
postcss: "^8.5.18",
|
|
6226
|
-
"resolve.exports": "2.0.3",
|
|
6227
|
-
semver: "7.8.0",
|
|
6228
|
-
tar: "7.5.22",
|
|
6229
|
-
unpdf: "^1.6.2",
|
|
6230
|
-
ws: "^8.21.0",
|
|
6231
|
-
yaml: "^2.8.2"
|
|
6232
|
-
},
|
|
6233
|
-
devDependencies: {
|
|
6234
|
-
"@types/bun": "1.3.14",
|
|
6235
|
-
"@types/markdown-it": "^14.1.2",
|
|
6236
|
-
"@types/node": "^22.0.0",
|
|
6237
|
-
"@types/semver": "^7.7.1",
|
|
6238
|
-
"@types/ws": "^8.5.13",
|
|
6239
|
-
playwright: "^1.60.0",
|
|
6240
|
-
rimraf: "^6.0.0",
|
|
6241
|
-
typescript: "^5"
|
|
6242
|
-
}
|
|
6243
|
-
};
|
|
6244
|
-
|
|
6245
|
-
// src/lib/version.ts
|
|
6246
|
-
var PACKAGE_META = {
|
|
6247
|
-
version: package_default.version ?? "unknown",
|
|
6248
|
-
dependencies: package_default.dependencies ?? {},
|
|
6249
|
-
devDependencies: package_default.devDependencies ?? {}
|
|
6250
|
-
};
|
|
6251
|
-
var PACKAGE_VERSION = PACKAGE_META.version;
|
|
6252
|
-
|
|
6253
|
-
// src/lib/build-fingerprint.ts
|
|
6254
6322
|
var FINGERPRINT_FILENAME = "build-fingerprint.json";
|
|
6255
6323
|
var VERSION_TIMEOUT_MS = 4000;
|
|
6256
6324
|
function toJsonValue(value) {
|
|
@@ -10646,6 +10714,7 @@ async function renderBook(ctx) {
|
|
|
10646
10714
|
const htmlFile = await renderChaptersToFile(renderDir, workDir, {
|
|
10647
10715
|
title: config.title,
|
|
10648
10716
|
print: config.print,
|
|
10717
|
+
printArea: { ...config.page, preset: config.preset, spec: config.spec },
|
|
10649
10718
|
styles: config.styles,
|
|
10650
10719
|
files: config.source.files,
|
|
10651
10720
|
plugins,
|
|
@@ -10798,7 +10867,7 @@ class PdfOutput {
|
|
|
10798
10867
|
const rawPdf = pdfxMode ? path13.join(stage, "raw.pdf") : path13.resolve(pdfFile);
|
|
10799
10868
|
await fsp2.mkdir(path13.dirname(path13.resolve(pdfFile)), { recursive: true });
|
|
10800
10869
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
10801
|
-
const { buildNativePdf } = await import("./engine-
|
|
10870
|
+
const { buildNativePdf } = await import("./engine-7ha27n2b.js");
|
|
10802
10871
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
10803
10872
|
title: config.title,
|
|
10804
10873
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -11072,6 +11141,7 @@ async function renderPreviewBook(inputPath, config, opts) {
|
|
|
11072
11141
|
return renderChapters(inputPath, {
|
|
11073
11142
|
title: config.title ?? "Document",
|
|
11074
11143
|
print: config.print,
|
|
11144
|
+
printArea: config.printArea,
|
|
11075
11145
|
styles: config.styles,
|
|
11076
11146
|
files: opts.files,
|
|
11077
11147
|
plugins,
|
|
@@ -11086,19 +11156,8 @@ async function renderPreviewBook(inputPath, config, opts) {
|
|
|
11086
11156
|
}
|
|
11087
11157
|
});
|
|
11088
11158
|
}
|
|
11089
|
-
function injectPreviewScripts(html
|
|
11090
|
-
const
|
|
11091
|
-
width: page.width,
|
|
11092
|
-
height: page.height,
|
|
11093
|
-
bleed: page.bleed ?? 0,
|
|
11094
|
-
safe: page.safe ?? 0,
|
|
11095
|
-
artSafe: page.artSafe,
|
|
11096
|
-
preset: page.preset,
|
|
11097
|
-
spec: page.spec
|
|
11098
|
-
}) : "";
|
|
11099
|
-
const meta = area ? ` <meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>
|
|
11100
|
-
` : "";
|
|
11101
|
-
const scripts = meta + ` <script src="/engine/gutterpress-viewer.js"></script>
|
|
11159
|
+
function injectPreviewScripts(html) {
|
|
11160
|
+
const scripts = ` <script src="/engine/gutterpress-viewer.js"></script>
|
|
11102
11161
|
` + `<script src="/preview/scripts/preview-interface.js"></script>
|
|
11103
11162
|
` + `<script src="/preview/scripts/preview-bridge.js"></script>
|
|
11104
11163
|
`;
|
|
@@ -11113,7 +11172,10 @@ async function generateAndWriteHtml(inputPath, tempDir, config, cssAssets, image
|
|
|
11113
11172
|
}
|
|
11114
11173
|
const nextAssets = new Map;
|
|
11115
11174
|
const nextImageRefs = new Set;
|
|
11116
|
-
const html = await renderPreviewBook(inputPath,
|
|
11175
|
+
const html = await renderPreviewBook(inputPath, {
|
|
11176
|
+
...config,
|
|
11177
|
+
printArea: config.page && { ...config.page, preset: config.preset, spec: config.spec }
|
|
11178
|
+
}, {
|
|
11117
11179
|
files: config.source?.files ?? null,
|
|
11118
11180
|
onCssAssets: (copies) => {
|
|
11119
11181
|
for (const copy of copies)
|
|
@@ -11132,7 +11194,7 @@ async function generateAndWriteHtml(inputPath, tempDir, config, cssAssets, image
|
|
|
11132
11194
|
for (const ref of nextImageRefs)
|
|
11133
11195
|
imageRefs.add(ref);
|
|
11134
11196
|
}
|
|
11135
|
-
await fsp3.writeFile(path15.join(tempDir, BOOK_HTML_FILENAME), injectPreviewScripts(html
|
|
11197
|
+
await fsp3.writeFile(path15.join(tempDir, BOOK_HTML_FILENAME), injectPreviewScripts(html), "utf-8");
|
|
11136
11198
|
}
|
|
11137
11199
|
function isDotPathUnderRoot(candidatePath, root) {
|
|
11138
11200
|
const normalizedRoot = root.replace(/\\/g, "/").replace(/\/+$/, "");
|
package/dist/index.js
CHANGED
|
@@ -154,14 +154,14 @@ import {
|
|
|
154
154
|
testRemoteAccess,
|
|
155
155
|
updateExtensions,
|
|
156
156
|
validateProjectExtensions
|
|
157
|
-
} from "./index-
|
|
157
|
+
} from "./index-t13p8y08.js";
|
|
158
158
|
import"./index-ht1bcqdd.js";
|
|
159
159
|
import {
|
|
160
160
|
BUILD_DIAGNOSTIC_CODES
|
|
161
|
-
} from "./index-
|
|
161
|
+
} from "./index-ad95fws8.js";
|
|
162
162
|
import {
|
|
163
163
|
BuildError
|
|
164
|
-
} from "./index-
|
|
164
|
+
} from "./index-gm5xbx5w.js";
|
|
165
165
|
import"./index-sth219v1.js";
|
|
166
166
|
import {
|
|
167
167
|
DEFAULT_PRINT_OPTS,
|
|
@@ -70,6 +70,12 @@ export interface ExtensionMetadata {
|
|
|
70
70
|
* does the merge.
|
|
71
71
|
*/
|
|
72
72
|
snippets?: string;
|
|
73
|
+
/**
|
|
74
|
+
* npm `engines.gutterpress` — the Gutterpress versions the extension works
|
|
75
|
+
* with, as a semver range (e.g. `">=0.11.20-alpha.3"`). Checked when the
|
|
76
|
+
* extension loads ({@link assertSupportsThisGutterpress}).
|
|
77
|
+
*/
|
|
78
|
+
gutterpressRange?: string;
|
|
73
79
|
/**
|
|
74
80
|
* The removed `engineStyles` field (#266), carried through from the
|
|
75
81
|
* `gutterpress` block ONLY so {@link assertExtensionContained} can reject it
|
|
@@ -119,6 +125,13 @@ export declare function extensionCarries(meta: ExtensionMetadata): ExtensionCarr
|
|
|
119
125
|
* doctrine {@link readExtensionMeta}'s tolerant JSON parse already follows).
|
|
120
126
|
*/
|
|
121
127
|
export declare function pathEscapesFolder(rel: string): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Refuse to load an extension whose `engines.gutterpress` range excludes this
|
|
130
|
+
* Gutterpress, so a book built with too old a version fails with the fix
|
|
131
|
+
* instead of quietly printing differently. Prereleases count: 0.12.0-alpha.1
|
|
132
|
+
* satisfies `>=0.11.20`.
|
|
133
|
+
*/
|
|
134
|
+
export declare function assertSupportsThisGutterpress(meta: ExtensionMetadata, ref: string): void;
|
|
122
135
|
/**
|
|
123
136
|
* Every path an extension declares must live INSIDE its own folder — an
|
|
124
137
|
* extension is self-contained by contract (apply/install copies the whole
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type LoadedPlugin } from "./renderer";
|
|
2
2
|
import { type PrintPadding } from "../../engine/shared/synthesis.ts";
|
|
3
|
+
import { type PrintAreaSource } from "../../engine/shared/print-area.ts";
|
|
3
4
|
/** Reader injected by the host: resolve a project-root-relative file → its text. */
|
|
4
5
|
export type ReadText = (relPath: string) => Promise<string>;
|
|
5
6
|
/**
|
|
@@ -9,8 +10,8 @@ export type ReadText = (relPath: string) => Promise<string>;
|
|
|
9
10
|
* `type`s (`ambiguous_marker_token`, `unrecognized_marker_token`,
|
|
10
11
|
* `extra_bare_marker_token`, `unknown_marker`, `nested_spread`,
|
|
11
12
|
* `continue_without_section`, `spread_without_pages`, `spread_eof_close`,
|
|
12
|
-
* `page_outside_spread`, `pin_outside_page`, `unknown_gp_class` —
|
|
13
|
-
* emitted by `gp-pin-scope.js`'s `gp_pin_scope_check`, same as
|
|
13
|
+
* `page_outside_spread`, `pin_outside_page`, `unknown_gp_class`, `flush_art` —
|
|
14
|
+
* the last two emitted by `gp-pin-scope.js`'s `gp_pin_scope_check`, same as
|
|
14
15
|
* `pin_outside_page`, see #226).
|
|
15
16
|
*
|
|
16
17
|
* #240 (declarative container components) adds three more, all emitted by
|
|
@@ -126,6 +127,15 @@ export interface AssembleBookHtmlOptions {
|
|
|
126
127
|
* engine/shared/synthesis.ts) and the two page counts agree.
|
|
127
128
|
*/
|
|
128
129
|
print?: PrintPadding;
|
|
130
|
+
/**
|
|
131
|
+
* The project's print area — the resolved manifest's `page` block plus its
|
|
132
|
+
* preset id and printer spec — written as `<meta name="gp-print-area">`
|
|
133
|
+
* (engine/shared/print-area.ts) into EVERY assembled book, preview, build
|
|
134
|
+
* and publish alike: the preview's print overlays judge the ink against it,
|
|
135
|
+
* and both engines place pinned art on its art-safe line. Metadata only:
|
|
136
|
+
* nothing renders from it but what reads it.
|
|
137
|
+
*/
|
|
138
|
+
printArea?: PrintAreaSource;
|
|
129
139
|
plugins?: LoadedPlugin[];
|
|
130
140
|
pluginCss?: string;
|
|
131
141
|
/** Add a layout-neutral source-file id to source-mapped preview blocks. */
|