gutterpress 0.11.23-alpha.1 → 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.
Files changed (62) hide show
  1. package/README.md +21 -22
  2. package/dist/api/index.d.ts +4 -4
  3. package/dist/api/index.js +16 -22
  4. package/dist/{build-09cd1n7s.js → build-encgnv0c.js} +9 -10
  5. package/dist/{cli-habkc5ng.js → cli-a35w7wzg.js} +5 -4
  6. package/dist/{cli-b0vyjvmt.js → cli-aqh6brew.js} +1 -1
  7. package/dist/{cli-ccp7sxz3.js → cli-evg8sbht.js} +1 -1
  8. package/dist/{cli-nr6j6300.js → cli-kh8v4vvw.js} +1 -1
  9. package/dist/{cli-h17e3mtz.js → cli-pwwfxdgb.js} +385 -10
  10. package/dist/{cli-dtckwda1.js → cli-pz4bn98t.js} +185 -9
  11. package/dist/{cli-dd115fa8.js → cli-sdmv4bba.js} +47 -123
  12. package/dist/{cli-5hkmp2wy.js → cli-xq6djqbj.js} +55 -88
  13. package/dist/{index-r7jcsk6h.js → cli-y28j019d.js} +19 -10
  14. package/dist/cli.js +12 -12
  15. package/dist/{doctor-nddspx4n.js → doctor-5gtpgpd1.js} +3 -3
  16. package/dist/{engine-892swzzc.js → engine-mc5br8g8.js} +1 -2
  17. package/dist/{engine-yjzknt0g.js → engine-tn13gk0b.js} +3 -3
  18. package/dist/{ext-zjpen4yx.js → ext-wn2a5afq.js} +18 -33
  19. package/dist/{extension-restore-w8xt4kbq.js → extension-restore-g8jnmmzq.js} +5 -6
  20. package/dist/{extension-restore-jvs60x9b.js → extension-restore-s3x1618g.js} +4 -4
  21. package/dist/{index-apc8w9w8.js → index-0skhjx3e.js} +180 -1
  22. package/dist/{index-2jpk25en.js → index-2bjcghze.js} +385 -10
  23. package/dist/index-46ycxe6r.js +18 -0
  24. package/dist/{index-0w2azsk1.js → index-4x6y8krm.js} +2 -4
  25. package/dist/{cli-h3phdstf.js → index-5x42amh8.js} +19 -10
  26. package/dist/{index-93pqkvty.js → index-h6yk5tjx.js} +5 -4
  27. package/dist/{index-zrhyb967.js → index-j5z86r4a.js} +335 -349
  28. package/dist/{index-m4hhzg3c.js → index-x3ema2w3.js} +59 -134
  29. package/dist/index.js +17 -23
  30. package/dist/lib/extension-manager.d.ts +16 -43
  31. package/dist/lib/extension-scaffold.d.ts +3 -3
  32. package/dist/lib/extension-specifier.d.ts +23 -6
  33. package/dist/lib/markdown/math.d.ts +1 -1
  34. package/dist/lib/npm-plugin-installer.d.ts +1 -1
  35. package/dist/lib/plugin-vendor.d.ts +11 -3
  36. package/dist/lib/project-gitignore.d.ts +2 -2
  37. package/dist/lib/project-scaffold.d.ts +5 -7
  38. package/dist/lib/project-templates.d.ts +0 -3
  39. package/dist/lib/snippets.d.ts +2 -1
  40. package/dist/lib/style-resolver.d.ts +1 -2
  41. package/dist/{manifest-8f10dr4f.yaml → manifest-eagfhba6.yaml} +2 -0
  42. package/dist/{manifest.schema-9aeaered.json → manifest.schema-t7nx2stg.json} +5 -5
  43. package/dist/{new-xhq8wczn.js → new-mhs46pw3.js} +22 -21
  44. package/dist/{plugins-9en8m9y0.js → plugins-1sxe0dkz.js} +4 -4
  45. package/dist/{plugins-gf0gkjmv.js → plugins-2cek4mz1.js} +2 -2
  46. package/dist/{preflight-negnxg7b.js → preflight-3k2b1x8e.js} +9 -10
  47. package/dist/{preview-cep2s9cg.js → preview-6p9v6rht.js} +9 -10
  48. package/dist/{publish-xery6qc6.js → publish-qgsngy8s.js} +9 -10
  49. package/dist/{source-provider-qbfknhyy.js → source-provider-98k5deda.js} +2 -2
  50. package/dist/{source-provider-2r74a7wp.js → source-provider-knmcam50.js} +2 -2
  51. package/dist/{validate-3d0sgf4g.js → validate-0v7xw6wa.js} +9 -10
  52. package/package.json +1 -1
  53. package/dist/cli-fe43evmf.js +0 -212
  54. package/dist/index-dsvk7q6s.js +0 -229
  55. package/dist/package-97gm31sg.json +0 -10
  56. package/dist/package-gag6ykwn.json +0 -10
  57. package/dist/package-nrhkwf2m.json +0 -10
  58. package/dist/package-zttkgydq.json +0 -10
  59. package/dist/theme-9c58td2d.css +0 -76
  60. package/dist/theme-h5recz6c.css +0 -61
  61. package/dist/theme-j2bagrfx.css +0 -59
  62. 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-2jpk25en.js";
