gutterpress 0.11.21 → 0.11.22-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 +11 -0
  2. package/dist/api/index.d.ts +5 -1
  3. package/dist/api/index.js +68 -47
  4. package/dist/{build-0neyk5h6.js → build-84retk4k.js} +16 -10
  5. package/dist/{index-sth219v1.js → cli-2ppw6q9v.js} +26 -6
  6. package/dist/cli-3twpesca.js +103 -0
  7. package/dist/cli-5et23z83.js +2089 -0
  8. package/dist/{cli-j79451n6.js → cli-5qhjwne5.js} +5 -76
  9. package/dist/cli-80t93x2r.js +75 -0
  10. package/dist/{cli-j0drzb6f.js → cli-885pcze8.js} +885 -5481
  11. package/dist/{cli-b57adna7.js → cli-9pk65fqf.js} +9 -201
  12. package/dist/{cli-sqkccnm7.js → cli-d8xjns66.js} +1 -102
  13. package/dist/cli-h3phdstf.js +200 -0
  14. package/dist/{index-qf7y4d85.js → cli-habkc5ng.js} +12 -258
  15. package/dist/cli-hndkg7bn.js +196 -0
  16. package/dist/cli-pn3z0y9p.js +3073 -0
  17. package/dist/cli.js +15 -13
  18. package/dist/{doctor-fptq8tvn.js → doctor-fmzpg7ag.js} +7 -4
  19. package/dist/engine/shared/print-area.d.ts +77 -1
  20. package/dist/{engine-x07q927h.js → engine-5p8tn9b4.js} +4 -3
  21. package/dist/{engine-0b8bt05n.js → engine-9710cd7x.js} +3 -2
  22. package/dist/{ext-gp624t5c.js → ext-hsdnad5c.js} +21 -14
  23. package/dist/extension-restore-05pae3cp.js +16 -0
  24. package/dist/extension-restore-3r7phztr.js +20 -0
  25. package/dist/{gutterpress-viewer-w7njnkj7.js → gutterpress-viewer-w9jzx6sb.js} +56 -52
  26. package/dist/{index-t7r8g75c.js → index-2d8j0enc.js} +4 -2
  27. package/dist/{cli-sth219v1.js → index-2ppw6q9v.js} +26 -6
  28. package/dist/{index-mr7zs8mv.js → index-3wcr69ba.js} +5579 -10055
  29. package/dist/{cli-5qr3z0qa.js → index-93pqkvty.js} +63 -207
  30. package/dist/{index-mr72vt8n.js → index-apc8w9w8.js} +55 -267
  31. package/dist/index-ew7cyk7c.js +2208 -0
  32. package/dist/index-jsz0s3dy.js +213 -0
  33. package/dist/index-kx03e4m4.js +3244 -0
  34. package/dist/index-r7jcsk6h.js +200 -0
  35. package/dist/index.js +71 -50
  36. package/dist/lib/extension-manifest.d.ts +22 -1
  37. package/dist/lib/markdown/assemble.d.ts +3 -2
  38. package/dist/lib/markdown/plugins.d.ts +20 -0
  39. package/dist/lib/markdown/two-versions.d.ts +32 -0
  40. package/dist/lib/page-size.d.ts +3 -4
  41. package/dist/lib/pdf-inspect.d.ts +12 -0
  42. package/dist/lib/project-scaffold.d.ts +3 -3
  43. package/dist/lib/publish/plugin-provider.d.ts +16 -0
  44. package/dist/lib/publish/run-publish.d.ts +13 -5
  45. package/dist/lib/publish/types.d.ts +34 -2
  46. package/dist/lib/text-diff.d.ts +43 -0
  47. package/dist/lib/two-versions-markers.d.ts +26 -0
  48. package/dist/lib/version-changes.d.ts +87 -0
  49. package/dist/{manifest.schema-n292sb77.json → manifest.schema-nvawq0xv.json} +2 -2
  50. package/dist/{new-dre6aw05.js → new-fqtt022k.js} +23 -16
  51. package/dist/{pdf-inspect-zdmy7qca.js → pdf-inspect-wnw4za71.js} +1 -1
  52. package/dist/plugins-gfvsgnxb.js +24 -0
  53. package/dist/plugins-nfxr831f.js +26 -0
  54. package/dist/{preflight-1k1zkg1p.js → preflight-gr9mscjw.js} +18 -11
  55. package/dist/{preview-dtrksvxf.js → preview-52w9pdps.js} +19 -13
  56. package/dist/{publish-g1ytnrmr.js → publish-esmcyhpb.js} +40 -23
  57. package/dist/render.js +706 -0
  58. package/dist/schema/manifest.types.d.ts +8 -3
  59. package/dist/{source-provider-pzmz0br9.js → source-provider-2r74a7wp.js} +2 -1
  60. package/dist/{source-provider-qbthnmqw.js → source-provider-qbfknhyy.js} +2 -1
  61. package/dist/{validate-yrrq8639.js → validate-vt1d7h6k.js} +16 -10
  62. package/package.json +1 -1
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  launchChromium
3
3
  } from "./cli-eyyggect.js";
