ink-markdown-es 1.1.0 → 1.2.0
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 +2 -0
- package/dist/highlight.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +264 -126
- package/dist/types.d.ts +8 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -77,6 +77,7 @@ const TestApp = () => {
|
|
|
77
77
|
return (
|
|
78
78
|
<Markdown
|
|
79
79
|
showSharp
|
|
80
|
+
theme="dracula"
|
|
80
81
|
renderers={{
|
|
81
82
|
h1: (text) => (
|
|
82
83
|
<Box padding={1} borderStyle="round" borderDimColor>
|
|
@@ -105,6 +106,7 @@ render(<TestApp />);
|
|
|
105
106
|
- `styles` (BlockStyles, optional): Custom styles for markdown blocks.
|
|
106
107
|
- `renderers` (BlockRenderers, optional): Custom renderers for markdown blocks.
|
|
107
108
|
- `showSharp` (boolean, optional): Whether to show sharp signs for headings. Default is `false`.
|
|
109
|
+
- `theme` (string, optional): The theme for syntax highlighting. Default is `github-dark`. Check out [shiki](https://shiki.style/themes) for more themes.
|
|
108
110
|
|
|
109
111
|
## Contributing
|
|
110
112
|
|
package/dist/highlight.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function highlightCodeAsync(code: string, language?: string, theme?: string): Promise<ReactNode[] | null>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** biome-ignore-all lint/suspicious/noArrayIndexKey: <empty> */
|
|
2
2
|
import { type Token, type Tokens } from 'marked';
|
|
3
3
|
import type { MarkdownProps } from './types';
|
|
4
|
-
declare function MarkdownComponent({ children, id, styles, renderers, showSharp, highlight, }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
declare function MarkdownComponent({ children, id, styles, renderers, showSharp, highlight, theme, }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
declare const Markdown: import("react").MemoExoticComponent<typeof MarkdownComponent>;
|
|
6
6
|
export default Markdown;
|
|
7
7
|
export type { Token, Tokens };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { marked } from "marked";
|
|
4
|
-
import { memo, useId, useMemo } from "react";
|
|
5
|
-
import
|
|
4
|
+
import { memo, useEffect, useId, useMemo, useState } from "react";
|
|
5
|
+
import { codeToTokens } from "shiki";
|
|
6
6
|
const DEFAULT_STYLES = {
|
|
7
7
|
h1: {
|
|
8
8
|
bold: true,
|
|
@@ -122,97 +122,114 @@ const BOX_STYLE_KEYS = [
|
|
|
122
122
|
'borderRightDimColor'
|
|
123
123
|
];
|
|
124
124
|
const TERMINAL_COLORS = {
|
|
125
|
+
comment: 'gray',
|
|
126
|
+
'comment.block': 'gray',
|
|
127
|
+
'comment.line': 'gray',
|
|
125
128
|
keyword: 'magenta',
|
|
126
129
|
'keyword.control': 'magenta',
|
|
127
|
-
'keyword.
|
|
130
|
+
'keyword.other': 'magenta',
|
|
128
131
|
string: 'green',
|
|
129
|
-
'string.
|
|
130
|
-
|
|
131
|
-
function: 'blue',
|
|
132
|
-
'function
|
|
133
|
-
'function
|
|
132
|
+
'string.quoted': 'green',
|
|
133
|
+
'string.regexp': 'red',
|
|
134
|
+
'entity.name.function': 'blue',
|
|
135
|
+
'support.function': 'blueBright',
|
|
136
|
+
'meta.function-call': 'blueBright',
|
|
134
137
|
variable: 'white',
|
|
135
|
-
'variable.builtin': 'yellow',
|
|
136
138
|
'variable.parameter': 'yellowBright',
|
|
137
|
-
|
|
138
|
-
'type
|
|
139
|
-
class: 'yellowBright',
|
|
140
|
-
|
|
141
|
-
'
|
|
142
|
-
constant: 'yellow',
|
|
143
|
-
'constant.
|
|
139
|
+
'variable.other': 'white',
|
|
140
|
+
'entity.name.type': 'cyan',
|
|
141
|
+
'entity.name.class': 'yellowBright',
|
|
142
|
+
'support.type': 'cyanBright',
|
|
143
|
+
'support.class': 'yellowBright',
|
|
144
|
+
'constant.numeric': 'yellow',
|
|
145
|
+
'constant.language': 'yellow',
|
|
144
146
|
operator: 'cyan',
|
|
145
147
|
punctuation: 'white',
|
|
146
|
-
property: 'blue',
|
|
147
|
-
attribute: 'blue',
|
|
148
|
-
tag: 'red',
|
|
149
|
-
'tag
|
|
150
|
-
boolean: 'yellow',
|
|
151
|
-
null: 'yellow',
|
|
152
|
-
regexp: 'red',
|
|
148
|
+
'variable.other.property': 'blue',
|
|
149
|
+
'entity.other.attribute-name': 'blue',
|
|
150
|
+
'entity.name.tag': 'red',
|
|
151
|
+
'meta.tag': 'red',
|
|
152
|
+
'constant.language.boolean': 'yellow',
|
|
153
|
+
'constant.language.null': 'yellow',
|
|
153
154
|
meta: 'gray',
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
storage: 'magenta',
|
|
156
|
+
'storage.type': 'magenta'
|
|
156
157
|
};
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
'
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
'
|
|
171
|
-
'
|
|
172
|
-
'
|
|
173
|
-
'
|
|
174
|
-
'
|
|
175
|
-
'
|
|
176
|
-
'
|
|
177
|
-
' ': ' ',
|
|
178
|
-
' ': ' '
|
|
158
|
+
function hexToTerminalColor(hex) {
|
|
159
|
+
const colorMap = {
|
|
160
|
+
'#6a737d': 'gray',
|
|
161
|
+
'#8b949e': 'gray',
|
|
162
|
+
'#6e7681': 'gray',
|
|
163
|
+
'#d73a49': 'magenta',
|
|
164
|
+
'#f97583': 'magenta',
|
|
165
|
+
'#ff7b72': 'red',
|
|
166
|
+
'#032f62': 'green',
|
|
167
|
+
'#22863a': 'green',
|
|
168
|
+
'#7ee787': 'green',
|
|
169
|
+
'#005cc5': 'blue',
|
|
170
|
+
'#0366d6': 'blue',
|
|
171
|
+
'#79c0ff': 'cyan',
|
|
172
|
+
'#58a6ff': 'blueBright',
|
|
173
|
+
'#a5d6ff': 'cyan',
|
|
174
|
+
'#e36209': 'yellow',
|
|
175
|
+
'#d29922': 'yellow',
|
|
176
|
+
'#ffa657': 'yellow',
|
|
177
|
+
'#0550ae': 'cyan'
|
|
179
178
|
};
|
|
180
|
-
|
|
179
|
+
const normalized = hex.toLowerCase();
|
|
180
|
+
if (colorMap[normalized]) return colorMap[normalized];
|
|
181
|
+
const r = Number.parseInt(normalized.slice(1, 3), 16);
|
|
182
|
+
const g = Number.parseInt(normalized.slice(3, 5), 16);
|
|
183
|
+
const b = Number.parseInt(normalized.slice(5, 7), 16);
|
|
184
|
+
const brightness = (299 * r + 587 * g + 114 * b) / 1000;
|
|
185
|
+
if (brightness < 80) return 'gray';
|
|
186
|
+
if (r > g && r > b) return 'red';
|
|
187
|
+
if (g > r && g > b) return 'green';
|
|
188
|
+
if (b > r && b > g) return 'blue';
|
|
189
|
+
if (r > 150 && g > 150) return 'yellow';
|
|
190
|
+
if (g > 150 && b > 150) return 'cyan';
|
|
191
|
+
if (r > 150 && b > 150) return 'magenta';
|
|
181
192
|
}
|
|
182
|
-
function
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const text = decodeHtmlEntities(match[2]);
|
|
191
|
-
const color = classToColor(className);
|
|
192
|
-
result.push(/*#__PURE__*/ jsx(Text, {
|
|
193
|
-
color: color,
|
|
194
|
-
children: text
|
|
195
|
-
}, index));
|
|
196
|
-
} else if (match[3]) result.push(/*#__PURE__*/ jsx(Text, {
|
|
197
|
-
children: decodeHtmlEntities(match[3])
|
|
198
|
-
}, index));
|
|
199
|
-
index++;
|
|
200
|
-
match = regex.exec(html);
|
|
193
|
+
function tokenScopeToColor(scopes) {
|
|
194
|
+
for (const scope of scopes){
|
|
195
|
+
if (TERMINAL_COLORS[scope]) return TERMINAL_COLORS[scope];
|
|
196
|
+
const parts = scope.split('.');
|
|
197
|
+
for(let i = parts.length; i > 0; i--){
|
|
198
|
+
const key = parts.slice(0, i).join('.');
|
|
199
|
+
if (TERMINAL_COLORS[key]) return TERMINAL_COLORS[key];
|
|
200
|
+
}
|
|
201
201
|
}
|
|
202
|
-
return result;
|
|
203
202
|
}
|
|
204
|
-
function
|
|
203
|
+
async function highlightCodeAsync(code, language, theme = 'github-dark') {
|
|
205
204
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
205
|
+
const result = await codeToTokens(code, {
|
|
206
|
+
lang: language || 'text',
|
|
207
|
+
theme: theme
|
|
208
|
+
});
|
|
209
|
+
const nodes = [];
|
|
210
|
+
let index = 0;
|
|
211
|
+
for(let lineIndex = 0; lineIndex < result.tokens.length; lineIndex++){
|
|
212
|
+
const line = result.tokens[lineIndex];
|
|
213
|
+
if (line) {
|
|
214
|
+
for (const token of line){
|
|
215
|
+
let color;
|
|
216
|
+
if (token.color) color = hexToTerminalColor(token.color);
|
|
217
|
+
if (!color && token.explanation) {
|
|
218
|
+
const scopes = token.explanation.map((e)=>e.scopes?.[0]?.scopeName || '');
|
|
219
|
+
color = tokenScopeToColor(scopes);
|
|
220
|
+
}
|
|
221
|
+
nodes.push(/*#__PURE__*/ jsx(Text, {
|
|
222
|
+
color: color,
|
|
223
|
+
children: token.content
|
|
224
|
+
}, `token-${index}`));
|
|
225
|
+
index++;
|
|
226
|
+
}
|
|
227
|
+
if (lineIndex < result.tokens.length - 1) nodes.push(/*#__PURE__*/ jsx(Text, {
|
|
228
|
+
children: '\n'
|
|
229
|
+
}, `nl-${lineIndex}`));
|
|
230
|
+
}
|
|
213
231
|
}
|
|
214
|
-
|
|
215
|
-
return parseHighlightedCode(highlighted.value);
|
|
232
|
+
return nodes;
|
|
216
233
|
} catch {
|
|
217
234
|
return null;
|
|
218
235
|
}
|
|
@@ -238,6 +255,51 @@ function mergeStyles(defaultStyle, userStyle) {
|
|
|
238
255
|
...userStyle
|
|
239
256
|
};
|
|
240
257
|
}
|
|
258
|
+
function CodeBlock({ code, language, style, theme }) {
|
|
259
|
+
const [highlightedCode, setHighlightedCode] = useState(null);
|
|
260
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
261
|
+
useEffect(()=>{
|
|
262
|
+
let cancelled = false;
|
|
263
|
+
async function highlight() {
|
|
264
|
+
try {
|
|
265
|
+
const result = await highlightCodeAsync(code, language, theme);
|
|
266
|
+
if (!cancelled) {
|
|
267
|
+
setHighlightedCode(result);
|
|
268
|
+
setIsLoading(false);
|
|
269
|
+
}
|
|
270
|
+
} catch {
|
|
271
|
+
if (!cancelled) {
|
|
272
|
+
setHighlightedCode(null);
|
|
273
|
+
setIsLoading(false);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
highlight();
|
|
278
|
+
return ()=>{
|
|
279
|
+
cancelled = true;
|
|
280
|
+
};
|
|
281
|
+
}, [
|
|
282
|
+
code,
|
|
283
|
+
language,
|
|
284
|
+
theme
|
|
285
|
+
]);
|
|
286
|
+
if (isLoading || !highlightedCode) return /*#__PURE__*/ jsx(Box, {
|
|
287
|
+
...extractBoxProps(style),
|
|
288
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
289
|
+
...extractTextProps(style),
|
|
290
|
+
children: code
|
|
291
|
+
})
|
|
292
|
+
});
|
|
293
|
+
return /*#__PURE__*/ jsx(Box, {
|
|
294
|
+
paddingX: 2,
|
|
295
|
+
paddingY: 1,
|
|
296
|
+
...extractBoxProps(style),
|
|
297
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
298
|
+
...extractTextProps(style),
|
|
299
|
+
children: highlightedCode
|
|
300
|
+
})
|
|
301
|
+
});
|
|
302
|
+
}
|
|
241
303
|
function renderInlineTokens(tokens, styles, renderers) {
|
|
242
304
|
if (!tokens || 0 === tokens.length) return null;
|
|
243
305
|
return tokens.map((token, index)=>{
|
|
@@ -345,7 +407,7 @@ function renderInlineTokens(tokens, styles, renderers) {
|
|
|
345
407
|
}
|
|
346
408
|
});
|
|
347
409
|
}
|
|
348
|
-
function renderBlockToken(token, styles, renderers, showSharp, highlight) {
|
|
410
|
+
function renderBlockToken(token, styles, renderers, showSharp, highlight, theme = 'github-dark') {
|
|
349
411
|
switch(token.type){
|
|
350
412
|
case 'heading':
|
|
351
413
|
{
|
|
@@ -386,19 +448,12 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight) {
|
|
|
386
448
|
const codeToken = token;
|
|
387
449
|
const codeStyle = mergeStyles(DEFAULT_STYLES.code, styles.code);
|
|
388
450
|
if (renderers.code) return renderers.code(codeToken.text, codeToken.lang, codeToken);
|
|
389
|
-
if (highlight) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
...extractBoxProps(codeStyle),
|
|
396
|
-
children: /*#__PURE__*/ jsx(Text, {
|
|
397
|
-
...extractTextProps(codeStyle),
|
|
398
|
-
children: highlightedCode
|
|
399
|
-
})
|
|
400
|
-
});
|
|
401
|
-
}
|
|
451
|
+
if (highlight) return /*#__PURE__*/ jsx(CodeBlock, {
|
|
452
|
+
code: codeToken.text,
|
|
453
|
+
language: codeToken.lang,
|
|
454
|
+
style: codeStyle,
|
|
455
|
+
theme: theme
|
|
456
|
+
});
|
|
402
457
|
return /*#__PURE__*/ jsx(Box, {
|
|
403
458
|
...extractBoxProps(codeStyle),
|
|
404
459
|
children: /*#__PURE__*/ jsx(Text, {
|
|
@@ -412,7 +467,7 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight) {
|
|
|
412
467
|
const blockquoteToken = token;
|
|
413
468
|
const blockquoteStyle = mergeStyles(DEFAULT_STYLES.blockquote, styles.blockquote);
|
|
414
469
|
const content = blockquoteToken.tokens.map((t, i)=>/*#__PURE__*/ jsx(Box, {
|
|
415
|
-
children: renderBlockToken(t, styles, renderers, showSharp, highlight)
|
|
470
|
+
children: renderBlockToken(t, styles, renderers, showSharp, highlight, theme)
|
|
416
471
|
}, `bq-${i}`));
|
|
417
472
|
if (renderers.blockquote) return renderers.blockquote(content, blockquoteToken);
|
|
418
473
|
return /*#__PURE__*/ jsx(Box, {
|
|
@@ -420,7 +475,7 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight) {
|
|
|
420
475
|
children: /*#__PURE__*/ jsx(Box, {
|
|
421
476
|
flexDirection: "column",
|
|
422
477
|
children: blockquoteToken.tokens.map((t, i)=>{
|
|
423
|
-
const rendered = renderBlockToken(t, styles, renderers, showSharp, highlight);
|
|
478
|
+
const rendered = renderBlockToken(t, styles, renderers, showSharp, highlight, theme);
|
|
424
479
|
if (rendered) return /*#__PURE__*/ jsx(Text, {
|
|
425
480
|
...extractTextProps(blockquoteStyle),
|
|
426
481
|
children: 'paragraph' === t.type ? renderInlineTokens(t.tokens, styles, renderers) : t.text || ''
|
|
@@ -482,40 +537,119 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight) {
|
|
|
482
537
|
const tableToken = token;
|
|
483
538
|
const tableStyle = mergeStyles(DEFAULT_STYLES.table, styles.table);
|
|
484
539
|
const cellStyle = mergeStyles(DEFAULT_STYLES.tableCell, styles.tableCell);
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
540
|
+
const getCellText = (tokens)=>tokens.map((t)=>{
|
|
541
|
+
if ('text' in t) return t.text;
|
|
542
|
+
return '';
|
|
543
|
+
}).join('');
|
|
544
|
+
const columnWidths = tableToken.header.map((cell, colIndex)=>{
|
|
545
|
+
const headerWidth = getCellText(cell.tokens).length;
|
|
546
|
+
const bodyWidth = Math.max(...tableToken.rows.map((row)=>{
|
|
547
|
+
const cellTokens = row[colIndex]?.tokens;
|
|
548
|
+
return cellTokens ? getCellText(cellTokens).length : 0;
|
|
549
|
+
}), 0);
|
|
550
|
+
return Math.max(headerWidth, bodyWidth, 3);
|
|
551
|
+
});
|
|
552
|
+
const topBorder = /*#__PURE__*/ jsxs(Text, {
|
|
553
|
+
dimColor: true,
|
|
554
|
+
children: [
|
|
555
|
+
"┌─",
|
|
556
|
+
columnWidths.map((w)=>'─'.repeat(w)).join('─┬─'),
|
|
557
|
+
"─┐"
|
|
558
|
+
]
|
|
559
|
+
});
|
|
560
|
+
const headerRow = /*#__PURE__*/ jsxs(Text, {
|
|
561
|
+
children: [
|
|
562
|
+
/*#__PURE__*/ jsx(Text, {
|
|
563
|
+
dimColor: true,
|
|
564
|
+
children: "│ "
|
|
565
|
+
}),
|
|
566
|
+
tableToken.header.map((cell, i)=>{
|
|
567
|
+
const content = renderInlineTokens(cell.tokens, styles, renderers);
|
|
568
|
+
const cellText = getCellText(cell.tokens);
|
|
569
|
+
return /*#__PURE__*/ jsxs(Text, {
|
|
570
|
+
children: [
|
|
571
|
+
/*#__PURE__*/ jsxs(Text, {
|
|
572
|
+
bold: true,
|
|
573
|
+
...extractTextProps(cellStyle),
|
|
574
|
+
children: [
|
|
575
|
+
content,
|
|
576
|
+
' '.repeat(Math.max(0, (columnWidths[i] || 3) - cellText.length))
|
|
577
|
+
]
|
|
578
|
+
}),
|
|
579
|
+
/*#__PURE__*/ jsxs(Text, {
|
|
580
|
+
dimColor: true,
|
|
581
|
+
children: [
|
|
582
|
+
" │",
|
|
583
|
+
i < tableToken.header.length - 1 ? ' ' : ''
|
|
584
|
+
]
|
|
585
|
+
})
|
|
586
|
+
]
|
|
587
|
+
}, `th-${i}`);
|
|
491
588
|
})
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
589
|
+
]
|
|
590
|
+
});
|
|
591
|
+
const headerSeparator = /*#__PURE__*/ jsxs(Text, {
|
|
592
|
+
dimColor: true,
|
|
593
|
+
children: [
|
|
594
|
+
"├─",
|
|
595
|
+
columnWidths.map((w)=>'─'.repeat(w)).join('─┼─'),
|
|
596
|
+
"─┤"
|
|
597
|
+
]
|
|
496
598
|
});
|
|
497
|
-
const bodyRows = tableToken.rows.map((row, rowIndex)=>/*#__PURE__*/
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
children:
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
599
|
+
const bodyRows = tableToken.rows.map((row, rowIndex)=>/*#__PURE__*/ jsxs(Text, {
|
|
600
|
+
children: [
|
|
601
|
+
/*#__PURE__*/ jsx(Text, {
|
|
602
|
+
dimColor: true,
|
|
603
|
+
children: "│ "
|
|
604
|
+
}),
|
|
605
|
+
row.map((cell, cellIndex)=>{
|
|
606
|
+
const content = renderInlineTokens(cell.tokens, styles, renderers);
|
|
607
|
+
const cellText = getCellText(cell.tokens);
|
|
608
|
+
const colWidth = columnWidths[cellIndex] || 3;
|
|
609
|
+
return /*#__PURE__*/ jsxs(Text, {
|
|
610
|
+
children: [
|
|
611
|
+
/*#__PURE__*/ jsxs(Text, {
|
|
612
|
+
...extractTextProps(cellStyle),
|
|
613
|
+
children: [
|
|
614
|
+
content,
|
|
615
|
+
' '.repeat(Math.max(0, colWidth - cellText.length))
|
|
616
|
+
]
|
|
617
|
+
}),
|
|
618
|
+
/*#__PURE__*/ jsxs(Text, {
|
|
619
|
+
dimColor: true,
|
|
620
|
+
children: [
|
|
621
|
+
" │",
|
|
622
|
+
cellIndex < row.length - 1 ? ' ' : ''
|
|
623
|
+
]
|
|
624
|
+
})
|
|
625
|
+
]
|
|
626
|
+
}, `td-${rowIndex}-${cellIndex}`);
|
|
627
|
+
})
|
|
628
|
+
]
|
|
506
629
|
}, `tr-${rowIndex}`));
|
|
507
|
-
const
|
|
508
|
-
|
|
630
|
+
const bottomBorder = /*#__PURE__*/ jsxs(Text, {
|
|
631
|
+
dimColor: true,
|
|
632
|
+
children: [
|
|
633
|
+
"└─",
|
|
634
|
+
columnWidths.map((w)=>'─'.repeat(w)).join('─┴─'),
|
|
635
|
+
"─┘"
|
|
636
|
+
]
|
|
509
637
|
});
|
|
510
|
-
|
|
511
|
-
return /*#__PURE__*/ jsxs(Box, {
|
|
512
|
-
flexDirection: "column",
|
|
513
|
-
...extractBoxProps(tableStyle),
|
|
638
|
+
const tableContent = /*#__PURE__*/ jsxs(Fragment, {
|
|
514
639
|
children: [
|
|
515
|
-
|
|
516
|
-
|
|
640
|
+
topBorder,
|
|
641
|
+
headerRow,
|
|
642
|
+
headerSeparator,
|
|
643
|
+
bodyRows,
|
|
644
|
+
bottomBorder
|
|
517
645
|
]
|
|
518
646
|
});
|
|
647
|
+
if (renderers.table) return renderers.table(headerRow, bodyRows, tableToken);
|
|
648
|
+
return /*#__PURE__*/ jsx(Box, {
|
|
649
|
+
flexDirection: "column",
|
|
650
|
+
...extractBoxProps(tableStyle),
|
|
651
|
+
children: tableContent
|
|
652
|
+
});
|
|
519
653
|
}
|
|
520
654
|
case 'space':
|
|
521
655
|
return /*#__PURE__*/ jsx(Text, {
|
|
@@ -536,16 +670,19 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight) {
|
|
|
536
670
|
return null;
|
|
537
671
|
}
|
|
538
672
|
}
|
|
539
|
-
const src_MemoizedBlock = /*#__PURE__*/ memo(function({ token, styles, renderers, showSharp, highlight }) {
|
|
673
|
+
const src_MemoizedBlock = /*#__PURE__*/ memo(function({ token, styles, renderers, showSharp, highlight, theme }) {
|
|
540
674
|
return /*#__PURE__*/ jsx(Fragment, {
|
|
541
|
-
children: renderBlockToken(token, styles, renderers, showSharp, highlight)
|
|
675
|
+
children: renderBlockToken(token, styles, renderers, showSharp, highlight, theme)
|
|
542
676
|
});
|
|
543
677
|
}, (prevProps, nextProps)=>prevProps.token === nextProps.token);
|
|
544
678
|
src_MemoizedBlock.displayName = 'MemoizedBlock';
|
|
545
|
-
function MarkdownComponent({ children, id, styles = {}, renderers = {}, showSharp = false, highlight = true }) {
|
|
679
|
+
function MarkdownComponent({ children, id, styles = {}, renderers = {}, showSharp = false, highlight = true, theme = 'github-dark' }) {
|
|
546
680
|
const generatedId = useId();
|
|
547
681
|
const key = id || generatedId;
|
|
548
|
-
const tokens = useMemo(()=>marked.lexer(children
|
|
682
|
+
const tokens = useMemo(()=>marked.lexer(children, {
|
|
683
|
+
silent: true,
|
|
684
|
+
gfm: true
|
|
685
|
+
}), [
|
|
549
686
|
children
|
|
550
687
|
]);
|
|
551
688
|
return /*#__PURE__*/ jsx(Box, {
|
|
@@ -555,7 +692,8 @@ function MarkdownComponent({ children, id, styles = {}, renderers = {}, showShar
|
|
|
555
692
|
styles: styles,
|
|
556
693
|
renderers: renderers,
|
|
557
694
|
showSharp: showSharp,
|
|
558
|
-
highlight: highlight
|
|
695
|
+
highlight: highlight,
|
|
696
|
+
theme: theme
|
|
559
697
|
}, `${key}-block-${index}`))
|
|
560
698
|
});
|
|
561
699
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -67,6 +67,13 @@ export type MarkdownProps = {
|
|
|
67
67
|
* @default true
|
|
68
68
|
*/
|
|
69
69
|
highlight?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Shiki theme name for syntax highlighting
|
|
72
|
+
* @default 'github-dark'
|
|
73
|
+
* @example 'github-dark', 'github-light', 'nord', 'dracula', etc.
|
|
74
|
+
* @see https://shiki.style/themes
|
|
75
|
+
*/
|
|
76
|
+
theme?: string;
|
|
70
77
|
};
|
|
71
78
|
export type MemoizedBlockProps = {
|
|
72
79
|
token: Token;
|
|
@@ -74,4 +81,5 @@ export type MemoizedBlockProps = {
|
|
|
74
81
|
renderers: BlockRenderers;
|
|
75
82
|
showSharp: boolean;
|
|
76
83
|
highlight: boolean;
|
|
84
|
+
theme: string;
|
|
77
85
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ink-markdown-es",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A modern performance markdown renderer for ink",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"dedent": "^1.7.1",
|
|
54
|
-
"
|
|
55
|
-
"
|
|
54
|
+
"marked": "^16.4.2",
|
|
55
|
+
"shiki": "^3.22.0"
|
|
56
56
|
}
|
|
57
57
|
}
|