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.
Files changed (76) hide show
  1. package/README.md +23 -24
  2. package/dist/{README-3nj919rm.md → README-8ef336pp.md} +1 -1
  3. package/dist/api/index.d.ts +4 -4
  4. package/dist/api/index.js +16 -22
  5. package/dist/{build-53bw14h7.js → build-encgnv0c.js} +9 -10
  6. package/dist/{chapter-01-rkpyvjna.md → chapter-01-gsbjt584.md} +1 -1
  7. package/dist/chapter-01-s71xrf5q.md +69 -0
  8. package/dist/{chapter-01-7jwqg1ct.md → chapter-01-wgjfz4w6.md} +1 -1
  9. package/dist/checks/source/character-table.d.ts +12 -6
  10. package/dist/{cli-habkc5ng.js → cli-a35w7wzg.js} +5 -4
  11. package/dist/{cli-kx4hbnx2.js → cli-aqh6brew.js} +1 -1
  12. package/dist/{cli-1hxxwbaq.js → cli-evg8sbht.js} +1 -1
  13. package/dist/{cli-cjftezxr.js → cli-kh8v4vvw.js} +2 -1
  14. package/dist/{cli-ntwqmdnw.js → cli-pwwfxdgb.js} +846 -13
  15. package/dist/{cli-8kg0wjdt.js → cli-pz4bn98t.js} +185 -9
  16. package/dist/{cli-zj5xaepv.js → cli-sdmv4bba.js} +57 -117
  17. package/dist/{cli-ke86zsz6.js → cli-xq6djqbj.js} +51 -54
  18. package/dist/{index-r7jcsk6h.js → cli-y28j019d.js} +19 -10
  19. package/dist/cli.js +12 -12
  20. package/dist/{doctor-xka1frnx.js → doctor-5gtpgpd1.js} +3 -3
  21. package/dist/{engine-p93f06gj.js → engine-mc5br8g8.js} +1 -2
  22. package/dist/{engine-0ndvy8vj.js → engine-tn13gk0b.js} +3 -3
  23. package/dist/{ext-dwfqyy1j.js → ext-wn2a5afq.js} +18 -33
  24. package/dist/{extension-restore-ct1wk344.js → extension-restore-g8jnmmzq.js} +5 -6
  25. package/dist/{extension-restore-7vp3vh77.js → extension-restore-s3x1618g.js} +4 -4
  26. package/dist/{index-apc8w9w8.js → index-0skhjx3e.js} +180 -1
  27. package/dist/{index-4v7e621e.js → index-2bjcghze.js} +847 -13
  28. package/dist/index-46ycxe6r.js +18 -0
  29. package/dist/{index-53nrm5j1.js → index-4x6y8krm.js} +2 -4
  30. package/dist/{cli-h3phdstf.js → index-5x42amh8.js} +19 -10
  31. package/dist/{index-93pqkvty.js → index-h6yk5tjx.js} +5 -4
  32. package/dist/{index-kh7fayjv.js → index-j5z86r4a.js} +57 -54
  33. package/dist/{index-6cmn2wpd.js → index-x3ema2w3.js} +69 -128
  34. package/dist/index.js +17 -23
  35. package/dist/lib/build-runner.d.ts +1 -1
  36. package/dist/lib/extension-manager.d.ts +16 -43
  37. package/dist/lib/extension-scaffold.d.ts +3 -3
  38. package/dist/lib/extension-specifier.d.ts +23 -6
  39. package/dist/lib/markdown/assemble.d.ts +7 -1
  40. package/dist/lib/markdown/gutterpress-css.d.ts +1 -1
  41. package/dist/lib/markdown/index.d.ts +4 -0
  42. package/dist/lib/markdown/math.d.ts +43 -0
  43. package/dist/lib/markdown/renderer.d.ts +11 -8
  44. package/dist/lib/markdown/table.d.ts +46 -0
  45. package/dist/lib/markdown/typography.d.ts +12 -0
  46. package/dist/lib/npm-plugin-installer.d.ts +1 -1
  47. package/dist/lib/plugin-vendor.d.ts +11 -3
  48. package/dist/lib/presets.d.ts +1 -1
  49. package/dist/lib/project-gitignore.d.ts +2 -2
  50. package/dist/lib/project-scaffold.d.ts +6 -8
  51. package/dist/lib/project-templates.d.ts +6 -1
  52. package/dist/lib/snippets.d.ts +2 -1
  53. package/dist/lib/style-resolver.d.ts +1 -2
  54. package/dist/manifest-eagfhba6.yaml +19 -0
  55. package/dist/{manifest.schema-399bx3vc.json → manifest.schema-t7nx2stg.json} +12 -5
  56. package/dist/{new-1pawj2qf.js → new-mhs46pw3.js} +22 -21
  57. package/dist/{plugins-fr4fnzhb.js → plugins-1sxe0dkz.js} +4 -4
  58. package/dist/{plugins-g4dgw7mn.js → plugins-2cek4mz1.js} +2 -2
  59. package/dist/{preflight-ept9q57t.js → preflight-3k2b1x8e.js} +9 -10
  60. package/dist/preview/file-watcher.d.ts +1 -0
  61. package/dist/{preview-fxpnjv7k.js → preview-6p9v6rht.js} +9 -10
  62. package/dist/{publish-zhqqsgmr.js → publish-qgsngy8s.js} +9 -10
  63. package/dist/render.js +470 -11
  64. package/dist/schema/manifest.types.d.ts +8 -0
  65. package/dist/{source-provider-qbfknhyy.js → source-provider-98k5deda.js} +2 -2
  66. package/dist/{source-provider-2r74a7wp.js → source-provider-knmcam50.js} +2 -2
  67. package/dist/{validate-t68gvckq.js → validate-0v7xw6wa.js} +9 -10
  68. package/package.json +2 -1
  69. package/dist/cli-1ngqzg8s.js +0 -196
  70. package/dist/index-vay3ff1f.js +0 -213
  71. package/dist/package-97gm31sg.json +0 -10
  72. package/dist/package-gag6ykwn.json +0 -10
  73. package/dist/package-nrhkwf2m.json +0 -10
  74. package/dist/theme-h5recz6c.css +0 -61
  75. package/dist/theme-j2bagrfx.css +0 -59
  76. package/dist/theme-nn6d53zy.css +0 -71
