@p-buddy/parkdown 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,7 +44,7 @@ populateMarkdownInclusions(file, writeFile);
44
44
 
45
45
  [](./.assets/authoring.md)
46
46
  <!-- p↓ BEGIN -->
47
- <!-- p↓ length lines: 558 chars: 17214 -->
47
+ <!-- p↓ length lines: 574 chars: 17955 -->
48
48
  ## Authoring
49
49
 
50
50
  You author inclusions in your markdown files using a link with no text i.e. `[](<url>)`, where `<url>` points to some local or remote text resource (e.g.`./other.md`, `https://example.com/remote.md`).
@@ -55,6 +55,8 @@ These links can be rendered either [inline](#inline) or [block](#block), dependi
55
55
 
56
56
  Inline inclusions occur when your _text-less_ link has 1 or more siblings (meaning it's **not** the only node in a [paragraph](https://www.markdownguide.org/basic-syntax/#paragraphs-1)).
57
57
 
58
+ > **CAUTION:** [parkdown](https://www.npmjs.com/package/@p-buddy/parkdown) will not protect you from authoring inline inclusions that should actually be [block](#block) inclusions to be valid markdown.
59
+
58
60
  There are two equivalent ways to author inline inclusions, [single-line](#single-line) or [multi-line](#multi-line), and which you choose depends solely on how you want your raw markdown to look (it will **not** affect the rendered output).
59
61
 
60
62
  #### Single-line
@@ -254,7 +256,7 @@ Before...
254
256
 
255
257
  [](.assets/query.md?heading=-1)
256
258
  <!-- p↓ BEGIN -->
257
- <!-- p↓ length lines: 347 chars: 12711 -->
259
+ <!-- p↓ length lines: 361 chars: 13249 -->
258
260
  ### Query parameters
259
261
 
260
262
  You can pass query parameters to your inclusion links to control how their content is processed and included within your markdown.
@@ -294,6 +296,8 @@ Below is the currently supported API for the `region` query parameter, where eac
294
296
  - `[](<url>?region=remove(some-specifier))`
295
297
  - `[](<url>?region=replace(some-specifier,replacement-content))`
296
298
 
299
+ If no value(s) are included (e.g. `[](<url>?region)`), then simply all comments that contain `parkdown:` or `p↓:` will be stripped (as is done as a post-processing step for all other `region` functionality).
300
+
297
301
  [](.assets/api-note.md?wrap=quote)
298
302
  <!-- p↓ BEGIN -->
299
303
  <!-- p↓ length lines: 9 chars: 352 -->
@@ -355,7 +359,7 @@ Skip the default processing behavior for the given type of file.
355
359
 
356
360
  [](src/include.ts?wrap=dropdown(See-default-processing-behavior.)&region=extract(Default-Behavior),replace(...))
357
361
  <!-- p↓ BEGIN -->
358
- <!-- p↓ length lines: 17 chars: 267 -->
362
+ <!-- p↓ length lines: 21 chars: 525 -->
359
363
 
360
364
  <details>
361
365
  <summary>
@@ -364,11 +368,15 @@ See default processing behavior.
364
368
 
365
369
  ```ts
366
370
  if (extension === "md") {
367
- ...
368
- content = recursivelyPopulateInclusions(content, ...);
371
+
372
+ const getContent = extendGetRelativePathContent(getRelativePathContent, target);
373
+ const relative = basePath ? join(basePath, dir) : dir;
374
+ const depth = clampHeadingSum(headingDepth, Number(headingModfiier));
375
+
376
+ content = recursivelyPopulateInclusions(content, depth, getContent, path, relative);
369
377
  }
370
378
  else if (/^(js|ts)x?|svelte$/i.test(extension))
371
- content = wrap(content, "code", ...);
379
+ content = wrap(content, "code", { extension, inline });
372
380
  ```
373
381
 
374
382
  </details>
@@ -422,6 +430,14 @@ If we instead wanted the included heading to remain a `h1` / `#` heading, we'd m
422
430
  [](./to-be-included.md?heading=-1)
423
431
  ```
424
432
 
433
+ which would result in the following:
434
+
435
+ ```md
436
+ # Heading
437
+
438
+ # Included Heading
439
+ ```
440
+
425
441
  </details>
426
442
 
427
443
  #### `inline` (Advanced)
@@ -496,7 +512,7 @@ const definitions = [
496
512
 
497
513
  [](.assets/api.md?heading=-1)
498
514
  <!-- p↓ BEGIN -->
499
- <!-- p↓ length lines: 104 chars: 4981 -->
515
+ <!-- p↓ length lines: 104 chars: 4973 -->
500
516
  #### Query Parameters with Function-like APIs
501
517
 
502
518
  Some query parameters have more complex APIs, which are defined by a collection of typescript function singatures (limited to only `string`, `boolean`, and `number` arguments), like:
@@ -570,7 +586,7 @@ const urlCharacters = {
570
586
 
571
587
  [](src/utils.ts?region=extract(sanitize))
572
588
  <!-- p↓ BEGIN -->
573
- <!-- p↓ length lines: 29 chars: 779 -->
589
+ <!-- p↓ length lines: 29 chars: 771 -->
574
590
 
575
591
  ```ts
576
592
  type Replacement = [from: RegExp | string, to: string];
@@ -591,8 +607,8 @@ const replacements: Record<string, Replacement[]> = {
591
607
  const applyReplacement = (accumulator: string, [from, to]: Replacement) =>
592
608
  accumulator.replaceAll(from, to);
593
609
 
594
- export const sanitize = (replacement: string, space: string = DEFAULT_SPACE) => {
595
- const sanitized = replacements.static.reduce(applyReplacement, replacement)
610
+ export const sanitize = (content: string, space: string = DEFAULT_SPACE) => {
611
+ const sanitized = replacements.static.reduce(applyReplacement, content)
596
612
  return replacements.url
597
613
  .map(([key, to]) => ([space + key + space, to] satisfies Replacement))
598
614
  .reduce(applyReplacement, sanitized)
package/dist/cli.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command as t } from "@commander-js/extra-typings";
3
- import { populateMarkdownInclusions as r, depopulateMarkdownInclusions as l } from "@p-buddy/parkdown";
4
- const p = "0.0.5", f = new t().version(p).option("--nw, --no-write", "Do NOT write result to file (defaults to false)", !1).option("--ni, --no-inclusions", "Do NOT process file inclusions (defaults to false)", !1).option("-d, --depopulate", "Remove populated inclusions from the file", !1).option("-f, --file <flag>", "The file(s) to process", (e, o) => (o.push(e), o), new Array()).option("-r, --remap-imports", "Remap import specifiers in code blocks from one destination to another").parse(), { inclusions: a, depopulate: c, file: n, write: i } = f.opts();
3
+ import { populateMarkdownInclusions as l, depopulateMarkdownInclusions as r } from "@p-buddy/parkdown";
4
+ const f = "0.0.7", p = new t().version(f).option("--nw, --no-write", "Do NOT write result to file (defaults to false)", !1).option("--ni, --no-inclusions", "Do NOT process file inclusions (defaults to false)", !1).option("-d, --depopulate", "Remove populated inclusions from the file", !1).option("-f, --file <flag>", "The file(s) to process", (s, o) => (o.push(s), o), new Array()).parse(), { inclusions: c, depopulate: u, file: n, write: i } = p.opts();
5
5
  n.length === 0 && n.push("README.md");
6
- const u = [
7
- [r, !a],
8
- [l, c]
6
+ const a = [
7
+ [l, !c],
8
+ [r, u]
9
9
  ];
10
- for (const [e] of u.filter(([o, s]) => s))
10
+ for (const [s] of a.filter(([o, e]) => e))
11
11
  for (const o of n) {
12
- const s = e(o, !i);
13
- i && console.log(s);
12
+ const e = s(o, !i);
13
+ i && console.log(e);
14
14
  }
package/dist/index.js CHANGED
@@ -1,31 +1,29 @@
1
- var ae = Object.defineProperty;
2
- var pe = (e, t, n) => t in e ? ae(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
- var q = (e, t, n) => pe(e, typeof t != "symbol" ? t + "" : t, n);
4
- import { writeFileSync as z, readFileSync as me } from "node:fs";
5
- import { basename as ue, dirname as O, join as S, resolve as X } from "node:path";
6
- import { URLSearchParams as he } from "node:url";
7
- import { unified as ge } from "unified";
8
- import fe from "remark-parse";
9
- import { visit as de } from "unist-util-visit";
10
- import ve from "stable-hash";
11
- import { dedent as T } from "ts-dedent";
12
- import we from "extract-comments";
1
+ var me = Object.defineProperty;
2
+ var ue = (e, t, n) => t in e ? me(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
+ var L = (e, t, n) => ue(e, typeof t != "symbol" ? t + "" : t, n);
4
+ import { writeFileSync as V, readFileSync as he } from "node:fs";
5
+ import { basename as ge, dirname as M, join as S, resolve as J } from "node:path";
6
+ import { URLSearchParams as fe } from "node:url";
7
+ import { unified as de } from "unified";
8
+ import we from "remark-parse";
9
+ import { visit as ve } from "unist-util-visit";
10
+ import { dedent as j } from "ts-dedent";
13
11
  const g = (e, t) => e.position.start.offset - t.position.start.offset;
14
12
  g.reverse = (e, t) => g(t, e);
15
- const D = (e) => e.position !== void 0 && e.position.start.offset !== void 0 && e.position.end.offset !== void 0, $e = ge().use(fe), I = {
13
+ const D = (e) => e.position !== void 0 && e.position.start.offset !== void 0 && e.position.end.offset !== void 0, $e = de().use(we), I = {
16
14
  md: (e) => $e.parse(e)
17
- }, b = (e, t) => {
15
+ }, N = (e, t) => {
18
16
  const n = [];
19
- return de(e, (s, o, r) => {
17
+ return ve(e, (s, o, r) => {
20
18
  if (s.type !== "root") {
21
19
  if (t && s.type !== t) return;
22
20
  if (D(s)) {
23
- const i = ve(r), c = ((r == null ? void 0 : r.children.length) ?? 0) - 1;
24
- n.push({ ...s, parentID: i, siblingIndex: o, siblingCount: c });
21
+ const i = ((r == null ? void 0 : r.children.length) ?? 0) - 1;
22
+ n.push({ ...s, siblingIndex: o, siblingCount: i });
25
23
  }
26
24
  }
27
25
  }), n;
28
- }, Ce = (e) => e.children.length === 0, J = (e, t, ...n) => {
26
+ }, Ce = (e) => e.children.length === 0, Z = (e, t, ...n) => {
29
27
  if (n.length === 0) throw new Error("No nodes to replace content from");
30
28
  n.sort(g);
31
29
  const s = n.at(0), o = n.at(-1);
@@ -37,10 +35,10 @@ const D = (e) => e.position !== void 0 && e.position.start.offset !== void 0 &&
37
35
  `), Se = (e) => {
38
36
  const t = e.split("?");
39
37
  return t.length > 1 ? [t.slice(0, -1).join("?"), t.at(-1)] : [e, ""];
40
- }, be = (e) => Se(e)[0];
38
+ }, Ne = (e) => Se(e)[0];
41
39
  class d {
42
40
  constructor() {
43
- q(this, "intervals", []);
41
+ L(this, "intervals", []);
44
42
  }
45
43
  push(t, n) {
46
44
  this.intervals.push([Math.min(t, n), Math.max(t, n)]);
@@ -78,7 +76,7 @@ class d {
78
76
  return this.intervals = o;
79
77
  }
80
78
  }
81
- const L = /,\s*(?![^()]*\))/, W = {
79
+ const q = /,\s*(?![^()]*\))/, B = {
82
80
  reserved: {
83
81
  semi: ";",
84
82
  slash: "/",
@@ -104,7 +102,7 @@ const L = /,\s*(?![^()]*\))/, W = {
104
102
  unsquare: "]",
105
103
  tick: "`"
106
104
  }
107
- }, Ne = "-", B = {
105
+ }, xe = "-", F = {
108
106
  static: [
109
107
  ["'''", '"'],
110
108
  ["''", "'"],
@@ -112,24 +110,24 @@ const L = /,\s*(?![^()]*\))/, W = {
112
110
  [/p↓:\s+/g, ""]
113
111
  ],
114
112
  url: [
115
- ...Object.entries(W.unsafe),
116
- ...Object.entries(W.reserved)
113
+ ...Object.entries(B.unsafe),
114
+ ...Object.entries(B.reserved)
117
115
  ]
118
- }, F = (e, [t, n]) => e.replaceAll(t, n), V = (e, t = Ne) => {
119
- const n = B.static.reduce(F, e);
120
- return B.url.map(([s, o]) => [t + s + t, o]).reduce(F, n).replaceAll(t, " ");
121
- }, ke = ["string", "number", "boolean"], xe = (e) => ke.includes(e), Me = /^([a-zA-Z0-9_-]+)(?:\(([^)]*)\))?$/, _e = (e) => {
122
- const t = e.match(Me);
116
+ }, U = (e, [t, n]) => e.replaceAll(t, n), K = (e, t = xe) => {
117
+ const n = F.static.reduce(U, e);
118
+ return F.url.map(([s, o]) => [t + s + t, o]).reduce(U, n).replaceAll(t, " ");
119
+ }, ke = ["string", "number", "boolean"], be = (e) => ke.includes(e), _e = /^([a-zA-Z0-9_-]+)(?:\(([^)]*)\))?$/, Te = (e) => {
120
+ const t = e.match(_e);
123
121
  if (!t) throw new Error(`Invalid invocation: ${e}`);
124
122
  const [, n, s = ""] = t;
125
123
  if (!s.trim()) return { name: n, parameters: [] };
126
- const o = Te(s);
124
+ const o = Me(s);
127
125
  return { name: n, parameters: o };
128
126
  }, Oe = (e, t) => {
129
127
  for (let n = t + 1; n < e.length; n++)
130
128
  if (e[n] !== void 0) return !1;
131
129
  return !0;
132
- }, Te = (e) => {
130
+ }, Me = (e) => {
133
131
  const t = [];
134
132
  let n = "", s = !1;
135
133
  for (let o = 0; o < e.length; o++) {
@@ -139,11 +137,11 @@ const L = /,\s*(?![^()]*\))/, W = {
139
137
  s = !s, n += c ? "'''" : "''", o += c ? 2 : 1;
140
138
  } else i ? (s = !s, n += r) : r === "," && !s ? (t.push(n.trim()), n = "") : n += r;
141
139
  }
142
- return t.push(n.trim()), t.map((o) => o === "" ? void 0 : o ? De(o) : void 0).filter((o, r, i) => o !== void 0 || !Oe(i, r));
143
- }, De = (e) => {
140
+ return t.push(n.trim()), t.map((o) => o === "" ? void 0 : o ? je(o) : void 0).filter((o, r, i) => o !== void 0 || !Oe(i, r));
141
+ }, je = (e) => {
144
142
  const t = e.length >= 2 && e[0] === "'" && e.at(-1) === "'", n = t && e.length >= 4 && e[1] === "'" && e.at(-2) === "'";
145
143
  return !t || n ? e : e.slice(1, -1);
146
- }, Ie = (e) => {
144
+ }, De = (e) => {
147
145
  const t = /^(\w+)(?:\(([^)]*)\))?/, n = e.match(t);
148
146
  if (!n) return { name: e };
149
147
  const [, s, o] = n;
@@ -152,17 +150,17 @@ const L = /,\s*(?![^()]*\))/, W = {
152
150
  let c;
153
151
  for (; (c = r.exec(o)) !== null; ) {
154
152
  const [, l, a, p] = c, m = p.trim();
155
- if (!xe(m)) throw new Error(`Unsupported type: ${m}`);
153
+ if (!be(m)) throw new Error(`Unsupported type: ${m}`);
156
154
  i.push({ name: l, optional: a === "?", type: m });
157
155
  }
158
156
  return { name: s, parameters: i };
159
- }, Z = (e) => {
160
- const t = e.map(Ie).reduce(
157
+ }, Y = (e) => {
158
+ const t = e.map(De).reduce(
161
159
  (n, { name: s, parameters: o }) => n.set(s, o),
162
160
  /* @__PURE__ */ new Map()
163
161
  );
164
162
  return (n) => {
165
- const { name: s, parameters: o } = _e(n);
163
+ const { name: s, parameters: o } = Te(n);
166
164
  if (!t.has(s))
167
165
  throw new Error(`Unknown method: ${s}`);
168
166
  const r = t.get(s);
@@ -192,7 +190,7 @@ const L = /,\s*(?![^()]*\))/, W = {
192
190
  return i;
193
191
  }, { name: s });
194
192
  };
195
- }, U = (e) => Object.entries(e).filter(([t]) => t !== "name" && !isNaN(Number(t))).map(([t, n]) => n), je = [
193
+ }, G = (e) => Object.entries(e).filter(([t]) => t !== "name" && !isNaN(Number(t))).map(([t, n]) => n), Ie = [
196
194
  /**
197
195
  * Wraps the content in a markdown-formatted code block.
198
196
  * @param lang The language of the code block (defaults to the file extension).
@@ -222,9 +220,9 @@ const L = /,\s*(?![^()]*\))/, W = {
222
220
  * @example [](<url>?wrap=dropdown(hello_world,,_))
223
221
  */
224
222
  "dropdown(summary: string, open?: boolean, space?: string)"
225
- ], Re = Z(je), f = (e, t = 1) => `
223
+ ], Re = Y(Ie), f = (e, t = 1) => `
226
224
  `.repeat(t) + e + `
227
- `.repeat(t), _ = (e, t, n) => `<${t}${n ? ` ${n}` : ""}>${f(e)}</${t}>`, G = (e, t, n) => {
225
+ `.repeat(t), O = (e, t, n) => `<${t}${n ? ` ${n}` : ""}>${f(e)}</${t}>`, H = (e, t, n) => {
228
226
  const s = Re(t);
229
227
  switch (s.name) {
230
228
  case "code":
@@ -235,13 +233,21 @@ const L = /,\s*(?![^()]*\))/, W = {
235
233
  case "quote":
236
234
  return n != null && n.inline && !e.includes(`
237
235
 
238
- `) ? `> ${e}` : f(_(f(e), "blockquote"));
236
+ `) ? `> ${e}` : f(O(f(e), "blockquote"));
239
237
  case "dropdown":
240
- const c = _(V(s.summary), "summary");
241
- return f(_([c, e].join(`
238
+ const c = O(K(s.summary), "summary");
239
+ return f(O([c, e].join(`
242
240
  `), "details", s.open ? "open" : void 0));
243
241
  }
244
- }, Ae = [
242
+ }, R = (e) => {
243
+ const t = /(\/\/[^\n]*|\/\*[\s\S]*?\*\/|<!--[\s\S]*?-->)/gm, n = [];
244
+ let s;
245
+ for (; (s = t.exec(e)) !== null; ) {
246
+ const o = [s.index, s.index + s[0].length], r = Ae(s[0]).trim();
247
+ n.push({ range: o, value: r });
248
+ }
249
+ return n;
250
+ }, Ae = (e) => e.startsWith("//") ? e.slice(2) : e.startsWith("/*") ? e.slice(2, -2) : e.startsWith("<!--") ? e.slice(4, -3) : e, Pe = [
245
251
  /**
246
252
  * Extract regions from the retrieved content between comments that INCLUDE the specified ids.
247
253
  * @param id The id of the comment to extract.
@@ -272,24 +278,24 @@ const L = /,\s*(?![^()]*\))/, W = {
272
278
  * @example [](<url>?region=replace(specifier,new_content,_)
273
279
  */
274
280
  "replace(id: string, with?: string, space?: string)"
275
- ], Pe = Z(Ae), j = (e) => we(e), H = (e, t) => j(e).filter(({ value: n }) => n.includes(t)).sort((n, s) => n.range[0] - s.range[0]), qe = (e, ...t) => {
281
+ ], We = Y(Pe), x = (e, t) => R(e).filter(({ value: n }) => n.includes(t)).sort((n, s) => n.range[0] - s.range[0]), Le = (e, ...t) => {
276
282
  if (t.length === 0) return e;
277
- const n = ([i, c]) => e.slice(i, c), s = j(e), o = new d(), r = new d();
283
+ const n = ([i, c]) => e.slice(i, c), s = R(e), o = new d(), r = new d();
278
284
  for (const i of t) {
279
285
  const c = s.filter(({ value: l }) => l.includes(i)).sort((l, a) => l.range[0] - a.range[0]);
280
286
  for (let l = 0; l < c.length - 1; l += 2) {
281
287
  const a = c[l], p = c[l + 1];
282
288
  o.push(a.range[1], p.range[0]);
283
- const [m, ...y] = n([a.range[1], p.range[0]]), v = y[y.length - 1];
284
- r.push(a.range[0], a.range[1] + (m.trim() ? 0 : 1)), r.push(p.range[0], p.range[1] + (v.trim() ? 0 : 1));
289
+ const [m, ...y] = n([a.range[1], p.range[0]]), w = y[y.length - 1];
290
+ r.push(a.range[0], a.range[1] + (m.trim() ? 0 : 1)), r.push(p.range[0], p.range[1] + (w.trim() ? 0 : 1));
285
291
  }
286
292
  }
287
- return o.collapse(), r.collapse(), T(
293
+ return o.collapse(), r.collapse(), j(
288
294
  o.subtract(r).map(n).filter(Boolean).join("")
289
295
  ).trim();
290
- }, Le = (e, ...t) => {
296
+ }, qe = (e, ...t) => {
291
297
  if (t.length === 0) return e;
292
- const n = ([i, c]) => e.slice(i, c), s = j(e), o = new d();
298
+ const n = ([i, c]) => e.slice(i, c), s = R(e), o = new d();
293
299
  for (const i of t) {
294
300
  const c = s.filter(({ value: l }) => l.includes(i)).sort((l, a) => l.range[0] - a.range[0]);
295
301
  for (let l = 0; l < c.length - 1; l += 2) {
@@ -300,40 +306,48 @@ const L = /,\s*(?![^()]*\))/, W = {
300
306
  }
301
307
  o.collapse();
302
308
  const r = new d();
303
- return r.push(0, e.length), r.subtract(o), T(
309
+ return r.push(0, e.length), r.subtract(o), j(
304
310
  r.collapse().map(n).filter(Boolean).join("")
305
311
  ).trim();
306
- }, We = (e, t, n, s) => {
312
+ }, Be = (e, t, n, s) => {
307
313
  if (!t) return e;
308
- const o = H(e, t);
314
+ const o = x(e, t);
309
315
  if (o.length < 2) return e;
310
316
  let r = "", i = 0;
311
317
  for (let l = 0; l < o.length - 1; l += 2) {
312
318
  const a = o[l], p = o[l + 1];
313
- r += e.slice(i, a.range[1]), r += V(n ?? a.value, s), i = p.range[0];
319
+ r += e.slice(i, a.range[1]), r += K(n ?? a.value, s), i = p.range[0];
314
320
  }
315
321
  r += e.slice(i);
316
322
  const c = new d();
317
323
  return c.push(0, r.length), c.subtract(
318
- H(r, t).reduce((l, { range: a }) => (l.push(...a), l), new d())
319
- ), T(
324
+ x(r, t).reduce((l, { range: a }) => (l.push(...a), l), new d())
325
+ ), j(
320
326
  c.collapse().map(([l, a]) => r.slice(l, a)).filter(Boolean).join("")
321
327
  ).trim();
322
- }, Be = (e, t) => {
323
- const n = Pe(t);
328
+ }, Q = (e) => ({ isSpace: e === " ", isNewline: e === `
329
+ ` || e === void 0 }), z = (e) => [
330
+ ...x(e, "p↓:"),
331
+ ...x(e, "parkdown:")
332
+ ].sort((t, n) => t.range[0] - n.range[0]).reverse().reduce((t, { range: [n, s], value: o }) => {
333
+ const r = (a, p) => t.slice(0, a) + t.slice(p), i = Q(t[n - 1]), c = Q(t[s]), l = s === t.length;
334
+ return i.isNewline && c.isNewline ? r(n - (l ? 1 : 0), s + 1) : i.isNewline ? r(n, s + (c.isSpace ? 1 : 0)) : r(n - (i.isSpace ? 1 : 0), s);
335
+ }, e), Fe = (e, t) => {
336
+ if (!t) return z(e);
337
+ const n = We(t);
324
338
  switch (n.name) {
325
339
  case "extract":
326
- e = qe(e, n.id, ...U(n));
340
+ e = Le(e, n.id, ...G(n));
327
341
  break;
328
342
  case "remove":
329
- e = Le(e, n.id, ...U(n));
343
+ e = qe(e, n.id, ...G(n));
330
344
  break;
331
345
  case "replace":
332
- e = We(e, n.id, n.with, n.space);
346
+ e = Be(e, n.id, n.with, n.space);
333
347
  break;
334
348
  }
335
- return e;
336
- }, Fe = ["http", "./", "../"], Ue = ({ url: e }) => Fe.some((t) => e.startsWith(t)), Ge = (e) => D(e) && Ce(e) && Ue(e), K = ({ url: e }, t) => `[](${t ? S(t, e) : e})`, u = {
349
+ return z(e);
350
+ }, Ue = ["http", "./", "../"], Ge = ({ url: e }) => Ue.some((t) => e.startsWith(t)), He = (e) => D(e) && Ce(e) && Ge(e), ee = ({ url: e }, t) => `[](${t ? S(t, e) : e})`, u = {
337
351
  _open: "<!--",
338
352
  _close: "-->",
339
353
  _flag: "p↓",
@@ -348,14 +362,14 @@ const L = /,\s*(?![^()]*\))/, W = {
348
362
  `).length}`, n = `chars: ${e.length}`;
349
363
  return E(u._open, u._flag, "length", t, n, u._close);
350
364
  }
351
- }, Q = (e) => (t) => D(t) && t.value === u[e], He = ({ position: e, url: t, siblingCount: n }, s) => ({ position: e, url: t, headingDepth: s, inline: n >= 1 }), Qe = ({ position: { start: e }, url: t, siblingCount: n }, { position: { end: s } }, o) => ({ position: { start: e, end: s }, url: t, headingDepth: o, inline: n >= 1 }), ze = (e, t, n) => (e.inline ? E : Ee)(
352
- K(e, n),
365
+ }, X = (e) => (t) => D(t) && t.value === u[e], Qe = ({ position: e, url: t, siblingCount: n }, s) => ({ position: e, url: t, headingDepth: s, inline: n >= 1 }), ze = ({ position: { start: e }, url: t, siblingCount: n }, { position: { end: s } }, o) => ({ position: { start: e, end: s }, url: t, headingDepth: o, inline: n >= 1 }), Xe = (e, t, n) => (e.inline ? E : Ee)(
366
+ ee(e, n),
353
367
  u.begin,
354
368
  u.lengthOf(t),
355
369
  t,
356
370
  u.end
357
- ), Xe = (e) => {
358
- const t = b(e, "heading").reduce((n, { position: s, depth: o }) => n.set(s.start.line, o), /* @__PURE__ */ new Map());
371
+ ), Ve = (e) => {
372
+ const t = N(e, "heading").reduce((n, { position: s, depth: o }) => n.set(s.start.line, o), /* @__PURE__ */ new Map());
359
373
  return (n) => {
360
374
  for (let s = n.position.start.line; s >= 1; s--) {
361
375
  const o = t.get(s);
@@ -363,7 +377,7 @@ const L = /,\s*(?![^()]*\))/, W = {
363
377
  }
364
378
  return 0;
365
379
  };
366
- }, N = {
380
+ }, k = {
367
381
  openingCommentDoesNotFollowLink: ({ position: { start: e } }) => new Error(`Opening comment (@${e.line}:${e.column}) does not follow link`),
368
382
  closingCommentNotMatchedToOpening: ({ position: { start: e } }) => new Error(`Closing comment (@${e.line}:${e.column}) does not match to opening comment`),
369
383
  openingCommentNotClosed: ({ position: { start: e } }) => new Error(`Opening comment (@${e.line}:${e.column}) is not followed by a closing comment`)
@@ -377,96 +391,96 @@ const L = /,\s*(?![^()]*\))/, W = {
377
391
  else {
378
392
  const i = r.node;
379
393
  if (o.length === 0)
380
- throw N.closingCommentNotMatchedToOpening(i);
394
+ throw k.closingCommentNotMatchedToOpening(i);
381
395
  const c = o.pop().node;
382
396
  if (o.length > 0) continue;
383
397
  n.push({ open: c, close: i });
384
398
  }
385
399
  if (o.length > 0)
386
- throw N.openingCommentNotClosed(o[0].node);
400
+ throw k.openingCommentNotClosed(o[0].node);
387
401
  return n;
388
- }, Ve = (e, t, n) => {
402
+ }, Ze = (e, t, n) => {
389
403
  const s = [...t].sort(g), o = [];
390
404
  return [...n].sort((r, i) => g.reverse(r.open, i.open)).forEach((r) => {
391
405
  for (; s.length > 0; ) {
392
406
  const i = s.pop();
393
407
  if (i.position.start.offset < r.open.position.start.offset) {
394
408
  if (ye(e, i, r.open).trim() !== "")
395
- throw N.openingCommentDoesNotFollowLink(r.open);
409
+ throw k.openingCommentDoesNotFollowLink(r.open);
396
410
  return o.push([i, r]);
397
411
  }
398
412
  o.push(i);
399
413
  }
400
- throw N.openingCommentDoesNotFollowLink(r.open);
414
+ throw k.openingCommentDoesNotFollowLink(r.open);
401
415
  }), o.push(...s.reverse()), o.reverse();
402
- }, Y = (e, t) => {
416
+ }, te = (e, t) => {
403
417
  t ?? (t = I.md(e));
404
- const n = Xe(t), s = b(t, "link").filter(Ge), o = b(t, "html").sort(g), r = o.filter(Q("begin")), i = o.filter(Q("end")), c = Je(r, i);
405
- return Ve(e, s, c).map((a) => Array.isArray(a) ? Qe(a[0], a[1].close, n(a[0])) : He(a, n(a)));
406
- }, Ze = (e, { url: t }) => (n) => e(S(O(t), n)), ee = (...e) => {
418
+ const n = Ve(t), s = N(t, "link").filter(He), o = N(t, "html").sort(g), r = o.filter(X("begin")), i = o.filter(X("end")), c = Je(r, i);
419
+ return Ze(e, s, c).map((a) => Array.isArray(a) ? ze(a[0], a[1].close, n(a[0])) : Qe(a, n(a)));
420
+ }, Ke = (e, { url: t }) => (n) => e(S(M(t), n)), ne = (...e) => {
407
421
  const t = e.reduce((n, s) => n + s, 0);
408
422
  return Math.min(Math.max(t, 1), 6);
409
- }, Ke = (e, t, n) => {
423
+ }, Ye = (e, t, n) => {
410
424
  if (t === 0) return e;
411
425
  n ?? (n = I.md(e));
412
- const s = b(n, "heading"), o = e.split(`
426
+ const s = N(n, "heading"), o = e.split(`
413
427
  `);
414
428
  for (const r of s) {
415
- const { depth: i, position: { start: c, end: l } } = r, a = ee(i, t), p = o[c.line - 1].slice(i, l.column), m = "#".repeat(a) + p;
429
+ const { depth: i, position: { start: c, end: l } } = r, a = ne(i, t), p = o[c.line - 1].slice(i, l.column), m = "#".repeat(a) + p;
416
430
  o[c.line - 1] = m, r.depth = a;
417
431
  }
418
432
  return o.join(`
419
433
  `);
420
- }, te = (e) => Y(e).reverse().sort(g.reverse).reduce((t, n) => J(t, K(n), n), e), ne = (e, t, n, s, o) => {
434
+ }, se = (e) => te(e).reverse().sort(g.reverse).reduce((t, n) => Z(t, ee(n), n), e), oe = (e, t, n, s, o) => {
421
435
  try {
422
- e = te(e), e = Ke(e, t);
436
+ e = se(e), e = Ye(e, t);
423
437
  const r = I.md(e);
424
- return Y(e, r).sort(g).reverse().map((i) => {
425
- var A, P;
426
- const { url: c, headingDepth: l } = i, [a, ...p] = ue(c).split("?"), m = a.split(".").pop() ?? "", y = p.join("?"), v = O(c), R = S(v, a);
438
+ return te(e, r).sort(g).reverse().map((i) => {
439
+ var P, W;
440
+ const { url: c, headingDepth: l } = i, [a, ...p] = ge(c).split("?"), m = a.split(".").pop() ?? "", y = p.join("?"), w = M(c), A = S(w, a);
427
441
  if (c.startsWith("./") || c.startsWith("../")) {
428
- let h = n(R);
429
- const w = new he(y), k = (A = w.get("region")) == null ? void 0 : A.split(L);
430
- h = (k == null ? void 0 : k.reduce(($, C) => Be($, C), h)) ?? h;
431
- const re = w.has("skip"), ie = w.get("heading") ?? 0, ce = w.has("inline");
432
- let { inline: x } = i;
433
- if (ce && (x = !0), !re)
442
+ let h = n(A);
443
+ const v = new fe(y), b = (P = v.get("region")) == null ? void 0 : P.split(q);
444
+ h = (b == null ? void 0 : b.reduce(($, C) => Fe($, C), h)) ?? h;
445
+ const ce = v.has("skip"), le = v.get("heading") ?? 0, ae = v.has("inline");
446
+ let { inline: _ } = i;
447
+ if (ae && (_ = !0), !ce)
434
448
  if (m === "md") {
435
- const $ = Ze(n, i), C = o ? S(o, v) : v, le = ee(l, Number(ie));
436
- h = ne(
449
+ const $ = Ke(n, i), C = o ? S(o, w) : w, pe = ne(l, Number(le));
450
+ h = oe(
437
451
  h,
438
452
  /** p↓: ... */
439
- le,
453
+ pe,
440
454
  $,
441
- R,
455
+ A,
442
456
  C
443
457
  /** p↓: ... */
444
458
  );
445
- } else /^(js|ts)x?|svelte$/i.test(m) && (h = G(
459
+ } else /^(js|ts)x?|svelte$/i.test(m) && (h = H(
446
460
  h,
447
461
  "code",
448
462
  /** p↓: ... */
449
- { extension: m, inline: x }
463
+ { extension: m, inline: _ }
450
464
  /** p↓: ... */
451
465
  ));
452
- const M = (P = w.get("wrap")) == null ? void 0 : P.split(L);
453
- return h = (M == null ? void 0 : M.reduce(($, C) => G($, C, { extension: m, inline: x }), h)) ?? h, { target: i, content: ze(i, h, o) };
466
+ const T = (W = v.get("wrap")) == null ? void 0 : W.split(q);
467
+ return h = (T == null ? void 0 : T.reduce(($, C) => H($, C, { extension: m, inline: _ }), h)) ?? h, { target: i, content: Xe(i, h, o) };
454
468
  } else throw c.startsWith("http") ? new Error("External web links are not implemented yet") : new Error(`Unsupported link type: ${c}`);
455
- }).reduce((i, { target: c, content: l }) => J(i, l, c), e);
469
+ }).reduce((i, { target: c, content: l }) => Z(i, l, c), e);
456
470
  } catch (r) {
457
- throw new Error(`Error populating inclusions in file ${s}: ${r}`);
471
+ throw new Error(`Error populating inclusions in file ${s ?? "(unknown)"}: ${r}`);
458
472
  }
459
- }, oe = (e) => me(e, "utf-8"), se = (e) => {
460
- const t = X(e), n = O(t);
461
- return { markdown: oe(t), dir: n, path: t };
473
+ }, re = (e) => he(e, "utf-8"), ie = (e) => {
474
+ const t = J(e), n = M(t);
475
+ return { markdown: re(t), dir: n, path: t };
476
+ }, lt = (e, t = !0) => {
477
+ const { dir: n, path: s, markdown: o } = ie(e), i = oe(o, 0, (c) => re(J(n, Ne(c))), s);
478
+ return t && V(s, i), i;
462
479
  }, at = (e, t = !0) => {
463
- const { dir: n, path: s, markdown: o } = se(e), i = ne(o, 0, (c) => oe(X(n, be(c))), s);
464
- return t && z(s, i), i;
465
- }, pt = (e, t = !0) => {
466
- const { path: n, markdown: s } = se(e), o = te(s);
467
- return t && z(n, o), o;
480
+ const { path: n, markdown: s } = ie(e), o = se(s);
481
+ return t && V(n, o), o;
468
482
  };
469
483
  export {
470
- pt as depopulateMarkdownInclusions,
471
- at as populateMarkdownInclusions
484
+ at as depopulateMarkdownInclusions,
485
+ lt as populateMarkdownInclusions
472
486
  };
@@ -1,12 +1,13 @@
1
- (function(p,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("node:fs"),require("node:path"),require("node:url"),require("unified"),require("remark-parse"),require("unist-util-visit"),require("stable-hash"),require("ts-dedent"),require("extract-comments")):typeof define=="function"&&define.amd?define(["exports","node:fs","node:path","node:url","unified","remark-parse","unist-util-visit","stable-hash","ts-dedent","extract-comments"],h):(p=typeof globalThis<"u"?globalThis:p||self,h(p.index={},p.node_fs,p.node_path,p.node_url,p.unified,p.remarkParse,p.unistUtilVisit,p.hash,p.tsDedent,p._extractComments))})(this,function(p,h,d,oe,re,ie,ce,le,q,ae){"use strict";var Xe=Object.defineProperty;var Ve=(p,h,d)=>h in p?Xe(p,h,{enumerable:!0,configurable:!0,writable:!0,value:d}):p[h]=d;var se=(p,h,d)=>Ve(p,typeof h!="symbol"?h+"":h,d);const v=(e,t)=>e.position.start.offset-t.position.start.offset;v.reverse=(e,t)=>v(t,e);const T=e=>e.position!==void 0&&e.position.start.offset!==void 0&&e.position.end.offset!==void 0,pe=re.unified().use(ie),b={md:e=>pe.parse(e)},k=(e,t)=>{const n=[];return ce.visit(e,(o,s,r)=>{if(o.type!=="root"){if(t&&o.type!==t)return;if(T(o)){const i=le(r),c=((r==null?void 0:r.children.length)??0)-1;n.push({...o,parentID:i,siblingIndex:s,siblingCount:c})}}}),n},ue=e=>e.children.length===0,R=(e,t,...n)=>{if(n.length===0)throw new Error("No nodes to replace content from");n.sort(v);const o=n.at(0),s=n.at(-1);return e.slice(0,o.position.start.offset)+t+e.slice(s.position.end.offset)},me=(e,t,n)=>{const o=Math.min(t.position.end.offset,n.position.end.offset),s=Math.max(t.position.start.offset,n.position.start.offset);return e.slice(o,s)},x=(...e)=>e.join(" "),he=(...e)=>e.join(`
2
- `),de=e=>{const t=e.split("?");return t.length>1?[t.slice(0,-1).join("?"),t.at(-1)]:[e,""]},fe=e=>de(e)[0];class w{constructor(){se(this,"intervals",[])}push(t,n){this.intervals.push([Math.min(t,n),Math.max(t,n)])}combine(t){this.intervals.push(...t.intervals)}collapse(){const{intervals:t}=this;if(!t.length)return this.intervals=[];t.sort((r,i)=>r[0]-i[0]);const n=[];let[o,s]=t[0];for(let r=1;r<t.length;r++){const[i,c]=t[r];i<=s?s=Math.max(s,c):(n.push([o,s]),o=i,s=c)}return n.push([o,s]),this.intervals=n}subtract(t){const{intervals:n}=this,{intervals:o}=t;if(!n.length||!o.length)return n;let s=[...n];for(const[r,i]of o){const c=[];for(const[l,a]of s){if(i<=l||r>=a){c.push([l,a]);continue}r>l&&c.push([l,r]),i<a&&c.push([i,a])}s=c}return this.intervals=s}}const _=/,\s*(?![^()]*\))/,A={reserved:{semi:";",slash:"/",question:"?",colon:":",at:"@",equal:"=",and:"&"},unsafe:{quote:'"',angle:"<",unangle:">",hash:"#",percent:"%",curly:"{",uncurly:"}",pipe:"|",back:"\\",carrot:"^",tilde:"~",square:"[",unsquare:"]",tick:"`"}},ge="-",L={static:[["'''",'"'],["''","'"],[/parkdown:\s+/g,""],[/p↓:\s+/g,""]],url:[...Object.entries(A.unsafe),...Object.entries(A.reserved)]},W=(e,[t,n])=>e.replaceAll(t,n),B=(e,t=ge)=>{const n=L.static.reduce(W,e);return L.url.map(([o,s])=>[t+o+t,s]).reduce(W,n).replaceAll(t," ")},ve=["string","number","boolean"],we=e=>ve.includes(e),$e=/^([a-zA-Z0-9_-]+)(?:\(([^)]*)\))?$/,Ce=e=>{const t=e.match($e);if(!t)throw new Error(`Invalid invocation: ${e}`);const[,n,o=""]=t;if(!o.trim())return{name:n,parameters:[]};const s=Ee(o);return{name:n,parameters:s}},ye=(e,t)=>{for(let n=t+1;n<e.length;n++)if(e[n]!==void 0)return!1;return!0},Ee=e=>{const t=[];let n="",o=!1;for(let s=0;s<e.length;s++){const r=e[s],i=r==="'";if(i&&e.at(s+1)==="'"){const c=e.at(s+2)==="'";o=!o,n+=c?"'''":"''",s+=c?2:1}else i?(o=!o,n+=r):r===","&&!o?(t.push(n.trim()),n=""):n+=r}return t.push(n.trim()),t.map(s=>s===""?void 0:s?Se(s):void 0).filter((s,r,i)=>s!==void 0||!ye(i,r))},Se=e=>{const t=e.length>=2&&e[0]==="'"&&e.at(-1)==="'",n=t&&e.length>=4&&e[1]==="'"&&e.at(-2)==="'";return!t||n?e:e.slice(1,-1)},ke=e=>{const t=/^(\w+)(?:\(([^)]*)\))?/,n=e.match(t);if(!n)return{name:e};const[,o,s]=n;if(!s)return{name:o};const r=/(\w+)(\?)?:\s*([^,]+)/g,i=[];let c;for(;(c=r.exec(s))!==null;){const[,l,a,u]=c,m=u.trim();if(!we(m))throw new Error(`Unsupported type: ${m}`);i.push({name:l,optional:a==="?",type:m})}return{name:o,parameters:i}},F=e=>{const t=e.map(ke).reduce((n,{name:o,parameters:s})=>n.set(o,s),new Map);return n=>{const{name:o,parameters:s}=Ce(n);if(!t.has(o))throw new Error(`Unknown method: ${o}`);const r=t.get(o);if(r===void 0)return{name:o};if(s.length>r.length){const i=r.filter(({optional:l})=>!l).length,c=i===r.length?i.toString():`${i} - ${r.length}`;throw new Error(`Too many parameters: ${s.length} for method '${o}' (expected: ${c})`)}return r.reduce((i,{name:c,optional:l,type:a},u)=>{const m=s[u];if(m===void 0){if(l)return i;throw new Error(`Missing required parameter: ${c} for method '${o}'`)}switch(a){case"string":i[c]=m;break;case"number":case"boolean":i[c]=JSON.parse(m);break}if(typeof i[c]!==a)throw new Error(`Invalid type: ${c} must be ${a}, got ${typeof i[c]} for method '${o}'`);return i},{name:o})}},U=e=>Object.entries(e).filter(([t])=>t!=="name"&&!isNaN(Number(t))).map(([t,n])=>n),xe=F(["code(lang?: string, meta?: string)","quote()","dropdown(summary: string, open?: boolean, space?: string)"]),$=(e,t=1)=>`
3
- `.repeat(t)+e+`
4
- `.repeat(t),j=(e,t,n)=>`<${t}${n?` ${n}`:""}>${$(e)}</${t}>`,G=(e,t,n)=>{const o=xe(t);switch(o.name){case"code":if(!o.lang&&!o.meta&&(n==null?void 0:n.inline)&&!e.includes(`
5
- `))return`\`${e}\``;const r=o.lang??(n==null?void 0:n.extension)??"",i=o.meta?` ${o.meta}`:"";return $(`\`\`\`${r}${i}${$(e)}\`\`\``);case"quote":return n!=null&&n.inline&&!e.includes(`
1
+ (function(u,d){typeof exports=="object"&&typeof module<"u"?d(exports,require("node:fs"),require("node:path"),require("node:url"),require("unified"),require("remark-parse"),require("unist-util-visit"),require("ts-dedent")):typeof define=="function"&&define.amd?define(["exports","node:fs","node:path","node:url","unified","remark-parse","unist-util-visit","ts-dedent"],d):(u=typeof globalThis<"u"?globalThis:u||self,d(u.index={},u.node_fs,u.node_path,u.node_url,u.unified,u.remarkParse,u.unistUtilVisit,u.tsDedent))})(this,function(u,d,h,ie,ce,le,ae,j){"use strict";var Xe=Object.defineProperty;var Je=(u,d,h)=>d in u?Xe(u,d,{enumerable:!0,configurable:!0,writable:!0,value:h}):u[d]=h;var re=(u,d,h)=>Je(u,typeof d!="symbol"?d+"":d,h);const v=(e,n)=>e.position.start.offset-n.position.start.offset;v.reverse=(e,n)=>v(n,e);const M=e=>e.position!==void 0&&e.position.start.offset!==void 0&&e.position.end.offset!==void 0,pe=ce.unified().use(le),O={md:e=>pe.parse(e)},k=(e,n)=>{const t=[];return ae.visit(e,(s,o,r)=>{if(s.type!=="root"){if(n&&s.type!==n)return;if(M(s)){const i=((r==null?void 0:r.children.length)??0)-1;t.push({...s,siblingIndex:o,siblingCount:i})}}}),t},ue=e=>e.children.length===0,D=(e,n,...t)=>{if(t.length===0)throw new Error("No nodes to replace content from");t.sort(v);const s=t.at(0),o=t.at(-1);return e.slice(0,s.position.start.offset)+n+e.slice(o.position.end.offset)},me=(e,n,t)=>{const s=Math.min(n.position.end.offset,t.position.end.offset),o=Math.max(n.position.start.offset,t.position.start.offset);return e.slice(s,o)},N=(...e)=>e.join(" "),de=(...e)=>e.join(`
2
+ `),he=e=>{const n=e.split("?");return n.length>1?[n.slice(0,-1).join("?"),n.at(-1)]:[e,""]},fe=e=>he(e)[0];class w{constructor(){re(this,"intervals",[])}push(n,t){this.intervals.push([Math.min(n,t),Math.max(n,t)])}combine(n){this.intervals.push(...n.intervals)}collapse(){const{intervals:n}=this;if(!n.length)return this.intervals=[];n.sort((r,i)=>r[0]-i[0]);const t=[];let[s,o]=n[0];for(let r=1;r<n.length;r++){const[i,c]=n[r];i<=o?o=Math.max(o,c):(t.push([s,o]),s=i,o=c)}return t.push([s,o]),this.intervals=t}subtract(n){const{intervals:t}=this,{intervals:s}=n;if(!t.length||!s.length)return t;let o=[...t];for(const[r,i]of s){const c=[];for(const[l,a]of o){if(i<=l||r>=a){c.push([l,a]);continue}r>l&&c.push([l,r]),i<a&&c.push([i,a])}o=c}return this.intervals=o}}const W=/,\s*(?![^()]*\))/,_={reserved:{semi:";",slash:"/",question:"?",colon:":",at:"@",equal:"=",and:"&"},unsafe:{quote:'"',angle:"<",unangle:">",hash:"#",percent:"%",curly:"{",uncurly:"}",pipe:"|",back:"\\",carrot:"^",tilde:"~",square:"[",unsquare:"]",tick:"`"}},ge="-",L={static:[["'''",'"'],["''","'"],[/parkdown:\s+/g,""],[/p↓:\s+/g,""]],url:[...Object.entries(_.unsafe),...Object.entries(_.reserved)]},B=(e,[n,t])=>e.replaceAll(n,t),F=(e,n=ge)=>{const t=L.static.reduce(B,e);return L.url.map(([s,o])=>[n+s+n,o]).reduce(B,t).replaceAll(n," ")},ve=["string","number","boolean"],we=e=>ve.includes(e),$e=/^([a-zA-Z0-9_-]+)(?:\(([^)]*)\))?$/,Ce=e=>{const n=e.match($e);if(!n)throw new Error(`Invalid invocation: ${e}`);const[,t,s=""]=n;if(!s.trim())return{name:t,parameters:[]};const o=Se(s);return{name:t,parameters:o}},ye=(e,n)=>{for(let t=n+1;t<e.length;t++)if(e[t]!==void 0)return!1;return!0},Se=e=>{const n=[];let t="",s=!1;for(let o=0;o<e.length;o++){const r=e[o],i=r==="'";if(i&&e.at(o+1)==="'"){const c=e.at(o+2)==="'";s=!s,t+=c?"'''":"''",o+=c?2:1}else i?(s=!s,t+=r):r===","&&!s?(n.push(t.trim()),t=""):t+=r}return n.push(t.trim()),n.map(o=>o===""?void 0:o?Ee(o):void 0).filter((o,r,i)=>o!==void 0||!ye(i,r))},Ee=e=>{const n=e.length>=2&&e[0]==="'"&&e.at(-1)==="'",t=n&&e.length>=4&&e[1]==="'"&&e.at(-2)==="'";return!n||t?e:e.slice(1,-1)},ke=e=>{const n=/^(\w+)(?:\(([^)]*)\))?/,t=e.match(n);if(!t)return{name:e};const[,s,o]=t;if(!o)return{name:s};const r=/(\w+)(\?)?:\s*([^,]+)/g,i=[];let c;for(;(c=r.exec(o))!==null;){const[,l,a,p]=c,m=p.trim();if(!we(m))throw new Error(`Unsupported type: ${m}`);i.push({name:l,optional:a==="?",type:m})}return{name:s,parameters:i}},U=e=>{const n=e.map(ke).reduce((t,{name:s,parameters:o})=>t.set(s,o),new Map);return t=>{const{name:s,parameters:o}=Ce(t);if(!n.has(s))throw new Error(`Unknown method: ${s}`);const r=n.get(s);if(r===void 0)return{name:s};if(o.length>r.length){const i=r.filter(({optional:l})=>!l).length,c=i===r.length?i.toString():`${i} - ${r.length}`;throw new Error(`Too many parameters: ${o.length} for method '${s}' (expected: ${c})`)}return r.reduce((i,{name:c,optional:l,type:a},p)=>{const m=o[p];if(m===void 0){if(l)return i;throw new Error(`Missing required parameter: ${c} for method '${s}'`)}switch(a){case"string":i[c]=m;break;case"number":case"boolean":i[c]=JSON.parse(m);break}if(typeof i[c]!==a)throw new Error(`Invalid type: ${c} must be ${a}, got ${typeof i[c]} for method '${s}'`);return i},{name:s})}},G=e=>Object.entries(e).filter(([n])=>n!=="name"&&!isNaN(Number(n))).map(([n,t])=>t),Ne=U(["code(lang?: string, meta?: string)","quote()","dropdown(summary: string, open?: boolean, space?: string)"]),$=(e,n=1)=>`
3
+ `.repeat(n)+e+`
4
+ `.repeat(n),q=(e,n,t)=>`<${n}${t?` ${t}`:""}>${$(e)}</${n}>`,H=(e,n,t)=>{const s=Ne(n);switch(s.name){case"code":if(!s.lang&&!s.meta&&(t==null?void 0:t.inline)&&!e.includes(`
5
+ `))return`\`${e}\``;const r=s.lang??(t==null?void 0:t.extension)??"",i=s.meta?` ${s.meta}`:"";return $(`\`\`\`${r}${i}${$(e)}\`\`\``);case"quote":return t!=null&&t.inline&&!e.includes(`
6
6
 
7
- `)?`> ${e}`:$(j($(e),"blockquote"));case"dropdown":const c=j(B(o.summary),"summary");return $(j([c,e].join(`
8
- `),"details",o.open?"open":void 0))}},Me=F(["extract(id: string, 0?: string, 1?: string, 2?: string)","remove(id: string, 0?: string, 1?: string, 2?: string)","replace(id: string, with?: string, space?: string)"]),O=e=>ae(e),H=(e,t)=>O(e).filter(({value:n})=>n.includes(t)).sort((n,o)=>n.range[0]-o.range[0]),Ne=(e,...t)=>{if(t.length===0)return e;const n=([i,c])=>e.slice(i,c),o=O(e),s=new w,r=new w;for(const i of t){const c=o.filter(({value:l})=>l.includes(i)).sort((l,a)=>l.range[0]-a.range[0]);for(let l=0;l<c.length-1;l+=2){const a=c[l],u=c[l+1];s.push(a.range[1],u.range[0]);const[m,...N]=n([a.range[1],u.range[0]]),C=N[N.length-1];r.push(a.range[0],a.range[1]+(m.trim()?0:1)),r.push(u.range[0],u.range[1]+(C.trim()?0:1))}}return s.collapse(),r.collapse(),q.dedent(s.subtract(r).map(n).filter(Boolean).join("")).trim()},qe=(e,...t)=>{if(t.length===0)return e;const n=([i,c])=>e.slice(i,c),o=O(e),s=new w;for(const i of t){const c=o.filter(({value:l})=>l.includes(i)).sort((l,a)=>l.range[0]-a.range[0]);for(let l=0;l<c.length-1;l+=2){const a=c[l],u=c[l+1],m=n([u.range[1],u.range[1]+1]).at(-1);s.push(a.range[0],m===`
9
- `?u.range[1]+1:u.range[1])}}s.collapse();const r=new w;return r.push(0,e.length),r.subtract(s),q.dedent(r.collapse().map(n).filter(Boolean).join("")).trim()},Te=(e,t,n,o)=>{if(!t)return e;const s=H(e,t);if(s.length<2)return e;let r="",i=0;for(let l=0;l<s.length-1;l+=2){const a=s[l],u=s[l+1];r+=e.slice(i,a.range[1]),r+=B(n??a.value,o),i=u.range[0]}r+=e.slice(i);const c=new w;return c.push(0,r.length),c.subtract(H(r,t).reduce((l,{range:a})=>(l.push(...a),l),new w)),q.dedent(c.collapse().map(([l,a])=>r.slice(l,a)).filter(Boolean).join("")).trim()},be=(e,t)=>{const n=Me(t);switch(n.name){case"extract":e=Ne(e,n.id,...U(n));break;case"remove":e=qe(e,n.id,...U(n));break;case"replace":e=Te(e,n.id,n.with,n.space);break}return e},je=["http","./","../"],Oe=({url:e})=>je.some(t=>e.startsWith(t)),Ie=e=>T(e)&&ue(e)&&Oe(e),Q=({url:e},t)=>`[](${t?d.join(t,e):e})`,f={_open:"<!--",_close:"-->",_flag:"p↓",get begin(){return x(f._open,f._flag,"BEGIN",f._close)},get end(){return x(f._open,f._flag,"END",f._close)},lengthOf(e){const t=`lines: ${e.split(`
10
- `).length}`,n=`chars: ${e.length}`;return x(f._open,f._flag,"length",t,n,f._close)}},z=e=>t=>T(t)&&t.value===f[e],De=({position:e,url:t,siblingCount:n},o)=>({position:e,url:t,headingDepth:o,inline:n>=1}),Pe=({position:{start:e},url:t,siblingCount:n},{position:{end:o}},s)=>({position:{start:e,end:o},url:t,headingDepth:s,inline:n>=1}),Re=(e,t,n)=>(e.inline?x:he)(Q(e,n),f.begin,f.lengthOf(t),t,f.end),_e=e=>{const t=k(e,"heading").reduce((n,{position:o,depth:s})=>n.set(o.start.line,s),new Map);return n=>{for(let o=n.position.start.line;o>=1;o--){const s=t.get(o);if(s)return s}return 0}},M={openingCommentDoesNotFollowLink:({position:{start:e}})=>new Error(`Opening comment (@${e.line}:${e.column}) does not follow link`),closingCommentNotMatchedToOpening:({position:{start:e}})=>new Error(`Closing comment (@${e.line}:${e.column}) does not match to opening comment`),openingCommentNotClosed:({position:{start:e}})=>new Error(`Opening comment (@${e.line}:${e.column}) is not followed by a closing comment`)},Ae=(e,t)=>{const n=[],o=[...e.map(r=>({node:r,type:"open"})),...t.map(r=>({node:r,type:"close"}))].sort((r,i)=>v(r.node,i.node)),s=[];for(const r of o)if(r.type==="open")s.push(r);else{const i=r.node;if(s.length===0)throw M.closingCommentNotMatchedToOpening(i);const c=s.pop().node;if(s.length>0)continue;n.push({open:c,close:i})}if(s.length>0)throw M.openingCommentNotClosed(s[0].node);return n},Le=(e,t,n)=>{const o=[...t].sort(v),s=[];return[...n].sort((r,i)=>v.reverse(r.open,i.open)).forEach(r=>{for(;o.length>0;){const i=o.pop();if(i.position.start.offset<r.open.position.start.offset){if(me(e,i,r.open).trim()!=="")throw M.openingCommentDoesNotFollowLink(r.open);return s.push([i,r])}s.push(i)}throw M.openingCommentDoesNotFollowLink(r.open)}),s.push(...o.reverse()),s.reverse()},X=(e,t)=>{t??(t=b.md(e));const n=_e(t),o=k(t,"link").filter(Ie),s=k(t,"html").sort(v),r=s.filter(z("begin")),i=s.filter(z("end")),c=Ae(r,i);return Le(e,o,c).map(a=>Array.isArray(a)?Pe(a[0],a[1].close,n(a[0])):De(a,n(a)))},We=(e,{url:t})=>n=>e(d.join(d.dirname(t),n)),V=(...e)=>{const t=e.reduce((n,o)=>n+o,0);return Math.min(Math.max(t,1),6)},Be=(e,t,n)=>{if(t===0)return e;n??(n=b.md(e));const o=k(n,"heading"),s=e.split(`
11
- `);for(const r of o){const{depth:i,position:{start:c,end:l}}=r,a=V(i,t),u=s[c.line-1].slice(i,l.column),m="#".repeat(a)+u;s[c.line-1]=m,r.depth=a}return s.join(`
12
- `)},J=e=>X(e).reverse().sort(v.reverse).reduce((t,n)=>R(t,Q(n),n),e),Z=(e,t,n,o,s)=>{try{e=J(e),e=Be(e,t);const r=b.md(e);return X(e,r).sort(v).reverse().map(i=>{var te,ne;const{url:c,headingDepth:l}=i,[a,...u]=d.basename(c).split("?"),m=a.split(".").pop()??"",N=u.join("?"),C=d.dirname(c),ee=d.join(C,a);if(c.startsWith("./")||c.startsWith("../")){let g=n(ee);const y=new oe.URLSearchParams(N),I=(te=y.get("region"))==null?void 0:te.split(_);g=(I==null?void 0:I.reduce((E,S)=>be(E,S),g))??g;const Ge=y.has("skip"),He=y.get("heading")??0,Qe=y.has("inline");let{inline:D}=i;if(Qe&&(D=!0),!Ge)if(m==="md"){const E=We(n,i),S=s?d.join(s,C):C,ze=V(l,Number(He));g=Z(g,ze,E,ee,S)}else/^(js|ts)x?|svelte$/i.test(m)&&(g=G(g,"code",{extension:m,inline:D}));const P=(ne=y.get("wrap"))==null?void 0:ne.split(_);return g=(P==null?void 0:P.reduce((E,S)=>G(E,S,{extension:m,inline:D}),g))??g,{target:i,content:Re(i,g,s)}}else throw c.startsWith("http")?new Error("External web links are not implemented yet"):new Error(`Unsupported link type: ${c}`)}).reduce((i,{target:c,content:l})=>R(i,l,c),e)}catch(r){throw new Error(`Error populating inclusions in file ${o}: ${r}`)}},K=e=>h.readFileSync(e,"utf-8"),Y=e=>{const t=d.resolve(e),n=d.dirname(t);return{markdown:K(t),dir:n,path:t}},Fe=(e,t=!0)=>{const{dir:n,path:o,markdown:s}=Y(e),i=Z(s,0,c=>K(d.resolve(n,fe(c))),o);return t&&h.writeFileSync(o,i),i},Ue=(e,t=!0)=>{const{path:n,markdown:o}=Y(e),s=J(o);return t&&h.writeFileSync(n,s),s};p.depopulateMarkdownInclusions=Ue,p.populateMarkdownInclusions=Fe,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})});
7
+ `)?`> ${e}`:$(q($(e),"blockquote"));case"dropdown":const c=q(F(s.summary),"summary");return $(q([c,e].join(`
8
+ `),"details",s.open?"open":void 0))}},I=e=>{const n=/(\/\/[^\n]*|\/\*[\s\S]*?\*\/|<!--[\s\S]*?-->)/gm,t=[];let s;for(;(s=n.exec(e))!==null;){const o=[s.index,s.index+s[0].length],r=xe(s[0]).trim();t.push({range:o,value:r})}return t},xe=e=>e.startsWith("//")?e.slice(2):e.startsWith("/*")?e.slice(2,-2):e.startsWith("<!--")?e.slice(4,-3):e,Te=U(["extract(id: string, 0?: string, 1?: string, 2?: string)","remove(id: string, 0?: string, 1?: string, 2?: string)","replace(id: string, with?: string, space?: string)"]),x=(e,n)=>I(e).filter(({value:t})=>t.includes(n)).sort((t,s)=>t.range[0]-s.range[0]),be=(e,...n)=>{if(n.length===0)return e;const t=([i,c])=>e.slice(i,c),s=I(e),o=new w,r=new w;for(const i of n){const c=s.filter(({value:l})=>l.includes(i)).sort((l,a)=>l.range[0]-a.range[0]);for(let l=0;l<c.length-1;l+=2){const a=c[l],p=c[l+1];o.push(a.range[1],p.range[0]);const[m,...b]=t([a.range[1],p.range[0]]),C=b[b.length-1];r.push(a.range[0],a.range[1]+(m.trim()?0:1)),r.push(p.range[0],p.range[1]+(C.trim()?0:1))}}return o.collapse(),r.collapse(),j.dedent(o.subtract(r).map(t).filter(Boolean).join("")).trim()},je=(e,...n)=>{if(n.length===0)return e;const t=([i,c])=>e.slice(i,c),s=I(e),o=new w;for(const i of n){const c=s.filter(({value:l})=>l.includes(i)).sort((l,a)=>l.range[0]-a.range[0]);for(let l=0;l<c.length-1;l+=2){const a=c[l],p=c[l+1],m=t([p.range[1],p.range[1]+1]).at(-1);o.push(a.range[0],m===`
9
+ `?p.range[1]+1:p.range[1])}}o.collapse();const r=new w;return r.push(0,e.length),r.subtract(o),j.dedent(r.collapse().map(t).filter(Boolean).join("")).trim()},Me=(e,n,t,s)=>{if(!n)return e;const o=x(e,n);if(o.length<2)return e;let r="",i=0;for(let l=0;l<o.length-1;l+=2){const a=o[l],p=o[l+1];r+=e.slice(i,a.range[1]),r+=F(t??a.value,s),i=p.range[0]}r+=e.slice(i);const c=new w;return c.push(0,r.length),c.subtract(x(r,n).reduce((l,{range:a})=>(l.push(...a),l),new w)),j.dedent(c.collapse().map(([l,a])=>r.slice(l,a)).filter(Boolean).join("")).trim()},Q=e=>({isSpace:e===" ",isNewline:e===`
10
+ `||e===void 0}),z=e=>[...x(e,"p↓:"),...x(e,"parkdown:")].sort((n,t)=>n.range[0]-t.range[0]).reverse().reduce((n,{range:[t,s],value:o})=>{const r=(a,p)=>n.slice(0,a)+n.slice(p),i=Q(n[t-1]),c=Q(n[s]),l=s===n.length;return i.isNewline&&c.isNewline?r(t-(l?1:0),s+1):i.isNewline?r(t,s+(c.isSpace?1:0)):r(t-(i.isSpace?1:0),s)},e),Oe=(e,n)=>{if(!n)return z(e);const t=Te(n);switch(t.name){case"extract":e=be(e,t.id,...G(t));break;case"remove":e=je(e,t.id,...G(t));break;case"replace":e=Me(e,t.id,t.with,t.space);break}return z(e)},qe=["http","./","../"],Ie=({url:e})=>qe.some(n=>e.startsWith(n)),Pe=e=>M(e)&&ue(e)&&Ie(e),V=({url:e},n)=>`[](${n?h.join(n,e):e})`,f={_open:"<!--",_close:"-->",_flag:"p↓",get begin(){return N(f._open,f._flag,"BEGIN",f._close)},get end(){return N(f._open,f._flag,"END",f._close)},lengthOf(e){const n=`lines: ${e.split(`
11
+ `).length}`,t=`chars: ${e.length}`;return N(f._open,f._flag,"length",n,t,f._close)}},X=e=>n=>M(n)&&n.value===f[e],Re=({position:e,url:n,siblingCount:t},s)=>({position:e,url:n,headingDepth:s,inline:t>=1}),Ae=({position:{start:e},url:n,siblingCount:t},{position:{end:s}},o)=>({position:{start:e,end:s},url:n,headingDepth:o,inline:t>=1}),De=(e,n,t)=>(e.inline?N:de)(V(e,t),f.begin,f.lengthOf(n),n,f.end),We=e=>{const n=k(e,"heading").reduce((t,{position:s,depth:o})=>t.set(s.start.line,o),new Map);return t=>{for(let s=t.position.start.line;s>=1;s--){const o=n.get(s);if(o)return o}return 0}},T={openingCommentDoesNotFollowLink:({position:{start:e}})=>new Error(`Opening comment (@${e.line}:${e.column}) does not follow link`),closingCommentNotMatchedToOpening:({position:{start:e}})=>new Error(`Closing comment (@${e.line}:${e.column}) does not match to opening comment`),openingCommentNotClosed:({position:{start:e}})=>new Error(`Opening comment (@${e.line}:${e.column}) is not followed by a closing comment`)},_e=(e,n)=>{const t=[],s=[...e.map(r=>({node:r,type:"open"})),...n.map(r=>({node:r,type:"close"}))].sort((r,i)=>v(r.node,i.node)),o=[];for(const r of s)if(r.type==="open")o.push(r);else{const i=r.node;if(o.length===0)throw T.closingCommentNotMatchedToOpening(i);const c=o.pop().node;if(o.length>0)continue;t.push({open:c,close:i})}if(o.length>0)throw T.openingCommentNotClosed(o[0].node);return t},Le=(e,n,t)=>{const s=[...n].sort(v),o=[];return[...t].sort((r,i)=>v.reverse(r.open,i.open)).forEach(r=>{for(;s.length>0;){const i=s.pop();if(i.position.start.offset<r.open.position.start.offset){if(me(e,i,r.open).trim()!=="")throw T.openingCommentDoesNotFollowLink(r.open);return o.push([i,r])}o.push(i)}throw T.openingCommentDoesNotFollowLink(r.open)}),o.push(...s.reverse()),o.reverse()},J=(e,n)=>{n??(n=O.md(e));const t=We(n),s=k(n,"link").filter(Pe),o=k(n,"html").sort(v),r=o.filter(X("begin")),i=o.filter(X("end")),c=_e(r,i);return Le(e,s,c).map(a=>Array.isArray(a)?Ae(a[0],a[1].close,t(a[0])):Re(a,t(a)))},Be=(e,{url:n})=>t=>e(h.join(h.dirname(n),t)),Z=(...e)=>{const n=e.reduce((t,s)=>t+s,0);return Math.min(Math.max(n,1),6)},Fe=(e,n,t)=>{if(n===0)return e;t??(t=O.md(e));const s=k(t,"heading"),o=e.split(`
12
+ `);for(const r of s){const{depth:i,position:{start:c,end:l}}=r,a=Z(i,n),p=o[c.line-1].slice(i,l.column),m="#".repeat(a)+p;o[c.line-1]=m,r.depth=a}return o.join(`
13
+ `)},K=e=>J(e).reverse().sort(v.reverse).reduce((n,t)=>D(n,V(t),t),e),Y=(e,n,t,s,o)=>{try{e=K(e),e=Fe(e,n);const r=O.md(e);return J(e,r).sort(v).reverse().map(i=>{var se,oe;const{url:c,headingDepth:l}=i,[a,...p]=h.basename(c).split("?"),m=a.split(".").pop()??"",b=p.join("?"),C=h.dirname(c),te=h.join(C,a);if(c.startsWith("./")||c.startsWith("../")){let g=t(te);const y=new ie.URLSearchParams(b),P=(se=y.get("region"))==null?void 0:se.split(W);g=(P==null?void 0:P.reduce((S,E)=>Oe(S,E),g))??g;const He=y.has("skip"),Qe=y.get("heading")??0,ze=y.has("inline");let{inline:R}=i;if(ze&&(R=!0),!He)if(m==="md"){const S=Be(t,i),E=o?h.join(o,C):C,Ve=Z(l,Number(Qe));g=Y(g,Ve,S,te,E)}else/^(js|ts)x?|svelte$/i.test(m)&&(g=H(g,"code",{extension:m,inline:R}));const A=(oe=y.get("wrap"))==null?void 0:oe.split(W);return g=(A==null?void 0:A.reduce((S,E)=>H(S,E,{extension:m,inline:R}),g))??g,{target:i,content:De(i,g,o)}}else throw c.startsWith("http")?new Error("External web links are not implemented yet"):new Error(`Unsupported link type: ${c}`)}).reduce((i,{target:c,content:l})=>D(i,l,c),e)}catch(r){throw new Error(`Error populating inclusions in file ${s??"(unknown)"}: ${r}`)}},ee=e=>d.readFileSync(e,"utf-8"),ne=e=>{const n=h.resolve(e),t=h.dirname(n);return{markdown:ee(n),dir:t,path:n}},Ue=(e,n=!0)=>{const{dir:t,path:s,markdown:o}=ne(e),i=Y(o,0,c=>ee(h.resolve(t,fe(c))),s);return n&&d.writeFileSync(s,i),i},Ge=(e,n=!0)=>{const{path:t,markdown:s}=ne(e),o=K(s);return n&&d.writeFileSync(t,o),o};u.depopulateMarkdownInclusions=Ge,u.populateMarkdownInclusions=Ue,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@p-buddy/parkdown",
3
3
  "type": "module",
4
4
  "private": false,
5
- "version": "0.0.5",
5
+ "version": "0.0.7",
6
6
  "main": "./dist/index.js",
7
7
  "bin": "./dist/cli.js",
8
8
  "files": [
@@ -24,10 +24,7 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@commander-js/extra-typings": "^13.1.0",
27
- "@flex-development/import-regex": "^3.0.0",
28
- "extract-comments": "^1.1.0",
29
27
  "remark-parse": "^11.0.0",
30
- "stable-hash": "^0.0.4",
31
28
  "ts-dedent": "^2.2.0",
32
29
  "unified": "^11.0.5",
33
30
  "unist-util-visit": "^5.0.0"
@@ -37,7 +34,8 @@
37
34
  "build:cli": "vite build --config vite.cli.config.ts",
38
35
  "build": "pnpm run build:lib && pnpm run build:cli",
39
36
  "test": "vitest",
40
- "test:run": "vitest run"
37
+ "test:run": "vitest run",
38
+ "cli": "npx tsx src/cli.ts"
41
39
  },
42
40
  "typings": "./dist/index.d.ts",
43
41
  "exports": {