@tanstack/markdown 0.0.14 → 0.0.15

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
@@ -20,10 +20,10 @@
20
20
 
21
21
  A tiny, fast, deterministic Markdown parser and renderer for blogs and documentation.
22
22
 
23
- - 4.9 KB gzip parser
24
- - 6.7 KB gzip HTML renderer
25
- - 6.6 KB gzip React adapter
26
- - 6.6 KB gzip Octane adapter
23
+ - 5.0 KB gzip parser
24
+ - 6.8 KB gzip HTML renderer
25
+ - 6.7 KB gzip React adapter
26
+ - 6.7 KB gzip Octane adapter
27
27
  - zero runtime dependencies
28
28
  - serializable AST
29
29
  - safe defaults for raw HTML and executable URLs
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAyD,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAG7K,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAGpF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CA0ChF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CA0BlF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAE9F"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAA8E,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAGlM,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAGpF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CA0ChF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CA4BlF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAE9F"}
package/dist/html.js CHANGED
@@ -72,6 +72,8 @@ export function renderInline(node, options = {}) {
72
72
  return '<br>';
73
73
  case 'inlineHtml':
74
74
  return options.allowHtml ? node.value : escapeHtml(node.value);
75
+ case 'inlineComponent':
76
+ return renderComponent(node, options);
75
77
  }
76
78
  }
