md-to-rich 1.0.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/LICENSE +21 -0
- package/README.md +203 -0
- package/dist/chunk-5CRCBG3P.js +221 -0
- package/dist/chunk-5CRCBG3P.js.map +1 -0
- package/dist/chunk-DJVBCM6N.cjs +35 -0
- package/dist/chunk-DJVBCM6N.cjs.map +1 -0
- package/dist/chunk-JMKP2EMX.cjs +165 -0
- package/dist/chunk-JMKP2EMX.cjs.map +1 -0
- package/dist/chunk-NNRBDNG7.js +173 -0
- package/dist/chunk-NNRBDNG7.js.map +1 -0
- package/dist/chunk-PKBYGGAU.cjs +176 -0
- package/dist/chunk-PKBYGGAU.cjs.map +1 -0
- package/dist/chunk-U7TPKOGA.js +28 -0
- package/dist/chunk-U7TPKOGA.js.map +1 -0
- package/dist/chunk-WWNNSHI7.cjs +224 -0
- package/dist/chunk-WWNNSHI7.cjs.map +1 -0
- package/dist/chunk-ZYIRT2QF.js +162 -0
- package/dist/chunk-ZYIRT2QF.js.map +1 -0
- package/dist/index.cjs +39 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/serializers/ansi/index.cjs +17 -0
- package/dist/serializers/ansi/index.cjs.map +1 -0
- package/dist/serializers/ansi/index.d.cts +8 -0
- package/dist/serializers/ansi/index.d.ts +8 -0
- package/dist/serializers/ansi/index.js +4 -0
- package/dist/serializers/ansi/index.js.map +1 -0
- package/dist/serializers/doc-tree/index.cjs +17 -0
- package/dist/serializers/doc-tree/index.cjs.map +1 -0
- package/dist/serializers/doc-tree/index.d.cts +8 -0
- package/dist/serializers/doc-tree/index.d.ts +8 -0
- package/dist/serializers/doc-tree/index.js +4 -0
- package/dist/serializers/doc-tree/index.js.map +1 -0
- package/dist/serializers/html/index.cjs +17 -0
- package/dist/serializers/html/index.cjs.map +1 -0
- package/dist/serializers/html/index.d.cts +8 -0
- package/dist/serializers/html/index.d.ts +8 -0
- package/dist/serializers/html/index.js +4 -0
- package/dist/serializers/html/index.js.map +1 -0
- package/dist/types-Di2funKi.d.cts +136 -0
- package/dist/types-Di2funKi.d.ts +136 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jithin Sebastian
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# md-to-rich
|
|
2
|
+
|
|
3
|
+
Convert Markdown to rich text output formats. TypeScript-first, tree-shakeable, ESM + CJS dual output.
|
|
4
|
+
|
|
5
|
+
**Built-in serializers:** HTML string · ANSI terminal string · Doc Tree (structured JSON)
|
|
6
|
+
|
|
7
|
+
**Extensible:** implement `Serializer<T>` to add any output format without touching this package.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install md-to-rich
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { toHtml, toAnsi, toDocTree } from 'md-to-rich'
|
|
23
|
+
|
|
24
|
+
toHtml('# Hello\n\n**bold**')
|
|
25
|
+
// → '<h1 id="hello">Hello</h1><p><strong>bold</strong></p>'
|
|
26
|
+
|
|
27
|
+
toAnsi('# Hello\n\n**bold**', { columns: 80 })
|
|
28
|
+
// → ANSI-escaped terminal string
|
|
29
|
+
|
|
30
|
+
toDocTree('# Hello')
|
|
31
|
+
// → { type: 'document', children: [{ type: 'heading', depth: 1, ... }] }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
### `toHtml(md, options?): string`
|
|
39
|
+
|
|
40
|
+
Converts Markdown to an HTML string.
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { toHtml } from 'md-to-rich'
|
|
44
|
+
// or sub-path:
|
|
45
|
+
import { toHtml } from 'md-to-rich/html'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
| Option | Type | Default | Description |
|
|
49
|
+
| --- | --- | --- | --- |
|
|
50
|
+
| `headingIds` | `boolean` | `true` | Add slug-based `id` attributes to headings (collision-safe) |
|
|
51
|
+
| `classNames` | `Partial<Record<HtmlElement, string>>` | `{}` | Custom CSS class per element |
|
|
52
|
+
| `renderImages` | `boolean` | `true` | Render `<img>` tags |
|
|
53
|
+
| `gfm` | `boolean` | `true` | Enable GitHub Flavored Markdown |
|
|
54
|
+
| `remarkPlugins` | `Plugin[]` | `[]` | Extra remark plugins |
|
|
55
|
+
|
|
56
|
+
### `toAnsi(md, options?): string`
|
|
57
|
+
|
|
58
|
+
Converts Markdown to an ANSI-escaped terminal string.
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { toAnsi } from 'md-to-rich'
|
|
62
|
+
// or:
|
|
63
|
+
import { toAnsi } from 'md-to-rich/ansi'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Option | Type | Default | Description |
|
|
67
|
+
| --- | --- | --- | --- |
|
|
68
|
+
| `columns` | `number` | `process.stdout.columns ?? 80` | Terminal width for word-wrap and HR |
|
|
69
|
+
| `hyperlinks` | `boolean` | `false` | Emit OSC 8 hyperlink sequences |
|
|
70
|
+
| `theme` | `Partial<AnsiTheme>` | built-in | Override ANSI styles |
|
|
71
|
+
| `gfm` | `boolean` | `true` | Enable GFM |
|
|
72
|
+
| `remarkPlugins` | `Plugin[]` | `[]` | Extra remark plugins |
|
|
73
|
+
|
|
74
|
+
**Default theme** uses bold/underline for headings, italic, strikethrough, reverse-video for inline code, and box-drawing characters for tables and code blocks. No external chalk dependency — inline ANSI constants only.
|
|
75
|
+
|
|
76
|
+
### `toDocTree(md, options?): DocDocument`
|
|
77
|
+
|
|
78
|
+
Converts Markdown to a structured `DocDocument` tree (plain JSON, no ANSI, no HTML).
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { toDocTree } from 'md-to-rich'
|
|
82
|
+
// or:
|
|
83
|
+
import { toDocTree } from 'md-to-rich/doc-tree'
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The tree is suitable for feeding into rich-text editors (ProseMirror, Slate, Quill, etc.) — see the adapter guide below.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### `serialize(md, serializer, options?): T`
|
|
91
|
+
|
|
92
|
+
Generic dispatch function — works with any `Serializer<T>` implementation.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { serialize } from 'md-to-rich'
|
|
96
|
+
import type { Serializer } from 'md-to-rich'
|
|
97
|
+
|
|
98
|
+
const PlainText: Serializer<string> = {
|
|
99
|
+
serialize(ast) {
|
|
100
|
+
// ast is an MDAST Root node
|
|
101
|
+
return myCustomWalker(ast)
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
serialize('# Hello\n\nWorld', PlainText) // → 'Hello\nWorld'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Building a Custom Serializer
|
|
111
|
+
|
|
112
|
+
Implement the `Serializer<TOutput, TOptions>` interface:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import type { Root } from 'mdast'
|
|
116
|
+
import { serialize } from 'md-to-rich'
|
|
117
|
+
import type { BaseOptions, Serializer } from 'md-to-rich'
|
|
118
|
+
|
|
119
|
+
interface MyOptions extends BaseOptions {
|
|
120
|
+
uppercase?: boolean
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const MySerializer: Serializer<string, MyOptions> = {
|
|
124
|
+
serialize(ast: Root, options: MyOptions): string {
|
|
125
|
+
// Walk the MDAST using your own logic, remark-stringify, unist-util-visit, etc.
|
|
126
|
+
const result = walkAst(ast)
|
|
127
|
+
return options.uppercase ? result.toUpperCase() : result
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function toMy(md: string, options?: MyOptions): string {
|
|
132
|
+
return serialize(md, MySerializer, options)
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The `Serializer` interface is the only contract. No inheritance, no registration — just pass your serializer to `serialize()`.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Doc Tree Node Types
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
DocDocument { type: 'document', children: DocBlockNode[] }
|
|
144
|
+
DocHeading { type: 'heading', depth: 1-6, children: DocInlineNode[] }
|
|
145
|
+
DocParagraph { type: 'paragraph', children: DocInlineNode[] }
|
|
146
|
+
DocBlockquote { type: 'blockquote', children: DocBlockNode[] }
|
|
147
|
+
DocCodeBlock { type: 'code', lang: string|null, value: string }
|
|
148
|
+
DocList { type: 'list', ordered: boolean, children: DocListItem[] }
|
|
149
|
+
DocListItem { type: 'listItem', checked: boolean|null, children: [...] }
|
|
150
|
+
DocTable { type: 'table', align: [...], children: DocTableRow[] }
|
|
151
|
+
DocTableRow { type: 'tableRow', isHeader: boolean, children: DocTableCell[] }
|
|
152
|
+
DocTableCell { type: 'tableCell', children: DocInlineNode[] }
|
|
153
|
+
DocHorizontalRule { type: 'thematicBreak' }
|
|
154
|
+
|
|
155
|
+
DocText { type: 'text', value: string, bold: boolean, italic: boolean, strikethrough: boolean }
|
|
156
|
+
DocInlineCode { type: 'inlineCode', value: string }
|
|
157
|
+
DocLink { type: 'link', url: string, title: string|null, children: DocInlineNode[] }
|
|
158
|
+
DocImage { type: 'image', url: string, alt: string|null, title: string|null }
|
|
159
|
+
DocBreak { type: 'break' }
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Nested `strong`/`emphasis`/`delete` marks are flattened into `DocText` boolean flags, making it straightforward to map into ProseMirror marks or Slate leaf properties.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## ProseMirror / Slate Adapter Guide
|
|
167
|
+
|
|
168
|
+
`toDocTree` outputs a plain JSON tree. Mapping to ProseMirror:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { toDocTree } from 'md-to-rich'
|
|
172
|
+
import type { DocBlockNode, DocInlineNode } from 'md-to-rich'
|
|
173
|
+
import { schema } from 'prosemirror-schema-basic'
|
|
174
|
+
|
|
175
|
+
function blockToNode(node: DocBlockNode) {
|
|
176
|
+
if (node.type === 'paragraph') {
|
|
177
|
+
return schema.nodes.paragraph!.create(null, node.children.map(inlineToNode))
|
|
178
|
+
}
|
|
179
|
+
if (node.type === 'heading') {
|
|
180
|
+
return schema.nodes.heading!.create({ level: node.depth }, node.children.map(inlineToNode))
|
|
181
|
+
}
|
|
182
|
+
// ... other block types
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function inlineToNode(node: DocInlineNode) {
|
|
186
|
+
if (node.type === 'text') {
|
|
187
|
+
const marks = []
|
|
188
|
+
if (node.bold) marks.push(schema.marks.strong!.create())
|
|
189
|
+
if (node.italic) marks.push(schema.marks.em!.create())
|
|
190
|
+
return schema.text(node.value, marks)
|
|
191
|
+
}
|
|
192
|
+
// ... other inline types
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const doc = toDocTree(markdownString)
|
|
196
|
+
const pmDoc = schema.nodes.doc!.create(null, doc.children.map(blockToNode))
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
MIT
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { serialize } from './chunk-U7TPKOGA.js';
|
|
2
|
+
|
|
3
|
+
// src/serializers/ansi/theme.ts
|
|
4
|
+
var ESC = "\x1B[";
|
|
5
|
+
function style(open, close) {
|
|
6
|
+
const openCodes = Array.isArray(open) ? open : [open];
|
|
7
|
+
return {
|
|
8
|
+
open: `${ESC}${openCodes.join(";")}m`,
|
|
9
|
+
close: `${ESC}${close}m`
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
var defaultTheme = {
|
|
13
|
+
h1: style([1, 4, 35], 0),
|
|
14
|
+
// bold + underline + magenta
|
|
15
|
+
h2: style([1, 4, 36], 0),
|
|
16
|
+
// bold + underline + cyan
|
|
17
|
+
h3: style([1, 36], 0),
|
|
18
|
+
// bold + cyan
|
|
19
|
+
bold: style(1, 22),
|
|
20
|
+
italic: style(3, 23),
|
|
21
|
+
strikethrough: style(9, 29),
|
|
22
|
+
inlineCode: style([7, 33], 0),
|
|
23
|
+
// reverse + yellow
|
|
24
|
+
codeBlock: style(90, 39),
|
|
25
|
+
// dark grey
|
|
26
|
+
blockquote: style(90, 39),
|
|
27
|
+
// dark grey
|
|
28
|
+
link: style([4, 34], 0),
|
|
29
|
+
// underline + blue
|
|
30
|
+
listBullet: "\u2022",
|
|
31
|
+
hrChar: "\u2500"
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// src/serializers/ansi/renderer.ts
|
|
35
|
+
var ANSI_RE = /\x1b\[[^m]*m|\x1b\][^\x07]*\x07/g;
|
|
36
|
+
function visibleWidth(s) {
|
|
37
|
+
return s.replace(ANSI_RE, "").length;
|
|
38
|
+
}
|
|
39
|
+
function wordWrap(text, columns, indent = "") {
|
|
40
|
+
const indentWidth = visibleWidth(indent);
|
|
41
|
+
const maxWidth = columns - indentWidth;
|
|
42
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
43
|
+
const lines = [];
|
|
44
|
+
let current = "";
|
|
45
|
+
for (const word of words) {
|
|
46
|
+
const candidate = current ? current + " " + word : word;
|
|
47
|
+
if (visibleWidth(candidate) > maxWidth && current) {
|
|
48
|
+
lines.push(current);
|
|
49
|
+
current = word;
|
|
50
|
+
} else {
|
|
51
|
+
current = candidate;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (current) lines.push(current);
|
|
55
|
+
return lines.map((l) => indent + l).join("\n");
|
|
56
|
+
}
|
|
57
|
+
function renderToAnsi(ast, opts) {
|
|
58
|
+
const columns = opts.columns ?? (process.stdout.columns ?? 80);
|
|
59
|
+
const hyperlinks = opts.hyperlinks ?? false;
|
|
60
|
+
const theme = { ...defaultTheme, ...opts.theme ?? {} };
|
|
61
|
+
function applyStyle(s, text) {
|
|
62
|
+
return `${s.open}${text}${s.close}`;
|
|
63
|
+
}
|
|
64
|
+
function renderBlocks(nodes) {
|
|
65
|
+
return nodes.map((n) => renderBlock(n)).filter(Boolean).join("\n\n");
|
|
66
|
+
}
|
|
67
|
+
function renderBlock(node) {
|
|
68
|
+
switch (node.type) {
|
|
69
|
+
case "root":
|
|
70
|
+
return renderBlocks(node.children);
|
|
71
|
+
case "heading":
|
|
72
|
+
return renderHeading(node);
|
|
73
|
+
case "paragraph":
|
|
74
|
+
return renderParagraph(node);
|
|
75
|
+
case "blockquote":
|
|
76
|
+
return renderBlockquote(node);
|
|
77
|
+
case "code":
|
|
78
|
+
return renderCode(node);
|
|
79
|
+
case "list":
|
|
80
|
+
return renderList(node, 0);
|
|
81
|
+
case "table":
|
|
82
|
+
return renderTable(node);
|
|
83
|
+
case "thematicBreak":
|
|
84
|
+
return renderHr();
|
|
85
|
+
default:
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function renderHeading(node) {
|
|
90
|
+
const text = renderInlines(node.children);
|
|
91
|
+
const styleKey = `h${node.depth}`;
|
|
92
|
+
const s = theme[styleKey] ?? theme.h3;
|
|
93
|
+
return applyStyle(s, text);
|
|
94
|
+
}
|
|
95
|
+
function renderParagraph(node) {
|
|
96
|
+
const text = renderInlines(node.children);
|
|
97
|
+
return wordWrap(text, columns);
|
|
98
|
+
}
|
|
99
|
+
function renderBlockquote(node) {
|
|
100
|
+
const inner = renderBlocks(node.children);
|
|
101
|
+
const prefix = applyStyle(theme.blockquote, "\u2502 ");
|
|
102
|
+
return inner.split("\n").map((line) => prefix + line).join("\n");
|
|
103
|
+
}
|
|
104
|
+
function renderCode(node) {
|
|
105
|
+
const lang = node.lang ? ` (${node.lang})` : "";
|
|
106
|
+
const header = applyStyle(theme.codeBlock, `\u250C\u2500 code${lang}`);
|
|
107
|
+
const lines = node.value.split("\n").map((l) => applyStyle(theme.codeBlock, `\u2502 ${l}`));
|
|
108
|
+
const footer = applyStyle(theme.codeBlock, "\u2514\u2500");
|
|
109
|
+
return [header, ...lines, footer].join("\n");
|
|
110
|
+
}
|
|
111
|
+
function renderList(node, depth) {
|
|
112
|
+
return node.children.map((li, i) => renderListItem(li, node, i + 1, depth)).join("\n");
|
|
113
|
+
}
|
|
114
|
+
function renderListItem(node, parent, index, depth) {
|
|
115
|
+
const indent = " ".repeat(depth);
|
|
116
|
+
const bullet = parent.ordered ? `${index}.` : applyStyle({ open: "", close: "" }, theme.listBullet);
|
|
117
|
+
const prefix = `${indent}${bullet} `;
|
|
118
|
+
const nestedLists = [];
|
|
119
|
+
const textParts = [];
|
|
120
|
+
for (const child of node.children) {
|
|
121
|
+
if (child.type === "list") {
|
|
122
|
+
nestedLists.push(child);
|
|
123
|
+
} else if (child.type === "paragraph") {
|
|
124
|
+
textParts.push(renderInlines(child.children));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const taskPrefix = node.checked !== null && node.checked !== void 0 ? node.checked ? "[x] " : "[ ] " : "";
|
|
128
|
+
const mainText = wordWrap(
|
|
129
|
+
taskPrefix + textParts.join(" "),
|
|
130
|
+
columns,
|
|
131
|
+
" ".repeat(visibleWidth(prefix))
|
|
132
|
+
).replace(/^\s+/, "");
|
|
133
|
+
const nested = nestedLists.map((l) => renderList(l, depth + 1)).join("\n");
|
|
134
|
+
return prefix + mainText + (nested ? "\n" + nested : "");
|
|
135
|
+
}
|
|
136
|
+
function renderTable(node) {
|
|
137
|
+
const [headerRow, ...bodyRows] = node.children;
|
|
138
|
+
if (!headerRow) return "";
|
|
139
|
+
const allRows = [headerRow, ...bodyRows];
|
|
140
|
+
const widths = [];
|
|
141
|
+
for (const row of allRows) {
|
|
142
|
+
for (let i = 0; i < row.children.length; i++) {
|
|
143
|
+
const cell = row.children[i];
|
|
144
|
+
const w = cell ? visibleWidth(renderInlines(cell.children)) : 0;
|
|
145
|
+
widths[i] = Math.max(widths[i] ?? 0, w);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function renderRow(row, isHeader) {
|
|
149
|
+
const cells = row.children.map((cell, i) => {
|
|
150
|
+
const text = renderInlines(cell.children);
|
|
151
|
+
const pad = (widths[i] ?? 0) - visibleWidth(text);
|
|
152
|
+
const padded = text + " ".repeat(Math.max(0, pad));
|
|
153
|
+
return isHeader ? applyStyle(theme.bold, padded) : padded;
|
|
154
|
+
});
|
|
155
|
+
return "\u2502 " + cells.join(" \u2502 ") + " \u2502";
|
|
156
|
+
}
|
|
157
|
+
function separator(char) {
|
|
158
|
+
return "\u251C" + widths.map((w) => char.repeat((w ?? 0) + 2)).join("\u253C") + "\u2524";
|
|
159
|
+
}
|
|
160
|
+
const top = "\u250C" + widths.map((w) => "\u2500".repeat((w ?? 0) + 2)).join("\u252C") + "\u2510";
|
|
161
|
+
const bottom = "\u2514" + widths.map((w) => "\u2500".repeat((w ?? 0) + 2)).join("\u2534") + "\u2518";
|
|
162
|
+
const lines = [top, renderRow(headerRow, true), separator("\u2500")];
|
|
163
|
+
for (const row of bodyRows) {
|
|
164
|
+
lines.push(renderRow(row, false));
|
|
165
|
+
}
|
|
166
|
+
lines.push(bottom);
|
|
167
|
+
return lines.join("\n");
|
|
168
|
+
}
|
|
169
|
+
function renderHr(_node) {
|
|
170
|
+
return theme.hrChar.repeat(columns);
|
|
171
|
+
}
|
|
172
|
+
function renderInlines(nodes) {
|
|
173
|
+
return nodes.map(renderInline).join("");
|
|
174
|
+
}
|
|
175
|
+
function renderInline(node) {
|
|
176
|
+
switch (node.type) {
|
|
177
|
+
case "text":
|
|
178
|
+
return node.value;
|
|
179
|
+
case "inlineCode":
|
|
180
|
+
return applyStyle(theme.inlineCode, node.value);
|
|
181
|
+
case "strong":
|
|
182
|
+
return applyStyle(theme.bold, renderInlines(node.children));
|
|
183
|
+
case "emphasis":
|
|
184
|
+
return applyStyle(theme.italic, renderInlines(node.children));
|
|
185
|
+
case "delete":
|
|
186
|
+
return applyStyle(theme.strikethrough, renderInlines(node.children));
|
|
187
|
+
case "link": {
|
|
188
|
+
const l = node;
|
|
189
|
+
const label = renderInlines(l.children);
|
|
190
|
+
if (hyperlinks) {
|
|
191
|
+
const safeUrl = l.url.replace(/[\x00-\x1f\x7f]/g, "");
|
|
192
|
+
return `\x1B]8;;${safeUrl}\x07${applyStyle(theme.link, label)}\x1B]8;;\x07`;
|
|
193
|
+
}
|
|
194
|
+
return `${applyStyle(theme.link, label)} (${l.url})`;
|
|
195
|
+
}
|
|
196
|
+
case "image": {
|
|
197
|
+
const img = node;
|
|
198
|
+
return `[image: ${img.alt ?? img.url}]`;
|
|
199
|
+
}
|
|
200
|
+
case "break":
|
|
201
|
+
return "\n";
|
|
202
|
+
default:
|
|
203
|
+
return "";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return renderBlocks(ast.children);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/serializers/ansi/index.ts
|
|
210
|
+
var AnsiSerializer = {
|
|
211
|
+
serialize(ast, options) {
|
|
212
|
+
return renderToAnsi(ast, options);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
function toAnsi(md, options) {
|
|
216
|
+
return serialize(md, AnsiSerializer, options);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export { AnsiSerializer, toAnsi };
|
|
220
|
+
//# sourceMappingURL=chunk-5CRCBG3P.js.map
|
|
221
|
+
//# sourceMappingURL=chunk-5CRCBG3P.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/serializers/ansi/theme.ts","../src/serializers/ansi/renderer.ts","../src/serializers/ansi/index.ts"],"names":[],"mappings":";;;AAGA,IAAM,GAAA,GAAM,OAAA;AAEZ,SAAS,KAAA,CAAM,MAAyB,KAAA,EAAgD;AACtF,EAAA,MAAM,YAAY,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,IAAA,GAAO,CAAC,IAAI,CAAA;AACpD,EAAA,OAAO;AAAA,IACL,MAAM,CAAA,EAAG,GAAG,GAAG,SAAA,CAAU,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAA;AAAA,IAClC,KAAA,EAAO,CAAA,EAAG,GAAG,CAAA,EAAG,KAAK,CAAA,CAAA;AAAA,GACvB;AACF;AAEO,IAAM,YAAA,GAA0B;AAAA,EACrC,IAAI,KAAA,CAAM,CAAC,GAAG,CAAA,EAAG,EAAE,GAAG,CAAC,CAAA;AAAA;AAAA,EACvB,IAAI,KAAA,CAAM,CAAC,GAAG,CAAA,EAAG,EAAE,GAAG,CAAC,CAAA;AAAA;AAAA,EACvB,IAAI,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,GAAG,CAAC,CAAA;AAAA;AAAA,EACpB,IAAA,EAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACjB,MAAA,EAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACnB,aAAA,EAAe,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EAC1B,YAAY,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,GAAG,CAAC,CAAA;AAAA;AAAA,EAC5B,SAAA,EAAW,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAAA;AAAA,EACvB,UAAA,EAAY,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAAA;AAAA,EACxB,MAAM,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,GAAG,CAAC,CAAA;AAAA;AAAA,EACtB,UAAA,EAAY,QAAA;AAAA,EACZ,MAAA,EAAQ;AACV,CAAA;;;ACbA,IAAM,OAAA,GAAU,kCAAA;AAEhB,SAAS,aAAa,CAAA,EAAmB;AACvC,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,OAAA,EAAS,EAAE,CAAA,CAAE,MAAA;AAChC;AAMA,SAAS,QAAA,CAAS,IAAA,EAAc,OAAA,EAAiB,MAAA,GAAS,EAAA,EAAY;AACpE,EAAA,MAAM,WAAA,GAAc,aAAa,MAAM,CAAA;AACvC,EAAA,MAAM,WAAW,OAAA,GAAU,WAAA;AAC3B,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,CAAE,OAAO,OAAO,CAAA;AAC9C,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,OAAA,GAAU,EAAA;AAEd,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,SAAA,GAAY,OAAA,GAAU,OAAA,GAAU,GAAA,GAAM,IAAA,GAAO,IAAA;AACnD,IAAA,IAAI,YAAA,CAAa,SAAS,CAAA,GAAI,QAAA,IAAY,OAAA,EAAS;AACjD,MAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAClB,MAAA,OAAA,GAAU,IAAA;AAAA,IACZ,CAAA,MAAO;AACL,MAAA,OAAA,GAAU,SAAA;AAAA,IACZ;AAAA,EACF;AACA,EAAA,IAAI,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AAC/B,EAAA,OAAO,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,SAAS,CAAC,CAAA,CAAE,KAAK,IAAI,CAAA;AAC/C;AAMO,SAAS,YAAA,CAAa,KAAW,IAAA,EAA2B;AACjE,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,KAAY,OAAA,CAAQ,OAAO,OAAA,IAAW,EAAA,CAAA;AAC3D,EAAA,MAAM,UAAA,GAAa,KAAK,UAAA,IAAc,KAAA;AACtC,EAAA,MAAM,KAAA,GAAmB,EAAE,GAAG,YAAA,EAAc,GAAI,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG;AAElE,EAAA,SAAS,UAAA,CAAW,GAAc,IAAA,EAAsB;AACtD,IAAA,OAAO,GAAG,CAAA,CAAE,IAAI,GAAG,IAAI,CAAA,EAAG,EAAE,KAAK,CAAA,CAAA;AAAA,EACnC;AAEA,EAAA,SAAS,aAAa,KAAA,EAA0B;AAC9C,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,WAAA,CAAY,CAAC,CAAC,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,MAAM,CAAA;AAAA,EACrE;AAEA,EAAA,SAAS,YAAY,IAAA,EAA8B;AACjD,IAAA,QAAQ,KAAK,IAAA;AAAM,MACjB,KAAK,MAAA;AACH,QAAA,OAAO,YAAA,CAAc,KAAc,QAAQ,CAAA;AAAA,MAC7C,KAAK,SAAA;AACH,QAAA,OAAO,cAAc,IAAe,CAAA;AAAA,MACtC,KAAK,WAAA;AACH,QAAA,OAAO,gBAAgB,IAAiB,CAAA;AAAA,MAC1C,KAAK,YAAA;AACH,QAAA,OAAO,iBAAiB,IAAkB,CAAA;AAAA,MAC5C,KAAK,MAAA;AACH,QAAA,OAAO,WAAW,IAAY,CAAA;AAAA,MAChC,KAAK,MAAA;AACH,QAAA,OAAO,UAAA,CAAW,MAAc,CAAC,CAAA;AAAA,MACnC,KAAK,OAAA;AACH,QAAA,OAAO,YAAY,IAAa,CAAA;AAAA,MAClC,KAAK,eAAA;AACH,QAAA,OAAO,SAA8B,CAAA;AAAA,MACvC;AACE,QAAA,OAAO,EAAA;AAAA;AACX,EACF;AAEA,EAAA,SAAS,cAAc,IAAA,EAAuB;AAC5C,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,IAAA,CAAK,QAAQ,CAAA;AACxC,IAAA,MAAM,QAAA,GAAY,CAAA,CAAA,EAAI,IAAA,CAAK,KAAK,CAAA,CAAA;AAChC,IAAA,MAAM,CAAA,GAAK,KAAA,CAAM,QAAQ,CAAA,IAAK,KAAA,CAAM,EAAA;AACpC,IAAA,OAAO,UAAA,CAAW,GAAG,IAAI,CAAA;AAAA,EAC3B;AAEA,EAAA,SAAS,gBAAgB,IAAA,EAAyB;AAChD,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,IAAA,CAAK,QAAQ,CAAA;AACxC,IAAA,OAAO,QAAA,CAAS,MAAM,OAAO,CAAA;AAAA,EAC/B;AAEA,EAAA,SAAS,iBAAiB,IAAA,EAA0B;AAClD,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,IAAA,CAAK,QAAQ,CAAA;AACxC,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,KAAA,CAAM,UAAA,EAAY,SAAI,CAAA;AAChD,IAAA,OAAO,KAAA,CACJ,KAAA,CAAM,IAAI,CAAA,CACV,GAAA,CAAI,CAAC,IAAA,KAAS,MAAA,GAAS,IAAI,CAAA,CAC3B,IAAA,CAAK,IAAI,CAAA;AAAA,EACd;AAEA,EAAA,SAAS,WAAW,IAAA,EAAoB;AACtC,IAAA,MAAM,OAAO,IAAA,CAAK,IAAA,GAAO,CAAA,EAAA,EAAK,IAAA,CAAK,IAAI,CAAA,CAAA,CAAA,GAAM,EAAA;AAC7C,IAAA,MAAM,SAAS,UAAA,CAAW,KAAA,CAAM,SAAA,EAAW,CAAA,iBAAA,EAAU,IAAI,CAAA,CAAE,CAAA;AAC3D,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,WAAW,KAAA,CAAM,SAAA,EAAW,CAAA,OAAA,EAAK,CAAC,EAAE,CAAC,CAAA;AACrF,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,KAAA,CAAM,SAAA,EAAW,cAAI,CAAA;AAC/C,IAAA,OAAO,CAAC,MAAA,EAAQ,GAAG,OAAO,MAAM,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,EAC7C;AAEA,EAAA,SAAS,UAAA,CAAW,MAAY,KAAA,EAAuB;AACrD,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAC,IAAI,CAAA,KAAM,cAAA,CAAe,EAAA,EAAI,IAAA,EAAM,IAAI,CAAA,EAAG,KAAK,CAAC,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,EACvF;AAEA,EAAA,SAAS,cAAA,CAAe,IAAA,EAAgB,MAAA,EAAc,KAAA,EAAe,KAAA,EAAuB;AAC1F,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAChC,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,OAAA,GAClB,CAAA,EAAG,KAAK,CAAA,CAAA,CAAA,GACR,UAAA,CAAW,EAAE,IAAA,EAAM,EAAA,EAAI,KAAA,EAAO,EAAA,EAAG,EAAG,MAAM,UAAU,CAAA;AACxD,IAAA,MAAM,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,EAAG,MAAM,CAAA,CAAA,CAAA;AAEjC,IAAA,MAAM,cAAsB,EAAC;AAC7B,IAAA,MAAM,YAAsB,EAAC;AAE7B,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,QAAA,EAAU;AACjC,MAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAQ;AACzB,QAAA,WAAA,CAAY,KAAK,KAAa,CAAA;AAAA,MAChC,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,WAAA,EAAa;AACrC,QAAA,SAAA,CAAU,IAAA,CAAK,aAAA,CAAe,KAAA,CAAoB,QAAQ,CAAC,CAAA;AAAA,MAC7D;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GACJ,IAAA,CAAK,OAAA,KAAY,IAAA,IAAQ,IAAA,CAAK,YAAY,MAAA,GACtC,IAAA,CAAK,OAAA,GACH,MAAA,GACA,MAAA,GACF,EAAA;AAEN,IAAA,MAAM,QAAA,GAAW,QAAA;AAAA,MACf,UAAA,GAAa,SAAA,CAAU,IAAA,CAAK,GAAG,CAAA;AAAA,MAC/B,OAAA;AAAA,MACA,GAAA,CAAI,MAAA,CAAO,YAAA,CAAa,MAAM,CAAC;AAAA,KACjC,CAAE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAEpB,IAAA,MAAM,MAAA,GAAS,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,KAAM,UAAA,CAAW,CAAA,EAAG,KAAA,GAAQ,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACzE,IAAA,OAAO,MAAA,GAAS,QAAA,IAAY,MAAA,GAAS,IAAA,GAAO,MAAA,GAAS,EAAA,CAAA;AAAA,EACvD;AAEA,EAAA,SAAS,YAAY,IAAA,EAAqB;AACxC,IAAA,MAAM,CAAC,SAAA,EAAW,GAAG,QAAQ,IAAI,IAAA,CAAK,QAAA;AACtC,IAAA,IAAI,CAAC,WAAW,OAAO,EAAA;AAEvB,IAAA,MAAM,OAAA,GAAsB,CAAC,SAAA,EAAW,GAAG,QAAQ,CAAA;AAEnD,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,MAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AAC5C,QAAA,MAAM,IAAA,GAAO,GAAA,CAAI,QAAA,CAAS,CAAC,CAAA;AAC3B,QAAA,MAAM,IAAI,IAAA,GAAO,YAAA,CAAa,cAAc,IAAA,CAAK,QAA6B,CAAC,CAAA,GAAI,CAAA;AACnF,QAAA,MAAA,CAAO,CAAC,IAAI,IAAA,CAAK,GAAA,CAAI,OAAO,CAAC,CAAA,IAAK,GAAG,CAAC,CAAA;AAAA,MACxC;AAAA,IACF;AAEA,IAAA,SAAS,SAAA,CAAU,KAAe,QAAA,EAA2B;AAC3D,MAAA,MAAM,QAAQ,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AAC1C,QAAA,MAAM,IAAA,GAAO,aAAA,CAAc,IAAA,CAAK,QAA6B,CAAA;AAC7D,QAAA,MAAM,OAAO,MAAA,CAAO,CAAC,CAAA,IAAK,CAAA,IAAK,aAAa,IAAI,CAAA;AAChD,QAAA,MAAM,MAAA,GAAS,OAAO,GAAA,CAAI,MAAA,CAAO,KAAK,GAAA,CAAI,CAAA,EAAG,GAAG,CAAC,CAAA;AACjD,QAAA,OAAO,QAAA,GAAW,UAAA,CAAW,KAAA,CAAM,IAAA,EAAM,MAAM,CAAA,GAAI,MAAA;AAAA,MACrD,CAAC,CAAA;AACD,MAAA,OAAO,SAAA,GAAO,KAAA,CAAM,IAAA,CAAK,UAAK,CAAA,GAAI,SAAA;AAAA,IACpC;AAEA,IAAA,SAAS,UAAU,IAAA,EAAsB;AACvC,MAAA,OAAO,QAAA,GAAM,MAAA,CAAO,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,MAAA,CAAA,CAAQ,CAAA,IAAK,CAAA,IAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,QAAG,CAAA,GAAI,QAAA;AAAA,IACxE;AAEA,IAAA,MAAM,GAAA,GAAM,QAAA,GAAM,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,QAAA,CAAI,MAAA,CAAA,CAAQ,CAAA,IAAK,KAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,QAAG,CAAA,GAAI,QAAA;AAC1E,IAAA,MAAM,MAAA,GAAS,QAAA,GAAM,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,QAAA,CAAI,MAAA,CAAA,CAAQ,CAAA,IAAK,KAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,QAAG,CAAA,GAAI,QAAA;AAC7E,IAAA,MAAM,KAAA,GAAQ,CAAC,GAAA,EAAK,SAAA,CAAU,WAAW,IAAI,CAAA,EAAG,SAAA,CAAU,QAAG,CAAC,CAAA;AAC9D,IAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,MAAA,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,KAAK,CAAC,CAAA;AAAA,IAClC;AACA,IAAA,KAAA,CAAM,KAAK,MAAM,CAAA;AACjB,IAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,EACxB;AAEA,EAAA,SAAS,SAAS,KAAA,EAA8B;AAC9C,IAAA,OAAO,KAAA,CAAM,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA;AAAA,EACpC;AAEA,EAAA,SAAS,cAAc,KAAA,EAAkC;AACvD,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA,CAAE,KAAK,EAAE,CAAA;AAAA,EACxC;AAEA,EAAA,SAAS,aAAa,IAAA,EAA+B;AACnD,IAAA,QAAQ,KAAK,IAAA;AAAM,MACjB,KAAK,MAAA;AACH,QAAA,OAAQ,IAAA,CAAc,KAAA;AAAA,MACxB,KAAK,YAAA;AACH,QAAA,OAAO,UAAA,CAAW,KAAA,CAAM,UAAA,EAAa,IAAA,CAAoB,KAAK,CAAA;AAAA,MAChE,KAAK,QAAA;AACH,QAAA,OAAO,WAAW,KAAA,CAAM,IAAA,EAAM,aAAA,CAAe,IAAA,CAAgB,QAAQ,CAAC,CAAA;AAAA,MACxE,KAAK,UAAA;AACH,QAAA,OAAO,WAAW,KAAA,CAAM,MAAA,EAAQ,aAAA,CAAe,IAAA,CAAkB,QAAQ,CAAC,CAAA;AAAA,MAC5E,KAAK,QAAA;AACH,QAAA,OAAO,WAAW,KAAA,CAAM,aAAA,EAAe,aAAA,CAAe,IAAA,CAAgB,QAAQ,CAAC,CAAA;AAAA,MACjF,KAAK,MAAA,EAAQ;AACX,QAAA,MAAM,CAAA,GAAI,IAAA;AACV,QAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,CAAA,CAAE,QAAQ,CAAA;AACtC,QAAA,IAAI,UAAA,EAAY;AAEd,UAAA,MAAM,OAAA,GAAU,CAAA,CAAE,GAAA,CAAI,OAAA,CAAQ,oBAAoB,EAAE,CAAA;AACpD,UAAA,OAAO,WAAW,OAAO,CAAA,IAAA,EAAO,WAAW,KAAA,CAAM,IAAA,EAAM,KAAK,CAAC,CAAA,YAAA,CAAA;AAAA,QAC/D;AACA,QAAA,OAAO,CAAA,EAAG,WAAW,KAAA,CAAM,IAAA,EAAM,KAAK,CAAC,CAAA,EAAA,EAAK,EAAE,GAAG,CAAA,CAAA,CAAA;AAAA,MACnD;AAAA,MACA,KAAK,OAAA,EAAS;AACZ,QAAA,MAAM,GAAA,GAAM,IAAA;AACZ,QAAA,OAAO,CAAA,QAAA,EAAW,GAAA,CAAI,GAAA,IAAO,GAAA,CAAI,GAAG,CAAA,CAAA,CAAA;AAAA,MACtC;AAAA,MACA,KAAK,OAAA;AACH,QAAA,OAAO,IAAA;AAAA,MACT;AACE,QAAA,OAAO,EAAA;AAAA;AACX,EACF;AAEA,EAAA,OAAO,YAAA,CAAa,IAAI,QAAQ,CAAA;AAClC;;;ACnOO,IAAM,cAAA,GAAkD;AAAA,EAC7D,SAAA,CAAU,KAAW,OAAA,EAA8B;AACjD,IAAA,OAAO,YAAA,CAAa,KAAK,OAAO,CAAA;AAAA,EAClC;AACF;AAEO,SAAS,MAAA,CAAO,IAAY,OAAA,EAA+B;AAChE,EAAA,OAAO,SAAA,CAAU,EAAA,EAAI,cAAA,EAAgB,OAAO,CAAA;AAC9C","file":"chunk-5CRCBG3P.js","sourcesContent":["import type { AnsiTheme } from '../../types.js'\n\n// Raw ANSI escape helpers — no external dependency\nconst ESC = '\\x1b['\n\nfunction style(open: number | number[], close: number): { open: string; close: string } {\n const openCodes = Array.isArray(open) ? open : [open]\n return {\n open: `${ESC}${openCodes.join(';')}m`,\n close: `${ESC}${close}m`,\n }\n}\n\nexport const defaultTheme: AnsiTheme = {\n h1: style([1, 4, 35], 0), // bold + underline + magenta\n h2: style([1, 4, 36], 0), // bold + underline + cyan\n h3: style([1, 36], 0), // bold + cyan\n bold: style(1, 22),\n italic: style(3, 23),\n strikethrough: style(9, 29),\n inlineCode: style([7, 33], 0), // reverse + yellow\n codeBlock: style(90, 39), // dark grey\n blockquote: style(90, 39), // dark grey\n link: style([4, 34], 0), // underline + blue\n listBullet: '•',\n hrChar: '─',\n}\n","import type {\n Root, Content, PhrasingContent,\n Heading, Paragraph, Blockquote, Code, List, ListItem,\n Table, TableRow, ThematicBreak,\n Text, InlineCode, Strong, Emphasis, Delete, Link, Image, Break,\n} from 'mdast'\nimport type { AnsiOptions, AnsiStyle, AnsiTheme } from '../../types.js'\nimport { defaultTheme } from './theme.js'\n\n// ---------------------------------------------------------------------------\n// ANSI escape sequence width — strip sequences for width calc\n// ---------------------------------------------------------------------------\n\nconst ANSI_RE = /\\x1b\\[[^m]*m|\\x1b\\][^\\x07]*\\x07/g\n\nfunction visibleWidth(s: string): number {\n return s.replace(ANSI_RE, '').length\n}\n\n// ---------------------------------------------------------------------------\n// Word-wrap that respects invisible ANSI sequences\n// ---------------------------------------------------------------------------\n\nfunction wordWrap(text: string, columns: number, indent = ''): string {\n const indentWidth = visibleWidth(indent)\n const maxWidth = columns - indentWidth\n const words = text.split(/\\s+/).filter(Boolean)\n const lines: string[] = []\n let current = ''\n\n for (const word of words) {\n const candidate = current ? current + ' ' + word : word\n if (visibleWidth(candidate) > maxWidth && current) {\n lines.push(current)\n current = word\n } else {\n current = candidate\n }\n }\n if (current) lines.push(current)\n return lines.map((l) => indent + l).join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Renderer\n// ---------------------------------------------------------------------------\n\nexport function renderToAnsi(ast: Root, opts: AnsiOptions): string {\n const columns = opts.columns ?? (process.stdout.columns ?? 80)\n const hyperlinks = opts.hyperlinks ?? false\n const theme: AnsiTheme = { ...defaultTheme, ...(opts.theme ?? {}) }\n\n function applyStyle(s: AnsiStyle, text: string): string {\n return `${s.open}${text}${s.close}`\n }\n\n function renderBlocks(nodes: Content[]): string {\n return nodes.map((n) => renderBlock(n)).filter(Boolean).join('\\n\\n')\n }\n\n function renderBlock(node: Content | Root): string {\n switch (node.type) {\n case 'root':\n return renderBlocks((node as Root).children)\n case 'heading':\n return renderHeading(node as Heading)\n case 'paragraph':\n return renderParagraph(node as Paragraph)\n case 'blockquote':\n return renderBlockquote(node as Blockquote)\n case 'code':\n return renderCode(node as Code)\n case 'list':\n return renderList(node as List, 0)\n case 'table':\n return renderTable(node as Table)\n case 'thematicBreak':\n return renderHr(node as ThematicBreak)\n default:\n return ''\n }\n }\n\n function renderHeading(node: Heading): string {\n const text = renderInlines(node.children)\n const styleKey = (`h${node.depth}`) as keyof Pick<AnsiTheme, 'h1' | 'h2' | 'h3'>\n const s = (theme[styleKey] ?? theme.h3) as AnsiStyle\n return applyStyle(s, text)\n }\n\n function renderParagraph(node: Paragraph): string {\n const text = renderInlines(node.children)\n return wordWrap(text, columns)\n }\n\n function renderBlockquote(node: Blockquote): string {\n const inner = renderBlocks(node.children)\n const prefix = applyStyle(theme.blockquote, '│ ')\n return inner\n .split('\\n')\n .map((line) => prefix + line)\n .join('\\n')\n }\n\n function renderCode(node: Code): string {\n const lang = node.lang ? ` (${node.lang})` : ''\n const header = applyStyle(theme.codeBlock, `┌─ code${lang}`)\n const lines = node.value.split('\\n').map((l) => applyStyle(theme.codeBlock, `│ ${l}`))\n const footer = applyStyle(theme.codeBlock, '└─')\n return [header, ...lines, footer].join('\\n')\n }\n\n function renderList(node: List, depth: number): string {\n return node.children.map((li, i) => renderListItem(li, node, i + 1, depth)).join('\\n')\n }\n\n function renderListItem(node: ListItem, parent: List, index: number, depth: number): string {\n const indent = ' '.repeat(depth)\n const bullet = parent.ordered\n ? `${index}.`\n : applyStyle({ open: '', close: '' }, theme.listBullet)\n const prefix = `${indent}${bullet} `\n\n const nestedLists: List[] = []\n const textParts: string[] = []\n\n for (const child of node.children) {\n if (child.type === 'list') {\n nestedLists.push(child as List)\n } else if (child.type === 'paragraph') {\n textParts.push(renderInlines((child as Paragraph).children))\n }\n }\n\n const taskPrefix =\n node.checked !== null && node.checked !== undefined\n ? node.checked\n ? '[x] '\n : '[ ] '\n : ''\n\n const mainText = wordWrap(\n taskPrefix + textParts.join(' '),\n columns,\n ' '.repeat(visibleWidth(prefix)),\n ).replace(/^\\s+/, '')\n\n const nested = nestedLists.map((l) => renderList(l, depth + 1)).join('\\n')\n return prefix + mainText + (nested ? '\\n' + nested : '')\n }\n\n function renderTable(node: Table): string {\n const [headerRow, ...bodyRows] = node.children\n if (!headerRow) return ''\n\n const allRows: TableRow[] = [headerRow, ...bodyRows]\n // Compute column widths\n const widths: number[] = []\n for (const row of allRows) {\n for (let i = 0; i < row.children.length; i++) {\n const cell = row.children[i]\n const w = cell ? visibleWidth(renderInlines(cell.children as PhrasingContent[])) : 0\n widths[i] = Math.max(widths[i] ?? 0, w)\n }\n }\n\n function renderRow(row: TableRow, isHeader: boolean): string {\n const cells = row.children.map((cell, i) => {\n const text = renderInlines(cell.children as PhrasingContent[])\n const pad = (widths[i] ?? 0) - visibleWidth(text)\n const padded = text + ' '.repeat(Math.max(0, pad))\n return isHeader ? applyStyle(theme.bold, padded) : padded\n })\n return '│ ' + cells.join(' │ ') + ' │'\n }\n\n function separator(char: string): string {\n return '├' + widths.map((w) => char.repeat((w ?? 0) + 2)).join('┼') + '┤'\n }\n\n const top = '┌' + widths.map((w) => '─'.repeat((w ?? 0) + 2)).join('┬') + '┐'\n const bottom = '└' + widths.map((w) => '─'.repeat((w ?? 0) + 2)).join('┴') + '┘'\n const lines = [top, renderRow(headerRow, true), separator('─')]\n for (const row of bodyRows) {\n lines.push(renderRow(row, false))\n }\n lines.push(bottom)\n return lines.join('\\n')\n }\n\n function renderHr(_node: ThematicBreak): string {\n return theme.hrChar.repeat(columns)\n }\n\n function renderInlines(nodes: PhrasingContent[]): string {\n return nodes.map(renderInline).join('')\n }\n\n function renderInline(node: PhrasingContent): string {\n switch (node.type) {\n case 'text':\n return (node as Text).value\n case 'inlineCode':\n return applyStyle(theme.inlineCode, (node as InlineCode).value)\n case 'strong':\n return applyStyle(theme.bold, renderInlines((node as Strong).children))\n case 'emphasis':\n return applyStyle(theme.italic, renderInlines((node as Emphasis).children))\n case 'delete':\n return applyStyle(theme.strikethrough, renderInlines((node as Delete).children))\n case 'link': {\n const l = node as Link\n const label = renderInlines(l.children)\n if (hyperlinks) {\n // OSC 8 hyperlink — strip control chars to prevent sequence injection\n const safeUrl = l.url.replace(/[\\x00-\\x1f\\x7f]/g, '')\n return `\\x1b]8;;${safeUrl}\\x07${applyStyle(theme.link, label)}\\x1b]8;;\\x07`\n }\n return `${applyStyle(theme.link, label)} (${l.url})`\n }\n case 'image': {\n const img = node as Image\n return `[image: ${img.alt ?? img.url}]`\n }\n case 'break':\n return '\\n'\n default:\n return ''\n }\n }\n\n return renderBlocks(ast.children)\n}\n","import type { Root } from 'mdast'\nimport { serialize } from '../../serialize.js'\nimport type { AnsiOptions, Serializer } from '../../types.js'\nimport { renderToAnsi } from './renderer.js'\n\nexport const AnsiSerializer: Serializer<string, AnsiOptions> = {\n serialize(ast: Root, options: AnsiOptions): string {\n return renderToAnsi(ast, options)\n },\n}\n\nexport function toAnsi(md: string, options?: AnsiOptions): string {\n return serialize(md, AnsiSerializer, options)\n}\n\nexport type { AnsiOptions }\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var remarkGfm = require('remark-gfm');
|
|
4
|
+
var remarkParse = require('remark-parse');
|
|
5
|
+
var unified = require('unified');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
10
|
+
var remarkParse__default = /*#__PURE__*/_interopDefault(remarkParse);
|
|
11
|
+
|
|
12
|
+
// src/parser.ts
|
|
13
|
+
function parseMarkdown(md, opts = {}) {
|
|
14
|
+
const processor = unified.unified().use(remarkParse__default.default);
|
|
15
|
+
if (opts.gfm !== false) {
|
|
16
|
+
processor.use(remarkGfm__default.default);
|
|
17
|
+
}
|
|
18
|
+
if (opts.remarkPlugins) {
|
|
19
|
+
for (const plugin of opts.remarkPlugins) {
|
|
20
|
+
processor.use(plugin);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return processor.runSync(processor.parse(md));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/serialize.ts
|
|
27
|
+
function serialize(md, serializer, options) {
|
|
28
|
+
const opts = options ?? {};
|
|
29
|
+
const ast = parseMarkdown(md, opts);
|
|
30
|
+
return serializer.serialize(ast, opts);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
exports.serialize = serialize;
|
|
34
|
+
//# sourceMappingURL=chunk-DJVBCM6N.cjs.map
|
|
35
|
+
//# sourceMappingURL=chunk-DJVBCM6N.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parser.ts","../src/serialize.ts"],"names":["unified","remarkParse","remarkGfm"],"mappings":";;;;;;;;;;;;AAMO,SAAS,aAAA,CAAc,EAAA,EAAY,IAAA,GAAoB,EAAC,EAAS;AACtE,EAAA,MAAM,SAAA,GAAYA,eAAA,EAAQ,CAAE,GAAA,CAAIC,4BAAW,CAAA;AAE3C,EAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,EAAO;AACtB,IAAA,SAAA,CAAU,IAAIC,0BAAS,CAAA;AAAA,EACzB;AAEA,EAAA,IAAI,KAAK,aAAA,EAAe;AACtB,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,aAAA,EAAe;AACvC,MAAA,SAAA,CAAU,IAAI,MAAM,CAAA;AAAA,IACtB;AAAA,EACF;AAGA,EAAA,OAAO,SAAA,CAAU,OAAA,CAAQ,SAAA,CAAU,KAAA,CAAM,EAAE,CAAC,CAAA;AAC9C;;;AClBO,SAAS,SAAA,CACd,EAAA,EACA,UAAA,EACA,OAAA,EACS;AACT,EAAA,MAAM,IAAA,GAAO,WAAY,EAAC;AAC1B,EAAA,MAAM,GAAA,GAAM,aAAA,CAAc,EAAA,EAAI,IAAI,CAAA;AAClC,EAAA,OAAO,UAAA,CAAW,SAAA,CAAU,GAAA,EAAK,IAAI,CAAA;AACvC","file":"chunk-DJVBCM6N.cjs","sourcesContent":["import remarkGfm from 'remark-gfm'\nimport remarkParse from 'remark-parse'\nimport { unified } from 'unified'\nimport type { Root } from 'mdast'\nimport type { BaseOptions } from './types.js'\n\nexport function parseMarkdown(md: string, opts: BaseOptions = {}): Root {\n const processor = unified().use(remarkParse)\n\n if (opts.gfm !== false) {\n processor.use(remarkGfm)\n }\n\n if (opts.remarkPlugins) {\n for (const plugin of opts.remarkPlugins) {\n processor.use(plugin)\n }\n }\n\n // parse() only tokenises; runSync() applies transformer plugins (e.g. user-supplied ones)\n return processor.runSync(processor.parse(md)) as Root\n}\n","import { parseMarkdown } from './parser.js'\nimport type { BaseOptions, Serializer } from './types.js'\n\nexport function serialize<TOutput, TOptions extends BaseOptions = BaseOptions>(\n md: string,\n serializer: Serializer<TOutput, TOptions>,\n options?: TOptions,\n): TOutput {\n const opts = options ?? ({} as TOptions)\n const ast = parseMarkdown(md, opts)\n return serializer.serialize(ast, opts)\n}\n"]}
|