@p-buddy/parkdown 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
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.2", 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();
5
+ n.length === 0 && n.push("README.md");
6
+ const u = [
7
+ [r, !a],
8
+ [l, c]
9
+ ];
10
+ for (const [e] of u.filter(([o, s]) => s))
11
+ for (const o of n) {
12
+ const s = e(o, !i);
13
+ i && console.log(s);
14
+ }
@@ -0,0 +1,7 @@
1
+ export declare const depopulateMarkdownInclusions: (file: string, writeFile?: boolean) => string;
2
+
3
+ export declare const populateMarkdownInclusions: (file: string, writeFile?: boolean) => string;
4
+
5
+ export declare const remapImportSpecifiers: (file: string, writeFile?: boolean) => void;
6
+
7
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,396 @@
1
+ import { writeFileSync as q, readFileSync as te } from "node:fs";
2
+ import { basename as ne, dirname as _, join as C, resolve as U } from "node:path";
3
+ import { URLSearchParams as oe } from "node:url";
4
+ import { unified as se } from "unified";
5
+ import re from "remark-parse";
6
+ import { visit as ie } from "unist-util-visit";
7
+ import ce from "stable-hash";
8
+ import { dedent as k } from "ts-dedent";
9
+ import le from "extract-comments";
10
+ const g = (e, n) => e.position.start.offset - n.position.start.offset;
11
+ g.reverse = (e, n) => g(n, e);
12
+ const T = (e) => e.position !== void 0 && e.position.start.offset !== void 0 && e.position.end.offset !== void 0, ae = se().use(re), I = {
13
+ md: (e) => ae.parse(e)
14
+ }, y = (e, n) => {
15
+ const t = [];
16
+ return ie(e, (s, o, r) => {
17
+ if (s.type !== "root") {
18
+ if (n && s.type !== n) return;
19
+ if (T(s)) {
20
+ const i = ce(r), c = ((r == null ? void 0 : r.children.length) ?? 0) - 1;
21
+ t.push({ ...s, parentID: i, siblingIndex: o, siblingCount: c });
22
+ }
23
+ }
24
+ }), t;
25
+ }, pe = (e) => e.children.length === 0, G = (e, n, ...t) => {
26
+ if (t.length === 0) throw new Error("No nodes to replace content from");
27
+ t.sort(g);
28
+ const s = t.at(0), o = t.at(-1);
29
+ return e.slice(0, s.position.start.offset) + n + e.slice(o.position.end.offset);
30
+ }, me = (e, n, t) => {
31
+ const s = Math.min(n.position.end.offset, t.position.end.offset), o = Math.max(n.position.start.offset, t.position.start.offset);
32
+ return e.slice(s, o);
33
+ }, L = (...e) => e.join(" "), ue = (...e) => e.join(`
34
+ `), he = (e) => {
35
+ const n = e.split("?");
36
+ return n.length > 1 ? [n.slice(0, -1).join("?"), n.at(-1)] : [e, ""];
37
+ }, ge = (e) => he(e)[0];
38
+ class d {
39
+ constructor() {
40
+ this.intervals = [];
41
+ }
42
+ push(n, t) {
43
+ this.intervals.push([Math.min(n, t), Math.max(n, t)]);
44
+ }
45
+ combine(n) {
46
+ this.intervals.push(...n.intervals);
47
+ }
48
+ collapse() {
49
+ const { intervals: n } = this;
50
+ if (!n.length) return this.intervals = [];
51
+ n.sort((r, i) => r[0] - i[0]);
52
+ const t = [];
53
+ let [s, o] = n[0];
54
+ for (let r = 1; r < n.length; r++) {
55
+ const [i, c] = n[r];
56
+ i <= o ? o = Math.max(o, c) : (t.push([s, o]), s = i, o = c);
57
+ }
58
+ return t.push([s, o]), this.intervals = t;
59
+ }
60
+ subtract(n) {
61
+ const { intervals: t } = this, { intervals: s } = n;
62
+ if (!t.length || !s.length) return t;
63
+ let o = [...t];
64
+ for (const [r, i] of s) {
65
+ const c = [];
66
+ for (const [l, a] of o) {
67
+ if (i <= l || r >= a) {
68
+ c.push([l, a]);
69
+ continue;
70
+ }
71
+ r > l && c.push([l, r]), i < a && c.push([i, a]);
72
+ }
73
+ o = c;
74
+ }
75
+ return this.intervals = o;
76
+ }
77
+ }
78
+ const P = /,\s*(?![^()]*\))/, fe = [
79
+ [/'''/g, '"'],
80
+ [/''/g, "'"],
81
+ [/parkdown:\s+/g, ""],
82
+ [/p▼:\s+/g, ""]
83
+ ], de = (e, n = "-") => {
84
+ const t = fe.reduce((s, [o, r]) => s.replaceAll(o, r), e);
85
+ return n ? t.replaceAll(n, " ") : t;
86
+ }, we = ["string", "number", "boolean"], ve = (e) => we.includes(e), $e = /^([a-zA-Z0-9_-]+)(?:\(([^)]*)\))?$/, Ce = (e) => {
87
+ const n = e.match($e);
88
+ if (!n) throw new Error(`Invalid invocation: ${e}`);
89
+ const [, t, s = ""] = n;
90
+ if (!s.trim()) return { name: t, parameters: [] };
91
+ const o = Ee(s);
92
+ return { name: t, parameters: o };
93
+ }, ye = (e, n) => {
94
+ for (let t = n + 1; t < e.length; t++)
95
+ if (e[t] !== void 0) return !1;
96
+ return !0;
97
+ }, Ee = (e) => {
98
+ const n = [];
99
+ let t = "", s = !1;
100
+ for (let o = 0; o < e.length; o++) {
101
+ const r = e[o], i = r === "'";
102
+ if (i && e.at(o + 1) === "'") {
103
+ const c = e.at(o + 2) === "'";
104
+ s = !s, t += c ? "'''" : "''", o += c ? 2 : 1;
105
+ } else i ? (s = !s, t += r) : r === "," && !s ? (n.push(t.trim()), t = "") : t += r;
106
+ }
107
+ return n.push(t.trim()), n.map((o) => o === "" ? void 0 : o ? Se(o) : void 0).filter((o, r, i) => o !== void 0 || !ye(i, r));
108
+ }, Se = (e) => {
109
+ const n = e.length >= 2 && e[0] === "'" && e.at(-1) === "'", t = n && e.length >= 4 && e[1] === "'" && e.at(-2) === "'";
110
+ return !n || t ? e : e.slice(1, -1);
111
+ }, Ne = (e) => {
112
+ const n = /^(\w+)(?:\(([^)]*)\))?/, t = e.match(n);
113
+ if (!t) return { name: e };
114
+ const [, s, o] = t;
115
+ if (!o) return { name: s };
116
+ const r = /(\w+)(\?)?:\s*([^,]+)/g, i = [];
117
+ let c;
118
+ for (; (c = r.exec(o)) !== null; ) {
119
+ const [, l, a, p] = c, m = p.trim();
120
+ if (!ve(m)) throw new Error(`Unsupported type: ${m}`);
121
+ i.push({ name: l, optional: a === "?", type: m });
122
+ }
123
+ return { name: s, parameters: i };
124
+ }, H = (e) => {
125
+ const n = e.map(Ne).reduce(
126
+ (t, { name: s, parameters: o }) => t.set(s, o),
127
+ /* @__PURE__ */ new Map()
128
+ );
129
+ return (t) => {
130
+ const { name: s, parameters: o } = Ce(t);
131
+ if (!n.has(s))
132
+ throw new Error(`Unknown method: ${s}`);
133
+ const r = n.get(s);
134
+ if (r === void 0)
135
+ return { name: s };
136
+ if (o.length > r.length) {
137
+ const i = r.filter(({ optional: l }) => !l).length, c = i === r.length ? i.toString() : `${i} - ${r.length}`;
138
+ throw new Error(`Too many parameters: ${o.length} for method '${s}' (expected: ${c})`);
139
+ }
140
+ return r.reduce((i, { name: c, optional: l, type: a }, p) => {
141
+ const m = o[p];
142
+ if (m === void 0) {
143
+ if (l) return i;
144
+ throw new Error(`Missing required parameter: ${c} for method '${s}'`);
145
+ }
146
+ switch (a) {
147
+ case "string":
148
+ i[c] = m;
149
+ break;
150
+ case "number":
151
+ case "boolean":
152
+ i[c] = JSON.parse(m);
153
+ break;
154
+ }
155
+ if (typeof i[c] !== a)
156
+ throw new Error(`Invalid type: ${c} must be ${a}, got ${typeof i[c]} for method '${s}'`);
157
+ return i;
158
+ }, { name: s });
159
+ };
160
+ }, R = (e) => Object.entries(e).filter(([n]) => n !== "name" && !isNaN(Number(n))).map(([n, t]) => t), xe = [
161
+ /**
162
+ * Wraps the content in a markdown-formatted code block.
163
+ * @param lang The language of the code block (defaults to the file extension).
164
+ * @param meta Additional metadata to include in the top line of the code block (i.e. to the right of the `lang`).
165
+ * @example [](<url>?wrap=code)
166
+ * @example [](<url>?wrap=code())
167
+ * @example [](<url>?wrap=code(ts))
168
+ * @example [](<url>?wrap=code(,some-meta))
169
+ */
170
+ "code(lang?: string, meta?: string)",
171
+ /**
172
+ * Wraps the content in a markdown-formatted blockquote
173
+ * (using the `>` character if the content is a single line,
174
+ * or the `<blockquote>` tag if the content is a multi-line block).
175
+ * @example [](<url>?wrap=quote)
176
+ * @example [](<url>?wrap=quote())
177
+ * @example [](<url>?wrap=quote(,))
178
+ */
179
+ "quote()",
180
+ /**
181
+ * Wraps the content in a markdown-formatted dropdown (using the `<details>` and `<summary>` tags).
182
+ * @param summary The summary text of the dropdown.
183
+ * @param open Whether the dropdown should be open by default.
184
+ * @param space The space character to use between words in the summary (defaults to `-`).
185
+ * @example [](<url>?wrap=dropdown(hello-world))
186
+ * @example [](<url>?wrap=dropdown('hello,-world',true))
187
+ * @example [](<url>?wrap=dropdown(hello_world,,_))
188
+ */
189
+ "dropdown(summary: string, open?: boolean, space?: string)"
190
+ ], Me = "-", be = H(xe), W = (e, n, t) => {
191
+ const s = be(n), o = (t == null ? void 0 : t.inline) && !e.includes(`
192
+
193
+ `);
194
+ switch (s.name) {
195
+ case "code":
196
+ const r = s.lang ?? (t == null ? void 0 : t.extension) ?? "", i = s.meta ? ` ${s.meta}` : "";
197
+ return `\`\`\`${r}${i}
198
+ ${e}
199
+ \`\`\``;
200
+ case "quote":
201
+ return o ? `> ${e}` : `<blockquote>
202
+
203
+ ${e}
204
+
205
+ </blockquote>
206
+ `;
207
+ case "dropdown":
208
+ const c = `<details${s.open ? " open" : ""}>`, l = `<summary>${s.summary.split(s.space ?? Me).join(" ")}</summary>`;
209
+ return ["", c, l, "", e, "</details>", ""].join(`
210
+ `);
211
+ }
212
+ }, _e = [
213
+ "extract(id: string, 0?: string, 1?: string, 2?: string)",
214
+ "remove(id: string, 0?: string, 1?: string, 2?: string)",
215
+ "replace(id: string, with?: string, space?: string)"
216
+ ], ke = H(_e), D = (e) => le(e), B = (e, n) => D(e).filter(({ value: t }) => t.includes(n)).sort((t, s) => t.range[0] - s.range[0]), Te = (e, ...n) => {
217
+ if (n.length === 0) return e;
218
+ const t = ([i, c]) => e.slice(i, c), s = D(e), o = new d(), r = new d();
219
+ for (const i of n) {
220
+ const c = s.filter(({ value: l }) => l.includes(i)).sort((l, a) => l.range[0] - a.range[0]);
221
+ for (let l = 0; l < c.length - 1; l += 2) {
222
+ const a = c[l], p = c[l + 1];
223
+ o.push(a.range[1], p.range[0]);
224
+ const [m, ...f] = t([a.range[1], p.range[0]]), S = f[f.length - 1];
225
+ r.push(a.range[0], a.range[1] + (m.trim() ? 0 : 1)), r.push(p.range[0], p.range[1] + (S.trim() ? 0 : 1));
226
+ }
227
+ }
228
+ return o.collapse(), r.collapse(), k(
229
+ o.subtract(r).map(t).filter(Boolean).join("")
230
+ ).trim();
231
+ }, Ie = (e, ...n) => {
232
+ if (n.length === 0) return e;
233
+ const t = ([i, c]) => e.slice(i, c), s = D(e), o = new d();
234
+ for (const i of n) {
235
+ const c = s.filter(({ value: l }) => l.includes(i)).sort((l, a) => l.range[0] - a.range[0]);
236
+ for (let l = 0; l < c.length - 1; l += 2) {
237
+ const a = c[l], p = c[l + 1], m = t([p.range[1], p.range[1] + 1]).at(-1);
238
+ o.push(a.range[0], m === `
239
+ ` ? p.range[1] + 1 : p.range[1]);
240
+ }
241
+ }
242
+ o.collapse();
243
+ const r = new d();
244
+ return r.push(0, e.length), r.subtract(o), k(
245
+ r.collapse().map(t).filter(Boolean).join("")
246
+ ).trim();
247
+ }, De = (e, n, t, s) => {
248
+ if (!n) return e;
249
+ const o = B(e, n);
250
+ if (o.length < 2) return e;
251
+ let r = "", i = 0;
252
+ for (let l = 0; l < o.length - 1; l += 2) {
253
+ const a = o[l], p = o[l + 1];
254
+ r += e.slice(i, a.range[1]), r += de(t ?? a.value, s), i = p.range[0];
255
+ }
256
+ r += e.slice(i);
257
+ const c = new d();
258
+ return c.push(0, r.length), c.subtract(
259
+ B(r, n).reduce((l, { range: a }) => (l.push(...a), l), new d())
260
+ ), k(
261
+ c.collapse().map(([l, a]) => r.slice(l, a)).filter(Boolean).join("")
262
+ ).trim();
263
+ }, je = (e, n) => {
264
+ const t = ke(n);
265
+ switch (t.name) {
266
+ case "extract":
267
+ return Te(e, t.id, ...R(t));
268
+ case "remove":
269
+ return Ie(e, t.id, ...R(t));
270
+ case "replace":
271
+ return De(e, t.id, t.with, t.space);
272
+ }
273
+ }, Oe = ["http", "./", "../"], Ae = ({ url: e }) => Oe.some((n) => e.startsWith(n)), Le = (e) => T(e) && pe(e) && Ae(e), b = ({ url: e }, n) => `[](${n ? C(n, e) : e})`, h = {
274
+ _open: "<!--",
275
+ _close: "-->",
276
+ _flag: "p▼",
277
+ get begin() {
278
+ return L(h._open, h._flag, "BEGIN", h._close);
279
+ },
280
+ get end() {
281
+ return L(h._open, h._flag, "END", h._close);
282
+ }
283
+ }, F = (e) => (n) => T(n) && n.value === h[e], Pe = ({ position: e, url: n, siblingCount: t }, s) => ({ position: e, url: n, headingDepth: s, inline: t >= 1 }), Re = ({ position: { start: e }, url: n, siblingCount: t }, { position: { end: s } }, o) => ({ position: { start: e, end: s }, url: n, headingDepth: o, inline: t >= 1 }), We = (e, n, t) => e.inline ? `${b(e, t)} ${h.begin} ${n} ${h.end}` : ue(b(e, t), h.begin, n, h.end), Be = (e) => {
284
+ const n = y(e, "heading").reduce((t, { position: s, depth: o }) => t.set(s.start.line, o), /* @__PURE__ */ new Map());
285
+ return (t) => {
286
+ for (let s = t.position.start.line; s >= 1; s--) {
287
+ const o = n.get(s);
288
+ if (o) return o;
289
+ }
290
+ return 0;
291
+ };
292
+ }, E = {
293
+ openingCommentDoesNotFollowLink: ({ position: { start: e } }) => new Error(`Opening comment (@${e.line}:${e.column}) does not follow link`),
294
+ closingCommentNotMatchedToOpening: ({ position: { start: e } }) => new Error(`Closing comment (@${e.line}:${e.column}) does not match to opening comment`),
295
+ openingCommentNotClosed: ({ position: { start: e } }) => new Error(`Opening comment (@${e.line}:${e.column}) is not followed by a closing comment`)
296
+ }, Fe = (e, n) => {
297
+ const t = [], s = [
298
+ ...e.map((r) => ({ node: r, type: "open" })),
299
+ ...n.map((r) => ({ node: r, type: "close" }))
300
+ ].sort((r, i) => g(r.node, i.node)), o = [];
301
+ for (const r of s)
302
+ if (r.type === "open") o.push(r);
303
+ else {
304
+ const i = r.node;
305
+ if (o.length === 0)
306
+ throw E.closingCommentNotMatchedToOpening(i);
307
+ const c = o.pop().node;
308
+ if (o.length > 0) continue;
309
+ t.push({ open: c, close: i });
310
+ }
311
+ if (o.length > 0)
312
+ throw E.openingCommentNotClosed(o[0].node);
313
+ return t;
314
+ }, qe = (e, n, t) => {
315
+ const s = [...n].sort(g), o = [];
316
+ return [...t].sort((r, i) => g.reverse(r.open, i.open)).forEach((r) => {
317
+ for (; s.length > 0; ) {
318
+ const i = s.pop();
319
+ if (i.position.start.offset < r.open.position.start.offset) {
320
+ if (me(e, i, r.open).trim() !== "")
321
+ throw E.openingCommentDoesNotFollowLink(r.open);
322
+ return o.push([i, r]);
323
+ }
324
+ o.push(i);
325
+ }
326
+ throw E.openingCommentDoesNotFollowLink(r.open);
327
+ }), o.push(...s.reverse()), o.reverse();
328
+ }, Q = (e, n) => {
329
+ n ?? (n = I.md(e));
330
+ const t = Be(n), s = y(n, "link").filter(Le), o = y(n, "html").sort(g), r = o.filter(F("begin")), i = o.filter(F("end")), c = Fe(r, i);
331
+ return qe(e, s, c).map((a) => Array.isArray(a) ? Re(a[0], a[1].close, t(a[0])) : Pe(a, t(a)));
332
+ }, Ue = (e, { url: n }) => (t) => e(C(_(n), t)), z = (...e) => {
333
+ const n = e.reduce((t, s) => t + s, 0);
334
+ return Math.min(Math.max(n, 1), 6);
335
+ }, Ge = (e, n, t) => {
336
+ if (n === 0) return e;
337
+ t ?? (t = I.md(e));
338
+ const s = y(t, "heading"), o = e.split(`
339
+ `);
340
+ for (const r of s) {
341
+ 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;
342
+ o[c.line - 1] = m, r.depth = a;
343
+ }
344
+ return o.join(`
345
+ `);
346
+ }, X = (e) => Q(e).reverse().sort(g.reverse).reduce((n, t) => G(n, b(t), t), e), J = (e, n, t, s) => {
347
+ e = X(e), e = Ge(e, n);
348
+ const o = I.md(e);
349
+ return Q(e, o).sort(g).reverse().map((r) => {
350
+ var O, A;
351
+ const { url: i, headingDepth: c } = r, [l, ...a] = ne(i).split("?"), p = l.split(".").pop() ?? "", m = a.join("?"), f = _(i), S = C(f, l);
352
+ if (i.startsWith("./") || i.startsWith("../")) {
353
+ let u = t(S);
354
+ const w = new oe(m), N = (O = w.get("region")) == null ? void 0 : O.split(P);
355
+ u = (N == null ? void 0 : N.reduce((v, $) => je(v, $), u)) ?? u;
356
+ const Z = w.has("skip"), K = w.get("heading") ?? 0, Y = w.has("inline");
357
+ let { inline: x } = r;
358
+ if (Y && (x = !0), !Z)
359
+ if (p === "md") {
360
+ const v = Ue(t, r), $ = s ? C(s, f) : f, ee = z(c, Number(K));
361
+ u = J(
362
+ u,
363
+ /** p▼: ... */
364
+ ee,
365
+ v,
366
+ $
367
+ /** p▼: ... */
368
+ );
369
+ } else /^(js|ts)x?|svelte$/i.test(p) && (u = W(
370
+ u,
371
+ "code",
372
+ /** p▼: ... */
373
+ { extension: p, inline: x }
374
+ /** p▼: ... */
375
+ ));
376
+ const M = (A = w.get("wrap")) == null ? void 0 : A.split(P);
377
+ return u = (M == null ? void 0 : M.reduce((v, $) => W(v, $, { extension: p, inline: x }), u)) ?? u, { target: r, content: We(r, u, s) };
378
+ } else throw i.startsWith("http") ? new Error("External web links are not implemented yet") : new Error(`Unsupported link type: ${i}`);
379
+ }).reduce((r, { target: i, content: c }) => G(r, c, i), e);
380
+ }, V = (e) => te(e, "utf-8"), j = (e) => {
381
+ const n = U(e), t = _(n);
382
+ return { markdown: V(n), dir: t, path: n };
383
+ }, et = (e, n = !0) => {
384
+ const { dir: t, path: s, markdown: o } = j(e), i = J(o, 0, (c) => V(U(t, ge(c))));
385
+ return n && q(s, i), i;
386
+ }, tt = (e, n = !0) => {
387
+ const { path: t, markdown: s } = j(e), o = X(s);
388
+ return n && q(t, o), o;
389
+ }, nt = (e, n = !0) => {
390
+ j(e);
391
+ };
392
+ export {
393
+ tt as depopulateMarkdownInclusions,
394
+ et as populateMarkdownInclusions,
395
+ nt as remapImportSpecifiers
396
+ };
@@ -0,0 +1,15 @@
1
+ (function(u,w){typeof exports=="object"&&typeof module<"u"?w(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"],w):(u=typeof globalThis<"u"?globalThis:u||self,w(u.index={},u.node_fs,u.node_path,u.node_url,u.unified,u.remarkParse,u.unistUtilVisit,u.hash,u.tsDedent,u._extractComments))})(this,function(u,w,f,J,Z,K,Y,ee,x,te){"use strict";const g=(e,n)=>e.position.start.offset-n.position.start.offset;g.reverse=(e,n)=>g(n,e);const N=e=>e.position!==void 0&&e.position.start.offset!==void 0&&e.position.end.offset!==void 0,ne=Z.unified().use(K),k={md:e=>ne.parse(e)},E=(e,n)=>{const t=[];return Y.visit(e,(o,s,r)=>{if(o.type!=="root"){if(n&&o.type!==n)return;if(N(o)){const i=ee(r),c=((r==null?void 0:r.children.length)??0)-1;t.push({...o,parentID:i,siblingIndex:s,siblingCount:c})}}}),t},se=e=>e.children.length===0,P=(e,n,...t)=>{if(t.length===0)throw new Error("No nodes to replace content from");t.sort(g);const o=t.at(0),s=t.at(-1);return e.slice(0,o.position.start.offset)+n+e.slice(s.position.end.offset)},oe=(e,n,t)=>{const o=Math.min(n.position.end.offset,t.position.end.offset),s=Math.max(n.position.start.offset,t.position.start.offset);return e.slice(o,s)},A=(...e)=>e.join(" "),re=(...e)=>e.join(`
2
+ `),ie=e=>{const n=e.split("?");return n.length>1?[n.slice(0,-1).join("?"),n.at(-1)]:[e,""]},ce=e=>ie(e)[0];class v{constructor(){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[o,s]=n[0];for(let r=1;r<n.length;r++){const[i,c]=n[r];i<=s?s=Math.max(s,c):(t.push([o,s]),o=i,s=c)}return t.push([o,s]),this.intervals=t}subtract(n){const{intervals:t}=this,{intervals:o}=n;if(!t.length||!o.length)return t;let s=[...t];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 L=/,\s*(?![^()]*\))/,le=[[/'''/g,'"'],[/''/g,"'"],[/parkdown:\s+/g,""],[/p▼:\s+/g,""]],ae=(e,n="-")=>{const t=le.reduce((o,[s,r])=>o.replaceAll(s,r),e);return n?t.replaceAll(n," "):t},pe=["string","number","boolean"],ue=e=>pe.includes(e),me=/^([a-zA-Z0-9_-]+)(?:\(([^)]*)\))?$/,de=e=>{const n=e.match(me);if(!n)throw new Error(`Invalid invocation: ${e}`);const[,t,o=""]=n;if(!o.trim())return{name:t,parameters:[]};const s=fe(o);return{name:t,parameters:s}},he=(e,n)=>{for(let t=n+1;t<e.length;t++)if(e[t]!==void 0)return!1;return!0},fe=e=>{const n=[];let t="",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,t+=c?"'''":"''",s+=c?2:1}else i?(o=!o,t+=r):r===","&&!o?(n.push(t.trim()),t=""):t+=r}return n.push(t.trim()),n.map(s=>s===""?void 0:s?ge(s):void 0).filter((s,r,i)=>s!==void 0||!he(i,r))},ge=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)},we=e=>{const n=/^(\w+)(?:\(([^)]*)\))?/,t=e.match(n);if(!t)return{name:e};const[,o,s]=t;if(!s)return{name:o};const r=/(\w+)(\?)?:\s*([^,]+)/g,i=[];let c;for(;(c=r.exec(s))!==null;){const[,l,a,p]=c,m=p.trim();if(!ue(m))throw new Error(`Unsupported type: ${m}`);i.push({name:l,optional:a==="?",type:m})}return{name:o,parameters:i}},R=e=>{const n=e.map(we).reduce((t,{name:o,parameters:s})=>t.set(o,s),new Map);return t=>{const{name:o,parameters:s}=de(t);if(!n.has(o))throw new Error(`Unknown method: ${o}`);const r=n.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},p)=>{const m=s[p];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})}},_=e=>Object.entries(e).filter(([n])=>n!=="name"&&!isNaN(Number(n))).map(([n,t])=>t),ve=["code(lang?: string, meta?: string)","quote()","dropdown(summary: string, open?: boolean, space?: string)"],$e="-",Ce=R(ve),F=(e,n,t)=>{const o=Ce(n),s=(t==null?void 0:t.inline)&&!e.includes(`
3
+
4
+ `);switch(o.name){case"code":const r=o.lang??(t==null?void 0:t.extension)??"",i=o.meta?` ${o.meta}`:"";return`\`\`\`${r}${i}
5
+ ${e}
6
+ \`\`\``;case"quote":return s?`> ${e}`:`<blockquote>
7
+
8
+ ${e}
9
+
10
+ </blockquote>
11
+ `;case"dropdown":const c=`<details${o.open?" open":""}>`,l=`<summary>${o.summary.split(o.space??$e).join(" ")}</summary>`;return["",c,l,"",e,"</details>",""].join(`
12
+ `)}},ye=R(["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)"]),T=e=>te(e),W=(e,n)=>T(e).filter(({value:t})=>t.includes(n)).sort((t,o)=>t.range[0]-o.range[0]),Se=(e,...n)=>{if(n.length===0)return e;const t=([i,c])=>e.slice(i,c),o=T(e),s=new v,r=new v;for(const i of n){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],p=c[l+1];s.push(a.range[1],p.range[0]);const[m,...$]=t([a.range[1],p.range[0]]),b=$[$.length-1];r.push(a.range[0],a.range[1]+(m.trim()?0:1)),r.push(p.range[0],p.range[1]+(b.trim()?0:1))}}return s.collapse(),r.collapse(),x.dedent(s.subtract(r).map(t).filter(Boolean).join("")).trim()},Ee=(e,...n)=>{if(n.length===0)return e;const t=([i,c])=>e.slice(i,c),o=T(e),s=new v;for(const i of n){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],p=c[l+1],m=t([p.range[1],p.range[1]+1]).at(-1);s.push(a.range[0],m===`
13
+ `?p.range[1]+1:p.range[1])}}s.collapse();const r=new v;return r.push(0,e.length),r.subtract(s),x.dedent(r.collapse().map(t).filter(Boolean).join("")).trim()},Me=(e,n,t,o)=>{if(!n)return e;const s=W(e,n);if(s.length<2)return e;let r="",i=0;for(let l=0;l<s.length-1;l+=2){const a=s[l],p=s[l+1];r+=e.slice(i,a.range[1]),r+=ae(t??a.value,o),i=p.range[0]}r+=e.slice(i);const c=new v;return c.push(0,r.length),c.subtract(W(r,n).reduce((l,{range:a})=>(l.push(...a),l),new v)),x.dedent(c.collapse().map(([l,a])=>r.slice(l,a)).filter(Boolean).join("")).trim()},xe=(e,n)=>{const t=ye(n);switch(t.name){case"extract":return Se(e,t.id,..._(t));case"remove":return Ee(e,t.id,..._(t));case"replace":return Me(e,t.id,t.with,t.space)}},Ne=["http","./","../"],ke=({url:e})=>Ne.some(n=>e.startsWith(n)),Te=e=>N(e)&&se(e)&&ke(e),I=({url:e},n)=>`[](${n?f.join(n,e):e})`,d={_open:"<!--",_close:"-->",_flag:"p▼",get begin(){return A(d._open,d._flag,"BEGIN",d._close)},get end(){return A(d._open,d._flag,"END",d._close)}},B=e=>n=>N(n)&&n.value===d[e],Ie=({position:e,url:n,siblingCount:t},o)=>({position:e,url:n,headingDepth:o,inline:t>=1}),je=({position:{start:e},url:n,siblingCount:t},{position:{end:o}},s)=>({position:{start:e,end:o},url:n,headingDepth:s,inline:t>=1}),be=(e,n,t)=>e.inline?`${I(e,t)} ${d.begin} ${n} ${d.end}`:re(I(e,t),d.begin,n,d.end),qe=e=>{const n=E(e,"heading").reduce((t,{position:o,depth:s})=>t.set(o.start.line,s),new Map);return t=>{for(let o=t.position.start.line;o>=1;o--){const s=n.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`)},De=(e,n)=>{const t=[],o=[...e.map(r=>({node:r,type:"open"})),...n.map(r=>({node:r,type:"close"}))].sort((r,i)=>g(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;t.push({open:c,close:i})}if(s.length>0)throw M.openingCommentNotClosed(s[0].node);return t},Oe=(e,n,t)=>{const o=[...n].sort(g),s=[];return[...t].sort((r,i)=>g.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(oe(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()},U=(e,n)=>{n??(n=k.md(e));const t=qe(n),o=E(n,"link").filter(Te),s=E(n,"html").sort(g),r=s.filter(B("begin")),i=s.filter(B("end")),c=De(r,i);return Oe(e,o,c).map(a=>Array.isArray(a)?je(a[0],a[1].close,t(a[0])):Ie(a,t(a)))},Pe=(e,{url:n})=>t=>e(f.join(f.dirname(n),t)),G=(...e)=>{const n=e.reduce((t,o)=>t+o,0);return Math.min(Math.max(n,1),6)},Ae=(e,n,t)=>{if(n===0)return e;t??(t=k.md(e));const o=E(t,"heading"),s=e.split(`
14
+ `);for(const r of o){const{depth:i,position:{start:c,end:l}}=r,a=G(i,n),p=s[c.line-1].slice(i,l.column),m="#".repeat(a)+p;s[c.line-1]=m,r.depth=a}return s.join(`
15
+ `)},H=e=>U(e).reverse().sort(g.reverse).reduce((n,t)=>P(n,I(t),t),e),Q=(e,n,t,o)=>{e=H(e),e=Ae(e,n);const s=k.md(e);return U(e,s).sort(g).reverse().map(r=>{var X,V;const{url:i,headingDepth:c}=r,[l,...a]=f.basename(i).split("?"),p=l.split(".").pop()??"",m=a.join("?"),$=f.dirname(i),b=f.join($,l);if(i.startsWith("./")||i.startsWith("../")){let h=t(b);const C=new J.URLSearchParams(m),q=(X=C.get("region"))==null?void 0:X.split(L);h=(q==null?void 0:q.reduce((y,S)=>xe(y,S),h))??h;const Fe=C.has("skip"),We=C.get("heading")??0,Be=C.has("inline");let{inline:D}=r;if(Be&&(D=!0),!Fe)if(p==="md"){const y=Pe(t,r),S=o?f.join(o,$):$,Ue=G(c,Number(We));h=Q(h,Ue,y,S)}else/^(js|ts)x?|svelte$/i.test(p)&&(h=F(h,"code",{extension:p,inline:D}));const O=(V=C.get("wrap"))==null?void 0:V.split(L);return h=(O==null?void 0:O.reduce((y,S)=>F(y,S,{extension:p,inline:D}),h))??h,{target:r,content:be(r,h,o)}}else throw i.startsWith("http")?new Error("External web links are not implemented yet"):new Error(`Unsupported link type: ${i}`)}).reduce((r,{target:i,content:c})=>P(r,c,i),e)},z=e=>w.readFileSync(e,"utf-8"),j=e=>{const n=f.resolve(e),t=f.dirname(n);return{markdown:z(n),dir:t,path:n}},Le=(e,n=!0)=>{const{dir:t,path:o,markdown:s}=j(e),i=Q(s,0,c=>z(f.resolve(t,ce(c))));return n&&w.writeFileSync(o,i),i},Re=(e,n=!0)=>{const{path:t,markdown:o}=j(e),s=H(o);return n&&w.writeFileSync(t,s),s},_e=(e,n=!0)=>{j(e)};u.depopulateMarkdownInclusions=Re,u.populateMarkdownInclusions=Le,u.remapImportSpecifiers=_e,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.1",
5
+ "version": "0.0.2",
6
6
  "main": "dist/index.js",
7
7
  "bin": "dist/cli.js",
8
8
  "devDependencies": {