4
+ import {
5
+ getAssetPath
6
+ } from "./cli-hndkg7bn.js";
4
7
 
5
8
  // src/engine/compiler/build.ts
6
- import { readFile as readFile2 } from "node:fs/promises";
7
- import { resolve as resolve2 } from "node:path";
9
+ import { readFile } from "node:fs/promises";
10
+ import { resolve } from "node:path";
8
11
  import { pathToFileURL } from "node:url";
9
12
 
10
13
  // src/engine/shared/gcpm-extract.ts
@@ -1123,201 +1126,6 @@ async function inspectPdf(bytes) {
1123
1126
  return { pageCount: pages.length, boxes, linkTargets, namedDests, outline };
1124
1127
  }
1125
1128
 
1126
- // src/lib/embedded-assets.ts
1127
- import { existsSync } from "node:fs";
1128
- import { mkdtemp, mkdir, writeFile, readFile } from "node:fs/promises";
1129
- import { tmpdir } from "node:os";
1130
- import { dirname, join, resolve } from "node:path";
1131
- import { fileURLToPath } from "node:url";
1132
-
1133
- // src/assets/favicon.ico
1134
- var favicon_default = "./favicon-272ga6y0.ico";
1135
-
1136
- // src/assets/manifest.schema.json
1137
- var manifest_schema_default = "./manifest.schema-n292sb77.json";
1138
-
1139
- // src/assets/preview/scripts/preview-interface.js
1140
- var preview_interface_default = "./preview-interface-nnmrxyqm.js";
1141
-
1142
- // src/assets/preview/scripts/preview-bridge.js
1143
- var preview_bridge_default = "./preview-bridge-8wjcjec3.js";
1144
-
1145
- // src/assets/preview/scripts/preview-shell.js
1146
- var preview_shell_default = "./preview-shell-wk9k3gcd.js";
1147
-
1148
- // profiles/CGATS21_CRPC1.icc
1149
- var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
1150
-
1151
- // src/assets/engine/gutterpress-viewer.js
1152
- var gutterpress_viewer_default = "./gutterpress-viewer-w7njnkj7.js";
1153
-
1154
- // src/assets/engine/gutterpress-agent.js
1155
- var gutterpress_agent_default = "./gutterpress-agent-d29ry3ak.js";
1156
-
1157
- // src/assets/templates/book/manifest.yaml
1158
- var manifest_default = "./manifest-n1gh3qw5.yaml";
1159
-
1160
- // src/assets/templates/book/chapter-01.md
1161
- var chapter_01_default = "./chapter-01-rkpyvjna.md";
1162
-
1163
- // src/assets/templates/zine/manifest.yaml
1164
- var manifest_default2 = "./manifest-n1gh3qw5.yaml";
1165
-
1166
- // src/assets/templates/zine/chapter-01.md
1167
- var chapter_01_default2 = "./chapter-01-7jwqg1ct.md";
1168
-
1169
- // src/assets/templates/technical/manifest.yaml
1170
- var manifest_default3 = "./manifest-n1gh3qw5.yaml";
1171
-
1172
- // src/assets/templates/technical/chapter-01.md
1173
- var chapter_01_default3 = "./chapter-01-6fn9pvd0.md";
1174
-
1175
- // src/assets/extension-templates/plugin/package.json
1176
- var package_default = "./package-9rv69pxm.json";
1177
-
1178
- // src/assets/extension-templates/plugin/README.md
1179
- var README_default = "./README-vsnsc1b3.md";
1180
-
1181
- // src/assets/extension-templates/plugin/plugin.js.tpl
1182
- var plugin_js_default = "./plugin.js-cswq7wvd.tpl";
1183
-
1184
- // src/assets/extension-templates/plugin/styles/plugin.css
1185
- var plugin_default = "./plugin-spbcem4j.css";
1186
-
1187
- // src/assets/extension-templates/plugin/snippets/term-box.md
1188
- var term_box_default = "./term-box-4y0w7y32.md";
1189
-
1190
- // src/assets/extension-templates/plugin/test/fixture.md
1191
- var fixture_default = "./fixture-2qnyqgb5.md";
1192
-
1193
- // src/assets/extension-templates/plugin/test/expected.html
1194
- var expected_default = "./expected-ycmacem8.html";
1195
-
1196
- // src/assets/extension-templates/plugin/test/plugin.test.js.tpl
1197
- var plugin_test_js_default = "./plugin.test.js-xgxrd8hf.tpl";
1198
-
1199
- // src/assets/extension-templates/theme/package.json
1200
- var package_default2 = "./package-aenwjew3.json";
1201
-
1202
- // src/assets/extension-templates/theme/README.md
1203
- var README_default2 = "./README-3nj919rm.md";
1204
-
1205
- // src/assets/extension-templates/theme/components.yaml
1206
- var components_default = "./components-zzqdpt3m.yaml";
1207
-
1208
- // src/assets/extension-templates/theme/snippets/callout.md
1209
- var callout_default = "./callout-hv56m16h.md";
1210
-
1211
- // src/assets/extension-templates/theme/styles/tokens.css
1212
- var tokens_default = "./tokens-7984461t.css";
1213
-
1214
- // src/assets/extension-templates/theme/styles/base.css
1215
- var base_default = "./base-ypqh9n7f.css";
1216
-
1217
- // src/assets/extension-templates/theme/styles/components.css
1218
- var components_default2 = "./components-aam0fe2z.css";
1219
-
1220
- // src/assets/extension-templates/theme/styles/page-templates.css
1221
- var page_templates_default = "./page-templates-tx9ryt19.css";
1222
-
1223
- // src/assets/extension-templates/theme/styles/page-rules.css
1224
- var page_rules_default = "./page-rules-nsj3aw42.css";
1225
-
1226
- // src/assets/extension-templates/theme/styles/book.css
1227
- var book_default = "./book-ted3tzrp.css";
1228
-
1229
- // src/assets/themes/clean-book/theme.css
1230
- var theme_default = "./theme-j2bagrfx.css";
1231
-
1232
- // src/assets/themes/clean-book/package.json
1233
- var package_default3 = "./package-97gm31sg.json";
1234
-
1235
- // src/assets/themes/zine/theme.css
1236
- var theme_default2 = "./theme-h5recz6c.css";
1237
-
1238
- // src/assets/themes/zine/package.json
1239
- var package_default4 = "./package-gag6ykwn.json";
1240
-
1241
- // src/assets/themes/technical-doc/theme.css
1242
- var theme_default3 = "./theme-nn6d53zy.css";
1243
-
1244
- // src/assets/themes/technical-doc/package.json
1245
- var package_default5 = "./package-nrhkwf2m.json";
1246
-
1247
- // src/lib/embedded-assets.ts
1248
- var __libdir = dirname(fileURLToPath(import.meta.url));
1249
- var abs = (p) => resolve(__libdir, p);
1250
- var filePath = (v) => v;
1251
- var EMBEDDED_ASSETS = {
1252
- "favicon.ico": abs(favicon_default),
1253
- "manifest.schema.json": abs(filePath(manifest_schema_default)),
1254
- "preview/scripts/preview-interface.js": abs(filePath(preview_interface_default)),
1255
- "preview/scripts/preview-bridge.js": abs(filePath(preview_bridge_default)),
1256
- "preview/scripts/preview-shell.js": abs(filePath(preview_shell_default)),
1257
- "profiles/CGATS21_CRPC1.icc": abs(filePath(CGATS21_CRPC1_default)),
1258
- "engine/gutterpress-viewer.js": abs(filePath(gutterpress_viewer_default)),
1259
- "engine/gutterpress-agent.js": abs(filePath(gutterpress_agent_default)),
1260
- "templates/book/manifest.yaml": abs(filePath(manifest_default)),
1261
- "templates/book/chapter-01.md": abs(filePath(chapter_01_default)),
1262
- "templates/zine/manifest.yaml": abs(filePath(manifest_default2)),
1263
- "templates/zine/chapter-01.md": abs(filePath(chapter_01_default2)),
1264
- "templates/technical/manifest.yaml": abs(filePath(manifest_default3)),
1265
- "templates/technical/chapter-01.md": abs(filePath(chapter_01_default3)),
1266
- "extension-templates/plugin/package.json": abs(filePath(package_default)),
1267
- "extension-templates/plugin/README.md": abs(filePath(README_default)),
1268
- "extension-templates/plugin/plugin.js.tpl": abs(filePath(plugin_js_default)),
1269
- "extension-templates/plugin/styles/plugin.css": abs(filePath(plugin_default)),
1270
- "extension-templates/plugin/snippets/term-box.md": abs(filePath(term_box_default)),
1271
- "extension-templates/plugin/test/fixture.md": abs(filePath(fixture_default)),
1272
- "extension-templates/plugin/test/expected.html": abs(filePath(expected_default)),
1273
- "extension-templates/plugin/test/plugin.test.js.tpl": abs(filePath(plugin_test_js_default)),
1274
- "extension-templates/theme/package.json": abs(filePath(package_default2)),
1275
- "extension-templates/theme/README.md": abs(filePath(README_default2)),
1276
- "extension-templates/theme/components.yaml": abs(filePath(components_default)),
1277
- "extension-templates/theme/snippets/callout.md": abs(filePath(callout_default)),
1278
- "extension-templates/theme/styles/tokens.css": abs(filePath(tokens_default)),
1279
- "extension-templates/theme/styles/base.css": abs(filePath(base_default)),
1280
- "extension-templates/theme/styles/components.css": abs(filePath(components_default2)),
1281
- "extension-templates/theme/styles/page-templates.css": abs(filePath(page_templates_default)),
1282
- "extension-templates/theme/styles/page-rules.css": abs(filePath(page_rules_default)),
1283
- "extension-templates/theme/styles/book.css": abs(filePath(book_default)),
1284
- "themes/clean-book/theme.css": abs(filePath(theme_default)),
1285
- "themes/clean-book/package.json": abs(filePath(package_default3)),
1286
- "themes/zine/theme.css": abs(filePath(theme_default2)),
1287
- "themes/zine/package.json": abs(filePath(package_default4)),
1288
- "themes/technical-doc/theme.css": abs(filePath(theme_default3)),
1289
- "themes/technical-doc/package.json": abs(filePath(package_default5))
1290
- };
1291
- var extractPromise = null;
1292
- async function extractAssets() {
1293
- const root = await mkdtemp(join(tmpdir(), "gutterpress-assets-"));
1294
- for (const [relPath, srcPath] of Object.entries(EMBEDDED_ASSETS)) {
1295
- const dest = join(root, relPath);
1296
- await mkdir(dirname(dest), { recursive: true });
1297
- const bytes = await readFile(srcPath);
1298
- await writeFile(dest, bytes);
1299
- }
1300
- return root;
1301
- }
1302
- var SENTINEL_ASSET = "engine/gutterpress-viewer.js";
1303
- async function getAssetsDir() {
1304
- if (extractPromise) {
1305
- try {
1306
- const root = await extractPromise;
1307
- if (existsSync(join(root, SENTINEL_ASSET))) {
1308
- return root;
1309
- }
1310
- } catch {}
1311
- extractPromise = null;
1312
- }
1313
- extractPromise = extractAssets();
1314
- return extractPromise;
1315
- }
1316
- async function getAssetPath(relPath) {
1317
- const root = await getAssetsDir();
1318
- return join(root, relPath);
1319
- }
1320
-
1321
1129
  // src/engine/compiler/tier2.ts
