svelte-streamdown 2.3.1 → 2.3.3
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 +108 -82
- package/dist/Block.svelte +1 -1
- package/dist/Elements/Element.svelte +36 -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 +12 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/marked/index.d.ts +17 -4
- package/dist/marked/index.js +22 -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-dl.d.ts +24 -0
- package/dist/marked/marked-dl.js +45 -0
- 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/dist/theme.d.ts +36 -0
- package/dist/theme.js +25 -1
- package/package.json +1 -2
|
@@ -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/dist/theme.d.ts
CHANGED
|
@@ -128,6 +128,18 @@ export declare const theme: {
|
|
|
128
128
|
footnotePopover: {
|
|
129
129
|
base: string;
|
|
130
130
|
};
|
|
131
|
+
descriptionList: {
|
|
132
|
+
base: string;
|
|
133
|
+
};
|
|
134
|
+
description: {
|
|
135
|
+
base: string;
|
|
136
|
+
};
|
|
137
|
+
descriptionTerm: {
|
|
138
|
+
base: string;
|
|
139
|
+
};
|
|
140
|
+
descriptionDetail: {
|
|
141
|
+
base: string;
|
|
142
|
+
};
|
|
131
143
|
};
|
|
132
144
|
export declare const shadcnTheme: {
|
|
133
145
|
link: {
|
|
@@ -257,6 +269,18 @@ export declare const shadcnTheme: {
|
|
|
257
269
|
footnotePopover: {
|
|
258
270
|
base: string;
|
|
259
271
|
};
|
|
272
|
+
descriptionList: {
|
|
273
|
+
base: string;
|
|
274
|
+
};
|
|
275
|
+
description: {
|
|
276
|
+
base: string;
|
|
277
|
+
};
|
|
278
|
+
descriptionTerm: {
|
|
279
|
+
base: string;
|
|
280
|
+
};
|
|
281
|
+
descriptionDetail: {
|
|
282
|
+
base: string;
|
|
283
|
+
};
|
|
260
284
|
};
|
|
261
285
|
export type Theme = typeof theme;
|
|
262
286
|
type DeepPartial<T> = {
|
|
@@ -391,5 +415,17 @@ export declare const mergeTheme: (customTheme?: DeepPartialTheme, baseTheme?: "t
|
|
|
391
415
|
footnotePopover: {
|
|
392
416
|
base: string;
|
|
393
417
|
};
|
|
418
|
+
descriptionList: {
|
|
419
|
+
base: string;
|
|
420
|
+
};
|
|
421
|
+
description: {
|
|
422
|
+
base: string;
|
|
423
|
+
};
|
|
424
|
+
descriptionTerm: {
|
|
425
|
+
base: string;
|
|
426
|
+
};
|
|
427
|
+
descriptionDetail: {
|
|
428
|
+
base: string;
|
|
429
|
+
};
|
|
394
430
|
};
|
|
395
431
|
export {};
|
package/dist/theme.js
CHANGED
|
@@ -128,6 +128,18 @@ export const theme = {
|
|
|
128
128
|
},
|
|
129
129
|
footnotePopover: {
|
|
130
130
|
base: 'fixed z-50 max-h-[30vh] max-w-3xl overflow-y-auto rounded-lg bg-background p-4 shadow'
|
|
131
|
+
},
|
|
132
|
+
descriptionList: {
|
|
133
|
+
base: 'my-4 space-y-2'
|
|
134
|
+
},
|
|
135
|
+
description: {
|
|
136
|
+
base: 'border-l-2 border-gray-200 pl-4'
|
|
137
|
+
},
|
|
138
|
+
descriptionTerm: {
|
|
139
|
+
base: 'font-semibold text-gray-900'
|
|
140
|
+
},
|
|
141
|
+
descriptionDetail: {
|
|
142
|
+
base: 'text-gray-700 ml-4 leading-relaxed'
|
|
131
143
|
}
|
|
132
144
|
};
|
|
133
145
|
export const shadcnTheme = {
|
|
@@ -247,7 +259,7 @@ export const shadcnTheme = {
|
|
|
247
259
|
base: ''
|
|
248
260
|
},
|
|
249
261
|
em: {
|
|
250
|
-
base: 'italic
|
|
262
|
+
base: 'italic'
|
|
251
263
|
},
|
|
252
264
|
del: {
|
|
253
265
|
base: 'text-muted-foreground'
|
|
@@ -257,6 +269,18 @@ export const shadcnTheme = {
|
|
|
257
269
|
},
|
|
258
270
|
footnotePopover: {
|
|
259
271
|
base: 'fixed z-50 max-h-[30vh] shadow max-w-3xl overflow-y-auto rounded-lg bg-background p-4'
|
|
272
|
+
},
|
|
273
|
+
descriptionList: {
|
|
274
|
+
base: 'my-4 space-y-2'
|
|
275
|
+
},
|
|
276
|
+
description: {
|
|
277
|
+
base: 'border-l-2 border-border pl-4'
|
|
278
|
+
},
|
|
279
|
+
descriptionTerm: {
|
|
280
|
+
base: 'font-semibold text-foreground'
|
|
281
|
+
},
|
|
282
|
+
descriptionDetail: {
|
|
283
|
+
base: 'text-muted-foreground ml-4 leading-relaxed'
|
|
260
284
|
}
|
|
261
285
|
};
|
|
262
286
|
export const mergeTheme = (customTheme, baseTheme) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-streamdown",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.3",
|
|
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",
|