17
+ } from "./index-2bjcghze.js";
13
18
  import {
14
19
  BuildError,
15
- EXIT_CODES,
16
- getAssetsDir
17
- } from "./index-dsvk7q6s.js";
20
+ EXIT_CODES
21
+ } from "./index-46ycxe6r.js";
18
22
  import {
19
- PLUGINS_DIR,
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-r7jcsk6h.js";
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 { cp, mkdir as mkdir3, readdir, readFile as readFile5, rm as rm3, stat } from "node:fs/promises";
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,44 +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
- "gutterpress-math"
97
- ];
98
- function isBundledExtension(name) {
99
- return BUNDLED_EXTENSIONS.includes(name);
100
- }
101
- function isPathSpecifier(use) {
102
- return use.startsWith("./") || use.startsWith("../") || use.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(use);
103
- }
104
- function parseExtensionSpecifier(use) {
105
- const spec = use.trim();
106
- if (!spec) {
107
- throw new Error("An extension specifier is required — an npm package name, or a ./ path.");
108
- }
109
- if (isPathSpecifier(spec))
110
- return { kind: "path", path: spec };
111
- if (/\.(m?js|cjs)$/i.test(spec) || !spec.startsWith("@") && spec.includes("/")) {
112
- 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.");
113
- }
114
- const parsed = parseNpmPluginSpec(spec);
115
- if (isBundledExtension(parsed.name)) {
116
- if (parsed.selector !== undefined) {
117
- throw new Error(`"${parsed.name}" is bundled with Gutterpress and always resolves to the bundled copy — ` + `drop "@${parsed.selector}".`);
118
- }
119
- return { kind: "bundled", name: parsed.name };
120
- }
121
- return parsed.selector === undefined ? { kind: "npm", name: parsed.name } : { kind: "npm", name: parsed.name, version: parsed.selector };
122
- }
123
- function pinnedNpmSpecifier(name, version) {
124
- return `${name}@${version}`;
125
- }
126
-
127
94
  // src/constants.ts
128
95
  var NETWORK = {
129
96
  DEFAULT_PORT: 3579
@@ -1324,13 +1291,13 @@ async function removeEmptyDirs(dirs) {
1324
1291
  }
1325
1292
  }
