ink-markdown-es 1.3.0 → 1.4.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/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, theme, }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
4
+ declare function MarkdownComponent({ children, id, styles, renderers, showSharp, }: 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,7 @@
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, useEffect, useId, useMemo, useState } from "react";
5
- import { codeToTokens } from "shiki";
4
+ import { memo, useId, useMemo } from "react";
6
5
  const DEFAULT_STYLES = {
7
6
  h1: {
8
7
  bold: true,
@@ -42,7 +41,8 @@ const DEFAULT_STYLES = {
42
41
  borderDimColor: true
43
42
  },
44
43
  code: {
45
- marginTop: 1
44
+ marginTop: 1,
45
+ paddingX: 2
46
46
  },
47
47
  codespan: {
48
48
  dimColor: true
@@ -121,35 +121,6 @@ const BOX_STYLE_KEYS = [
121
121
  'borderLeftDimColor',
122
122
  'borderRightDimColor'
123
123
  ];
124
- async function highlightCodeAsync(code, language, theme = 'github-dark') {
125
- try {
126
- const result = await codeToTokens(code, {
127
- lang: language || 'text',
128
- theme: theme
129
- });
130
- const nodes = [];
131
- let index = 0;
132
- for(let lineIndex = 0; lineIndex < result.tokens.length; lineIndex++){
133
- const line = result.tokens[lineIndex];
134
- if (line) {
135
- for (const token of line){
136
- const color = token.color || void 0;
137
- nodes.push(/*#__PURE__*/ jsx(Text, {
138
- color: color,
139
- children: token.content
140
- }, `token-${index}`));
141
- index++;
142
- }
143
- if (lineIndex < result.tokens.length - 1) nodes.push(/*#__PURE__*/ jsx(Text, {
144
- children: '\n'
145
- }, `nl-${lineIndex}`));
146
- }
147
- }
148
- return nodes;
149
- } catch {
150
- return null;
151
- }
152
- }
153
124
  function extractTextProps(style) {
154
125
  if (!style) return {};
155
126
  const result = {};
@@ -171,51 +142,6 @@ function mergeStyles(defaultStyle, userStyle) {
171
142
  ...userStyle
172
143
  };
173
144
  }
174
- function CodeBlock({ code, language, style, theme }) {
175
- const [highlightedCode, setHighlightedCode] = useState(null);
176
- const [isLoading, setIsLoading] = useState(true);
177
- useEffect(()=>{
178
- let cancelled = false;
179
- async function highlight() {
180
- try {
181
- const result = await highlightCodeAsync(code, language, theme);
182
- if (!cancelled) {
183
- setHighlightedCode(result);
184
- setIsLoading(false);
185
- }
186
- } catch {
187
- if (!cancelled) {
188
- setHighlightedCode(null);
189
- setIsLoading(false);
190
- }
191
- }
192
- }
193
- highlight();
194
- return ()=>{
195
- cancelled = true;
196
- };
197
- }, [
198
- code,
199
- language,
200
- theme
201
- ]);
202
- if (isLoading || !highlightedCode) return /*#__PURE__*/ jsx(Box, {
203
- ...extractBoxProps(style),
204
- children: /*#__PURE__*/ jsx(Text, {
205
- ...extractTextProps(style),
206
- children: code
207
- })
208
- });
209
- return /*#__PURE__*/ jsx(Box, {
210
- paddingX: 2,
211
- paddingY: 1,
212
- ...extractBoxProps(style),
213
- children: /*#__PURE__*/ jsx(Text, {
214
- ...extractTextProps(style),
215
- children: highlightedCode
216
- })
217
- });
218
- }
219
145
  function renderInlineTokens(tokens, styles, renderers) {
220
146
  if (!tokens || 0 === tokens.length) return null;
221
147
  return tokens.map((token, index)=>{
@@ -323,7 +249,7 @@ function renderInlineTokens(tokens, styles, renderers) {
323
249
  }
324
250
  });
325
251
  }
326
- function renderBlockToken(token, styles, renderers, showSharp, highlight, theme = 'github-dark') {
252
+ function renderBlockToken(token, styles, renderers, showSharp) {
327
253
  switch(token.type){
328
254
  case 'heading':
329
255
  {
@@ -364,12 +290,6 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight, theme
364
290
  const codeToken = token;
365
291
  const codeStyle = mergeStyles(DEFAULT_STYLES.code, styles.code);
366
292
  if (renderers.code) return renderers.code(codeToken.text, codeToken.lang, codeToken);
367
- if (highlight) return /*#__PURE__*/ jsx(CodeBlock, {
368
- code: codeToken.text,
369
- language: codeToken.lang,
370
- style: codeStyle,
371
- theme: theme
372
- });
373
293
  return /*#__PURE__*/ jsx(Box, {
374
294
  ...extractBoxProps(codeStyle),
375
295
  children: /*#__PURE__*/ jsx(Text, {
@@ -382,22 +302,20 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight, theme
382
302
  {
383
303
  const blockquoteToken = token;
384
304
  const blockquoteStyle = mergeStyles(DEFAULT_STYLES.blockquote, styles.blockquote);
385
- const content = blockquoteToken.tokens.map((t, i)=>/*#__PURE__*/ jsx(Box, {
386
- children: renderBlockToken(t, styles, renderers, showSharp, highlight, theme)
387
- }, `bq-${i}`));
388
- if (renderers.blockquote) return renderers.blockquote(content, blockquoteToken);
305
+ if (renderers.blockquote) {
306
+ const content = blockquoteToken.tokens.map((t, i)=>/*#__PURE__*/ jsx(Box, {
307
+ children: renderBlockToken(t, styles, renderers, showSharp)
308
+ }, `bq-${i}`));
309
+ return renderers.blockquote(content, blockquoteToken);
310
+ }
389
311
  return /*#__PURE__*/ jsx(Box, {
390
312
  ...extractBoxProps(blockquoteStyle),
391
313
  children: /*#__PURE__*/ jsx(Box, {
392
314
  flexDirection: "column",
393
- children: blockquoteToken.tokens.map((t, i)=>{
394
- const rendered = renderBlockToken(t, styles, renderers, showSharp, highlight, theme);
395
- if (rendered) return /*#__PURE__*/ jsx(Text, {
315
+ children: blockquoteToken.tokens.map((t, i)=>/*#__PURE__*/ jsx(Text, {
396
316
  ...extractTextProps(blockquoteStyle),
397
317
  children: 'paragraph' === t.type ? renderInlineTokens(t.tokens, styles, renderers) : t.text || ''
398
- }, `bq-text-${i}`);
399
- return null;
400
- })
318
+ }, `bq-text-${i}`))
401
319
  })
402
320
  });
403
321
  }
@@ -495,7 +413,8 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight, theme
495
413
  /*#__PURE__*/ jsxs(Text, {
496
414
  dimColor: true,
497
415
  children: [
498
- " │",
416
+ ' ',
417
+ "│",
499
418
  i < tableToken.header.length - 1 ? ' ' : ''
500
419
  ]
501
420
  })
@@ -586,13 +505,13 @@ function renderBlockToken(token, styles, renderers, showSharp, highlight, theme
586
505
  return null;
587
506
  }
588
507
  }
589
- const src_MemoizedBlock = /*#__PURE__*/ memo(function({ token, styles, renderers, showSharp, highlight, theme }) {
508
+ const src_MemoizedBlock = /*#__PURE__*/ memo(function({ token, styles, renderers, showSharp }) {
590
509
  return /*#__PURE__*/ jsx(Fragment, {
591
- children: renderBlockToken(token, styles, renderers, showSharp, highlight, theme)
510
+ children: renderBlockToken(token, styles, renderers, showSharp)
592
511
  });
593
512
  }, (prevProps, nextProps)=>prevProps.token === nextProps.token);
594
513
  src_MemoizedBlock.displayName = 'MemoizedBlock';
595
- function MarkdownComponent({ children, id, styles = {}, renderers = {}, showSharp = false, highlight = true, theme = 'github-dark' }) {
514
+ function MarkdownComponent({ children, id, styles = {}, renderers = {}, showSharp = false }) {
596
515
  const generatedId = useId();
597
516
  const key = id || generatedId;
598
517
  const tokens = useMemo(()=>marked.lexer(children, {
@@ -607,9 +526,7 @@ function MarkdownComponent({ children, id, styles = {}, renderers = {}, showShar
607
526
  token: token,
608
527
  styles: styles,
609
528
  renderers: renderers,
610
- showSharp: showSharp,
611
- highlight: highlight,
612
- theme: theme
529
+ showSharp: showSharp
613
530
  }, `${key}-block-${index}`))
614
531
  });
615
532
  }
package/dist/types.d.ts CHANGED
@@ -62,24 +62,10 @@ export type MarkdownProps = {
62
62
  styles?: BlockStyles;
63
63
  renderers?: BlockRenderers;
64
64
  showSharp?: boolean;
65
- /**
66
- * Enable syntax highlighting for code blocks
67
- * @default true
68
- */
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;
77
65
  };
78
66
  export type MemoizedBlockProps = {
79
67
  token: Token;
80
68
  styles: BlockStyles;
81
69
  renderers: BlockRenderers;
82
70
  showSharp: boolean;
83
- highlight: boolean;
84
- theme: string;
85
71
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ink-markdown-es",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "A modern performance markdown renderer for ink",
5
5
  "keywords": [
6
6
  "markdown",
@@ -28,9 +28,9 @@
28
28
  ],
29
29
  "scripts": {
30
30
  "build": "rslib build",
31
- "check": "biome check --write",
31
+ "check": "biome check --write .",
32
32
  "dev": "bun --watch run examples/index.tsx",
33
- "format": "biome format --write",
33
+ "format": "biome format --write .",
34
34
  "prepublishOnly": "bun run build"
35
35
  },
36
36
  "devDependencies": {
@@ -40,6 +40,7 @@
40
40
  "@types/react": "^19",
41
41
  "@biomejs/biome": "2.3.8",
42
42
  "ink": "^6",
43
+ "ink-shiki-code": "workspace:*",
43
44
  "react": "^19",
44
45
  "react-devtools-core": "^6",
45
46
  "typescript": "^5.9.3",
@@ -51,7 +52,6 @@
51
52
  },
52
53
  "dependencies": {
53
54
  "dedent": "^1.7.1",
54
- "marked": "^16.4.2",
55
- "shiki": "^3.22.0"
55
+ "marked": "^16.4.2"
56
56
  }
57
57
  }
package/README.md DELETED
@@ -1,123 +0,0 @@
1
- # ink-markdown-es
2
-
3
- A modern performance markdown renderer for [ink](https://github.com/vadimdemedes/ink) using [marked](https://github.com/markedjs/marked).
4
-
5
- Inspired by [ink-markdown](https://github.com/vadimdemedes/ink-markdown) and [prompt-kit](https://github.com/ibelick/prompt-kit).
6
-
7
- Compare with [ink-markdown](https://github.com/vadimdemedes/ink-markdown):
8
-
9
- - **ES module** support & only
10
- - Use memo & useMemo to improve performance
11
- - More flexible configuration (`renderers` prop)
12
-
13
- ## Quick Start
14
-
15
- ```bash
16
- npm install ink-markdown-es # npm
17
-
18
- pnpm add ink-markdown-es # pnpm
19
-
20
- bun add ink-markdown-es # bun
21
- ```
22
-
23
- ```tsx
24
- const text = `# Hello World
25
-
26
- This is a show case.
27
- It's very fast!
28
-
29
- ## Features
30
- - Render markdown in ink
31
- - Support custom renderers
32
- - **Bold text** and *italic text*
33
- - Inline \`code\` support
34
- - **Syntax highlighting** for code blocks powered by highlight.js
35
-
36
- ### Code Block with Syntax Highlighting
37
-
38
- \`\`\`typescript
39
- interface User {
40
- id: number;
41
- name: string;
42
- email: string;
43
- }
44
-
45
- const user: User = {
46
- id: 1,
47
- name: "Alice",
48
- email: "alice@example.com"
49
- };
50
-
51
- async function fetchUser(id: number): Promise<User> {
52
- const response = await fetch(\`/api/users/\${id}\`);
53
- return response.json();
54
- }
55
- \`\`\`
56
-
57
- > This is a blockquote
58
- > with multiple lines
59
-
60
- ---
61
-
62
- Check out [this link](https://example.com) for more info.
63
-
64
- 1. First item
65
- 2. Second item
66
- 3. Third item
67
-
68
- | Name | Age |
69
- |------|-----|
70
- | Alice | 25 |
71
- | Bob | 30 |
72
- `;
73
-
74
- const TestApp = () => {
75
- useInput(() => {});
76
-
77
- return (
78
- <Markdown
79
- showSharp
80
- theme="dracula"
81
- renderers={{
82
- h1: (text) => (
83
- <Box padding={1} borderStyle="round" borderDimColor>
84
- <Text bold color="greenBright">
85
- {text}
86
- </Text>
87
- </Box>
88
- ),
89
- }}
90
- >
91
- {text}
92
- </Markdown>
93
- );
94
- };
95
-
96
- render(<TestApp />);
97
-
98
- ```
99
-
100
- <img width="1904" height="964" alt="image" src="https://github.com/user-attachments/assets/bed0c942-6d08-4f24-a42a-4999bdf1fc85" />
101
-
102
- ## Props
103
-
104
- - `children` (string): The markdown content to render.
105
- - `id` (string, optional): A unique identifier for the component. In AI scene, it's useful to identify the component in the DOM tree, you can use AI message id.
106
- - `styles` (BlockStyles, optional): Custom styles for markdown blocks.
107
- - `renderers` (BlockRenderers, optional): Custom renderers for markdown blocks.
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.
110
-
111
- ## Contributing
112
-
113
- To install dependencies:
114
-
115
- ```bash
116
- bun install
117
- ```
118
-
119
- To run:
120
-
121
- ```bash
122
- bun run dev
123
- ```
@@ -1,2 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- export declare function highlightCodeAsync(code: string, language?: string, theme?: string): Promise<ReactNode[] | null>;