gutterpress 0.11.23-alpha.7 → 0.11.23-beta.2
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/README.md +3 -1
- package/dist/{README-syg2hn83.md → README-8rct3axy.md} +2 -2
- package/dist/api/index.d.ts +3 -3
- package/dist/api/index.js +8 -6
- package/dist/{build-w572wq10.js → build-3e18wnqj.js} +9 -8
- package/dist/{cli-mmgtqnmr.js → cli-0ep11b0q.js} +1 -1
- package/dist/cli-65gy8ask.js +82 -0
- package/dist/{cli-6pv84kf3.js → cli-88arpdke.js} +6 -84
- package/dist/{cli-eatdqx3z.js → cli-9n9kg58f.js} +1 -1
- package/dist/{cli-58fsk6d7.js → cli-pd2cje5b.js} +187 -44
- package/dist/{cli-3cvq3n1c.js → cli-pnrararp.js} +189 -85
- package/dist/{cli-wyg7qstd.js → cli-tgnyvra3.js} +15 -5
- package/dist/{cli-31anr0r9.js → cli-v0evdpdf.js} +68 -28
- package/dist/{cli-5ba6bm6z.js → cli-x7gcdg6w.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-2f3zqmza.js → doctor-2f4s9dyn.js} +3 -3
- package/dist/engine/compiler/postprocess.d.ts +3 -0
- package/dist/engine/shared/page-vars.d.ts +32 -0
- package/dist/engine/shared/pdf-inspect.d.ts +33 -0
- package/dist/{engine-4rabsgwq.js → engine-c4pxz79g.js} +2 -1
- package/dist/{engine-wm4fggac.js → engine-cs5g2ez0.js} +3 -3
- package/dist/{ext-0cgky8n3.js → ext-70gv86v5.js} +9 -8
- package/dist/{extension-restore-vghc58vx.js → extension-restore-chj5nx3t.js} +3 -3
- package/dist/{extension-restore-e7je32pr.js → extension-restore-pd87p8r2.js} +5 -4
- package/dist/{gutterpress-agent-d29ry3ak.js → gutterpress-agent-wyryqehx.js} +13 -4
- package/dist/{gutterpress-viewer-mafsby5k.js → gutterpress-viewer-ywkf49q5.js} +90 -166
- package/dist/{index-nfysshcc.js → index-0k43evt0.js} +309 -155
- package/dist/{index-wm4x7xbf.js → index-2t1gdma7.js} +178 -35
- package/dist/{index-cw03e9p4.js → index-7j3hkwya.js} +68 -28
- package/dist/{index-fp7xwvpr.js → index-80vg3ed6.js} +15 -5
- package/dist/{index-2vxzxyyj.js → index-swfdgn2n.js} +10 -10
- package/dist/index-tayzfr9c.js +99 -0
- package/dist/{index-hphcn7th.js → index-ytjkvwy5.js} +5 -85
- package/dist/index.d.ts +2 -0
- package/dist/index.js +234 -7
- package/dist/lib/book-css.d.ts +56 -0
- package/dist/lib/markdown/assemble.d.ts +58 -0
- package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
- package/dist/lib/publish/google-drive.d.ts +12 -4
- package/dist/lib/publish/manifest-publish.d.ts +6 -0
- package/dist/lib/publish/providers/gdrive-folder.d.ts +30 -0
- package/dist/lib/publish/run-publish.d.ts +6 -1
- package/dist/lib/publish/types.d.ts +52 -5
- package/dist/lib/remote-auth/converge-merge.d.ts +3 -3
- package/dist/lib/remote-auth/sync-messages.d.ts +2 -2
- package/dist/lib/root-tokens.d.ts +76 -0
- package/dist/lib/source-provider.d.ts +27 -0
- package/dist/lib/version-changes.d.ts +26 -16
- package/dist/{manifest-79zsgkpn.yaml → manifest-0vwaskj2.yaml} +1 -1
- package/dist/{manifest-2kc56wvw.yaml → manifest-aya31jwt.yaml} +1 -1
- package/dist/{manifest-41ddzm13.yaml → manifest-mffah3hr.yaml} +1 -1
- package/dist/{manifest-sqzm4681.yaml → manifest-wbcv8cbp.yaml} +2 -2
- package/dist/{manifest.schema-93sd7zje.json → manifest.schema-0jgj0jt1.json} +1 -1
- package/dist/{new-88rkrv71.js → new-d61n5cn0.js} +9 -8
- package/dist/{page-rules-ytj9p04v.css → page-rules-vnja6grt.css} +2 -2
- package/dist/{plugins-3aj0wc5h.js → plugins-0hhw6s17.js} +1 -1
- package/dist/{plugins-sprxsz5d.js → plugins-e0n46s6m.js} +3 -3
- package/dist/{preflight-11dg1qkk.js → preflight-fjayhjr5.js} +9 -8
- package/dist/{preview-nftp782j.js → preview-h815jrfb.js} +9 -8
- package/dist/{publish-6tgxfck9.js → publish-ft39zgma.js} +25 -9
- package/dist/render.js +77 -26
- package/dist/schema/manifest.types.d.ts +2 -1
- package/dist/{source-provider-n7vehh6t.js → source-provider-j1w7byeq.js} +5 -1
- package/dist/{source-provider-tgzet3j5.js → source-provider-tjaf303m.js} +5 -1
- package/dist/test-helpers/vocabulary.d.ts +12 -0
- package/dist/{tokens-n82t4k9h.css → tokens-a7grv940.css} +4 -5
- package/dist/{validate-pktqrye5.js → validate-b201dbrb.js} +9 -8
- package/package.json +1 -1
- package/dist/index-46ycxe6r.js +0 -18
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// src/lib/build-error.ts
|
|
2
|
+
var EXIT_CODES = {
|
|
3
|
+
OK: 0,
|
|
4
|
+
FINDINGS: 1,
|
|
5
|
+
USAGE: 2,
|
|
6
|
+
PIPELINE: 3
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
class BuildError extends Error {
|
|
10
|
+
exitCode;
|
|
11
|
+
constructor(message, exitCode = EXIT_CODES.PIPELINE, options) {
|
|
12
|
+
super(message, options);
|
|
13
|
+
this.name = "BuildError";
|
|
14
|
+
this.exitCode = exitCode;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/engine/shared/print-area.ts
|
|
19
|
+
function isPositivePoints(value) {
|
|
20
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
21
|
+
}
|
|
22
|
+
function isNonNegativePoints(value) {
|
|
23
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
24
|
+
}
|
|
25
|
+
var round3 = (n) => Math.round(n * 1000) / 1000;
|
|
26
|
+
function cssLength(pt) {
|
|
27
|
+
const inches = round3(pt / 72);
|
|
28
|
+
return Math.abs(inches * 72 - pt) < 0.000001 ? `${inches}in` : `${round3(pt)}pt`;
|
|
29
|
+
}
|
|
30
|
+
function formatPageSize(page) {
|
|
31
|
+
return `${cssLength(page.width)} ${cssLength(page.height)}`;
|
|
32
|
+
}
|
|
33
|
+
function printAreaMeta(page) {
|
|
34
|
+
const area = JSON.stringify({
|
|
35
|
+
width: page.width,
|
|
36
|
+
height: page.height,
|
|
37
|
+
bleed: page.bleed ?? 0,
|
|
38
|
+
safe: page.safe ?? 0,
|
|
39
|
+
artSafe: page.artSafe,
|
|
40
|
+
gutter: page.gutter,
|
|
41
|
+
preset: page.preset,
|
|
42
|
+
spec: page.spec
|
|
43
|
+
});
|
|
44
|
+
return `<meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>`;
|
|
45
|
+
}
|
|
46
|
+
function pageBoxes(area, side, scale = 1) {
|
|
47
|
+
const w = area.width * scale;
|
|
48
|
+
const h = area.height * scale;
|
|
49
|
+
const b = Math.max(0, area.bleed) * scale;
|
|
50
|
+
const s = Math.max(0, area.safe) * scale;
|
|
51
|
+
const a = Math.max(0, area.artSafe) * scale;
|
|
52
|
+
const g = Math.max(0, area.gutter) * scale;
|
|
53
|
+
const [textLeft, textRight] = side === "verso" ? [s, g] : [g, s];
|
|
54
|
+
const [artLeft, artRight] = side === "verso" ? [a, g] : [g, a];
|
|
55
|
+
const trim = { x: side === "verso" ? b : 0, y: b, w: Math.max(0, w - b), h: Math.max(0, h - 2 * b) };
|
|
56
|
+
return {
|
|
57
|
+
sheet: { x: 0, y: 0, w, h },
|
|
58
|
+
trim,
|
|
59
|
+
safe: {
|
|
60
|
+
x: trim.x + textLeft,
|
|
61
|
+
y: trim.y + s,
|
|
62
|
+
w: Math.max(0, trim.w - textLeft - textRight),
|
|
63
|
+
h: Math.max(0, trim.h - 2 * s)
|
|
64
|
+
},
|
|
65
|
+
safeArt: {
|
|
66
|
+
x: trim.x + artLeft,
|
|
67
|
+
y: trim.y + a,
|
|
68
|
+
w: Math.max(0, trim.w - artLeft - artRight),
|
|
69
|
+
h: Math.max(0, trim.h - 2 * a)
|
|
70
|
+
},
|
|
71
|
+
bleed: b
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
var SEVERITY = { inside: 0, unsafe: 1, bleed: 2, "off-page": 3 };
|
|
75
|
+
function judgeRect(r, boxes, rule, tol = 0) {
|
|
76
|
+
const { sheet, trim } = boxes;
|
|
77
|
+
const safe = rule === "art" ? boxes.safeArt : boxes.safe;
|
|
78
|
+
const sides = [
|
|
79
|
+
["left", -r.x, -safe.x, -trim.x, -sheet.x],
|
|
80
|
+
["right", r.x + r.w, safe.x + safe.w, trim.x + trim.w, sheet.x + sheet.w],
|
|
81
|
+
["top", -r.y, -safe.y, -trim.y, -sheet.y],
|
|
82
|
+
["bottom", r.y + r.h, safe.y + safe.h, trim.y + trim.h, sheet.y + sheet.h]
|
|
83
|
+
];
|
|
84
|
+
let worst = { kind: "inside", gap: 0, need: 0, edge: null };
|
|
85
|
+
let beyond = 0;
|
|
86
|
+
for (const [edge, ink, limit, trimEdge, sheetEdge] of sides) {
|
|
87
|
+
const past = ink - limit;
|
|
88
|
+
if (past <= tol || rule === "art" && ink >= sheetEdge - tol)
|
|
89
|
+
continue;
|
|
90
|
+
const kind = ink > sheetEdge + tol ? "off-page" : ink > trimEdge + tol ? "bleed" : "unsafe";
|
|
91
|
+
if (SEVERITY[kind] > SEVERITY[worst.kind] || kind === worst.kind && past > beyond) {
|
|
92
|
+
worst = { kind, gap: trimEdge - ink, need: trimEdge - limit, edge };
|
|
93
|
+
beyond = past;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return worst;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { isPositivePoints, isNonNegativePoints, round3, cssLength, formatPageSize, printAreaMeta, pageBoxes, judgeRect, EXIT_CODES, BuildError };
|
|
@@ -14,11 +14,12 @@ import {
|
|
|
14
14
|
readExtensionMeta,
|
|
15
15
|
resolveExtension,
|
|
16
16
|
slugify
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-80vg3ed6.js";
|
|
18
18
|
import {
|
|
19
19
|
BuildError,
|
|
20
|
-
EXIT_CODES
|
|
21
|
-
|
|
20
|
+
EXIT_CODES,
|
|
21
|
+
isNonNegativePoints
|
|
22
|
+
} from "./index-tayzfr9c.js";
|
|
22
23
|
import {
|
|
23
24
|
EXTENSIONS_DIR,
|
|
24
25
|
VENDORED_NPM_DIR,
|
|
@@ -91,87 +92,6 @@ import { existsSync, statSync } from "node:fs";
|
|
|
91
92
|
import { resolve, dirname } from "node:path";
|
|
92
93
|
import { parse as parseYaml, YAMLParseError } from "yaml";
|
|
93
94
|
|
|
94
|
-
// src/engine/shared/print-area.ts
|
|
95
|
-
function isPositivePoints(value) {
|
|
96
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
97
|
-
}
|
|
98
|
-
function isNonNegativePoints(value) {
|
|
99
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
100
|
-
}
|
|
101
|
-
var round3 = (n) => Math.round(n * 1000) / 1000;
|
|
102
|
-
function cssLength(pt) {
|
|
103
|
-
const inches = round3(pt / 72);
|
|
104
|
-
return Math.abs(inches * 72 - pt) < 0.000001 ? `${inches}in` : `${round3(pt)}pt`;
|
|
105
|
-
}
|
|
106
|
-
function formatPageSize(page) {
|
|
107
|
-
return `${cssLength(page.width)} ${cssLength(page.height)}`;
|
|
108
|
-
}
|
|
109
|
-
function printAreaMeta(page) {
|
|
110
|
-
const area = JSON.stringify({
|
|
111
|
-
width: page.width,
|
|
112
|
-
height: page.height,
|
|
113
|
-
bleed: page.bleed ?? 0,
|
|
114
|
-
safe: page.safe ?? 0,
|
|
115
|
-
artSafe: page.artSafe,
|
|
116
|
-
gutter: page.gutter,
|
|
117
|
-
preset: page.preset,
|
|
118
|
-
spec: page.spec
|
|
119
|
-
});
|
|
120
|
-
return `<meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>`;
|
|
121
|
-
}
|
|
122
|
-
function pageBoxes(area, side, scale = 1) {
|
|
123
|
-
const w = area.width * scale;
|
|
124
|
-
const h = area.height * scale;
|
|
125
|
-
const b = Math.max(0, area.bleed) * scale;
|
|
126
|
-
const s = Math.max(0, area.safe) * scale;
|
|
127
|
-
const a = Math.max(0, area.artSafe) * scale;
|
|
128
|
-
const g = Math.max(0, area.gutter) * scale;
|
|
129
|
-
const [textLeft, textRight] = side === "verso" ? [s, g] : [g, s];
|
|
130
|
-
const [artLeft, artRight] = side === "verso" ? [a, g] : [g, a];
|
|
131
|
-
const trim = { x: side === "verso" ? b : 0, y: b, w: Math.max(0, w - b), h: Math.max(0, h - 2 * b) };
|
|
132
|
-
return {
|
|
133
|
-
sheet: { x: 0, y: 0, w, h },
|
|
134
|
-
trim,
|
|
135
|
-
safe: {
|
|
136
|
-
x: trim.x + textLeft,
|
|
137
|
-
y: trim.y + s,
|
|
138
|
-
w: Math.max(0, trim.w - textLeft - textRight),
|
|
139
|
-
h: Math.max(0, trim.h - 2 * s)
|
|
140
|
-
},
|
|
141
|
-
safeArt: {
|
|
142
|
-
x: trim.x + artLeft,
|
|
143
|
-
y: trim.y + a,
|
|
144
|
-
w: Math.max(0, trim.w - artLeft - artRight),
|
|
145
|
-
h: Math.max(0, trim.h - 2 * a)
|
|
146
|
-
},
|
|
147
|
-
bleed: b
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
var SEVERITY = { inside: 0, unsafe: 1, bleed: 2, "off-page": 3 };
|
|
151
|
-
function judgeRect(r, boxes, rule, tol = 0) {
|
|
152
|
-
const { sheet, trim } = boxes;
|
|
153
|
-
const safe = rule === "art" ? boxes.safeArt : boxes.safe;
|
|
154
|
-
const sides = [
|
|
155
|
-
["left", -r.x, -safe.x, -trim.x, -sheet.x],
|
|
156
|
-
["right", r.x + r.w, safe.x + safe.w, trim.x + trim.w, sheet.x + sheet.w],
|
|
157
|
-
["top", -r.y, -safe.y, -trim.y, -sheet.y],
|
|
158
|
-
["bottom", r.y + r.h, safe.y + safe.h, trim.y + trim.h, sheet.y + sheet.h]
|
|
159
|
-
];
|
|
160
|
-
let worst = { kind: "inside", gap: 0, need: 0, edge: null };
|
|
161
|
-
let beyond = 0;
|
|
162
|
-
for (const [edge, ink, limit, trimEdge, sheetEdge] of sides) {
|
|
163
|
-
const past = ink - limit;
|
|
164
|
-
if (past <= tol || rule === "art" && ink >= sheetEdge - tol)
|
|
165
|
-
continue;
|
|
166
|
-
const kind = ink > sheetEdge + tol ? "off-page" : ink > trimEdge + tol ? "bleed" : "unsafe";
|
|
167
|
-
if (SEVERITY[kind] > SEVERITY[worst.kind] || kind === worst.kind && past > beyond) {
|
|
168
|
-
worst = { kind, gap: trimEdge - ink, need: trimEdge - limit, edge };
|
|
169
|
-
beyond = past;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return worst;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
95
|
// src/constants.ts
|
|
176
96
|
var NETWORK = {
|
|
177
97
|
DEFAULT_PORT: 3579
|
|
@@ -2318,4 +2238,4 @@ async function restoreForCommand(dir, options) {
|
|
|
2318
2238
|
log.warn(problem);
|
|
2319
2239
|
}
|
|
2320
2240
|
|
|
2321
|
-
export {
|
|
2241
|
+
export { DEBOUNCE, UsageError, resolvePort, PRESET_IDS, PRESETS, TARGETS, TARGET_IDS, publishTargetFor, resolveTargets, applyDefaultPdfStrictChecks, MANIFEST_FILENAMES, hasProjectManifest, loadManifest, loadManifestWithPath, resolveConfig, resolveConfigForTarget, MARGIN_EDGES, validatePageMargin, FriendlyHttpError, withFetchTimeout, loadManifestDoc, writeManifestDoc, scalarString, DEFAULT_NPM_REGISTRY, npmRegistryUrl, ensureProjectGitignore, sameExtension, listProjectExtensions, describeExtension, extensionConfigFor, setExtensionEnabled, reorderExtensions, removeExtension, addExtension, listNpmVersions, checkExtensionUpdates, updateExtensions, listBundledExtensions, uniqueExtensionId, validateProjectExtensions, readExtensionCss, readEntryCss, restorePinnedExtensions, restoreFailureMessage, restoreOfflineMessage, restoreForCommand };
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export type { PlatformAdapter, FileStat, FileWriteResult } from "./platform.ts";
|
|
|
26
26
|
export { inspectImage } from "./lib/image-inspect.ts";
|
|
27
27
|
export type { ImageInfo, ColorSpace } from "./lib/image-inspect.ts";
|
|
28
28
|
export { checkCss } from "./lib/printsafe.ts";
|
|
29
|
+
export { readBookCss, bookTokenEdits } from "./lib/book-css.ts";
|
|
30
|
+
export type { BookCss, BookCssChunk, CssChunk, CssChunkOrigin, RootToken, StylesheetEdit, TokenUpdate, } from "./lib/book-css.ts";
|
|
29
31
|
export { BUILD_DIAGNOSTIC_CODES } from "./engine/compiler/build.ts";
|
|
30
32
|
export type { BuildDiagnostic, BuildDiagnosticCode } from "./engine/compiler/build.ts";
|
|
31
33
|
export type { PrintSafeWarning } from "./lib/printsafe.ts";
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
SYNC_SNAPSHOT_MESSAGE,
|
|
22
22
|
VERSION_CHANGES_SHOWN,
|
|
23
23
|
adoptFolder,
|
|
24
|
+
assembleCssChunks,
|
|
24
25
|
autoSnapshotDelayMs,
|
|
25
26
|
autoSyncDelayMs,
|
|
26
27
|
checkCss,
|
|
@@ -70,6 +71,7 @@ import {
|
|
|
70
71
|
listPublishProviders,
|
|
71
72
|
listRepoBooks,
|
|
72
73
|
listSnippets,
|
|
74
|
+
listVersionChanges,
|
|
73
75
|
openPath,
|
|
74
76
|
parseRemoteOrigin,
|
|
75
77
|
pkceChallengeFromVerifier,
|
|
@@ -80,6 +82,7 @@ import {
|
|
|
80
82
|
readPageSetup,
|
|
81
83
|
readPublishSettings,
|
|
82
84
|
refreshRemoteCopies,
|
|
85
|
+
relDisplay,
|
|
83
86
|
renameRevision,
|
|
84
87
|
repairOnlineBackup,
|
|
85
88
|
reportMissingTools,
|
|
@@ -119,7 +122,7 @@ import {
|
|
|
119
122
|
substituteVariables,
|
|
120
123
|
syncProject,
|
|
121
124
|
testRemoteAccess
|
|
122
|
-
} from "./index-
|
|
125
|
+
} from "./index-0k43evt0.js";
|
|
123
126
|
import {
|
|
124
127
|
DEFAULT_NPM_REGISTRY,
|
|
125
128
|
MANIFEST_FILENAMES,
|
|
@@ -149,7 +152,7 @@ import {
|
|
|
149
152
|
setExtensionEnabled,
|
|
150
153
|
updateExtensions,
|
|
151
154
|
validateProjectExtensions
|
|
152
|
-
} from "./index-
|
|
155
|
+
} from "./index-ytjkvwy5.js";
|
|
153
156
|
import {
|
|
154
157
|
BUNDLED_EXTENSIONS,
|
|
155
158
|
EXTENSION_MANIFEST_FILENAME,
|
|
@@ -160,20 +163,21 @@ import {
|
|
|
160
163
|
extensionStyleList,
|
|
161
164
|
isBundledExtension,
|
|
162
165
|
isPathSpecifier,
|
|
166
|
+
loadPluginsWithCss,
|
|
163
167
|
log,
|
|
164
168
|
parseExtensionSpecifier,
|
|
165
169
|
pathEscapesFolder,
|
|
166
170
|
readExtensionMeta,
|
|
167
171
|
resolveExtension
|
|
168
|
-
} from "./index-
|
|
172
|
+
} from "./index-80vg3ed6.js";
|
|
169
173
|
import"./index-ht1bcqdd.js";
|
|
170
174
|
import {
|
|
171
175
|
BUILD_DIAGNOSTIC_CODES
|
|
172
|
-
} from "./index-
|
|
173
|
-
import"./index-
|
|
176
|
+
} from "./index-2t1gdma7.js";
|
|
177
|
+
import"./index-swfdgn2n.js";
|
|
174
178
|
import {
|
|
175
179
|
BuildError
|
|
176
|
-
} from "./index-
|
|
180
|
+
} from "./index-tayzfr9c.js";
|
|
177
181
|
import"./index-5crpmz42.js";
|
|
178
182
|
import {
|
|
179
183
|
DEFAULT_PRINT_OPTS,
|
|
@@ -195,7 +199,7 @@ import {
|
|
|
195
199
|
revisionNameFrom,
|
|
196
200
|
switchBranch,
|
|
197
201
|
whenGitIdle
|
|
198
|
-
} from "./index-
|
|
202
|
+
} from "./index-7j3hkwya.js";
|
|
199
203
|
import {
|
|
200
204
|
EXTENSIONS_DIR
|
|
201
205
|
} from "./index-5x42amh8.js";
|
|
@@ -207,6 +211,226 @@ import {
|
|
|
207
211
|
repoSubPath
|
|
208
212
|
} from "./index-v5mp7a6q.js";
|
|
209
213
|
import"./index-37x76zdn.js";
|
|
214
|
+
// src/lib/book-css.ts
|
|
215
|
+
import { readFile } from "node:fs/promises";
|
|
216
|
+
import path from "node:path";
|
|
217
|
+
|
|
218
|
+
// src/lib/root-tokens.ts
|
|
219
|
+
import postcss from "postcss";
|
|
220
|
+
var DIRECTIVE_RE = /@(group|label|internal)\b[ \t]*([^\n\r@]*)/gi;
|
|
221
|
+
function fold(into, comment) {
|
|
222
|
+
for (const d of comment.matchAll(DIRECTIVE_RE)) {
|
|
223
|
+
const key = d[1].toLowerCase();
|
|
224
|
+
if (key === "internal") {
|
|
225
|
+
into.internal = true;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const value = d[2].trim();
|
|
229
|
+
if (value)
|
|
230
|
+
into[key] = value;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function rootRules(root) {
|
|
234
|
+
const out = [];
|
|
235
|
+
const visit = (container, layer) => {
|
|
236
|
+
container.each((node) => {
|
|
237
|
+
if (node.type === "rule") {
|
|
238
|
+
if (node.selectors.some((s) => s.trim().toLowerCase() === ":root")) {
|
|
239
|
+
out.push(layer === undefined ? { rule: node } : { rule: node, layer });
|
|
240
|
+
}
|
|
241
|
+
} else if (node.type === "atrule" && node.name.toLowerCase() === "layer" && node.nodes) {
|
|
242
|
+
const name = node.params.trim();
|
|
243
|
+
visit(node, layer === undefined ? name : name ? `${layer}.${name}` : layer);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
visit(root, undefined);
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
250
|
+
function leadingComments(rule) {
|
|
251
|
+
const out = [];
|
|
252
|
+
for (let prev = rule.prev();prev?.type === "comment"; prev = prev.prev())
|
|
253
|
+
out.unshift(prev.text);
|
|
254
|
+
return out;
|
|
255
|
+
}
|
|
256
|
+
function writtenValue(decl) {
|
|
257
|
+
return decl.raws.value?.raw ?? decl.value;
|
|
258
|
+
}
|
|
259
|
+
function rootTokens(css) {
|
|
260
|
+
const out = [];
|
|
261
|
+
for (const { rule, layer } of rootRules(postcss.parse(css))) {
|
|
262
|
+
const defaults = {};
|
|
263
|
+
for (const comment of leadingComments(rule))
|
|
264
|
+
fold(defaults, comment);
|
|
265
|
+
let pending = {};
|
|
266
|
+
rule.each((node) => {
|
|
267
|
+
if (node.type === "comment") {
|
|
268
|
+
fold(pending, node.text);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (node.type !== "decl" || !node.prop.startsWith("--"))
|
|
272
|
+
return;
|
|
273
|
+
const own = pending;
|
|
274
|
+
pending = {};
|
|
275
|
+
const annotated = own.group !== undefined || own.label !== undefined;
|
|
276
|
+
if (own.internal || defaults.internal && !annotated)
|
|
277
|
+
return;
|
|
278
|
+
const group = own.group ?? defaults.group;
|
|
279
|
+
out.push({
|
|
280
|
+
name: node.prop,
|
|
281
|
+
value: writtenValue(node),
|
|
282
|
+
...own.label !== undefined ? { label: own.label } : {},
|
|
283
|
+
...group !== undefined ? { group } : {},
|
|
284
|
+
...layer !== undefined ? { layer } : {}
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
289
|
+
}
|
|
290
|
+
function declarationsOf(root, name) {
|
|
291
|
+
return rootRules(root).flatMap(({ rule }) => (rule.nodes ?? []).filter((n) => n.type === "decl" && n.prop === name));
|
|
292
|
+
}
|
|
293
|
+
function removeDeclaration(decl) {
|
|
294
|
+
const rule = decl.parent;
|
|
295
|
+
decl.remove();
|
|
296
|
+
if ((rule.nodes ?? []).length > 0)
|
|
297
|
+
return;
|
|
298
|
+
const parent = rule.parent;
|
|
299
|
+
const next = rule.next();
|
|
300
|
+
const before = rule.raws.before ?? "";
|
|
301
|
+
rule.remove();
|
|
302
|
+
const keep = (after) => before + (after ?? "").replace(/^\n/, "");
|
|
303
|
+
if (next)
|
|
304
|
+
next.raws.before = keep(next.raws.before);
|
|
305
|
+
else
|
|
306
|
+
parent.raws.after = keep(parent.raws.after);
|
|
307
|
+
}
|
|
308
|
+
function insertDeclaration(root, name, value) {
|
|
309
|
+
const rule = rootRules(root)[0]?.rule;
|
|
310
|
+
if (rule) {
|
|
311
|
+
const hadDeclaration = (rule.nodes ?? []).some((n) => n.type === "decl");
|
|
312
|
+
rule.prepend(postcss.decl({ prop: name, value, raws: { before: rule.first?.raws.before ?? `
|
|
313
|
+
`, between: ": " } }));
|
|
314
|
+
if (!hadDeclaration)
|
|
315
|
+
rule.raws.semicolon = true;
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const tail = root.raws.after ?? "";
|
|
319
|
+
const added = postcss.rule({ selector: ":root", raws: { between: " ", after: `
|
|
320
|
+
`, semicolon: true } });
|
|
321
|
+
added.append(postcss.decl({ prop: name, value, raws: { before: `
|
|
322
|
+
`, between: ": " } }));
|
|
323
|
+
root.append(added);
|
|
324
|
+
added.raws.before = tail + ((root.nodes.length > 1 || tail) && !tail.endsWith(`
|
|
325
|
+
`) ? `
|
|
326
|
+
` : "");
|
|
327
|
+
root.raws.after = `
|
|
328
|
+
`;
|
|
329
|
+
}
|
|
330
|
+
function applyTokenUpdates(sheets, target, updates) {
|
|
331
|
+
const roots = sheets.map((css) => postcss.parse(css));
|
|
332
|
+
const changed = new Set;
|
|
333
|
+
for (const { name, value } of updates) {
|
|
334
|
+
const declared = roots.map((root) => declarationsOf(root, name));
|
|
335
|
+
if (value === null) {
|
|
336
|
+
declared.forEach((decls, i) => {
|
|
337
|
+
for (const decl of decls)
|
|
338
|
+
removeDeclaration(decl);
|
|
339
|
+
if (decls.length > 0)
|
|
340
|
+
changed.add(i);
|
|
341
|
+
});
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
let at = declared.length - 1;
|
|
345
|
+
while (at >= 0 && declared[at].length === 0)
|
|
346
|
+
at--;
|
|
347
|
+
if (at >= 0) {
|
|
348
|
+
for (const decl of declared[at])
|
|
349
|
+
decl.value = value;
|
|
350
|
+
changed.add(at);
|
|
351
|
+
} else {
|
|
352
|
+
insertDeclaration(roots[target], name, value);
|
|
353
|
+
changed.add(target);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return sheets.map((css, i) => changed.has(i) ? roots[i].toString() : css);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// src/lib/book-css.ts
|
|
360
|
+
async function readText(file) {
|
|
361
|
+
try {
|
|
362
|
+
return await readFile(file, "utf8");
|
|
363
|
+
} catch (error) {
|
|
364
|
+
if (error.code === "ENOENT")
|
|
365
|
+
return "";
|
|
366
|
+
throw error;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
async function bookSheets(projectDir, styles) {
|
|
370
|
+
return (await resolveActiveStyles(projectDir, styles)).map((rel) => path.resolve(projectDir, rel));
|
|
371
|
+
}
|
|
372
|
+
async function readBookCss(projectDir) {
|
|
373
|
+
const { manifest } = await loadManifestWithPath(projectDir);
|
|
374
|
+
const config = resolveConfig({}, manifest);
|
|
375
|
+
const { pluginStyles } = await loadPluginsWithCss(config.extensions, projectDir, () => {});
|
|
376
|
+
const extensions = [];
|
|
377
|
+
for (const group of pluginStyles) {
|
|
378
|
+
const layered = (css, file) => {
|
|
379
|
+
if (!css.trim())
|
|
380
|
+
return;
|
|
381
|
+
extensions.push({
|
|
382
|
+
origin: { kind: "extension", name: group.name, layer: group.layer, ...file ? { file } : {} },
|
|
383
|
+
css: `@layer ${group.layer} {
|
|
384
|
+
${css.trim()}
|
|
385
|
+
}`
|
|
386
|
+
});
|
|
387
|
+
};
|
|
388
|
+
for (const file of group.paths)
|
|
389
|
+
layered(await readText(file), relDisplay(projectDir, file));
|
|
390
|
+
if (group.css)
|
|
391
|
+
layered(group.css);
|
|
392
|
+
}
|
|
393
|
+
const book = [];
|
|
394
|
+
for (const file of await bookSheets(projectDir, config.styles)) {
|
|
395
|
+
const css = await readText(file);
|
|
396
|
+
if (css.trim())
|
|
397
|
+
book.push({ origin: { kind: "book", file: relDisplay(projectDir, file) }, css });
|
|
398
|
+
}
|
|
399
|
+
const chunks = assembleCssChunks({
|
|
400
|
+
printArea: { ...config.page, preset: config.preset, spec: config.spec },
|
|
401
|
+
extensions,
|
|
402
|
+
book
|
|
403
|
+
});
|
|
404
|
+
return {
|
|
405
|
+
chunks: chunks.map((chunk) => {
|
|
406
|
+
let tokens = [];
|
|
407
|
+
try {
|
|
408
|
+
tokens = rootTokens(chunk.css);
|
|
409
|
+
} catch {}
|
|
410
|
+
return { ...chunk, tokens };
|
|
411
|
+
})
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
async function bookTokenEdits(projectDir, target, updates) {
|
|
415
|
+
const { manifest } = await loadManifestWithPath(projectDir);
|
|
416
|
+
const sheets = await bookSheets(projectDir, Array.isArray(manifest.styles) ? manifest.styles : undefined);
|
|
417
|
+
const at = sheets.indexOf(path.resolve(projectDir, target));
|
|
418
|
+
if (at < 0) {
|
|
419
|
+
throw new Error(`${relDisplay(projectDir, path.resolve(projectDir, target))} is not one of the book's stylesheets.`);
|
|
420
|
+
}
|
|
421
|
+
const before = await Promise.all(sheets.map(readText));
|
|
422
|
+
let after;
|
|
423
|
+
try {
|
|
424
|
+
after = applyTokenUpdates(before, at, updates);
|
|
425
|
+
} catch (error) {
|
|
426
|
+
const e = error;
|
|
427
|
+
const i = e.source === undefined ? -1 : before.indexOf(e.source);
|
|
428
|
+
if (i < 0 || !e.reason)
|
|
429
|
+
throw error;
|
|
430
|
+
throw new Error(`Couldn't read ${relDisplay(projectDir, sheets[i])}${e.line ? ` (line ${e.line})` : ""}: ${e.reason}.`);
|
|
431
|
+
}
|
|
432
|
+
return sheets.flatMap((file, i) => after[i] === before[i] ? [] : [{ path: file, content: after[i] }]);
|
|
433
|
+
}
|
|
210
434
|
export {
|
|
211
435
|
whenGitIdle,
|
|
212
436
|
validateProjectExtensions,
|
|
@@ -271,6 +495,7 @@ export {
|
|
|
271
495
|
readManifestFields,
|
|
272
496
|
readExtensionMeta,
|
|
273
497
|
readExtensionCss,
|
|
498
|
+
readBookCss,
|
|
274
499
|
publishTargetFor,
|
|
275
500
|
publishProviderFor,
|
|
276
501
|
publishCredentialKey,
|
|
@@ -285,6 +510,7 @@ export {
|
|
|
285
510
|
log,
|
|
286
511
|
loadManifestWithPath,
|
|
287
512
|
loadManifest,
|
|
513
|
+
listVersionChanges,
|
|
288
514
|
listSnippets,
|
|
289
515
|
listRevisions,
|
|
290
516
|
listRepoBooks,
|
|
@@ -352,6 +578,7 @@ export {
|
|
|
352
578
|
checkCss,
|
|
353
579
|
capabilitiesFor,
|
|
354
580
|
bundledExtension,
|
|
581
|
+
bookTokenEdits,
|
|
355
582
|
autoSyncDelayMs,
|
|
356
583
|
autoSnapshotDelayMs,
|
|
357
584
|
assertMilestone,
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The book's stylesheet as Book setup's design settings see it, and their one
|
|
3
|
+
* writer (#454).
|
|
4
|
+
*
|
|
5
|
+
* What the settings show is what the build assembles: core's CSS, every
|
|
6
|
+
* enabled extension's CSS — its stylesheet files and its `css` export,
|
|
7
|
+
* through the same loader the build uses, each in its cascade layer — then
|
|
8
|
+
* every one of the book's own `styles:` sheets, in the order
|
|
9
|
+
* `assembleCssChunks` gives them. A file's chunk is the file as written, so a
|
|
10
|
+
* value reads back as the author typed it: the build's inlining (fonts and
|
|
11
|
+
* images embedded, local `@import`s followed) is left out here.
|
|
12
|
+
*
|
|
13
|
+
* Writes go to the book's own `styles:` sheets only, never to an extension's
|
|
14
|
+
* files or a sheet the build does not use, with a postcss edit
|
|
15
|
+
* (`root-tokens.ts`).
|
|
16
|
+
*/
|
|
17
|
+
import { type CssChunk } from "./markdown/assemble.ts";
|
|
18
|
+
import { type RootToken, type TokenUpdate } from "./root-tokens.ts";
|
|
19
|
+
export type { RootToken, TokenUpdate } from "./root-tokens.ts";
|
|
20
|
+
export type { CssChunk, CssChunkOrigin } from "./markdown/assemble.ts";
|
|
21
|
+
/** One chunk of the book's stylesheet and the root-level custom properties it declares. */
|
|
22
|
+
export interface BookCssChunk extends CssChunk {
|
|
23
|
+
/**
|
|
24
|
+
* Its root-level `:root` custom properties, in source order (`@internal`
|
|
25
|
+
* ones left out). Empty for a chunk postcss cannot parse: the print-safety
|
|
26
|
+
* check reports that one.
|
|
27
|
+
*/
|
|
28
|
+
tokens: RootToken[];
|
|
29
|
+
}
|
|
30
|
+
/** The book's stylesheet, in cascade order. */
|
|
31
|
+
export interface BookCss {
|
|
32
|
+
/** Joined with blank lines, the chunks cascade as the built book's stylesheet does. */
|
|
33
|
+
chunks: BookCssChunk[];
|
|
34
|
+
}
|
|
35
|
+
/** One stylesheet the token writer changed: its absolute path and new text. */
|
|
36
|
+
export interface StylesheetEdit {
|
|
37
|
+
path: string;
|
|
38
|
+
content: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The book's stylesheet as ordered chunks tagged with their origin, each with
|
|
42
|
+
* its root-level custom properties. An extension that cannot load (not
|
|
43
|
+
* downloaded yet, a broken folder) is left out, as the live preview leaves it
|
|
44
|
+
* out; Book setup's Extensions tab reports it. Throws for a manifest the
|
|
45
|
+
* build would refuse.
|
|
46
|
+
*/
|
|
47
|
+
export declare function readBookCss(projectDir: string): Promise<BookCss>;
|
|
48
|
+
/**
|
|
49
|
+
* Apply token edits to the book's own stylesheets with postcss
|
|
50
|
+
* (`applyTokenUpdates`): a token is changed in place in the last of them that
|
|
51
|
+
* declares it at root level, and a new one is added to the `:root` of
|
|
52
|
+
* `target`, which must be one of them. A removal takes the token out of all
|
|
53
|
+
* of them. Returns the sheets that change, with their new text, for the
|
|
54
|
+
* caller to write; nothing is written here.
|
|
55
|
+
*/
|
|
56
|
+
export declare function bookTokenEdits(projectDir: string, target: string, updates: TokenUpdate[]): Promise<StylesheetEdit[]>;
|
|
@@ -167,6 +167,64 @@ export interface AssembleBookHtmlOptions {
|
|
|
167
167
|
*/
|
|
168
168
|
onImageRefs?: (refs: string[]) => void;
|
|
169
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Split a stylesheet into everything but its `@page` rules, and its `@page`
|
|
172
|
+
* rules, which the caller writes after it, unlayered, in source order. A
|
|
173
|
+
* rule inside an `@layer` loses that layer; one inside `@media` or
|
|
174
|
+
* `@supports` keeps the condition. CSS postcss cannot read is left as it was.
|
|
175
|
+
*
|
|
176
|
+
* Chromium ranks `@page` declarations by cascade layer before page name, so a
|
|
177
|
+
* layered `@page full { margin: 0 }` lost to the manifest's unlayered
|
|
178
|
+
* `@page { margin }` on its own pages, while the engine's reader, which
|
|
179
|
+
* ignores layers, kept it (#454). So no `@page` rule is written inside a
|
|
180
|
+
* layer — core's, an extension's or one in a layer the book declares —
|
|
181
|
+
* except core's 1in default (`defaultPageMarginCss`), which must lose to all
|
|
182
|
+
* of them.
|
|
183
|
+
* Unlayered, page rules cascade by page selector, then order: a named page
|
|
184
|
+
* keeps its margins, and the book's own sheet and the manifest, written
|
|
185
|
+
* later, still win on the pages they share with it.
|
|
186
|
+
*/
|
|
187
|
+
export declare function liftPageRules(css: string): {
|
|
188
|
+
layered: string;
|
|
189
|
+
pages: string;
|
|
190
|
+
};
|
|
191
|
+
/** Where one chunk of a book's stylesheet comes from. */
|
|
192
|
+
export type CssChunkOrigin = {
|
|
193
|
+
kind: "core";
|
|
194
|
+
}
|
|
195
|
+
/** One extension's CSS: `file` (project-relative) for one of its stylesheets, none for its `css` export. */
|
|
196
|
+
| {
|
|
197
|
+
kind: "extension";
|
|
198
|
+
name?: string;
|
|
199
|
+
layer?: string;
|
|
200
|
+
file?: string;
|
|
201
|
+
}
|
|
202
|
+
/** One of the book's own `styles:` sheets (project-relative). */
|
|
203
|
+
| {
|
|
204
|
+
kind: "book";
|
|
205
|
+
file?: string;
|
|
206
|
+
};
|
|
207
|
+
/** One piece of a book's stylesheet, tagged with where it comes from. */
|
|
208
|
+
export interface CssChunk {
|
|
209
|
+
origin: CssChunkOrigin;
|
|
210
|
+
css: string;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* A book's stylesheet as ordered chunks, each tagged with its origin, in
|
|
214
|
+
* cascade order (see the note where {@link assembleBookHtml} calls this).
|
|
215
|
+
* Joined with blank lines, the chunks are the `<style data-project-css>`
|
|
216
|
+
* block that function writes; it passes the extensions' CSS and the book's
|
|
217
|
+
* whole, one chunk each. Book setup's design settings pass them one extension
|
|
218
|
+
* file and one book sheet at a time, so each setting can say where it comes
|
|
219
|
+
* from (`book-css.ts`).
|
|
220
|
+
*/
|
|
221
|
+
export declare function assembleCssChunks(opts: {
|
|
222
|
+
printArea?: PrintAreaSource;
|
|
223
|
+
/** The extensions' CSS, already in their cascade layers, in `extensions:` order. */
|
|
224
|
+
extensions?: CssChunk[];
|
|
225
|
+
/** The book's own stylesheets, in `styles:` order. */
|
|
226
|
+
book?: CssChunk[];
|
|
227
|
+
}): CssChunk[];
|
|
170
228
|
/**
|
|
171
229
|
* Assemble a single `book.html` string from the given markdown files.
|
|
172
230
|
*
|