@luckyfishes/markdown-core 0.1.0 → 0.2.1
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 +399 -14
- package/dist/index.cjs +1220 -0
- package/dist/index.d.cts +140 -0
- package/dist/index.js +28 -4
- package/package.json +7 -4
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { PluggableList } from 'unified';
|
|
2
|
+
import { RootContent, Text, Root } from 'mdast';
|
|
3
|
+
|
|
4
|
+
declare const FOOTNOTES_HEADING_TEXT = "Footnotes";
|
|
5
|
+
declare const FOOTNOTES_HEADING_ID = "footnote-label";
|
|
6
|
+
type FootnotesOptions = {
|
|
7
|
+
headingId?: string;
|
|
8
|
+
headingText?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type HastNode$1 = {
|
|
12
|
+
type: string;
|
|
13
|
+
tagName?: string;
|
|
14
|
+
properties?: Record<string, unknown>;
|
|
15
|
+
children?: HastNode$1[];
|
|
16
|
+
value?: string;
|
|
17
|
+
};
|
|
18
|
+
type CodeFenceComponentMapping = {
|
|
19
|
+
componentName: string;
|
|
20
|
+
propName: string;
|
|
21
|
+
};
|
|
22
|
+
type CodeFenceComponentMappings = Record<string, CodeFenceComponentMapping>;
|
|
23
|
+
declare const DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS: CodeFenceComponentMappings;
|
|
24
|
+
declare function createCodeFenceComponentPlugin(mappings?: CodeFenceComponentMappings): (tree: HastNode$1) => void;
|
|
25
|
+
|
|
26
|
+
type NodeWithPosition = {
|
|
27
|
+
position?: {
|
|
28
|
+
start?: {
|
|
29
|
+
line?: number;
|
|
30
|
+
offset?: number;
|
|
31
|
+
};
|
|
32
|
+
end?: {
|
|
33
|
+
line?: number;
|
|
34
|
+
offset?: number;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
type FlowNode = RootContent & NodeWithPosition;
|
|
39
|
+
type CustomSyntaxComponentNames = {
|
|
40
|
+
badge: string;
|
|
41
|
+
tip: string;
|
|
42
|
+
tabs: string;
|
|
43
|
+
tabsList: string;
|
|
44
|
+
tabsTrigger: string;
|
|
45
|
+
tabsContent: string;
|
|
46
|
+
};
|
|
47
|
+
type CustomSyntaxOptions = {
|
|
48
|
+
componentNames?: Partial<CustomSyntaxComponentNames>;
|
|
49
|
+
};
|
|
50
|
+
declare const DEFAULT_CUSTOM_SYNTAX_COMPONENT_NAMES: CustomSyntaxComponentNames;
|
|
51
|
+
declare function resolveCustomSyntaxComponentNames(options?: CustomSyntaxOptions): CustomSyntaxComponentNames;
|
|
52
|
+
type BlockHandlerKind = "block" | "container";
|
|
53
|
+
type BlockHandlerMatchContext = {
|
|
54
|
+
children: FlowNode[];
|
|
55
|
+
componentNames: CustomSyntaxComponentNames;
|
|
56
|
+
getNodeSource: (node: NodeWithPosition) => string;
|
|
57
|
+
index: number;
|
|
58
|
+
source: string;
|
|
59
|
+
lines: string[];
|
|
60
|
+
};
|
|
61
|
+
type BlockHandlerTransformContext = BlockHandlerMatchContext & {
|
|
62
|
+
consumeThroughLine: (endLine: number) => number;
|
|
63
|
+
createFlowElement: (name: string, props?: Record<string, unknown>, children?: RootContent[]) => RootContent;
|
|
64
|
+
createInlineTextElement: (name: string, props?: Record<string, unknown>, text?: string) => RootContent;
|
|
65
|
+
createText: (value: string) => Text;
|
|
66
|
+
getLine: (lineNumber: number) => string;
|
|
67
|
+
getNodeSource: (node: NodeWithPosition) => string;
|
|
68
|
+
parseYamlProps: (yamlSource: string) => Record<string, unknown>;
|
|
69
|
+
transformFragment: (markdown: string) => RootContent[];
|
|
70
|
+
};
|
|
71
|
+
type BlockHandlerResult = {
|
|
72
|
+
consumed: number;
|
|
73
|
+
nodes: RootContent[];
|
|
74
|
+
};
|
|
75
|
+
type CustomSyntaxBlockHandler = {
|
|
76
|
+
kind: BlockHandlerKind;
|
|
77
|
+
match: (context: BlockHandlerMatchContext) => boolean;
|
|
78
|
+
name: string;
|
|
79
|
+
priority?: number;
|
|
80
|
+
transform: (context: BlockHandlerTransformContext) => BlockHandlerResult;
|
|
81
|
+
};
|
|
82
|
+
type InlineHandlerContext = {
|
|
83
|
+
componentNames: CustomSyntaxComponentNames;
|
|
84
|
+
createInlineTextElement: (name: string, props?: Record<string, unknown>, text?: string) => RootContent;
|
|
85
|
+
createText: (value: string) => Text;
|
|
86
|
+
getNodeSource: (node: NodeWithPosition) => string;
|
|
87
|
+
source: string;
|
|
88
|
+
};
|
|
89
|
+
type CustomSyntaxInlineHandler = {
|
|
90
|
+
kind: "inline";
|
|
91
|
+
match: (nodes: RootContent[], index: number, context: InlineHandlerContext) => boolean;
|
|
92
|
+
name: string;
|
|
93
|
+
priority?: number;
|
|
94
|
+
transform: (nodes: RootContent[], index: number, context: InlineHandlerContext) => {
|
|
95
|
+
consumed: number;
|
|
96
|
+
nodes: RootContent[];
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
type MarkdownPresetOptions = {
|
|
101
|
+
codeFenceMappings?: CodeFenceComponentMappings;
|
|
102
|
+
customSyntax?: CustomSyntaxOptions;
|
|
103
|
+
footnotes?: FootnotesOptions;
|
|
104
|
+
};
|
|
105
|
+
type MarkdownPreset = {
|
|
106
|
+
remarkPlugins: PluggableList;
|
|
107
|
+
rehypePlugins: PluggableList;
|
|
108
|
+
};
|
|
109
|
+
declare function createMarkdownPreset(options?: MarkdownPresetOptions): MarkdownPreset;
|
|
110
|
+
|
|
111
|
+
type HastNode = {
|
|
112
|
+
type: string;
|
|
113
|
+
tagName?: string;
|
|
114
|
+
properties?: Record<string, unknown>;
|
|
115
|
+
children?: HastNode[];
|
|
116
|
+
value?: string;
|
|
117
|
+
};
|
|
118
|
+
declare function rehypeFootnotesHeading(options?: FootnotesOptions): (tree: HastNode) => void;
|
|
119
|
+
|
|
120
|
+
declare function createCustomSyntaxRemarkPlugin(options?: CustomSyntaxOptions): (tree: Root, file?: {
|
|
121
|
+
value?: unknown;
|
|
122
|
+
}) => void;
|
|
123
|
+
|
|
124
|
+
declare const YAML_PROP_PREFIX = "__YAML__";
|
|
125
|
+
|
|
126
|
+
type MdastNode = {
|
|
127
|
+
type: string;
|
|
128
|
+
value?: string;
|
|
129
|
+
children?: MdastNode[];
|
|
130
|
+
};
|
|
131
|
+
declare function remarkSuperSub(): (tree: MdastNode) => void;
|
|
132
|
+
|
|
133
|
+
type MarkdownHeading = {
|
|
134
|
+
depth: 1 | 2 | 3;
|
|
135
|
+
text: string;
|
|
136
|
+
id: string;
|
|
137
|
+
};
|
|
138
|
+
declare function extractHeadings(markdown: string, options?: FootnotesOptions): MarkdownHeading[];
|
|
139
|
+
|
|
140
|
+
export { type CodeFenceComponentMapping, type CodeFenceComponentMappings, type CustomSyntaxBlockHandler, type CustomSyntaxComponentNames, type CustomSyntaxInlineHandler, type CustomSyntaxOptions, DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS, DEFAULT_CUSTOM_SYNTAX_COMPONENT_NAMES, FOOTNOTES_HEADING_ID, FOOTNOTES_HEADING_TEXT, type FlowNode, type FootnotesOptions, type MarkdownHeading, type MarkdownPreset, type MarkdownPresetOptions, type NodeWithPosition, YAML_PROP_PREFIX, createCodeFenceComponentPlugin, createCustomSyntaxRemarkPlugin, createMarkdownPreset, extractHeadings, rehypeFootnotesHeading, remarkSuperSub, resolveCustomSyntaxComponentNames };
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,14 @@ function resolveFootnotesHeadingDepth(depths) {
|
|
|
8
8
|
// src/preset.ts
|
|
9
9
|
import remarkGfm2 from "remark-gfm";
|
|
10
10
|
|
|
11
|
+
// src/module-interop.ts
|
|
12
|
+
function resolveModuleDefault(value) {
|
|
13
|
+
if (value && typeof value === "object" && "default" in value) {
|
|
14
|
+
return value.default;
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
// src/rehype/code-fence-components.ts
|
|
12
20
|
import { visit } from "unist-util-visit";
|
|
13
21
|
var DEFAULT_CODE_FENCE_COMPONENT_MAPPINGS = {
|
|
@@ -163,6 +171,8 @@ import matter from "gray-matter";
|
|
|
163
171
|
import remarkGfm from "remark-gfm";
|
|
164
172
|
import remarkParse from "remark-parse";
|
|
165
173
|
import { unified } from "unified";
|
|
174
|
+
var remarkGfmPlugin = resolveModuleDefault(remarkGfm);
|
|
175
|
+
var remarkParsePlugin = resolveModuleDefault(remarkParse);
|
|
166
176
|
var YAML_PROP_PREFIX = "__YAML__";
|
|
167
177
|
var YAML_BODY_SPLIT_RE = /^---\s*$/;
|
|
168
178
|
var COMPONENT_START_RE = /^::([A-Za-z][A-Za-z0-9_]*)\s*$/;
|
|
@@ -249,7 +259,7 @@ function createInlineTextElement(name, props = {}, text = "") {
|
|
|
249
259
|
return node;
|
|
250
260
|
}
|
|
251
261
|
function parseMarkdownFragment(markdown) {
|
|
252
|
-
return unified().use(
|
|
262
|
+
return unified().use(remarkParsePlugin).use(remarkGfmPlugin).parse(markdown);
|
|
253
263
|
}
|
|
254
264
|
|
|
255
265
|
// src/remark/custom-syntax/handlers/component-block.ts
|
|
@@ -690,6 +700,7 @@ function splitTabSections(value) {
|
|
|
690
700
|
let yamlSource = "";
|
|
691
701
|
let yamlCaptured = false;
|
|
692
702
|
let inInnerFence = null;
|
|
703
|
+
let nestedBlockDepth = 0;
|
|
693
704
|
for (const line of lines) {
|
|
694
705
|
const trimmed = line.trim();
|
|
695
706
|
if (inInnerFence) {
|
|
@@ -709,7 +720,17 @@ function splitTabSections(value) {
|
|
|
709
720
|
currentSection.push(line);
|
|
710
721
|
continue;
|
|
711
722
|
}
|
|
712
|
-
if (
|
|
723
|
+
if (DOUBLE_BLOCK_START_RE.test(line)) {
|
|
724
|
+
nestedBlockDepth += 1;
|
|
725
|
+
currentSection.push(line);
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
if (BLOCK_END_RE.test(line) && nestedBlockDepth > 0) {
|
|
729
|
+
nestedBlockDepth -= 1;
|
|
730
|
+
currentSection.push(line);
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (nestedBlockDepth === 0 && YAML_BODY_SPLIT_RE.test(line)) {
|
|
713
734
|
if (!yamlCaptured) {
|
|
714
735
|
yamlSource = currentSection.join("\n");
|
|
715
736
|
yamlCaptured = true;
|
|
@@ -1054,6 +1075,7 @@ function remarkSuperSub() {
|
|
|
1054
1075
|
}
|
|
1055
1076
|
|
|
1056
1077
|
// src/preset.ts
|
|
1078
|
+
var remarkGfmPlugin2 = resolveModuleDefault(remarkGfm2);
|
|
1057
1079
|
function createMarkdownPreset(options) {
|
|
1058
1080
|
const customSyntaxPlugin = options?.customSyntax ? function customSyntaxPresetPlugin() {
|
|
1059
1081
|
return createCustomSyntaxRemarkPlugin(options.customSyntax);
|
|
@@ -1067,7 +1089,7 @@ function createMarkdownPreset(options) {
|
|
|
1067
1089
|
return {
|
|
1068
1090
|
remarkPlugins: [
|
|
1069
1091
|
customSyntaxPlugin,
|
|
1070
|
-
[
|
|
1092
|
+
[remarkGfmPlugin2, { singleTilde: false }],
|
|
1071
1093
|
remarkSuperSub
|
|
1072
1094
|
],
|
|
1073
1095
|
rehypePlugins: [
|
|
@@ -1083,6 +1105,8 @@ import remarkGfm3 from "remark-gfm";
|
|
|
1083
1105
|
import remarkParse2 from "remark-parse";
|
|
1084
1106
|
import { unified as unified2 } from "unified";
|
|
1085
1107
|
import { visit as visit3 } from "unist-util-visit";
|
|
1108
|
+
var remarkGfmPlugin3 = resolveModuleDefault(remarkGfm3);
|
|
1109
|
+
var remarkParsePlugin2 = resolveModuleDefault(remarkParse2);
|
|
1086
1110
|
function extractText2(children) {
|
|
1087
1111
|
return children.map((child) => {
|
|
1088
1112
|
if ("value" in child && typeof child.value === "string") {
|
|
@@ -1098,7 +1122,7 @@ function extractText2(children) {
|
|
|
1098
1122
|
}).join("");
|
|
1099
1123
|
}
|
|
1100
1124
|
function extractHeadings(markdown, options) {
|
|
1101
|
-
const tree = unified2().use(
|
|
1125
|
+
const tree = unified2().use(remarkParsePlugin2).use(remarkGfmPlugin3).parse(markdown);
|
|
1102
1126
|
const slugger = new GithubSlugger();
|
|
1103
1127
|
const headings = [];
|
|
1104
1128
|
const headingId = options?.headingId ?? FOOTNOTES_HEADING_ID;
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luckyfishes/markdown-core",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Core Markdown/MDX parsing and AST transformation utilities extracted from noname_blog.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
8
9
|
"homepage": "https://github.com/lijiajunply/nonameblog-markdown-core#readme",
|
|
9
10
|
"bugs": {
|
|
@@ -16,7 +17,9 @@
|
|
|
16
17
|
"exports": {
|
|
17
18
|
".": {
|
|
18
19
|
"types": "./dist/index.d.ts",
|
|
19
|
-
"import": "./dist/index.js"
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"require": "./dist/index.cjs",
|
|
22
|
+
"default": "./dist/index.js"
|
|
20
23
|
}
|
|
21
24
|
},
|
|
22
25
|
"files": [
|
|
@@ -27,7 +30,7 @@
|
|
|
27
30
|
"access": "public"
|
|
28
31
|
},
|
|
29
32
|
"scripts": {
|
|
30
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
33
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
31
34
|
"prepare": "npm run build",
|
|
32
35
|
"test": "vitest run"
|
|
33
36
|
},
|