-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathconvertToMDX.ts
More file actions
94 lines (77 loc) · 2.82 KB
/
convertToMDX.ts
File metadata and controls
94 lines (77 loc) · 2.82 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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { readFile, writeFile } from 'fs/promises'
import { glob } from 'glob'
import path from 'path'
import { fileExists } from './fileExists.js'
function handleTsExamples(content: string): string {
//regex link: https://regexr.com/8f0bu
const ExampleBlockRegex = /```[tj]s file=['"]\.?\/?(\w*)\.(\w*)['"]\s*\n```/g
//the first capture group is the example file name without the extension or path, the second is the extension
const replacementString = `\nimport $1 from "./$1.$2?raw"\n\n<LiveExample src={$1} />`
return content.replace(ExampleBlockRegex, replacementString)
}
async function handleHTMLExamples(
content: string,
fileDir: string,
): Promise<string> {
const htmlCodeFenceRegex = /```html\n([\s\S]*?)\n```/g
const matches = Array.from(content.matchAll(htmlCodeFenceRegex))
const replacements = await Promise.all(
matches.map(async (match, index) => {
const htmlContent = match[1]
const exampleName = `Example${index + 1}`
const htmlFilePath = path.join(fileDir, `${exampleName}.html`)
await writeFile(htmlFilePath, htmlContent)
return {
original: match[0],
replacement: `\nimport ${exampleName} from './${exampleName}.html?raw'\n\n<LiveExample html={${exampleName}} />`,
}
}),
)
return replacements.reduce(
(result, { original, replacement }) =>
result.replace(original, replacement),
content,
)
}
function removeNoLiveTags(content: string): string {
return content.replace(/```no[lL]ive/g, '```')
}
function removeExistingImports(content: string): string {
// Remove imports that are absolute and not CSS
const importRegex = /^import {?[\w\s,\n]*}? from ['"](?!\.\.?\/)(?!.*\.css['"])[^'"]*['"];?\n/gm
return content.replace(importRegex, '')
}
function convertCommentsToMDX(content: string): string {
return content.replace(
/<!--([\s\S]*?)-->/g,
(_, comment) => `{/*${comment}*/}`,
)
}
async function processFile(file: string): Promise<void> {
const exists = await fileExists(file)
// if the file is already an mdx file or doesn't exist we don't need to do anything
if (file.endsWith('.mdx') || !exists) {
return
}
const fileContent = await readFile(file, 'utf-8')
const fileDir = path.dirname(file)
const transformations = [
removeNoLiveTags,
removeExistingImports,
(content: string) => handleHTMLExamples(content, fileDir),
handleTsExamples,
convertCommentsToMDX,
]
const processedContent = await transformations.reduce(
async (contentPromise, transform) => {
const content = await contentPromise
return transform(content)
},
Promise.resolve(fileContent),
)
await writeFile(file + 'x', processedContent)
}
export async function convertToMDX(globPath: string): Promise<void> {
const files = await glob(globPath)
await Promise.all(files.map(processFile))
}