77
79
  export function renderDocument(document, options = {}) {
@@ -83,10 +85,12 @@ function renderInlines(nodes, options) {
83
85
  function renderCodeBlock(node, options) {
84
86
  const lang = node.lang ?? 'plaintext';
85
87
  const preAttrs = `class="tm-code${options.codeLineNumbers ? ' tm-code--line-numbers' : ''}" data-lang="${escapeAttr(lang)}"`
88
+ + (node.meta ? ` data-meta="${escapeAttr(node.meta)}"` : '')
86
89
  + (node.title ? ` data-code-title="${escapeAttr(node.title)}"` : '')
87
90
  + (node.file ? ` data-filename="${escapeAttr(node.file)}"` : '')
88
91
  + (node.framework ? ` data-framework="${escapeAttr(node.framework)}"` : '');
89
92
  const html = options.highlighter?.(node.value, lang, {
93
+ ...(node.meta && { meta: node.meta }),
90
94
  ...(node.highlightLines && { highlightLines: node.highlightLines }),
91
95
  ...(options.codeLineNumbers !== undefined && { lineNumbers: options.codeLineNumbers }),
92
96
  }) ?? escapeHtml(node.value);
@@ -142,9 +146,11 @@ function renderFootnoteBackrefs(item) {
142
146
  return result;
143
147
  }
144
148
  function renderComponent(node, options) {
145
- const tag = node.tagName ?? 'md-comment-component';
149
+ const tag = node.tagName ?? (node.type === 'inlineComponent' ? 'span' : 'md-comment-component');
146
150
  const attrs = renderComponentAttrs(node);
147
- const children = node.children.map(child => renderBlock(child, options)).join('\n');
151
+ const children = node.type === 'inlineComponent'
152
+ ? renderInlines(node.children, options)
153
+ : node.children.map(child => renderBlock(child, options)).join('\n');
148
154
  return `<${tag}${attrs}>${children}</${tag}>`;
149
155
  }
150
156
  function renderTableCell(tag, cell, align, options) {
package/dist/inline.js CHANGED
@@ -70,8 +70,9 @@ function parseInlineRaw(value, options, budget = { scans: Math.max(value.length
70
70
  const links = budget.links;
71
71
  const children = parseInlineRaw(parsed.label, image ? (options.references ? { references: options.references } : {}) : options, budget);
72
72
  const nested = !image && budget.links !== links;
73
- const href = sanitizeUrl(parsed.href);
74
- if (image || (!nested && (href || !parsed.href))) {
73
+ const defaultUrl = sanitizeUrl(parsed.href);
74
+ const href = options.urlTransform ? options.urlTransform(parsed.href, image ? 'image' : 'link', defaultUrl) : defaultUrl;
75
+ if (href !== null && (image || (!nested && (href || !parsed.href)))) {
75
76
  pushText();
76
77
  nodes.push({
77
78
  ...(image ? { type: 'image', src: href, alt: plainText(children) } : { type: 'link', href, children }),
@@ -1 +1 @@
1
- {"version":3,"file":"octane.d.ts","sourceRoot":"","sources":["../src/octane.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAG1E,OAAO,KAAK,EAAE,SAAS,EAAmC,UAAU,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAErI,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAExE,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,UAAU,CAAC,EAAE,YAAY,CAAA;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,qBAAqB;IAC1D,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,aAAa,GAAG,iBAAiB,CAEnF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,qBAA0B,GAAG,UAAU,EAAE,CAG5G;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,qBAA0B,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,iBAAiB,CA+DvH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,qBAA0B,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAwClH"}
1
+ {"version":3,"file":"octane.d.ts","sourceRoot":"","sources":["../src/octane.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAG1E,OAAO,KAAK,EAAE,SAAS,EAAwD,UAAU,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAE1J,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAExE,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,UAAU,CAAC,EAAE,YAAY,CAAA;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,qBAAqB;IAC1D,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,aAAa,GAAG,iBAAiB,CAEnF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,qBAA0B,GAAG,UAAU,EAAE,CAG5G;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,qBAA0B,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,iBAAiB,CA+DvH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,qBAA0B,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CA0ClH"}
package/dist/octane.js CHANGED
@@ -69,6 +69,8 @@ export function renderInlineOctane(node, options = {}, key) {
69
69
  return options.allowHtml
70
70
  ? h(options, 'span', { key, dangerouslySetInnerHTML: { __html: node.value } })
71
71
  : node.value;
72
+ case 'inlineComponent':
73
+ return renderComponentOctane(node, options, key);
72
74
  }
73
75
  }
74
76
  function renderInlines(nodes, options) {
@@ -82,6 +84,7 @@ function renderCodeBlockOctane(node, options, key) {
82
84
  ? {
83
85
  dangerouslySetInnerHTML: {
84
86
  __html: highlighter(node.value, lang, {
87
+ ...(node.meta && { meta: node.meta }),
85
88
  ...(node.highlightLines && { highlightLines: node.highlightLines }),
86
89
  ...(options.codeLineNumbers !== undefined && { lineNumbers: options.codeLineNumbers }),
87
90
  }),
@@ -91,6 +94,7 @@ function renderCodeBlockOctane(node, options, key) {
91
94
  const pre = h(options, 'pre', {
92
95
  className: `tm-code${options.codeLineNumbers ? ' tm-code--line-numbers' : ''}`,
93
96
  'data-lang': lang,
97
+ ...(node.meta ? { 'data-meta': node.meta } : {}),
94
98
  ...(node.title ? { 'data-code-title': node.title } : {}),
95
99
  ...(node.file ? { 'data-filename': node.file } : {}),
96
100
  ...(node.framework ? { 'data-framework': node.framework } : {}),
@@ -164,7 +168,7 @@ function h(options, tag, props, ...children) {
164
168
  return createElement(component, props ?? undefined, ...children);
165
169
  }
166
170
  function renderComponentOctane(node, options, key) {
167
- const tag = node.tagName ?? 'md-comment-component';
171
+ const tag = node.tagName ?? (node.type === 'inlineComponent' ? 'span' : 'md-comment-component');
168
172
  const props = {
169
173
  ...(node.properties ?? {}),
170
174
  };
@@ -173,7 +177,9 @@ function renderComponentOctane(node, options, key) {
173
177
  if (!props['data-attributes'])
174
178
  props['data-attributes'] = JSON.stringify(node.attributes);
175
179
  }
176
- return h(options, tag, { key, ...props }, node.children.map((child, index) => renderBlockOctane(child, options, `${key}:${index}`)));
180
+ return h(options, tag, { key, ...props }, node.type === 'inlineComponent'
181
+ ? renderInlines(node.children, options)
182
+ : node.children.map((child, index) => renderBlockOctane(child, options, `${key}:${index}`)));
177
183
  }
178
184
  function renderHeadingAnchorOctane(id, options) {
179
185
  if (!id || !options.headingAnchors)
package/dist/parser.js CHANGED
@@ -22,12 +22,12 @@ export function parseMarkdown(markdown, options = {}) {
22
22
  const parseOptions = hasReferences || hasFootnotes
23
23
  ? {
24
24
  ...options,
25
- ...(hasReferences ? { references: definitions.references } : {}),
26
- ...(hasFootnotes ? { footnotes: definitions.footnotes, footnoteOrder, footnoteCounts } : {}),
25
+ ...(hasReferences && { references: definitions.references }),
26
+ ...(hasFootnotes && { footnotes: definitions.footnotes, footnoteOrder, footnoteCounts }),
27
27
  }
28
28
  : options;
29
29
  const slugger = createSlugger();
30
- const parser = new BlockParser(lines, parseOptions, slugger);
30
+ const parser = createBlockParser(lines, parseOptions, slugger);
31
31
  const children = parser.parse();
32
32
  if (hasFootnotes && footnoteOrder.length > 0) {
33
33
  children.push(createFootnotesBlock(definitions.footnotes, footnoteOrder, parseOptions, slugger));
@@ -38,89 +38,86 @@ export function parseMarkdown(markdown, options = {}) {
38
38
  }
39
39
  return document;
40
40
  }
41
- class BlockParser {
42
- lines;
43
- options;
44
- slugger;
45
- budget;
46
- index = 0;
47
- loose = false;
48
- constructor(lines, options, slugger, budget = { depth: 0 }) {
49
- this.lines = lines;
50
- this.options = options;
51
- this.slugger = slugger;
52
- this.budget = budget;
53
- }
54
- parse() {
55
- if (this.budget.depth >= maxBlockDepth) {
56
- const value = this.lines.slice(this.index).join('\n');
57
- this.index = this.lines.length;
58
- return value ? [{ type: 'paragraph', children: parseInline(value, this.options) }] : [];
41
+ function createBlockParser(inputLines, options, slugger, budget = { depth: 0 }) {
42
+ let cursor = 0;
43
+ let looseBlocks = false;
44
+ return {
45
+ parse,
46
+ get loose() {
47
+ return looseBlocks;
48
+ },
49
+ };
50
+ function parse() {
51
+ if (budget.depth >= maxBlockDepth) {
52
+ const value = inputLines.slice(cursor).join('\n');
53
+ cursor = inputLines.length;
54
+ return value ? [{ type: 'paragraph', children: parseInline(value, options) }] : [];
59
55
  }
60
- this.budget.depth++;
56
+ budget.depth++;
61
57
  const nodes = [];
62
- while (this.index < this.lines.length) {
63
- if (isBlank(this.current())) {
58
+ while (cursor < inputLines.length) {
59
+ if (isBlank(current())) {
64
60
  if (nodes.length)
65
- this.loose = true;
66
- this.index++;
61
+ looseBlocks = true;
62
+ cursor++;
67
63
  continue;
68
64
  }
69
- const extensionNode = this.parseExtensionBlock();
65
+ const extensionNode = parseExtensionBlock();
70
66
  if (extensionNode) {
71
67
  nodes.push(extensionNode);
72
68
  continue;
73
69
  }
74
- const node = this.parseFence() ??
75
- this.parseHeading() ??
76
- this.parseThematicBreak() ??
77
- this.parseBlockquote() ??
78
- this.parseList() ??
79
- this.parseTable() ??
80
- this.parseHtmlBlock() ??
81
- this.parseParagraph();
70
+ // Letter-led text cannot open a fence, heading, rule, quote, or list.
71
+ // It can still be a table header, so table detection remains below.
72
+ const node = (/^[a-z]/i.test(current()) ? undefined : (parseFence() ??
73
+ parseHeading() ??
74
+ parseThematicBreak() ??
75
+ parseBlockquote() ??
76
+ parseList())) ??
77
+ parseTable() ??
78
+ parseHtmlBlock() ??
79
+ parseParagraph();
82
80
  nodes.push(node);
83
81
  }
84
- this.budget.depth--;
82
+ budget.depth--;
85
83
  return nodes;
86
84
  }
87
- parseExtensionBlock() {
88
- for (const extension of this.options.extensions ?? []) {
85
+ function parseExtensionBlock() {
86
+ for (const extension of options.extensions ?? []) {
89
87
  let consumed = 0;
90
88
  const node = extension.parseBlock?.({
91
- lines: this.lines,
92
- index: this.index,
93
- options: this.options,
94
- parseInline: value => parseInline(value, this.options),
95
- parseBlocks: value => new BlockParser(normalizeInput(value).split('\n'), this.options, this.slugger, this.budget).parse(),
89
+ lines: inputLines,
90
+ index: cursor,
91
+ options: options,
92
+ parseInline: value => parseInline(value, options),
93
+ parseBlocks: value => createBlockParser(normalizeInput(value).split('\n'), options, slugger, budget).parse(),
96
94
  consume: lines => {
97
95
  consumed = lines;
98
96
  },
99
97
  });
100
98
  if (node) {
101
- this.index += Math.max(consumed, 1);
99
+ cursor += Math.max(consumed, 1);
102
100
  return node;
103
101
  }
104
102
  }
105
103
  return undefined;
106
104
  }
107
- parseFence() {
108
- const match = this.current().match(/^( {0,3})(`{3,}|~{3,})(.*)$/);
105
+ function parseFence() {
106
+ const match = current().match(/^( {0,3})(`{3,}|~{3,})(.*)$/);
109
107
  if (!match)
110
108
  return undefined;
111
109
  const fence = match[2];
112
110
  const info = match[3].trim();
113
111
  const code = [];
114
- this.index++;
115
- while (this.index < this.lines.length) {
116
- const line = this.current();
117
- const close = line.match(/^ {0,3}(`{3,}|~{3,})\s*$/);
118
- if (close?.[1].startsWith(fence)) {
119
- this.index++;
112
+ cursor++;
113
+ while (cursor < inputLines.length) {
114
+ const line = current();
115
+ if (line.includes(fence) && /^ {0,3}(?:`+|~+)\s*$/.test(line)) {
116
+ cursor++;
120
117
  break;
121
118
  }
122
119
  code.push(stripIndent(line, match[1].length));
123
- this.index++;
120
+ cursor++;
124
121
  }
125
122
  return {
126
123
  type: 'code',
@@ -128,54 +125,54 @@ class BlockParser {
128
125
  ...parseCodeInfo(info),
129
126
  };
130
127
  }
131
- parseHeading() {
132
- const match = this.current().match(/^ {0,3}(#{1,6})(?:[ \t]+(.*)|[ \t]*)$/);
128
+ function parseHeading() {
129
+ const match = current().match(/^ {0,3}(#{1,6})(?:[ \t]+(.*)|[ \t]*)$/);
133
130
  if (!match)
134
131
  return undefined;
135
132
  const depth = match[1].length;
136
133
  const rawValue = match[2] ?? '';
137
134
  const value = (/^#+[ \t]*$/.test(rawValue) ? '' : rawValue.replace(/[ \t]+#+[ \t]*$/, '')).trim();
138
- const children = parseInline(value, this.options);
139
- const id = this.createHeadingId(children);
140
- this.index++;
135
+ const children = parseInline(value, options);
136
+ const id = createHeadingId(children);
137
+ cursor++;
141
138
  return id ? { type: 'heading', depth, id, children } : { type: 'heading', depth, children };
142
139
  }
143
- parseThematicBreak() {
144
- if (!/^ {0,3}([-*_])(?:\s*\1){2,}\s*$/.test(this.current()))
140
+ function parseThematicBreak() {
141
+ if (!/^ {0,3}([-*_])(?:\s*\1){2,}\s*$/.test(current()))
145
142
  return undefined;
146
- this.index++;
143
+ cursor++;
147
144
  return { type: 'thematicBreak' };
148
145
  }
149
- parseBlockquote() {
150
- if (!/^ {0,3}>\s?/.test(this.current()))
146
+ function parseBlockquote() {
147
+ if (!/^ {0,3}>\s?/.test(current()))
151
148
  return undefined;
152
149
  const quoted = [];
153
- while (this.index < this.lines.length) {
154
- const line = this.current();
150
+ while (cursor < inputLines.length) {
151
+ const line = current();
155
152
  const match = line.match(/^ {0,3}>\s?(.*)$/);
156
153
  if (!match) {
157
154
  if (!isBlank(line))
158
155
  break;
159
- this.loose = true;
156
+ looseBlocks = true;
160
157
  }
161
158
  quoted.push(match?.[1] ?? '');
162
- this.index++;
159
+ cursor++;
163
160
  }
164
161
  return {
165
162
  type: 'blockquote',
166
- children: new BlockParser(quoted, this.options, this.slugger, this.budget).parse(),
163
+ children: createBlockParser(quoted, options, slugger, budget).parse(),
167
164
  };
168
165
  }
169
- parseList() {
170
- const first = listMarker(this.current());
166
+ function parseList() {
167
+ const first = listMarker(current());
171
168
  if (!first)
172
169
  return undefined;
173
170
  const items = [];
174
171
  const ordered = first.ordered;
175
172
  const baseIndent = first.indent;
176
173
  let loose = false;
177
- while (this.index < this.lines.length) {
178
- const marker = listMarker(this.current());
174
+ while (cursor < inputLines.length) {
175
+ const marker = listMarker(current());
179
176
  if (!marker || marker.marker !== first.marker || marker.indent !== baseIndent)
180
177
  break;
181
178
  let firstLine = marker.content;
@@ -184,17 +181,17 @@ class BlockParser {
184
181
  if (task)
185
182
  firstLine = task[2];
186
183
  const itemLines = [firstLine];
187
- this.index++;
188
- while (this.index < this.lines.length) {
189
- const line = this.current();
184
+ cursor++;
185
+ while (cursor < inputLines.length) {
186
+ const line = current();
190
187
  const nextMarker = listMarker(line);
191
188
  if (nextMarker && nextMarker.indent === baseIndent)
192
189
  break;
193
190
  if (isBlank(line)) {
194
- let nextIndex = this.index;
195
- while (nextIndex < this.lines.length && isBlank(this.lines[nextIndex]))
191
+ let nextIndex = cursor;
192
+ while (nextIndex < inputLines.length && isBlank(inputLines[nextIndex]))
196
193
  nextIndex++;
197
- const following = this.lines[nextIndex];
194
+ const following = inputLines[nextIndex];
198
195
  if (following === undefined)
199
196
  break;
200
197
  const followingMarker = listMarker(following);
@@ -202,26 +199,26 @@ class BlockParser {
202
199
  if (followingMarker.marker !== first.marker)
203
200
  break;
204
201
  loose = true;
205
- this.index = nextIndex;
202
+ cursor = nextIndex;
206
203
  break;
207
204
  }
208
205
  if (leadingSpaces(following) < marker.contentIndent)
209
206
  break;
210
- while (this.index < nextIndex)
211
- itemLines.push(stripIndent(this.lines[this.index++], marker.contentIndent));
207
+ while (cursor < nextIndex)
208
+ itemLines.push(stripIndent(inputLines[cursor++], marker.contentIndent));
212
209
  continue;
213
210
  }
214
211
  if (leadingSpaces(line) >= marker.contentIndent) {
215
212
  itemLines.push(stripIndent(line, marker.contentIndent));
216
- this.index++;
213
+ cursor++;
217
214
  continue;
218
215
  }
219
- if (isBlockStart(line, this.next()))
216
+ if (isBlockStart(line, next()))
220
217
  break;
221
218
  itemLines.push(line.trimStart());
222
- this.index++;
219
+ cursor++;
223
220
  }
224
- const parser = new BlockParser(itemLines, this.options, this.slugger, this.budget);
221
+ const parser = createBlockParser(itemLines, options, slugger, budget);
225
222
  const children = parser.parse();
226
223
  loose ||= parser.loose;
227
224
  const item = { type: 'listItem', children };
@@ -237,100 +234,96 @@ class BlockParser {
237
234
  items,
238
235
  };
239
236
  }
240
- parseTable() {
241
- const header = this.current();
242
- const delimiter = this.next();
237
+ function parseTable() {
238
+ const header = current();
239
+ const delimiter = next();
243
240
  if (!delimiter || !looksLikeTableHeader(header, delimiter))
244
241
  return undefined;
245
242
  const headerCells = splitTableRow(header);
246
243
  const align = splitTableRow(delimiter).map(parseAlign);
247
244
  const columns = headerCells.length;
248
245
  const rows = [];
249
- this.index += 2;
250
- while (this.index < this.lines.length) {
251
- const line = this.current();
252
- if (isBlank(line) || isBlockStart(line, this.next()))
246
+ cursor += 2;
247
+ while (cursor < inputLines.length) {
248
+ const line = current();
249
+ if (isBlank(line) || isBlockStart(line, next()))
253
250
  break;
254
251
  const values = splitTableRow(line);
255
- rows.push(Array.from({ length: columns }, (_, index) => cell(values[index] ?? '', this.options)));
256
- this.index++;
252
+ rows.push(Array.from({ length: columns }, (_, index) => cell(values[index] ?? '', options)));
253
+ cursor++;
257
254
  }
258
255
  return {
259
256
  type: 'table',
260
257
  align,
261
- header: headerCells.map(value => cell(value, this.options)),
258
+ header: headerCells.map(value => cell(value, options)),
262
259
  rows,
263
260
  };
264
261
  }
265
- parseHtmlBlock() {
266
- if (!this.options.allowHtml || !/^ {0,3}<([A-Za-z][\w:-]*|!--|\/[A-Za-z])/.test(this.current()))
262
+ function parseHtmlBlock() {
263
+ if (!options.allowHtml || !/^ {0,3}<([A-Za-z][\w:-]*|!--|\/[A-Za-z])/.test(current()))
267
264
  return undefined;
268
265
  const html = [];
269
- if (/^ {0,3}<!--/.test(this.current())) {
270
- while (this.index < this.lines.length) {
271
- const line = this.current();
266
+ if (/^ {0,3}<!--/.test(current())) {
267
+ while (cursor < inputLines.length) {
268
+ const line = current();
272
269
  html.push(line);
273
- this.index++;
270
+ cursor++;
274
271
  if (line.includes('-->'))
275
272
  break;
276
273
  }
277
274
  return { type: 'html', value: html.join('\n') };
278
275
  }
279
- while (this.index < this.lines.length && !isBlank(this.current())) {
280
- html.push(this.current());
281
- this.index++;
276
+ while (cursor < inputLines.length && !isBlank(current())) {
277
+ html.push(current());
278
+ cursor++;
282
279
  }
283
280
  return { type: 'html', value: html.join('\n') };
284
281
  }
285
- parseParagraph() {
282
+ function parseParagraph() {
286
283
  const lines = [];
287
- while (this.index < this.lines.length) {
288
- const line = this.current();
284
+ while (cursor < inputLines.length) {
285
+ const line = current();
289
286
  if (isBlank(line))
290
287
  break;
291
- if (lines.length > 0 && isBlockStart(line, this.next()))
288
+ if (lines.length > 0 && isBlockStart(line, next()))
292
289
  break;
293
290
  lines.push(line.trim());
294
- this.index++;
291
+ cursor++;
295
292
  }
296
293
  return {
297
294
  type: 'paragraph',
298
- children: parseInline(lines.join('\n'), this.options),
295
+ children: parseInline(lines.join('\n'), options),
299
296
  };
300
297
  }
301
- createHeadingId(children) {
302
- if (this.options.headingIds === false)
298
+ function createHeadingId(children) {
299
+ if (options.headingIds === false)
303
300
  return undefined;
304
301
  const text = plainText(children);
305
- if (typeof this.options.headingIds === 'function')
306
- return this.options.headingIds(text, this.index);
307
- return this.slugger(text);
302
+ if (typeof options.headingIds === 'function')
303
+ return options.headingIds(text, cursor);
304
+ return slugger(text);
308
305
  }
309
- current() {
310
- return this.lines[this.index] ?? '';
306
+ function current() {
307
+ return inputLines[cursor] ?? '';
311
308
  }
312
- next() {
313
- return this.lines[this.index + 1];
309
+ function next() {
310
+ return inputLines[cursor + 1];
314
311
  }
315
312
  }
316
313
  function parseCodeInfo(info) {
317
- if (!info)
318
- return {};
319
314
  const langMatch = info.match(/^([A-Za-z0-9_+.#-]+)/);
320
315
  const lang = langMatch?.[1];
321
316
  const meta = lang ? info.slice(lang.length).trim() : info;
322
- const titleMatch = meta.match(/(?:^|\s)(?:title|file)=(?:"([^"]+)"|'([^']+)'|([^\s}]+))/);
323
- const frameworkMatch = meta.match(/(?:^|\s)framework=(?:"([^"]+)"|'([^']+)'|([^\s}]+))/);
317
+ const title = meta.match(/(?:^|\s)(?:title|file)=(?:"([^"]+)"|'([^']+)'|([^\s}]+))/)?.slice(1).find(Boolean);
318
+ const framework = meta.match(/(?:^|\s)framework=(?:"([^"]+)"|'([^']+)'|([^\s}]+))/)?.slice(1).find(Boolean);
324
319
  const rangeMatch = meta.match(/\{([^}]+)\}|(?:^|\s)lines=([^\s]+)/);
325
320
  const highlightLines = rangeMatch ? parseLineRanges(rangeMatch[1] ?? rangeMatch[2]) : [];
326
- const title = titleMatch ? titleMatch[1] ?? titleMatch[2] ?? titleMatch[3] : undefined;
327
- const framework = frameworkMatch ? frameworkMatch[1] ?? frameworkMatch[2] ?? frameworkMatch[3] : undefined;
328
321
  return {
329
- ...(lang ? { lang } : {}),
330
- ...(meta ? { meta } : {}),
331
- ...(title ? { title, file: title } : {}),
332
- ...(framework ? { framework: framework.toLowerCase() } : {}),
333
- ...(highlightLines.length ? { highlightLines } : {}),
322
+ ...(lang && { lang }),
323
+ ...(meta && { meta }),
324
+ ...(title && { title, file: title }),
325
+ ...(framework && { framework: framework.toLowerCase() }),
326
+ ...(highlightLines.length && { highlightLines }),
334
327
  };
335
328
  }
336
329
  function extractDefinitions(lines) {
@@ -342,7 +335,7 @@ function extractDefinitions(lines) {
342
335
  let index = 0;
343
336
  while (index < lines.length) {
344
337
  const line = lines[index];
345
- const fence = line.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
338
+ const fence = (!activeFence || line.includes(activeFence)) && line.match(/^ {0,3}(`{3,}|~{3,})(.*)$/);
346
339
  if (fence) {
347
340
  if (!activeFence)
348
341
  activeFence = fence[1];
@@ -391,7 +384,7 @@ function createFootnotesBlock(footnotes, footnoteOrder, options, slugger) {
391
384
  items.push({
392
385
  id: definition.id ?? footnoteId(definition.label),
393
386
  number: index + 1,
394
- children: new BlockParser(normalizeInput(definition.content).split('\n'), options, slugger).parse(),
387
+ children: createBlockParser(normalizeInput(definition.content).split('\n'), options, slugger).parse(),
395
388
  });
396
389
  }
397
390
  for (const item of items) {
@@ -425,7 +418,7 @@ function listMarker(line) {
425
418
  const ordered = /\d/.test(marker[0]);
426
419
  return {
427
420
  ordered,
428
- ...(ordered ? { number: Number.parseInt(marker, 10) } : {}),
421
+ ...(ordered && { number: Number.parseInt(marker, 10) }),
429
422
  indent: match[1].length,
430
423
  marker: ordered ? marker.at(-1) : marker,
431
424
  contentIndent: match[1].length + marker.length + (match[3]?.length ?? 1),
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGlG,OAAO,KAAK,EAAE,SAAS,EAAmC,UAAU,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAErI,KAAK,oBAAoB,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAA;AACvD,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAExE,MAAM,MAAM,sBAAsB,CAAC,OAAO,SAAS,oBAAoB,IAAI,wBAAwB,CAAC,OAAO,CAAC,CAAA;AAE5G,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC;KACtC,OAAO,IAAI,oBAAoB,GAAG,oBAAoB,GAAG,aAAa,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;CACzG,CAAC,GACA,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAA;AAEzD,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,UAAU,CAAC,EAAE,YAAY,CAAA;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,oBAAoB;IACzD,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,aAAa,GAAG,YAAY,CAE9E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,oBAAyB,GAAG,SAAS,CAGvG;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,oBAAyB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY,CA+DhH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAwC/G"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGlG,OAAO,KAAK,EAAE,SAAS,EAAwD,UAAU,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAE1J,KAAK,oBAAoB,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAA;AACvD,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAExE,MAAM,MAAM,sBAAsB,CAAC,OAAO,SAAS,oBAAoB,IAAI,wBAAwB,CAAC,OAAO,CAAC,CAAA;AAE5G,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC;KACtC,OAAO,IAAI,oBAAoB,GAAG,oBAAoB,GAAG,aAAa,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;CACzG,CAAC,GACA,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAA;AAEzD,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,UAAU,CAAC,EAAE,YAAY,CAAA;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,oBAAoB;IACzD,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,aAAa,GAAG,YAAY,CAE9E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,oBAAyB,GAAG,SAAS,CAGvG;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,oBAAyB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY,CA+DhH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CA0C/G"}
package/dist/react.js CHANGED
@@ -11,14 +11,14 @@ export function renderMarkdownReact(input, options = {}) {
11
11
  export function renderBlockReact(node, options = {}, key) {
12
12
  switch (node.type) {
13
13
  case 'heading':
14
- return h(options, `h${node.depth}`, { key, ...(node.id ? { id: node.id } : {}), ...(node.framework ? { 'data-framework': node.framework } : {}) }, renderInlines(node.children, options), renderHeadingAnchorReact(node.id, options));
14
+ return h(options, `h${node.depth}`, { key, ...(node.id && { id: node.id }), ...(node.framework && { 'data-framework': node.framework }) }, renderInlines(node.children, options), renderHeadingAnchorReact(node.id, options));
15
15
  case 'paragraph':
16
16
  return h(options, 'p', { key }, renderInlines(node.children, options));
17
17
  case 'code':
18
18
  return renderCodeBlockReact(node, options, key);
19
19
  case 'list': {
20
20
  const tag = node.ordered ? 'ol' : 'ul';
21
- return h(options, tag, { key, ...(node.ordered && node.start !== undefined && node.start !== 1 ? { start: node.start } : {}) }, node.items.map((item, index) => h(options, 'li', { key: index }, renderListItemChildrenReact(item.children, item.checked, node.loose, options, `${index}`))));
21
+ return h(options, tag, { key, ...(node.ordered && node.start !== undefined && node.start !== 1 && { start: node.start }) }, node.items.map((item, index) => h(options, 'li', { key: index }, renderListItemChildrenReact(item.children, item.checked, node.loose, options, `${index}`))));
22
22
  }
23
23
  case 'blockquote':
24
24
  return h(options, 'blockquote', { key }, node.children.map((child, index) => renderBlockReact(child, options, `${key}:${index}`)));
@@ -60,15 +60,17 @@ export function renderInlineReact(node, options = {}, key) {
60
60
  href: `#user-content-fn-${node.id}`,
61
61
  }, node.number));
62
62
  case 'link':
63
- return h(options, 'a', { key, href: node.href, ...(node.title ? { title: node.title } : {}) }, renderInlines(node.children, options));
63
+ return h(options, 'a', { key, href: node.href, ...(node.title && { title: node.title }) }, renderInlines(node.children, options));
64
64
  case 'image':
65
- return h(options, 'img', { key, src: node.src, alt: node.alt, ...(node.title ? { title: node.title } : {}) });
65
+ return h(options, 'img', { key, src: node.src, alt: node.alt, ...(node.title && { title: node.title }) });
66
66
  case 'break':
67
67
  return h(options, 'br', { key });
68
68
  case 'inlineHtml':
69
69
  return options.allowHtml
70
70
  ? h(options, 'span', { key, dangerouslySetInnerHTML: { __html: node.value } })
71
71
  : node.value;
72
+ case 'inlineComponent':
73
+ return renderComponentReact(node, options, key);
72
74
  }
73
75
  }
74
76
  function renderInlines(nodes, options) {
@@ -77,14 +79,17 @@ function renderInlines(nodes, options) {
77
79
  function renderCodeBlockReact(node, options, key) {
78
80
  const lang = node.lang ?? 'plaintext';
79
81
  const highlighter = options.highlighter;
80
- const codeProps = {
81
- className: `language-${lang}`,
82
- };
83
- const content = highlighter ? undefined : node.value;
82
+ // Keep completed groups of lines in stable text nodes as code grows. Grouping
83
+ // bounds React's sibling work without relaying out the entire code block.
84
+ // Static rendering and custom code components retain string children.
85
+ const content = highlighter ? undefined : !options.components?.code && options.extensions?.some(extension => extension.name === 'streaming')
86
+ ? node.value.match(/(?:[^\n]*\n){1,4}|[^\n]+$/g)
87
+ : node.value;
84
88
  const highlighted = highlighter
85
89
  ? {
86
90
  dangerouslySetInnerHTML: {
87
91
  __html: highlighter(node.value, lang, {
92
+ ...(node.meta && { meta: node.meta }),
88
93
  ...(node.highlightLines && { highlightLines: node.highlightLines }),
89
94
  ...(options.codeLineNumbers !== undefined && { lineNumbers: options.codeLineNumbers }),
90
95
  }),
@@ -92,14 +97,16 @@ function renderCodeBlockReact(node, options, key) {
92
97
  }
93
98
  : undefined;
94
99
  const pre = h(options, 'pre', {
100
+ key,
95
101
  className: `tm-code${options.codeLineNumbers ? ' tm-code--line-numbers' : ''}`,
96
102
  'data-lang': lang,
97
- ...(node.title ? { 'data-code-title': node.title } : {}),
98
- ...(node.file ? { 'data-filename': node.file } : {}),
99
- ...(node.framework ? { 'data-framework': node.framework } : {}),
100
- }, h(options, 'code', { ...codeProps, ...highlighted }, content));
103
+ ...(node.meta && { 'data-meta': node.meta }),
104
+ ...(node.title && { 'data-code-title': node.title }),
105
+ ...(node.file && { 'data-filename': node.file }),
106
+ ...(node.framework && { 'data-framework': node.framework }),
107
+ }, h(options, 'code', { className: `language-${lang}`, ...highlighted }, content));
101
108
  if (!node.title)
102
- return h(options, Fragment, { key }, pre);
109
+ return pre;
103
110
  return h(options, 'figure', { key, className: 'tm-code-frame', 'data-lang': lang }, h(options, 'figcaption', null, node.title), pre);
104
111
  }
105
112
  function renderListItemChildrenReact(children, checked, loose, options, key) {
@@ -129,7 +136,7 @@ function renderListItemChildrenReact(children, checked, loose, options, key) {
129
136
  return result;
130
137
  }
131
138
  function renderTableCellReact(tag, cell, align, options, key) {
132
- return h(options, tag, { key, ...(align ? { style: { textAlign: align } } : {}) }, renderInlines(cell.children, options));
139
+ return h(options, tag, { key, ...(align && { style: { textAlign: align } }) }, renderInlines(cell.children, options));
133
140
  }
134
141
  function renderFootnotesReact(items, options, key) {
135
142
  return h(options, 'section', { key, 'data-footnotes': '', className: 'footnotes' }, h(options, 'h2', { id: 'footnote-label', className: 'sr-only' }, 'Footnotes', renderHeadingAnchorReact('footnote-label', options)), h(options, 'ol', null, items.map(item => h(options, 'li', { key: item.id, id: `user-content-fn-${item.id}` }, renderFootnoteItemReact(item, options)))));
@@ -167,16 +174,18 @@ function h(options, tag, props, ...children) {
167
174
  return createElement(component, props, ...children);
168
175
  }
169
176
  function renderComponentReact(node, options, key) {
170
- const tag = node.tagName ?? 'md-comment-component';
177
+ const tag = node.tagName ?? (node.type === 'inlineComponent' ? 'span' : 'md-comment-component');
171
178
  const props = {
172
- ...(node.properties ?? {}),
179
+ ...node.properties,
173
180
  };
174
181
  if (!node.tagName) {
175
182
  props['data-component'] = node.name;
176
183
  if (!props['data-attributes'])
177
184
  props['data-attributes'] = JSON.stringify(node.attributes);
178
185
  }
179
- return h(options, tag, { key, ...props }, node.children.map((child, index) => renderBlockReact(child, options, `${key}:${index}`)));
186
+ return h(options, tag, { key, ...props }, node.type === 'inlineComponent'
187
+ ? renderInlines(node.children, options)
188
+ : node.children.map((child, index) => renderBlockReact(child, options, `${key}:${index}`)));
180
189
  }
181
190
  function renderHeadingAnchorReact(id, options) {
182
191
  if (!id || !options.headingAnchors)
package/dist/types.d.ts CHANGED
@@ -84,7 +84,11 @@ export interface ComponentNode {
84
84
  tagName?: string;
85
85
  properties?: Record<string, string>;
86
86
  }
87
- export type InlineNode = TextNode | CodeSpanNode | StrongNode | EmphasisNode | StrikeNode | FootnoteReferenceNode | LinkNode | ImageNode | BreakNode | HtmlInlineNode;
87
+ export interface InlineComponentNode extends Omit<ComponentNode, 'type' | 'children'> {
88
+ type: 'inlineComponent';
89
+ children: InlineNode[];
90
+ }
91
+ export type InlineNode = TextNode | CodeSpanNode | StrongNode | EmphasisNode | StrikeNode | FootnoteReferenceNode | LinkNode | ImageNode | BreakNode | HtmlInlineNode | InlineComponentNode;
88
92
  export interface TextNode {
89
93
  type: 'text';
90
94
  value: string;
@@ -158,6 +162,7 @@ export interface HtmlRenderContext {
158
162
  }
159
163
  export interface ParseOptions {
160
164
  allowHtml?: boolean;
165
+ urlTransform?: UrlTransform;
161
166
  frontmatter?: boolean;
162
167
  headingIds?: boolean | ((text: string, index: number) => string);
163
168
  extensions?: MarkdownExtension[];
@@ -166,6 +171,9 @@ export interface ParseOptions {
166
171
  footnoteOrder?: string[];
167
172
  footnoteCounts?: Record<string, number>;
168
173
  }
174
+ export interface UrlTransform {
175
+ (url: string, kind: 'link' | 'image', defaultUrl: string): string | null;
176
+ }
169
177
  export interface RenderOptions extends ParseOptions {
170
178
  highlighter?: CodeHighlighter;
171
179
  codeLineNumbers?: boolean;
@@ -175,6 +183,7 @@ export interface CodeHighlighter {
175
183
  (code: string, lang?: string, options?: CodeHighlightOptions): string;
176
184
  }
177
185
  export interface CodeHighlightOptions {
186
+ meta?: string;
178
187
  highlightLines?: number[];
179
188
  lineNumbers?: boolean;
180
189
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAUrE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAQrD;AAED,wBAAgB,aAAa,CAAC,SAAS,qBAAc,IAG3C,OAAO,MAAM,YAStB;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ1C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CAMnF;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,CAEjE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAIlD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAarE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAQrD;AAED,wBAAgB,aAAa,CAAC,SAAS,qBAAc,IAG3C,OAAO,MAAM,YAStB;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ1C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CAMnF;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,CAEjE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAIlD"}
package/dist/utils.js CHANGED
@@ -4,15 +4,17 @@ const htmlEscapes = {
4
4
  '>': '&gt;',
5
5
  '"': '&quot;',
6
6
  "'": '&#39;',
7
+ '`': '&#96;',
7
8
  };
9
+ const escapeCharacter = (char) => htmlEscapes[char];
8
10
  export function normalizeInput(value) {
9
11
  return value.replace(/^\uFEFF/, '').replace(/\r\n?/g, '\n');
10
12
  }
11
13
  export function escapeHtml(value) {
12
- return value.replace(/[&<>"']/g, char => htmlEscapes[char]);
14
+ return value.replace(/[&<>"']/g, escapeCharacter);
13
15
  }
14
16
  export function escapeAttr(value) {
15
- return escapeHtml(value).replace(/`/g, '&#96;');
17
+ return value.replace(/[&<>"'`]/g, escapeCharacter);
16
18
  }
17
19
  export function isBlank(value) {
18
20
  return /^\s*$/.test(value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/markdown",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "description": "A tiny, fast, deterministic Markdown renderer for blogs and documentation.",
6
6
  "license": "MIT",
@@ -100,11 +100,14 @@
100
100
  "marked": "^18.0.5",
101
101
  "micromark": "^4.0.2",
102
102
  "octane": "0.1.12",
103
+ "playwright": "1.63.0",
103
104
  "react": "^19.0.0",
104
105
  "react-dom": "^19.0.0",
105
106
  "rehype-stringify": "^10.0.1",
106
107
  "remark-parse": "^11.0.0",
107
108
  "remark-rehype": "^11.1.2",
109
+ "streamdown": "2.6.0",
110
+ "streaming-markdown": "0.2.15",
108
111
  "tsx": "^4.20.0",
109
112
  "typescript": "^5.8.0",
110
113
  "unified": "^11.0.5",
@@ -117,6 +120,7 @@
117
120
  "build": "rm -rf dist && tsc -p tsconfig.build.json",
118
121
  "typecheck": "tsc --noEmit",
119
122
  "test": "vitest run",
123
+ "test:streaming-browser": "tsx scripts/verify-streaming-browser.ts",
120
124
  "test:corpus": "vitest run tests/corpus.test.tsx",
121
125
  "corpus:audit": "tsx scripts/audit-corpus.ts",
122
126
  "corpus:audit:tanstack": "tsx scripts/audit-tanstack-corpus.ts",
@@ -132,6 +136,7 @@
132
136
  "release:publish": "pnpm run verify && changeset publish",
133
137
  "conformance": "tsx scripts/conformance.ts",
134
138
  "bench": "tsx scripts/bench.ts",
139
+ "bench:streaming": "tsx scripts/bench-streaming-browser.ts",
135
140
  "size": "tsx scripts/measure-size.ts",
136
141
  "research": "pnpm run conformance && pnpm run size && pnpm run bench",
137
142
  "verify": "pnpm test && pnpm run typecheck && pnpm run build && pnpm run docs:verify && pnpm run test:skills && pnpm run research && pnpm pack --dry-run",
@@ -2,12 +2,12 @@
2
2
  name: 'custom-extensions'
3
3
  description: >
4
4
  Implement MarkdownExtension block parsers, inline and document transforms,
5
- HTML hooks, and portable ComponentNode output. Load when adding deterministic
5
+ HTML hooks, and portable block and inline component output. Load when adding deterministic
6
6
  custom syntax or rendering behavior across HTML, React, and Octane.
7
7
  metadata:
8
8
  type: core
9
9
  library: '@tanstack/markdown'
10
- library_version: '0.0.14'
10
+ library_version: '0.0.15'
11
11
  requires:
12
12
  - 'render-markdown'
13
13
  sources:
@@ -111,6 +111,13 @@ console.log(html)
111
111
 
112
112
  Transforms receive built-in inline nodes and must return a deterministic replacement array.
113
113
 
114
+ For custom inline UI, return an `InlineComponentNode` with `type: 'inlineComponent'`,
115
+ `name`, `attributes`, inline `children`, and optional `tagName` and string `properties`.
116
+ It uses the same emitted-tag component maps as a block `ComponentNode`, but defaults
117
+ to `<span>` instead of `<md-comment-component>`. Keep tag and property names under
118
+ extension control, use phrasing content, and recurse through inline `children` when
119
+ transforming text nested inside links or emphasis. This does not require `allowHtml`.
120
+
114
121
  ### Derive document metadata after parsing
115
122
 
116
123
  ```ts
@@ -370,7 +377,7 @@ export function Article() {
370
377
  }
371
378
  ```
372
379
 
373
- `renderHtml` hooks do not run in React or Octane; a `ComponentNode` and emitted-tag component mapping is the portable path.
380
+ `renderHtml` hooks do not run in React or Octane; a `ComponentNode` or `InlineComponentNode` and emitted-tag component mapping is the portable path.
374
381
 
375
382
  Source: `docs/guides/extensions.md`
376
383
 
@@ -425,7 +432,7 @@ Source: `docs/guides/extensions.md`
425
432
 
426
433
  ### HIGH Rich output versus untrusted-content safety
427
434
 
428
- Prefer `ComponentNode` plus application components for rich output. Treat `allowHtml`, extension HTML strings, and highlighter markup as explicit trusted boundaries; see `production-pipelines`.
435
+ Prefer block or inline component nodes plus application components for rich output. Treat `allowHtml`, extension HTML strings, and highlighter markup as explicit trusted boundaries; see `production-pipelines`.
429
436
 
430
437
  ### MEDIUM Parse-ahead performance versus option timing
431
438
 
@@ -9,7 +9,7 @@ description: >
9
9
  metadata:
10
10
  type: core
11
11
  library: '@tanstack/markdown'
12
- library_version: '0.0.14'
12
+ library_version: '0.0.15'
13
13
  requires:
14
14
  - 'render-markdown'
15
15
  sources:
@@ -317,4 +317,4 @@ interface CodeBlockNode {
317
317
  - `{2,4-6}` and `lines=2,4-6` produce sorted, unique positive line numbers.
318
318
  - Invalid ranges are ignored, and each individual range expands to at most 1,000 lines.
319
319
 
320
- HTML code blocks expose `data-lang`, `data-code-title`, `data-filename`, and `data-framework` when the corresponding values exist. Highlight lines are passed to a configured highlighter; metadata alone does not create token or line markup.
320
+ HTML, React, and Octane code blocks expose `data-lang`, `data-meta`, `data-code-title`, `data-filename`, and `data-framework` on `<pre>` when the corresponding values exist. Framework `pre` replacements can read `props['data-meta']`; highlighters receive the raw metadata in `options.meta` alongside highlight lines. Metadata alone does not create token or line markup.
@@ -9,7 +9,7 @@ metadata:
9
9
  type: framework
10
10
  library: '@tanstack/markdown'
11
11
  framework: 'octane'
12
- library_version: '0.0.14'
12
+ library_version: '0.0.15'
13
13
  requires:
14
14
  - 'render-markdown'
15
15
  sources:
@@ -8,7 +8,7 @@ description: >
8
8
  metadata:
9
9
  type: lifecycle
10
10
  library: '@tanstack/markdown'
11
- library_version: '0.0.14'
11
+ library_version: '0.0.15'
12
12
  requires:
13
13
  - 'render-markdown'
14
14
  sources:
@@ -127,7 +127,7 @@ import { parseMarkdown } from '@tanstack/markdown/parser'
127
127
  const cache = new Map<string, MarkdownDocument>()
128
128
 
129
129
  export function renderCachedArticle(key: string, source: string): string {
130
- const cacheKey = `markdown-0.0.14:${key}`
130
+ const cacheKey = `markdown-0.0.15:${key}`
131
131
  let document = cache.get(cacheKey)
132
132
  if (!document) {
133
133
  document = parseMarkdown(source, {
@@ -331,6 +331,14 @@ export function renderWithPolicy(
331
331
 
332
332
  Core escaping and protocol filtering do not enforce application-specific outbound-link, image, or final-HTML policy.
333
333
 
334
+ For parsed Markdown destinations, `urlTransform(url, kind, defaultUrl)` can return
335
+ the screened default, a trusted replacement, or `null` to remove the link or image
336
+ while retaining its label content. Only allow data images after application validation
337
+ of their content, MIME type, and size. Keep the default policy for other destinations.
338
+ Callback results are not screened again, and the callback does not apply to raw HTML,
339
+ extension-created URLs, or ASTs supplied directly to renderers. Do not enable raw HTML
340
+ to allow images. Include URL-policy changes in persisted AST cache invalidation.
341
+
334
342
  Source: `docs/core-concepts/security.md`
335
343
 
336
344
  ### HIGH Assuming complete CommonMark behavior
@@ -9,7 +9,7 @@ metadata:
9
9
  type: framework
10
10
  library: '@tanstack/markdown'
11
11
  framework: 'react'
12
- library_version: '0.0.14'
12
+ library_version: '0.0.15'
13
13
  requires:
14
14
  - 'render-markdown'
15
15
  sources:
@@ -9,7 +9,7 @@ description: >
9
9
  metadata:
10
10
  type: core
11
11
  library: '@tanstack/markdown'
12
- library_version: '0.0.14'
12
+ library_version: '0.0.15'
13
13
  sources:
14
14
  - 'TanStack/markdown:docs/quick-start.md'
15
15
  - 'TanStack/markdown:docs/core-concepts/document-model.md'
@@ -1,6 +1,6 @@
1
1
  # AST and Options Reference
2
2
 
3
- This reference targets `@tanstack/markdown@0.0.14`. Shared public types are
3
+ This reference targets `@tanstack/markdown@0.0.15`. Shared public types are
4
4
  exported from `@tanstack/markdown`.
5
5
 
6
6
  ## Entry Points
@@ -190,10 +190,11 @@ Important rendering invariants:
190
190
  | `emphasis` | `EmphasisNode` | inline `children` |
191
191
  | `strike` | `StrikeNode` | inline `children` |
192
192
  | `footnoteReference` | `FootnoteReferenceNode` | normalized `id`, display `number`, optional `referenceIndex` |
193
- | `link` | `LinkNode` | sanitized `href`, optional `title`, inline `children` |
194
- | `image` | `ImageNode` | sanitized `src`, text `alt`, optional `title` |
193
+ | `link` | `LinkNode` | policy-processed `href`, optional `title`, inline `children` |
194
+ | `image` | `ImageNode` | policy-processed `src`, text `alt`, optional `title` |
195
195
  | `break` | `BreakNode` | no additional fields |
196
196
  | `inlineHtml` | `HtmlInlineNode` | raw `value` |
197
+ | `inlineComponent` | `InlineComponentNode` | `name`, `attributes`, inline `children`, optional `tagName`, optional string `properties` |
197
198
 
198
199
  `HtmlInlineNode` is created only when parsing with `allowHtml: true`.
199
200
  Repeated footnote references use `referenceIndex` to produce unique source
@@ -206,10 +207,12 @@ import type {
206
207
  FootnoteDefinition,
207
208
  LinkReferenceDefinition,
208
209
  MarkdownExtension,
210
+ UrlTransform,
209
211
  } from '@tanstack/markdown'
210
212
 
211
213
  interface ParseOptions {
212
214
  allowHtml?: boolean
215
+ urlTransform?: UrlTransform
213
216
  frontmatter?: boolean
214
217
  headingIds?: boolean | ((text: string, index: number) => string)
215
218
  extensions?: MarkdownExtension[]
@@ -223,6 +226,7 @@ interface ParseOptions {
223
226
  | Option | Default | Contract |
224
227
  | --- | --- | --- |
225
228
  | `allowHtml` | `false` | Recognize raw block and inline HTML nodes. Rendering also requires this option to emit their raw values. |
229
+ | `urlTransform` | built-in policy | Synchronous `(url, kind, defaultUrl) => string \| null`; return the screened default, a trusted replacement, or `null` to keep only label content. Applies to Markdown destinations, not raw HTML or supplied ASTs. |
226
230
  | `frontmatter` | `true` | Extract one leading `---` block into `document.frontmatter`. The library does not parse YAML. |
227
231
  | `headingIds` | `true` | Generate duplicate-safe IDs, disable IDs with `false`, or return an ID from `(text, normalizedLineIndex)`. |
228
232
  | `extensions` | `[]` | Run block parsers and inline/document transforms in array order. |
@@ -259,6 +263,7 @@ interface HeadingAnchorOptions {
259
263
  }
260
264
 
261
265
  interface CodeHighlightOptions {
266
+ meta?: string
262
267
  highlightLines?: number[]
263
268
  lineNumbers?: boolean
264
269
  }