@vornrun/connector-substack 0.1.0

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/index.js ADDED
@@ -0,0 +1,2070 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/connector.ts
4
+ import { defineConnector } from "@vornrun/connector-sdk";
5
+
6
+ // src/feed.ts
7
+ var ENTITIES = {
8
+ amp: "&",
9
+ lt: "<",
10
+ gt: ">",
11
+ quot: '"',
12
+ apos: "'",
13
+ nbsp: "\xA0"
14
+ };
15
+ function decodeEntities(value) {
16
+ return value.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi, (whole, name) => {
17
+ if (name.startsWith("#")) {
18
+ const code = /^#x/i.test(name) ? parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);
19
+ return Number.isInteger(code) && code >= 0 && code <= 1114111 ? String.fromCodePoint(code) : whole;
20
+ }
21
+ return ENTITIES[name.toLowerCase()] ?? whole;
22
+ });
23
+ }
24
+ var CDATA = /<!\[CDATA\[([\s\S]*?)\]\]>/g;
25
+ function textOf(raw) {
26
+ let out = "";
27
+ let last = 0;
28
+ for (const match of raw.matchAll(CDATA)) {
29
+ out += decodeEntities(raw.slice(last, match.index)) + match[1];
30
+ last = match.index + match[0].length;
31
+ }
32
+ return (out + decodeEntities(raw.slice(last))).trim();
33
+ }
34
+ function tagText(item, masked, name) {
35
+ const open = new RegExp(`<${name}(?:\\s[^>]*)?>`).exec(masked);
36
+ if (!open) return "";
37
+ const start = open.index + open[0].length;
38
+ const end = masked.indexOf(`</${name}>`, start);
39
+ return end === -1 ? "" : textOf(item.slice(start, end));
40
+ }
41
+ function plainText(html) {
42
+ return decodeEntities(
43
+ html.replace(/<(br|hr)\s*\/?>/gi, "\n").replace(/<(p|h[1-6]|li|blockquote|pre|div|ul|ol)(\s[^>]*)?>/gi, "\n").replace(/<\/(p|h[1-6]|li|blockquote|pre|div)>/gi, "\n").replace(/<[^>]+>/g, "")
44
+ ).split("\n").map((line) => line.replace(/[ \t ]+/g, " ").trim()).filter((line) => line !== "").join("\n");
45
+ }
46
+ function parseFeed(xml) {
47
+ const posts = [];
48
+ for (const match of xml.matchAll(/<item(?:\s[^>]*)?>([\s\S]*?)<\/item>/g)) {
49
+ const item = match[1] ?? "";
50
+ const masked = item.replace(CDATA, (section) => " ".repeat(section.length));
51
+ const url = tagText(item, masked, "link");
52
+ const id = tagText(item, masked, "guid") || url;
53
+ if (id === "") continue;
54
+ const published = new Date(tagText(item, masked, "pubDate"));
55
+ const html = tagText(item, masked, "content:encoded");
56
+ posts.push({
57
+ id,
58
+ title: tagText(item, masked, "title"),
59
+ subtitle: tagText(item, masked, "description"),
60
+ url,
61
+ author: tagText(item, masked, "dc:creator"),
62
+ publishedAt: Number.isNaN(published.getTime()) ? "" : published.toISOString(),
63
+ html,
64
+ text: plainText(html)
65
+ });
66
+ }
67
+ return posts;
68
+ }
69
+
70
+ // ../../node_modules/marked/lib/marked.esm.js
71
+ function A() {
72
+ return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
73
+ }
74
+ var R = A();
75
+ function j(l3) {
76
+ R = l3;
77
+ }
78
+ var z = { exec: () => null };
79
+ function I(l3) {
80
+ let e = [];
81
+ return (t) => {
82
+ let n = Math.max(0, Math.min(3, t - 1)), s = e[n];
83
+ return s || (s = l3(n), e[n] = s), s;
84
+ };
85
+ }
86
+ function k(l3, e = "") {
87
+ let t = typeof l3 == "string" ? l3 : l3.source, n = { replace: (s, r) => {
88
+ let i = typeof r == "string" ? r : r.source;
89
+ return i = i.replace(m.caret, "$1"), t = t.replace(s, i), n;
90
+ }, getRegex: () => new RegExp(t, e) };
91
+ return n;
92
+ }
93
+ var Oe = ((l3 = "") => {
94
+ try {
95
+ return !!new RegExp("(?<=1)(?<!1)" + l3);
96
+ } catch {
97
+ return false;
98
+ }
99
+ })();
100
+ var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] +\S/, listReplaceTask: /^\[[ xX]\] +/, listTaskCheckbox: /\[[ xX]\]/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^<a /i, endATag: /^<\/a>/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^</, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (l3) => new RegExp(`^( {0,3}${l3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: I((l3) => new RegExp(`^ {0,${l3}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)), hrRegex: I((l3) => new RegExp(`^ {0,${l3}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`)), fencesBeginRegex: I((l3) => new RegExp(`^ {0,${l3}}(?:\`\`\`|~~~)`)), headingBeginRegex: I((l3) => new RegExp(`^ {0,${l3}}#`)), htmlBeginRegex: I((l3) => new RegExp(`^ {0,${l3}}<(?:[a-z].*>|!--)`, "i")), blockquoteBeginRegex: I((l3) => new RegExp(`^ {0,${l3}}>`)) };
101
+ var Te = /^(?:[ \t]*(?:\n|$))+/;
102
+ var we = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
103
+ var ye = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
104
+ var q = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
105
+ var Pe = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
106
+ var U = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
107
+ var oe = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
108
+ var ae = k(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
109
+ var Se = k(oe).replace(/bull/g, U).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}(?:\s|$)/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
110
+ var K = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \t]+\n)[^\n]+)*)/;
111
+ var _e = /^[^\n]+/;
112
+ var W = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
113
+ var $e = k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", W).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
114
+ var Le = k(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g, U).getRegex();
115
+ var Q = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
116
+ var X = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
117
+ var Ee = k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n*|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n*|$)|<![A-Z][\\s\\S]*?(?:>[^\\n]*\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>[^\\n]*\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", X).replace("tag", Q).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
118
+ var le = (l3) => k(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", l3).replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
119
+ var ze = le(/ {0,3}(?:[*+-]|1[.)])[ \t]+[^ \t\n]/);
120
+ var Me = le(/ {0,3}(?:[*+-]|\d{1,9}[.)])(?:[ \t]|\n|$)/);
121
+ var Ae = k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", Me).getRegex();
122
+ var J = { blockquote: Ae, code: we, def: $e, fences: ye, heading: Pe, hr: q, html: Ee, lheading: ae, list: Le, newline: Te, paragraph: ze, table: z, text: _e };
123
+ var se = k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex();
124
+ var Ie = { ...J, lheading: Se, table: se, paragraph: k(K).replace("hr", q).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*(?:\\n|$))|~~~)[^\\n]*(?:\\n|$)").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", Q).getRegex() };
125
+ var Ce = { ...J, html: k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", X).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: z, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: k(K).replace("hr", q).replace("heading", ` *#{1,6} *[^
126
+ ]`).replace("lheading", ae).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
127
+ var Be = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
128
+ var De = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
129
+ var ue = /^( {2,}|\\)\n(?!\s*$)/;
130
+ var qe = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
131
+ var _ = /[\p{P}\p{S}]/u;
132
+ var C = /[\s\p{P}\p{S}]/u;
133
+ var v = /[^\s\p{P}\p{S}]/u;
134
+ var ve = k(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, C).getRegex();
135
+ var He = /[\p{Pi}\p{Ps}"']/u;
136
+ var pe = /(?!~)[\p{P}\p{S}]/u;
137
+ var Ze = /(?!~)[\s\p{P}\p{S}]/u;
138
+ var Ge = /(?:[^\s\p{P}\p{S}]|~)/u;
139
+ var Qe = k(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", Oe ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
140
+ var ce = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
141
+ var Ne = k(ce, "u").replace(/punct/g, _).getRegex();
142
+ var je = k(ce, "u").replace(/punct/g, pe).getRegex();
143
+ var Fe = /^(?:\*+(?:((?!\*)(?!openQuote)punct)|([^\s*]))?)|^_+(?:((?!_)(?!openQuote)punct)|([^\s_]))?/;
144
+ var Ue = k(Fe, "u").replace(/openQuote/g, He).replace(/punct/g, _).getRegex();
145
+ var he = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
146
+ var Ke = k(he, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
147
+ var We = k(he, "gu").replace(/notPunctSpace/g, Ge).replace(/punctSpace/g, Ze).replace(/punct/g, pe).getRegex();
148
+ var Xe = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)[\\s](\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|(?:(?!\\*)punct|notPunctSpace)(\\*+)(?!\\*)(?=notPunctSpace)";
149
+ var Je = k(Xe, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
150
+ var Ve = k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
151
+ var Ye = "^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)[\\s](_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)|(?:(?!_)punct|notPunctSpace)(_+)(?!_)(?=notPunctSpace)";
152
+ var et = k(Ye, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
153
+ var tt = k(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, _).getRegex();
154
+ var nt = "^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)";
155
+ var rt = k(nt, "gu").replace(/notPunctSpace/g, v).replace(/punctSpace/g, C).replace(/punct/g, _).getRegex();
156
+ var st = k(/\\(punct)/, "gu").replace(/punct/g, _).getRegex();
157
+ var it = k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
158
+ var ot = k(X).replace("(?:-->|$)", "-->").getRegex();
159
+ var at = k("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", ot).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
160
+ var G = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/;
161
+ var lt = k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", G).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
162
+ var ke = k(/^!?\[(label)\]\[(ref)\]/).replace("label", G).replace("ref", W).getRegex();
163
+ var de = k(/^!?\[(ref)\](?:\[\])?/).replace("ref", W).getRegex();
164
+ var ut = k("reflink|nolink(?!\\()", "g").replace("reflink", ke).replace("nolink", de).getRegex();
165
+ var ie = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
166
+ var V = { _backpedal: z, anyPunctuation: st, autolink: it, blockSkip: Qe, br: ue, code: De, del: z, delLDelim: z, delRDelim: z, emStrongLDelim: Ne, emStrongRDelimAst: Ke, emStrongRDelimUnd: Ve, escape: Be, link: lt, nolink: de, punctuation: ve, reflink: ke, reflinkSearch: ut, tag: at, text: qe, url: z };
167
+ var pt = { ...V, emStrongLDelim: Ue, emStrongRDelimAst: Je, emStrongRDelimUnd: et, link: k(/^!?\[(label)\]\((.*?)\)/).replace("label", G).getRegex(), reflink: k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", G).getRegex() };
168
+ var F = { ...V, emStrongRDelimAst: We, emStrongLDelim: je, delLDelim: tt, delRDelim: rt, url: k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", ie).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: k(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", ie).getRegex() };
169
+ var ct = { ...F, br: k(ue).replace("{2,}", "*").getRegex(), text: k(F.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
170
+ var H = { normal: J, gfm: Ie, pedantic: Ce };
171
+ var B = { normal: V, gfm: F, breaks: ct, pedantic: pt };
172
+ var ht = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
173
+ var ge = (l3) => ht[l3];
174
+ function T(l3, e) {
175
+ if (e) {
176
+ if (m.escapeTest.test(l3)) return l3.replace(m.escapeReplace, ge);
177
+ } else if (m.escapeTestNoEncode.test(l3)) return l3.replace(m.escapeReplaceNoEncode, ge);
178
+ return l3;
179
+ }
180
+ function Y(l3) {
181
+ try {
182
+ l3 = encodeURI(l3).replace(m.percentDecode, "%");
183
+ } catch {
184
+ return null;
185
+ }
186
+ return l3;
187
+ }
188
+ function ee(l3, e) {
189
+ let t = l3.replace(m.findPipe, (r, i, o) => {
190
+ let u = false, a = i;
191
+ for (; --a >= 0 && o[a] === "\\"; ) u = !u;
192
+ return u ? "|" : " |";
193
+ }), n = t.split(m.splitPipe), s = 0;
194
+ if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
195
+ else for (; n.length < e; ) n.push("");
196
+ for (; s < n.length; s++) n[s] = n[s].trim().replace(m.slashPipe, "|");
197
+ return n;
198
+ }
199
+ function $(l3, e, t) {
200
+ let n = l3.length;
201
+ if (n === 0) return "";
202
+ let s = 0;
203
+ for (; s < n; ) {
204
+ let r = l3.charAt(n - s - 1);
205
+ if (r === e && !t) s++;
206
+ else if (r !== e && t) s++;
207
+ else break;
208
+ }
209
+ return l3.slice(0, n - s);
210
+ }
211
+ function te(l3) {
212
+ let e = l3.split(`
213
+ `), t = e.length - 1;
214
+ for (; t >= 0 && m.blankLine.test(e[t]); ) t--;
215
+ return e.length - t <= 2 ? l3 : e.slice(0, t + 1).join(`
216
+ `);
217
+ }
218
+ function fe(l3, e) {
219
+ if (l3.indexOf(e[1]) === -1) return -1;
220
+ let t = 0;
221
+ for (let n = 0; n < l3.length; n++) if (l3[n] === "\\") n++;
222
+ else if (l3[n] === e[0]) t++;
223
+ else if (l3[n] === e[1] && (t--, t < 0)) return n;
224
+ return t > 0 ? -2 : -1;
225
+ }
226
+ function me(l3, e = 0) {
227
+ let t = e, n = "";
228
+ for (let s of l3) if (s === " ") {
229
+ let r = 4 - t % 4;
230
+ n += " ".repeat(r), t += r;
231
+ } else n += s, t++;
232
+ return n;
233
+ }
234
+ function xe(l3, e, t, n, s) {
235
+ let r = e.href, i = e.title || null, o = l3[1].replace(s.other.outputLinkReplace, "$1"), u = l3[0].charAt(0) === "!";
236
+ n.state.inLink = true;
237
+ let a = n.state.linkEmitted, p = n.state.inRawBlock;
238
+ n.state.linkEmitted = false;
239
+ let c = n.inlineTokens(o), h = n.state.linkEmitted;
240
+ if (n.state.linkEmitted = a, n.state.inLink = false, !u) {
241
+ if (h) {
242
+ n.state.inRawBlock = p;
243
+ return;
244
+ }
245
+ n.state.linkEmitted = true;
246
+ }
247
+ return { type: u ? "image" : "link", raw: t, href: r, title: i, text: o, tokens: c };
248
+ }
249
+ function kt(l3, e, t) {
250
+ let n = l3.match(t.other.indentCodeCompensation);
251
+ if (n === null) return e;
252
+ let s = n[1];
253
+ return e.split(`
254
+ `).map((r) => {
255
+ let i = r.match(t.other.beginningSpace);
256
+ if (i === null) return r;
257
+ let [o] = i;
258
+ return o.length >= s.length ? r.slice(s.length) : r;
259
+ }).join(`
260
+ `);
261
+ }
262
+ var y = class {
263
+ options;
264
+ rules;
265
+ lexer;
266
+ constructor(e) {
267
+ this.options = e || R;
268
+ }
269
+ space(e) {
270
+ let t = this.rules.block.newline.exec(e);
271
+ if (t && t[0].length > 0) return { type: "space", raw: t[0] };
272
+ }
273
+ code(e) {
274
+ let t = this.rules.block.code.exec(e);
275
+ if (t) {
276
+ let n = this.options.pedantic ? t[0] : te(t[0]), s = n.replace(this.rules.other.codeRemoveIndent, "");
277
+ return { type: "code", raw: n, codeBlockStyle: "indented", text: s };
278
+ }
279
+ }
280
+ fences(e) {
281
+ let t = this.rules.block.fences.exec(e);
282
+ if (t) {
283
+ let n = t[0], s = kt(n, t[3] || "", this.rules);
284
+ return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: s };
285
+ }
286
+ }
287
+ heading(e) {
288
+ let t = this.rules.block.heading.exec(e);
289
+ if (t) {
290
+ let n = t[2].trim();
291
+ if (this.rules.other.endingHash.test(n)) {
292
+ let s = $(n, "#");
293
+ (this.options.pedantic || !s || this.rules.other.endingSpaceChar.test(s)) && (n = s.trim());
294
+ }
295
+ return { type: "heading", raw: $(t[0], `
296
+ `), depth: t[1].length, text: n, tokens: this.lexer.inline(n) };
297
+ }
298
+ }
299
+ hr(e) {
300
+ let t = this.rules.block.hr.exec(e);
301
+ if (t) return { type: "hr", raw: $(t[0], `
302
+ `) };
303
+ }
304
+ blockquote(e) {
305
+ let t = this.rules.block.blockquote.exec(e);
306
+ if (t) {
307
+ let n = $(t[0], `
308
+ `).split(`
309
+ `), s = "", r = "", i = [];
310
+ for (; n.length > 0; ) {
311
+ let o = false, u = [], a;
312
+ for (a = 0; a < n.length; a++) if (this.rules.other.blockquoteStart.test(n[a])) u.push(n[a]), o = true;
313
+ else if (!o) u.push(n[a]);
314
+ else break;
315
+ n = n.slice(a);
316
+ let p = u.join(`
317
+ `), c = p.replace(this.rules.other.blockquoteSetextReplace, `
318
+ $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
319
+ s = s ? `${s}
320
+ ${p}` : p, r = r ? `${r}
321
+ ${c}` : c;
322
+ let h = this.lexer.state.top;
323
+ if (this.lexer.state.top = true, this.lexer.blockTokens(c, i, true), this.lexer.state.top = h, n.length === 0) break;
324
+ let d = i.at(-1);
325
+ if (d?.type === "code") break;
326
+ if (d?.type === "blockquote") {
327
+ let O = d, g = n.join(`
328
+ `), w = O.raw + `
329
+ ` + g.replace(this.rules.other.blockquoteSetextReplace2, ""), E = this.blockquote(w);
330
+ i[i.length - 1] = E, s = `${s}
331
+ ${g}`, r = r.substring(0, r.length - O.text.length) + E.text;
332
+ break;
333
+ } else if (d?.type === "list") {
334
+ let O = d, g = O.raw + `
335
+ ` + n.join(`
336
+ `), w = this.list(g);
337
+ i[i.length - 1] = w, s = s.substring(0, s.length - d.raw.length) + w.raw, r = r.substring(0, r.length - O.raw.length) + w.raw, n = g.substring(i.at(-1).raw.length).split(`
338
+ `);
339
+ continue;
340
+ }
341
+ }
342
+ return { type: "blockquote", raw: s, tokens: i, text: r };
343
+ }
344
+ }
345
+ list(e) {
346
+ let t = this.rules.block.list.exec(e);
347
+ if (t) {
348
+ let n = t[1].trim(), s = n.length > 1, r = { type: "list", raw: "", ordered: s, start: s ? +n.slice(0, -1) : "", loose: false, items: [] };
349
+ n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]");
350
+ let i = this.rules.other.listItemRegex(n), o = false;
351
+ for (; e; ) {
352
+ let a = false, p = "", c = "";
353
+ if (!(t = i.exec(e)) || this.rules.block.hr.test(e)) break;
354
+ p = t[0], e = e.substring(p.length);
355
+ let h = me(t[2].split(`
356
+ `, 1)[0], t[1].length), d = e.split(`
357
+ `, 1)[0], O = !h.trim(), g = 0;
358
+ if (this.options.pedantic ? (g = 2, c = h.trimStart()) : O ? g = t[1].length + 1 : (g = h.search(this.rules.other.nonSpaceChar), g = g > 4 ? 1 : g, c = h.slice(g), g += t[1].length), O && this.rules.other.blankLine.test(d) && (p += d + `
359
+ `, e = e.substring(d.length + 1), a = true), !a) {
360
+ let w = this.rules.other.nextBulletRegex(g), E = this.rules.other.hrRegex(g), ne = this.rules.other.fencesBeginRegex(g), re = this.rules.other.headingBeginRegex(g), be = this.rules.other.htmlBeginRegex(g), Re = this.rules.other.blockquoteBeginRegex(g);
361
+ for (; e; ) {
362
+ let N = e.split(`
363
+ `, 1)[0], D;
364
+ if (d = N, this.options.pedantic ? (d = d.replace(this.rules.other.listReplaceNesting, " "), D = d) : D = d.replace(this.rules.other.tabCharGlobal, " "), ne.test(d) || re.test(d) || be.test(d) || Re.test(d) || w.test(d) || E.test(d)) break;
365
+ if (D.search(this.rules.other.nonSpaceChar) >= g || !d.trim()) c += `
366
+ ` + D.slice(g);
367
+ else {
368
+ if (O || h.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || ne.test(h) || re.test(h) || E.test(h)) break;
369
+ c += `
370
+ ` + d;
371
+ }
372
+ O = !d.trim(), p += N + `
373
+ `, e = e.substring(N.length + 1), h = D.slice(g);
374
+ }
375
+ }
376
+ r.loose || (o ? r.loose = true : this.rules.other.doubleBlankLine.test(p) && (o = true)), r.items.push({ type: "list_item", raw: p, task: !!this.options.gfm && this.rules.other.listIsTask.test(c), loose: false, text: c, tokens: [] }), r.raw += p;
377
+ }
378
+ let u = r.items.at(-1);
379
+ if (u) u.raw = u.raw.trimEnd(), u.text = u.text.trimEnd();
380
+ else return;
381
+ r.raw = r.raw.trimEnd();
382
+ for (let a of r.items) if (this.lexer.state.top = false, a.tokens = this.lexer.blockTokens(a.text, []), !r.loose) {
383
+ let p = a.tokens.filter((h) => h.type === "space"), c = p.length > 0 && p.some((h) => this.rules.other.anyLine.test(h.raw));
384
+ r.loose = c;
385
+ }
386
+ for (let a of r.items) {
387
+ let p = a.tokens[0];
388
+ if (a.task && (p?.type === "text" || p?.type === "paragraph")) {
389
+ a.text = a.text.replace(this.rules.other.listReplaceTask, ""), p.raw = p.raw.replace(this.rules.other.listReplaceTask, ""), p.text = p.text.replace(this.rules.other.listReplaceTask, "");
390
+ for (let h = this.lexer.inlineQueue.length - 1; h >= 0; h--) if (this.rules.other.listIsTask.test(this.lexer.inlineQueue[h].src)) {
391
+ this.lexer.inlineQueue[h].src = this.lexer.inlineQueue[h].src.replace(this.rules.other.listReplaceTask, "");
392
+ break;
393
+ }
394
+ let c = this.rules.other.listTaskCheckbox.exec(a.raw);
395
+ if (c) {
396
+ let h = { type: "checkbox", raw: c[0] + " ", checked: c[0] !== "[ ]" };
397
+ a.checked = h.checked, r.loose ? a.tokens[0] && ["paragraph", "text"].includes(a.tokens[0].type) && "tokens" in a.tokens[0] && a.tokens[0].tokens ? (a.tokens[0].raw = h.raw + a.tokens[0].raw, a.tokens[0].text = h.raw + a.tokens[0].text, a.tokens[0].tokens.unshift(h)) : a.tokens.unshift({ type: "paragraph", raw: h.raw, text: h.raw, tokens: [h] }) : a.tokens.unshift(h);
398
+ }
399
+ } else a.task && (a.task = false);
400
+ }
401
+ if (r.loose) for (let a of r.items) {
402
+ a.loose = true;
403
+ for (let p of a.tokens) p.type === "text" && (p.type = "paragraph");
404
+ }
405
+ return r;
406
+ }
407
+ }
408
+ html(e) {
409
+ let t = this.rules.block.html.exec(e);
410
+ if (t) {
411
+ let n = te(t[0]);
412
+ return { type: "html", block: true, raw: n, pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: n };
413
+ }
414
+ }
415
+ def(e) {
416
+ let t = this.rules.block.def.exec(e);
417
+ if (t) {
418
+ let n = t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), s = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", r = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3];
419
+ return { type: "def", tag: n, raw: $(t[0], `
420
+ `), href: s, title: r };
421
+ }
422
+ }
423
+ table(e) {
424
+ let t = this.rules.block.table.exec(e);
425
+ if (!t || !this.rules.other.tableDelimiter.test(t[2])) return;
426
+ let n = ee(t[1]), s = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), r = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
427
+ `) : [], i = { type: "table", raw: $(t[0], `
428
+ `), header: [], align: [], rows: [] };
429
+ if (n.length === s.length) {
430
+ for (let o of s) this.rules.other.tableAlignRight.test(o) ? i.align.push("right") : this.rules.other.tableAlignCenter.test(o) ? i.align.push("center") : this.rules.other.tableAlignLeft.test(o) ? i.align.push("left") : i.align.push(null);
431
+ for (let o = 0; o < n.length; o++) i.header.push({ text: n[o], tokens: this.lexer.inline(n[o]), header: true, align: i.align[o] });
432
+ for (let o of r) i.rows.push(ee(o, i.header.length).map((u, a) => ({ text: u, tokens: this.lexer.inline(u), header: false, align: i.align[a] })));
433
+ return i;
434
+ }
435
+ }
436
+ lheading(e) {
437
+ let t = this.rules.block.lheading.exec(e);
438
+ if (t) {
439
+ let n = t[1].trim();
440
+ return { type: "heading", raw: $(t[0], `
441
+ `), depth: t[2].charAt(0) === "=" ? 1 : 2, text: n, tokens: this.lexer.inline(n) };
442
+ }
443
+ }
444
+ paragraph(e) {
445
+ let t = this.rules.block.paragraph.exec(e);
446
+ if (t) {
447
+ let n = t[1].charAt(t[1].length - 1) === `
448
+ ` ? t[1].slice(0, -1) : t[1];
449
+ return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) };
450
+ }
451
+ }
452
+ text(e) {
453
+ let t = this.rules.block.text.exec(e);
454
+ if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) };
455
+ }
456
+ escape(e) {
457
+ let t = this.rules.inline.escape.exec(e);
458
+ if (t) return { type: "escape", raw: t[0], text: t[1] };
459
+ }
460
+ tag(e) {
461
+ let t = this.rules.inline.tag.exec(e);
462
+ if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] };
463
+ }
464
+ link(e) {
465
+ let t = this.rules.inline.link.exec(e);
466
+ if (t) {
467
+ let n = t[2].trim();
468
+ if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) {
469
+ if (!this.rules.other.endAngleBracket.test(n)) return;
470
+ let i = $(n.slice(0, -1), "\\");
471
+ if ((n.length - i.length) % 2 === 0) return;
472
+ } else {
473
+ let i = fe(t[2], "()");
474
+ if (i === -2) return;
475
+ if (i > -1) {
476
+ let u = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + i;
477
+ t[2] = t[2].substring(0, i), t[0] = t[0].substring(0, u).trim(), t[3] = "";
478
+ }
479
+ }
480
+ let s = t[2], r = "";
481
+ if (this.options.pedantic) {
482
+ let i = this.rules.other.pedanticHrefTitle.exec(s);
483
+ i && (s = i[1], r = i[3]);
484
+ } else r = t[3] ? t[3].slice(1, -1) : "";
485
+ return s = s.trim(), this.rules.other.startAngleBracket.test(s) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n) ? s = s.slice(1) : s = s.slice(1, -1)), xe(t, { href: s && s.replace(this.rules.inline.anyPunctuation, "$1"), title: r && r.replace(this.rules.inline.anyPunctuation, "$1") }, t[0], this.lexer, this.rules);
486
+ }
487
+ }
488
+ reflink(e, t) {
489
+ let n;
490
+ if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) {
491
+ let s = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), r = t[s.toLowerCase()];
492
+ if (!r) {
493
+ let i = n[0].charAt(0);
494
+ return { type: "text", raw: i, text: i };
495
+ }
496
+ return xe(n, r, n[0], this.lexer, this.rules);
497
+ }
498
+ }
499
+ emStrong(e, t, n = "") {
500
+ let s = this.rules.inline.emStrongLDelim.exec(e);
501
+ if (!s || !s[1] && !s[2] && !s[3] && !s[4] || s[4] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
502
+ if (!(s[1] || s[3] || "") || !n || this.rules.inline.punctuation.exec(n)) {
503
+ let i = [...s[0]].length - 1, o, u, a = i, p = 0, c = s[0][0], h = n === c, d = c === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
504
+ for (d.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = d.exec(t)) !== null; ) {
505
+ if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) continue;
506
+ if (u = [...o].length, s[3] || s[4]) {
507
+ a += u;
508
+ continue;
509
+ } else if (s[5] || s[6]) {
510
+ if (i % 3 && !((i + u) % 3)) {
511
+ p += u;
512
+ continue;
513
+ }
514
+ if (h) break;
515
+ }
516
+ if (a -= u, a > 0) continue;
517
+ u = Math.min(u, u + a + p);
518
+ let O = [...s[0]][0].length, g = e.slice(0, i + s.index + O + u);
519
+ if (Math.min(i, u) % 2) {
520
+ let E = g.slice(1, -1);
521
+ return { type: "em", raw: g, text: E, tokens: this.lexer.inlineTokens(E) };
522
+ }
523
+ let w = g.slice(2, -2);
524
+ return { type: "strong", raw: g, text: w, tokens: this.lexer.inlineTokens(w) };
525
+ }
526
+ }
527
+ }
528
+ codespan(e) {
529
+ let t = this.rules.inline.code.exec(e);
530
+ if (t) {
531
+ let n = t[2].replace(this.rules.other.newLineCharGlobal, " "), s = this.rules.other.nonSpaceChar.test(n), r = this.rules.other.startingSpaceChar.test(n) && this.rules.other.endingSpaceChar.test(n);
532
+ return s && r && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n };
533
+ }
534
+ }
535
+ br(e) {
536
+ let t = this.rules.inline.br.exec(e);
537
+ if (t) return { type: "br", raw: t[0] };
538
+ }
539
+ del(e, t, n = "") {
540
+ let s = this.rules.inline.delLDelim.exec(e);
541
+ if (!s) return;
542
+ if (!(s[1] || "") || !n || this.rules.inline.punctuation.exec(n)) {
543
+ let i = [...s[0]].length - 1, o, u, a = i, p = this.rules.inline.delRDelim;
544
+ for (p.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = p.exec(t)) !== null; ) {
545
+ if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o || (u = [...o].length, u !== i)) continue;
546
+ if (s[3] || s[4]) {
547
+ a += u;
548
+ continue;
549
+ }
550
+ if (a -= u, a > 0) continue;
551
+ u = Math.min(u, u + a);
552
+ let c = [...s[0]][0].length, h = e.slice(0, i + s.index + c + u), d = h.slice(i, -i);
553
+ return { type: "del", raw: h, text: d, tokens: this.lexer.inlineTokens(d) };
554
+ }
555
+ }
556
+ }
557
+ autolink(e) {
558
+ let t = this.rules.inline.autolink.exec(e);
559
+ if (t) {
560
+ let n, s;
561
+ return t[2] === "@" ? (n = t[1], s = "mailto:" + n) : (n = t[1], s = n), { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
562
+ }
563
+ }
564
+ url(e) {
565
+ let t;
566
+ if (t = this.rules.inline.url.exec(e)) {
567
+ let n, s;
568
+ if (t[2] === "@") n = t[0], s = "mailto:" + n;
569
+ else {
570
+ let r;
571
+ do
572
+ r = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? "";
573
+ while (r !== t[0]);
574
+ n = t[0], t[1] === "www." ? s = "http://" + t[0] : s = t[0];
575
+ }
576
+ return { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
577
+ }
578
+ }
579
+ inlineText(e) {
580
+ let t = this.rules.inline.text.exec(e);
581
+ if (t) {
582
+ let n = this.lexer.state.inRawBlock;
583
+ return { type: "text", raw: t[0], text: t[0], escaped: n };
584
+ }
585
+ }
586
+ };
587
+ var x = class l {
588
+ tokens;
589
+ options;
590
+ state;
591
+ inlineQueue;
592
+ tokenizer;
593
+ constructor(e) {
594
+ this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || R, this.options.tokenizer = this.options.tokenizer || new y(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, linkEmitted: false, top: true };
595
+ let t = { other: m, block: H.normal, inline: B.normal };
596
+ this.options.pedantic ? (t.block = H.pedantic, t.inline = B.pedantic) : this.options.gfm && (t.block = H.gfm, this.options.breaks ? t.inline = B.breaks : t.inline = B.gfm), this.tokenizer.rules = t;
597
+ }
598
+ static get rules() {
599
+ return { block: H, inline: B };
600
+ }
601
+ static lex(e, t) {
602
+ return new l(t).lex(e);
603
+ }
604
+ static lexInline(e, t) {
605
+ return new l(t).inlineTokens(e);
606
+ }
607
+ lex(e) {
608
+ e = e.replace(m.carriageReturn, `
609
+ `), this.blockTokens(e, this.tokens);
610
+ for (let t = 0; t < this.inlineQueue.length; t++) {
611
+ let n = this.inlineQueue[t];
612
+ this.inlineTokens(n.src, n.tokens);
613
+ }
614
+ return this.inlineQueue = [], this.tokens;
615
+ }
616
+ blockTokens(e, t = [], n = false) {
617
+ this.tokenizer.lexer = this, this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, ""));
618
+ let s = 1 / 0;
619
+ for (; e; ) {
620
+ if (e.length < s) s = e.length;
621
+ else {
622
+ this.infiniteLoopError(e.charCodeAt(0));
623
+ break;
624
+ }
625
+ let r;
626
+ if (this.options.extensions?.block?.some((o) => (r = o.call({ lexer: this }, e, t)) ? (e = e.substring(r.raw.length), t.push(r), true) : false)) continue;
627
+ if (r = this.tokenizer.space(e)) {
628
+ e = e.substring(r.raw.length);
629
+ let o = t.at(-1);
630
+ r.raw.length === 1 && o !== void 0 ? o.raw += `
631
+ ` : t.push(r);
632
+ continue;
633
+ }
634
+ if (r = this.tokenizer.code(e)) {
635
+ e = e.substring(r.raw.length);
636
+ let o = t.at(-1);
637
+ o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
638
+ `) ? "" : `
639
+ `) + r.raw, o.text += `
640
+ ` + r.text, this.inlineQueue.at(-1).src = o.text) : t.push(r);
641
+ continue;
642
+ }
643
+ if (r = this.tokenizer.fences(e)) {
644
+ e = e.substring(r.raw.length), t.push(r);
645
+ continue;
646
+ }
647
+ if (r = this.tokenizer.heading(e)) {
648
+ e = e.substring(r.raw.length), t.push(r);
649
+ continue;
650
+ }
651
+ if (r = this.tokenizer.hr(e)) {
652
+ e = e.substring(r.raw.length), t.push(r);
653
+ continue;
654
+ }
655
+ if (r = this.tokenizer.blockquote(e)) {
656
+ e = e.substring(r.raw.length), t.push(r);
657
+ continue;
658
+ }
659
+ if (r = this.tokenizer.list(e)) {
660
+ e = e.substring(r.raw.length), t.push(r);
661
+ continue;
662
+ }
663
+ if (r = this.tokenizer.html(e)) {
664
+ e = e.substring(r.raw.length), t.push(r);
665
+ continue;
666
+ }
667
+ if (r = this.tokenizer.def(e)) {
668
+ e = e.substring(r.raw.length);
669
+ let o = t.at(-1);
670
+ o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
671
+ `) ? "" : `
672
+ `) + r.raw, o.text += `
673
+ ` + r.raw, this.inlineQueue.at(-1).src = o.text) : this.tokens.links[r.tag] || (this.tokens.links[r.tag] = { href: r.href, title: r.title }, t.push(r));
674
+ continue;
675
+ }
676
+ if (r = this.tokenizer.table(e)) {
677
+ e = e.substring(r.raw.length), t.push(r);
678
+ continue;
679
+ }
680
+ if (r = this.tokenizer.lheading(e)) {
681
+ e = e.substring(r.raw.length), t.push(r);
682
+ continue;
683
+ }
684
+ let i = e;
685
+ if (this.options.extensions?.startBlock) {
686
+ let o = 1 / 0, u = e.slice(1), a;
687
+ this.options.extensions.startBlock.forEach((p) => {
688
+ a = p.call({ lexer: this }, u), typeof a == "number" && a >= 0 && (o = Math.min(o, a));
689
+ }), o < 1 / 0 && o >= 0 && (i = e.substring(0, o + 1));
690
+ }
691
+ if (this.state.top && (r = this.tokenizer.paragraph(i))) {
692
+ let o = t.at(-1);
693
+ n && o?.type === "paragraph" ? (o.raw += (o.raw.endsWith(`
694
+ `) ? "" : `
695
+ `) + r.raw, o.text += `
696
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r), n = i.length !== e.length, e = e.substring(r.raw.length);
697
+ continue;
698
+ }
699
+ if (r = this.tokenizer.text(e)) {
700
+ e = e.substring(r.raw.length);
701
+ let o = t.at(-1);
702
+ o?.type === "text" ? (o.raw += (o.raw.endsWith(`
703
+ `) ? "" : `
704
+ `) + r.raw, o.text += `
705
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r);
706
+ continue;
707
+ }
708
+ if (e) {
709
+ this.infiniteLoopError(e.charCodeAt(0));
710
+ break;
711
+ }
712
+ }
713
+ return this.state.top = true, t;
714
+ }
715
+ inline(e, t = []) {
716
+ return this.inlineQueue.push({ src: e, tokens: t }), t;
717
+ }
718
+ linkInText(e) {
719
+ if (!e.includes("[")) return false;
720
+ let t = this.tokenizer.rules.inline.link;
721
+ for (let n of e.matchAll(this.tokenizer.rules.inline.blockSkip)) if (t.test(n[0]) && e.charAt(n.index - 1) !== "!") return true;
722
+ for (let n of e.matchAll(this.tokenizer.rules.inline.reflinkSearch)) {
723
+ let s = n[0], r = s.lastIndexOf("[");
724
+ if (!(s.charAt(0) === "!" || !Object.hasOwn(this.tokens.links, s.slice(r + 1, -1))) && !(r > 1 && this.linkInText(s.slice(1, r - 1)))) return true;
725
+ }
726
+ return false;
727
+ }
728
+ inlineTokens(e, t = []) {
729
+ this.tokenizer.lexer = this;
730
+ let n = e;
731
+ if (this.tokens.links && e.includes("[")) {
732
+ let o = this.tokenizer.rules.inline.reflinkSearch, u = (a) => {
733
+ let p = a.lastIndexOf("[");
734
+ if (!Object.hasOwn(this.tokens.links, a.slice(p + 1, -1))) return a;
735
+ if (p > 1 && a.charAt(0) !== "!") {
736
+ let c = a.slice(1, p - 1);
737
+ if (this.linkInText(c)) return "[" + c.replace(o, u) + "][" + "a".repeat(a.length - p - 2) + "]";
738
+ }
739
+ return "[" + "a".repeat(a.length - 2) + "]";
740
+ };
741
+ n = n.replace(o, u);
742
+ }
743
+ n = n.replace(this.tokenizer.rules.inline.anyPunctuation, (o) => "+".repeat(o.length)), n = n.replace(this.tokenizer.rules.inline.blockSkip, (o, u, a) => {
744
+ let p = a ? a.length : 0;
745
+ return o.slice(0, p) + "[" + "a".repeat(o.length - p - 2) + "]";
746
+ }), n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
747
+ let s = false, r = "", i = 1 / 0;
748
+ for (; e; ) {
749
+ if (e.length < i) i = e.length;
750
+ else {
751
+ this.infiniteLoopError(e.charCodeAt(0));
752
+ break;
753
+ }
754
+ s || (r = ""), s = false;
755
+ let o;
756
+ if (this.options.extensions?.inline?.some((a) => (o = a.call({ lexer: this }, e, t)) ? (e = e.substring(o.raw.length), t.push(o), true) : false)) continue;
757
+ if (o = this.tokenizer.escape(e)) {
758
+ e = e.substring(o.raw.length), t.push(o);
759
+ continue;
760
+ }
761
+ if (o = this.tokenizer.tag(e)) {
762
+ e = e.substring(o.raw.length), t.push(o);
763
+ continue;
764
+ }
765
+ if (o = this.tokenizer.link(e)) {
766
+ e = e.substring(o.raw.length), t.push(o);
767
+ continue;
768
+ }
769
+ if (o = this.tokenizer.reflink(e, this.tokens.links)) {
770
+ e = e.substring(o.raw.length);
771
+ let a = t.at(-1);
772
+ o.type === "text" && a?.type === "text" ? (a.raw += o.raw, a.text += o.text) : t.push(o);
773
+ continue;
774
+ }
775
+ if (o = this.tokenizer.emStrong(e, n, r)) {
776
+ e = e.substring(o.raw.length), t.push(o);
777
+ continue;
778
+ }
779
+ if (o = this.tokenizer.codespan(e)) {
780
+ e = e.substring(o.raw.length), t.push(o);
781
+ continue;
782
+ }
783
+ if (o = this.tokenizer.br(e)) {
784
+ e = e.substring(o.raw.length), t.push(o);
785
+ continue;
786
+ }
787
+ if (o = this.tokenizer.del(e, n, r)) {
788
+ e = e.substring(o.raw.length), t.push(o);
789
+ continue;
790
+ }
791
+ if (o = this.tokenizer.autolink(e)) {
792
+ e = e.substring(o.raw.length), t.push(o);
793
+ continue;
794
+ }
795
+ if (!this.state.inLink && (o = this.tokenizer.url(e))) {
796
+ e = e.substring(o.raw.length), t.push(o);
797
+ continue;
798
+ }
799
+ let u = e;
800
+ if (this.options.extensions?.startInline) {
801
+ let a = 1 / 0, p = e.slice(1), c;
802
+ this.options.extensions.startInline.forEach((h) => {
803
+ c = h.call({ lexer: this }, p), typeof c == "number" && c >= 0 && (a = Math.min(a, c));
804
+ }), a < 1 / 0 && a >= 0 && (u = e.substring(0, a + 1));
805
+ }
806
+ if (o = this.tokenizer.inlineText(u)) {
807
+ e = e.substring(o.raw.length), o.raw.slice(-1) !== "_" && (r = o.raw.slice(-1)), s = true;
808
+ let a = t.at(-1);
809
+ a?.type === "text" ? (a.raw += o.raw, a.text += o.text) : t.push(o);
810
+ continue;
811
+ }
812
+ if (e) {
813
+ this.infiniteLoopError(e.charCodeAt(0));
814
+ break;
815
+ }
816
+ }
817
+ return t;
818
+ }
819
+ infiniteLoopError(e) {
820
+ let t = "Infinite loop on byte: " + e;
821
+ if (this.options.silent) console.error(t);
822
+ else throw new Error(t);
823
+ }
824
+ };
825
+ var P = class {
826
+ options;
827
+ parser;
828
+ constructor(e) {
829
+ this.options = e || R;
830
+ }
831
+ space(e) {
832
+ return "";
833
+ }
834
+ code({ text: e, lang: t, escaped: n }) {
835
+ let s = (t || "").match(m.notSpaceStart)?.[0], r = e.replace(m.endingNewline, "") + `
836
+ `;
837
+ return s ? '<pre><code class="language-' + T(s) + '">' + (n ? r : T(r, true)) + `</code></pre>
838
+ ` : "<pre><code>" + (n ? r : T(r, true)) + `</code></pre>
839
+ `;
840
+ }
841
+ blockquote({ tokens: e }) {
842
+ return `<blockquote>
843
+ ${this.parser.parse(e)}</blockquote>
844
+ `;
845
+ }
846
+ html({ text: e }) {
847
+ return e;
848
+ }
849
+ def(e) {
850
+ return "";
851
+ }
852
+ heading({ tokens: e, depth: t }) {
853
+ return `<h${t}>${this.parser.parseInline(e)}</h${t}>
854
+ `;
855
+ }
856
+ hr(e) {
857
+ return `<hr>
858
+ `;
859
+ }
860
+ list(e) {
861
+ let t = e.ordered, n = e.start, s = "";
862
+ for (let o = 0; o < e.items.length; o++) {
863
+ let u = e.items[o];
864
+ s += this.listitem(u);
865
+ }
866
+ let r = t ? "ol" : "ul", i = t && n !== 1 ? ' start="' + n + '"' : "";
867
+ return "<" + r + i + `>
868
+ ` + s + "</" + r + `>
869
+ `;
870
+ }
871
+ listitem(e) {
872
+ return `<li>${this.parser.parse(e.tokens)}</li>
873
+ `;
874
+ }
875
+ checkbox({ checked: e }) {
876
+ return "<input " + (e ? 'checked="" ' : "") + 'disabled="" type="checkbox"> ';
877
+ }
878
+ paragraph({ tokens: e }) {
879
+ return `<p>${this.parser.parseInline(e)}</p>
880
+ `;
881
+ }
882
+ table(e) {
883
+ let t = "", n = "";
884
+ for (let r = 0; r < e.header.length; r++) n += this.tablecell(e.header[r]);
885
+ t += this.tablerow({ text: n });
886
+ let s = "";
887
+ for (let r = 0; r < e.rows.length; r++) {
888
+ let i = e.rows[r];
889
+ n = "";
890
+ for (let o = 0; o < i.length; o++) n += this.tablecell(i[o]);
891
+ s += this.tablerow({ text: n });
892
+ }
893
+ return s && (s = `<tbody>${s}</tbody>`), `<table>
894
+ <thead>
895
+ ` + t + `</thead>
896
+ ` + s + `</table>
897
+ `;
898
+ }
899
+ tablerow({ text: e }) {
900
+ return `<tr>
901
+ ${e}</tr>
902
+ `;
903
+ }
904
+ tablecell(e) {
905
+ let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td";
906
+ return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + `</${n}>
907
+ `;
908
+ }
909
+ strong({ tokens: e }) {
910
+ return `<strong>${this.parser.parseInline(e)}</strong>`;
911
+ }
912
+ em({ tokens: e }) {
913
+ return `<em>${this.parser.parseInline(e)}</em>`;
914
+ }
915
+ codespan({ text: e }) {
916
+ return `<code>${T(e, true)}</code>`;
917
+ }
918
+ br(e) {
919
+ return "<br>";
920
+ }
921
+ del({ tokens: e }) {
922
+ return `<del>${this.parser.parseInline(e)}</del>`;
923
+ }
924
+ link({ href: e, title: t, tokens: n }) {
925
+ let s = this.parser.parseInline(n), r = Y(e);
926
+ if (r === null) return s;
927
+ e = r;
928
+ let i = '<a href="' + e + '"';
929
+ return t && (i += ' title="' + T(t) + '"'), i += ">" + s + "</a>", i;
930
+ }
931
+ image({ href: e, title: t, text: n, tokens: s }) {
932
+ s && (n = this.parser.parseInline(s, this.parser.textRenderer));
933
+ let r = Y(e);
934
+ if (r === null) return T(n);
935
+ e = r;
936
+ let i = `<img src="${e}" alt="${T(n)}"`;
937
+ return t && (i += ` title="${T(t)}"`), i += ">", i;
938
+ }
939
+ text(e) {
940
+ return "tokens" in e && e.tokens ? this.parser.parseInline(e.tokens) : "escaped" in e && e.escaped ? e.text : T(e.text);
941
+ }
942
+ };
943
+ var L = class {
944
+ strong({ text: e }) {
945
+ return e;
946
+ }
947
+ em({ text: e }) {
948
+ return e;
949
+ }
950
+ codespan({ text: e }) {
951
+ return e;
952
+ }
953
+ del({ text: e }) {
954
+ return e;
955
+ }
956
+ html({ text: e }) {
957
+ return e;
958
+ }
959
+ text({ text: e }) {
960
+ return e;
961
+ }
962
+ link({ text: e }) {
963
+ return "" + e;
964
+ }
965
+ image({ text: e }) {
966
+ return "" + e;
967
+ }
968
+ br() {
969
+ return "";
970
+ }
971
+ checkbox({ raw: e }) {
972
+ return e;
973
+ }
974
+ };
975
+ var b = class l2 {
976
+ options;
977
+ renderer;
978
+ textRenderer;
979
+ constructor(e) {
980
+ this.options = e || R, this.options.renderer = this.options.renderer || new P(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new L();
981
+ }
982
+ static parse(e, t) {
983
+ return new l2(t).parse(e);
984
+ }
985
+ static parseInline(e, t) {
986
+ return new l2(t).parseInline(e);
987
+ }
988
+ parse(e) {
989
+ this.renderer.parser = this;
990
+ let t = "";
991
+ for (let n = 0; n < e.length; n++) {
992
+ let s = e[n];
993
+ if (this.options.extensions?.renderers?.[s.type]) {
994
+ let i = s, o = this.options.extensions.renderers[i.type].call({ parser: this }, i);
995
+ if (o !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "checkbox", "html", "def", "paragraph", "text"].includes(i.type)) {
996
+ t += o || "";
997
+ continue;
998
+ }
999
+ }
1000
+ let r = s;
1001
+ switch (r.type) {
1002
+ case "space": {
1003
+ t += this.renderer.space(r);
1004
+ break;
1005
+ }
1006
+ case "hr": {
1007
+ t += this.renderer.hr(r);
1008
+ break;
1009
+ }
1010
+ case "heading": {
1011
+ t += this.renderer.heading(r);
1012
+ break;
1013
+ }
1014
+ case "code": {
1015
+ t += this.renderer.code(r);
1016
+ break;
1017
+ }
1018
+ case "table": {
1019
+ t += this.renderer.table(r);
1020
+ break;
1021
+ }
1022
+ case "blockquote": {
1023
+ t += this.renderer.blockquote(r);
1024
+ break;
1025
+ }
1026
+ case "list": {
1027
+ t += this.renderer.list(r);
1028
+ break;
1029
+ }
1030
+ case "checkbox": {
1031
+ t += this.renderer.checkbox(r);
1032
+ break;
1033
+ }
1034
+ case "html": {
1035
+ t += this.renderer.html(r);
1036
+ break;
1037
+ }
1038
+ case "def": {
1039
+ t += this.renderer.def(r);
1040
+ break;
1041
+ }
1042
+ case "paragraph": {
1043
+ t += this.renderer.paragraph(r);
1044
+ break;
1045
+ }
1046
+ case "text": {
1047
+ t += this.renderer.text(r);
1048
+ break;
1049
+ }
1050
+ default: {
1051
+ let i = 'Token with "' + r.type + '" type was not found.';
1052
+ if (this.options.silent) return console.error(i), "";
1053
+ throw new Error(i);
1054
+ }
1055
+ }
1056
+ }
1057
+ return t;
1058
+ }
1059
+ parseInline(e, t = this.renderer) {
1060
+ this.renderer.parser = this;
1061
+ let n = "";
1062
+ for (let s = 0; s < e.length; s++) {
1063
+ let r = e[s];
1064
+ if (this.options.extensions?.renderers?.[r.type]) {
1065
+ let o = this.options.extensions.renderers[r.type].call({ parser: this }, r);
1066
+ if (o !== false || !["escape", "html", "link", "image", "checkbox", "strong", "em", "codespan", "br", "del", "text"].includes(r.type)) {
1067
+ n += o || "";
1068
+ continue;
1069
+ }
1070
+ }
1071
+ let i = r;
1072
+ switch (i.type) {
1073
+ case "escape": {
1074
+ n += t.text(i);
1075
+ break;
1076
+ }
1077
+ case "html": {
1078
+ n += t.html(i);
1079
+ break;
1080
+ }
1081
+ case "link": {
1082
+ n += t.link(i);
1083
+ break;
1084
+ }
1085
+ case "image": {
1086
+ n += t.image(i);
1087
+ break;
1088
+ }
1089
+ case "checkbox": {
1090
+ n += t.checkbox(i);
1091
+ break;
1092
+ }
1093
+ case "strong": {
1094
+ n += t.strong(i);
1095
+ break;
1096
+ }
1097
+ case "em": {
1098
+ n += t.em(i);
1099
+ break;
1100
+ }
1101
+ case "codespan": {
1102
+ n += t.codespan(i);
1103
+ break;
1104
+ }
1105
+ case "br": {
1106
+ n += t.br(i);
1107
+ break;
1108
+ }
1109
+ case "del": {
1110
+ n += t.del(i);
1111
+ break;
1112
+ }
1113
+ case "text": {
1114
+ n += t.text(i);
1115
+ break;
1116
+ }
1117
+ default: {
1118
+ let o = 'Token with "' + i.type + '" type was not found.';
1119
+ if (this.options.silent) return console.error(o), "";
1120
+ throw new Error(o);
1121
+ }
1122
+ }
1123
+ }
1124
+ return n;
1125
+ }
1126
+ };
1127
+ var S = class {
1128
+ options;
1129
+ block;
1130
+ constructor(e) {
1131
+ this.options = e || R;
1132
+ }
1133
+ static passThroughHooks = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"]);
1134
+ static passThroughHooksRespectAsync = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"]);
1135
+ preprocess(e) {
1136
+ return e;
1137
+ }
1138
+ postprocess(e) {
1139
+ return e;
1140
+ }
1141
+ processAllTokens(e) {
1142
+ return e;
1143
+ }
1144
+ emStrongMask(e) {
1145
+ return e;
1146
+ }
1147
+ provideLexer(e = this.block) {
1148
+ return e ? x.lex : x.lexInline;
1149
+ }
1150
+ provideParser(e = this.block) {
1151
+ return e ? b.parse : b.parseInline;
1152
+ }
1153
+ };
1154
+ var Z = class {
1155
+ defaults = A();
1156
+ options = this.setOptions;
1157
+ parse = this.parseMarkdown(true);
1158
+ parseInline = this.parseMarkdown(false);
1159
+ Parser = b;
1160
+ Renderer = P;
1161
+ TextRenderer = L;
1162
+ Lexer = x;
1163
+ Tokenizer = y;
1164
+ Hooks = S;
1165
+ constructor(...e) {
1166
+ this.use(...e);
1167
+ }
1168
+ walkTokens(e, t) {
1169
+ let n = [];
1170
+ for (let s of e) switch (n = n.concat(t.call(this, s)), s.type) {
1171
+ case "table": {
1172
+ let r = s;
1173
+ for (let i of r.header) n = n.concat(this.walkTokens(i.tokens, t));
1174
+ for (let i of r.rows) for (let o of i) n = n.concat(this.walkTokens(o.tokens, t));
1175
+ break;
1176
+ }
1177
+ case "list": {
1178
+ let r = s;
1179
+ n = n.concat(this.walkTokens(r.items, t));
1180
+ break;
1181
+ }
1182
+ default: {
1183
+ let r = s;
1184
+ this.defaults.extensions?.childTokens?.[r.type] ? this.defaults.extensions.childTokens[r.type].forEach((i) => {
1185
+ let o = r[i].flat(1 / 0);
1186
+ n = n.concat(this.walkTokens(o, t));
1187
+ }) : r.tokens && (n = n.concat(this.walkTokens(r.tokens, t)));
1188
+ }
1189
+ }
1190
+ return n;
1191
+ }
1192
+ use(...e) {
1193
+ let t = this.defaults.extensions || { renderers: {}, childTokens: {} };
1194
+ return e.forEach((n) => {
1195
+ let s = { ...n };
1196
+ if (s.async = this.defaults.async || s.async || false, n.extensions && (n.extensions.forEach((r) => {
1197
+ if (!r.name) throw new Error("extension name required");
1198
+ if ("renderer" in r) {
1199
+ let i = t.renderers[r.name];
1200
+ i ? t.renderers[r.name] = function(...o) {
1201
+ let u = r.renderer.apply(this, o);
1202
+ return u === false && (u = i.apply(this, o)), u;
1203
+ } : t.renderers[r.name] = r.renderer;
1204
+ }
1205
+ if ("tokenizer" in r) {
1206
+ if (!r.level || r.level !== "block" && r.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
1207
+ let i = t[r.level];
1208
+ i ? i.unshift(r.tokenizer) : t[r.level] = [r.tokenizer], r.start && (r.level === "block" ? t.startBlock ? t.startBlock.push(r.start) : t.startBlock = [r.start] : r.level === "inline" && (t.startInline ? t.startInline.push(r.start) : t.startInline = [r.start]));
1209
+ }
1210
+ "childTokens" in r && r.childTokens && (t.childTokens[r.name] = r.childTokens);
1211
+ }), s.extensions = t), n.renderer) {
1212
+ let r = this.defaults.renderer || new P(this.defaults);
1213
+ for (let i in n.renderer) {
1214
+ if (!(i in r)) throw new Error(`renderer '${i}' does not exist`);
1215
+ if (["options", "parser"].includes(i)) continue;
1216
+ let o = i, u = n.renderer[o], a = r[o];
1217
+ r[o] = (...p) => {
1218
+ let c = u.apply(r, p);
1219
+ return c === false && (c = a.apply(r, p)), c || "";
1220
+ };
1221
+ }
1222
+ s.renderer = r;
1223
+ }
1224
+ if (n.tokenizer) {
1225
+ let r = this.defaults.tokenizer || new y(this.defaults);
1226
+ for (let i in n.tokenizer) {
1227
+ if (!(i in r)) throw new Error(`tokenizer '${i}' does not exist`);
1228
+ if (["options", "rules", "lexer"].includes(i)) continue;
1229
+ let o = i, u = n.tokenizer[o], a = r[o];
1230
+ r[o] = (...p) => {
1231
+ let c = u.apply(r, p);
1232
+ return c === false && (c = a.apply(r, p)), c;
1233
+ };
1234
+ }
1235
+ s.tokenizer = r;
1236
+ }
1237
+ if (n.hooks) {
1238
+ let r = this.defaults.hooks || new S();
1239
+ for (let i in n.hooks) {
1240
+ if (!(i in r)) throw new Error(`hook '${i}' does not exist`);
1241
+ if (["options", "block"].includes(i)) continue;
1242
+ let o = i, u = n.hooks[o], a = r[o];
1243
+ S.passThroughHooks.has(i) ? r[o] = (p) => {
1244
+ if (this.defaults.async && S.passThroughHooksRespectAsync.has(i)) return (async () => {
1245
+ let h = await u.call(r, p);
1246
+ return a.call(r, h);
1247
+ })();
1248
+ let c = u.call(r, p);
1249
+ return a.call(r, c);
1250
+ } : r[o] = (...p) => {
1251
+ if (this.defaults.async) return (async () => {
1252
+ let h = await u.apply(r, p);
1253
+ return h === false && (h = await a.apply(r, p)), h;
1254
+ })();
1255
+ let c = u.apply(r, p);
1256
+ return c === false && (c = a.apply(r, p)), c;
1257
+ };
1258
+ }
1259
+ s.hooks = r;
1260
+ }
1261
+ if (n.walkTokens) {
1262
+ let r = this.defaults.walkTokens, i = n.walkTokens;
1263
+ s.walkTokens = function(o) {
1264
+ let u = [];
1265
+ return u.push(i.call(this, o)), r && (u = u.concat(r.call(this, o))), u;
1266
+ };
1267
+ }
1268
+ this.defaults = { ...this.defaults, ...s };
1269
+ }), this;
1270
+ }
1271
+ setOptions(e) {
1272
+ return this.defaults = { ...this.defaults, ...e }, this;
1273
+ }
1274
+ lexer(e, t) {
1275
+ return x.lex(e, t ?? this.defaults);
1276
+ }
1277
+ parser(e, t) {
1278
+ return b.parse(e, t ?? this.defaults);
1279
+ }
1280
+ parseMarkdown(e) {
1281
+ return (n, s) => {
1282
+ let r = { ...s }, i = { ...this.defaults, ...r }, o = this.onError(!!i.silent, !!i.async);
1283
+ if (this.defaults.async === true && r.async === false) return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
1284
+ if (typeof n > "u" || n === null) return o(new Error("marked(): input parameter is undefined or null"));
1285
+ if (typeof n != "string") return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
1286
+ if (i.hooks && (i.hooks.options = i, i.hooks.block = e), i.async) return (async () => {
1287
+ let u = i.hooks ? await i.hooks.preprocess(n) : n, p = await (i.hooks ? await i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(u, i), c = i.hooks ? await i.hooks.processAllTokens(p) : p;
1288
+ i.walkTokens && await Promise.all(this.walkTokens(c, i.walkTokens));
1289
+ let d = await (i.hooks ? await i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(c, i);
1290
+ return i.hooks ? await i.hooks.postprocess(d) : d;
1291
+ })().catch(o);
1292
+ try {
1293
+ i.hooks && (n = i.hooks.preprocess(n));
1294
+ let a = (i.hooks ? i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(n, i);
1295
+ i.hooks && (a = i.hooks.processAllTokens(a)), i.walkTokens && this.walkTokens(a, i.walkTokens);
1296
+ let c = (i.hooks ? i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(a, i);
1297
+ return i.hooks && (c = i.hooks.postprocess(c)), c;
1298
+ } catch (u) {
1299
+ return o(u);
1300
+ }
1301
+ };
1302
+ }
1303
+ onError(e, t) {
1304
+ return (n) => {
1305
+ if (n.message += `
1306
+ Please report this to https://github.com/markedjs/marked.`, e) {
1307
+ let s = "<p>An error occurred:</p><pre>" + T(n.message + "", true) + "</pre>";
1308
+ return t ? Promise.resolve(s) : s;
1309
+ }
1310
+ if (t) return Promise.reject(n);
1311
+ throw n;
1312
+ };
1313
+ }
1314
+ };
1315
+ var M = new Z();
1316
+ function f(l3, e) {
1317
+ return M.parse(l3, e);
1318
+ }
1319
+ f.options = f.setOptions = function(l3) {
1320
+ return M.setOptions(l3), f.defaults = M.defaults, j(f.defaults), f;
1321
+ };
1322
+ f.getDefaults = A;
1323
+ f.defaults = R;
1324
+ function dt(...l3) {
1325
+ return M.use(...l3), f.defaults = M.defaults, j(f.defaults), f;
1326
+ }
1327
+ f.use = dt;
1328
+ f.walkTokens = function(l3, e) {
1329
+ return M.walkTokens(l3, e);
1330
+ };
1331
+ f.parseInline = M.parseInline;
1332
+ f.Parser = b;
1333
+ f.parser = b.parse;
1334
+ f.Renderer = P;
1335
+ f.TextRenderer = L;
1336
+ f.Lexer = x;
1337
+ f.lexer = x.lex;
1338
+ f.Tokenizer = y;
1339
+ f.Hooks = S;
1340
+ f.parse = f;
1341
+ var nn = f.options;
1342
+ var rn = f.setOptions;
1343
+ var sn = f.walkTokens;
1344
+ var on = f.parseInline;
1345
+ var ln = b.parse;
1346
+ var un = x.lex;
1347
+
1348
+ // src/markdown.ts
1349
+ var SAFE_LINK = /^(https?:|mailto:)/i;
1350
+ function node(type, content, attrs) {
1351
+ return {
1352
+ type,
1353
+ ...attrs && { attrs },
1354
+ ...content.length > 0 && { content }
1355
+ };
1356
+ }
1357
+ function text(value, marks) {
1358
+ if (value === "") return [];
1359
+ return [{ type: "text", text: value, ...marks.length > 0 && { marks } }];
1360
+ }
1361
+ function withMark(marks, mark) {
1362
+ return marks.some((existing) => existing.type === mark.type) ? marks : [...marks, mark];
1363
+ }
1364
+ function withLink(marks, href) {
1365
+ return SAFE_LINK.test(href) ? withMark(marks, { type: "link", attrs: { href } }) : marks;
1366
+ }
1367
+ function inline(tokens, marks = []) {
1368
+ return tokens.flatMap((token) => {
1369
+ switch (token.type) {
1370
+ case "strong":
1371
+ return inline(token.tokens, withMark(marks, { type: "strong" }));
1372
+ case "em":
1373
+ return inline(token.tokens, withMark(marks, { type: "em" }));
1374
+ case "del":
1375
+ return inline(token.tokens, withMark(marks, { type: "strikethrough" }));
1376
+ case "codespan":
1377
+ return text(token.text, withMark(marks, { type: "code" }));
1378
+ case "link": {
1379
+ const link = token;
1380
+ return inline(link.tokens, withLink(marks, link.href));
1381
+ }
1382
+ case "image": {
1383
+ const image = token;
1384
+ return text(image.text || image.href, withLink(marks, image.href));
1385
+ }
1386
+ case "br":
1387
+ return [{ type: "hard_break" }];
1388
+ case "text":
1389
+ return text(token.text, marks);
1390
+ default:
1391
+ return "text" in token && typeof token.text === "string" ? text(token.text, marks) : [];
1392
+ }
1393
+ });
1394
+ }
1395
+ function paragraph(tokens) {
1396
+ const content = inline(tokens);
1397
+ return content.length > 0 ? [node("paragraph", content)] : [];
1398
+ }
1399
+ function blocks(tokens) {
1400
+ return tokens.flatMap((token) => {
1401
+ switch (token.type) {
1402
+ case "heading": {
1403
+ const heading = token;
1404
+ return [
1405
+ node("heading", inline(heading.tokens), {
1406
+ level: heading.depth
1407
+ })
1408
+ ];
1409
+ }
1410
+ case "paragraph":
1411
+ return paragraph(token.tokens);
1412
+ case "text": {
1413
+ const t = token;
1414
+ return paragraph(t.tokens ?? [{ type: "text", raw: t.raw, text: t.text }]);
1415
+ }
1416
+ case "list": {
1417
+ const list = token;
1418
+ const items = list.items.map((item) => {
1419
+ const content = blocks(item.tokens);
1420
+ return node("list_item", content.length > 0 ? content : [node("paragraph", [])]);
1421
+ });
1422
+ if (!list.ordered) return [node("bullet_list", items)];
1423
+ return [node("ordered_list", items, { start: Number(list.start) })];
1424
+ }
1425
+ case "blockquote":
1426
+ return [node("blockquote", blocks(token.tokens))];
1427
+ case "hr":
1428
+ return [{ type: "horizontal_rule" }];
1429
+ case "code": {
1430
+ const code = token;
1431
+ return [
1432
+ node("code_block", text(code.text, []), {
1433
+ language: code.lang || null
1434
+ })
1435
+ ];
1436
+ }
1437
+ case "table": {
1438
+ const table = token;
1439
+ const rows = [table.header, ...table.rows];
1440
+ return rows.flatMap(
1441
+ (row) => paragraph(
1442
+ row.flatMap((cell, i) => [
1443
+ ...i > 0 ? [{ type: "text", raw: " | ", text: " | " }] : [],
1444
+ ...cell.tokens
1445
+ ])
1446
+ )
1447
+ );
1448
+ }
1449
+ case "space":
1450
+ return [];
1451
+ default:
1452
+ return "text" in token && typeof token.text === "string" && token.text.trim() !== "" ? [node("paragraph", text(token.text.trim(), []))] : [];
1453
+ }
1454
+ });
1455
+ }
1456
+ function markdownToDoc(markdown) {
1457
+ const content = blocks(x.lex(markdown, { gfm: true }));
1458
+ return {
1459
+ type: "doc",
1460
+ content: content.length > 0 ? content : [{ type: "paragraph" }]
1461
+ };
1462
+ }
1463
+
1464
+ // src/publication.ts
1465
+ var SUBDOMAIN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
1466
+ function publicationHost(value) {
1467
+ const raw = String(value ?? "").trim();
1468
+ if (raw === "") throw new Error('publication is required: its substack.com subdomain, such as "novumai"');
1469
+ if (SUBDOMAIN.test(raw)) return `${raw.toLowerCase()}.substack.com`;
1470
+ try {
1471
+ return new URL(raw.includes("://") ? raw : `https://${raw}`).hostname.toLowerCase();
1472
+ } catch {
1473
+ throw new Error(`"${raw}" is neither a publication subdomain nor an address`);
1474
+ }
1475
+ }
1476
+ function substackHost(value) {
1477
+ const host = publicationHost(value);
1478
+ if (!host.endsWith(".substack.com")) {
1479
+ throw new Error(
1480
+ `${host} is a custom domain; use the publication's substack.com address instead, such as novumai.substack.com`
1481
+ );
1482
+ }
1483
+ return host;
1484
+ }
1485
+ function postRef(value) {
1486
+ const raw = String(value ?? "").trim();
1487
+ const notAPost = new Error(
1488
+ `post must be a post's address, such as https://novumai.substack.com/p/its-slug; got "${raw}"`
1489
+ );
1490
+ let url;
1491
+ try {
1492
+ url = new URL(raw);
1493
+ } catch {
1494
+ throw notAPost;
1495
+ }
1496
+ const slug = /^\/p\/([^/]+)\/?/.exec(url.pathname)?.[1];
1497
+ if (url.protocol !== "https:" || !slug) throw notAPost;
1498
+ return { host: url.hostname.toLowerCase(), slug: decodeURIComponent(slug) };
1499
+ }
1500
+
1501
+ // package.json
1502
+ var package_default = {
1503
+ name: "@vornrun/connector-substack",
1504
+ version: "0.1.0",
1505
+ description: "Trigger workflows from new posts on a Substack publication, and read, search and comment on posts or save a draft from a step.",
1506
+ type: "module",
1507
+ license: "MIT",
1508
+ author: "Javier Canizalez <javier-canizalez@outlook.com>",
1509
+ repository: {
1510
+ type: "git",
1511
+ url: "git+https://github.com/vorn-run/connectors.git",
1512
+ directory: "packages/substack"
1513
+ },
1514
+ keywords: [
1515
+ "vorn",
1516
+ "connector",
1517
+ "substack",
1518
+ "newsletter",
1519
+ "mcp"
1520
+ ],
1521
+ bin: {
1522
+ "vorn-connector-substack": "dist/index.js"
1523
+ },
1524
+ main: "./dist/index.js",
1525
+ types: "./dist/index.d.ts",
1526
+ exports: {
1527
+ ".": {
1528
+ types: "./dist/index.d.ts",
1529
+ default: "./dist/index.js"
1530
+ }
1531
+ },
1532
+ files: [
1533
+ "dist",
1534
+ "README.md",
1535
+ "CHANGELOG.md"
1536
+ ],
1537
+ scripts: {
1538
+ build: "tsup",
1539
+ typecheck: "tsc --noEmit",
1540
+ test: "vitest run"
1541
+ },
1542
+ dependencies: {
1543
+ "@vornrun/connector-sdk": "^0.7.0-beta.18"
1544
+ },
1545
+ devDependencies: {
1546
+ "@types/node": "^22.10.2",
1547
+ "@vitest/coverage-v8": "^4.1.10",
1548
+ marked: "^18.0.11",
1549
+ tsup: "^8.5.1",
1550
+ typescript: "^6.0.3",
1551
+ vitest: "^4.1.10"
1552
+ },
1553
+ vorn: {
1554
+ category: "Social",
1555
+ keywords: [
1556
+ "substack",
1557
+ "newsletter",
1558
+ "posts",
1559
+ "comments",
1560
+ "drafts",
1561
+ "writing"
1562
+ ],
1563
+ auth: "Sign in to Substack in the window Vorn opens; reading a publication's feed and searching posts need no sign-in.",
1564
+ packs: true
1565
+ }
1566
+ };
1567
+
1568
+ // src/connector.ts
1569
+ var ORIGINS = ["https://substack.com", "https://*.substack.com"];
1570
+ var PROFILE_URL = "https://substack.com/api/v1/user/profile/self";
1571
+ var SEARCH_URL = "https://substack.com/api/v1/post/search";
1572
+ var MAX_FEED_POSTS = 20;
1573
+ var DEFAULT_FEED_POSTS = 10;
1574
+ var REACTION = "\u2764";
1575
+ var SLUG = /^[a-z0-9][a-z0-9-]*$/i;
1576
+ var NEVER = /publish|schedul/i;
1577
+ function text2(value) {
1578
+ const trimmed = String(value ?? "").trim();
1579
+ return trimmed || void 0;
1580
+ }
1581
+ function detail(body) {
1582
+ try {
1583
+ const parsed = JSON.parse(body);
1584
+ if (typeof parsed.error === "string") return `: ${parsed.error}`;
1585
+ const first = parsed.errors?.[0];
1586
+ if (first) return `: ${String(first.param ?? "")} ${String(first.msg ?? "")}`.trimEnd();
1587
+ } catch {
1588
+ }
1589
+ return "";
1590
+ }
1591
+ async function call(fetchImpl, url, init = {}) {
1592
+ const method = init.method ?? "GET";
1593
+ const { pathname } = new URL(url);
1594
+ const res = await fetchImpl(url, {
1595
+ method,
1596
+ headers: {
1597
+ accept: "application/json",
1598
+ ...init.body !== void 0 && { "content-type": "application/json" }
1599
+ },
1600
+ ...init.body !== void 0 && { body: JSON.stringify(init.body) }
1601
+ });
1602
+ const body = await res.text();
1603
+ if (!res.ok) throw new Error(`${method} ${pathname} answered ${res.status}${detail(body)}`);
1604
+ if (body.trim() === "") return {};
1605
+ try {
1606
+ return JSON.parse(body);
1607
+ } catch {
1608
+ throw new Error(`${method} ${pathname} answered something that is not JSON`);
1609
+ }
1610
+ }
1611
+ function neverPublishing(fetchImpl) {
1612
+ return ((input, init) => {
1613
+ const { pathname } = new URL(input instanceof Request ? input.url : String(input));
1614
+ if (NEVER.test(pathname)) {
1615
+ return Promise.reject(new Error(`Refused ${pathname}: this connector never publishes or schedules`));
1616
+ }
1617
+ return fetchImpl(input, init);
1618
+ });
1619
+ }
1620
+ function signedIn(session) {
1621
+ if (!session)
1622
+ throw new Error("This action acts as you on Substack, so it runs from Vorn once the connection is signed in");
1623
+ return { fetch: neverPublishing(session.fetch) };
1624
+ }
1625
+ function publicationsOf(me2) {
1626
+ return (me2.publicationUsers ?? []).flatMap((user) => {
1627
+ const subdomain = text2(user.publication?.subdomain);
1628
+ if (subdomain === void 0) return [];
1629
+ return [{ subdomain, name: text2(user.publication?.name) ?? subdomain, primary: user.is_primary === true }];
1630
+ });
1631
+ }
1632
+ function stepPublication(value, config) {
1633
+ return text2(value) ?? config.publication;
1634
+ }
1635
+ async function readPosts(fetchImpl, host) {
1636
+ const res = await fetchImpl(`https://${host}/feed`, {
1637
+ headers: { accept: "application/rss+xml, application/xml, text/xml" }
1638
+ });
1639
+ if (!res.ok) throw new Error(`GET /feed on ${host} answered ${res.status}`);
1640
+ return parseFeed(await res.text());
1641
+ }
1642
+ function feedLimit(value) {
1643
+ const raw = text2(value);
1644
+ if (raw === void 0) return DEFAULT_FEED_POSTS;
1645
+ const parsed = Number(raw);
1646
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_FEED_POSTS) {
1647
+ throw new Error(`limit must be a whole number from 1 to ${MAX_FEED_POSTS}`);
1648
+ }
1649
+ return parsed;
1650
+ }
1651
+ function wholeId(value, name) {
1652
+ const parsed = Number(text2(value));
1653
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) throw new Error(`${name} must be a Substack id, a whole number`);
1654
+ return parsed;
1655
+ }
1656
+ function namedPublication(value, config) {
1657
+ const named = text2(value) ?? text2(config.publication);
1658
+ return named === void 0 ? void 0 : substackHost(named);
1659
+ }
1660
+ function primaryPublication(me2) {
1661
+ const publications = publicationsOf(me2);
1662
+ const primary = publications.find((publication) => publication.primary) ?? publications[0];
1663
+ if (primary === void 0) throw new Error("This account has no publication; name one in the step or the connection");
1664
+ return substackHost(primary.subdomain);
1665
+ }
1666
+ async function ownPublication(value, config, session) {
1667
+ return namedPublication(value, config) ?? primaryPublication(await call(session.fetch, PROFILE_URL));
1668
+ }
1669
+ function postHost(post, publication) {
1670
+ const raw = text2(post);
1671
+ return raw?.includes("/") ? postRef(raw).host : publicationHost(publication);
1672
+ }
1673
+ async function resolvePost(fetchImpl, post, postId, publication) {
1674
+ const raw = text2(post);
1675
+ const ref = raw?.includes("/") ? postRef(raw) : void 0;
1676
+ const host = postHost(post, publication);
1677
+ if (text2(postId) !== void 0) return { host, id: wholeId(postId, "postId") };
1678
+ if (raw === void 0) throw new Error("Give the post's address, its slug, or its id");
1679
+ if (/^\d+$/.test(raw)) return { host, id: Number(raw) };
1680
+ const slug = ref?.slug ?? raw;
1681
+ if (!SLUG.test(slug)) throw new Error(`"${slug}" is not a post slug`);
1682
+ const found = await call(fetchImpl, `https://${host}/api/v1/posts/${slug}`);
1683
+ if (typeof found.id !== "number") throw new Error(`No post "${slug}" on ${host}`);
1684
+ return { host, id: found.id };
1685
+ }
1686
+ function postItem(post) {
1687
+ return {
1688
+ externalId: post.id,
1689
+ title: post.title || post.url,
1690
+ url: post.url,
1691
+ ...post.subtitle && { description: post.subtitle },
1692
+ ...post.author && { assignee: post.author },
1693
+ ...post.publishedAt && { updatedAt: post.publishedAt },
1694
+ data: { subtitle: post.subtitle, author: post.author, publishedAt: post.publishedAt, text: post.text }
1695
+ };
1696
+ }
1697
+ function flattenComments(comments) {
1698
+ return (comments ?? []).flatMap((comment) => {
1699
+ const parent = String(comment.ancestor_path ?? "").split(".").filter(Boolean).at(-1);
1700
+ const record = {
1701
+ id: Number(comment.id),
1702
+ body: comment.deleted === true ? "" : String(comment.body ?? ""),
1703
+ author: String(comment.name ?? ""),
1704
+ handle: String(comment.handle ?? ""),
1705
+ date: String(comment.date ?? ""),
1706
+ likes: Number(comment.reaction_count ?? 0),
1707
+ parentId: parent === void 0 ? null : Number(parent),
1708
+ replies: Number(comment.children_count ?? comment.children?.length ?? 0)
1709
+ };
1710
+ return [record, ...flattenComments(comment.children)];
1711
+ });
1712
+ }
1713
+ var SAMPLE_POST = {
1714
+ id: "https://novumai.substack.com/p/anthropic-passed-openai-this-week",
1715
+ title: "Anthropic passed OpenAI this week. The $65 billion shows what the lead costs.",
1716
+ subtitle: "Both moves are really about one question: who can pay for compute.",
1717
+ url: "https://novumai.substack.com/p/anthropic-passed-openai-this-week",
1718
+ author: "Javier Canizalez",
1719
+ publishedAt: "2026-05-29T20:03:32.000Z",
1720
+ html: "<p>Both moves are really about one question.</p>",
1721
+ text: "Both moves are really about one question."
1722
+ };
1723
+ var PUBLICATION_INPUT = {
1724
+ key: "publication",
1725
+ label: "Publication",
1726
+ description: "Its substack.com subdomain or address; the connection's publication when empty."
1727
+ };
1728
+ var OWN_PUBLICATION_INPUT = {
1729
+ ...PUBLICATION_INPUT,
1730
+ description: "Its substack.com subdomain; the connection's publication when empty, else the account's primary one."
1731
+ };
1732
+ var POST_INPUTS = [
1733
+ {
1734
+ key: "post",
1735
+ label: "Post",
1736
+ description: "The post's address, or its slug on the publication; not needed when its id is given."
1737
+ },
1738
+ {
1739
+ key: "postId",
1740
+ label: "Post id",
1741
+ type: "number",
1742
+ description: "The post's id, as Search posts returns it; saves looking the post up by address."
1743
+ }
1744
+ ];
1745
+ var COMMENT_PUBLICATION_INPUT = {
1746
+ ...PUBLICATION_INPUT,
1747
+ description: "The publication the comment's post is on; the connection's when empty, else the account's primary one."
1748
+ };
1749
+ var connector = defineConnector({
1750
+ id: "substack",
1751
+ name: "Substack",
1752
+ version: package_default.version,
1753
+ description: "Trigger workflows from new posts on a Substack publication, and read, search and comment on posts or save a draft from a step.",
1754
+ icon: {
1755
+ viewBox: "0 0 24 24",
1756
+ paths: [
1757
+ "M22.539 8.242H1.46V5.406h21.08v2.836zM1.46 10.812V24L12 18.11 22.54 24V10.812H1.46zM22.54 0H1.46v2.836h21.08V0z"
1758
+ ]
1759
+ },
1760
+ auth: {
1761
+ rung: "browser",
1762
+ browser: {
1763
+ signInUrl: "https://substack.com/sign-in",
1764
+ origins: ORIGINS,
1765
+ check: { url: PROFILE_URL, identity: ["name", "handle"] }
1766
+ }
1767
+ },
1768
+ config: [
1769
+ {
1770
+ key: "publication",
1771
+ label: "Publication",
1772
+ env: "SUBSTACK_PUBLICATION",
1773
+ description: "Your publication's substack.com subdomain, such as novumai. The new-post trigger reads its feed, and a step that names no publication uses it.",
1774
+ builderHint: "The part before .substack.com in the publication address; a custom domain works for reading only."
1775
+ }
1776
+ ],
1777
+ options: {
1778
+ publications: async (ctx) => {
1779
+ if (!ctx.session) return [];
1780
+ const me2 = await call(signedIn(ctx.session).fetch, PROFILE_URL);
1781
+ return publicationsOf(me2).map(({ subdomain, name }) => ({ value: subdomain, label: name }));
1782
+ }
1783
+ },
1784
+ triggers: [
1785
+ {
1786
+ type: "newPost",
1787
+ label: "New post",
1788
+ description: "A post appears in the publication's RSS feed. Reading the feed needs no sign-in; it holds about the last twenty posts, so a burst larger than that between polls loses the oldest.",
1789
+ dedupe: "timestamp",
1790
+ fetch: async (ctx) => (await readPosts(ctx.fetch, publicationHost(ctx.config.publication))).map(postItem),
1791
+ sample: [postItem(SAMPLE_POST)]
1792
+ }
1793
+ ],
1794
+ actions: [
1795
+ {
1796
+ type: "readFeed",
1797
+ label: "Read feed",
1798
+ description: `The newest posts of any publication from its RSS feed, up to ${MAX_FEED_POSTS}, with each body as text and HTML. Needs no sign-in.`,
1799
+ idempotent: true,
1800
+ inputs: [
1801
+ PUBLICATION_INPUT,
1802
+ {
1803
+ key: "limit",
1804
+ label: "Posts",
1805
+ type: "number",
1806
+ description: `How many of the newest posts, from 1 to ${MAX_FEED_POSTS}; ${DEFAULT_FEED_POSTS} when empty.`
1807
+ }
1808
+ ],
1809
+ outputs: [
1810
+ { key: "publication", type: "string", description: "The host the feed was read from" },
1811
+ { key: "count", type: "number", description: "How many posts came back, in `posts`" }
1812
+ ],
1813
+ run: async (args, ctx) => {
1814
+ const host = publicationHost(stepPublication(args.publication, ctx.config));
1815
+ const posts = (await readPosts(ctx.fetch, host)).slice(0, feedLimit(args.limit));
1816
+ return { publication: host, count: posts.length, posts };
1817
+ }
1818
+ },
1819
+ {
1820
+ type: "searchPosts",
1821
+ label: "Search posts",
1822
+ description: "Posts across Substack matching a query, a page at a time, as Substack search ranks them. Needs no sign-in.",
1823
+ idempotent: true,
1824
+ inputs: [
1825
+ { key: "query", label: "Query", required: true, description: "Words to search posts for." },
1826
+ { key: "page", label: "Page", type: "number", description: "Which page of results, from 0; 0 when empty." }
1827
+ ],
1828
+ outputs: [
1829
+ { key: "count", type: "number", description: "How many posts are on this page, in `posts`" },
1830
+ { key: "more", type: "boolean", description: "Whether a next page exists" }
1831
+ ],
1832
+ run: async (args, ctx) => {
1833
+ const query = text2(args.query);
1834
+ if (query === void 0) throw new Error("query is required");
1835
+ const page = text2(args.page) === void 0 ? 0 : Number(args.page);
1836
+ if (!Number.isInteger(page) || page < 0) throw new Error("page must be a whole number from 0");
1837
+ const url = new URL(SEARCH_URL);
1838
+ url.search = new URLSearchParams({
1839
+ query,
1840
+ page: String(page),
1841
+ includePlatformResults: "true",
1842
+ filter: "all"
1843
+ }).toString();
1844
+ const found = await call(ctx.fetch, url.href);
1845
+ const posts = (found.results ?? []).map((post) => ({
1846
+ id: Number(post.id),
1847
+ title: String(post.title ?? ""),
1848
+ subtitle: String(post.subtitle ?? ""),
1849
+ url: String(post.canonical_url ?? ""),
1850
+ publishedAt: String(post.post_date ?? ""),
1851
+ author: String(post.publishedBylines?.[0]?.name ?? ""),
1852
+ authorHandle: String(post.publishedBylines?.[0]?.handle ?? ""),
1853
+ likes: Number(post.reaction_count ?? 0),
1854
+ comments: Number(post.comment_count ?? 0),
1855
+ publicationId: Number(post.publication_id ?? 0)
1856
+ }));
1857
+ return { query, page, count: posts.length, more: found.more === true, posts };
1858
+ }
1859
+ },
1860
+ {
1861
+ type: "readComments",
1862
+ label: "Read comments",
1863
+ description: "Every comment on a post, newest first, with replies after the comment they answer. Needs no sign-in for a public post.",
1864
+ idempotent: true,
1865
+ inputs: [...POST_INPUTS, PUBLICATION_INPUT],
1866
+ outputs: [
1867
+ { key: "postId", type: "number", description: "The post's id" },
1868
+ { key: "count", type: "number", description: "How many comments came back, in `comments`" }
1869
+ ],
1870
+ run: async (args, ctx) => {
1871
+ const publication = stepPublication(args.publication, ctx.config);
1872
+ const { host, id } = await resolvePost(ctx.fetch, args.post, args.postId, publication);
1873
+ const found = await call(
1874
+ ctx.fetch,
1875
+ `https://${host}/api/v1/post/${id}/comments?all_comments=true&sort=newest_first`
1876
+ );
1877
+ const comments = flattenComments(found.comments);
1878
+ return { postId: id, count: comments.length, comments };
1879
+ }
1880
+ },
1881
+ {
1882
+ type: "createDraft",
1883
+ label: "Save draft",
1884
+ description: "Save a new draft on your publication from a title and markdown, for you to review and publish in Substack. It never publishes, since publishing emails every subscriber.",
1885
+ idempotent: false,
1886
+ inputs: [
1887
+ { key: "title", label: "Title", required: true, description: "The draft's title." },
1888
+ { key: "subtitle", label: "Subtitle", description: "The line under the title." },
1889
+ {
1890
+ key: "body",
1891
+ label: "Body",
1892
+ required: true,
1893
+ description: "The post in markdown: headings, lists, quotes, code, links and emphasis carry over."
1894
+ },
1895
+ { ...OWN_PUBLICATION_INPUT, type: "select", loadOptions: "publications" }
1896
+ ],
1897
+ outputs: [
1898
+ { key: "id", type: "number", description: "The draft's id" },
1899
+ { key: "editUrl", type: "string", description: "Where to open the draft in the Substack editor" }
1900
+ ],
1901
+ run: async (args, ctx) => {
1902
+ const session = signedIn(ctx.session);
1903
+ const title = text2(args.title);
1904
+ const body = text2(args.body);
1905
+ if (title === void 0) throw new Error("title is required");
1906
+ if (body === void 0) throw new Error("body is required");
1907
+ const me2 = await call(session.fetch, PROFILE_URL);
1908
+ const host = namedPublication(args.publication, ctx.config) ?? primaryPublication(me2);
1909
+ const draft = await call(session.fetch, `https://${host}/api/v1/drafts`, {
1910
+ method: "POST",
1911
+ body: {
1912
+ draft_title: title,
1913
+ draft_subtitle: text2(args.subtitle) ?? "",
1914
+ draft_body: JSON.stringify(markdownToDoc(body)),
1915
+ // Substack refuses a draft without a byline and says so; only a profile with no id leaves it out.
1916
+ ...typeof me2.id === "number" && { draft_bylines: [{ id: me2.id, is_guest: false }] },
1917
+ type: "newsletter",
1918
+ audience: "everyone",
1919
+ section_chosen: false,
1920
+ draft_section_id: null
1921
+ }
1922
+ });
1923
+ const id = typeof draft.id === "number" ? draft.id : void 0;
1924
+ return { title, ...id !== void 0 && { id, editUrl: `https://${host}/publish/post/${id}` } };
1925
+ }
1926
+ },
1927
+ {
1928
+ type: "deleteDraft",
1929
+ label: "Delete draft",
1930
+ description: "Delete a draft on your publication. A published post is refused, so this never removes one.",
1931
+ idempotent: false,
1932
+ inputs: [
1933
+ {
1934
+ key: "draftId",
1935
+ label: "Draft id",
1936
+ type: "number",
1937
+ required: true,
1938
+ description: "The id Save draft returned."
1939
+ },
1940
+ OWN_PUBLICATION_INPUT
1941
+ ],
1942
+ outputs: [{ key: "deleted", type: "boolean", description: "Whether the draft was deleted" }],
1943
+ run: async (args, ctx) => {
1944
+ const session = signedIn(ctx.session);
1945
+ const id = wholeId(args.draftId, "draftId");
1946
+ const host = await ownPublication(args.publication, ctx.config, session);
1947
+ const draft = await call(session.fetch, `https://${host}/api/v1/drafts/${id}`);
1948
+ if (draft.is_published === true) {
1949
+ throw new Error(`${id} is a published post, not a draft; this action deletes only drafts`);
1950
+ }
1951
+ await call(session.fetch, `https://${host}/api/v1/drafts/${id}`, { method: "DELETE" });
1952
+ return { deleted: true, id };
1953
+ }
1954
+ },
1955
+ {
1956
+ type: "commentOnPost",
1957
+ label: "Comment on post",
1958
+ description: "Post a comment on a post as the signed-in account.",
1959
+ idempotent: false,
1960
+ inputs: [
1961
+ ...POST_INPUTS,
1962
+ { key: "body", label: "Comment", required: true, description: "The comment, as plain text." },
1963
+ PUBLICATION_INPUT
1964
+ ],
1965
+ outputs: [
1966
+ { key: "id", type: "number", description: "The new comment's id" },
1967
+ { key: "postId", type: "number", description: "The post's id" }
1968
+ ],
1969
+ run: async (args, ctx) => {
1970
+ const session = signedIn(ctx.session);
1971
+ const body = text2(args.body);
1972
+ if (body === void 0) throw new Error("body is required");
1973
+ const publication = stepPublication(args.publication, ctx.config);
1974
+ const host = substackHost(postHost(args.post, publication));
1975
+ const { id } = await resolvePost(ctx.fetch, args.post, args.postId, publication);
1976
+ const comment = await call(session.fetch, `https://${host}/api/v1/post/${id}/comment`, {
1977
+ method: "POST",
1978
+ body: { body }
1979
+ });
1980
+ return { postId: id, ...typeof comment.id === "number" && { id: comment.id } };
1981
+ }
1982
+ },
1983
+ {
1984
+ type: "setCommentLike",
1985
+ label: "Like or unlike comment",
1986
+ description: "Like a comment as the signed-in account, or take the like back. Setting the same state twice changes nothing.",
1987
+ idempotent: true,
1988
+ inputs: [
1989
+ {
1990
+ key: "commentId",
1991
+ label: "Comment id",
1992
+ type: "number",
1993
+ required: true,
1994
+ description: "The id Read comments returned."
1995
+ },
1996
+ {
1997
+ key: "liked",
1998
+ label: "Liked",
1999
+ type: "boolean",
2000
+ required: true,
2001
+ description: "true to like it, false to take the like back."
2002
+ },
2003
+ COMMENT_PUBLICATION_INPUT
2004
+ ],
2005
+ outputs: [{ key: "liked", type: "boolean", description: "The state now set" }],
2006
+ run: async (args, ctx) => {
2007
+ const session = signedIn(ctx.session);
2008
+ const id = wholeId(args.commentId, "commentId");
2009
+ const liked = args.liked === true;
2010
+ const host = await ownPublication(args.publication, ctx.config, session);
2011
+ await call(session.fetch, `https://${host}/api/v1/comment/${id}/reaction`, {
2012
+ method: liked ? "POST" : "DELETE",
2013
+ body: { reaction: REACTION }
2014
+ });
2015
+ return { commentId: id, liked };
2016
+ }
2017
+ },
2018
+ {
2019
+ type: "deleteComment",
2020
+ label: "Delete comment",
2021
+ description: "Delete one of the signed-in account's comments, or one on its own publication.",
2022
+ idempotent: false,
2023
+ inputs: [
2024
+ {
2025
+ key: "commentId",
2026
+ label: "Comment id",
2027
+ type: "number",
2028
+ required: true,
2029
+ description: "The id Read comments or Comment on post returned."
2030
+ },
2031
+ COMMENT_PUBLICATION_INPUT
2032
+ ],
2033
+ outputs: [{ key: "deleted", type: "boolean", description: "Whether the comment was deleted" }],
2034
+ run: async (args, ctx) => {
2035
+ const session = signedIn(ctx.session);
2036
+ const id = wholeId(args.commentId, "commentId");
2037
+ const host = await ownPublication(args.publication, ctx.config, session);
2038
+ await call(session.fetch, `https://${host}/api/v1/comment/${id}`, { method: "DELETE" });
2039
+ return { deleted: true, commentId: id };
2040
+ }
2041
+ }
2042
+ ]
2043
+ });
2044
+
2045
+ // src/entry.ts
2046
+ import { realpathSync } from "fs";
2047
+ import { fileURLToPath } from "url";
2048
+ import { serveConnector } from "@vornrun/connector-sdk";
2049
+ function isEntryPoint(moduleUrl, argv = process.argv) {
2050
+ const invoked = argv[1];
2051
+ if (invoked === void 0) return false;
2052
+ try {
2053
+ return realpathSync(fileURLToPath(moduleUrl)) === realpathSync(invoked);
2054
+ } catch {
2055
+ return false;
2056
+ }
2057
+ }
2058
+ async function serveIfEntryPoint(moduleUrl, serve = serveConnector) {
2059
+ if (!isEntryPoint(moduleUrl)) return false;
2060
+ await serve(connector);
2061
+ return true;
2062
+ }
2063
+
2064
+ // src/index.ts
2065
+ var index_default = connector;
2066
+ await serveIfEntryPoint(import.meta.url);
2067
+ export {
2068
+ connector,
2069
+ index_default as default
2070
+ };