pd-markdown 2.0.1 → 2.0.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 +7 -5
- package/package.json +23 -12
- package/packages/parser/dist/index.cjs +191 -0
- package/packages/parser/dist/index.cjs.map +1 -0
- package/packages/parser/dist/index.d.ts +121 -0
- package/packages/parser/dist/index.mjs +185 -0
- package/packages/parser/dist/index.mjs.map +1 -0
- package/packages/utils/dist/index.cjs +358 -0
- package/packages/utils/dist/index.cjs.map +1 -0
- package/packages/utils/dist/index.d.ts +144 -0
- package/packages/utils/dist/index.mjs +343 -0
- package/packages/utils/dist/index.mjs.map +1 -0
- package/packages/web/dist/index.cjs +715 -0
- package/packages/web/dist/index.cjs.map +1 -0
- package/packages/web/dist/index.d.ts +265 -0
- package/packages/web/dist/index.mjs +694 -0
- package/packages/web/dist/index.mjs.map +1 -0
- package/packages/parser/README.md +0 -120
- package/packages/utils/README.md +0 -130
- package/packages/web/README.md +0 -110
package/README.md
CHANGED
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
- ⚛️ **React 组件** - 提供开箱即用的 React 渲染组件
|
|
12
12
|
- 🎨 **可定制** - 支持自定义组件覆盖(Heading, Code, Table 等)
|
|
13
13
|
- 🔗 **自动锚点** - 标题自动生成 slug 锚点
|
|
14
|
-
- 📦 **Tree-shakable** -
|
|
14
|
+
- 📦 **Tree-shakable** - 基于 ESM 设计,支持按需加载,最小化打包体积
|
|
15
|
+
- 🛠️ **现代兼容性** - 完美支持 Subpath Exports,确保在 Next.js、Vite 等现代开发环境下无缝解析
|
|
16
|
+
- 🛡️ **类型友好** - 完整的 TypeScript 定义,提供极致的开发体验
|
|
15
17
|
|
|
16
18
|
## 安装
|
|
17
19
|
|
|
@@ -29,10 +31,10 @@ yarn add pd-markdown
|
|
|
29
31
|
## 模块结构
|
|
30
32
|
|
|
31
33
|
| 模块路径 | 描述 |
|
|
32
|
-
|
|
|
33
|
-
| `pd-markdown/parser` |
|
|
34
|
-
| `pd-markdown/web` | React
|
|
35
|
-
| `pd-markdown/utils` |
|
|
34
|
+
| :--- | :--- |
|
|
35
|
+
| `pd-markdown/parser` | **核心解析器**:将 Markdown 转换为标准 AST |
|
|
36
|
+
| `pd-markdown/web` | **React 渲染层**:包含渲染组件与流式处理 Hooks |
|
|
37
|
+
| `pd-markdown/utils` | **通用工具**:提供 AST 遍历、Slug 生成及字符串处理 |
|
|
36
38
|
|
|
37
39
|
## 快速开始
|
|
38
40
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pd-markdown",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"type": "module",
|
|
5
|
+
"main": "./packages/web/dist/index.cjs",
|
|
6
|
+
"module": "./packages/web/dist/index.mjs",
|
|
7
|
+
"types": "./packages/web/dist/index.d.ts",
|
|
5
8
|
"description": "A modular markdown parsing and rendering library",
|
|
6
9
|
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./packages/web/dist/index.d.ts",
|
|
12
|
+
"import": "./packages/web/dist/index.mjs",
|
|
13
|
+
"require": "./packages/web/dist/index.cjs"
|
|
14
|
+
},
|
|
7
15
|
"./parser": {
|
|
8
16
|
"types": "./packages/parser/dist/index.d.ts",
|
|
9
17
|
"import": "./packages/parser/dist/index.mjs",
|
|
@@ -22,6 +30,9 @@
|
|
|
22
30
|
},
|
|
23
31
|
"typesVersions": {
|
|
24
32
|
"*": {
|
|
33
|
+
".": [
|
|
34
|
+
"./packages/web/dist/index.d.ts"
|
|
35
|
+
],
|
|
25
36
|
"parser": [
|
|
26
37
|
"./packages/parser/dist/index.d.ts"
|
|
27
38
|
],
|
|
@@ -36,15 +47,6 @@
|
|
|
36
47
|
"files": [
|
|
37
48
|
"packages/*/dist"
|
|
38
49
|
],
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "pnpm -r run build",
|
|
41
|
-
"test": "vitest run",
|
|
42
|
-
"test:watch": "vitest",
|
|
43
|
-
"test:coverage": "vitest run --coverage",
|
|
44
|
-
"typecheck": "tsc --noEmit",
|
|
45
|
-
"clean": "pnpm -r run clean",
|
|
46
|
-
"prepublishOnly": "pnpm run build"
|
|
47
|
-
},
|
|
48
50
|
"peerDependencies": {
|
|
49
51
|
"react": "^18.0.0 || ^19.0.0",
|
|
50
52
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
@@ -72,6 +74,7 @@
|
|
|
72
74
|
"@rollup/rollup-darwin-arm64": "^4.57.1",
|
|
73
75
|
"@testing-library/jest-dom": "^6.9.1",
|
|
74
76
|
"@types/node": "^22.13.5",
|
|
77
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
75
78
|
"rollup": "^4.34.8",
|
|
76
79
|
"rollup-plugin-dts": "^6.1.1",
|
|
77
80
|
"tslib": "^2.8.1",
|
|
@@ -91,5 +94,13 @@
|
|
|
91
94
|
"type": "git",
|
|
92
95
|
"url": "https://github.com/LaoChen1994/pd-markdown"
|
|
93
96
|
},
|
|
94
|
-
"sideEffects": false
|
|
95
|
-
|
|
97
|
+
"sideEffects": false,
|
|
98
|
+
"scripts": {
|
|
99
|
+
"build": "pnpm -r run build",
|
|
100
|
+
"test": "vitest run",
|
|
101
|
+
"test:watch": "vitest",
|
|
102
|
+
"test:coverage": "vitest run --coverage",
|
|
103
|
+
"typecheck": "tsc --noEmit",
|
|
104
|
+
"clean": "pnpm -r run clean"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var unified = require('unified');
|
|
4
|
+
var remarkParse = require('remark-parse');
|
|
5
|
+
var remarkGfm = require('remark-gfm');
|
|
6
|
+
var remarkFrontmatter = require('remark-frontmatter');
|
|
7
|
+
var unistUtilVisit = require('unist-util-visit');
|
|
8
|
+
var yaml = require('yaml');
|
|
9
|
+
var pdMarkdownUtils = require('pd-markdown/utils');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Extract text content from phrasing content nodes
|
|
13
|
+
*/
|
|
14
|
+
function extractText(nodes) {
|
|
15
|
+
return nodes
|
|
16
|
+
.map((node) => {
|
|
17
|
+
if (node.type === 'text') {
|
|
18
|
+
return node.value;
|
|
19
|
+
}
|
|
20
|
+
if ('children' in node) {
|
|
21
|
+
return extractText(node.children);
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
})
|
|
25
|
+
.join('');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Transform plugin that adds slug IDs to headings
|
|
29
|
+
*/
|
|
30
|
+
function transformHeading(tree) {
|
|
31
|
+
const slugs = new Set();
|
|
32
|
+
unistUtilVisit.visit(tree, 'heading', (node) => {
|
|
33
|
+
const text = extractText(node.children);
|
|
34
|
+
const slug = pdMarkdownUtils.uniqueSlugify(text, slugs);
|
|
35
|
+
// Add data.id to the heading node
|
|
36
|
+
const data = (node.data || {});
|
|
37
|
+
data.id = slug;
|
|
38
|
+
const hProperties = (data.hProperties || {});
|
|
39
|
+
hProperties.id = slug;
|
|
40
|
+
data.hProperties = hProperties;
|
|
41
|
+
node.data = data;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Transform plugin that adds index to list items
|
|
47
|
+
*/
|
|
48
|
+
function transformList(tree) {
|
|
49
|
+
unistUtilVisit.visit(tree, 'list', (node) => {
|
|
50
|
+
node.children.forEach((item, index) => {
|
|
51
|
+
item.data = item.data || {};
|
|
52
|
+
item.data.index = index;
|
|
53
|
+
// For ordered lists, also store the actual number
|
|
54
|
+
if (node.ordered) {
|
|
55
|
+
const start = node.start ?? 1;
|
|
56
|
+
item.data.index = start + index;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Transform plugin that enhances table structure
|
|
64
|
+
* - Separates header and body rows
|
|
65
|
+
* - Adds alignment and index info to cells
|
|
66
|
+
*/
|
|
67
|
+
function transformTable(tree) {
|
|
68
|
+
unistUtilVisit.visit(tree, 'table', (node) => {
|
|
69
|
+
if (node.children.length === 0)
|
|
70
|
+
return;
|
|
71
|
+
const [headerRow, ...bodyRows] = node.children;
|
|
72
|
+
const align = node.align || [];
|
|
73
|
+
// Mark header row and cells
|
|
74
|
+
if (headerRow) {
|
|
75
|
+
headerRow.children.forEach((cell, index) => {
|
|
76
|
+
cell.data = cell.data || {};
|
|
77
|
+
cell.data.isHeader = true;
|
|
78
|
+
cell.data.align = align[index] || null;
|
|
79
|
+
cell.data.columnIndex = index;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// Mark body cells
|
|
83
|
+
bodyRows.forEach((row) => {
|
|
84
|
+
row.children.forEach((cell, index) => {
|
|
85
|
+
cell.data = cell.data || {};
|
|
86
|
+
cell.data.isHeader = false;
|
|
87
|
+
cell.data.align = align[index] || null;
|
|
88
|
+
cell.data.columnIndex = index;
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
// Store structured data on table node
|
|
92
|
+
node.data = node.data || {};
|
|
93
|
+
node.data.header = headerRow;
|
|
94
|
+
node.data.body = bodyRows;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Default parser options
|
|
100
|
+
*/
|
|
101
|
+
const DEFAULT_OPTIONS = {
|
|
102
|
+
gfm: true,
|
|
103
|
+
frontmatter: true,
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Create frontmatter extraction plugin
|
|
107
|
+
*/
|
|
108
|
+
function extractFrontmatter() {
|
|
109
|
+
return (tree, file) => {
|
|
110
|
+
unistUtilVisit.visit(tree, 'yaml', (node) => {
|
|
111
|
+
try {
|
|
112
|
+
const data = yaml.parse(node.value);
|
|
113
|
+
file.data.frontmatter = data;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Invalid YAML, ignore
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Create a markdown parser with the specified options
|
|
123
|
+
*
|
|
124
|
+
* @param options - Parser configuration options
|
|
125
|
+
* @returns Parser instance with parse method
|
|
126
|
+
*/
|
|
127
|
+
function createParser(options = {}) {
|
|
128
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
129
|
+
const customPlugins = options.plugins || [];
|
|
130
|
+
// Build processor (使用 any 绕过复杂的类型检查)
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
132
|
+
let processor = unified.unified().use(remarkParse);
|
|
133
|
+
// Add GFM support
|
|
134
|
+
if (opts.gfm) {
|
|
135
|
+
processor = processor.use(remarkGfm);
|
|
136
|
+
}
|
|
137
|
+
// Add frontmatter support
|
|
138
|
+
if (opts.frontmatter) {
|
|
139
|
+
processor = processor.use(remarkFrontmatter, ['yaml']);
|
|
140
|
+
}
|
|
141
|
+
// Run custom "before" plugins
|
|
142
|
+
const beforePlugins = customPlugins.filter((p) => p.phase === 'before');
|
|
143
|
+
for (const plugin of beforePlugins) {
|
|
144
|
+
processor = processor.use(() => plugin.transform);
|
|
145
|
+
}
|
|
146
|
+
// Add frontmatter extraction
|
|
147
|
+
if (opts.frontmatter) {
|
|
148
|
+
processor = processor.use(extractFrontmatter);
|
|
149
|
+
}
|
|
150
|
+
// Add built-in transform plugins
|
|
151
|
+
processor = processor
|
|
152
|
+
.use(() => transformHeading)
|
|
153
|
+
.use(() => transformList)
|
|
154
|
+
.use(() => transformTable);
|
|
155
|
+
// Run custom "after" plugins
|
|
156
|
+
const afterPlugins = customPlugins.filter((p) => p.phase === 'after');
|
|
157
|
+
for (const plugin of afterPlugins) {
|
|
158
|
+
processor = processor.use(() => plugin.transform);
|
|
159
|
+
}
|
|
160
|
+
// Freeze processor
|
|
161
|
+
processor.freeze();
|
|
162
|
+
return {
|
|
163
|
+
parse(content) {
|
|
164
|
+
// Parse markdown to AST
|
|
165
|
+
const tree = processor.parse(content);
|
|
166
|
+
// Run all transform plugins
|
|
167
|
+
processor.runSync(tree);
|
|
168
|
+
return tree;
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Type-safe helper to define a parser plugin
|
|
174
|
+
*
|
|
175
|
+
* @param config - Plugin configuration
|
|
176
|
+
* @returns Parser plugin
|
|
177
|
+
*/
|
|
178
|
+
function definePlugin(config, options) {
|
|
179
|
+
return {
|
|
180
|
+
name: config.name,
|
|
181
|
+
phase: config.phase,
|
|
182
|
+
transform: config.transform(options),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
exports.createParser = createParser;
|
|
187
|
+
exports.definePlugin = definePlugin;
|
|
188
|
+
exports.transformHeading = transformHeading;
|
|
189
|
+
exports.transformList = transformList;
|
|
190
|
+
exports.transformTable = transformTable;
|
|
191
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/plugins/transform/heading.ts","../src/plugins/transform/list.ts","../src/plugins/transform/table.ts","../src/processor.ts"],"sourcesContent":[null,null,null,null],"names":["visit","uniqueSlugify","parseYaml","unified"],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Root } from 'mdast';
|
|
2
|
+
import { VFile } from 'vfile';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parser plugin configuration
|
|
6
|
+
*/
|
|
7
|
+
interface ParserPlugin {
|
|
8
|
+
/** Unique plugin name */
|
|
9
|
+
name: string;
|
|
10
|
+
/** When to run: before or after built-in transforms */
|
|
11
|
+
phase: 'before' | 'after';
|
|
12
|
+
/** Transform function */
|
|
13
|
+
transform: (tree: Root, file: VFile) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parser options
|
|
17
|
+
*/
|
|
18
|
+
interface ParserOptions {
|
|
19
|
+
/** Custom plugins to add */
|
|
20
|
+
plugins?: ParserPlugin[];
|
|
21
|
+
/** Enable GFM syntax (default: true) */
|
|
22
|
+
gfm?: boolean;
|
|
23
|
+
/** Enable frontmatter parsing (default: true) */
|
|
24
|
+
frontmatter?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parser instance
|
|
28
|
+
*/
|
|
29
|
+
interface Parser {
|
|
30
|
+
/** Parse markdown string to AST */
|
|
31
|
+
parse(content: string): Root;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Plugin definition helper config
|
|
35
|
+
*/
|
|
36
|
+
interface PluginConfig<T = unknown> {
|
|
37
|
+
/** Plugin name */
|
|
38
|
+
name: string;
|
|
39
|
+
/** When to run */
|
|
40
|
+
phase: 'before' | 'after';
|
|
41
|
+
/** Transform function factory */
|
|
42
|
+
transform: (options?: T) => (tree: Root, file: VFile) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Frontmatter data extracted from markdown
|
|
46
|
+
*/
|
|
47
|
+
interface FrontmatterData {
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Extended file data with frontmatter
|
|
52
|
+
*/
|
|
53
|
+
interface FileData {
|
|
54
|
+
frontmatter?: FrontmatterData;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Create a markdown parser with the specified options
|
|
59
|
+
*
|
|
60
|
+
* @param options - Parser configuration options
|
|
61
|
+
* @returns Parser instance with parse method
|
|
62
|
+
*/
|
|
63
|
+
declare function createParser(options?: ParserOptions): Parser;
|
|
64
|
+
/**
|
|
65
|
+
* Type-safe helper to define a parser plugin
|
|
66
|
+
*
|
|
67
|
+
* @param config - Plugin configuration
|
|
68
|
+
* @returns Parser plugin
|
|
69
|
+
*/
|
|
70
|
+
declare function definePlugin<T = void>(config: {
|
|
71
|
+
name: string;
|
|
72
|
+
phase: 'before' | 'after';
|
|
73
|
+
transform: (options?: T) => (tree: Root, file: VFile) => void;
|
|
74
|
+
}, options?: T): ParserPlugin;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Transform plugin that adds slug IDs to headings
|
|
78
|
+
*/
|
|
79
|
+
declare function transformHeading(tree: Root): void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Extended list item with index
|
|
83
|
+
*/
|
|
84
|
+
declare module 'mdast' {
|
|
85
|
+
interface ListItemData {
|
|
86
|
+
index?: number;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Transform plugin that adds index to list items
|
|
91
|
+
*/
|
|
92
|
+
declare function transformList(tree: Root): void;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extended table data
|
|
96
|
+
*/
|
|
97
|
+
declare module 'mdast' {
|
|
98
|
+
interface TableData {
|
|
99
|
+
/** Header row */
|
|
100
|
+
header?: TableRow;
|
|
101
|
+
/** Body rows */
|
|
102
|
+
body?: TableRow[];
|
|
103
|
+
}
|
|
104
|
+
interface TableCellData {
|
|
105
|
+
/** Whether this cell is in header */
|
|
106
|
+
isHeader?: boolean;
|
|
107
|
+
/** Column alignment */
|
|
108
|
+
align?: 'left' | 'center' | 'right' | null;
|
|
109
|
+
/** Column index */
|
|
110
|
+
columnIndex?: number;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Transform plugin that enhances table structure
|
|
115
|
+
* - Separates header and body rows
|
|
116
|
+
* - Adds alignment and index info to cells
|
|
117
|
+
*/
|
|
118
|
+
declare function transformTable(tree: Root): void;
|
|
119
|
+
|
|
120
|
+
export { createParser, definePlugin, transformHeading, transformList, transformTable };
|
|
121
|
+
export type { FileData, FrontmatterData, Parser, ParserOptions, ParserPlugin, PluginConfig };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { unified } from 'unified';
|
|
2
|
+
import remarkParse from 'remark-parse';
|
|
3
|
+
import remarkGfm from 'remark-gfm';
|
|
4
|
+
import remarkFrontmatter from 'remark-frontmatter';
|
|
5
|
+
import { visit } from 'unist-util-visit';
|
|
6
|
+
import { parse } from 'yaml';
|
|
7
|
+
import { uniqueSlugify } from 'pd-markdown/utils';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extract text content from phrasing content nodes
|
|
11
|
+
*/
|
|
12
|
+
function extractText(nodes) {
|
|
13
|
+
return nodes
|
|
14
|
+
.map((node) => {
|
|
15
|
+
if (node.type === 'text') {
|
|
16
|
+
return node.value;
|
|
17
|
+
}
|
|
18
|
+
if ('children' in node) {
|
|
19
|
+
return extractText(node.children);
|
|
20
|
+
}
|
|
21
|
+
return '';
|
|
22
|
+
})
|
|
23
|
+
.join('');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Transform plugin that adds slug IDs to headings
|
|
27
|
+
*/
|
|
28
|
+
function transformHeading(tree) {
|
|
29
|
+
const slugs = new Set();
|
|
30
|
+
visit(tree, 'heading', (node) => {
|
|
31
|
+
const text = extractText(node.children);
|
|
32
|
+
const slug = uniqueSlugify(text, slugs);
|
|
33
|
+
// Add data.id to the heading node
|
|
34
|
+
const data = (node.data || {});
|
|
35
|
+
data.id = slug;
|
|
36
|
+
const hProperties = (data.hProperties || {});
|
|
37
|
+
hProperties.id = slug;
|
|
38
|
+
data.hProperties = hProperties;
|
|
39
|
+
node.data = data;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Transform plugin that adds index to list items
|
|
45
|
+
*/
|
|
46
|
+
function transformList(tree) {
|
|
47
|
+
visit(tree, 'list', (node) => {
|
|
48
|
+
node.children.forEach((item, index) => {
|
|
49
|
+
item.data = item.data || {};
|
|
50
|
+
item.data.index = index;
|
|
51
|
+
// For ordered lists, also store the actual number
|
|
52
|
+
if (node.ordered) {
|
|
53
|
+
const start = node.start ?? 1;
|
|
54
|
+
item.data.index = start + index;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Transform plugin that enhances table structure
|
|
62
|
+
* - Separates header and body rows
|
|
63
|
+
* - Adds alignment and index info to cells
|
|
64
|
+
*/
|
|
65
|
+
function transformTable(tree) {
|
|
66
|
+
visit(tree, 'table', (node) => {
|
|
67
|
+
if (node.children.length === 0)
|
|
68
|
+
return;
|
|
69
|
+
const [headerRow, ...bodyRows] = node.children;
|
|
70
|
+
const align = node.align || [];
|
|
71
|
+
// Mark header row and cells
|
|
72
|
+
if (headerRow) {
|
|
73
|
+
headerRow.children.forEach((cell, index) => {
|
|
74
|
+
cell.data = cell.data || {};
|
|
75
|
+
cell.data.isHeader = true;
|
|
76
|
+
cell.data.align = align[index] || null;
|
|
77
|
+
cell.data.columnIndex = index;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Mark body cells
|
|
81
|
+
bodyRows.forEach((row) => {
|
|
82
|
+
row.children.forEach((cell, index) => {
|
|
83
|
+
cell.data = cell.data || {};
|
|
84
|
+
cell.data.isHeader = false;
|
|
85
|
+
cell.data.align = align[index] || null;
|
|
86
|
+
cell.data.columnIndex = index;
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
// Store structured data on table node
|
|
90
|
+
node.data = node.data || {};
|
|
91
|
+
node.data.header = headerRow;
|
|
92
|
+
node.data.body = bodyRows;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Default parser options
|
|
98
|
+
*/
|
|
99
|
+
const DEFAULT_OPTIONS = {
|
|
100
|
+
gfm: true,
|
|
101
|
+
frontmatter: true,
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Create frontmatter extraction plugin
|
|
105
|
+
*/
|
|
106
|
+
function extractFrontmatter() {
|
|
107
|
+
return (tree, file) => {
|
|
108
|
+
visit(tree, 'yaml', (node) => {
|
|
109
|
+
try {
|
|
110
|
+
const data = parse(node.value);
|
|
111
|
+
file.data.frontmatter = data;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Invalid YAML, ignore
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Create a markdown parser with the specified options
|
|
121
|
+
*
|
|
122
|
+
* @param options - Parser configuration options
|
|
123
|
+
* @returns Parser instance with parse method
|
|
124
|
+
*/
|
|
125
|
+
function createParser(options = {}) {
|
|
126
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
127
|
+
const customPlugins = options.plugins || [];
|
|
128
|
+
// Build processor (使用 any 绕过复杂的类型检查)
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
130
|
+
let processor = unified().use(remarkParse);
|
|
131
|
+
// Add GFM support
|
|
132
|
+
if (opts.gfm) {
|
|
133
|
+
processor = processor.use(remarkGfm);
|
|
134
|
+
}
|
|
135
|
+
// Add frontmatter support
|
|
136
|
+
if (opts.frontmatter) {
|
|
137
|
+
processor = processor.use(remarkFrontmatter, ['yaml']);
|
|
138
|
+
}
|
|
139
|
+
// Run custom "before" plugins
|
|
140
|
+
const beforePlugins = customPlugins.filter((p) => p.phase === 'before');
|
|
141
|
+
for (const plugin of beforePlugins) {
|
|
142
|
+
processor = processor.use(() => plugin.transform);
|
|
143
|
+
}
|
|
144
|
+
// Add frontmatter extraction
|
|
145
|
+
if (opts.frontmatter) {
|
|
146
|
+
processor = processor.use(extractFrontmatter);
|
|
147
|
+
}
|
|
148
|
+
// Add built-in transform plugins
|
|
149
|
+
processor = processor
|
|
150
|
+
.use(() => transformHeading)
|
|
151
|
+
.use(() => transformList)
|
|
152
|
+
.use(() => transformTable);
|
|
153
|
+
// Run custom "after" plugins
|
|
154
|
+
const afterPlugins = customPlugins.filter((p) => p.phase === 'after');
|
|
155
|
+
for (const plugin of afterPlugins) {
|
|
156
|
+
processor = processor.use(() => plugin.transform);
|
|
157
|
+
}
|
|
158
|
+
// Freeze processor
|
|
159
|
+
processor.freeze();
|
|
160
|
+
return {
|
|
161
|
+
parse(content) {
|
|
162
|
+
// Parse markdown to AST
|
|
163
|
+
const tree = processor.parse(content);
|
|
164
|
+
// Run all transform plugins
|
|
165
|
+
processor.runSync(tree);
|
|
166
|
+
return tree;
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Type-safe helper to define a parser plugin
|
|
172
|
+
*
|
|
173
|
+
* @param config - Plugin configuration
|
|
174
|
+
* @returns Parser plugin
|
|
175
|
+
*/
|
|
176
|
+
function definePlugin(config, options) {
|
|
177
|
+
return {
|
|
178
|
+
name: config.name,
|
|
179
|
+
phase: config.phase,
|
|
180
|
+
transform: config.transform(options),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export { createParser, definePlugin, transformHeading, transformList, transformTable };
|
|
185
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/plugins/transform/heading.ts","../src/plugins/transform/list.ts","../src/plugins/transform/table.ts","../src/processor.ts"],"sourcesContent":[null,null,null,null],"names":["parseYaml"],"mappings":"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"}
|