-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
105 lines (89 loc) · 2.77 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { Root, RootContent, Heading, Text } from "mdast";
import remarkStringify from "remark-stringify";
import { validate } from "schema-utils";
import { LoaderContext } from "webpack";
import remarkParse from "remark-parse";
import { unified } from "unified";
const debug = await import("debug").then((d) => d.default("rc:md-loader"));
interface LoaderProperties {}
const schema = {
type: "object" as "object",
properties: {}
};
export default function (
this: LoaderContext<LoaderProperties>,
source: string
): string {
// Get options from webpack loader & validate
const options = this.getOptions();
validate(schema, options, {
name: "md-loader",
baseDataPath: "options"
});
const { resourceFragment, resourcePath, mode } = this;
const parser = unified().use(remarkParse);
const ast = parser().parse(source);
let result = { ast, fragment: source };
if (resourceFragment.trim().length > 0) {
const frag = resourceFragment.trim();
let rootElm: RootContent | Root = ast;
let searchStack: (RootContent | Root)[] = [];
console.assert(rootElm.type == "root");
searchStack.push(rootElm);
let nodesExamined = 0;
for (;;) {
const c = searchStack.shift();
if (c === undefined) {
debug(`FRAG SEARCH: examined ${nodesExamined}; did not find.`);
return "export default undefined";
}
nodesExamined += 1;
if (
c.type === "heading" &&
c.children.length == 1 &&
c.children[0]!.type === "text"
) {
const hding = c.children.at(0)!;
if (
hding.type === "text" &&
"#" +
hding.value
.split(/\s+/)
.map((w) => w.toLowerCase())
.join("-") ===
frag
) {
const sectionNodes = [c as RootContent];
while (searchStack.length > 0) {
const stackNode = searchStack.shift();
nodesExamined++;
if (
stackNode === undefined ||
(stackNode.type === "heading" && stackNode.depth <= c.depth)
)
break;
sectionNodes.push(stackNode as any);
}
const strFrag = unified()
.use(remarkStringify)
.stringify({ type: "root", children: sectionNodes });
result = {
ast: { type: "root", children: sectionNodes },
fragment: strFrag
};
debug(
`FRAG SEARCH: examined ${nodesExamined}: found fragment: ${strFrag.substring(
0,
32
)}`
);
break;
}
}
if (Array.isArray((c as any).children)) {
searchStack.push(...(c as any).children);
}
}
}
return `export default ${JSON.stringify(result)};`;
}