-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathMarkdownDictPlugin.ts
More file actions
76 lines (55 loc) · 2.12 KB
/
MarkdownDictPlugin.ts
File metadata and controls
76 lines (55 loc) · 2.12 KB
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
import fs from 'node:fs/promises';
import path from 'node:path';
import matter from 'gray-matter';
import type { Compiler, WebpackPluginInstance } from 'webpack';
import VirtualModulesPlugin from 'webpack-virtual-modules';
interface MarkdownDictPluginOptions {
dir: string;
modulePath?: string; // e.g. 'node_modules/virtual/markdown-dict.js'
}
export class MarkdownDictPlugin implements WebpackPluginInstance {
constructor(private readonly options: MarkdownDictPluginOptions) {}
apply(compiler: Compiler) {
const virtualPath =
this.options.modulePath ?? 'node_modules/virtual/markdown-dict.js';
const virtualModules = new VirtualModulesPlugin();
virtualModules.apply(compiler);
compiler.hooks.beforeCompile.tapPromise('MarkdownDictPlugin', async () => {
const files = await fs.readdir(this.options.dir);
const imports = new Set(['import { createElement } from "react";']);
const code: string[] = ['export default ['];
for (const file of files) {
if (!file.endsWith('.md')) {
continue;
}
const fullPath = path.join(this.options.dir, file);
const { data } = matter(await fs.readFile(fullPath, 'utf-8'));
const match = /^(\w+)\.(\w\w)\.md$/.exec(file);
if (!match) {
throw new Error('invalid filename ' + file);
}
if ('icon' in data) {
imports.add(
`import { ${data.icon} } from 'react-icons/${data.icon.slice(0, 2).toLowerCase()}';`,
);
}
const fields: string[] = [`key: "${match[1]}"`, `lang: "${match[2]}"`];
if ('title' in data) {
fields.push(`title: ${JSON.stringify(data.title)}`);
}
if ('listed' in data) {
fields.push(`listed: ${data.listed}`);
}
if ('icon' in data) {
fields.push(`icon: createElement(${data.icon})`);
}
if ('order' in data) {
fields.push(`order: ${data.order}`);
}
code.push(`{ ${fields.join(', ')} },`);
}
code.push('];');
virtualModules.writeModule(virtualPath, [...imports, ...code].join('\n'));
});
}
}