stream-markdown-parser 0.0.59-beta.9 → 0.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -227,7 +227,7 @@ Processes raw markdown-it tokens into a flat array.
227
227
 
228
228
  #### `parseInlineTokens(tokens, content?, preToken?, options?)`
229
229
 
230
- Parses inline markdown-it-ts tokens into renderer nodes. Pass the inline token array plus the optional raw `content` string (from the parent token), an optional previous token, and inline parse options (`requireClosingStrong`, `customHtmlTags`).
230
+ Parses inline markdown-it-ts tokens into renderer nodes. Pass the inline token array plus the optional raw `content` string (from the parent token), an optional previous token, and inline parse options (`requireClosingStrong`, `customHtmlTags`, `validateLink`).
231
231
 
232
232
  ### Configuration Functions
233
233
 
@@ -255,6 +255,8 @@ interface ParseOptions {
255
255
  postTransformTokens?: (tokens: Token[]) => Token[]
256
256
  // Custom HTML-like tags to emit as custom nodes (e.g. ['thinking'])
257
257
  customHtmlTags?: string[]
258
+ // Validate link href before emitting a `link` node; false -> plain text
259
+ validateLink?: (url: string) => boolean
258
260
  // When true, treats the input as complete (end-of-stream)
259
261
  final?: boolean
260
262
  // Require closing `**` for strong parsing (default: false)
@@ -279,6 +281,22 @@ const tagged = nodes.map(node =>
279
281
 
280
282
  Use the metadata in your renderer to show custom UI without mangling the original Markdown.
281
283
 
284
+ Example — enforce safe link protocols:
285
+
286
+ ```ts
287
+ const md = getMarkdown('safe-links')
288
+ md.set?.({
289
+ validateLink: (url: string) => !/^\s*javascript:/i.test(url.trim()),
290
+ })
291
+
292
+ const nodes = parseMarkdownToStructure(
293
+ '[ok](https://example.com) [bad](javascript:alert(1))',
294
+ md,
295
+ { final: true },
296
+ )
297
+ // "ok" stays a link node; "bad" is downgraded to plain text
298
+ ```
299
+
282
300
  ### Unknown HTML-like tags
283
301
 
284
302
  By default, non-standard HTML-like tags (for example `<question>`) are rendered as raw HTML elements once they are complete; during streaming, partial tags are kept as **literal text** to avoid flicker. If you want them emitted as custom nodes (`type: 'question'` with parsed attrs/content), opt in via `customHtmlTags`.
package/README.zh-CN.md CHANGED
@@ -226,7 +226,7 @@ interface GetMarkdownOptions {
226
226
 
227
227
  #### `parseInlineTokens(tokens, content?, preToken?, options?)`
228
228
 
229
- 解析内联 markdown-it-ts tokens 并产出节点。可传入原始 `content`(来自父 token)、可选的前一个 token,以及 inline 解析选项(`requireClosingStrong`、`customHtmlTags`)。
229
+ 解析内联 markdown-it-ts tokens 并产出节点。可传入原始 `content`(来自父 token)、可选的前一个 token,以及 inline 解析选项(`requireClosingStrong`、`customHtmlTags`、`validateLink`)。
230
230
 
231
231
  ### 配置函数
232
232
 
@@ -254,6 +254,8 @@ interface ParseOptions {
254
254
  postTransformTokens?: (tokens: Token[]) => Token[]
255
255
  // 自定义 HTML 类标签,作为自定义节点输出(如 ['thinking'])
256
256
  customHtmlTags?: string[]
257
+ // 输出 link 节点前校验 href;返回 false 时降级为纯文本
258
+ validateLink?: (url: string) => boolean
257
259
  // true 表示输入已结束(end-of-stream)
258
260
  final?: boolean
259
261
  // 解析 strong 时要求闭合 `**`(默认 false)
@@ -278,6 +280,22 @@ const tagged = nodes.map(node =>
278
280
 
279
281
  在渲染器中读取 `node.meta` 即可渲染自定义 UI,而无需直接修改 Markdown 文本。
280
282
 
283
+ 示例 —— 限制链接协议,拦截不安全链接:
284
+
285
+ ```ts
286
+ const md = getMarkdown('safe-links')
287
+ md.set?.({
288
+ validateLink: (url: string) => !/^\s*javascript:/i.test(url.trim()),
289
+ })
290
+
291
+ const nodes = parseMarkdownToStructure(
292
+ '[ok](https://example.com) [bad](javascript:alert(1))',
293
+ md,
294
+ { final: true },
295
+ )
296
+ // "ok" 保持为 link 节点;"bad" 会降级为纯文本
297
+ ```
298
+
281
299
  ### 未知 HTML 类标签
282
300
 
283
301
  默认情况下,非标准的 HTML 类标签(例如 `<question>`)在完整闭合时会按原生 HTML 渲染(作为自定义元素输出);流式场景下未闭合的片段会先按**纯文本**处理以避免闪烁。若希望它们作为自定义节点输出(`type: 'question'`,携带 attrs/content),需要在 `customHtmlTags` 中显式声明。
package/dist/index.d.ts CHANGED
@@ -336,6 +336,14 @@ interface ParseOptions {
336
336
  * to enable mid-state suppression for the same tags during streaming.
337
337
  */
338
338
  customHtmlTags?: string[];
339
+ /**
340
+ * If provided, link nodes are only emitted when this returns true for the href.
341
+ * When it returns false, the link is rendered as plain text (the link text only).
342
+ * Typically set from the MarkdownIt instance (e.g. md.options.validateLink or
343
+ * md.set({ validateLink })) so that unsafe URLs (e.g. javascript:) are not
344
+ * output as links.
345
+ */
346
+ validateLink?: (url: string) => boolean;
339
347
  debug?: boolean;
340
348
  }
341
349
  type PostTransformNodesHook = (nodes: ParsedNode[]) => ParsedNode[];
@@ -344,6 +352,7 @@ type PostTransformNodesHook = (nodes: ParsedNode[]) => ParsedNode[];
344
352
  declare function parseInlineTokens(tokens: MarkdownToken[], raw?: string, pPreToken?: MarkdownToken, options?: {
345
353
  requireClosingStrong?: boolean;
346
354
  customHtmlTags?: readonly string[];
355
+ validateLink?: (url: string) => boolean;
347
356
  }): ParsedNode[];
348
357
  //#endregion
349
358
  //#region src/parser/index.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/factory.ts","../src/types.ts","../src/parser/inline-parsers/index.ts","../src/parser/index.ts","../src/config.ts","../src/findMatchingClose.ts","../src/parser/inline-parsers/fence-parser.ts","../src/plugins/containers.ts","../src/plugins/isMathLike.ts","../src/plugins/math.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/factory.ts","../src/types.ts","../src/parser/inline-parsers/index.ts","../src/parser/index.ts","../src/config.ts","../src/findMatchingClose.ts","../src/parser/inline-parsers/fence-parser.ts","../src/plugins/containers.ts","../src/plugins/isMathLike.ts","../src/plugins/math.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;UAaiB,cAAA,SAAuB;sBAClB;;EADL,gBAAA,CAAe,EAAA,OAAA;;;;ECXf,CAAA;EAaL;AAEZ;AAMA;;EAKY,cAAA,CAAA,EAAA,SAAA,MAAA,EAAA;EALyB;;AAQrC;AAMA;EAMiB,0BAKR,CAAA,EAAA,OAAA;AAGT;;;UAjDiB,QAAA;;EDWA,GAAA,EAAA,MAAA;;;;ACXjB;AAaA;AAEA;AAMA;;;AAAqC,KARzB,WAAA,GAAc,QAQW,GARA,MAQA,CAAA,MAAA,EAAA,OAAA,CAAA;AAAQ,UAN5B,QAAA,SAAiB,QAMW,CAAA;EAQ5B,IAAA,EAAA,MAAA;EAMA,OAAA,EAAA,MAAW;EAMX,MAAA,CAAA,EAAA,OAAS;AAQ1B;AAKiB,UAjCA,WAAA,SAAoB,QAiCU,CAAA;EAiB9B,IAAA,EAAA,SAAA;EAOA,KAAA,EAAA,MAAA;EAYL,IAAA,EAAA,MAAA;EAYK,KAAA,CAAA,EA7EP,MA6EO,CAAA,MAAA,EAAoB,MAAA,GAAA,OAAA,CAAA;EAK3B,QAAA,EAjFE,UAiFF,EAAA;;AALmC,UAzE5B,aAAA,SAAsB,QAyEM,CAAA;EAAQ,IAAA,EAAA,WAAA;EAUpC,QAAA,EAjFL,UAiFoB,EAAA;EAKf,aAAS,CAAA,EAAA,OAKd;AAGZ;AAOiB,UAjGA,UAAA,SAAmB,QAiGO,CAAQ;EAIlC,IAAA,EAAA,QAAA;EASL,QAAA,EA5GA,UA4Gc,EAAA;EAST,OAAA,CAAA,EAAA,MAAA;AAKjB;AAEU,UAxHO,QAAA,SAAiB,QAwHxB,CAAA;EACF,IAAA,EAAA,MAAA;EAH2B,OAAA,EAAA,OAAA;EAAQ,KAAA,CAAA,EAAA,MAAA;EAM1B,KAAA,EAvHR,YAuHqB,EAAA;AAK9B;AAOiB,UAhIA,YAAA,SAAqB,QAkI7B,CAAA;EAGQ,IAAA,EAAA,WAAA;EAET,QAAA,EArII,UAqIJ,EAAA;;AAFoC,UAhI3B,aAAA,SAAsB,QAgIK,CAAA;EAAQ,IAAA,EAAA,YAAA;EAMnC,QAAA,EAAA,MAAa;EAMb,IAAA,EAAA,MAAA;EAKA,SAAA,CAAA,EAAA,MAAA;EAKA,OAAA,CAAA,EAAA,MAAA;EAOA,OAAA,CAAA,EAAA,OAAA;EAKP,IAAA,CAAA,EAAA,OAAA;EACE,YAAA,CAAA,EAAA,MAAA;EAN8B,WAAA,CAAA,EAAA,MAAA;EAAQ,GAAA,EAAA,MAAA;AASlD;AAKiB,UA1JA,aAAA,SAAsB,QA0JD,CAAA;EAKrB,IAAA,EAAA,YAAA;EAKA,KAAA,CAAA,EAAA,CAAA,MAAA,EAAc,MAAA,CAAA,EAAA,GAEnB,IAAA;EAGK,GAAA,EAAA,MAAA;EAKA,OAAA,EAAA,MAAA;AAKjB;AAKiB,UAjLA,cAAA,SAAuB,QAiLM,CAAA;EAK7B,IAAA,EAAA,aAAA;EAKA,GAAA,CAAA,EAAA,MAAU;EAMV,OAAA,EAAA,MAAA;EAIA,QAAA,EAjML,UAiMoB,EAAA;EAMf;AAMjB;AAMA;AAkBA;EAEY,UAAA,CAAA,EAAU,OAAA;;AAEhB,KAjOM,oBAAA,GAiON,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,GA/NA,MA+NA,CAAA,MAAA,EAAA,MAAA,GAAA,OAAA,CAAA,GA9NA,KA8NA,CAAA;EACA,IAAA,EAAA,MAAA;EACA,KAAA,EAAA,MAAA,GAAA,OAAA;CACA,CAAA,GAAA,IAAA;;;;;;;AAOA,UA/NW,mBAAA,SAA4B,QA+NvC,CAAA;EACA;EACA,IAAA,EAAA,MAAA;EACA,GAAA,EAAA,MAAA;EACA,OAAA,EAAA,MAAA;EACA,KAAA,CAAA,EA/NI,oBA+NJ;EACA,QAAA,CAAA,EA/NO,UA+NP,EAAA;EACA,UAAA,CAAA,EAAA,OAAA;;AAEA,UA9NW,cAAA,SAAuB,QA8NlC,CAAA;EACA,IAAA,EAAA,aAAA;EACA,IAAA,EAAA,MAAA;;AAEA,UA7NW,QAAA,SAAiB,QA6N5B,CAAA;EACA,IAAA,EAAA,MAAA;EACA,IAAA,EAAA,MAAA;EACA,KAAA,EAAA,MAAA,GAAA,IAAA;EACA,IAAA,EAAA,MAAA;EACA,QAAA,EA7NM,UA6NN,EAAA;;AAEA,UA5NW,SAAA,SAAkB,QA4N7B,CAAA;EACA,IAAA,EAAA,OAAA;EACA,GAAA,EAAA,MAAA;EACA,GAAA,EAAA,MAAA;EACA,KAAA,EAAA,MAAA,GAAA,IAAA;;AAEA,UA3NW,iBAAA,SAA0B,QA2NrC,CAAA;EAAW,IAAA,EAAA,gBAAA;AACjB;AAmCY,UA3PK,gBAAA,CA2Pc;EAEd,IAAA,EAAA;IA8BL,IAAA,EAAA,YAAA;;;;ECnVI,CAAA;;AAGF,KD8DF,cAAA,GC9DE;EAEX,OAAA,EAAA,MAAA;EAAU,KAAA,CAAA,EAAA,SAAA;;;SDmEF;AEmvBX,CAAA;AAEM,UFnvBW,cAAA,SAAuB,QEmvBlC,CAAA;EACK,IAAA,EAAA,YAAA;EACR,QAAA,EFnvBS,UEmvBT,EAAA;;AAuLa,UFv6BC,SAAA,SAAkB,QEu6BN,CAAA;EAAS,IAAA,EAAA,OAAA;EAA2B,MAAA,EFr6BvD,YEq6BuD;EAAe,IAAA,EFp6BxE,YEo6BwE,EAAA;;UFj6B/D,YAAA,SAAqB;;SAE7B;AGhKT;AAqBgB,UH8IC,aAAA,SAAsB,QG9IK,CAAA;;;YHiJhC;EI/KI,KAAA,CAAA,EAAA,MAAA,GAAA,OAAiB,GAAA,QAAA;;UJmLhB,kBAAA,SAA2B;;EK/I5B,KAAA,ELiJP,kBKjJsB,EAAA;;ULoJd,kBAAA,SAA2B;;EMvD5B,IAAA,ENyDR,UMzDQ,EAAe;cN0DjB;;UAGG,YAAA,SAAqB;EO9LzB,IAAA,EAAA,UAAA;EAoBA,EAAA,EAAA,MAAA;EA6BG,QAAA,EPgJJ,UOhJc,EAAA;;UPmJT,qBAAA,SAA8B;;EQnLlC,EAAA,EAAA,MAAA;AAyKb;AAmFgB,URpEC,kBAAA,SAA2B,QQoES,CAAA;;;;ACxPrC,UTyLC,cAAA,SAAuB,QSzLF,CAAA;EAItB,IAAA,EAAA,YAAA;EAwBC,IAAA,EAAA,MAAA;EACN,KAAA,EAAA,MAAA;EACU,QAAA,ET+JT,US/JS,EAAA;;AAKgB,UT6JpB,gBAAA,SAAyB,QS7JL,CAAA;EAPO,IAAA,EAAA,eAAA;EAAc,IAAA,EAAA,MAAA;EAU1C;;UT+JN;YACE;;UAGK,UAAA,SAAmB;;YAExB;;UAGK,YAAA,SAAqB;;YAE1B;;UAGK,iBAAA,SAA0B;;YAE/B;;UAGK,aAAA,SAAsB;;YAE3B;;UAGK,UAAA,SAAmB;;YAExB;;UAGK,aAAA,SAAsB;;YAE3B;;UAGK,eAAA,SAAwB;;YAE7B;;UAGK,YAAA,SAAqB;;;;UAKrB,iBAAA,SAA0B;;;;UAK1B,SAAA,SAAkB;;;;;UAMlB,aAAA,SAAsB;;;UAItB,cAAA,SAAuB;;;;;UAMvB,aAAA,SAAsB;;;;;UAMtB,aAAA,SAAsB;;;;UAMtB,iBAAA;;;;;;;;;;;;;aAaJ;;;;KAKD,aAAA,IAAiB;;;KAA+C;KAEhE,UAAA,GACN,WACA,cACA,gBACA,WACA,eACA,gBACA,iBACA,WACA,YACA,oBACA,iBACA,YACA,eACA,gBACA,aACA,eACA,oBACA,gBACA,aACA,gBACA,kBACA,eACA,oBACA,YACA,qBACA,qBACA,eACA,wBACA,iBACA,mBACA,gBACA,iBACA,gBACA,gBACA,gBACA,iBACA,sBACA;UACW,gBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmCL,mBAAA,YAA+B,oBAAoB;UAE9C,YAAA;uBACM;wBACC;;;;;;;;;;;;;;;;;;;;;;;;;KA4BZ,sBAAA,WAAiC,iBAAiB;;;iBCnV9C,iBAAA,SACN,2CAEI;EFxEG,oBAAe,CAAA,EAAA,OACV;;;IEyEnB;;;iBCszBa,wBAAA,uBAEV,wBACK,eACR;iBAuLa,aAAA,SAAsB,2BAA2B,eAAe;;;;;;AH3jChF;;;;ACXA;AAaA;AAEiB,UGRA,WAAA,CHQiB;EAMjB;EAIP,QAAA,CAAA,EAAA,SAAA,MAAA,EAAA;EACE;EALyB,iBAAA,CAAA,EAAA,OAAA;EAAQ;AAQ7C;AAMA;AAMA;AAQA;AAKA;AAiBA;AAOA;AAYA;AAYA;;EAMa,gBAAA,CAAA,EAAA,OAAA;;AANwC,iBG1ErC,qBAAA,CH0EqC,IAAA,EG1ET,WH0ES,GAAA,SAAA,CAAA,EAAA,IAAA;;;iBIxGrC,iBAAA;;;iBCoCA,eAAA,QAAuB,gBAAgB;;;iBC6FvC,eAAA,KAAoB;;;cCjIvB;cAoBA;iBA6BG,UAAA;;;cChCH;iBAyKG,6BAAA,mBAAgD;iBAmFhD,SAAA,KAAc,yBAAuB;;;AThQpC,iBUQD,sBAAA,CVR8B,MAAA,EAAA,OAAA,CAAA,EAAA,IAAA;iBUY9B,8BAAA,CAAA;ATMC,USkBA,kBAAA,SAA2B,cTlBG,CAAA;EAM9B,MAAA,CAAA,ESaN,KTbiB,CAAA,OAAA,CAAA;EAMX,KAAA,CAAA,ESQP,KTRgB,CAAA,CAAA,EAAA,ESQL,UTHZ,EAAA,GAAA,IALyB,CAAA;EAQjB;AAKjB;AAiBA;AAOA;EAYY,IAAA,CAAA,EAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAoB,MAAA,CAAA,GSpCK,MTsC/B,CAAA,MACA,EAAK,MAAA,CAAA;AASX;AAKU,iBSlDM,WAAA,CTkDN,KAAA,CAAA,EAAA,MAAA,EAAA,OAAA,CAAA,ESlDmE,kBTkDnE,CAAA,ESlD0F,UTkD1F"}
package/dist/index.js CHANGED
@@ -7708,6 +7708,9 @@ function applyFixHtmlInlineTokens(md, options = {}) {
7708
7708
  if (!t || t.type !== "inline") continue;
7709
7709
  if (t.children.length === 2 && t.children[0].type === "html_inline") {
7710
7710
  const tag = (t.children[0].content?.match(/<([^\s>/]+)/)?.[1] ?? "").toLowerCase();
7711
+ const second = t.children[1];
7712
+ const secondCloseTag = String(second?.content ?? "").match(/^<\s*\/\s*([^\s>]+)/)?.[1]?.toLowerCase() ?? "";
7713
+ if (second?.type === "html_inline" && secondCloseTag === tag) continue;
7711
7714
  if (autoCloseInlineTagSet.has(tag)) {
7712
7715
  t.children[0].loading = true;
7713
7716
  t.children[0].tag = tag;
@@ -9504,7 +9507,8 @@ function parseEmphasisToken(tokens, startIndex, options) {
9504
9507
  }
9505
9508
  children.push(...parseInlineTokens(innerTokens, void 0, void 0, {
9506
9509
  requireClosingStrong: options?.requireClosingStrong,
9507
- customHtmlTags: options?.customHtmlTags
9510
+ customHtmlTags: options?.customHtmlTags,
9511
+ validateLink: options?.validateLink
9508
9512
  }));
9509
9513
  return {
9510
9514
  node: {
@@ -10026,7 +10030,8 @@ function parseStrongToken(tokens, startIndex, raw, options) {
10026
10030
  }
10027
10031
  children.push(...parseInlineTokens(innerTokens, raw, void 0, {
10028
10032
  requireClosingStrong: options?.requireClosingStrong,
10029
- customHtmlTags: options?.customHtmlTags
10033
+ customHtmlTags: options?.customHtmlTags,
10034
+ validateLink: options?.validateLink
10030
10035
  }));
10031
10036
  return {
10032
10037
  node: {
@@ -10129,6 +10134,28 @@ function countUnescapedAsterisks(str) {
10129
10134
  }
10130
10135
  return count;
10131
10136
  }
10137
+ const WORD_CHAR_RE = /[\p{L}\p{N}]/u;
10138
+ const WORD_ONLY_RE = /^[\p{L}\p{N}]+$/u;
10139
+ function isWordChar(ch) {
10140
+ if (!ch) return false;
10141
+ return WORD_CHAR_RE.test(ch);
10142
+ }
10143
+ function isWordOnly(text$1) {
10144
+ if (!text$1) return false;
10145
+ return WORD_ONLY_RE.test(text$1);
10146
+ }
10147
+ function getAsteriskRunInfo(content, start) {
10148
+ let end = start;
10149
+ while (end < content.length && content[end] === "*") end++;
10150
+ const prev = start > 0 ? content[start - 1] : void 0;
10151
+ const next = end < content.length ? content[end] : void 0;
10152
+ return {
10153
+ len: end - start,
10154
+ prev,
10155
+ next,
10156
+ intraword: isWordChar(prev) && isWordChar(next)
10157
+ };
10158
+ }
10132
10159
  function parseInlineTokens(tokens, raw, pPreToken, options) {
10133
10160
  if (!tokens || tokens.length === 0) return [];
10134
10161
  const result = [];
@@ -10220,15 +10247,32 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
10220
10247
  return true;
10221
10248
  }
10222
10249
  }
10250
+ const runInfo = getAsteriskRunInfo(content, openIdx);
10223
10251
  const exec = STRONG_PAIR_RE.exec(content);
10224
10252
  let inner = "";
10225
10253
  let after = "";
10226
10254
  if (exec && typeof exec.index === "number") {
10227
10255
  inner = exec[1];
10228
10256
  after = content.slice(exec.index + exec[0].length);
10257
+ const closeRunInfo = getAsteriskRunInfo(content, exec.index + exec[0].length - 2);
10258
+ if (runInfo.intraword && closeRunInfo.intraword && !isWordOnly(inner)) {
10259
+ pushText(content.slice(beforeText.length), content.slice(beforeText.length));
10260
+ i++;
10261
+ return true;
10262
+ }
10263
+ if (!inner && runInfo.len >= 4 && runInfo.intraword) {
10264
+ pushText(content.slice(beforeText.length), content.slice(beforeText.length));
10265
+ i++;
10266
+ return true;
10267
+ }
10229
10268
  } else {
10230
10269
  if (requireClosingStrong) {
10231
- pushText(content, content);
10270
+ pushText(content.slice(beforeText.length), content.slice(beforeText.length));
10271
+ i++;
10272
+ return true;
10273
+ }
10274
+ if (runInfo.intraword) {
10275
+ pushText(content.slice(beforeText.length), content.slice(beforeText.length));
10232
10276
  i++;
10233
10277
  return true;
10234
10278
  }
@@ -10294,7 +10338,13 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
10294
10338
  };
10295
10339
  result.push(currentTextNode);
10296
10340
  }
10341
+ const runInfo = getAsteriskRunInfo(content, idx);
10297
10342
  const closeIndex = content.indexOf("*", idx + 1);
10343
+ if (closeIndex === -1 && runInfo.intraword) {
10344
+ pushText(content.slice(idx), content.slice(idx));
10345
+ i++;
10346
+ return true;
10347
+ }
10298
10348
  const { node } = parseEmphasisToken([
10299
10349
  {
10300
10350
  type: "em_open",
@@ -10590,7 +10640,11 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
10590
10640
  i++;
10591
10641
  break;
10592
10642
  default:
10593
- pushToken(token);
10643
+ if (token.type === "link" && token.href != null && options?.validateLink && !options.validateLink(token.href)) {
10644
+ resetCurrentTextNode();
10645
+ const displayText = String(token.text ?? "");
10646
+ pushText(displayText, displayText);
10647
+ } else pushToken(token);
10594
10648
  i++;
10595
10649
  break;
10596
10650
  }
@@ -10670,6 +10724,10 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
10670
10724
  resetCurrentTextNode();
10671
10725
  const { node, nextIndex } = parseLinkToken(tokens, i, { requireClosingStrong });
10672
10726
  i = nextIndex;
10727
+ if (options?.validateLink && !options.validateLink(node.href)) {
10728
+ pushText(node.text, node.text);
10729
+ return;
10730
+ }
10673
10731
  const hrefAttr = token.attrs?.find(([name]) => name === "href")?.[1];
10674
10732
  const hrefStr = String(hrefAttr ?? "");
10675
10733
  if (raw && hrefStr) {
@@ -10723,9 +10781,11 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
10723
10781
  loading$1 = false;
10724
10782
  } else if (last?.type === "text" && last.content === ".") i++;
10725
10783
  if (textNodeContent) pushText(textNodeContent, textNodeContent);
10726
- pushParsed({
10784
+ const hrefFromToken = String(textToken$1.content ?? "");
10785
+ if (options?.validateLink && !options.validateLink(hrefFromToken)) pushText(text$1, text$1);
10786
+ else pushParsed({
10727
10787
  type: "link",
10728
- href: String(textToken$1.content ?? ""),
10788
+ href: hrefFromToken,
10729
10789
  title: null,
10730
10790
  text: text$1,
10731
10791
  children: [{
@@ -10816,7 +10876,8 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
10816
10876
  const { node } = parseEmphasisToken(newTokens, 0, options);
10817
10877
  pushNode(node);
10818
10878
  }
10819
- } else pushParsed({
10879
+ } else if (options?.validateLink && !options.validateLink(href)) pushText(text$1, text$1);
10880
+ else pushParsed({
10820
10881
  type: "link",
10821
10882
  href,
10822
10883
  title: null,
@@ -10959,7 +11020,8 @@ function parseList(tokens, index, options) {
10959
11020
  type: "paragraph",
10960
11021
  children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), preToken, {
10961
11022
  requireClosingStrong: options?.requireClosingStrong,
10962
- customHtmlTags: options?.customHtmlTags
11023
+ customHtmlTags: options?.customHtmlTags,
11024
+ validateLink: options?.validateLink
10963
11025
  }),
10964
11026
  raw: String(contentToken.content ?? "")
10965
11027
  });
@@ -11016,7 +11078,8 @@ function parseAdmonition(tokens, index, match, options) {
11016
11078
  type: "paragraph",
11017
11079
  children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
11018
11080
  requireClosingStrong: options?.requireClosingStrong,
11019
- customHtmlTags: options?.customHtmlTags
11081
+ customHtmlTags: options?.customHtmlTags,
11082
+ validateLink: options?.validateLink
11020
11083
  }),
11021
11084
  raw: String(contentToken.content ?? "")
11022
11085
  });
@@ -11088,7 +11151,8 @@ function parseContainer(tokens, index, options) {
11088
11151
  type: "paragraph",
11089
11152
  children: parseInlineTokens(_children || [], void 0, void 0, {
11090
11153
  requireClosingStrong: options?.requireClosingStrong,
11091
- customHtmlTags: options?.customHtmlTags
11154
+ customHtmlTags: options?.customHtmlTags,
11155
+ validateLink: options?.validateLink
11092
11156
  }),
11093
11157
  raw: String(contentToken.content ?? "").replace(/\n:+$/, "").replace(/\n\s*:::\s*$/, "")
11094
11158
  });
@@ -11145,7 +11209,8 @@ function parseBlockquote(tokens, index, options) {
11145
11209
  type: "paragraph",
11146
11210
  children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
11147
11211
  requireClosingStrong: options?.requireClosingStrong,
11148
- customHtmlTags: options?.customHtmlTags
11212
+ customHtmlTags: options?.customHtmlTags,
11213
+ validateLink: options?.validateLink
11149
11214
  }),
11150
11215
  raw: String(contentToken.content ?? "")
11151
11216
  });
@@ -11209,7 +11274,8 @@ function parseDefinitionList(tokens, index, options) {
11209
11274
  const termToken = tokens[j + 1];
11210
11275
  termNodes = parseInlineTokens(termToken.children || [], void 0, void 0, {
11211
11276
  requireClosingStrong: options?.requireClosingStrong,
11212
- customHtmlTags: options?.customHtmlTags
11277
+ customHtmlTags: options?.customHtmlTags,
11278
+ validateLink: options?.validateLink
11213
11279
  });
11214
11280
  j += 3;
11215
11281
  } else if (tokens[j].type === "dd_open") {
@@ -11221,7 +11287,8 @@ function parseDefinitionList(tokens, index, options) {
11221
11287
  type: "paragraph",
11222
11288
  children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
11223
11289
  requireClosingStrong: options?.requireClosingStrong,
11224
- customHtmlTags: options?.customHtmlTags
11290
+ customHtmlTags: options?.customHtmlTags,
11291
+ validateLink: options?.validateLink
11225
11292
  }),
11226
11293
  raw: String(contentToken.content ?? "")
11227
11294
  });
@@ -11260,7 +11327,8 @@ function parseFootnote(tokens, index, options) {
11260
11327
  type: "paragraph",
11261
11328
  children: parseInlineTokens(contentToken.children || [], String(contentToken.content ?? ""), void 0, {
11262
11329
  requireClosingStrong: options?.requireClosingStrong,
11263
- customHtmlTags: options?.customHtmlTags
11330
+ customHtmlTags: options?.customHtmlTags,
11331
+ validateLink: options?.validateLink
11264
11332
  }),
11265
11333
  raw: String(contentToken.content ?? "")
11266
11334
  });
@@ -11291,7 +11359,8 @@ function parseHeading(tokens, index, options) {
11291
11359
  ...attrsRecord ? { attrs: attrsRecord } : {},
11292
11360
  children: parseInlineTokens(headingContentToken.children || [], headingContent, void 0, {
11293
11361
  requireClosingStrong: options?.requireClosingStrong,
11294
- customHtmlTags: options?.customHtmlTags
11362
+ customHtmlTags: options?.customHtmlTags,
11363
+ validateLink: options?.validateLink
11295
11364
  }),
11296
11365
  raw: headingContent
11297
11366
  };
@@ -11406,7 +11475,8 @@ function parseTable(tokens, index, options) {
11406
11475
  header: isHeaderCell || isHeader,
11407
11476
  children: parseInlineTokens(contentToken.children || [], content, void 0, {
11408
11477
  requireClosingStrong: options?.requireClosingStrong,
11409
- customHtmlTags: options?.customHtmlTags
11478
+ customHtmlTags: options?.customHtmlTags,
11479
+ validateLink: options?.validateLink
11410
11480
  }),
11411
11481
  raw: content,
11412
11482
  align
@@ -11506,7 +11576,8 @@ function parseVmrContainer(tokens, index, options) {
11506
11576
  type: "paragraph",
11507
11577
  children: parseInlineTokens(childrenArr || [], void 0, void 0, {
11508
11578
  requireClosingStrong: options?.requireClosingStrong,
11509
- customHtmlTags: options?.customHtmlTags
11579
+ customHtmlTags: options?.customHtmlTags,
11580
+ validateLink: options?.validateLink
11510
11581
  }),
11511
11582
  raw: String(contentToken.content ?? "")
11512
11583
  });
@@ -11769,7 +11840,8 @@ function parseParagraph(tokens, index, options) {
11769
11840
  type: "paragraph",
11770
11841
  children: parseInlineTokens(paragraphContentToken.children || [], paragraphContent, void 0, {
11771
11842
  requireClosingStrong: options?.requireClosingStrong,
11772
- customHtmlTags: options?.customHtmlTags
11843
+ customHtmlTags: options?.customHtmlTags,
11844
+ validateLink: options?.validateLink
11773
11845
  }),
11774
11846
  raw: paragraphContent
11775
11847
  };
@@ -12174,7 +12246,16 @@ function ensureBlankLineAfterCustomHtmlCloseBeforeBlockMarkerSameLine(markdown,
12174
12246
  fenceLen = fenceMatch.markerLen;
12175
12247
  }
12176
12248
  let nextContent = contentLine;
12177
- if (!inFence && nextContent.includes("</")) for (const re of closeTagRes) nextContent = nextContent.replace(re, "$1\n\n");
12249
+ if (!inFence && nextContent.includes("</")) for (const re of closeTagRes) nextContent = nextContent.replace(re, (match, closeTag, offset, src) => {
12250
+ if (src.replace(/^[\t ]+/, "").startsWith("|")) return match;
12251
+ const before = src.slice(0, offset).replace(/^[\t ]+/, "");
12252
+ if (before.length > 0) {
12253
+ const closeTagName = closeTag.match(/^<\s*\/\s*([A-Za-z][\w:-]*)/i)?.[1]?.toLowerCase() ?? "";
12254
+ const openTagName = before.match(/^<\s*([A-Za-z][\w:-]*)/i)?.[1]?.toLowerCase() ?? "";
12255
+ if (!closeTagName || !openTagName || closeTagName !== openTagName) return match;
12256
+ }
12257
+ return `${closeTag}\n\n`;
12258
+ });
12178
12259
  if (prefix) {
12179
12260
  const withPrefix = prefix + nextContent.split("\n").join(`\n${prefix}`);
12180
12261
  out += withPrefix;
@@ -12431,8 +12512,11 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
12431
12512
  const post = options.postTransformTokens;
12432
12513
  let transformedTokens = tokens;
12433
12514
  if (pre && typeof pre === "function") transformedTokens = pre(transformedTokens) || transformedTokens;
12515
+ const mdAny = md;
12516
+ const validateLink$1 = options.validateLink ?? mdAny.options?.validateLink ?? (typeof mdAny.validateLink === "function" ? mdAny.validateLink : void 0);
12434
12517
  const internalOptions = {
12435
12518
  ...options,
12519
+ validateLink: validateLink$1,
12436
12520
  __sourceMarkdown: safeMarkdown,
12437
12521
  __customHtmlBlockCursor: 0
12438
12522
  };
@@ -12512,7 +12596,8 @@ function processTokens(tokens, options) {
12512
12596
  {
12513
12597
  const parsed = parseInlineTokens(token.children || [], String(token.content ?? ""), void 0, {
12514
12598
  requireClosingStrong: options?.requireClosingStrong,
12515
- customHtmlTags: options?.customHtmlTags
12599
+ customHtmlTags: options?.customHtmlTags,
12600
+ validateLink: options?.validateLink
12516
12601
  });
12517
12602
  if (parsed.length === 0) {} else if (parsed.every((n) => n.type === "html_block")) result.push(...parsed);
12518
12603
  else result.push({