@@ -8,16 +8,17 @@ import {
8
8
  stampCreator,
9
9
  stripAnnotations,
10
10
  transparentPages
11
- } from "./cli-1hxxwbaq.js";
11
+ } from "./cli-evg8sbht.js";
12
12
  import {
13
13
  blackTextToGray
14
14
  } from "./cli-ht1bcqdd.js";
15
15
  import {
16
16
  MARGIN_BOX_IGNORED_PROPERTIES,
17
17
  extract,
18
+ getAssetPath,
18
19
  lastPageMode,
19
20
  resolvePage
20
- } from "./cli-8kg0wjdt.js";
21
+ } from "./cli-pz4bn98t.js";
21
22
  import {
22
23
  countLinkAnnotations,
23
24
  getImageResolutions,
@@ -42,13 +43,12 @@ import {
42
43
  import {
43
44
  hasUncommittedChanges,
44
45
  listWorkdirChanges
45
- } from "./cli-habkc5ng.js";
46
+ } from "./cli-a35w7wzg.js";
46
47
  import {
47
48
  detectProjectSource,
48
49
  repoSubPath
49
50
  } from "./cli-v5mp7a6q.js";
50
51
  import {
51
- EXTENSIONS_DIR,
52
52
  FriendlyHttpError,
53
53
  MANIFEST_FILENAMES,
54
54
  PRESETS,
@@ -70,7 +70,7 @@ import {
70
70
  uniqueExtensionId,
71
71
  withFetchTimeout,
72
72
  writeManifestDoc
73
- } from "./cli-zj5xaepv.js";
73
+ } from "./cli-sdmv4bba.js";
74
74
  import {
75
75
  EXTENSION_MANIFEST_FILENAME,
76
76
  GUTTERPRESS_CSS,
@@ -91,7 +91,7 @@ import {
91
91
  readExtensionMeta,
92
92
  resolveDeclaredStyles,
93
93
  slugify
94
- } from "./cli-ntwqmdnw.js";
94
+ } from "./cli-pwwfxdgb.js";
95
95
  import {
96
96
  PACKAGE_META,
97
97
  PACKAGE_VERSION,
@@ -101,22 +101,20 @@ import {
101
101
  log,
102
102
  setLogLevel,
103
103
  warn
104
- } from "./cli-kx4hbnx2.js";
104
+ } from "./cli-aqh6brew.js";
105
105
  import {
106
106
  DEBOUNCE,
107
107
  UsageError,
108
108
  resolvePort
109
109
  } from "./cli-d8xjns66.js";
110
- import {
111
- getAssetPath
112
- } from "./cli-1ngqzg8s.js";
113
110
  import {
114
111
  BuildError
115
112
  } from "./cli-46ycxe6r.js";
116
113
  import {
114
+ EXTENSIONS_DIR,
117
115
  resolveVendoredPluginInstallRoot,
118
116
  vendoredNpmPluginPackageDir
119
- } from "./cli-h3phdstf.js";
117
+ } from "./cli-y28j019d.js";
120
118
  import {
121
119
  __require
122
120
  } from "./cli-37x76zdn.js";
@@ -1817,13 +1815,7 @@ import { existsSync as existsSync3 } from "node:fs";
1817
1815
  import { readdir } from "node:fs/promises";
1818
1816
  import path from "node:path";
1819
1817
  var STYLES_SUBDIR = "styles";
1820
- var FALLBACK_PRIORITY = [
1821
- "styles/book.css",
1822
- "css/print.css",
1823
- "css/index.css",
1824
- "css/style.css",
1825
- "css/main.css"
1826
- ];
1818
+ var DEFAULT_STYLESHEET = "styles/book.css";
1827
1819
  function relDisplay(projectDir, absPath) {
1828
1820
  return path.relative(projectDir, absPath).split(path.sep).join("/");
1829
1821
  }
