gutterpress 0.11.17-alpha.6 → 0.11.17-alpha.7
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.d.ts +2 -2
- package/dist/api/index.js +3 -1
- package/dist/{build-yswp3npj.js → build-nbwgzcgv.js} +3 -3
- package/dist/{cli-jjbeqx94.js → cli-2yvrfr58.js} +1 -1
- package/dist/{cli-an3pxzzk.js → cli-v3xmpvs8.js} +116 -10
- package/dist/{cli-0wtnw98y.js → cli-vsgj1n9s.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-xjgxr88y.js → doctor-dmagdmyw.js} +2 -2
- package/dist/{ext-n664e0ka.js → ext-twnqxfba.js} +3 -3
- package/dist/{index-2vd5b3vy.js → index-k0k4syyd.js} +140 -12
- package/dist/index.js +3 -1
- package/dist/lib/markdown/assemble.d.ts +3 -1
- package/dist/lib/markdown/markers.d.ts +27 -162
- package/dist/lib/markdown/renderer.d.ts +10 -1
- package/dist/lib/snippets.d.ts +23 -0
- package/dist/{new-8xwac8nd.js → new-mvtamd8q.js} +3 -3
- package/dist/{preflight-62c2r37w.js → preflight-et7fnz7v.js} +3 -3
- package/dist/{preview-qdby30fx.js → preview-xzvwzsyz.js} +3 -3
- package/dist/{publish-v9tdq7kc.js → publish-2x100s48.js} +3 -3
- package/dist/render.js +114 -8
- package/dist/{validate-9nszbckg.js → validate-nrpa6kah.js} +3 -3
- package/package.json +1 -1
|
@@ -1184,18 +1184,53 @@ var CORE_DECLARED_MARKERS = {
|
|
|
1184
1184
|
class: "gp-columns",
|
|
1185
1185
|
preset: { variant: "2" },
|
|
1186
1186
|
variants: { 1: "gp-columns-1", 2: "gp-columns-2", 3: "gp-columns-3", 4: "gp-columns-4", 5: "gp-columns-5" }
|
|
1187
|
-
}
|
|
1187
|
+
},
|
|
1188
|
+
page: { variants: { blank: "gp-page-blank", "full-bleed": "gp-page-full-bleed" } }
|
|
1188
1189
|
};
|
|
1190
|
+
var LOCATION_KINDS = ["page", "chapter", "section"];
|
|
1191
|
+
var LOCATION_KEYS = ["variants", "label", "snippet"];
|
|
1192
|
+
function isLocationDeclaration(name, rawDecl) {
|
|
1193
|
+
return LOCATION_KINDS.includes(name) && rawDecl !== null && typeof rawDecl === "object" && !Array.isArray(rawDecl) && Object.hasOwn(rawDecl, "variants") && Object.keys(rawDecl).every((k) => LOCATION_KEYS.includes(k));
|
|
1194
|
+
}
|
|
1195
|
+
function addLocationVariants(kind, rawDecl, pluginName, into) {
|
|
1196
|
+
const { variants, label, snippet } = rawDecl;
|
|
1197
|
+
const where = `Plugin "${pluginName}" declares @${kind} variants`;
|
|
1198
|
+
if (variants === null || typeof variants !== "object" || Array.isArray(variants)) {
|
|
1199
|
+
throw new Error(`${where} that are not a plain object of { word: 'class' }.`);
|
|
1200
|
+
}
|
|
1201
|
+
if (label !== undefined && typeof label !== "string")
|
|
1202
|
+
throw new Error(`${where} with a \`label\` that is not a string.`);
|
|
1203
|
+
if (snippet !== undefined && typeof snippet !== "string")
|
|
1204
|
+
throw new Error(`${where} with a \`snippet\` that is not a string.`);
|
|
1205
|
+
for (const [word, cls] of Object.entries(variants)) {
|
|
1206
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(word)) {
|
|
1207
|
+
throw new Error(`${where} with an invalid word "${word}" — use letters, digits, hyphens and underscores.`);
|
|
1208
|
+
}
|
|
1209
|
+
if (typeof cls !== "string" || !cls.trim()) {
|
|
1210
|
+
throw new Error(`${where}: variant "${word}" needs a non-empty class string.`);
|
|
1211
|
+
}
|
|
1212
|
+
const taken = into[kind].get(word);
|
|
1213
|
+
if (taken) {
|
|
1214
|
+
throw new Error(`@${kind} variant "${word}" is declared by both plugin "${taken.owner}" and plugin "${pluginName}". ` + `Variant words must be unique across every loaded plugin — rename one of them.`);
|
|
1215
|
+
}
|
|
1216
|
+
into[kind].set(word, { class: cls.trim(), owner: pluginName, ...label ? { label } : {}, ...snippet ? { snippet } : {} });
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1189
1219
|
function buildDeclaredMarkerRegistry(sources) {
|
|
1190
1220
|
const rawRegistry = new Map;
|
|
1191
1221
|
const originOf = new Map;
|
|
1222
|
+
const locationVariants = { page: new Map, chapter: new Map, section: new Map };
|
|
1192
1223
|
for (const { pluginName, markers } of [{ pluginName: CORE_MARKER_OWNER, markers: CORE_DECLARED_MARKERS }, ...sources]) {
|
|
1193
1224
|
if (!markers)
|
|
1194
1225
|
continue;
|
|
1195
1226
|
for (const [name, rawDecl] of Object.entries(markers)) {
|
|
1196
1227
|
validateDeclaredMarkerName(name, pluginName);
|
|
1228
|
+
if (isLocationDeclaration(name, rawDecl)) {
|
|
1229
|
+
addLocationVariants(name, rawDecl, pluginName, locationVariants);
|
|
1230
|
+
continue;
|
|
1231
|
+
}
|
|
1197
1232
|
if (KNOWN_KINDS.includes(name) || pluginName !== CORE_MARKER_OWNER && name in CORE_DECLARED_MARKERS) {
|
|
1198
|
-
throw new Error(`Plugin "${pluginName}" declares marker "@${name}", which is a core Gutterpress marker name ` + `(${[...KNOWN_KINDS, ...Object.keys(CORE_DECLARED_MARKERS)].map((k) => `@${k}`).join(", ")}). ` + `Core marker names cannot be shadowed — ` + `rename the plugin's marker.`);
|
|
1233
|
+
throw new Error(`Plugin "${pluginName}" declares marker "@${name}", which is a core Gutterpress marker name ` + `(${[...KNOWN_KINDS, ...Object.keys(CORE_DECLARED_MARKERS).filter((k) => !KNOWN_KINDS.includes(k))].map((k) => `@${k}`).join(", ")}). ` + `Core marker names cannot be shadowed — ` + `rename the plugin's marker.`);
|
|
1199
1234
|
}
|
|
1200
1235
|
if (rawRegistry.has(name)) {
|
|
1201
1236
|
throw new Error(`Marker "@${name}" is declared by both plugin "${originOf.get(name)}" and plugin "${pluginName}". ` + `Declared marker names must be unique across every loaded plugin — rename one of them.`);
|
|
@@ -1208,6 +1243,7 @@ function buildDeclaredMarkerRegistry(sources) {
|
|
|
1208
1243
|
for (const [name, rawDecl] of rawRegistry) {
|
|
1209
1244
|
resolved.set(name, resolveMarkerDeclaration(name, rawDecl, rawRegistry, originOf));
|
|
1210
1245
|
}
|
|
1246
|
+
resolved.locationVariants = locationVariants;
|
|
1211
1247
|
return resolved;
|
|
1212
1248
|
}
|
|
1213
1249
|
function declaredKindWords(declaredMarkers) {
|
|
@@ -1263,6 +1299,9 @@ function scanForUnknownDeclaredMarkers(state, declaredMarkers) {
|
|
|
1263
1299
|
function variantClassFor(decl, word) {
|
|
1264
1300
|
return word && decl.variants && Object.hasOwn(decl.variants, word) ? decl.variants[word] : "";
|
|
1265
1301
|
}
|
|
1302
|
+
function nearVariant(word, variants) {
|
|
1303
|
+
return variants.find((v) => v.toLowerCase() === word.toLowerCase()) || (word.length >= 3 ? nearestDeclaredMarkerName(word, variants) : null);
|
|
1304
|
+
}
|
|
1266
1305
|
function warnUnknownVariant(env, meta, decl) {
|
|
1267
1306
|
const word = meta.name;
|
|
1268
1307
|
if (!word)
|
|
@@ -1270,9 +1309,16 @@ function warnUnknownVariant(env, meta, decl) {
|
|
|
1270
1309
|
const variants = Object.keys(decl.variants || {});
|
|
1271
1310
|
if (variants.includes(word))
|
|
1272
1311
|
return;
|
|
1273
|
-
const near =
|
|
1312
|
+
const near = nearVariant(word, variants);
|
|
1274
1313
|
warn(env, meta.__line, "unknown_variant", `"${word}" is not a variant of @${meta.kind}, so it adds no styling. ` + (variants.length ? `Variants: ${variants.join(", ")}.` : `@${meta.kind} has no variants.`) + (near ? ` Did you mean "${near}"?` : ""), meta);
|
|
1275
1314
|
}
|
|
1315
|
+
function warnNearMissVariant(env, meta, kind, variants) {
|
|
1316
|
+
const words = [...variants.keys()];
|
|
1317
|
+
const near = nearVariant(meta.name, words);
|
|
1318
|
+
if (!near)
|
|
1319
|
+
return;
|
|
1320
|
+
warn(env, meta.__line, "unknown_variant", `"${meta.name}" is not a variant of @${kind}, so it is only a ${kind} name and adds no styling. ` + `Variants: ${words.join(", ")}. Did you mean "${near}"?`, meta);
|
|
1321
|
+
}
|
|
1276
1322
|
function plugin(md, pluginOptions = {}) {
|
|
1277
1323
|
const options = {
|
|
1278
1324
|
preferPagesInSpreads: false,
|
|
@@ -1280,6 +1326,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1280
1326
|
};
|
|
1281
1327
|
const declaredMarkers = options.declaredMarkers instanceof Map && options.declaredMarkers.size > 0 ? options.declaredMarkers : buildDeclaredMarkerRegistry([]);
|
|
1282
1328
|
const declaredWords = declaredKindWords(declaredMarkers);
|
|
1329
|
+
const locationVariants = declaredMarkers.locationVariants || buildDeclaredMarkerRegistry([]).locationVariants;
|
|
1283
1330
|
function markerBlock(state, startLine, endLine, silent) {
|
|
1284
1331
|
const pos = state.bMarks[startLine] + state.tShift[startLine];
|
|
1285
1332
|
const max = state.eMarks[startLine];
|
|
@@ -1463,14 +1510,16 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1463
1510
|
function openChapter(meta) {
|
|
1464
1511
|
const t = new state.Token("layout_chapter_open", "div", 1);
|
|
1465
1512
|
t.meta = { line: meta.__line };
|
|
1466
|
-
const
|
|
1513
|
+
const variant = locationVariants.chapter.get(meta.name);
|
|
1514
|
+
const label = variant ? "" : meta.name;
|
|
1515
|
+
const classes = [variant?.class, meta.attrs?.class].filter(Boolean).join(" ");
|
|
1467
1516
|
addClasses(t, "chapter", classes);
|
|
1468
|
-
attachDataAttrs(t, "chapter",
|
|
1517
|
+
attachDataAttrs(t, "chapter", label, meta.attrs || {});
|
|
1469
1518
|
const explicit = (classes.match(/(?:^|\s)(chapter-\d+)(?=\s|$)/) || [])[1] || "";
|
|
1470
1519
|
const fromAttr = meta.attrs?.ch ? `chapter-${meta.attrs.ch}` : "";
|
|
1471
1520
|
stack.open({
|
|
1472
1521
|
kind: "chapter",
|
|
1473
|
-
label:
|
|
1522
|
+
label: label || "",
|
|
1474
1523
|
counterClass: explicit || fromAttr,
|
|
1475
1524
|
openerEmitted: false
|
|
1476
1525
|
}, t);
|
|
@@ -1494,7 +1543,11 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1494
1543
|
const explicit = meta.attrs && meta.attrs.class ? meta.attrs.class : "";
|
|
1495
1544
|
const counterClass = chapter ? chapter.counterClass : "";
|
|
1496
1545
|
const tokens = explicit ? explicit.split(/\s+/) : [];
|
|
1497
|
-
const
|
|
1546
|
+
const withCounter = counterClass && !tokens.includes(counterClass) ? explicit ? `${explicit} ${counterClass}` : counterClass : explicit;
|
|
1547
|
+
const variant = locationVariants.page.get(meta.name);
|
|
1548
|
+
if (!variant && meta.name)
|
|
1549
|
+
warnNearMissVariant(state.env, meta, "page", locationVariants.page);
|
|
1550
|
+
const merged = [variant?.class, withCounter].filter(Boolean).join(" ");
|
|
1498
1551
|
addClasses(t, "page", merged);
|
|
1499
1552
|
attachDataAttrs(t, "page", meta.name, meta.attrs || {});
|
|
1500
1553
|
const label = chapter ? chapter.label : "";
|
|
@@ -1533,7 +1586,8 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1533
1586
|
function openSection(meta, inColumns = false) {
|
|
1534
1587
|
const t = new state.Token("layout_section_open", "div", 1);
|
|
1535
1588
|
const component = meta.__component || null;
|
|
1536
|
-
|
|
1589
|
+
const variant = component ? null : locationVariants.section.get(meta.name);
|
|
1590
|
+
addClasses(t, "section", [variant?.class, meta.attrs && meta.attrs.class].filter(Boolean).join(" "));
|
|
1537
1591
|
if (component)
|
|
1538
1592
|
attachDataAttrs(t, component.kind, component.variant, meta.attrs || {});
|
|
1539
1593
|
else
|
|
@@ -1620,6 +1674,9 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1620
1674
|
if (spread && spread.noPagesYet) {
|
|
1621
1675
|
warn(state.env, line, "spread_without_pages", "@section inside a spread without an explicit @page. Allowed (adhoc spread), but explicit @page markers give stronger control.", meta);
|
|
1622
1676
|
}
|
|
1677
|
+
if (meta.name && !locationVariants.section.has(meta.name)) {
|
|
1678
|
+
warnNearMissVariant(state.env, meta, "section", locationVariants.section);
|
|
1679
|
+
}
|
|
1623
1680
|
openSection(meta, keep > 0);
|
|
1624
1681
|
continue;
|
|
1625
1682
|
}
|
|
@@ -1744,6 +1801,25 @@ function plugin(md, pluginOptions = {}) {
|
|
|
1744
1801
|
};
|
|
1745
1802
|
md.renderer.rules.layout_marker = () => "";
|
|
1746
1803
|
}
|
|
1804
|
+
var NO_MARGIN_BOXES = [
|
|
1805
|
+
"top-left-corner",
|
|
1806
|
+
"top-left",
|
|
1807
|
+
"top-center",
|
|
1808
|
+
"top-right",
|
|
1809
|
+
"top-right-corner",
|
|
1810
|
+
"bottom-left-corner",
|
|
1811
|
+
"bottom-left",
|
|
1812
|
+
"bottom-center",
|
|
1813
|
+
"bottom-right",
|
|
1814
|
+
"bottom-right-corner",
|
|
1815
|
+
"left-top",
|
|
1816
|
+
"left-middle",
|
|
1817
|
+
"left-bottom",
|
|
1818
|
+
"right-top",
|
|
1819
|
+
"right-middle",
|
|
1820
|
+
"right-bottom"
|
|
1821
|
+
].map((box) => ` @${box} { content: none; }`).join(`
|
|
1822
|
+
`);
|
|
1747
1823
|
var MARKER_CSS = `
|
|
1748
1824
|
/* The UA default of 8px body margin is a screen affordance with no meaning
|
|
1749
1825
|
in paged media, and engines disagree about it: a polyfill that treats the
|
|
@@ -1778,6 +1854,34 @@ body { margin: 0; }
|
|
|
1778
1854
|
:where(p) > :where(img:not([class])) { max-height: calc(var(--gp-content-h) - 4px); object-fit: contain; }
|
|
1779
1855
|
:where(figure) { break-inside: avoid; }
|
|
1780
1856
|
|
|
1857
|
+
/* Core page variants — \`@page blank\` and \`@page full-bleed\` (CORE_DECLARED_MARKERS).
|
|
1858
|
+
Each is the \`.page\` the marker already emits plus one class; the class
|
|
1859
|
+
assigns the page to a NAMED page, and the named \`@page\` block below is
|
|
1860
|
+
plain CSS Paged Media. Authors never write these names.
|
|
1861
|
+
|
|
1862
|
+
SPEC GAP FILLED: none. Named pages (\`@page <name>\`, \`page:\`) and margin
|
|
1863
|
+
box \`content: none\` are standard and implemented in Chromium; this is
|
|
1864
|
+
author vocabulary that expands to them (permanent, like @columns), not a
|
|
1865
|
+
shim, so nothing here is deleted when Chrome catches up. Both pages are
|
|
1866
|
+
named \`gp-\`, which the shrink-to-fit audit (engine/compiler/build.ts)
|
|
1867
|
+
leaves out of its per-page limits, so they cannot loosen it for other pages.
|
|
1868
|
+
|
|
1869
|
+
The folio still COUNTS on these pages (only what is drawn is cleared), and
|
|
1870
|
+
a book that assigns \`page:\` to every \`.page\` in its own unlayered CSS
|
|
1871
|
+
overrides the assignment, as any unlayered rule overrides this layer. */
|
|
1872
|
+
@page gp-page-blank {
|
|
1873
|
+
${NO_MARGIN_BOXES}
|
|
1874
|
+
}
|
|
1875
|
+
.page.gp-page-blank { page: gp-page-blank; }
|
|
1876
|
+
|
|
1877
|
+
/* full-bleed: zero page margin, so the content box IS the sheet. The margin
|
|
1878
|
+
boxes are cleared too — with zero margins they would land on the trim line. */
|
|
1879
|
+
@page gp-page-full-bleed {
|
|
1880
|
+
margin: 0;
|
|
1881
|
+
${NO_MARGIN_BOXES}
|
|
1882
|
+
}
|
|
1883
|
+
.page.gp-page-full-bleed { page: gp-page-full-bleed; }
|
|
1884
|
+
|
|
1781
1885
|
`;
|
|
1782
1886
|
|
|
1783
1887
|
// src/lib/markdown/gutterpress-css.ts
|
|
@@ -2021,6 +2125,8 @@ var GP_CLASSES = new Set([
|
|
|
2021
2125
|
"gp-columns-3",
|
|
2022
2126
|
"gp-columns-4",
|
|
2023
2127
|
"gp-columns-5",
|
|
2128
|
+
"gp-page-blank",
|
|
2129
|
+
"gp-page-full-bleed",
|
|
2024
2130
|
"gp-no-break",
|
|
2025
2131
|
"gp-break-before",
|
|
2026
2132
|
"gp-shape",
|
|
@@ -5641,7 +5747,7 @@ import git from "isomorphic-git";
|
|
|
5641
5747
|
// package.json
|
|
5642
5748
|
var package_default = {
|
|
5643
5749
|
name: "gutterpress",
|
|
5644
|
-
version: "0.11.17-alpha.
|
|
5750
|
+
version: "0.11.17-alpha.7",
|
|
5645
5751
|
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
5646
5752
|
author: "itlackey",
|
|
5647
5753
|
license: "MPL-2.0",
|
|
@@ -12594,8 +12700,11 @@ async function collectLibrary(projectDir) {
|
|
|
12594
12700
|
loaded.push({ entry, source, folder, snippets: snippets2, markers: await declaredMarkers(entry, projectDir) });
|
|
12595
12701
|
}
|
|
12596
12702
|
let registry;
|
|
12703
|
+
let variantRegistry = buildDeclaredMarkerRegistry([]).locationVariants;
|
|
12597
12704
|
try {
|
|
12598
|
-
|
|
12705
|
+
const built = buildDeclaredMarkerRegistry(loaded.flatMap((l) => l.markers ? [{ pluginName: l.entry.label, markers: l.markers }] : []));
|
|
12706
|
+
registry = built;
|
|
12707
|
+
variantRegistry = built.locationVariants;
|
|
12599
12708
|
} catch {
|
|
12600
12709
|
registry = undefined;
|
|
12601
12710
|
}
|
|
@@ -12661,7 +12770,23 @@ async function collectLibrary(projectDir) {
|
|
|
12661
12770
|
component.snippet = best.body;
|
|
12662
12771
|
}
|
|
12663
12772
|
components.sort((a, b) => a.name.localeCompare(b.name));
|
|
12664
|
-
|
|
12773
|
+
const sourceOf = new Map(loaded.map((l) => [l.entry.label, l.source]));
|
|
12774
|
+
const locationVariants = [];
|
|
12775
|
+
for (const kind of ["page", "chapter", "section"]) {
|
|
12776
|
+
for (const [word, v] of variantRegistry[kind]) {
|
|
12777
|
+
const source = sourceOf.get(v.owner) ?? { kind: "core" };
|
|
12778
|
+
locationVariants.push({
|
|
12779
|
+
kind,
|
|
12780
|
+
word,
|
|
12781
|
+
class: v.class,
|
|
12782
|
+
source,
|
|
12783
|
+
...v.label ? { label: v.label } : {},
|
|
12784
|
+
...v.snippet ? { snippet: v.snippet } : {}
|
|
12785
|
+
});
|
|
12786
|
+
}
|
|
12787
|
+
}
|
|
12788
|
+
locationVariants.sort((a, b) => a.kind.localeCompare(b.kind) || a.word.localeCompare(b.word));
|
|
12789
|
+
return { snippets, components, locationVariants };
|
|
12665
12790
|
}
|
|
12666
12791
|
async function listMergedSnippets(projectDir) {
|
|
12667
12792
|
return (await collectLibrary(projectDir)).snippets;
|
|
@@ -12669,6 +12794,9 @@ async function listMergedSnippets(projectDir) {
|
|
|
12669
12794
|
async function listMarkerComponents(projectDir) {
|
|
12670
12795
|
return (await collectLibrary(projectDir)).components;
|
|
12671
12796
|
}
|
|
12797
|
+
async function listLocationVariants(projectDir) {
|
|
12798
|
+
return (await collectLibrary(projectDir)).locationVariants;
|
|
12799
|
+
}
|
|
12672
12800
|
// src/lib/extension-import.ts
|
|
12673
12801
|
import { existsSync as existsSync16 } from "node:fs";
|
|
12674
12802
|
import { cp as cp4, mkdir as mkdir13, mkdtemp as mkdtemp2, readFile as readFile34, rm as rm5, writeFile as writeFile13 } from "node:fs/promises";
|
|
@@ -16871,4 +16999,4 @@ async function setPublishProviderConfig(projectDir, providerId, values) {
|
|
|
16871
16999
|
await writeManifestDoc(file, doc);
|
|
16872
17000
|
return settingsFromDoc(doc);
|
|
16873
17001
|
}
|
|
16874
|
-
export { BUNDLED_EXTENSIONS, isBundledExtension, isPathSpecifier, parseExtensionSpecifier, PRESET_IDS, PRESETS, TARGETS, TARGET_IDS, publishTargetFor, MANIFEST_FILENAMES, hasProjectManifest, loadManifest, loadManifestWithPath, resolveConfig, SYNC_SNAPSHOT_MESSAGE, log, resolveActiveStyles, listProjectStyles, EXTENSION_MANIFEST_FILENAME, readExtensionMeta, extensionStyleList, extensionEntry, extensionCarries, pathEscapesFolder, assertExtensionContained, resolveExtension, DEFAULT_NPM_REGISTRY, npmRegistryUrl, ensureProjectGitignore, EXTENSIONS_DIR, RECOMMENDED_EXTENSIONS, BUILT_IN_STYLE_SET_IDS, sameExtension, listProjectExtensions, describeExtension, setExtensionEnabled, reorderExtensions, removeExtension, addExtension, listNpmVersions, checkExtensionUpdates, updateExtensions, listBuiltInStyleSets, addBuiltInStyleSet, validateProjectExtensions, readExtensionCss, restorePinnedExtensions, restoreFailureMessage, getChecks, getCheckById, resolveCheckSelectors, formatReport, ruleRemoteUrls, ruleRiskyProps, ruleSyntax, checkCss, inspectImage, runChecks, checkToolAvailability, reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, defaultConfigDir, FileTokenStore, extractUrlCredential, getSystemDiagnostics, readPageSetup, setPageSetup, slugifyProjectName, escapeYamlScalar, scaffoldProject, adoptFolder, EXTENSION_KINDS, RESERVED_PREFIX, resolveExtensionPrefix, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, listBuiltInTemplates, saveProjectAsTemplate, listCustomTemplates, importTemplateFromFolder, SNIPPETS_DIR, extractVariables, substituteVariables, listSnippets, saveSnippet, deleteSnippet, listMergedSnippets, listMarkerComponents, importExtensionFromFile, importExtensionFromUrl, MAX_SEARCH_BYTES, SEARCH_KEYWORDS, searchNpmExtensions, setManifestFields, readManifestFields, setActiveStyles, AUTO_SNAPSHOT_DEFAULT_MINUTES, AUTO_SYNC_MIN_MINUTES, AUTO_SYNC_MAX_MINUTES, AUTO_SYNC_DEFAULT_MINUTES, AUTO_SYNC_PUSH_INTERVAL_MINUTES, autoSnapshotDelayMs, autoSyncDelayMs, isGitInternalPath, resolveGitHubClientId, GITHUB_HOST, GitHubAuthProvider, GDRIVE_HOST, resolveGoogleClientId, resolveGoogleClientSecret, GOOGLE_NOT_CONFIGURED_MESSAGE, requireGoogleClientCredentials, pkceChallengeFromVerifier, GoogleAuthProvider, revokeGoogleCredential, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listGitHubRepositories, listRepoBooks, listGitHubBranches, syncProject, refreshRemoteCopies, isValidRepositoryName, setUpOnlineBackup, sanitizeCloneFolderName, cloneRepository, isSshRemoteUrl, testRemoteAccess, knownForgeTokenUrl, connectGenericHost, parseRemoteOrigin, forgeKindForHost, diagnoseProjectRemote, REPAIR_SNAPSHOT_MESSAGE, repairOnlineBackup, scorchedEarth, listPublishProviders, publishProviderFor, resolvePublishFormat, resolvePublishRequest, runPublish, connectPublishProvider, disconnectPublishCredential, PublishSelectionsStore, readPublishSettings, setPublishProviderConfig };
|
|
17002
|
+
export { BUNDLED_EXTENSIONS, isBundledExtension, isPathSpecifier, parseExtensionSpecifier, PRESET_IDS, PRESETS, TARGETS, TARGET_IDS, publishTargetFor, MANIFEST_FILENAMES, hasProjectManifest, loadManifest, loadManifestWithPath, resolveConfig, SYNC_SNAPSHOT_MESSAGE, log, resolveActiveStyles, listProjectStyles, EXTENSION_MANIFEST_FILENAME, readExtensionMeta, extensionStyleList, extensionEntry, extensionCarries, pathEscapesFolder, assertExtensionContained, resolveExtension, DEFAULT_NPM_REGISTRY, npmRegistryUrl, ensureProjectGitignore, EXTENSIONS_DIR, RECOMMENDED_EXTENSIONS, BUILT_IN_STYLE_SET_IDS, sameExtension, listProjectExtensions, describeExtension, setExtensionEnabled, reorderExtensions, removeExtension, addExtension, listNpmVersions, checkExtensionUpdates, updateExtensions, listBuiltInStyleSets, addBuiltInStyleSet, validateProjectExtensions, readExtensionCss, restorePinnedExtensions, restoreFailureMessage, getChecks, getCheckById, resolveCheckSelectors, formatReport, ruleRemoteUrls, ruleRiskyProps, ruleSyntax, checkCss, inspectImage, runChecks, checkToolAvailability, reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, defaultConfigDir, FileTokenStore, extractUrlCredential, getSystemDiagnostics, readPageSetup, setPageSetup, slugifyProjectName, escapeYamlScalar, scaffoldProject, adoptFolder, EXTENSION_KINDS, RESERVED_PREFIX, resolveExtensionPrefix, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, listBuiltInTemplates, saveProjectAsTemplate, listCustomTemplates, importTemplateFromFolder, SNIPPETS_DIR, extractVariables, substituteVariables, listSnippets, saveSnippet, deleteSnippet, listMergedSnippets, listMarkerComponents, listLocationVariants, importExtensionFromFile, importExtensionFromUrl, MAX_SEARCH_BYTES, SEARCH_KEYWORDS, searchNpmExtensions, setManifestFields, readManifestFields, setActiveStyles, AUTO_SNAPSHOT_DEFAULT_MINUTES, AUTO_SYNC_MIN_MINUTES, AUTO_SYNC_MAX_MINUTES, AUTO_SYNC_DEFAULT_MINUTES, AUTO_SYNC_PUSH_INTERVAL_MINUTES, autoSnapshotDelayMs, autoSyncDelayMs, isGitInternalPath, resolveGitHubClientId, GITHUB_HOST, GitHubAuthProvider, GDRIVE_HOST, resolveGoogleClientId, resolveGoogleClientSecret, GOOGLE_NOT_CONFIGURED_MESSAGE, requireGoogleClientCredentials, pkceChallengeFromVerifier, GoogleAuthProvider, revokeGoogleCredential, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listGitHubRepositories, listRepoBooks, listGitHubBranches, syncProject, refreshRemoteCopies, isValidRepositoryName, setUpOnlineBackup, sanitizeCloneFolderName, cloneRepository, isSshRemoteUrl, testRemoteAccess, knownForgeTokenUrl, connectGenericHost, parseRemoteOrigin, forgeKindForHost, diagnoseProjectRemote, REPAIR_SNAPSHOT_MESSAGE, repairOnlineBackup, scorchedEarth, listPublishProviders, publishProviderFor, resolvePublishFormat, resolvePublishRequest, runPublish, connectPublishProvider, disconnectPublishCredential, PublishSelectionsStore, readPublishSettings, setPublishProviderConfig };
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ import {
|
|
|
78
78
|
listCustomTemplates,
|
|
79
79
|
listGitHubBranches,
|
|
80
80
|
listGitHubRepositories,
|
|
81
|
+
listLocationVariants,
|
|
81
82
|
listMarkerComponents,
|
|
82
83
|
listMergedSnippets,
|
|
83
84
|
listNpmVersions,
|
|
@@ -152,7 +153,7 @@ import {
|
|
|
152
153
|
testRemoteAccess,
|
|
153
154
|
updateExtensions,
|
|
154
155
|
validateProjectExtensions
|
|
155
|
-
} from "./index-
|
|
156
|
+
} from "./index-k0k4syyd.js";
|
|
156
157
|
import"./index-ht1bcqdd.js";
|
|
157
158
|
import {
|
|
158
159
|
BUILD_DIAGNOSTIC_CODES
|
|
@@ -271,6 +272,7 @@ export {
|
|
|
271
272
|
listNpmVersions,
|
|
272
273
|
listMergedSnippets,
|
|
273
274
|
listMarkerComponents,
|
|
275
|
+
listLocationVariants,
|
|
274
276
|
listLocalBranches,
|
|
275
277
|
listGitHubRepositories,
|
|
276
278
|
listGitHubBranches,
|
|
@@ -31,7 +31,9 @@ export type ReadText = (relPath: string) => Promise<string>;
|
|
|
31
31
|
* returned something unusable).
|
|
32
32
|
*
|
|
33
33
|
* `unknown_variant` is emitted for a declared marker (container or
|
|
34
|
-
* `section: true`) whose bare word is not one of its declared `variants
|
|
34
|
+
* `section: true`) whose bare word is not one of its declared `variants`, and
|
|
35
|
+
* for an `@page` / `@section` word that is a near-miss of a declared page /
|
|
36
|
+
* section variant (any other word there is a free name and stays silent).
|
|
35
37
|
*
|
|
36
38
|
* There is deliberately no `section_without_page`: a @section with no open
|
|
37
39
|
* @page is valid authoring (17/17 false positives across two real books).
|
|
@@ -12,172 +12,37 @@
|
|
|
12
12
|
* One entry per LOADED plugin that declared a non-empty `markers` export,
|
|
13
13
|
* in plugin load order. A plugin with no `markers` export is simply
|
|
14
14
|
* omitted by the caller — this function never sees it.
|
|
15
|
-
* @
|
|
15
|
+
* @typedef {{ class: string, owner: string, label?: string, snippet?: string }} LocationVariant
|
|
16
|
+
* @returns {Map<string, object> & { locationVariants: { page: Map<string, LocationVariant>, chapter: Map<string, LocationVariant>, section: Map<string, LocationVariant> } }}
|
|
17
|
+
* the container markers (core's `@columns` always), plus the merged
|
|
18
|
+
* `page`/`chapter`/`section` variants as `locationVariants.<kind>: Map<word, { class,
|
|
19
|
+
* owner, label?, snippet? }>` (core's own page variants always).
|
|
16
20
|
*/
|
|
17
21
|
export function buildDeclaredMarkerRegistry(sources: {
|
|
18
22
|
pluginName: string;
|
|
19
23
|
markers: Record<string, unknown>;
|
|
20
|
-
}[]): Map<string, object
|
|
24
|
+
}[]): Map<string, object> & {
|
|
25
|
+
locationVariants: {
|
|
26
|
+
page: Map<string, LocationVariant>;
|
|
27
|
+
chapter: Map<string, LocationVariant>;
|
|
28
|
+
section: Map<string, LocationVariant>;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
21
31
|
export default function plugin(md: any, pluginOptions?: {}): void;
|
|
32
|
+
export const MARKER_CSS: string;
|
|
22
33
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* the CSS Cascade Layers
|
|
32
|
-
* spec unlayered CSS always wins over layered CSS regardless of selector
|
|
33
|
-
* specificity. That is what makes "author wins" true now, not injection
|
|
34
|
-
* order. The `:where()` wrapping on the break/orphan/sizing rules below is
|
|
35
|
-
* a NARROWER, still-necessary guarantee that survives the layer: it keeps
|
|
36
|
-
* this block from out-specificity-ing whatever ELSE an author writes
|
|
37
|
-
* (their own plain `.section { break-inside: ... }`, say) — a concern
|
|
38
|
-
* `@layer` doesn't touch, since two unlayered rules still settle by
|
|
39
|
-
* ordinary specificity between themselves.
|
|
40
|
-
*
|
|
41
|
-
* `.page`/`.spread` are given `position: relative` so they are the containing
|
|
42
|
-
* block for any abspos descendant: a mispinned `bottom: 0` now fails LOCALLY
|
|
43
|
-
* on its own page instead of resolving against the document canvas and
|
|
44
|
-
* painting on the last page of the book.
|
|
45
|
-
*
|
|
46
|
-
* `min-height: var(--gp-content-h)` is the other half of that contract: a
|
|
47
|
-
* page root that only shrink-wraps its text is a containing block whose
|
|
48
|
-
* `bottom` edge is the end of the PROSE, so `.gp-pin .gp-bottom` (and every
|
|
49
|
-
* hand-written `position: absolute; bottom: 0`) lands under the last
|
|
50
|
-
* paragraph instead of at the page foot. Nothing in a continuous document
|
|
51
|
-
* stretches a page root to the page area on its own, so both renderers
|
|
52
|
-
* publish the page CONTENT height as `--gp-content-h` for the page context
|
|
53
|
-
* the element is in
|
|
54
|
-
* (the viewer on each `.gp-strip`; the compiler on `:root` plus every
|
|
55
|
-
* `page:` assignment selector), and custom properties inherit, so this one
|
|
56
|
-
* rule reaches a page root at any wrapper depth. Undefined var (plain
|
|
57
|
-
* markdown-it use, no engine) falls back to `1px`, which the cushion below
|
|
58
|
-
* takes back to zero — the rule is inert outside the pipeline, leaving the
|
|
59
|
-
* page root shrink-wrapped exactly as it is today.
|
|
60
|
-
*
|
|
61
|
-
* It is `min-height`, not `height`: a `.page` whose content runs past one
|
|
62
|
-
* sheet must still fragment normally. The whole rule is `:where()`, so an
|
|
63
|
-
* author who wants any of it back sets their own value at any specificity.
|
|
64
|
-
*
|
|
65
|
-
* `box-sizing` and `display` are what make a page-sized min-height safe, and
|
|
66
|
-
* both were found by MEASURING a real book (docs/fixtures/css-authoring-spike)
|
|
67
|
-
* print one extra sheet without them:
|
|
68
|
-
*
|
|
69
|
-
* - `border-box`, because a page root with padding (that fixture's cover
|
|
70
|
-
* has `padding-top: 2.5in`) would otherwise be one content box PLUS its
|
|
71
|
-
* padding tall, which is one sheet plus 2.5in — the overflow lands on a
|
|
72
|
-
* spurious blank sheet.
|
|
73
|
-
* - `flow-root`, because a child margin collapsing THROUGH the root's edge
|
|
74
|
-
* survives the forced break and eats into the new sheet: that fixture's
|
|
75
|
-
* last page opens with an `<h2>` whose 22.4px margin-top pushed a
|
|
76
|
-
* 719px-tall root down 22.4px on a 720px sheet, spilling it. A page root
|
|
77
|
-
* is a page; containing its children's margins is what a page does. The
|
|
78
|
-
* viewer already forces `flow-root` on displaced page roots for exactly
|
|
79
|
-
* this reason (`stabilizeFullHeightPageRoots`, fragment.ts) — declaring
|
|
80
|
-
* it once in core means both renderers start from the same box. Zero
|
|
81
|
-
* specificity, so an authored `display: flex`/`grid` page root still
|
|
82
|
-
* wins, which is the case that function's comment warns about.
|
|
83
|
-
*
|
|
84
|
-
* The `- 1px` is the fragmentation cushion, and it is load-bearing. A box
|
|
85
|
-
* whose bottom edge lands EXACTLY on the fragmentainer's edge costs an empty
|
|
86
|
-
* fragment: MEASURED (Chromium 148, 384x480px sheet, 24px margins, one
|
|
87
|
-
* short page root) `min-height: 432px` prints 2 sheets with the second
|
|
88
|
-
* blank while `431px` prints 1 — and the viewer's multicol strip does the
|
|
89
|
-
* same, which is how it first showed up (an 8pp preview of a 7pp book on
|
|
90
|
-
* the gp-image-positioning fixture). One px at 96dpi is 0.75pt: it moves a
|
|
91
|
-
* pinned foot up by less than a point and absorbs sub-pixel rounding in the
|
|
92
|
-
* published value. Do not "clean it up" — the sheet it costs is silent.
|
|
93
|
-
*
|
|
94
|
-
* The break/orphan rules below (`break-after` on headings, image sizing)
|
|
95
|
-
* are all `:where()` so they carry zero specificity —
|
|
96
|
-
* author CSS at any specificity wins outright, reusing this same
|
|
97
|
-
* after-author injection point.
|
|
98
|
-
*
|
|
99
|
-
* There is deliberately NO `.section > :first-child { break-before: avoid }`
|
|
100
|
-
* "glue". A first child's break-before propagates to its parent's start
|
|
101
|
-
* edge, so it made the break BEFORE every section `avoid`: a section after
|
|
102
|
-
* other content could not move whole to the next page, and Chromium split it
|
|
103
|
-
* instead, ignoring its own `break-inside: avoid`. Measured with and without
|
|
104
|
-
* (marker-css-section-break.test.ts): it never prevented a stranded top edge
|
|
105
|
-
* or heading. Its one useful side effect, a lead-in paragraph travelling with
|
|
106
|
-
* a following @section that wraps a table, is the explicit rule below.
|
|
107
|
-
*
|
|
108
|
-
* `vertical-align: bottom` on a lone image is a print-correctness rule, not
|
|
109
|
-
* cosmetics. An `<img>` in a `<p>` is inline-level, so its line box adds
|
|
110
|
-
* half-leading/descender space UNDER the image: an image sized to exactly the
|
|
111
|
-
* page content box (a book capping art at `page-height - margins`, or art that
|
|
112
|
-
* naturally fills the page) produces a paragraph a few px TALLER than the box
|
|
113
|
-
* it was sized to fit. MEASURED (Chromium 148, field guide chapter 1, 10in
|
|
114
|
-
* content box): a 956px image made a 963.59px paragraph — a 3.6px overflow
|
|
115
|
-
* that pushed the enclosing named-page wrapper's bottom edge onto the NEXT
|
|
116
|
-
* sheet, so Chromium named that sheet after the PREVIOUS page name and the new
|
|
117
|
-
* template's running head and folio silently vanished. `vertical-align:
|
|
118
|
-
* bottom` collapses the line box onto the image, keeping the image inline (so
|
|
119
|
-
* `text-align: center` still centers it — `display: block` would not).
|
|
120
|
-
*
|
|
121
|
-
* #231 — two engine-generic print fixes adopted from a real book's own
|
|
122
|
-
* engine sheet, because both are written entirely in terms of core's own
|
|
123
|
-
* published contract and fix a failure every book with big art or a
|
|
124
|
-
* `<figure>` hits, not a DC-brand-specific one:
|
|
125
|
-
*
|
|
126
|
-
* - A bare markdown placard (``, no class) taller than the
|
|
127
|
-
* page content box is monolithic replaced content, and the fragmenter
|
|
128
|
-
* SLICES it mid-image across the page break instead of moving it whole.
|
|
129
|
-
* Capping a bare image to `--gp-content-h` (core's own published page
|
|
130
|
-
* CONTENT height for the page context it is in — see the min-height
|
|
131
|
-
* rule above) with `object-fit: contain` letterboxes it onto one page
|
|
132
|
-
* instead. Scoped to `:not([class])` so it never touches a `.gp-full`,
|
|
133
|
-
* `.gp-bleed`, or any other explicitly sized/classed image — an author
|
|
134
|
-
* who already sized their own art has already made the call this rule
|
|
135
|
-
* exists to make for the ones who haven't. `--gp-content-h` is
|
|
136
|
-
* published by BOTH renderers (the compiler on `:root` plus every
|
|
137
|
-
* `page:` assignment selector; the viewer on each `.gp-strip`), so this
|
|
138
|
-
* rule cannot itself split preview from print.
|
|
139
|
-
*
|
|
140
|
-
* MEASURED on the field guide (295pp, adopted verbatim from its own
|
|
141
|
-
* native-furniture.css §9, which carried this exact rule for months):
|
|
142
|
-
* chapter-01's rabbit placard paints 717.0pt tall on the default page
|
|
143
|
-
* both before and after adoption (core's cap and the book's copy agree
|
|
144
|
-
* bit-for-bit — the book's copy is now a harmless duplicate of core's,
|
|
145
|
-
* not a competing rule). Chapter-03's full-sheet plate (an `@page` with
|
|
146
|
-
* zero margins, so the content box IS the sheet) paints 621.0 x 804.0pt
|
|
147
|
-
* inside its 621 x 810pt sheet both before and after — the OLD hand-
|
|
148
|
-
* computed version of this rule (`calc(var(--page-height) - 0.5in -
|
|
149
|
-
* 0.75in - 4px)`, hard-coding the DEFAULT page's margins) over-capped
|
|
150
|
-
* this named page's art to 553.5 x 717.0pt, a 1.3in band of bare wall
|
|
151
|
-
* along its foot; reading the cap off `--gp-content-h` instead fixed
|
|
152
|
-
* that BEFORE core ever adopted the rule, so adoption itself changes
|
|
153
|
-
* nothing further. Total page count unchanged at 295pp — no
|
|
154
|
-
* shrink-to-fit side effect from moving the rule into core.
|
|
155
|
-
*
|
|
156
|
-
* - `figure { break-inside: avoid }` keeps in-flow art (anything an
|
|
157
|
-
* author or a plugin wraps in a real `<figure>`) from being sliced
|
|
158
|
-
* across a page break the same way a bare placard would be — the
|
|
159
|
-
* `:where(p > img:only-child, figure > img)` sizing rule above already
|
|
160
|
-
* assumes the figure survives as one piece; without this it did not.
|
|
161
|
-
*
|
|
162
|
-
* Design-for-deletion note (CLAUDE.md): neither rule is a Chromium-gap shim
|
|
163
|
-
* with a removal trigger — both are permanent, standards-verbatim defaults
|
|
164
|
-
* in the same category as the min-height/box-sizing/vertical-align rules
|
|
165
|
-
* above (real print-fragmentation behavior, not a spec feature Chrome has
|
|
166
|
-
* yet to ship). They stay `:where()` so an author's own sizing or
|
|
167
|
-
* break-inside rule, at ANY specificity, still wins outright.
|
|
168
|
-
*
|
|
169
|
-
* The companion "spanner + unbreakable box" glue pattern (`column-span: all`
|
|
170
|
-
* followed by a `break-inside: avoid` box) was measured for this same adoption pass and DELIBERATELY NOT
|
|
171
|
-
* adopted: a `:where()`-zero-specificity override can never win against
|
|
172
|
-
* whatever real-specificity rule gave the box its `break-inside: avoid` in
|
|
173
|
-
* the first place (a synthetic 2-column fixture with the candidate
|
|
174
|
-
* `:where(.gp-columns-all) + :where(*) { break-inside: auto }` produced
|
|
175
|
-
* BYTE-IDENTICAL output to the same fixture without it, across every
|
|
176
|
-
* geometry swept), and the field guide's own native-furniture.css §13 shows
|
|
177
|
-
* a context-blind version of the same idea is actively wrong for at least
|
|
178
|
-
* one real, shipped case (a short, non-fragmenting instance that needed its
|
|
179
|
-
* `avoid` restored after a general fragmenting-context rule took it away).
|
|
180
|
-
* Core ships no spanner class: a spanning heading is the end of one @columns run and the start of the next.
|
|
181
|
-
*
|
|
34
|
+
* Merge every loaded plugin's `markers` export into ONE flat, resolved
|
|
35
|
+
* registry — `Map<name, ResolvedDecl>` — validating collisions at LOAD TIME
|
|
36
|
+
* (#240 / P2): a declared name that shadows a core reserved name, or that
|
|
37
|
+
* two different plugins both declare, throws immediately, naming both
|
|
38
|
+
* sides, instead of the pre-#240 silent-skip footgun (core claims its
|
|
39
|
+
* `@`-names during block parsing, before any plugin runs, so a colliding
|
|
40
|
+
* plugin marker used to never run and never warn — see the header comment
|
|
41
|
+
* on `KNOWN_KINDS`).
|
|
182
42
|
*/
|
|
183
|
-
export
|
|
43
|
+
export type LocationVariant = {
|
|
44
|
+
class: string;
|
|
45
|
+
owner: string;
|
|
46
|
+
label?: string;
|
|
47
|
+
snippet?: string;
|
|
48
|
+
};
|
|
@@ -241,7 +241,16 @@ export type GutterpressComponentProblem = string | {
|
|
|
241
241
|
};
|
|
242
242
|
/** `validate`'s return value: nothing, one message, or a list of problems. */
|
|
243
243
|
export type GutterpressComponentProblems = GutterpressComponentProblem[] | string | void | null | undefined;
|
|
244
|
-
/**
|
|
244
|
+
/**
|
|
245
|
+
* A plugin's full declared marker table — see {@link GutterpressMarkerDeclaration}.
|
|
246
|
+
*
|
|
247
|
+
* The reserved kinds `page`, `chapter` and `section` may also appear, in a
|
|
248
|
+
* variants-only form: `{ variants: { 'chapter-start': 'dc-page-chapter-start' },
|
|
249
|
+
* label?, snippet? }`. `@page chapter-start` then adds that class to the
|
|
250
|
+
* `.page` (likewise `@chapter`, `@section`), so book CSS styles by location:
|
|
251
|
+
* `.page.dc-page-chapter-start .section { … }`. Any other key on those names
|
|
252
|
+
* is a load error.
|
|
253
|
+
*/
|
|
245
254
|
export type GutterpressMarkerTable = Record<string, GutterpressMarkerDeclaration>;
|
|
246
255
|
/**
|
|
247
256
|
* Full shape a plugin module may export. Only `default` is required.
|
package/dist/lib/snippets.d.ts
CHANGED
|
@@ -93,8 +93,31 @@ export interface MarkerComponent {
|
|
|
93
93
|
/** The winning example snippet's body (book, then extension, then core). */
|
|
94
94
|
snippet?: string;
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* One `page` / `chapter` / `section` variant the book can use (`@page blank`,
|
|
98
|
+
* `@section card`): the bare word, the class it adds, and who declares it.
|
|
99
|
+
* Core's own (`blank`, `full-bleed`) have `source: { kind: "core" }`. `label`
|
|
100
|
+
* and `snippet` are the declaring plugin's group values for that kind, passed
|
|
101
|
+
* through as declared (`snippet` is a path relative to the extension, unread).
|
|
102
|
+
* Data only — what the renderer does with a variant is `markers.js`'s.
|
|
103
|
+
*/
|
|
104
|
+
export interface LocationVariant {
|
|
105
|
+
kind: "page" | "chapter" | "section";
|
|
106
|
+
/** The word after the marker: `@page <word>`. */
|
|
107
|
+
word: string;
|
|
108
|
+
/** The class it adds to the emitted element. */
|
|
109
|
+
class: string;
|
|
110
|
+
source: Extract<SnippetSource, {
|
|
111
|
+
kind: "extension" | "core";
|
|
112
|
+
}>;
|
|
113
|
+
label?: string;
|
|
114
|
+
snippet?: string;
|
|
115
|
+
}
|
|
96
116
|
/** Every snippet the project can insert, from every level — see {@link collectLibrary}. */
|
|
97
117
|
export declare function listMergedSnippets(projectDir: string): Promise<SnippetEntry[]>;
|
|
98
118
|
/** Every component the project's enabled extensions declare, each with its
|
|
99
119
|
* winning example snippet (book > extension > core) — see {@link collectLibrary}. */
|
|
100
120
|
export declare function listMarkerComponents(projectDir: string): Promise<MarkerComponent[]>;
|
|
121
|
+
/** Every `page` / `chapter` / `section` variant the project can use — core's
|
|
122
|
+
* own plus each enabled extension's — see {@link LocationVariant}. */
|
|
123
|
+
export declare function listLocationVariants(projectDir: string): Promise<LocationVariant[]>;
|
|
@@ -7,15 +7,15 @@ import {
|
|
|
7
7
|
TARGET_IDS,
|
|
8
8
|
scaffoldExtension,
|
|
9
9
|
scaffoldProject
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-v3xmpvs8.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveGhostscript
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-vsgj1n9s.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError,
|
|
16
16
|
rejectExtraPositionals,
|
|
17
17
|
rejectUnknownFlags
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-2yvrfr58.js";
|
|
19
19
|
import"./cli-ht1bcqdd.js";
|
|
20
20
|
import"./cli-ycbg7mxk.js";
|
|
21
21
|
import {
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
executeValidation,
|
|
3
3
|
publishTargetFor,
|
|
4
4
|
reportMissingTools
|
|
5
|
-
} from "./cli-
|
|
5
|
+
} from "./cli-v3xmpvs8.js";
|
|
6
6
|
import {
|
|
7
7
|
log
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-vsgj1n9s.js";
|
|
9
9
|
import {
|
|
10
10
|
UsageError,
|
|
11
11
|
rejectExtraPositionals,
|
|
12
12
|
rejectUnknownFlags
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-2yvrfr58.js";
|
|
14
14
|
import"./cli-ht1bcqdd.js";
|
|
15
15
|
import"./cli-ycbg7mxk.js";
|
|
16
16
|
import {
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
runBuild,
|
|
8
8
|
splitOutPath,
|
|
9
9
|
startPreviewServer
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-v3xmpvs8.js";
|
|
11
11
|
import {
|
|
12
12
|
log
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-vsgj1n9s.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError,
|
|
16
16
|
parseFormat,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
rejectExtraPositionals,
|
|
19
19
|
rejectUnknownFlags,
|
|
20
20
|
resolvePort
|
|
21
|
-
} from "./cli-
|
|
21
|
+
} from "./cli-2yvrfr58.js";
|
|
22
22
|
import"./cli-ht1bcqdd.js";
|
|
23
23
|
import"./cli-ycbg7mxk.js";
|
|
24
24
|
import {
|