svelte-streamdown 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,75 +4,121 @@ const blockRule = /^(\$\$)(?:\n((?:\\[\s\S]|[^\\])+?)\n\1(?:\n|$)|([^$\n]+?)\1(?
4
4
  // Inline math: handles both single ($) and double ($$) dollar delimiters
5
5
  // Avoids matching currency by checking context and requiring proper content
6
6
  const inlineRule = /^(\${1,2})(?!\$)((?:[^$\n]|\\\$)*?)\1(?!\d)/;
7
- export function markedMath() {
8
- return {
9
- extensions: [
10
- {
11
- name: 'math',
12
- level: 'block',
13
- tokenizer(src) {
14
- const match = src.match(blockRule);
15
- if (match) {
16
- // match[2] is multiline format, match[3] is single-line format
17
- const content = (match[2] || match[3]).trim();
18
- return {
19
- type: 'math',
20
- isInline: false,
21
- displayMode: true,
22
- raw: match[0],
23
- text: content
24
- };
25
- }
7
+ // Enhanced currency detection patterns
8
+ const currencyPatterns = {
9
+ // Simple price patterns: $123, $123.45, $1,234.56
10
+ simplePrice: /^\d{1,3}(?:,\d{3})*(?:\.\d{2})?$/,
11
+ // Multiple prices or numbers: "123, 456", "123.45, 678.90", "123 or 456"
12
+ multipleNumbers: /^\d+(?:[.,]\d+)*(?:\s*[,;]\s*\d+(?:[.,]\d+)*)+$/,
13
+ // Price ranges: "123-456", "123 - 456", "123 to 456"
14
+ priceRange: /^\d+(?:\.\d{2})?\s*(?:-|to|or)\s*\d+(?:\.\d{2})?$/i,
15
+ // Common currency words nearby (check surrounding context)
16
+ currencyContext: /(?:price|cost|dollar|euro|pound|yen|currency|pay|buy|sell|expensive|cheap)/i
17
+ };
18
+ export const markedMath = [
19
+ {
20
+ name: 'math',
21
+ level: 'block',
22
+ tokenizer(src) {
23
+ const match = src.match(blockRule);
24
+ if (match) {
25
+ // match[2] is multiline format, match[3] is single-line format
26
+ const content = (match[2] || match[3]).trim();
27
+ return {
28
+ type: 'math',
29
+ isInline: false,
30
+ displayMode: true,
31
+ raw: match[0],
32
+ text: content
33
+ };
34
+ }
35
+ }
36
+ },
37
+ {
38
+ name: 'math',
39
+ level: 'inline',
40
+ start(src) {
41
+ let index = 0;
42
+ let searchSrc = src;
43
+ while (searchSrc) {
44
+ const dollarIndex = searchSrc.indexOf('$');
45
+ if (dollarIndex === -1) {
46
+ return;
26
47
  }
27
- },
28
- {
29
- name: 'math',
30
- level: 'inline',
31
- start(src) {
32
- let index = 0;
33
- let searchSrc = src;
34
- while (searchSrc) {
35
- const dollarIndex = searchSrc.indexOf('$');
36
- if (dollarIndex === -1) {
37
- return;
38
- }
39
- const currentIndex = index + dollarIndex;
40
- const possibleMath = src.substring(currentIndex);
41
- // Check if this could be math (not currency)
42
- if (possibleMath.match(inlineRule)) {
43
- // Additional check: avoid currency patterns like $5.00
44
- const beforeChar = currentIndex > 0 ? src[currentIndex - 1] : '';
45
- const afterDollar = possibleMath.substring(1, 6); // Check first few chars after $
46
- // Skip if it looks like currency (digit immediately after $ or decimal pattern)
47
- if (!/^\d+(\.\d{2})?\s/.test(afterDollar)) {
48
- return currentIndex;
49
- }
50
- }
51
- index += dollarIndex + 1;
52
- searchSrc = src.substring(index);
53
- }
54
- },
55
- tokenizer(src) {
56
- const match = src.match(inlineRule);
48
+ const currentIndex = index + dollarIndex;
49
+ const possibleMath = src.substring(currentIndex);
50
+ // Check if this could be math (not currency)
51
+ if (possibleMath.match(inlineRule)) {
52
+ const match = possibleMath.match(inlineRule);
57
53
  if (match) {
58
- // Additional validation: avoid currency patterns
59
54
  const content = match[2];
60
- if (/^\d+(\.\d{2})?$/.test(content.trim())) {
61
- // This looks like currency, skip it
62
- return;
55
+ const dollarCount = match[1]; // '$' or '$$'
56
+ // Only apply currency detection to single dollars
57
+ // Double dollars ($$) indicate explicit math intent
58
+ if (dollarCount === '$' && isCurrencyPattern(content, src, currentIndex)) {
59
+ // This looks like currency with single dollars, skip it
60
+ index += dollarIndex + 1;
61
+ searchSrc = src.substring(index);
62
+ continue;
63
63
  }
64
- // Double dollars are display mode, single dollars are inline
65
- const isDisplayMode = match[1] === '$$';
66
- return {
67
- type: 'math',
68
- isInline: !isDisplayMode,
69
- displayMode: isDisplayMode,
70
- raw: match[0],
71
- text: content.trim()
72
- };
64
+ return currentIndex;
73
65
  }
74
66
  }
67
+ index += dollarIndex + 1;
68
+ searchSrc = src.substring(index);
69
+ }
70
+ },
71
+ tokenizer(src) {
72
+ const match = src.match(inlineRule);
73
+ if (match) {
74
+ const content = match[2];
75
+ const dollarCount = match[1]; // '$' or '$$'
76
+ const isDisplayMode = dollarCount === '$$';
77
+ // Only apply currency detection to single dollars
78
+ // Double dollars ($$) indicate explicit math intent
79
+ if (dollarCount === '$' && isCurrencyPattern(content, src, 0)) {
80
+ // This looks like currency with single dollars, skip it
81
+ return;
82
+ }
83
+ return {
84
+ type: 'math',
85
+ isInline: true, // Inline tokenizer always produces inline math
86
+ displayMode: isDisplayMode, // $$ = display mode styling, $ = inline styling
87
+ raw: match[0],
88
+ text: content.trim()
89
+ };
75
90
  }
76
- ]
77
- };
91
+ }
92
+ }
93
+ ];
94
+ // Helper function to detect currency patterns
95
+ function isCurrencyPattern(content, fullSrc, dollarIndex) {
96
+ const trimmedContent = content.trim();
97
+ // Check for simple price patterns
98
+ if (currencyPatterns.simplePrice.test(trimmedContent)) {
99
+ return true;
100
+ }
101
+ // Check for multiple numbers/prices pattern (like "199, 199")
102
+ if (currencyPatterns.multipleNumbers.test(trimmedContent)) {
103
+ return true;
104
+ }
105
+ // Check for price ranges
106
+ if (currencyPatterns.priceRange.test(trimmedContent)) {
107
+ return true;
108
+ }
109
+ // Check surrounding context for currency-related words
110
+ const contextStart = Math.max(0, dollarIndex - 50);
111
+ const contextEnd = Math.min(fullSrc.length, dollarIndex + content.length + 50);
112
+ const context = fullSrc.substring(contextStart, contextEnd);
113
+ if (currencyPatterns.currencyContext.test(context)) {
114
+ // If currency context is found and content is purely numeric, likely currency
115
+ if (/^\d+(?:[.,]\d+)*$/.test(trimmedContent)) {
116
+ return true;
117
+ }
118
+ }
119
+ // Additional check: if content is just numbers with common currency formatting
120
+ if (/^\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?$/.test(trimmedContent)) {
121
+ return true;
122
+ }
123
+ return false;
78
124
  }
@@ -1,12 +1,6 @@
1
- import type { TokenizerExtensionFunction, TokenizerStartFunction } from 'marked';
2
- export declare function markedSubSup(): {
3
- extensions: {
4
- name: string;
5
- level: 'inline';
6
- tokenizer: TokenizerExtensionFunction;
7
- start?: TokenizerStartFunction;
8
- }[];
9
- };
1
+ import type { Extension } from './index.js';
2
+ export declare const markedSub: Extension;
3
+ export declare const markedSup: Extension;
10
4
  /**
11
5
  * Represents a subscript token.
12
6
  */
@@ -1,45 +1,40 @@
1
1
  const subRule = /^~([^~\s](?:[^~]*[^~\s])?)~/; // ~text~
2
2
  const supRule = /^\^([^\^\s](?:[^\^]*[^\^\s])?)\^/; // ^text^
3
- export function markedSubSup() {
4
- return {
5
- extensions: [
6
- {
7
- name: 'sub',
8
- level: 'inline',
9
- start(src) {
10
- const i = src.indexOf('~');
11
- return i === -1 ? undefined : i;
12
- },
13
- tokenizer(src) {
14
- const match = src.match(subRule);
15
- if (match) {
16
- return {
17
- type: 'sub',
18
- raw: match[0],
19
- text: match[1],
20
- tokens: this.lexer.inlineTokens(match[1])
21
- };
22
- }
23
- }
24
- },
25
- {
26
- name: 'sup',
27
- level: 'inline',
28
- start(src) {
29
- return src.indexOf('^');
30
- },
31
- tokenizer(src) {
32
- const match = src.match(supRule);
33
- if (match) {
34
- return {
35
- type: 'sup',
36
- raw: match[0],
37
- text: match[1],
38
- tokens: this.lexer.inlineTokens(match[1])
39
- };
40
- }
41
- }
42
- }
43
- ]
44
- };
45
- }
3
+ export const markedSub = {
4
+ name: 'sub',
5
+ level: 'inline',
6
+ start(src) {
7
+ const i = src.indexOf('~');
8
+ return i === -1 ? undefined : i;
9
+ },
10
+ tokenizer(src) {
11
+ const match = src.match(subRule);
12
+ if (match) {
13
+ return {
14
+ type: 'sub',
15
+ raw: match[0],
16
+ text: match[1],
17
+ tokens: this.lexer.inlineTokens(match[1])
18
+ };
19
+ }
20
+ }
21
+ };
22
+ export const markedSup = {
23
+ name: 'sup',
24
+ level: 'inline',
25
+ start(src) {
26
+ const i = src.indexOf('^');
27
+ return i === -1 ? undefined : i;
28
+ },
29
+ tokenizer(src) {
30
+ const match = src.match(supRule);
31
+ if (match) {
32
+ return {
33
+ type: 'sup',
34
+ raw: match[0],
35
+ text: match[1],
36
+ tokens: this.lexer.inlineTokens(match[1])
37
+ };
38
+ }
39
+ }
40
+ };
@@ -1,4 +1,4 @@
1
- import type { TokenizerExtensionFunction, TokenizerStartFunction } from 'marked';
1
+ import type { Extension } from './index.js';
2
2
  export interface SpanTableOptions {
3
3
  useTheadTbody?: boolean;
4
4
  useTfoot?: boolean;
@@ -56,12 +56,5 @@ type WorkingRow = WorkingCell[];
56
56
  export declare const DEFAULT_OPTIONS: Required<SpanTableOptions>;
57
57
  export declare const getTableCell: (text: string, cell: BaseCell, type: "th" | "td", align: string | null) => string;
58
58
  export declare const splitCells: (tableRow: string, count: number | null, prevRow?: WorkingRow | null, maxColspan?: number | null) => WorkingRow;
59
- export declare function markedTable(options?: SpanTableOptions): {
60
- extensions: {
61
- name: string;
62
- level: 'block' | 'inline';
63
- start: TokenizerStartFunction;
64
- tokenizer: TokenizerExtensionFunction;
65
- }[];
66
- };
59
+ export declare const markedTable: Extension;
67
60
  export {};
@@ -116,8 +116,7 @@ const processSpans = (cells, count, prevRow = [], maxColspan = null) => {
116
116
  let cellText = cell.text;
117
117
  // Handle Rowspan - cells ending with ^ (but not superscript ^text^)
118
118
  // Check if it's a rowspan indicator (single ^ at end) vs superscript (^text^)
119
- const isRowspanIndicator = cellText.slice(-1) === '^' &&
120
- !cellText.match(/\^[^^\n\r]+\^$/); // Not a superscript pattern ^text^
119
+ const isRowspanIndicator = cellText.slice(-1) === '^' && !cellText.match(/\^[^^\n\r]+\^$/); // Not a superscript pattern ^text^
121
120
  if (isRowspanIndicator && prevRow.length > 0) {
122
121
  // Clean the ^ indicator from the cell text
123
122
  cell.text = cellText.slice(0, -1).trim();
@@ -374,129 +373,121 @@ function processRows(headerRows, bodyRows, alignment, colCount, lexer, maxColspa
374
373
  }
375
374
  return tokens;
376
375
  }
376
+ const { detectFooter, maxColspan } = DEFAULT_OPTIONS;
377
377
  // Adds support for extended tables in marked with row spanning, column spanning,
378
378
  // multi-row headers, and column alignment
379
- export function markedTable(options = {}) {
380
- const config = { ...DEFAULT_OPTIONS, ...options };
381
- const { detectFooter, maxColspan } = config;
382
- return {
383
- extensions: [
384
- {
385
- name: 'table',
386
- level: 'block',
387
- start(src) {
388
- // Check for table with potential header alignment
389
- let match = src.match(/^\n *([^\n ].*\|.*)\n/);
390
- if (match)
391
- return match.index;
392
- // Check for simple table without header alignment
393
- match = src.match(/^\n *(\|.*\|)\n/);
394
- if (match)
395
- return match.index;
379
+ export const markedTable = {
380
+ name: 'table',
381
+ level: 'block',
382
+ start(src) {
383
+ // Check for table with potential header alignment
384
+ let match = src.match(/^\n *([^\n ].*\|.*)\n/);
385
+ if (match)
386
+ return match.index;
387
+ // Check for simple table without header alignment
388
+ match = src.match(/^\n *(\|.*\|)\n/);
389
+ if (match)
390
+ return match.index;
391
+ return undefined;
392
+ },
393
+ tokenizer(src) {
394
+ // Try to match table with header and alignment first
395
+ let regex = new RegExp('^' +
396
+ '([^\\n ].*\\|.*\\n(?: *[^\\s].*\\n)*?)' + // Header
397
+ ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?' + // Header Align
398
+ '(?:\\n((?:(?! *\\n| {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})' + // Body Cells
399
+ '(?:\\n+|$)| {0,3}#{1,6} | {0,3}>| {4}[^\\n]| {0,3}(?:`{3,}' +
400
+ '(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n| {0,3}(?:[*+-]|1[.)]) |' +
401
+ '<\\/?(?:address|article|aside|base|basefont|blockquote|body|' +
402
+ 'caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(?: +|\\n|\\/?>)|<(?:script|pre|style|textarea|!--)).*(?:\\n|$))*)\\n*|$)');
403
+ let cap = regex.exec(src);
404
+ let hasHeaderAlignment = true;
405
+ // If no match with header alignment, try table without header alignment
406
+ if (!cap) {
407
+ // Simple regex for tables without header alignment
408
+ regex = /^(\|.*\|(?:\n\|.*\|)*)/;
409
+ cap = regex.exec(src);
410
+ hasHeaderAlignment = false;
411
+ }
412
+ if (!cap)
413
+ return undefined;
414
+ // Combine all captured groups to get complete table rows
415
+ let allTableContent = cap[1]; // Headers
416
+ if (cap[2])
417
+ allTableContent += '\n' + cap[2]; // Alignment row
418
+ if (cap[3])
419
+ allTableContent += '\n' + cap[3]; // Body rows
420
+ const allRows = allTableContent.replace(/\n$/, '').split('\n');
421
+ let headerRows = [];
422
+ let bodyRows = [];
423
+ let alignRow = [];
424
+ let alignment = [];
425
+ let colCount = 0;
426
+ if (hasHeaderAlignment) {
427
+ // Traditional table with header and alignment
428
+ // Parse all rows and identify which are headers vs body
429
+ let headerEndIndex = -1;
430
+ // Find the FIRST alignment row (contains dashes/underscores/asterisks)
431
+ for (let i = 0; i < allRows.length; i++) {
432
+ const row = allRows[i].trim();
433
+ const isAlignment = /^ *(\| *)?:?-+:? *(\| *:?-+:? *)*(\| *)?$/.test(row);
434
+ // Check if this row matches alignment pattern (contains only |, spaces, and alignment chars)
435
+ if (isAlignment) {
436
+ headerEndIndex = i;
437
+ alignRow = row.replace(/^ *\| *| *\| *$/g, '').split(/ *\| */);
438
+ break; // Stop at the first alignment row
439
+ }
440
+ }
441
+ if (headerEndIndex === -1) {
442
+ // No alignment row found, treat as simple table
443
+ bodyRows = allRows;
444
+ colCount = bodyRows[0].split('|').filter((cell) => cell.trim() !== '').length;
445
+ alignment = new Array(colCount).fill(null);
446
+ }
447
+ else {
448
+ // Found alignment row, split headers and body
449
+ // Filter out empty rows and the alignment row itself from headers
450
+ headerRows = allRows.slice(0, headerEndIndex).filter((row) => row.trim() !== '');
451
+ bodyRows = headerEndIndex + 1 < allRows.length ? allRows.slice(headerEndIndex + 1) : [];
452
+ // Use alignment row length as the authoritative column count
453
+ colCount = alignRow.length;
454
+ // Validate that we have a reasonable table structure
455
+ if (colCount === 0)
396
456
  return undefined;
397
- },
398
- tokenizer(src) {
399
- // Try to match table with header and alignment first
400
- let regex = new RegExp('^' +
401
- '([^\\n ].*\\|.*\\n(?: *[^\\s].*\\n)*?)' + // Header
402
- ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?' + // Header Align
403
- '(?:\\n((?:(?! *\\n| {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})' + // Body Cells
404
- '(?:\\n+|$)| {0,3}#{1,6} | {0,3}>| {4}[^\\n]| {0,3}(?:`{3,}' +
405
- '(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n| {0,3}(?:[*+-]|1[.)]) |' +
406
- '<\\/?(?:address|article|aside|base|basefont|blockquote|body|' +
407
- 'caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(?: +|\\n|\\/?>)|<(?:script|pre|style|textarea|!--)).*(?:\\n|$))*)\\n*|$)');
408
- let cap = regex.exec(src);
409
- let hasHeaderAlignment = true;
410
- // If no match with header alignment, try table without header alignment
411
- if (!cap) {
412
- // Simple regex for tables without header alignment
413
- regex = /^(\|.*\|(?:\n\|.*\|)*)/;
414
- cap = regex.exec(src);
415
- hasHeaderAlignment = false;
416
- }
417
- if (!cap)
418
- return null;
419
- // Combine all captured groups to get complete table rows
420
- let allTableContent = cap[1]; // Headers
421
- if (cap[2])
422
- allTableContent += '\n' + cap[2]; // Alignment row
423
- if (cap[3])
424
- allTableContent += '\n' + cap[3]; // Body rows
425
- const allRows = allTableContent.replace(/\n$/, '').split('\n');
426
- let headerRows = [];
427
- let bodyRows = [];
428
- let alignRow = [];
429
- let alignment = [];
430
- let colCount = 0;
431
- if (hasHeaderAlignment) {
432
- // Traditional table with header and alignment
433
- // Parse all rows and identify which are headers vs body
434
- let headerEndIndex = -1;
435
- // Find the FIRST alignment row (contains dashes/underscores/asterisks)
436
- for (let i = 0; i < allRows.length; i++) {
437
- const row = allRows[i].trim();
438
- const isAlignment = /^ *(\| *)?:?-+:? *(\| *:?-+:? *)*(\| *)?$/.test(row);
439
- // Check if this row matches alignment pattern (contains only |, spaces, and alignment chars)
440
- if (isAlignment) {
441
- headerEndIndex = i;
442
- alignRow = row.replace(/^ *\| *| *\| *$/g, '').split(/ *\| */);
443
- break; // Stop at the first alignment row
444
- }
445
- }
446
- if (headerEndIndex === -1) {
447
- // No alignment row found, treat as simple table
448
- bodyRows = allRows;
449
- colCount = bodyRows[0].split('|').filter((cell) => cell.trim() !== '').length;
450
- alignment = new Array(colCount).fill(null);
451
- }
452
- else {
453
- // Found alignment row, split headers and body
454
- // Filter out empty rows and the alignment row itself from headers
455
- headerRows = allRows.slice(0, headerEndIndex).filter((row) => row.trim() !== '');
456
- bodyRows =
457
- headerEndIndex + 1 < allRows.length ? allRows.slice(headerEndIndex + 1) : [];
458
- // Use alignment row length as the authoritative column count
459
- colCount = alignRow.length;
460
- // Validate that we have a reasonable table structure
461
- if (colCount === 0)
462
- return null;
463
- // Process alignment
464
- alignment = processAlignment(alignRow);
465
- }
466
- }
467
- else {
468
- // Table without header alignment - treat all rows as body rows
469
- bodyRows = allRows;
470
- const firstRowCells = bodyRows[0].split('|').filter((cell) => cell.trim() !== '');
471
- colCount = firstRowCells.length;
472
- alignment = new Array(colCount).fill(null); // No alignment for tables without headers
473
- }
474
- // Detect footer alignment row pattern in body rows (only for tables with header alignment)
475
- let shouldDetectFooter = false;
476
- let processedBodyRows = bodyRows;
477
- if (detectFooter && hasHeaderAlignment && bodyRows.length > 0) {
478
- // Check if any row matches the alignment pattern (contains only dashes, pipes, colons, and spaces)
479
- for (let i = bodyRows.length - 1; i >= 0; i--) {
480
- const row = bodyRows[i];
481
- if (/^ *\| *:?-+:? *(\| *:?-+:? *)*\| *$/.test(row)) {
482
- // Found footer alignment row - remove it and enable footer detection
483
- shouldDetectFooter = true;
484
- processedBodyRows = bodyRows.slice(0, i).concat(bodyRows.slice(i + 1));
485
- break;
486
- }
487
- }
488
- }
489
- // Process all rows and create table sections
490
- const tokens = processRows(headerRows, processedBodyRows, alignment, colCount, this.lexer, maxColspan, shouldDetectFooter);
491
- const item = {
492
- type: 'table',
493
- tokens,
494
- raw: cap[0],
495
- align: alignment
496
- };
497
- return item;
457
+ // Process alignment
458
+ alignment = processAlignment(alignRow);
459
+ }
460
+ }
461
+ else {
462
+ // Table without header alignment - treat all rows as body rows
463
+ bodyRows = allRows;
464
+ const firstRowCells = bodyRows[0].split('|').filter((cell) => cell.trim() !== '');
465
+ colCount = firstRowCells.length;
466
+ alignment = new Array(colCount).fill(null); // No alignment for tables without headers
467
+ }
468
+ // Detect footer alignment row pattern in body rows (only for tables with header alignment)
469
+ let shouldDetectFooter = false;
470
+ let processedBodyRows = bodyRows;
471
+ if (detectFooter && hasHeaderAlignment && bodyRows.length > 0) {
472
+ // Check if any row matches the alignment pattern (contains only dashes, pipes, colons, and spaces)
473
+ for (let i = bodyRows.length - 1; i >= 0; i--) {
474
+ const row = bodyRows[i];
475
+ if (/^ *\| *:?-+:? *(\| *:?-+:? *)*\| *$/.test(row)) {
476
+ // Found footer alignment row - remove it and enable footer detection
477
+ shouldDetectFooter = true;
478
+ processedBodyRows = bodyRows.slice(0, i).concat(bodyRows.slice(i + 1));
479
+ break;
498
480
  }
499
481
  }
500
- ]
501
- };
502
- }
482
+ }
483
+ // Process all rows and create table sections
484
+ const tokens = processRows(headerRows, processedBodyRows, alignment, colCount, this.lexer, maxColspan, shouldDetectFooter);
485
+ const item = {
486
+ type: 'table',
487
+ tokens,
488
+ raw: cap[0],
489
+ align: alignment
490
+ };
491
+ return item;
492
+ }
493
+ };
package/dist/theme.js CHANGED
@@ -121,7 +121,7 @@ export const theme = {
121
121
  base: 'italic'
122
122
  },
123
123
  del: {
124
- base: 'line-through'
124
+ base: 'text-gray-600'
125
125
  },
126
126
  footnoteRef: {
127
127
  base: 'text-gray-600 px-1 py-0.5 rounded-md bg-gray-100/80'
@@ -250,7 +250,7 @@ export const shadcnTheme = {
250
250
  base: 'italic text-foreground'
251
251
  },
252
252
  del: {
253
- base: 'line-through text-muted-foreground'
253
+ base: 'text-muted-foreground'
254
254
  },
255
255
  footnoteRef: {
256
256
  base: 'text-muted-foreground px-1 text-sm inline-block rounded-full bg-muted/80 aspect-square border border-border'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-streamdown",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -73,7 +73,6 @@
73
73
  "dependencies": {
74
74
  "@floating-ui/dom": "^1.7.4",
75
75
  "clsx": "^2.1.1",
76
- "html-url-attributes": "^3.0.1",
77
76
  "katex": "^0.16.22",
78
77
  "marked": "^16.2.1",
79
78
  "mermaid": "^11.11.0",