1326
1293
  async function prepareVendorParent(projectDir, name) {
1327
- const plugins = path2.join(projectDir, PLUGINS_DIR);
1328
- const npm = path2.join(plugins, VENDORED_NPM_DIR);
1294
+ const extensions = path2.join(projectDir, EXTENSIONS_DIR);
1295
+ const npm = path2.join(extensions, VENDORED_NPM_DIR);
1329
1296
  const packageParent = path2.dirname(vendoredNpmPluginRoot(projectDir, name, "0.0.0"));
1330
1297
  await mkdir2(projectDir, { recursive: true });
1331
1298
  const createdDirs = [];
1332
1299
  try {
1333
- for (const dir of [plugins, npm, packageParent]) {
1300
+ for (const dir of [extensions, npm, packageParent]) {
1334
1301
  if (await ensureDirectory(dir))
1335
1302
  createdDirs.push(dir);
1336
1303
  }
@@ -1449,7 +1416,7 @@ function ignoreStatus(gitignore, entry) {
1449
1416
  return "ignored";
1450
1417
  return dir.unignored || file.unignored ? "negated" : "open";
1451
1418
  }
1452
- var PROJECT_GITIGNORE_ENTRIES = ["dist/", "plugins/npm/"];
1419
+ var PROJECT_GITIGNORE_ENTRIES = ["dist/", "extensions/npm/"];
1453
1420
  async function ensureProjectGitignore(projectDir) {
1454
1421
  const gitignorePath = path3.join(projectDir, ".gitignore");
1455
1422
  let existing = null;
@@ -1477,40 +1444,6 @@ async function ensureProjectGitignore(projectDir) {
1477
1444
  }
1478
1445
 
1479
1446
  // src/lib/extension-manager.ts
1480
- var EXTENSIONS_DIR = "extensions";
1481
- var RECOMMENDED_EXTENSIONS = [
1482
- {
1483
- use: "markdown-it-mark",
1484
- label: "Highlight",
1485
- description: "Highlight text by wrapping it in `==double equals==`."
1486
- },
1487
- {
1488
- use: "markdown-it-sub",
1489
- label: "Subscript",
1490
- description: "Lower text below the line, like the 2 in `H~2~O`."
1491
- },
1492
- {
1493
- use: "markdown-it-sup",
1494
- label: "Superscript",
1495
- description: "Raise text above the line, like the th in `29^th^`."
1496
- },
1497
- {
1498
- use: "markdown-it-abbr",
1499
- label: "Abbreviations",
1500
- description: "Explain an abbreviation when readers hover over it. Define it once, like `*[GPS]: Global Positioning System`."
1501
- },
1502
- {
1503
- use: "gutterpress-gfm-alerts",
1504
- label: "Callouts",
1505
- description: "Turn a quote into a boxed note: start it with `> [!NOTE]` (or `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`)."
1506
- },
1507
- {
1508
- use: "gutterpress-math",
1509
- label: "Math",
1510
- description: "Write LaTeX math between dollar signs: `$E = mc^2$` in a line, or `$$` … `$$` on lines of their own."
1511
- }
1512
- ];
1513
- var BUILT_IN_STYLE_SET_IDS = ["clean-book", "zine", "technical-doc", "academic"];
1514
1447
  var mutationQueues = new Map;
1515
1448
  function projectKey(projectDir) {
1516
1449
  const resolved = path4.resolve(projectDir);
@@ -1626,15 +1559,14 @@ async function describeEntry(projectDir, raw) {
1626
1559
  return withWarnings({ ...common, kind: "npm", name: raw.use, label: raw.use, carries: NO_CARRIES });
1627
1560
  }
1628
1561
  if (parsed.kind === "bundled") {
1629
- const bundledName = parsed.name;
1630
- const rec = RECOMMENDED_EXTENSIONS.find((r) => r.use === bundledName);
1562
+ const bundled = bundledExtension(parsed.name);
1631
1563
  return withWarnings({
1632
1564
  ...common,
1633
1565
  kind: "bundled",
1634
- name: bundledName,
1635
- label: rec?.label ?? bundledName,
1636
- ...rec ? { description: rec.description } : {},
1637
- 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 } }
1638
1570
  });
1639
1571
  }
1640
1572
  if (parsed.kind === "path") {
@@ -1779,9 +1711,10 @@ async function removeExtension(projectDir, use) {
1779
1711
  return;
1780
1712
  }
1781
1713
  if (parsed.kind === "npm" && parsed.version) {
1782
- const root = vendoredNpmPluginRoot(projectDir, parsed.name, parsed.version);
1783
- await rm3(root, { recursive: true, force: true });
1784
- await removeEmptyDirs([path4.dirname(root)]);
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
+ }
1785
1718
  }
1786
1719
  });
1787
1720
  }