@@ -1861,10 +1853,8 @@ async function resolveActiveStyles(projectDir, manifestStyles) {
1861
1853
  const manifest = configured.filter((s) => typeof s === "string" && s.trim().length > 0);
1862
1854
  if (manifest.length > 0)
1863
1855
  return manifest;
1864
- for (const rel of FALLBACK_PRIORITY) {
1865
- if (existsSync3(path.join(projectDir, rel)))
1866
- return [rel];
1867
- }
1856
+ if (existsSync3(path.join(projectDir, DEFAULT_STYLESHEET)))
1857
+ return [DEFAULT_STYLESHEET];
1868
1858
  const discovered = await discoverCssFiles(projectDir);
1869
1859
  if (discovered.length > 0) {
1870
1860
  const first = discovered.map((abs) => relDisplay(projectDir, abs)).sort((a, b) => a.localeCompare(b))[0];
@@ -3024,7 +3014,7 @@ async function collectKnownClasses(ctx, plugins) {
3024
3014
  var check26 = {
3025
3015
  id: "source.markdown.layout-markers",
3026
3016
  name: "Layout Markers",
3027
- description: "Reports @page/@section/@chapter marker arguments Gutterpress could not understand, plus any unknown gp-* class and any other class no stylesheet mentions",
3017
+ description: "Reports @page/@section/@chapter marker arguments Gutterpress could not understand, any unknown gp-* class and any other class no stylesheet mentions, a table row with more cells than its table has columns, and a formula that could not be typeset",
3028
3018
  category: "source",
3029
3019
  phase: "pre-build",
3030
3020
  async run(ctx) {
@@ -3188,14 +3178,14 @@ registerCheck(check27);
3188
3178
  import { readFile as readFile13 } from "node:fs/promises";
3189
3179
 
3190
3180
  // src/checks/source/character-table.ts
3191
- var CHARACTER_PATTERN = new RegExp("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u00A0\\u00AD\\u00B4\\u02BC" + "\\u061C\\u2000-\\u2015\\u2018\\u2019\\u201B-\\u201D\\u201F\\u2022\\u2026" + "\\u2028-\\u202F\\u2032\\u2033\\u205F\\u2060\\u2066-\\u2069\\u2190\\u2192" + "\\u2194\\u21D2\\u2212\\u25AA\\u25E6\\u2605\\u2713\\u2714\\u2717\\u3000" + "\\uE000-\\uF8FF\\uFEFF\\uFF02\\uFF07\\uFFFD]" + "|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}(?=\\uFE0F)", "gu");
3181
+ var CHARACTER_PATTERN = new RegExp("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u00A0\\u00AD\\u00B4\\u02BC" + "\\u061C\\u2000-\\u2015\\u2018\\u201B-\\u201D\\u201F\\u2022\\u2026" + "\\u2028-\\u202F\\u2032\\u2033\\u205F\\u2060\\u2066-\\u2069\\u2190\\u2192" + "\\u2194\\u21D2\\u2212\\u25AA\\u25E6\\u2605\\u2713\\u2714\\u2717\\u3000" + "\\uE000-\\uF8FF\\uFEFF\\uFF02\\uFF07\\uFFFD]" + "|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}(?=\\uFE0F)" + "|(?<=[\\p{L}\\p{N}])\\u2019|\\u2019(?![\\p{L}\\p{N}])", "gu");
3192
3182
  var NAMED = {
3193
3183
  8212: ["Em dash", "typographer", "---"],
3194
3184
  8211: ["En dash", "typographer", "--"],
3195
- 8220: ["Opening curly quote", "typographer", '"'],
3196
- 8221: ["Closing curly quote", "typographer", '"'],
3197
- 8216: ["Opening curly single quote", "typographer", "'"],
3198
- 8217: ["Curly apostrophe", "typographer", "'"],
3185
+ 8220: ["Left curly quote", "typographer", '"'],
3186
+ 8221: ["Right curly quote", "typographer", '"'],
3187
+ 8216: ["Left curly single quote", "typographer", "'"],
3188
+ 8217: ["Right curly single quote (apostrophe)", "typographer", "'"],
3199
3189
  8230: ["Ellipsis character", "typographer", "..."],
3200
3190
  700: ["Modifier-letter apostrophe", "lookalike", "'"],
3201
3191
  180: ["Acute accent", "lookalike", "'"],
@@ -3955,7 +3945,7 @@ function reportMissingTools(result) {
3955
3945
  const affected = checkIds.filter((id) => result.skippedChecks.includes(id));
3956
3946
  if (affected.length === 0)
3957
3947
  continue;
3958
- log.warn(`Tool "${tool}" not found — skipping: ${affected.join(", ")}`);
3948
+ log.warn(`Tool "${tool}" not found; skipping: ${affected.join(", ")}`);
3959
3949
  }
3960
3950
  }
3961
3951
 
@@ -4020,11 +4010,12 @@ async function assembleBookHtml(opts) {
4020
4010
  const title = opts.title ?? "Document";
4021
4011
  const projectCss = opts.projectCss ?? "";
4022
4012
  const pluginCss = opts.pluginCss ?? "";
4013
+ const language = opts.language ?? "en";
4023
4014
  const files = opts.files;
4024
4015
  if (files.length === 0) {
4025
4016
  throw new Error("No markdown files to render");
4026
4017
  }
4027
- const md = createMarkdownRenderer(opts.plugins);
4018
+ const md = createMarkdownRenderer(opts.plugins, { language });
4028
4019
  let bodyContent = "";
4029
4020
  const imageRefs = new Set;
4030
4021
  for (const file of files) {
@@ -4036,7 +4027,7 @@ async function assembleBookHtml(opts) {
4036
4027
  const errorMsg = err instanceof Error ? err.message : String(err);
4037
4028
  throw new Error(`Failed to read file ${file}: ${errorMsg}`);
4038
4029
  }
4039
- const env = {};
4030
+ const env = { docId: slugify(chapterId) };
4040
4031
  if (opts.annotateSourceChapters)
4041
4032
  env.sourceChapter = chapterId;
4042
4033
  const rendered = md.render(content, env);
@@ -4082,7 +4073,7 @@ ${projectCss.trim()}` : null
4082
4073
  const lastPage = opts.print && lastPageMode(opts.print);
4083
4074
  const printAttrs = (opts.print?.signature && opts.print.signature > 1 ? ` data-gp-signature="${opts.print.signature}"` : "") + (lastPage ? ` data-gp-last-page="${lastPage}"` : "");
4084
4075
  return `<!DOCTYPE html>
4085
- <html lang="en"${printAttrs}>
4076
+ <html lang="${language}"${printAttrs}>
4086
4077
  <head>
4087
4078
  <meta charset="UTF-8">
4088
4079
  <meta name="viewport" content="width=device-width, initial-scale=1.0">${opts.printArea ? `
@@ -4145,6 +4136,7 @@ ${css.trim()}
4145
4136
  projectCss: inlined.css,
4146
4137
  preloadImages: cssAssetCopies.map((c) => c.to),
4147
4138
  title: opts.title,
4139
+ language: opts.language,
4148
4140
  print: opts.print,
4149
4141
  printArea: opts.printArea,
4150
4142
  plugins: opts.plugins,
@@ -4158,6 +4150,7 @@ async function renderChaptersToFile(inputDir, outDir, opts = {}) {
4158
4150
  await mkdir(outDir, { recursive: true });
4159
4151
  const html = await renderChapters(inputDir, {
4160
4152
  title: opts.title,
4153
+ language: opts.language,
4161
4154
  print: opts.print,
4162
4155
  printArea: opts.printArea,
4163
4156
  styles: opts.styles,
@@ -5058,6 +5051,7 @@ async function renderBook(ctx) {
5058
5051
  const cssAssets = [];
5059
5052
  const htmlFile = await renderChaptersToFile(renderDir, workDir, {
5060
5053
  title: config.title,
5054
+ language: config.language,
5061
5055
  print: config.print,
5062
5056
  printArea: { ...config.page, preset: config.preset, spec: config.spec },
5063
5057
  styles: config.styles,
@@ -5212,7 +5206,7 @@ class PdfOutput {
5212
5206
  const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
5213
5207
  await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
5214
5208
  log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
5215
- const { buildNativePdf } = await import("./engine-p93f06gj.js");
5209
+ const { buildNativePdf } = await import("./engine-mc5br8g8.js");
5216
5210
  const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
5217
5211
  title: config.title,
5218
5212
  author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
@@ -5514,6 +5508,7 @@ async function renderPreviewBook(inputPath, config, opts) {
5514
5508
  const { plugins, pluginStyles } = await loadPluginsWithCss(config.extensions, inputPath, (ref, err) => warn(`Skipping plugin "${ref}" in preview — ${err.message}`));
5515
5509
  return renderChapters(inputPath, {
5516
5510
  title: config.title ?? "Document",
5511
+ language: config.language,
5517
5512
  print: config.print,
5518
5513
  printArea: config.printArea,
5519
5514
  styles: config.styles,
@@ -5591,7 +5586,7 @@ function isGeneratedProjectPath(relative) {
5591
5586
  const segment = segments[i];
5592
5587
  if (segment === "dist" || segment === "node_modules")
5593
5588
  return true;
5594
- if (segment === "plugins" && segments[i + 1] === "npm")
5589
+ if ((segment === "extensions" || segment === "plugins") && segments[i + 1] === "npm")
5595
5590
  return true;
5596
5591
  }
5597
5592
  return false;
@@ -6528,10 +6523,10 @@ function starterOverridesCss() {
6528
6523
  * Your book's own styles.
6529
6524
  *
6530
6525
  * This file loads AFTER every extension, so any rule you add here overrides
6531
- * a look's defaults. A new book has no look until you add one:
6532
- * gutterpress ext add clean-book <book> --look (a built-in look)
6533
- * gutterpress ext add <package> <book> (a look from npm)
6534
- * A book has one look at a time; adding another turns the current one off.
6526
+ * a look's defaults. A new book has no look until its template or you add
6527
+ * one:
6528
+ * gutterpress ext add academic <book> (a built-in look)
6529
+ * gutterpress ext add <package> <book> (a look from npm)
6535
6530
  */
6536
6531
  `;
6537
6532
  }
@@ -6552,9 +6547,8 @@ function escapeYamlScalar(value) {
6552
6547
  }
6553
6548
  var DEFAULT_AUTHOR = "Anonymous";
6554
6549
  function requirePreset(preset, customPage) {
6555
- if (!preset || !PRESET_IDS.includes(preset)) {
6556
- const got = preset ? ` (got "${preset}")` : "";
6557
- throw new CreateProjectErrorImpl("preset-required", `A preset is required to create a book${got}. Choose one of: ${PRESET_IDS.join(", ")}.`);
6550
+ if (!PRESET_IDS.includes(preset)) {
6551
+ throw new CreateProjectErrorImpl("preset-required", `Unknown preset "${preset}". Choose one of: ${PRESET_IDS.join(", ")}.`);
6558
6552
  }
6559
6553
  if (preset === "custom") {
6560
6554
  const missing = [];
@@ -6612,7 +6606,7 @@ async function scaffoldProject(options) {
6612
6606
  }
6613
6607
  const template = options.template ?? "book";
6614
6608
  const customTemplateDir = options.templateDir;
6615
- const preset = customTemplateDir && options.preset === undefined ? undefined : requirePreset(options.preset, options.customPage);
6609
+ const preset = options.preset === undefined ? undefined : requirePreset(options.preset, options.customPage);
6616
6610
  const targets = preset ? resolveScaffoldTargets(options.targets, preset) : undefined;
6617
6611
  try {
6618
6612
  await mkdir4(projectDir, { recursive: true });
@@ -6650,10 +6644,12 @@ async function scaffoldProject(options) {
6650
6644
  let openFile = path12.join(projectDir, "chapter-01.md");
6651
6645
  try {
6652
6646
  await fillTemplateFile(manifestPath, substitutions);
6653
- if (preset) {
6647
+ if (preset || options.customPage) {
6654
6648
  const { doc, file } = await loadManifestDoc(projectDir);
6655
- doc.set("preset", preset);
6656
- doc.set("targets", doc.createNode(targets ?? []));
6649
+ if (preset) {
6650
+ doc.set("preset", preset);
6651
+ doc.set("targets", doc.createNode(targets ?? []));
6652
+ }
6657
6653
  if (options.customPage)
6658
6654
  writePageBounds(doc, options.customPage);
6659
6655
  await writeManifestDoc(file, doc);
@@ -6670,7 +6666,7 @@ async function scaffoldProject(options) {
6670
6666
  let versionHistoryError;
6671
6667
  if (requested === "local-git") {
6672
6668
  try {
6673
- const { providerFor } = await import("./source-provider-2r74a7wp.js");
6669
+ const { providerFor } = await import("./source-provider-knmcam50.js");
6674
6670
  const provider = providerFor({ type: "local-folder", path: projectDir });
6675
6671
  await provider.initVersionHistory({
6676
6672
  projectDir,
@@ -6722,7 +6718,7 @@ async function fillTemplateFile(filePath, substitutions) {
6722
6718
  import { access as access2, mkdir as mkdir5, readFile as readFile23, writeFile as writeFile6 } from "node:fs/promises";
6723
6719
  import { constants as FS2 } from "node:fs";
6724
6720
  import path13 from "node:path";
6725
- var EXTENSION_KINDS = ["plugin", "theme"];
6721
+ var EXTENSION_KINDS = ["plugin", "look"];
6726
6722
  var RESERVED_PREFIX = "gp-";
6727
6723
  var TEMPLATE_FILES = {
6728
6724
  plugin: [
@@ -6735,7 +6731,7 @@ var TEMPLATE_FILES = {
6735
6731
  ["test/expected.html", "test/expected.html"],
6736
6732
  ["test/plugin.test.js.tpl", "test/plugin.test.js"]
6737
6733
  ],
6738
- theme: [
6734
+ look: [
6739
6735
  ["package.json", "package.json"],
6740
6736
  ["README.md", "README.md"],
6741
6737
  ["components.yaml", "components.yaml"],
@@ -6750,11 +6746,11 @@ var TEMPLATE_FILES = {
6750
6746
  };
6751
6747
  var OPEN_FILE = {
6752
6748
  plugin: "plugin.js",
6753
- theme: "styles/tokens.css"
6749
+ look: "styles/tokens.css"
6754
6750
  };
6755
6751
  var DEFAULT_DESCRIPTION = {
6756
6752
  plugin: "A Gutterpress plugin.",
6757
- theme: "A Gutterpress theme."
6753
+ look: "A Gutterpress look."
6758
6754
  };
6759
6755
  var DEFAULT_AUTHOR2 = "Anonymous";
6760
6756
 
@@ -6786,7 +6782,7 @@ function escapeJsonScalar(value) {
6786
6782
  }
6787
6783
  async function scaffoldExtension(options) {
6788
6784
  const kind = options.kind;
6789
- if (kind !== "plugin" && kind !== "theme") {
6785
+ if (kind !== "plugin" && kind !== "look") {
6790
6786
  throw new ExtensionScaffoldError("invalid-name", `Unknown extension kind "${String(kind)}". Choose one of: ${EXTENSION_KINDS.join(", ")}.`);
6791
6787
  }
6792
6788
  const name = (options.name ?? "").trim();
@@ -6867,7 +6863,8 @@ import { isMap as isMap2, isScalar, isSeq, parseDocument } from "yaml";
6867
6863
  var BUILT_IN_TEMPLATE_IDS = [
6868
6864
  "book",
6869
6865
  "zine",
6870
- "technical"
6866
+ "technical",
6867
+ "paper"
6871
6868
  ];
6872
6869
  var SKIP_ENTRIES = new Set([
6873
6870
  ".git",
@@ -9023,7 +9020,7 @@ async function resolvePublishProvider(id, book) {
9023
9020
  const ext = await bookExtensions(book);
9024
9021
  const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
9025
9022
  if (npmEntry) {
9026
- const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-ct1wk344.js");
9023
+ const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-g8jnmmzq.js");
9027
9024
  await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
9028
9025
  }
9029
9026
  const publishers = await discover(ext);
@@ -9061,7 +9058,7 @@ function infoFor(p) {
9061
9058
  }
9062
9059
  function pluginProvider(p) {
9063
9060
  let loading;
9064
- const load = () => loading ??= import("./plugins-fr4fnzhb.js").then((m) => m.loadPublishFunction(p));
9061
+ const load = () => loading ??= import("./plugins-1sxe0dkz.js").then((m) => m.loadPublishFunction(p));
9065
9062
  return {
9066
9063
  info: infoFor(p),
9067
9064
  async authenticate() {
@@ -2,7 +2,8 @@
2
2
  import { lstat, readFile, realpath } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { exports as resolveExports } from "resolve.exports";
5
- var PLUGINS_DIR = "plugins";
5
+ var EXTENSIONS_DIR = "extensions";
6
+ var LEGACY_PLUGINS_DIR = "plugins";
6
7
  var VENDORED_NPM_DIR = "npm";
7
8
  var NPM_SEGMENT = /^[a-z0-9][a-z0-9._~-]*$/;
8
9
  var EXACT_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
@@ -51,7 +52,10 @@ function encodePathPart(value) {
51
52
  return encodeURIComponent(value).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
52
53
  }
53
54
  function vendoredNpmPluginRoot(projectDir, name, version) {
54
- return path.join(projectDir, PLUGINS_DIR, VENDORED_NPM_DIR, encodePathPart(name), encodePathPart(version));
55
+ return path.join(projectDir, EXTENSIONS_DIR, VENDORED_NPM_DIR, encodePathPart(name), encodePathPart(version));
56
+ }
57
+ function vendoredNpmPluginRoots(projectDir, name, version) {
58
+ return [EXTENSIONS_DIR, LEGACY_PLUGINS_DIR].map((parent) => path.join(projectDir, parent, VENDORED_NPM_DIR, encodePathPart(name), encodePathPart(version)));
55
59
  }
56
60
  function vendoredNpmPluginPackageDir(installRoot, name) {
57
61
  return path.join(installRoot, "node_modules", ...name.split("/"));
@@ -175,15 +179,20 @@ async function resolvePackageEntry(packageDir, packageJson) {
175
179
  }
176
180
  async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expectedVersion) {
177
181
  const requestedProjectRoot = path.resolve(projectDir);
178
- const requestedInstallRoot = vendoredNpmPluginRoot(requestedProjectRoot, expectedName, expectedVersion);
182
+ let requestedInstallRoot = "";
179
183
  let installInfo;
180
- try {
181
- installInfo = await lstat(requestedInstallRoot);
182
- } catch (error) {
183
- if (error.code === "ENOENT")
184
- return null;
185
- throw error;
184
+ for (const candidate of vendoredNpmPluginRoots(requestedProjectRoot, expectedName, expectedVersion)) {
185
+ requestedInstallRoot = candidate;
186
+ try {
187
+ installInfo = await lstat(requestedInstallRoot);
188
+ break;
189
+ } catch (error) {
190
+ if (error.code !== "ENOENT")
191
+ throw error;
192
+ }
186
193
  }
194
+ if (!installInfo)
195
+ return null;
187
196
  if (!installInfo.isDirectory() || installInfo.isSymbolicLink()) {
188
197
  throw new Error("Vendor install root is not a normal directory.");
189
198
  }
@@ -197,4 +206,4 @@ async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expect
197
206
  return installRoot;
198
207
  }
199
208
 
200
- export { PLUGINS_DIR, VENDORED_NPM_DIR, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginPackageDir, toPosixPath, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, safePackageTarget, resolvePackageEntry, resolveVendoredPluginInstallRoot };
209
+ export { EXTENSIONS_DIR, LEGACY_PLUGINS_DIR, VENDORED_NPM_DIR, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginRoots, vendoredNpmPluginPackageDir, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, safePackageTarget, resolvePackageEntry, resolveVendoredPluginInstallRoot };
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  } from "./cli-d8xjns66.js";
9
9
  import {
10
10
  package_default
11
- } from "./cli-cjftezxr.js";
11
+ } from "./cli-kh8v4vvw.js";
12
12
  import {
13
13
  EXIT_CODES
14
14
  } from "./cli-46ycxe6r.js";
@@ -20,14 +20,14 @@ import {
20
20
  import { defineCommand, parseArgs, runMain } from "citty";
21
21
  import { statSync } from "node:fs";
22
22
  var SUBCOMMANDS = {
23
- new: () => import("./new-1pawj2qf.js").then((m) => m.default),
24
- preview: () => import("./preview-fxpnjv7k.js").then((m) => m.default),
25
- build: () => import("./build-53bw14h7.js").then((m) => m.default),
26
- publish: () => import("./publish-zhqqsgmr.js").then((m) => m.default),
27
- validate: () => import("./validate-t68gvckq.js").then((m) => m.default),
28
- preflight: () => import("./preflight-ept9q57t.js").then((m) => m.default),
29
- doctor: () => import("./doctor-xka1frnx.js").then((m) => m.default),
30
- ext: () => import("./ext-dwfqyy1j.js").then((m) => m.default)
23
+ new: () => import("./new-mhs46pw3.js").then((m) => m.default),
24
+ preview: () => import("./preview-6p9v6rht.js").then((m) => m.default),
25
+ build: () => import("./build-encgnv0c.js").then((m) => m.default),
26
+ publish: () => import("./publish-qgsngy8s.js").then((m) => m.default),
27
+ validate: () => import("./validate-0v7xw6wa.js").then((m) => m.default),
28
+ preflight: () => import("./preflight-3k2b1x8e.js").then((m) => m.default),
29
+ doctor: () => import("./doctor-5gtpgpd1.js").then((m) => m.default),
30
+ ext: () => import("./ext-wn2a5afq.js").then((m) => m.default)
31
31
  };
32
32
  var VERSION = package_default.version;
33
33
  var main = defineCommand({
@@ -52,7 +52,7 @@ async function preflightRequiredInvocations(rawArgs) {
52
52
  const [command, ...commandArgs] = rawArgs;
53
53
  try {
54
54
  if (command === "new") {
55
- const { newArgs } = await import("./new-1pawj2qf.js");
55
+ const { newArgs } = await import("./new-mhs46pw3.js");
56
56
  rejectUnknownFlags(commandArgs, newArgs, "new");
57
57
  const parsed = parseArgs(commandArgs, {
58
58
  ...newArgs,
@@ -64,7 +64,7 @@ async function preflightRequiredInvocations(rawArgs) {
64
64
  return;
65
65
  }
66
66
  if (command === "preflight") {
67
- const { preflightArgs } = await import("./preflight-ept9q57t.js");
67
+ const { preflightArgs } = await import("./preflight-3k2b1x8e.js");
68
68
  rejectUnknownFlags(commandArgs, preflightArgs, "preflight");
69
69
  const parsed = parseArgs(commandArgs, {
70
70
  ...preflightArgs,
@@ -84,7 +84,7 @@ async function preflightRequiredInvocations(rawArgs) {
84
84
  }
85
85
  if (subcommand.startsWith("-"))
86
86
  return;
87
- const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-dwfqyy1j.js");
87
+ const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-wn2a5afq.js");
88
88
  if (!EXT_SUBCOMMANDS.includes(subcommand)) {
89
89
  throw new UsageError(`gutterpress ext: unknown command "${subcommand}"`);
90
90
  }
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  getSystemDiagnostics
3
- } from "./cli-1hxxwbaq.js";
3
+ } from "./cli-evg8sbht.js";
4
4
  import"./cli-asap4t1z.js";
5
5
  import {
6
6
  log
7
- } from "./cli-kx4hbnx2.js";
7
+ } from "./cli-aqh6brew.js";
8
8
  import {
9
9
  UsageError,
10
10
  rejectExtraPositionals,
11
11
  rejectUnknownFlags
12
12
  } from "./cli-d8xjns66.js";
13
- import"./cli-cjftezxr.js";
13
+ import"./cli-kh8v4vvw.js";
14
14
  import"./cli-46ycxe6r.js";
15
15
  import"./cli-37x76zdn.js";
16
16
 
@@ -1,9 +1,8 @@
1
1
  import {
2
2
  build
3
- } from "./cli-8kg0wjdt.js";
3
+ } from "./cli-pz4bn98t.js";
4
4
  import"./cli-eyyggect.js";
5
5
  import"./cli-asap4t1z.js";
6
- import"./cli-1ngqzg8s.js";
7
6
  import {
8
7
  BuildError
9
8
  } from "./cli-46ycxe6r.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  build
3
- } from "./index-53nrm5j1.js";
4
- import"./index-apc8w9w8.js";
3
+ } from "./index-4x6y8krm.js";
4
+ import"./index-0skhjx3e.js";
5
5
  import {
6
6
  BuildError
7
- } from "./index-vay3ff1f.js";
7
+ } from "./index-46ycxe6r.js";
8
8
  import"./index-bt0qws5c.js";
9
9
  import"./index-37x76zdn.js";
10
10
 
@@ -2,29 +2,28 @@ import {
2
2
  importExtensionFromFile,
3
3
  importExtensionFromUrl,
4
4
  searchNpmExtensions
5
- } from "./cli-ke86zsz6.js";
6
- import"./cli-1hxxwbaq.js";
5
+ } from "./cli-xq6djqbj.js";
6
+ import"./cli-evg8sbht.js";
7
7
  import"./cli-ht1bcqdd.js";
8
- import"./cli-8kg0wjdt.js";
8
+ import"./cli-pz4bn98t.js";
9
9
  import"./cli-2ppw6q9v.js";
10
10
  import"./cli-eyyggect.js";
11
11
  import"./cli-asap4t1z.js";
12
- import"./cli-habkc5ng.js";
12
+ import"./cli-a35w7wzg.js";
13
13
  import"./cli-v5mp7a6q.js";
14
14
  import {
15
- BUILT_IN_STYLE_SET_IDS,
16
- addBuiltInStyleSet,
17
15
  addExtension,
18
16
  checkExtensionUpdates,
19
- isPathSpecifier,
20
17
  listProjectExtensions,
21
- parseExtensionSpecifier,
22
18
  removeExtension,
23
19
  setExtensionEnabled,
24
20
  updateExtensions
25
- } from "./cli-zj5xaepv.js";
26
- import"./cli-ntwqmdnw.js";
27
- import"./cli-kx4hbnx2.js";
21
+ } from "./cli-sdmv4bba.js";
22
+ import {
23
+ isPathSpecifier,
24
+ parseExtensionSpecifier
25
+ } from "./cli-pwwfxdgb.js";
26
+ import"./cli-aqh6brew.js";
28
27
  import {
29
28
  UsageError,
30
29
  exitForUsage,
@@ -32,12 +31,11 @@ import {
32
31
  rejectUnknownFlags,
33
32
  resolveProjectDir
34
33
  } from "./cli-d8xjns66.js";
35
- import"./cli-cjftezxr.js";
36
- import"./cli-1ngqzg8s.js";
34
+ import"./cli-kh8v4vvw.js";
37
35
  import {
38
36
  EXIT_CODES
39
37
  } from "./cli-46ycxe6r.js";
40
- import"./cli-h3phdstf.js";
38
+ import"./cli-y28j019d.js";
41
39
  import"./cli-37x76zdn.js";
42
40
 
43
41
  // src/commands/ext.ts
@@ -58,7 +56,7 @@ var extListArgs = { dir: dirArg };
58
56
  var extAddArgs = {
59
57
  source: {
60
58
  type: "positional",
61
- description: "What to add: an npm package (name or name@version), a bundled feature (markdown-it-mark, …), a folder or plugin file path, a .zip or .css file, or an http(s) URL",
59
+ description: "What to add: an npm package (name or name@version), a bundled name (a feature like markdown-it-mark or a look like academic), a folder or plugin file path, a .zip or .css file, or an http(s) URL",
62
60
  required: true
63
61
  },
64
62
  dir: dirArg,
@@ -66,11 +64,6 @@ var extAddArgs = {
66
64
  type: "string",
67
65
  description: "Named module export to use as the plugin function (npm and path extensions only)",
68
66
  required: false
69
- },
70
- look: {
71
- type: "boolean",
72
- description: "Treat SOURCE as a built-in look id (clean-book, zine, technical-doc): copy it into extensions/ and add it",
73
- required: false
74
67
  }
75
68
  };
76
69
  var extRemoveArgs = { specifier: specifierArg, dir: dirArg };
@@ -140,10 +133,10 @@ function printAdded(entry, projectDir, warnings = []) {
140
133
  if (entry.kind === "npm") {
141
134
  console.log(`Installed ${entry.use}`);
142
135
  console.log(` project: ${projectDir}`);
143
- console.log(" vendored under: plugins/npm");
136
+ console.log(" vendored under: extensions/npm");
144
137
  console.log(" manifest: exact version pinned");
145
138
  } else if (entry.kind === "bundled") {
146
- console.log(`Enabled bundled feature ${entry.use}`);
139
+ console.log(`Enabled bundled ${entry.carries.styles && !entry.carries.markdown ? "look" : "feature"} ${entry.use}`);
147
140
  console.log(` project: ${projectDir}`);
148
141
  } else {
149
142
  console.log(`Added ${entry.use} (${carriesLabel(entry)})`);
@@ -189,7 +182,7 @@ var list = defineCommand({
189
182
  var add = defineCommand({
190
183
  meta: {
191
184
  name: "add",
192
- description: "Add an extension: an npm package, a bundled feature, a folder or plugin file, a .zip/.css file, or a URL"
185
+ description: "Add an extension: an npm package, a bundled name (a feature or a look), a folder or plugin file, a .zip/.css file, or a URL"
193
186
  },
194
187
  args: extAddArgs,
195
188
  async run({ args, rawArgs }) {
@@ -208,10 +201,7 @@ var add = defineCommand({
208
201
  if (typeof args.export === "string" && !exportName) {
209
202
  throw new UsageError("gutterpress ext add: --export requires a non-empty name");
210
203
  }
211
- if (args.look && !BUILT_IN_STYLE_SET_IDS.includes(source)) {
212
- throw new UsageError(`gutterpress ext add --look: unknown built-in look "${source}" (one of: ${BUILT_IN_STYLE_SET_IDS.join(", ")})`);
213
- }
214
- if (!args.look && !isUrl && !existing) {
204
+ if (!isUrl && !existing) {
215
205
  try {
216
206
  if (path.isAbsolute(source) || isPathSpecifier(source)) {
217
207
  throw new Error(`source not found: ${candidate}`);
@@ -225,11 +215,6 @@ var add = defineCommand({
225
215
  exitForUsage(error);
226
216
  }
227
217
  try {
228
- if (args.look) {
229
- const entry2 = await addBuiltInStyleSet(projectDir, source);
230
- printAdded(entry2, projectDir);
231
- return;
232
- }
233
218
  if (isUrl) {
234
219
  const { entry: entry2, warnings } = await importExtensionFromUrl(projectDir, source);
235
220
  printAdded(entry2, projectDir, warnings.map((w) => w.message));
@@ -385,7 +370,7 @@ var update = defineCommand({
385
370
  for (const u of updated)
386
371
  console.log(`Updated ${u.name} ${u.from} -> ${u.to}`);
387
372
  console.log(` project: ${projectDir}`);
388
- console.log(" vendored under: plugins/npm (previous version removed)");
373
+ console.log(" vendored under: extensions/npm (previous version removed)");
389
374
  console.log(" manifest: exact version re-pinned");
390
375
  } catch (error) {
391
376
  failPipeline("Could not update extensions", error);
@@ -3,14 +3,13 @@ import {
3
3
  restoreForCommand,
4
4
  restoreOfflineMessage,
5
5
  restorePinnedExtensions
6
- } from "./cli-zj5xaepv.js";
7
- import"./cli-ntwqmdnw.js";
8
- import"./cli-kx4hbnx2.js";
6
+ } from "./cli-sdmv4bba.js";
7
+ import"./cli-pwwfxdgb.js";
8
+ import"./cli-aqh6brew.js";
9
9
  import"./cli-d8xjns66.js";
10
- import"./cli-cjftezxr.js";
11
- import"./cli-1ngqzg8s.js";
10
+ import"./cli-kh8v4vvw.js";
12
11
  import"./cli-46ycxe6r.js";
13
- import"./cli-h3phdstf.js";
12
+ import"./cli-y28j019d.js";
14
13
  import"./cli-37x76zdn.js";
15
14
  export {
16
15
  restorePinnedExtensions,