@tanstack/markdown 0.0.4 → 0.0.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAuC,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAG3J,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,CAsChF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAwBlF;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,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,CAwChF;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"}
package/dist/html.js CHANGED
@@ -33,6 +33,8 @@ export function renderBlock(node, options = {}) {
33
33
  .join('')}</tbody>`;
34
34
  return `<table>${header}${body}</table>`;
35
35
  }
36
+ case 'footnotes':
37
+ return renderFootnotes(node.items, options);
36
38
  case 'thematicBreak':
37
39
  return '<hr>';
38
40
  case 'html':
@@ -57,7 +59,9 @@ export function renderInline(node, options = {}) {
57
59
  case 'emphasis':
58
60
  return `<em>${renderInlines(node.children, options)}</em>`;
59
61
  case 'strike':
60
- return `<s>${renderInlines(node.children, options)}</s>`;
62
+ return `<del>${renderInlines(node.children, options)}</del>`;
63
+ case 'footnoteReference':
64
+ return `<sup><a id="user-content-fnref-${escapeAttr(footnoteReferenceId(node))}" data-footnote-ref="" aria-describedby="footnote-label" href="#user-content-fn-${escapeAttr(node.id)}">${node.number}</a></sup>`;
61
65
  case 'link':
62
66
  return `<a href="${escapeAttr(node.href)}"${node.title ? ` title="${escapeAttr(node.title)}"` : ''}>${renderInlines(node.children, options)}</a>`;
63
67
  case 'image':
@@ -97,8 +101,11 @@ function renderCodeBlock(node, options) {
97
101
  function renderListItemChildren(children, checked, loose, options) {
98
102
  const first = children[0];
99
103
  const task = checked === undefined ? '' : `<input type="checkbox" disabled${checked ? ' checked' : ''}> `;
100
- if ((checked !== undefined || !loose) && first?.type === 'paragraph')
101
- return `${task}${renderInlines(first.children, options)}${children.length > 1 ? `\n${children.slice(1).map(child => renderBlock(child, options)).join('\n')}` : ''}`;
104
+ if (first?.type === 'paragraph') {
105
+ const content = `${task}${renderInlines(first.children, options)}`;
106
+ const rest = children.length > 1 ? `\n${children.slice(1).map(child => renderBlock(child, options)).join('\n')}` : '';
107
+ return `${loose ? `<p>${content}</p>` : content}${rest}`;
108
+ }
102
109
  return `${task}${children.map(child => renderBlock(child, options)).join('\n')}`;
103
110
  }
104
111
  function renderCallout(node, options) {
@@ -106,6 +113,36 @@ function renderCallout(node, options) {
106
113
  const children = node.children.map(child => renderBlock(child, options)).join('\n');
107
114
  return `<div class="markdown-alert markdown-alert-${escapeAttr(kind)}"><p class="markdown-alert-title">${escapeHtml(node.title)}</p><div class="markdown-alert-content">${children}</div></div>`;
108
115
  }
116
+ function renderFootnotes(items, options) {
117
+ const renderedItems = items.map(item => `<li id="user-content-fn-${escapeAttr(item.id)}">\n${renderFootnoteItem(item, options)}\n</li>`).join('\n');
118
+ return `<section data-footnotes="" class="footnotes"><h2 id="footnote-label" class="sr-only">Footnotes${renderHeadingAnchor('footnote-label', options)}</h2>\n<ol>\n${renderedItems}\n</ol>\n</section>`;
119
+ }
120
+ function renderFootnoteItem(item, options) {
121
+ const backref = renderFootnoteBackrefs(item);
122
+ const lastIndex = item.children.length - 1;
123
+ if (lastIndex < 0)
124
+ return `<p>${backref.trimStart()}</p>`;
125
+ return item.children
126
+ .map((child, index) => {
127
+ if (index === lastIndex && child.type === 'paragraph') {
128
+ return `<p>${renderInlines(child.children, options)}${backref}</p>`;
129
+ }
130
+ return renderBlock(child, options);
131
+ })
132
+ .join('\n');
133
+ }
134
+ function renderFootnoteBackrefs(item) {
135
+ let result = '';
136
+ for (let index = 1; index <= (item.referenceCount ?? 1); index++) {
137
+ const referenceId = index === 1 ? item.id : `${item.id}-${index}`;
138
+ const label = index === 1 ? `${item.number}` : `${item.number}-${index}`;
139
+ result += ` <a data-footnote-backref="" aria-label="Back to reference ${label}" class="data-footnote-backref" href="#user-content-fnref-${escapeAttr(referenceId)}">&#8617;</a>`;
140
+ }
141
+ return result;
142
+ }
143
+ function footnoteReferenceId(node) {
144
+ return node.referenceIndex && node.referenceIndex > 1 ? `${node.id}-${node.referenceIndex}` : node.id;
145
+ }
109
146
  function renderComponent(node, options) {
110
147
  const tag = node.tagName ?? 'md-comment-component';
111
148
  const attrs = renderComponentAttrs(node);
package/dist/inline.js CHANGED
@@ -1,4 +1,4 @@
1
- import { normalizeReferenceLabel, sanitizeUrl } from './utils.js';
1
+ import { footnoteId, normalizeReferenceLabel, sanitizeUrl } from './utils.js';
2
2
  export function parseInline(value, options = {}) {
3
3
  const nodes = parseInlineRaw(value, options);
4
4
  let result = mergeText(nodes);
@@ -61,6 +61,13 @@ function parseInlineRaw(value, options) {
61
61
  }
62
62
  }
63
63
  if (char === '[') {
64
+ const footnote = parseFootnoteReference(value, index, options);
65
+ if (footnote) {
66
+ pushText();
67
+ nodes.push(footnote.node);
68
+ index = footnote.end;
69
+ continue;
70
+ }
64
71
  const parsed = parseLinkish(value, index, options);
65
72
  if (parsed) {
66
73
  const href = sanitizeUrl(parsed.href);
@@ -110,6 +117,18 @@ function parseInlineRaw(value, options) {
110
117
  index += 2;
111
118
  continue;
112
119
  }
120
+ if (char === '~') {
121
+ const close = findSingleTildeDelimiter(value, index + 1);
122
+ if (close !== -1) {
123
+ pushText();
124
+ nodes.push({
125
+ type: 'strike',
126
+ children: parseInlineRaw(value.slice(index + 1, close), options),
127
+ });
128
+ index = close + 1;
129
+ continue;
130
+ }
131
+ }
113
132
  if (char === '*' || char === '_') {
114
133
  const close = findDelimiter(value, index + 1, char);
115
134
  if (close !== -1 && !isIntrawordUnderscore(value, index, close, char)) {
@@ -137,6 +156,35 @@ function parseInlineRaw(value, options) {
137
156
  pushText();
138
157
  return nodes;
139
158
  }
159
+ function parseFootnoteReference(value, open, options) {
160
+ if (value[open + 1] !== '^')
161
+ return undefined;
162
+ const close = value.indexOf(']', open + 2);
163
+ if (close === -1)
164
+ return undefined;
165
+ const label = value.slice(open + 2, close);
166
+ const key = normalizeReferenceLabel(label);
167
+ const definition = options.footnotes?.[key];
168
+ if (!definition || !options.footnoteOrder)
169
+ return undefined;
170
+ let orderIndex = options.footnoteOrder.indexOf(key);
171
+ if (orderIndex === -1) {
172
+ options.footnoteOrder.push(key);
173
+ orderIndex = options.footnoteOrder.length - 1;
174
+ }
175
+ const referenceIndex = (options.footnoteCounts?.[key] ?? 0) + 1;
176
+ if (options.footnoteCounts)
177
+ options.footnoteCounts[key] = referenceIndex;
178
+ return {
179
+ node: {
180
+ type: 'footnoteReference',
181
+ id: definition.id ?? (footnoteId(definition.label) || 'footnote'),
182
+ number: orderIndex + 1,
183
+ ...(referenceIndex > 1 ? { referenceIndex } : {}),
184
+ },
185
+ end: close + 1,
186
+ };
187
+ }
140
188
  function parseLinkish(value, open, options) {
141
189
  const closeBracket = findBalanced(value, open, '[', ']');
142
190
  if (closeBracket === -1)
@@ -221,11 +269,30 @@ function findDelimiter(value, start, delimiter) {
221
269
  }
222
270
  return -1;
223
271
  }
272
+ function findSingleTildeDelimiter(value, start) {
273
+ if (isWhitespace(value[start] ?? ''))
274
+ return -1;
275
+ for (let index = start; index < value.length; index++) {
276
+ if (value[index - 1] === '\\')
277
+ continue;
278
+ if (value[index] !== '~')
279
+ continue;
280
+ if (value[index + 1] === '~')
281
+ continue;
282
+ if (isWhitespace(value[index - 1] ?? ''))
283
+ return -1;
284
+ return index;
285
+ }
286
+ return -1;
287
+ }
224
288
  function isIntrawordUnderscore(value, open, close, delimiter) {
225
289
  if (delimiter !== '_')
226
290
  return false;
227
291
  return /\w/.test(value[open - 1] ?? '') && /\w/.test(value[close + 1] ?? '');
228
292
  }
293
+ function isWhitespace(value) {
294
+ return /\s/.test(value);
295
+ }
229
296
  function textFromMarkdown(value) {
230
297
  return parseInlineRaw(value, {}).map(node => (node.type === 'text' || node.type === 'inlineCode' ? node.value : '')).join('');
231
298
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAOV,gBAAgB,EAChB,YAAY,EAGb,MAAM,YAAY,CAAA;AAKnB,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,gBAAgB,CAiC5F"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAQV,gBAAgB,EAChB,YAAY,EAGb,MAAM,YAAY,CAAA;AAKnB,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,gBAAgB,CAyC5F"}
package/dist/parser.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { parseInline } from './inline.js';
2
- import { createSlugger, isBlank, normalizeInput, normalizeReferenceLabel, plainText, stripIndent } from './utils.js';
2
+ import { createSlugger, footnoteId, isBlank, normalizeInput, normalizeReferenceLabel, plainText, stripIndent } from './utils.js';
3
3
  export function parseMarkdown(markdown, options = {}) {
4
4
  const normalized = normalizeInput(markdown);
5
5
  const frontmatterEnabled = options.frontmatter !== false;
@@ -12,16 +12,24 @@ export function parseMarkdown(markdown, options = {}) {
12
12
  lines = lines.slice(end + 1);
13
13
  }
14
14
  }
15
- const referenceResult = extractReferenceDefinitions(lines);
16
- lines = referenceResult.lines;
17
- const parseOptions = Object.keys(referenceResult.references).length === 0
18
- ? options
19
- : {
15
+ const definitions = extractDefinitions(lines);
16
+ lines = definitions.lines;
17
+ const footnoteOrder = [];
18
+ const footnoteCounts = Object.create(null);
19
+ const hasReferences = Object.keys(definitions.references).length > 0;
20
+ const hasFootnotes = Object.keys(definitions.footnotes).length > 0;
21
+ const parseOptions = hasReferences || hasFootnotes
22
+ ? {
20
23
  ...options,
21
- references: referenceResult.references,
22
- };
24
+ ...(hasReferences ? { references: definitions.references } : {}),
25
+ ...(hasFootnotes ? { footnotes: definitions.footnotes, footnoteOrder, footnoteCounts } : {}),
26
+ }
27
+ : options;
23
28
  const parser = new BlockParser(lines, parseOptions, createSlugger());
24
29
  const children = parser.parse();
30
+ if (hasFootnotes && footnoteOrder.length > 0) {
31
+ children.push(createFootnotesBlock(definitions.footnotes, footnoteOrder, parseOptions));
32
+ }
25
33
  let document = frontmatter === undefined ? { type: 'root', children } : { type: 'root', frontmatter, children };
26
34
  for (const extension of parseOptions.extensions ?? []) {
27
35
  document = extension.transformDocument?.(document, { options: parseOptions }) ?? document;
@@ -157,7 +165,7 @@ class BlockParser {
157
165
  let loose = false;
158
166
  while (this.index < this.lines.length) {
159
167
  const marker = listMarker(this.current());
160
- if (!marker || marker.ordered !== ordered || marker.indent !== baseIndent)
168
+ if (!marker || !sameListType(marker, first) || marker.indent !== baseIndent)
161
169
  break;
162
170
  let firstLine = marker.content;
163
171
  const task = firstLine.match(/^\[([ xX])\]\s+(.*)$/);
@@ -169,18 +177,32 @@ class BlockParser {
169
177
  while (this.index < this.lines.length) {
170
178
  const line = this.current();
171
179
  const nextMarker = listMarker(line);
172
- if (nextMarker && nextMarker.indent === baseIndent && nextMarker.ordered === ordered)
180
+ if (nextMarker && nextMarker.indent === baseIndent)
173
181
  break;
174
182
  if (isBlank(line)) {
175
- if (!this.next())
183
+ let nextIndex = this.index;
184
+ while (nextIndex < this.lines.length && isBlank(this.lines[nextIndex]))
185
+ nextIndex++;
186
+ const following = this.lines[nextIndex];
187
+ if (following === undefined)
188
+ break;
189
+ const followingMarker = listMarker(following);
190
+ if (followingMarker?.indent === baseIndent) {
191
+ if (!sameListType(followingMarker, first))
192
+ break;
193
+ loose = true;
194
+ this.index = nextIndex;
195
+ break;
196
+ }
197
+ if (leadingSpaces(following) < marker.contentIndent)
176
198
  break;
177
199
  loose = true;
178
200
  itemLines.push('');
179
- this.index++;
201
+ this.index = nextIndex;
180
202
  continue;
181
203
  }
182
- if (leadingSpaces(line) > baseIndent) {
183
- itemLines.push(stripIndent(line, baseIndent + 2));
204
+ if (leadingSpaces(line) >= marker.contentIndent) {
205
+ itemLines.push(stripIndent(line, marker.contentIndent));
184
206
  this.index++;
185
207
  continue;
186
208
  }
@@ -287,12 +309,16 @@ function parseCodeInfo(info) {
287
309
  ...(highlightLines.length ? { highlightLines } : {}),
288
310
  };
289
311
  }
290
- function extractReferenceDefinitions(lines) {
291
- const references = {};
312
+ function extractDefinitions(lines) {
313
+ const references = Object.create(null);
314
+ const footnotes = Object.create(null);
315
+ const footnoteIds = new Map();
292
316
  const remaining = [];
293
317
  let fenceMarker;
294
318
  let fenceSize = 0;
295
- for (const line of lines) {
319
+ let index = 0;
320
+ while (index < lines.length) {
321
+ const line = lines[index];
296
322
  const fence = line.match(/^ {0,3}(`{3,}|~{3,})/);
297
323
  if (fence) {
298
324
  const marker = fence[1][0];
@@ -305,18 +331,62 @@ function extractReferenceDefinitions(lines) {
305
331
  fenceSize = 0;
306
332
  }
307
333
  remaining.push(line);
334
+ index++;
308
335
  continue;
309
336
  }
310
337
  if (!fenceMarker) {
338
+ const footnote = line.match(/^ {0,3}\[\^([^\]\n]+)\]:[ \t]*(.*)$/);
339
+ if (footnote) {
340
+ const label = footnote[1];
341
+ const content = [footnote[2] ?? ''];
342
+ index++;
343
+ while (index < lines.length) {
344
+ const continuation = lines[index];
345
+ if (!/^(?: {4,}|\t)/.test(continuation))
346
+ break;
347
+ content.push(continuation.replace(/^(?: {4}|\t)/, ''));
348
+ index++;
349
+ }
350
+ const key = normalizeReferenceLabel(label);
351
+ if (!footnotes[key]) {
352
+ const baseId = footnoteId(label) || 'footnote';
353
+ const count = (footnoteIds.get(baseId) ?? 0) + 1;
354
+ footnoteIds.set(baseId, count);
355
+ footnotes[key] = { label, content: content.join('\n'), id: count === 1 ? baseId : `${baseId}-${count}` };
356
+ }
357
+ continue;
358
+ }
311
359
  const definition = line.match(/^ {0,3}\[([^\]\n]+)\]:[ \t]*(\S+)[ \t]*$/);
312
360
  if (definition) {
313
361
  references[normalizeReferenceLabel(definition[1])] = { href: definition[2].replace(/^<|>$/g, '') };
362
+ index++;
314
363
  continue;
315
364
  }
316
365
  }
317
366
  remaining.push(line);
367
+ index++;
368
+ }
369
+ return { lines: remaining, references, footnotes };
370
+ }
371
+ function createFootnotesBlock(footnotes, footnoteOrder, options) {
372
+ const items = [];
373
+ for (let index = 0; index < footnoteOrder.length; index++) {
374
+ const key = footnoteOrder[index];
375
+ const definition = footnotes[key];
376
+ if (!definition)
377
+ continue;
378
+ items.push({
379
+ id: definition.id ?? (footnoteId(definition.label) || 'footnote'),
380
+ number: index + 1,
381
+ children: new BlockParser(normalizeInput(definition.content).split('\n'), options, createSlugger()).parse(),
382
+ });
318
383
  }
319
- return { lines: remaining, references };
384
+ for (const item of items) {
385
+ const count = options.footnoteCounts?.[footnoteOrder[item.number - 1]] ?? 1;
386
+ if (count > 1)
387
+ item.referenceCount = count;
388
+ }
389
+ return { type: 'footnotes', items };
320
390
  }
321
391
  function parseLineRanges(value) {
322
392
  const lines = new Set();
@@ -332,7 +402,7 @@ function parseLineRanges(value) {
332
402
  return [...lines].sort((a, b) => a - b);
333
403
  }
334
404
  function listMarker(line) {
335
- const match = line.match(/^(\s{0,8})([-+*]|\d{1,9}[.)])\s+(.*)$/);
405
+ const match = line.match(/^(\s{0,8})([-+*]|\d{1,9}[.)])(?:([ \t]+)(.*))?$/);
336
406
  if (!match)
337
407
  return undefined;
338
408
  const marker = match[2];
@@ -341,9 +411,14 @@ function listMarker(line) {
341
411
  ordered,
342
412
  ...(ordered ? { number: Number.parseInt(marker, 10) } : {}),
343
413
  indent: match[1].length,
344
- content: match[3],
414
+ marker: ordered ? marker.at(-1) : marker,
415
+ contentIndent: match[1].length + marker.length + (match[3]?.length ?? 1),
416
+ content: match[4] ?? '',
345
417
  };
346
418
  }
419
+ function sameListType(left, right) {
420
+ return left.ordered === right.ordered && left.marker === right.marker;
421
+ }
347
422
  function leadingSpaces(line) {
348
423
  return line.match(/^ */)?.[0].length ?? 0;
349
424
  }
@@ -359,7 +434,7 @@ function looksLikeTableHeader(header, delimiter) {
359
434
  if (!header.includes('|'))
360
435
  return false;
361
436
  const cells = splitTableRow(delimiter);
362
- return cells.length > 0 && cells.every(cell => /^:?-{3,}:?$/.test(cell.trim()));
437
+ return cells.length > 0 && cells.every(cell => /^:?-{2,}:?$/.test(cell.trim()));
363
438
  }
364
439
  function splitTableRow(value) {
365
440
  let row = value.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAiB,UAAU,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAA;AAEnH,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAExE,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,CA2DhH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAuB/G"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEnE,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,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,CA6DhH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAwC/G"}
package/dist/react.js CHANGED
@@ -23,6 +23,8 @@ export function renderBlockReact(node, options = {}, key) {
23
23
  return h(options, 'blockquote', { key }, node.children.map((child, index) => renderBlockReact(child, options, `${key}:${index}`)));
24
24
  case 'table':
25
25
  return h(options, 'table', { key }, h(options, 'thead', null, h(options, 'tr', null, node.header.map((cell, index) => renderTableCellReact('th', cell, node.align[index], options, index)))), h(options, 'tbody', null, node.rows.map((row, rowIndex) => h(options, 'tr', { key: rowIndex }, row.map((cell, index) => renderTableCellReact('td', cell, node.align[index], options, index))))));
26
+ case 'footnotes':
27
+ return renderFootnotesReact(node.items, options, key);
26
28
  case 'thematicBreak':
27
29
  return h(options, 'hr', { key });
28
30
  case 'html':
@@ -46,7 +48,14 @@ export function renderInlineReact(node, options = {}, key) {
46
48
  case 'emphasis':
47
49
  return h(options, 'em', { key }, renderInlines(node.children, options));
48
50
  case 'strike':
49
- return h(options, 's', { key }, renderInlines(node.children, options));
51
+ return h(options, 'del', { key }, renderInlines(node.children, options));
52
+ case 'footnoteReference':
53
+ return h(options, 'sup', { key }, h(options, 'a', {
54
+ id: `user-content-fnref-${footnoteReferenceId(node)}`,
55
+ 'data-footnote-ref': '',
56
+ 'aria-describedby': 'footnote-label',
57
+ href: `#user-content-fn-${node.id}`,
58
+ }, node.number));
50
59
  case 'link':
51
60
  return h(options, 'a', { key, href: node.href, ...(node.title ? { title: node.title } : {}) }, renderInlines(node.children, options));
52
61
  case 'image':
@@ -104,10 +113,10 @@ function renderListItemChildrenReact(children, checked, loose, options, key) {
104
113
  }),
105
114
  ' ',
106
115
  ];
107
- if (checked !== undefined && first?.type === 'paragraph') {
116
+ if (first?.type === 'paragraph') {
117
+ const content = [...task, ...renderInlines(first.children, options)];
108
118
  return [
109
- ...task,
110
- ...renderInlines(first.children, options),
119
+ ...(loose ? [h(options, 'p', { key: `${key}:paragraph` }, content)] : content),
111
120
  ...rest.flatMap((child, childIndex) => renderListChildReact(child, loose, options, `${key}:${childIndex + 1}`)),
112
121
  ];
113
122
  }
@@ -119,6 +128,39 @@ function renderListChildReact(child, loose, options, key) {
119
128
  function renderTableCellReact(tag, cell, align, options, key) {
120
129
  return h(options, tag, { key, ...(align ? { style: { textAlign: align } } : {}) }, renderInlines(cell.children, options));
121
130
  }
131
+ function renderFootnotesReact(items, options, key) {
132
+ 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)))));
133
+ }
134
+ function renderFootnoteItemReact(item, options) {
135
+ const lastIndex = item.children.length - 1;
136
+ const backrefs = renderFootnoteBackrefsReact(item, options);
137
+ if (lastIndex < 0)
138
+ return [h(options, 'p', { key: 'backref-wrapper' }, backrefs.slice(1))];
139
+ return item.children.map((child, index) => {
140
+ if (index === lastIndex && child.type === 'paragraph') {
141
+ return h(options, 'p', { key: index }, renderInlines(child.children, options), backrefs);
142
+ }
143
+ return renderBlockReact(child, options, `${index}`);
144
+ });
145
+ }
146
+ function renderFootnoteBackrefsReact(item, options) {
147
+ const result = [];
148
+ for (let index = 1; index <= (item.referenceCount ?? 1); index++) {
149
+ const referenceId = index === 1 ? item.id : `${item.id}-${index}`;
150
+ const label = index === 1 ? `${item.number}` : `${item.number}-${index}`;
151
+ result.push(' ', h(options, 'a', {
152
+ key: index,
153
+ 'data-footnote-backref': '',
154
+ 'aria-label': `Back to reference ${label}`,
155
+ className: 'data-footnote-backref',
156
+ href: `#user-content-fnref-${referenceId}`,
157
+ }, '\u21a9'));
158
+ }
159
+ return result;
160
+ }
161
+ function footnoteReferenceId(node) {
162
+ return node.referenceIndex && node.referenceIndex > 1 ? `${node.id}-${node.referenceIndex}` : node.id;
163
+ }
122
164
  function h(options, tag, props, ...children) {
123
165
  const component = typeof tag === 'string' ? options.components?.[tag] ?? tag : tag;
124
166
  return createElement(component, props, ...children);
package/dist/types.d.ts CHANGED
@@ -5,7 +5,7 @@ export interface MarkdownDocument {
5
5
  frontmatter?: string;
6
6
  headings?: MarkdownHeading[];
7
7
  }
8
- export type BlockNode = HeadingNode | ParagraphNode | CodeBlockNode | ListNode | BlockquoteNode | TableNode | ThematicBreakNode | HtmlBlockNode | CalloutNode | ComponentNode;
8
+ export type BlockNode = HeadingNode | ParagraphNode | CodeBlockNode | ListNode | BlockquoteNode | TableNode | FootnotesNode | ThematicBreakNode | HtmlBlockNode | CalloutNode | ComponentNode;
9
9
  export interface HeadingNode {
10
10
  type: 'heading';
11
11
  depth: 1 | 2 | 3 | 4 | 5 | 6;
@@ -53,6 +53,16 @@ export interface TableCellNode {
53
53
  type: 'tableCell';
54
54
  children: InlineNode[];
55
55
  }
56
+ export interface FootnotesNode {
57
+ type: 'footnotes';
58
+ items: FootnoteItemNode[];
59
+ }
60
+ export interface FootnoteItemNode {
61
+ id: string;
62
+ number: number;
63
+ referenceCount?: number;
64
+ children: BlockNode[];
65
+ }
56
66
  export interface ThematicBreakNode {
57
67
  type: 'thematicBreak';
58
68
  }
@@ -74,7 +84,7 @@ export interface ComponentNode {
74
84
  tagName?: string;
75
85
  properties?: Record<string, string>;
76
86
  }
77
- export type InlineNode = TextNode | CodeSpanNode | StrongNode | EmphasisNode | StrikeNode | LinkNode | ImageNode | BreakNode | HtmlInlineNode;
87
+ export type InlineNode = TextNode | CodeSpanNode | StrongNode | EmphasisNode | StrikeNode | FootnoteReferenceNode | LinkNode | ImageNode | BreakNode | HtmlInlineNode;
78
88
  export interface TextNode {
79
89
  type: 'text';
80
90
  value: string;
@@ -95,6 +105,12 @@ export interface StrikeNode {
95
105
  type: 'strike';
96
106
  children: InlineNode[];
97
107
  }
108
+ export interface FootnoteReferenceNode {
109
+ type: 'footnoteReference';
110
+ id: string;
111
+ number: number;
112
+ referenceIndex?: number;
113
+ }
98
114
  export interface LinkNode {
99
115
  type: 'link';
100
116
  href: string;
@@ -146,6 +162,9 @@ export interface ParseOptions {
146
162
  headingIds?: boolean | ((text: string, index: number) => string);
147
163
  extensions?: MarkdownExtension[];
148
164
  references?: Record<string, LinkReferenceDefinition>;
165
+ footnotes?: Record<string, FootnoteDefinition>;
166
+ footnoteOrder?: string[];
167
+ footnoteCounts?: Record<string, number>;
149
168
  }
150
169
  export interface RenderOptions extends ParseOptions {
151
170
  highlighter?: CodeHighlighter;
@@ -175,4 +194,9 @@ export interface LinkReferenceDefinition {
175
194
  href: string;
176
195
  title?: string;
177
196
  }
197
+ export interface FootnoteDefinition {
198
+ label: string;
199
+ content: string;
200
+ id?: string;
201
+ }
178
202
  //# sourceMappingURL=types.d.ts.map
@@ -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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"}
package/dist/utils.d.ts CHANGED
@@ -8,5 +8,6 @@ export declare function plainText(nodes: InlineNode[]): string;
8
8
  export declare function createSlugger(): (value: string) => string;
9
9
  export declare function sanitizeUrl(value: string): string;
10
10
  export declare function normalizeReferenceLabel(value: string): string;
11
+ export declare function footnoteId(label: string): string;
11
12
  export declare function splitLines(value: string): string[];
12
13
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAU5C,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,KAGnB,OAAO,MAAM,YActB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;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,MAAM,YAAY,CAAA;AAU5C,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,KAGnB,OAAO,MAAM,YActB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAIlD"}
package/dist/utils.js CHANGED
@@ -65,6 +65,11 @@ export function sanitizeUrl(value) {
65
65
  export function normalizeReferenceLabel(value) {
66
66
  return value.trim().toLowerCase();
67
67
  }
68
+ export function footnoteId(label) {
69
+ return normalizeReferenceLabel(label)
70
+ .replace(/[^a-z0-9_-]+/g, '-')
71
+ .replace(/^-+|-+$/g, '');
72
+ }
68
73
  export function splitLines(value) {
69
74
  const lines = value.split('\n');
70
75
  if (lines.at(-1) === '')
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@tanstack/markdown",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "type": "module",
5
5
  "description": "A tiny deterministic TanStack-flavored markdown renderer.",
6
6
  "license": "MIT",
7
+ "packageManager": "pnpm@11.4.0",
7
8
  "sideEffects": false,
8
9
  "files": [
9
10
  "dist",
@@ -52,6 +53,14 @@
52
53
  "import": "./dist/extensions/tabs.js"
53
54
  }
54
55
  },
56
+ "scripts": {
57
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
58
+ "typecheck": "tsc --noEmit",
59
+ "test": "vitest run",
60
+ "bench": "tsx scripts/bench.ts",
61
+ "size": "tsx scripts/measure-size.ts",
62
+ "research": "pnpm run size && pnpm run bench"
63
+ },
55
64
  "publishConfig": {
56
65
  "access": "public"
57
66
  },
@@ -82,13 +91,5 @@
82
91
  "typescript": "^5.8.0",
83
92
  "unified": "^11.0.5",
84
93
  "vitest": "^3.2.0"
85
- },
86
- "scripts": {
87
- "build": "rm -rf dist && tsc -p tsconfig.build.json",
88
- "typecheck": "tsc --noEmit",
89
- "test": "vitest run",
90
- "bench": "tsx scripts/bench.ts",
91
- "size": "tsx scripts/measure-size.ts",
92
- "research": "pnpm run size && pnpm run bench"
93
94
  }
94
- }
95
+ }