@@ -1899,8 +1832,8 @@ async function vendorNpmExtension(projectDir, input, exportName, options, commit
1899
1832
  });
1900
1833
  try {
1901
1834
  const { negated } = await ensureProjectGitignore(projectDir);
1902
- if (negated.includes("plugins/npm/")) {
1903
- warnings.push("Your .gitignore re-includes plugins/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.");
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.");
1904
1837
  }
1905
1838
  } catch (error) {
1906
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)}`);
@@ -1926,24 +1859,32 @@ async function pinnedVersionsOf(projectDir, name) {
1926
1859
  return versions;
1927
1860
  }
1928
1861
  async function pruneStaleVersions(projectDir, name, keep) {
1929
- const parent = path4.dirname(vendoredNpmPluginRoot(projectDir, name, "0.0.0"));
1862
+ const parents = vendoredNpmPluginRoots(projectDir, name, "0.0.0").map((root) => path4.dirname(root));
1930
1863
  try {
1931
- for (const entry of await readdir(parent, { withFileTypes: true })) {
1932
- if (!entry.isDirectory())
1933
- continue;
1934
- let version;
1864
+ for (const parent of parents) {
1865
+ let entries;
1935
1866
  try {
1936
- version = decodeURIComponent(entry.name);
1937
- } catch {
1938
- continue;
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 });
1939
1885
  }
1940
- if (!isExactNpmVersion(version) || keep.includes(version))
1941
- continue;
1942
- await rm3(path4.join(parent, entry.name), { recursive: true, force: true });
1943
1886
  }
1944
1887
  } catch (error) {
1945
- if (error.code === "ENOENT")
1946
- return [];
1947
1888
  return [
1948
1889
  `The extension was installed, but a previous version's downloaded copy could not be removed: ` + `${error instanceof Error ? error.message : String(error)}`
1949
1890
  ];
@@ -2029,18 +1970,13 @@ async function updateExtensions(projectDir, options = {}) {
2029
1970
  }
2030
1971
  return updated;
2031
1972
  }
2032
- async function listBuiltInStyleSets() {
2033
- const assets = await getAssetsDir();
2034
- const out = [];
2035
- for (const id of BUILT_IN_STYLE_SET_IDS) {
2036
- const meta = await readExtensionMeta(path4.join(assets, "themes", id));
2037
- out.push({
2038
- id,
2039
- name: prettify(meta.name?.trim() || id),
2040
- description: meta.description?.trim() || ""
2041
- });
2042
- }
2043
- 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
+ }));
2044
1980
  }
2045
1981
  async function uniqueExtensionId(projectDir, base) {
2046
1982
  const slug = slugify(base) || "extension";
@@ -2050,20 +1986,6 @@ async function uniqueExtensionId(projectDir, base) {
2050
1986
  }
2051
1987
  return candidate;
2052
1988
  }
