svelte-streamdown 2.3.1 → 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.
- package/README.md +101 -82
- package/dist/Block.svelte +1 -1
- package/dist/Elements/Element.svelte +12 -2
- package/dist/Elements/index.d.ts +0 -1
- package/dist/Elements/index.js +0 -1
- package/dist/Streamdown.svelte +9 -1
- package/dist/context.svelte.d.ts +7 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/marked/index.d.ts +15 -3
- package/dist/marked/index.js +21 -33
- package/dist/marked/marked-alert.d.ts +2 -8
- package/dist/marked/marked-alert.js +14 -20
- package/dist/marked/marked-br.d.ts +2 -8
- package/dist/marked/marked-br.js +15 -21
- package/dist/marked/marked-footnotes.d.ts +2 -9
- package/dist/marked/marked-footnotes.js +55 -58
- package/dist/marked/marked-hr.d.ts +2 -8
- package/dist/marked/marked-hr.js +18 -24
- package/dist/marked/marked-list.d.ts +3 -9
- package/dist/marked/marked-list.js +176 -182
- package/dist/marked/marked-math.d.ts +2 -9
- package/dist/marked/marked-math.js +65 -69
- package/dist/marked/marked-subsup.d.ts +3 -9
- package/dist/marked/marked-subsup.js +38 -43
- package/dist/marked/marked-table.d.ts +2 -9
- package/dist/marked/marked-table.js +114 -123
- package/package.json +1 -2
|
@@ -15,86 +15,82 @@ const currencyPatterns = {
|
|
|
15
15
|
// Common currency words nearby (check surrounding context)
|
|
16
16
|
currencyContext: /(?:price|cost|dollar|euro|pound|yen|currency|pay|buy|sell|expensive|cheap)/i
|
|
17
17
|
};
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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;
|
|
37
47
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
let index = 0;
|
|
44
|
-
let searchSrc = src;
|
|
45
|
-
while (searchSrc) {
|
|
46
|
-
const dollarIndex = searchSrc.indexOf('$');
|
|
47
|
-
if (dollarIndex === -1) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const currentIndex = index + dollarIndex;
|
|
51
|
-
const possibleMath = src.substring(currentIndex);
|
|
52
|
-
// Check if this could be math (not currency)
|
|
53
|
-
if (possibleMath.match(inlineRule)) {
|
|
54
|
-
const match = possibleMath.match(inlineRule);
|
|
55
|
-
if (match) {
|
|
56
|
-
const content = match[2];
|
|
57
|
-
const dollarCount = match[1]; // '$' or '$$'
|
|
58
|
-
// Only apply currency detection to single dollars
|
|
59
|
-
// Double dollars ($$) indicate explicit math intent
|
|
60
|
-
if (dollarCount === '$' && isCurrencyPattern(content, src, currentIndex)) {
|
|
61
|
-
// This looks like currency with single dollars, skip it
|
|
62
|
-
index += dollarIndex + 1;
|
|
63
|
-
searchSrc = src.substring(index);
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
return currentIndex;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
index += dollarIndex + 1;
|
|
70
|
-
searchSrc = src.substring(index);
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
tokenizer(src) {
|
|
74
|
-
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);
|
|
75
53
|
if (match) {
|
|
76
54
|
const content = match[2];
|
|
77
55
|
const dollarCount = match[1]; // '$' or '$$'
|
|
78
|
-
const isDisplayMode = dollarCount === '$$';
|
|
79
56
|
// Only apply currency detection to single dollars
|
|
80
57
|
// Double dollars ($$) indicate explicit math intent
|
|
81
|
-
if (dollarCount === '$' && isCurrencyPattern(content, src,
|
|
58
|
+
if (dollarCount === '$' && isCurrencyPattern(content, src, currentIndex)) {
|
|
82
59
|
// This looks like currency with single dollars, skip it
|
|
83
|
-
|
|
60
|
+
index += dollarIndex + 1;
|
|
61
|
+
searchSrc = src.substring(index);
|
|
62
|
+
continue;
|
|
84
63
|
}
|
|
85
|
-
return
|
|
86
|
-
type: 'math',
|
|
87
|
-
isInline: true, // Inline tokenizer always produces inline math
|
|
88
|
-
displayMode: isDisplayMode, // $$ = display mode styling, $ = inline styling
|
|
89
|
-
raw: match[0],
|
|
90
|
-
text: content.trim()
|
|
91
|
-
};
|
|
64
|
+
return currentIndex;
|
|
92
65
|
}
|
|
93
66
|
}
|
|
67
|
+
index += dollarIndex + 1;
|
|
68
|
+
searchSrc = src.substring(index);
|
|
94
69
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
];
|
|
98
94
|
// Helper function to detect currency patterns
|
|
99
95
|
function isCurrencyPattern(content, fullSrc, dollarIndex) {
|
|
100
96
|
const trimmedContent = content.trim();
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare
|
|
3
|
-
|
|
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
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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 {
|
|
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
|
|
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
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
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
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-streamdown",
|
|
3
|
-
"version": "2.3.
|
|
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",
|