gutterpress 0.11.22 → 0.11.23-alpha.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 +23 -24
- package/dist/{README-3nj919rm.md → README-8ef336pp.md} +1 -1
- package/dist/api/index.d.ts +4 -4
- package/dist/api/index.js +16 -22
- package/dist/{build-53bw14h7.js → build-encgnv0c.js} +9 -10
- package/dist/{chapter-01-rkpyvjna.md → chapter-01-gsbjt584.md} +1 -1
- package/dist/chapter-01-s71xrf5q.md +69 -0
- package/dist/{chapter-01-7jwqg1ct.md → chapter-01-wgjfz4w6.md} +1 -1
- package/dist/checks/source/character-table.d.ts +12 -6
- package/dist/{cli-habkc5ng.js → cli-a35w7wzg.js} +5 -4
- package/dist/{cli-kx4hbnx2.js → cli-aqh6brew.js} +1 -1
- package/dist/{cli-1hxxwbaq.js → cli-evg8sbht.js} +1 -1
- package/dist/{cli-cjftezxr.js → cli-kh8v4vvw.js} +2 -1
- package/dist/{cli-ntwqmdnw.js → cli-pwwfxdgb.js} +846 -13
- package/dist/{cli-8kg0wjdt.js → cli-pz4bn98t.js} +185 -9
- package/dist/{cli-zj5xaepv.js → cli-sdmv4bba.js} +57 -117
- package/dist/{cli-ke86zsz6.js → cli-xq6djqbj.js} +51 -54
- package/dist/{index-r7jcsk6h.js → cli-y28j019d.js} +19 -10
- package/dist/cli.js +12 -12
- package/dist/{doctor-xka1frnx.js → doctor-5gtpgpd1.js} +3 -3
- package/dist/{engine-p93f06gj.js → engine-mc5br8g8.js} +1 -2
- package/dist/{engine-0ndvy8vj.js → engine-tn13gk0b.js} +3 -3
- package/dist/{ext-dwfqyy1j.js → ext-wn2a5afq.js} +18 -33
- package/dist/{extension-restore-ct1wk344.js → extension-restore-g8jnmmzq.js} +5 -6
- package/dist/{extension-restore-7vp3vh77.js → extension-restore-s3x1618g.js} +4 -4
- package/dist/{index-apc8w9w8.js → index-0skhjx3e.js} +180 -1
- package/dist/{index-4v7e621e.js → index-2bjcghze.js} +847 -13
- package/dist/index-46ycxe6r.js +18 -0
- package/dist/{index-53nrm5j1.js → index-4x6y8krm.js} +2 -4
- package/dist/{cli-h3phdstf.js → index-5x42amh8.js} +19 -10
- package/dist/{index-93pqkvty.js → index-h6yk5tjx.js} +5 -4
- package/dist/{index-kh7fayjv.js → index-j5z86r4a.js} +57 -54
- package/dist/{index-6cmn2wpd.js → index-x3ema2w3.js} +69 -128
- package/dist/index.js +17 -23
- package/dist/lib/build-runner.d.ts +1 -1
- package/dist/lib/extension-manager.d.ts +16 -43
- package/dist/lib/extension-scaffold.d.ts +3 -3
- package/dist/lib/extension-specifier.d.ts +23 -6
- package/dist/lib/markdown/assemble.d.ts +7 -1
- package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
- package/dist/lib/markdown/index.d.ts +4 -0
- package/dist/lib/markdown/math.d.ts +43 -0
- package/dist/lib/markdown/renderer.d.ts +11 -8
- package/dist/lib/markdown/table.d.ts +46 -0
- package/dist/lib/markdown/typography.d.ts +12 -0
- package/dist/lib/npm-plugin-installer.d.ts +1 -1
- package/dist/lib/plugin-vendor.d.ts +11 -3
- package/dist/lib/presets.d.ts +1 -1
- package/dist/lib/project-gitignore.d.ts +2 -2
- package/dist/lib/project-scaffold.d.ts +6 -8
- package/dist/lib/project-templates.d.ts +6 -1
- package/dist/lib/snippets.d.ts +2 -1
- package/dist/lib/style-resolver.d.ts +1 -2
- package/dist/manifest-eagfhba6.yaml +19 -0
- package/dist/{manifest.schema-399bx3vc.json → manifest.schema-t7nx2stg.json} +12 -5
- package/dist/{new-1pawj2qf.js → new-mhs46pw3.js} +22 -21
- package/dist/{plugins-fr4fnzhb.js → plugins-1sxe0dkz.js} +4 -4
- package/dist/{plugins-g4dgw7mn.js → plugins-2cek4mz1.js} +2 -2
- package/dist/{preflight-ept9q57t.js → preflight-3k2b1x8e.js} +9 -10
- package/dist/preview/file-watcher.d.ts +1 -0
- package/dist/{preview-fxpnjv7k.js → preview-6p9v6rht.js} +9 -10
- package/dist/{publish-zhqqsgmr.js → publish-qgsngy8s.js} +9 -10
- package/dist/render.js +470 -11
- package/dist/schema/manifest.types.d.ts +8 -0
- package/dist/{source-provider-qbfknhyy.js → source-provider-98k5deda.js} +2 -2
- package/dist/{source-provider-2r74a7wp.js → source-provider-knmcam50.js} +2 -2
- package/dist/{validate-t68gvckq.js → validate-0v7xw6wa.js} +9 -10
- package/package.json +2 -1
- package/dist/cli-1ngqzg8s.js +0 -196
- package/dist/index-vay3ff1f.js +0 -213
- package/dist/package-97gm31sg.json +0 -10
- package/dist/package-gag6ykwn.json +0 -10
- package/dist/package-nrhkwf2m.json +0 -10
- package/dist/theme-h5recz6c.css +0 -61
- package/dist/theme-j2bagrfx.css +0 -59
- package/dist/theme-nn6d53zy.css +0 -71
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BUNDLED_EXTENSIONS,
|
|
2
3
|
EXTENSION_MANIFEST_FILENAME,
|
|
3
4
|
TWO_VERSIONS_OPEN,
|
|
5
|
+
bundledExtension,
|
|
4
6
|
extensionCarries,
|
|
5
7
|
extensionStyleList,
|
|
8
|
+
isPathSpecifier,
|
|
6
9
|
loadPlugin,
|
|
7
10
|
log,
|
|
11
|
+
parseExtensionSpecifier,
|
|
12
|
+
pinnedNpmSpecifier,
|
|
8
13
|
prettify,
|
|
9
14
|
readExtensionMeta,
|
|
10
15
|
resolveExtension,
|
|
11
16
|
slugify
|
|
12
|
-
} from "./index-
|
|
17
|
+
} from "./index-2bjcghze.js";
|
|
13
18
|
import {
|
|
14
19
|
BuildError,
|
|
15
|
-
EXIT_CODES
|
|
16
|
-
|
|
17
|
-
} from "./index-vay3ff1f.js";
|
|
20
|
+
EXIT_CODES
|
|
21
|
+
} from "./index-46ycxe6r.js";
|
|
18
22
|
import {
|
|
19
|
-
|
|
23
|
+
EXTENSIONS_DIR,
|
|
20
24
|
VENDORED_NPM_DIR,
|
|
21
25
|
assertWindowsSafeRelativePath,
|
|
22
26
|
isExactNpmVersion,
|
|
@@ -25,8 +29,9 @@ import {
|
|
|
25
29
|
resolveVendoredPluginInstallRoot,
|
|
26
30
|
vendoredNpmPluginPackageDir,
|
|
27
31
|
vendoredNpmPluginRoot,
|
|
32
|
+
vendoredNpmPluginRoots,
|
|
28
33
|
windowsPathKey
|
|
29
|
-
} from "./index-
|
|
34
|
+
} from "./index-5x42amh8.js";
|
|
30
35
|
import {
|
|
31
36
|
__require
|
|
32
37
|
} from "./index-37x76zdn.js";
|
|
@@ -68,7 +73,7 @@ async function withFetchTimeout(options, run) {
|
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
// src/lib/extension-manager.ts
|
|
71
|
-
import {
|
|
76
|
+
import { readdir, readFile as readFile5, rm as rm3, stat } from "node:fs/promises";
|
|
72
77
|
import { existsSync as existsSync3 } from "node:fs";
|
|
73
78
|
import path4 from "node:path";
|
|
74
79
|
import { isSeq as isSeq2, isMap, isScalar, YAMLMap, Scalar } from "yaml";
|
|
@@ -86,43 +91,6 @@ import { existsSync, statSync } from "node:fs";
|
|
|
86
91
|
import { resolve, dirname } from "node:path";
|
|
87
92
|
import { parse as parseYaml, YAMLParseError } from "yaml";
|
|
88
93
|
|
|
89
|
-
// src/lib/extension-specifier.ts
|
|
90
|
-
var BUNDLED_EXTENSIONS = [
|
|
91
|
-
"markdown-it-mark",
|
|
92
|
-
"markdown-it-sub",
|
|
93
|
-
"markdown-it-sup",
|
|
94
|
-
"markdown-it-abbr",
|
|
95
|
-
"gutterpress-gfm-alerts"
|
|
96
|
-
];
|
|
97
|
-
function isBundledExtension(name) {
|
|
98
|
-
return BUNDLED_EXTENSIONS.includes(name);
|
|
99
|
-
}
|
|
100
|
-
function isPathSpecifier(use) {
|
|
101
|
-
return use.startsWith("./") || use.startsWith("../") || use.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(use);
|
|
102
|
-
}
|
|
103
|
-
function parseExtensionSpecifier(use) {
|
|
104
|
-
const spec = use.trim();
|
|
105
|
-
if (!spec) {
|
|
106
|
-
throw new Error("An extension specifier is required — an npm package name, or a ./ path.");
|
|
107
|
-
}
|
|
108
|
-
if (isPathSpecifier(spec))
|
|
109
|
-
return { kind: "path", path: spec };
|
|
110
|
-
if (/\.(m?js|cjs)$/i.test(spec) || !spec.startsWith("@") && spec.includes("/")) {
|
|
111
|
-
throw new Error(`"${spec}" looks like a path — write it as "./${spec}". A specifier that does not ` + "start with ./, ../ or / is an npm package name.");
|
|
112
|
-
}
|
|
113
|
-
const parsed = parseNpmPluginSpec(spec);
|
|
114
|
-
if (isBundledExtension(parsed.name)) {
|
|
115
|
-
if (parsed.selector !== undefined) {
|
|
116
|
-
throw new Error(`"${parsed.name}" is bundled with Gutterpress and always resolves to the bundled copy — ` + `drop "@${parsed.selector}".`);
|
|
117
|
-
}
|
|
118
|
-
return { kind: "bundled", name: parsed.name };
|
|
119
|
-
}
|
|
120
|
-
return parsed.selector === undefined ? { kind: "npm", name: parsed.name } : { kind: "npm", name: parsed.name, version: parsed.selector };
|
|
121
|
-
}
|
|
122
|
-
function pinnedNpmSpecifier(name, version) {
|
|
123
|
-
return `${name}@${version}`;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
94
|
// src/constants.ts
|
|
127
95
|
var NETWORK = {
|
|
128
96
|
DEFAULT_PORT: 3579
|
|
@@ -603,6 +571,15 @@ function mergeShape(cli, manifest, preset) {
|
|
|
603
571
|
}
|
|
604
572
|
return out;
|
|
605
573
|
}
|
|
574
|
+
var LANGUAGE_TAG = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})*$/;
|
|
575
|
+
function resolveLanguage(value) {
|
|
576
|
+
if (value === undefined)
|
|
577
|
+
return "en";
|
|
578
|
+
if (typeof value !== "string" || !LANGUAGE_TAG.test(value)) {
|
|
579
|
+
throw new UsageError(`Manifest field \`language\` must be a language tag such as "en", "de" or "pt-BR", got ${JSON.stringify(value)}.`);
|
|
580
|
+
}
|
|
581
|
+
return value;
|
|
582
|
+
}
|
|
606
583
|
function resolveConfig(cliOverrides, manifest) {
|
|
607
584
|
const presetName = cliOverrides.preset ?? manifest.preset;
|
|
608
585
|
return resolveWithPreset(cliOverrides, manifest, resolvePreset(presetName));
|
|
@@ -690,6 +667,7 @@ function resolveWithPreset(cliOverrides, manifest, preset) {
|
|
|
690
667
|
return {
|
|
691
668
|
title: c.title ?? m.title ?? "Document",
|
|
692
669
|
authors: c.authors ?? m.authors ?? [],
|
|
670
|
+
language: resolveLanguage(c.language ?? m.language),
|
|
693
671
|
preset: preset.id,
|
|
694
672
|
spec: preset.spec,
|
|
695
673
|
styles: c.styles ?? m.styles,
|
|
@@ -1313,13 +1291,13 @@ async function removeEmptyDirs(dirs) {
|
|
|
1313
1291
|
}
|
|
1314
1292
|
}
|
|
1315
1293
|
async function prepareVendorParent(projectDir, name) {
|
|
1316
|
-
const
|
|
1317
|
-
const npm = path2.join(
|
|
1294
|
+
const extensions = path2.join(projectDir, EXTENSIONS_DIR);
|
|
1295
|
+
const npm = path2.join(extensions, VENDORED_NPM_DIR);
|
|
1318
1296
|
const packageParent = path2.dirname(vendoredNpmPluginRoot(projectDir, name, "0.0.0"));
|
|
1319
1297
|
await mkdir2(projectDir, { recursive: true });
|
|
1320
1298
|
const createdDirs = [];
|
|
1321
1299
|
try {
|
|
1322
|
-
for (const dir of [
|
|
1300
|
+
for (const dir of [extensions, npm, packageParent]) {
|
|
1323
1301
|
if (await ensureDirectory(dir))
|
|
1324
1302
|
createdDirs.push(dir);
|
|
1325
1303
|
}
|
|
@@ -1438,7 +1416,7 @@ function ignoreStatus(gitignore, entry) {
|
|
|
1438
1416
|
return "ignored";
|
|
1439
1417
|
return dir.unignored || file.unignored ? "negated" : "open";
|
|
1440
1418
|
}
|
|
1441
|
-
var PROJECT_GITIGNORE_ENTRIES = ["dist/", "
|
|
1419
|
+
var PROJECT_GITIGNORE_ENTRIES = ["dist/", "extensions/npm/"];
|
|
1442
1420
|
async function ensureProjectGitignore(projectDir) {
|
|
1443
1421
|
const gitignorePath = path3.join(projectDir, ".gitignore");
|
|
1444
1422
|
let existing = null;
|
|
@@ -1466,35 +1444,6 @@ async function ensureProjectGitignore(projectDir) {
|
|
|
1466
1444
|
}
|
|
1467
1445
|
|
|
1468
1446
|
// src/lib/extension-manager.ts
|
|
1469
|
-
var EXTENSIONS_DIR = "extensions";
|
|
1470
|
-
var RECOMMENDED_EXTENSIONS = [
|
|
1471
|
-
{
|
|
1472
|
-
use: "markdown-it-mark",
|
|
1473
|
-
label: "Highlight",
|
|
1474
|
-
description: "Highlight text by wrapping it in `==double equals==`."
|
|
1475
|
-
},
|
|
1476
|
-
{
|
|
1477
|
-
use: "markdown-it-sub",
|
|
1478
|
-
label: "Subscript",
|
|
1479
|
-
description: "Lower text below the line, like the 2 in `H~2~O`."
|
|
1480
|
-
},
|
|
1481
|
-
{
|
|
1482
|
-
use: "markdown-it-sup",
|
|
1483
|
-
label: "Superscript",
|
|
1484
|
-
description: "Raise text above the line, like the th in `29^th^`."
|
|
1485
|
-
},
|
|
1486
|
-
{
|
|
1487
|
-
use: "markdown-it-abbr",
|
|
1488
|
-
label: "Abbreviations",
|
|
1489
|
-
description: "Explain an abbreviation when readers hover over it. Define it once, like `*[GPS]: Global Positioning System`."
|
|
1490
|
-
},
|
|
1491
|
-
{
|
|
1492
|
-
use: "gutterpress-gfm-alerts",
|
|
1493
|
-
label: "Callouts",
|
|
1494
|
-
description: "Turn a quote into a boxed note: start it with `> [!NOTE]` (or `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`)."
|
|
1495
|
-
}
|
|
1496
|
-
];
|
|
1497
|
-
var BUILT_IN_STYLE_SET_IDS = ["clean-book", "zine", "technical-doc"];
|
|
1498
1447
|
var mutationQueues = new Map;
|
|
1499
1448
|
function projectKey(projectDir) {
|
|
1500
1449
|
const resolved = path4.resolve(projectDir);
|
|
@@ -1610,15 +1559,14 @@ async function describeEntry(projectDir, raw) {
|
|
|
1610
1559
|
return withWarnings({ ...common, kind: "npm", name: raw.use, label: raw.use, carries: NO_CARRIES });
|
|
1611
1560
|
}
|
|
1612
1561
|
if (parsed.kind === "bundled") {
|
|
1613
|
-
const
|
|
1614
|
-
const rec = RECOMMENDED_EXTENSIONS.find((r) => r.use === bundledName);
|
|
1562
|
+
const bundled = bundledExtension(parsed.name);
|
|
1615
1563
|
return withWarnings({
|
|
1616
1564
|
...common,
|
|
1617
1565
|
kind: "bundled",
|
|
1618
|
-
name:
|
|
1619
|
-
label:
|
|
1620
|
-
|
|
1621
|
-
carries: { ...NO_CARRIES, markdown: true }
|
|
1566
|
+
name: parsed.name,
|
|
1567
|
+
label: bundled.label,
|
|
1568
|
+
description: bundled.description,
|
|
1569
|
+
carries: { ...NO_CARRIES, ...bundled.css !== undefined ? { styles: true } : { markdown: true } }
|
|
1622
1570
|
});
|
|
1623
1571
|
}
|
|
1624
1572
|
if (parsed.kind === "path") {
|
|
@@ -1763,9 +1711,10 @@ async function removeExtension(projectDir, use) {
|
|
|
1763
1711
|
return;
|
|
1764
1712
|
}
|
|
1765
1713
|
if (parsed.kind === "npm" && parsed.version) {
|
|
1766
|
-
const root
|
|
1767
|
-
|
|
1768
|
-
|
|
1714
|
+
for (const root of vendoredNpmPluginRoots(projectDir, parsed.name, parsed.version)) {
|
|
1715
|
+
await rm3(root, { recursive: true, force: true });
|
|
1716
|
+
await removeEmptyDirs([path4.dirname(root)]);
|
|
1717
|
+
}
|
|
1769
1718
|
}
|
|
1770
1719
|
});
|
|
1771
1720
|
}
|
|
@@ -1883,8 +1832,8 @@ async function vendorNpmExtension(projectDir, input, exportName, options, commit
|
|
|
1883
1832
|
});
|
|
1884
1833
|
try {
|
|
1885
1834
|
const { negated } = await ensureProjectGitignore(projectDir);
|
|
1886
|
-
if (negated.includes("
|
|
1887
|
-
warnings.push("Your .gitignore re-includes
|
|
1835
|
+
if (negated.includes("extensions/npm/")) {
|
|
1836
|
+
warnings.push("Your .gitignore re-includes extensions/npm/, so downloaded extensions will be committed with " + "your book. They shouldn't be: the manifest pins each version and a build downloads a " + "missing copy again.");
|
|
1888
1837
|
}
|
|
1889
1838
|
} catch (error) {
|
|
1890
1839
|
warnings.push(`The extension was installed, but .gitignore could not be updated to keep it out of version history: ` + `${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -1910,24 +1859,32 @@ async function pinnedVersionsOf(projectDir, name) {
|
|
|
1910
1859
|
return versions;
|
|
1911
1860
|
}
|
|
1912
1861
|
async function pruneStaleVersions(projectDir, name, keep) {
|
|
1913
|
-
const
|
|
1862
|
+
const parents = vendoredNpmPluginRoots(projectDir, name, "0.0.0").map((root) => path4.dirname(root));
|
|
1914
1863
|
try {
|
|
1915
|
-
for (const
|
|
1916
|
-
|
|
1917
|
-
continue;
|
|
1918
|
-
let version;
|
|
1864
|
+
for (const parent of parents) {
|
|
1865
|
+
let entries;
|
|
1919
1866
|
try {
|
|
1920
|
-
|
|
1921
|
-
} catch {
|
|
1922
|
-
|
|
1867
|
+
entries = await readdir(parent, { withFileTypes: true });
|
|
1868
|
+
} catch (error) {
|
|
1869
|
+
if (error.code === "ENOENT")
|
|
1870
|
+
continue;
|
|
1871
|
+
throw error;
|
|
1872
|
+
}
|
|
1873
|
+
for (const entry of entries) {
|
|
1874
|
+
if (!entry.isDirectory())
|
|
1875
|
+
continue;
|
|
1876
|
+
let version;
|
|
1877
|
+
try {
|
|
1878
|
+
version = decodeURIComponent(entry.name);
|
|
1879
|
+
} catch {
|
|
1880
|
+
continue;
|
|
1881
|
+
}
|
|
1882
|
+
if (!isExactNpmVersion(version) || keep.includes(version))
|
|
1883
|
+
continue;
|
|
1884
|
+
await rm3(path4.join(parent, entry.name), { recursive: true, force: true });
|
|
1923
1885
|
}
|
|
1924
|
-
if (!isExactNpmVersion(version) || keep.includes(version))
|
|
1925
|
-
continue;
|
|
1926
|
-
await rm3(path4.join(parent, entry.name), { recursive: true, force: true });
|
|
1927
1886
|
}
|
|
1928
1887
|
} catch (error) {
|
|
1929
|
-
if (error.code === "ENOENT")
|
|
1930
|
-
return [];
|
|
1931
1888
|
return [
|
|
1932
1889
|
`The extension was installed, but a previous version's downloaded copy could not be removed: ` + `${error instanceof Error ? error.message : String(error)}`
|
|
1933
1890
|
];
|
|
@@ -2013,18 +1970,13 @@ async function updateExtensions(projectDir, options = {}) {
|
|
|
2013
1970
|
}
|
|
2014
1971
|
return updated;
|
|
2015
1972
|
}
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
name: prettify(meta.name?.trim() || id),
|
|
2024
|
-
description: meta.description?.trim() || ""
|
|
2025
|
-
});
|
|
2026
|
-
}
|
|
2027
|
-
return out;
|
|
1973
|
+
function listBundledExtensions() {
|
|
1974
|
+
return BUNDLED_EXTENSIONS.map((b) => ({
|
|
1975
|
+
use: b.name,
|
|
1976
|
+
label: b.label,
|
|
1977
|
+
description: b.description,
|
|
1978
|
+
look: b.css !== undefined
|
|
1979
|
+
}));
|
|
2028
1980
|
}
|
|
2029
1981
|
async function uniqueExtensionId(projectDir, base) {
|
|
2030
1982
|
const slug = slugify(base) || "extension";
|
|
@@ -2034,20 +1986,6 @@ async function uniqueExtensionId(projectDir, base) {
|
|
|
2034
1986
|
}
|
|
2035
1987
|
return candidate;
|
|
2036
1988
|
}
|
|
2037
|
-
async function addBuiltInStyleSet(projectDir, id) {
|
|
2038
|
-
if (!BUILT_IN_STYLE_SET_IDS.includes(id)) {
|
|
2039
|
-
throw new Error(`Unknown built-in look "${id}" (one of: ${BUILT_IN_STYLE_SET_IDS.join(", ")}).`);
|
|
2040
|
-
}
|
|
2041
|
-
return withMutationLock(projectDir, async () => {
|
|
2042
|
-
const dest = path4.join(projectDir, EXTENSIONS_DIR, id);
|
|
2043
|
-
if (!existsSync3(dest)) {
|
|
2044
|
-
const src = path4.join(await getAssetsDir(), "themes", id);
|
|
2045
|
-
await mkdir3(path4.dirname(dest), { recursive: true });
|
|
2046
|
-
await cp(src, dest, { recursive: true });
|
|
2047
|
-
}
|
|
2048
|
-
return addExtensionUnlocked(projectDir, `./${EXTENSIONS_DIR}/${id}`, {});
|
|
2049
|
-
});
|
|
2050
|
-
}
|
|
2051
1989
|
async function validateProjectExtensions(projectDir) {
|
|
2052
1990
|
const out = [];
|
|
2053
1991
|
for (const entry of await listProjectExtensions(projectDir)) {
|
|
@@ -2074,6 +2012,9 @@ async function readExtensionCss(projectDir, use) {
|
|
|
2074
2012
|
const entry = await describeExtension(projectDir, use);
|
|
2075
2013
|
if (!entry)
|
|
2076
2014
|
throw new Error(`Extension "${use}" is not in the manifest.`);
|
|
2015
|
+
const bundledCss = entry.kind === "bundled" ? bundledExtension(entry.name)?.css : undefined;
|
|
2016
|
+
if (bundledCss !== undefined)
|
|
2017
|
+
return bundledCss;
|
|
2077
2018
|
if (!entry.dir)
|
|
2078
2019
|
throw new Error(`Extension "${use}" has no stylesheets to preview.`);
|
|
2079
2020
|
const meta = await readExtensionMeta(entry.dir);
|
|
@@ -2205,4 +2146,4 @@ async function restoreForCommand(dir, options) {
|
|
|
2205
2146
|
log.warn(problem);
|
|
2206
2147
|
}
|
|
2207
2148
|
|
|
2208
|
-
export {
|
|
2149
|
+
export { DEBOUNCE, UsageError, resolvePort, PRESET_IDS, PRESETS, TARGETS, TARGET_IDS, publishTargetFor, resolveTargets, applyDefaultPdfStrictChecks, MANIFEST_FILENAMES, hasProjectManifest, loadManifest, loadManifestWithPath, resolveConfig, resolveConfigForTarget, FriendlyHttpError, withFetchTimeout, loadManifestDoc, writeManifestDoc, ensureSeq, scalarString, DEFAULT_NPM_REGISTRY, npmRegistryUrl, ensureProjectGitignore, sameExtension, listProjectExtensions, describeExtension, extensionConfigFor, setExtensionEnabled, reorderExtensions, removeExtension, addExtension, listNpmVersions, checkExtensionUpdates, updateExtensions, listBundledExtensions, uniqueExtensionId, validateProjectExtensions, readExtensionCss, restorePinnedExtensions, restoreFailureMessage, restoreOfflineMessage, restoreForCommand };
|
package/dist/index.js
CHANGED
|
@@ -116,33 +116,25 @@ import {
|
|
|
116
116
|
substituteVariables,
|
|
117
117
|
syncProject,
|
|
118
118
|
testRemoteAccess
|
|
119
|
-
} from "./index-
|
|
119
|
+
} from "./index-j5z86r4a.js";
|
|
120
120
|
import {
|
|
121
|
-
BUILT_IN_STYLE_SET_IDS,
|
|
122
|
-
BUNDLED_EXTENSIONS,
|
|
123
121
|
DEFAULT_NPM_REGISTRY,
|
|
124
|
-
EXTENSIONS_DIR,
|
|
125
122
|
MANIFEST_FILENAMES,
|
|
126
123
|
PRESETS,
|
|
127
124
|
PRESET_IDS,
|
|
128
|
-
RECOMMENDED_EXTENSIONS,
|
|
129
125
|
TARGETS,
|
|
130
126
|
TARGET_IDS,
|
|
131
|
-
addBuiltInStyleSet,
|
|
132
127
|
addExtension,
|
|
133
128
|
checkExtensionUpdates,
|
|
134
129
|
describeExtension,
|
|
135
130
|
ensureProjectGitignore,
|
|
136
131
|
hasProjectManifest,
|
|
137
|
-
|
|
138
|
-
isPathSpecifier,
|
|
139
|
-
listBuiltInStyleSets,
|
|
132
|
+
listBundledExtensions,
|
|
140
133
|
listNpmVersions,
|
|
141
134
|
listProjectExtensions,
|
|
142
135
|
loadManifest,
|
|
143
136
|
loadManifestWithPath,
|
|
144
137
|
npmRegistryUrl,
|
|
145
|
-
parseExtensionSpecifier,
|
|
146
138
|
publishTargetFor,
|
|
147
139
|
readExtensionCss,
|
|
148
140
|
removeExtension,
|
|
@@ -154,26 +146,31 @@ import {
|
|
|
154
146
|
setExtensionEnabled,
|
|
155
147
|
updateExtensions,
|
|
156
148
|
validateProjectExtensions
|
|
157
|
-
} from "./index-
|
|
149
|
+
} from "./index-x3ema2w3.js";
|
|
158
150
|
import {
|
|
151
|
+
BUNDLED_EXTENSIONS,
|
|
159
152
|
EXTENSION_MANIFEST_FILENAME,
|
|
160
153
|
assertExtensionContained,
|
|
154
|
+
bundledExtension,
|
|
161
155
|
extensionCarries,
|
|
162
156
|
extensionEntry,
|
|
163
157
|
extensionStyleList,
|
|
158
|
+
isBundledExtension,
|
|
159
|
+
isPathSpecifier,
|
|
164
160
|
log,
|
|
161
|
+
parseExtensionSpecifier,
|
|
165
162
|
pathEscapesFolder,
|
|
166
163
|
readExtensionMeta,
|
|
167
164
|
resolveExtension
|
|
168
|
-
} from "./index-
|
|
165
|
+
} from "./index-2bjcghze.js";
|
|
169
166
|
import"./index-ht1bcqdd.js";
|
|
170
167
|
import {
|
|
171
168
|
BUILD_DIAGNOSTIC_CODES
|
|
172
|
-
} from "./index-
|
|
173
|
-
import"./index-
|
|
169
|
+
} from "./index-4x6y8krm.js";
|
|
170
|
+
import"./index-0skhjx3e.js";
|
|
174
171
|
import {
|
|
175
172
|
BuildError
|
|
176
|
-
} from "./index-
|
|
173
|
+
} from "./index-46ycxe6r.js";
|
|
177
174
|
import"./index-2ppw6q9v.js";
|
|
178
175
|
import {
|
|
179
176
|
DEFAULT_PRINT_OPTS,
|
|
@@ -193,10 +190,10 @@ import {
|
|
|
193
190
|
restoreVersionWithBackup,
|
|
194
191
|
switchBranch,
|
|
195
192
|
whenGitIdle
|
|
196
|
-
} from "./index-
|
|
193
|
+
} from "./index-h6yk5tjx.js";
|
|
197
194
|
import {
|
|
198
|
-
|
|
199
|
-
} from "./index-
|
|
195
|
+
EXTENSIONS_DIR
|
|
196
|
+
} from "./index-5x42amh8.js";
|
|
200
197
|
import {
|
|
201
198
|
capabilitiesFor,
|
|
202
199
|
detectProjectSource,
|
|
@@ -295,8 +292,8 @@ export {
|
|
|
295
292
|
listGitHubRepositories,
|
|
296
293
|
listGitHubBranches,
|
|
297
294
|
listCustomTemplates,
|
|
295
|
+
listBundledExtensions,
|
|
298
296
|
listBuiltInTemplates,
|
|
299
|
-
listBuiltInStyleSets,
|
|
300
297
|
listBookPublishProviders,
|
|
301
298
|
knownForgeTokenUrl,
|
|
302
299
|
isValidRepositoryName,
|
|
@@ -344,13 +341,13 @@ export {
|
|
|
344
341
|
checkExtensionUpdates,
|
|
345
342
|
checkCss,
|
|
346
343
|
capabilitiesFor,
|
|
344
|
+
bundledExtension,
|
|
347
345
|
autoSyncDelayMs,
|
|
348
346
|
autoSnapshotDelayMs,
|
|
349
347
|
assertMilestone,
|
|
350
348
|
assertExtensionContained,
|
|
351
349
|
adoptFolder,
|
|
352
350
|
addExtension,
|
|
353
|
-
addBuiltInStyleSet,
|
|
354
351
|
VERSION_CHANGES_SHOWN,
|
|
355
352
|
TARGET_IDS,
|
|
356
353
|
TARGETS,
|
|
@@ -361,11 +358,9 @@ export {
|
|
|
361
358
|
RESTORE_BACKUP_MESSAGE,
|
|
362
359
|
RESERVED_PREFIX,
|
|
363
360
|
REPAIR_SNAPSHOT_MESSAGE,
|
|
364
|
-
RECOMMENDED_EXTENSIONS,
|
|
365
361
|
PublishSelectionsStore,
|
|
366
362
|
PRESET_IDS,
|
|
367
363
|
PRESETS,
|
|
368
|
-
PLUGINS_DIR,
|
|
369
364
|
MAX_SEARCH_BYTES,
|
|
370
365
|
MANIFEST_FILENAMES,
|
|
371
366
|
HISTORY_PAGE_LIMIT,
|
|
@@ -383,7 +378,6 @@ export {
|
|
|
383
378
|
BuildError,
|
|
384
379
|
BUNDLED_EXTENSIONS,
|
|
385
380
|
BUILT_IN_TEMPLATE_IDS,
|
|
386
|
-
BUILT_IN_STYLE_SET_IDS,
|
|
387
381
|
BUILD_DIAGNOSTIC_CODES,
|
|
388
382
|
AUTO_SYNC_PUSH_INTERVAL_MINUTES,
|
|
389
383
|
AUTO_SYNC_MIN_MINUTES,
|
|
@@ -169,7 +169,7 @@ export interface BuildContext {
|
|
|
169
169
|
* The build's ONE plugin load (#262). `null` until {@link loadBuildPlugins}
|
|
170
170
|
* runs; every stage that needs plugins (the preValidate gate in
|
|
171
171
|
* {@link runQualityGates}, and {@link renderBook}) calls that function and
|
|
172
|
-
* gets the SAME resolved `{ plugins,
|
|
172
|
+
* gets the SAME resolved `{ plugins, pluginStyles, pluginStylePaths }` back,
|
|
173
173
|
* whichever of them runs first.
|
|
174
174
|
*
|
|
175
175
|
* One load means one answer: the validation gate checks exactly the plugin
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { type NpmPluginInstallOptions } from "./npm-plugin-installer.ts";
|
|
2
2
|
import { type ExtensionCarries } from "./extension-manifest.ts";
|
|
3
3
|
import type { ResolvedExtensionConfig } from "../schema/manifest.types.ts";
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export { PLUGINS_DIR } from "./plugin-vendor.ts";
|
|
4
|
+
/** The folder (relative to the project root) a book's extensions live under:
|
|
5
|
+
* vendored npm copies in `extensions/npm/`, zip and URL imports beside them
|
|
6
|
+
* (extension-import.ts). Path entries elsewhere are never moved. */
|
|
7
|
+
export { EXTENSIONS_DIR } from "./plugin-vendor.ts";
|
|
9
8
|
/** How an `extensions:` entry resolves — the form of its specifier decides. */
|
|
10
9
|
export type ExtensionSourceKind = "bundled" | "path" | "npm";
|
|
11
10
|
/** One configured extension, as surfaced to the CLI and the desktop. */
|
|
@@ -54,34 +53,6 @@ export interface ExtensionValidationResult {
|
|
|
54
53
|
/** The loader's fail-fast error message when `ok` is `false`. */
|
|
55
54
|
error?: string;
|
|
56
55
|
}
|
|
57
|
-
/** A curated, bundled markdown feature an author can turn on. */
|
|
58
|
-
export interface RecommendedExtension {
|
|
59
|
-
/** The bundled name — also the manifest entry "Add" writes. */
|
|
60
|
-
use: string;
|
|
61
|
-
/** Short, plain-language feature name shown as the row title. */
|
|
62
|
-
label: string;
|
|
63
|
-
/** One-line author-friendly description in plain words. Backtick spans mark
|
|
64
|
-
* "what to type" (the desktop sets them in code type), so keep them paired
|
|
65
|
-
* and keep HTML tag names out of the prose. */
|
|
66
|
-
description: string;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* The bundled markdown features (`BUNDLED_EXTENSIONS`): adding one writes the
|
|
70
|
-
* manifest entry AND the feature works immediately — no terminal, no install,
|
|
71
|
-
* offline. The always-on defaults (attrs/footnote/deflist, applied
|
|
72
|
-
* unconditionally in renderer.ts) are deliberately NOT listed: recommending
|
|
73
|
-
* the author "add" something already active is pure confusion.
|
|
74
|
-
*/
|
|
75
|
-
export declare const RECOMMENDED_EXTENSIONS: RecommendedExtension[];
|
|
76
|
-
/** The built-in looks shipped as embedded assets (ids are folder names). */
|
|
77
|
-
export declare const BUILT_IN_STYLE_SET_IDS: readonly ["clean-book", "zine", "technical-doc"];
|
|
78
|
-
export type BuiltInStyleSetId = (typeof BUILT_IN_STYLE_SET_IDS)[number];
|
|
79
|
-
/** A built-in look, as listed for the desktop's Look view. */
|
|
80
|
-
export interface BuiltInStyleSet {
|
|
81
|
-
id: BuiltInStyleSetId;
|
|
82
|
-
name: string;
|
|
83
|
-
description: string;
|
|
84
|
-
}
|
|
85
56
|
/** One key per book folder, however the path is spelled (Windows paths are case-insensitive). */
|
|
86
57
|
export declare function projectKey(projectDir: string): string;
|
|
87
58
|
/**
|
|
@@ -157,7 +128,7 @@ export declare function restoreNpmExtension(projectDir: string, name: string, ve
|
|
|
157
128
|
/** Every version of `name` an enabled manifest entry pins — never pruned. */
|
|
158
129
|
keepVersions?: readonly string[];
|
|
159
130
|
}): Promise<string[]>;
|
|
160
|
-
/** True when `
|
|
131
|
+
/** True when `extensions/npm/<name>/<version>/` is absent or has no loadable entry — what the loader calls "not installed" or "incomplete". */
|
|
161
132
|
export declare function vendoredCopyNeedsInstall(projectDir: string, name: string, version: string): Promise<boolean>;
|
|
162
133
|
/** One pinned npm extension against npm's `latest` tag. */
|
|
163
134
|
export interface ExtensionUpdateCheck {
|
|
@@ -215,17 +186,19 @@ export interface UpdateExtensionsOptions extends CheckExtensionUpdatesOptions {
|
|
|
215
186
|
* Returns what moved; an up-to-date book returns `[]`.
|
|
216
187
|
*/
|
|
217
188
|
export declare function updateExtensions(projectDir: string, options?: UpdateExtensionsOptions): Promise<ExtensionUpdateResult[]>;
|
|
218
|
-
/**
|
|
219
|
-
export
|
|
189
|
+
/** A bundled extension as the desktop lists it: "Add" writes `use`. */
|
|
190
|
+
export interface BundledExtensionInfo {
|
|
191
|
+
use: string;
|
|
192
|
+
/** Short, plain-language name shown as the row title. */
|
|
193
|
+
label: string;
|
|
194
|
+
description: string;
|
|
195
|
+
/** A look (styles only), as opposed to a markdown feature. */
|
|
196
|
+
look: boolean;
|
|
197
|
+
}
|
|
198
|
+
/** The bundled extensions, in table order. */
|
|
199
|
+
export declare function listBundledExtensions(): BundledExtensionInfo[];
|
|
220
200
|
/** A folder name under `extensions/` not yet taken: `<slug>`, `<slug>-2`, … */
|
|
221
201
|
export declare function uniqueExtensionId(projectDir: string, base: string): Promise<string>;
|
|
222
|
-
/**
|
|
223
|
-
* Copy a built-in look into `extensions/<id>/` and add it to the manifest as
|
|
224
|
-
* `./extensions/<id>`. The copy is deliberate (see the module doc): the look
|
|
225
|
-
* becomes the author's own editable files. Idempotent — a folder already
|
|
226
|
-
* there is kept as it is and only (re-)referenced.
|
|
227
|
-
*/
|
|
228
|
-
export declare function addBuiltInStyleSet(projectDir: string, id: string): Promise<ProjectExtensionEntry>;
|
|
229
202
|
/**
|
|
230
203
|
* Validate every configured extension by attempting to LOAD it through the
|
|
231
204
|
* one loader. Disabled entries are reported as disabled and NOT load-tested.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Which starter package to create. */
|
|
2
|
-
export type ExtensionKind = "plugin" | "
|
|
2
|
+
export type ExtensionKind = "plugin" | "look";
|
|
3
3
|
/** The kinds `--kind` accepts, for CLI help text and pickers. */
|
|
4
|
-
export declare const EXTENSION_KINDS: readonly ["plugin", "
|
|
4
|
+
export declare const EXTENSION_KINDS: readonly ["plugin", "look"];
|
|
5
5
|
/**
|
|
6
6
|
* The class/property prefix a scaffolded extension is FORBIDDEN to take.
|
|
7
7
|
* `gp-` is Gutterpress core's own vocabulary (CLAUDE.md §6); an extension
|
|
@@ -56,7 +56,7 @@ export interface ScaffoldExtensionResult {
|
|
|
56
56
|
*/
|
|
57
57
|
export declare function resolveExtensionPrefix(slug: string, requested?: string): string;
|
|
58
58
|
/**
|
|
59
|
-
* Create a plugin or
|
|
59
|
+
* Create a plugin or look starter package.
|
|
60
60
|
*
|
|
61
61
|
* Resolves with a {@link ScaffoldExtensionResult}; throws a
|
|
62
62
|
* {@link CreateProjectError} (the SAME error type `scaffoldProject` throws, so
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
* `
|
|
4
|
-
*
|
|
2
|
+
* The extensions compiled into Gutterpress. Writing one of these names in
|
|
3
|
+
* `extensions:` installs nothing: the loader resolves it from the bundle, so
|
|
4
|
+
* it works offline and in the compiled binary.
|
|
5
|
+
*
|
|
6
|
+
* A markdown feature loads from `BUILTIN_OPTIONAL_PLUGINS`
|
|
7
|
+
* (`markdown/renderer.ts`, keyed by the same name; a test pins the two
|
|
8
|
+
* together). A look is its stylesheet, inlined here as text, so the loader
|
|
9
|
+
* hands it straight to the cascade and nothing is read from disk or copied
|
|
10
|
+
* into a book. Both carry their author-facing words here.
|
|
5
11
|
*/
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
export interface BundledExtension {
|
|
13
|
+
/** The specifier an author writes. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Short, plain-language name shown as the row title. */
|
|
16
|
+
label: string;
|
|
17
|
+
/** One line in plain words. Backtick spans mark "what to type" (the desktop
|
|
18
|
+
* sets them in code type), so keep them paired and keep HTML tags out. */
|
|
19
|
+
description: string;
|
|
20
|
+
/** A look's stylesheet. Absent for a markdown feature. */
|
|
21
|
+
css?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const BUNDLED_EXTENSIONS: readonly BundledExtension[];
|
|
24
|
+
export declare function bundledExtension(name: string): BundledExtension | undefined;
|
|
25
|
+
export declare function isBundledExtension(name: string): boolean;
|
|
9
26
|
/** `./x`, `../x`, `/x`, or a Windows drive path (`C:\x`). Nothing else is a path. */
|
|
10
27
|
export declare function isPathSpecifier(use: string): boolean;
|
|
11
28
|
export type ParsedExtensionSpecifier = {
|
|
@@ -4,7 +4,7 @@ import { type PrintAreaSource } from "../../engine/shared/print-area.ts";
|
|
|
4
4
|
/** Reader injected by the host: resolve a project-root-relative file → its text. */
|
|
5
5
|
export type ReadText = (relPath: string) => Promise<string>;
|
|
6
6
|
/**
|
|
7
|
-
* One author-mistake warning emitted by Gutterpress's marker parser.
|
|
7
|
+
* One author-mistake warning, most emitted by Gutterpress's marker parser.
|
|
8
8
|
* Mirrors the shape `markers.js`'s `warn()` pushes onto
|
|
9
9
|
* `env.layoutWarnings` — see that file's header comment for the warning
|
|
10
10
|
* `type`s (`ambiguous_marker_token`, `unrecognized_marker_token`,
|
|
@@ -36,6 +36,10 @@ export type ReadText = (relPath: string) => Promise<string>;
|
|
|
36
36
|
* for an `@page` / `@section` word that is a near-miss of a declared page /
|
|
37
37
|
* section variant (any other word there is a free name and stays silent).
|
|
38
38
|
*
|
|
39
|
+
* Two come from outside the marker parser: `table_extra_cells` (a table
|
|
40
|
+
* row with more cells than the header, `table.ts`) and `math_error` (a
|
|
41
|
+
* formula MathJax could not typeset, `math.ts`).
|
|
42
|
+
*
|
|
39
43
|
* There is deliberately no `section_without_page`: a @section with no open
|
|
40
44
|
* @page is valid authoring (17/17 false positives across two real books).
|
|
41
45
|
*/
|
|
@@ -60,6 +64,8 @@ export declare const PAGE_BACKGROUND_FIXED_MILESTONE = 152;
|
|
|
60
64
|
export interface AssembleBookHtmlOptions {
|
|
61
65
|
/** Ordered list of project-root-relative `.md` files to concatenate. */
|
|
62
66
|
files: string[];
|
|
67
|
+
/** The book's BCP 47 language tag (manifest `language`); `en` when absent. */
|
|
68
|
+
language?: string;
|
|
63
69
|
/** Async reader the assembler uses to fetch each file's contents. */
|
|
64
70
|
readText: ReadText;
|
|
65
71
|
/**
|