2053
- async function addBuiltInStyleSet(projectDir, id) {
2054
- if (!BUILT_IN_STYLE_SET_IDS.includes(id)) {
2055
- throw new Error(`Unknown built-in look "${id}" (one of: ${BUILT_IN_STYLE_SET_IDS.join(", ")}).`);
2056
- }
2057
- return withMutationLock(projectDir, async () => {
2058
- const dest = path4.join(projectDir, EXTENSIONS_DIR, id);
2059
- if (!existsSync3(dest)) {
2060
- const src = path4.join(await getAssetsDir(), "themes", id);
2061
- await mkdir3(path4.dirname(dest), { recursive: true });
2062
- await cp(src, dest, { recursive: true });
2063
- }
2064
- return addExtensionUnlocked(projectDir, `./${EXTENSIONS_DIR}/${id}`, {});
2065
- });
2066
- }
2067
1989
  async function validateProjectExtensions(projectDir) {
2068
1990
  const out = [];
2069
1991
  for (const entry of await listProjectExtensions(projectDir)) {
@@ -2090,6 +2012,9 @@ async function readExtensionCss(projectDir, use) {
2090
2012
  const entry = await describeExtension(projectDir, use);
2091
2013
  if (!entry)
2092
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;
2093
2018
  if (!entry.dir)
2094
2019
  throw new Error(`Extension "${use}" has no stylesheets to preview.`);
2095
2020
  const meta = await readExtensionMeta(entry.dir);
@@ -2221,4 +2146,4 @@ async function restoreForCommand(dir, options) {
2221
2146
  log.warn(problem);
2222
2147
  }
2223
2148
 
2224
- export { BUNDLED_EXTENSIONS, isBundledExtension, isPathSpecifier, parseExtensionSpecifier, 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, EXTENSIONS_DIR, RECOMMENDED_EXTENSIONS, BUILT_IN_STYLE_SET_IDS, sameExtension, listProjectExtensions, describeExtension, extensionConfigFor, setExtensionEnabled, reorderExtensions, removeExtension, addExtension, listNpmVersions, checkExtensionUpdates, updateExtensions, listBuiltInStyleSets, uniqueExtensionId, addBuiltInStyleSet, validateProjectExtensions, readExtensionCss, restorePinnedExtensions, restoreFailureMessage, restoreOfflineMessage, restoreForCommand };
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-zrhyb967.js";
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
- isBundledExtension,
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-m4hhzg3c.js";
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-2jpk25en.js";
165
+ } from "./index-2bjcghze.js";
169
166
  import"./index-ht1bcqdd.js";
170
167
  import {
171
168
  BUILD_DIAGNOSTIC_CODES
172
- } from "./index-0w2azsk1.js";
173
- import"./index-apc8w9w8.js";
169
+ } from "./index-4x6y8krm.js";
170
+ import"./index-0skhjx3e.js";
174
171
  import {
175
172
  BuildError
176
- } from "./index-dsvk7q6s.js";
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-93pqkvty.js";
193
+ } from "./index-h6yk5tjx.js";
197
194
  import {
198
- PLUGINS_DIR
199
- } from "./index-r7jcsk6h.js";
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,
@@ -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
- /** Folder (relative to the project root) extensions this module COPIES land in
5
- * (built-in looks, zip/URL imports). Path entries elsewhere are never moved. */
6
- export declare const EXTENSIONS_DIR = "extensions";
7
- /** The vendored npm tree stays where 0.10.8 put it. */
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", "academic"];
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 `plugins/npm/<name>/<version>/` is absent or has no loadable entry — what the loader calls "not installed" or "incomplete". */
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
- /** List the built-in looks (metadata read from the embedded assets). */
219
- export declare function listBuiltInStyleSets(): Promise<BuiltInStyleSet[]>;
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" | "theme";
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", "theme"];
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 theme starter package.
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 markdown features compiled into Gutterpress (`BUILTIN_OPTIONAL_PLUGINS`,
3
- * `markdown/renderer.ts` — a test pins the two lists together). Writing one
4
- * of these names installs nothing: the loader resolves it from the bundle.
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 declare const BUNDLED_EXTENSIONS: readonly ["markdown-it-mark", "markdown-it-sub", "markdown-it-sup", "markdown-it-abbr", "gutterpress-gfm-alerts", "gutterpress-math"];
7
- export type BundledExtensionName = (typeof BUNDLED_EXTENSIONS)[number];
8
- export declare function isBundledExtension(name: string): name is BundledExtensionName;
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 = {
@@ -5,7 +5,7 @@ import type MarkdownIt from "markdown-it";
5
5
  *
6
6
  * Bundled, OPT-IN markdown feature (`gutterpress-math` in
7
7
  * `BUILTIN_OPTIONAL_PLUGINS`, renderer.ts; "Math" in
8
- * `RECOMMENDED_EXTENSIONS`, extension-manager.ts), exactly like the Callouts
8
+ * `BUNDLED_EXTENSIONS`, extension-specifier.ts), exactly like the Callouts
9
9
  * feature: a book that never lists it renders `$` as the character it is.
