Files
supabase/apps/docs/scripts/codemod/mdx-meta.mjs

117 lines
3.6 KiB
JavaScript

// @ts-check
/**
* Copies MDX files from the `pages` directory to the `content` directory,
* replacing frontmatter in `meta` with YAML frontmatter.
*
* Also deletes import and export statements.
*/
let SUB_DIR = 'self-hosting'
import { parse } from 'acorn'
import { fromMarkdown } from 'mdast-util-from-markdown'
import { mdxFromMarkdown } from 'mdast-util-mdx'
import { mdxjs } from 'micromark-extension-mdxjs'
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises'
import { dirname, extname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = dirname(fileURLToPath(import.meta.url))
const ROOT_DIR = join(__dirname, '../..')
let PAGES_DIR = join(ROOT_DIR, 'pages/guides')
let CONTENT_DIR = join(ROOT_DIR, 'content/guides')
if (SUB_DIR) {
PAGES_DIR = join(PAGES_DIR, SUB_DIR)
CONTENT_DIR = join(CONTENT_DIR, SUB_DIR)
}
function convertToYaml(properties) {
let result = '---\n'
for (const property of properties) {
const key = property.key.name
const value = property.value.value
result += `${key}: "${value}"\n`
}
result += '---\n\n'
return result
}
async function main() {
try {
const origDirContents = await readdir(PAGES_DIR, { recursive: true })
const origMdxFiles = origDirContents.filter((filename) => extname(filename) === '.mdx')
await Promise.all(
origMdxFiles.map(async (filename) => {
const content = await readFile(join(PAGES_DIR, filename), 'utf-8')
const mdxTree = fromMarkdown(content, {
extensions: [mdxjs()],
mdastExtensions: [mdxFromMarkdown()],
})
const meta = mdxTree.children.find(
(node) => node.type === 'mdxjsEsm' && node.value.trim().startsWith('export const meta')
)
let yamlString = ''
if (meta) {
// @ts-ignore
const parsedMeta = parse(meta.value, { ecmaVersion: 2020, sourceType: 'module' })
yamlString = convertToYaml(
// @ts-ignore
parsedMeta.body[0].declaration.declarations[0].init.properties
)
}
const importStatements = mdxTree.children.filter(
(node) => node.type === 'mdxjsEsm' && node.value.trim().match(/^import \w+ from/)
)
const exportStatements = mdxTree.children.filter(
(node) =>
node.type === 'mdxjsEsm' &&
(node.value.trim().match(/^export const (?!meta)/) ||
node.value.trim().startsWith('export default'))
)
const positions = [meta, ...importStatements, ...exportStatements]
// @ts-ignore
.map(({ position }) => [position.start.line, position.end.line])
// splicing them out in reverse order means we don't have to worry about line numbers shifting
.sort((a, b) => b[0] - a[0])
let index = 0
while (index < positions.length - 1) {
const overlapsNext = positions[index][0] <= positions[index + 1][1]
if (overlapsNext) {
positions[index][0] = positions[index + 1][0]
positions.splice(index + 1, 1)
} else {
index++
}
}
const lines = content.split('\n')
for (const position of positions) {
lines.splice(position[0] - 1, position[1] - position[0] + 1)
}
const splicedLines = lines.join('\n')
const splicedWithFrontmatter = yamlString + splicedLines
const destinationPath = join(CONTENT_DIR, filename)
await mkdir(dirname(destinationPath), { recursive: true })
writeFile(destinationPath, splicedWithFrontmatter)
})
)
} catch (err) {
console.error(err)
}
}
main()