import { readdirSync, statSync, readFileSync } from "node:fs" import { join } from "node:path" export type TemplateVariable = { path: string type: string } const IF_RE = /<@if\(context\.(.+?)\)>/g const VAR_RE = /<@var\(context\.(.+?)(?::(\w+))?\)>/g function extractFromString(text: string, vars: TemplateVariable[]) { for (const match of text.matchAll(IF_RE)) { vars.push({ path: match[1]!, type: "boolean" }) } 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() return vars.filter(v => { const key = `${v.path}:${v.type}` if (seen.has(key)) return false seen.add(key) return true }) }