62 lines
1.6 KiB
TypeScript
62 lines
1.6 KiB
TypeScript
import { readdirSync, statSync, readFileSync } from "node:fs"
|
|
import { join } from "node:path"
|
|
|
|
export type TemplateVariable = {
|
|
path: string
|
|
type: string
|
|
}
|
|
|
|
const IF_RE = /<@(?:if|elseif)\((.+?)\)>/g
|
|
const VAR_RE = /<@var\(context\.(.+?)(?::(\w+))?\)>/g
|
|
const EQ_RE = /^eq\(context\.(.+?),\s*"(.*)"\)$/
|
|
const PATH_RE = /^context\.(.+)$/
|
|
|
|
function extractCondition(expr: string, vars: TemplateVariable[]) {
|
|
const eqMatch = expr.match(EQ_RE)
|
|
if (eqMatch) {
|
|
vars.push({ path: eqMatch[1]!, type: "string" })
|
|
return
|
|
}
|
|
const pathMatch = expr.match(PATH_RE)
|
|
if (pathMatch) {
|
|
vars.push({ path: pathMatch[1]!, type: "boolean" })
|
|
}
|
|
}
|
|
|
|
function extractFromString(text: string, vars: TemplateVariable[]) {
|
|
for (const match of text.matchAll(IF_RE)) {
|
|
extractCondition(match[1]!, vars)
|
|
}
|
|
for (const match of text.matchAll(VAR_RE)) {
|
|
vars.push({ path: match[1]!, type: match[2] ?? "string" })
|
|
}
|
|
}
|
|
|
|
function walkDir(dirPath: string, vars: TemplateVariable[]) {
|
|
const entries = readdirSync(dirPath).sort()
|
|
for (const entry of entries) {
|
|
const fullPath = join(dirPath, entry)
|
|
extractFromString(entry, vars)
|
|
|
|
const stat = statSync(fullPath)
|
|
if (stat.isDirectory()) {
|
|
walkDir(fullPath, vars)
|
|
} else if (stat.isFile()) {
|
|
const content = readFileSync(fullPath, "utf-8")
|
|
extractFromString(content, vars)
|
|
}
|
|
}
|
|
}
|
|
|
|
export function parse(dirPath: string): TemplateVariable[] {
|
|
const vars: TemplateVariable[] = []
|
|
walkDir(dirPath, vars)
|
|
const seen = new Set<string>()
|
|
return vars.filter(v => {
|
|
const key = `${v.path}:${v.type}`
|
|
if (seen.has(key)) return false
|
|
seen.add(key)
|
|
return true
|
|
})
|
|
}
|