10
10
  *
11
11
  * WHY SVG. Each formula is written as a drawing of its own glyphs, so the
@@ -22,7 +22,7 @@ export interface InstalledNpmPlugin {
22
22
  installRoot: string;
23
23
  /** Previous same-version directory held until the manifest commits. */
24
24
  backupRoot: string | null;
25
- /** Folders THIS install created (`plugins/`, `plugins/npm/`, `plugins/npm/<name>/`), outermost first. */
25
+ /** Folders THIS install created (`extensions/`, `extensions/npm/`, `extensions/npm/<name>/`), outermost first. */
26
26
  createdDirs: string[];
27
27
  warnings: string[];
28
28
  }
@@ -1,5 +1,7 @@
1
- /** Project-relative folder shared by local and vendored npm plugins. */
2
- export declare const PLUGINS_DIR = "plugins";
1
+ /** Project-relative folder every extension a book carries lives under: vendored npm copies in `npm/`, imports beside them. */
2
+ export declare const EXTENSIONS_DIR = "extensions";
3
+ /** Where books vendored before 0.11.23 keep their npm copies. Read, never written. */
4
+ export declare const LEGACY_PLUGINS_DIR = "plugins";
3
5
  export declare const VENDORED_NPM_DIR = "npm";
4
6
  export interface ParsedNpmPluginSpec {
5
7
  name: string;
@@ -15,8 +17,14 @@ export declare function isValidNpmPackageName(name: string): boolean;
15
17
  /** Parse `name`, `name@selector`, `@scope/name`, or `@scope/name@selector`. */
16
18
  export declare function parseNpmPluginSpec(input: string): ParsedNpmPluginSpec;
17
19
  export declare function isExactNpmVersion(version: string): boolean;
18
- /** Root containing one pinned package's private `node_modules` tree. */
20
+ /** Root containing one pinned package's private `node_modules` tree — where an install writes. */
19
21
  export declare function vendoredNpmPluginRoot(projectDir: string, name: string, version: string): string;
22
+ /**
23
+ * Every root a pinned package's copy may live at: the current folder first,
24
+ * then the one books vendored before 0.11.23 used. Resolution, removal and
25
+ * pruning all go through this list so they agree on where a copy can be.
26
+ */
27
+ export declare function vendoredNpmPluginRoots(projectDir: string, name: string, version: string): string[];
20
28
  /** npm-compatible package location within a versioned vendor root. */
21
29
  export declare function vendoredNpmPluginPackageDir(installRoot: string, name: string): string;
22
30
  export declare function toPosixPath(value: string): string;
@@ -1,7 +1,7 @@
1
1
  /** Entries every book ignores, in the order they are appended. */
2
- export declare const PROJECT_GITIGNORE_ENTRIES: readonly ["dist/", "plugins/npm/"];
2
+ export declare const PROJECT_GITIGNORE_ENTRIES: readonly ["dist/", "extensions/npm/"];
3
3
  /**
4
- * Make sure `<projectDir>/.gitignore` ignores `dist/` and `plugins/npm/`,
4
+ * Make sure `<projectDir>/.gitignore` ignores `dist/` and `extensions/npm/`,
5
5
  * creating the file or appending what is missing. Returns the entries the
6
6
  * author's own rules re-include (left alone) so a caller can warn.
7
7
  */