1322
1130
  var DEFAULT_SLUG_PT = 18;
1323
1131
  function classify(model) {
@@ -1643,8 +1451,8 @@ function pagePseudoContexts(model) {
1643
1451
  }
1644
1452
  async function build(opts) {
1645
1453
  const log = opts.onProgress ?? (() => {});
1646
- const AGENT = await readFile2(await getAssetPath("engine/gutterpress-agent.js"), "utf8");
1647
- const VIEWER = await readFile2(await getAssetPath("engine/gutterpress-viewer.js"), "utf8");
1454
+ const AGENT = await readFile(await getAssetPath("engine/gutterpress-agent.js"), "utf8");
1455
+ const VIEWER = await readFile(await getAssetPath("engine/gutterpress-viewer.js"), "utf8");
1648
1456
  const browser = opts.browser ?? await launchChromium();
1649
1457
  const ownsBrowser = !opts.browser;
1650
1458
  const page = await browser.newPage();
@@ -1653,7 +1461,7 @@ async function build(opts) {
1653
1461
  const diagnose = (code, message, severity = "warning") => diagnostics.push({ code, severity, message });
1654
1462
  let prints = 0;
1655
1463
  try {
1656
- const url = /^(https?|file):\/\//.test(opts.input) ? opts.input : pathToFileURL(resolve2(opts.input)).href;
1464
+ const url = /^(https?|file):\/\//.test(opts.input) ? opts.input : pathToFileURL(resolve(opts.input)).href;
1657
1465
  await page.navigate(url);
1658
1466
  await page.evaluate(AGENT);
1659
1467
  await page.waitForReady();
@@ -2695,4 +2503,4 @@ ${lines.length ? lines.join(`
2695
2503
  `);
2696
2504
  }
2697
2505
 
2698
- export { lastPageMode, getAssetsDir, getAssetPath, MARGIN_BOX_IGNORED_PROPERTIES, build };
2506
+ export { lastPageMode, extract, resolvePage, MARGIN_BOX_IGNORED_PROPERTIES, build };
@@ -1,107 +1,6 @@
1
1
  import {
2
2
  EXIT_CODES
3
3
  } from "./cli-46ycxe6r.js";
4
- // package.json
5
- var package_default = {
6
- name: "gutterpress",
7
- version: "0.11.21",
8
- description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
9
- author: "itlackey",
10
- license: "MPL-2.0",
11
- keywords: [
12
- "markdown",
13
- "pdf",
14
- "print",
15
- "ghostscript",
16
- "book",
17
- "publishing",
18
- "zine"
19
- ],
20
- repository: {
21
- type: "git",
22
- url: "https://github.com/dimm-city/gutterpress.git"
23
- },
24
- homepage: "https://github.com/dimm-city/gutterpress#readme",
25
- bugs: {
26
- url: "https://github.com/dimm-city/gutterpress/issues"
27
- },
28
- type: "module",
29
- main: "./dist/index.js",
30
- types: "./dist/index.d.ts",
31
- bin: {
32
- gutterpress: "./dist/cli.js"
33
- },
34
- exports: {
35
- ".": {
36
- types: "./dist/index.d.ts",
37
- default: "./dist/index.js"
38
- },
39
- "./api": {
40
- types: "./dist/api/index.d.ts",
41
- default: "./dist/api/index.js"
42
- },
43
- "./render": {
44
- types: "./dist/render.d.ts",
45
- default: "./dist/render.js"
46
- }
47
- },
48
- files: [
49
- "dist/",
50
- "README.md",
51
- "LICENSE"
52
- ],
53
- scripts: {
54
- "build:library": "bun scripts/build-engine-bundles.mjs && rimraf dist && bun build src/index.ts src/api/index.ts --target=node --packages=external --splitting --outdir=dist && bun build src/render.ts --target=node --packages=external --outdir=dist && node scripts/check-render-pure.mjs && tsc -p tsconfig.build.json",
55
- build: "bun run build:library && bun build src/cli.ts --target=node --packages=external --splitting --outdir=dist",
56
- prepublishOnly: "bun run build",
57
- test: "bun test",
58
- typecheck: "tsc --noEmit",
59
- "typecheck:engine-browser": "tsc --noEmit -p src/engine/browser.tsconfig.json",
60
- "parity:gate": "bun scripts/native-parity-gate.ts"
61
- },
62
- engines: {
63
- bun: ">=1.0.0",
64
- node: ">=22.0.0"
65
- },
66
- dependencies: {
67
- chokidar: "^5.0.0",
68
- citty: "^0.2.0",
69
- diff3: "0.0.3",
70
- fflate: "0.8.3",
71
- glob: "^13.0.0",
72
- htmlhint: "^1.9.2",
73
- ignore: "^5.3.2",
74
- "isomorphic-git": "^1.38.4",
75
- "markdown-it": "^14.3.2",
76
- "markdown-it-abbr": "^2.0.0",
77
- "markdown-it-attrs": "^4.3.0",
78
- "markdown-it-deflist": "^3.0.1",
79
- "markdown-it-footnote": "^4.0.0",
80
- "markdown-it-mark": "^4.0.0",
81
- "markdown-it-source-map": "^0.1.1",
82
- "markdown-it-sub": "^2.0.0",
83
- "markdown-it-sup": "^2.0.0",
84
- markdownlint: "^0.40.0",
85
- "pdf-lib": "^1.17.1",
86
- postcss: "^8.5.18",
87
- "resolve.exports": "2.0.3",
88
- semver: "7.8.0",
89
- tar: "7.5.22",
90
- unpdf: "^1.6.2",
91
- ws: "^8.21.0",
92
- yaml: "^2.8.2"
93
- },
94
- devDependencies: {
95
- "@types/bun": "1.3.14",
96
- "@types/markdown-it": "^14.1.2",
97
- "@types/node": "^22.0.0",
98
- "@types/semver": "^7.7.1",
99
- "@types/ws": "^8.5.13",
100
- playwright: "^1.60.0",
101
- rimraf: "^6.0.0",
102
- typescript: "^5"
103
- }
104
- };
105
4
 
106
5
  // src/lib/cli-args.ts
107
6
  import { resolve } from "node:path";
@@ -278,4 +177,4 @@ function resolveProjectDir(dir) {
278
177
  return resolve(typeof dir === "string" && dir ? dir : process.cwd());
279
178
  }
280
179
 
281
- export { package_default, DEBOUNCE, UsageError, rejectUnknownFlags, rejectExtraPositionals, parseFormat, parsePdfxFlavor, resolvePort, exitForUsage, resolveProjectDir };
180
+ export { DEBOUNCE, UsageError, rejectUnknownFlags, rejectExtraPositionals, parseFormat, parsePdfxFlavor, resolvePort, exitForUsage, resolveProjectDir };
@@ -0,0 +1,200 @@
1
+ // src/lib/plugin-vendor.ts
2
+ import { lstat, readFile, realpath } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { exports as resolveExports } from "resolve.exports";
5
+ var PLUGINS_DIR = "plugins";
6
+ var VENDORED_NPM_DIR = "npm";
7
+ var NPM_SEGMENT = /^[a-z0-9][a-z0-9._~-]*$/;
8
+ 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-]+)*)?$/;
9
+ var WINDOWS_RESERVED = /^(con|prn|aux|nul|clock\$|conin\$|conout\$|com[1-9¹²³]|lpt[1-9¹²³])(?:\..*)?$/i;
10
+ function isValidNpmPackageName(name) {
11
+ if (!name || name.length > 214 || name !== name.toLowerCase())
12
+ return false;
13
+ if (name.startsWith("@")) {
14
+ const parts = name.slice(1).split("/");
15
+ return parts.length === 2 && parts.every((part) => NPM_SEGMENT.test(part));
16
+ }
17
+ return !name.includes("/") && NPM_SEGMENT.test(name);
18
+ }
19
+ function parseNpmPluginSpec(input) {
20
+ const spec = input.trim();
21
+ if (!spec)
22
+ throw new Error("An npm package name is required.");
23
+ let name = spec;
24
+ let selector;
25
+ if (spec.startsWith("@")) {
26
+ const slash = spec.indexOf("/");
27
+ const versionAt = spec.lastIndexOf("@");
28
+ if (slash > 1 && versionAt > slash) {
29
+ name = spec.slice(0, versionAt);
30
+ selector = spec.slice(versionAt + 1);
31
+ }
32
+ } else {
33
+ const versionAt = spec.lastIndexOf("@");
34
+ if (versionAt > 0) {
35
+ name = spec.slice(0, versionAt);
36
+ selector = spec.slice(versionAt + 1);
37
+ }
38
+ }
39
+ if (!isValidNpmPackageName(name)) {
40
+ throw new Error(`"${name}" is not a valid npm package name. Use a name like ` + "markdown-it-highlightjs or @scope/markdown-it-plugin.");
41
+ }
42
+ if (selector !== undefined && !selector) {
43
+ throw new Error(`The package spec "${spec}" is missing a selector after @.`);
44
+ }
45
+ return selector === undefined ? { name } : { name, selector };
46
+ }
47
+ function isExactNpmVersion(version) {
48
+ return EXACT_VERSION.test(version);
49
+ }
50
+ function encodePathPart(value) {
51
+ return encodeURIComponent(value).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
52
+ }
53
+ function vendoredNpmPluginRoot(projectDir, name, version) {
54
+ return path.join(projectDir, PLUGINS_DIR, VENDORED_NPM_DIR, encodePathPart(name), encodePathPart(version));
55
+ }
56
+ function vendoredNpmPluginPackageDir(installRoot, name) {
57
+ return path.join(installRoot, "node_modules", ...name.split("/"));
58
+ }
59
+ function toPosixPath(value) {
60
+ return value.split(path.sep).join("/");
61
+ }
62
+ function assertWindowsSafeRelativePath(relative) {
63
+ if (!relative || relative.includes("\\") || relative.startsWith("/") || /^[a-zA-Z]:/.test(relative)) {
64
+ throw new Error(`Unsafe package path: ${relative || "(empty)"}`);
65
+ }
66
+ const normalized = relative.normalize("NFKC");
67
+ const parts = normalized.split("/");
68
+ if (parts.some((part) => !part || part === "." || part === "..")) {
69
+ throw new Error(`Unsafe package path: ${relative}`);
70
+ }
71
+ for (const part of parts) {
72
+ if (part.length > 255 || /[\u0000-\u001f<>:"|?*]/.test(part) || part.endsWith(".") || part.endsWith(" ") || WINDOWS_RESERVED.test(part)) {
73
+ throw new Error(`Package path is invalid on Windows: ${relative}`);
74
+ }
75
+ }
76
+ }
77
+ function windowsPathKey(relative) {
78
+ return relative.normalize("NFKC").toLowerCase();
79
+ }
80
+ function isContained(root, candidate) {
81
+ const relative = path.relative(root, candidate);
82
+ return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
83
+ }
84
+ function object(value) {
85
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
86
+ }
87
+ async function readPackageJson(packageDir) {
88
+ const packageJsonPath = path.join(packageDir, "package.json");
89
+ const info = await lstat(packageJsonPath);
90
+ if (!info.isFile() || info.isSymbolicLink()) {
91
+ throw new Error(`Package metadata is not a regular file: ${packageJsonPath}`);
92
+ }
93
+ const parsed = object(JSON.parse(await readFile(packageJsonPath, "utf8")));
94
+ if (!parsed)
95
+ throw new Error(`Package metadata is not an object: ${packageJsonPath}`);
96
+ return parsed;
97
+ }
98
+ function packageResolutionTargets(manifest, subpath, condition) {
99
+ if (manifest.exports !== undefined) {
100
+ try {
101
+ const targets2 = resolveExports(manifest, subpath ? `./${subpath}` : ".", { require: condition === "require" }) ?? [];
102
+ return targets2.map((target) => ({ target, exact: true }));
103
+ } catch {
104
+ return [];
105
+ }
106
+ }
107
+ if (subpath)
108
+ return [{ target: subpath, exact: false }];
109
+ const targets = [
110
+ ...condition === "import" && typeof manifest.module === "string" ? [manifest.module] : [],
111
+ ...typeof manifest.main === "string" ? [manifest.main] : [],
112
+ "index.mjs",
113
+ "index.js",
114
+ "index.cjs"
115
+ ];
116
+ return [...new Set(targets)].map((target) => ({ target, exact: false }));
117
+ }
118
+ function safePackageTarget(target) {
119
+ if (!target || target.includes("\\") || target.includes("*") || target.includes("?") || target.includes("#")) {
120
+ return null;
121
+ }
122
+ const relative = target.startsWith("./") ? target.slice(2) : target;
123
+ if (!relative || path.isAbsolute(relative))
124
+ return null;
125
+ assertWindowsSafeRelativePath(relative);
126
+ if (relative.normalize("NFKC").split("/").some((part) => part.toLowerCase() === "node_modules")) {
127
+ return null;
128
+ }
129
+ return relative;
130
+ }
131
+ async function resolveEntryCandidate(packageDir, resolution) {
132
+ const relative = safePackageTarget(resolution.target);
133
+ if (!relative)
134
+ return null;
135
+ const base = path.resolve(packageDir, ...relative.split("/"));
136
+ if (!isContained(packageDir, base))
137
+ return null;
138
+ const candidates = resolution.exact ? [base] : [
139
+ base,
140
+ `${base}.mjs`,
141
+ `${base}.js`,
142
+ `${base}.cjs`,
143
+ `${base}.json`,
144
+ path.join(base, "index.mjs"),
145
+ path.join(base, "index.js"),
146
+ path.join(base, "index.cjs"),
147
+ path.join(base, "index.json")
148
+ ];
149
+ for (const candidate of candidates) {
150
+ try {
151
+ const info = await lstat(candidate);
152
+ if (!info.isFile() || info.isSymbolicLink())
153
+ continue;
154
+ const extension = path.extname(candidate);
155
+ if (extension && ![".js", ".mjs", ".cjs", ".json"].includes(extension))
156
+ continue;
157
+ const [realRoot, realCandidate] = await Promise.all([realpath(packageDir), realpath(candidate)]);
158
+ if (!isContained(realRoot, realCandidate))
159
+ continue;
160
+ return toPosixPath(path.relative(packageDir, realCandidate));
161
+ } catch {}
162
+ }
163
+ return null;
164
+ }
165
+ async function resolvePackageEntry(packageDir, packageJson) {
166
+ const manifest = packageJson ?? await readPackageJson(packageDir);
167
+ for (const condition of ["import", "require"]) {
168
+ for (const target of packageResolutionTargets(manifest, "", condition)) {
169
+ const resolved = await resolveEntryCandidate(packageDir, target);
170
+ if (resolved)
171
+ return resolved;
172
+ }
173
+ }
174
+ throw new Error("Package has no contained JavaScript entry point.");
175
+ }
176
+ async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expectedVersion) {
177
+ const requestedProjectRoot = path.resolve(projectDir);
178
+ const requestedInstallRoot = vendoredNpmPluginRoot(requestedProjectRoot, expectedName, expectedVersion);
179
+ let installInfo;
180
+ try {
181
+ installInfo = await lstat(requestedInstallRoot);
182
+ } catch (error) {
183
+ if (error.code === "ENOENT")
184
+ return null;
185
+ throw error;
186
+ }
187
+ if (!installInfo.isDirectory() || installInfo.isSymbolicLink()) {
188
+ throw new Error("Vendor install root is not a normal directory.");
189
+ }
190
+ const [realProjectRoot, installRoot] = await Promise.all([
191
+ realpath(requestedProjectRoot),
192
+ realpath(requestedInstallRoot)
193
+ ]);
194
+ if (!isContained(realProjectRoot, installRoot)) {
195
+ throw new Error("Vendor install root resolves outside the book folder.");
196
+ }
197
+ return installRoot;
198
+ }
199
+
200
+ export { PLUGINS_DIR, VENDORED_NPM_DIR, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginPackageDir, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, safePackageTarget, resolvePackageEntry, resolveVendoredPluginInstallRoot };