@tiveor/scg 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -41
- package/dist/chunk-XKYTW4HW.js +589 -0
- package/dist/chunk-XKYTW4HW.js.map +1 -0
- package/dist/cli.cjs +779 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +173 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +991 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +653 -0
- package/dist/index.d.ts +653 -0
- package/dist/index.js +373 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -7
- package/templates/express-route/controller.ejs +35 -0
- package/templates/express-route/routes.ejs +10 -0
- package/templates/express-route/scaffold.json +13 -0
- package/templates/express-route/service.ejs +16 -0
- package/templates/github-action/scaffold.json +12 -0
- package/templates/github-action/workflow.ejs +33 -0
- package/templates/react-component/component.ejs +25 -0
- package/templates/react-component/index.ejs +2 -0
- package/templates/react-component/scaffold.json +15 -0
- package/templates/react-component/styles.ejs +4 -0
- package/templates/react-component/test.ejs +14 -0
- package/templates/vue-component/component.ejs +19 -0
- package/templates/vue-component/scaffold.json +12 -0
- package/templates/vue-component/test.ejs +16 -0
- package/.prettierignore +0 -1
- package/.prettierrc +0 -10
- package/.travis.yml +0 -9
- package/example/ejs/conditional.ejs +0 -9
- package/example/ejs/hello.ejs +0 -8
- package/example/handlebars/conditional.handlebars +0 -9
- package/example/handlebars/hello.handlebars +0 -6
- package/example/index.js +0 -180
- package/example/pug/conditional.pug +0 -4
- package/example/pug/hello.pug +0 -3
- package/index.js +0 -15
- package/src/command_helper.js +0 -41
- package/src/ejs_helper.js +0 -30
- package/src/file_helper.js +0 -140
- package/src/handlebars_helper.js +0 -32
- package/src/param_helper.js +0 -25
- package/src/pug_helper.js +0 -28
- package/src/string_helper.js +0 -18
- package/src/template_builder.js +0 -38
- package/src/template_handlers.js +0 -7
- package/test/test.js +0 -394
package/dist/cli.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/handlebars_helper.ts","../src/file_helper.ts","../src/string_helper.ts","../src/ejs_helper.ts","../src/pug_helper.ts","../src/template_handlers.ts","../src/template_builder.ts","../src/scaffold.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport fs from 'fs';\nimport path from 'path';\nimport { TemplateBuilder } from './template_builder.js';\nimport { Scaffold, type ScaffoldOptions } from './scaffold.js';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nfunction parseFlags(args: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (const arg of args) {\n const match = arg.match(/^--([a-zA-Z0-9_-]+)=(.*)$/);\n if (match) {\n flags[match[1]] = match[2].replace(/^['\"]/, '').replace(/['\"]$/, '');\n }\n }\n return flags;\n}\n\nfunction printHelp(): void {\n console.log(`\nSCG - Simple Code Generator\n\nUsage:\n scg <command> [options]\n\nCommands:\n init Initialize a scaffold manifest (scaffold.json)\n generate Generate files from a scaffold manifest\n render <template> Render a single template file\n\nOptions:\n --manifest=<path> Path to scaffold manifest (default: scaffold.json)\n --vars=<key=val,...> Comma-separated variables (e.g. name=Button,style=module)\n --data=<json> JSON data for template rendering\n --engine=<name> Template engine (EJS, HANDLEBARS, PUG)\n --output=<path> Output file path (for render command)\n --dry-run Preview without writing files\n\nExamples:\n scg init\n scg generate --manifest=scaffold.json --vars=name=Button\n scg render template.ejs --data='{\"name\": \"World\"}'\n scg render template.ejs --data='{\"name\": \"World\"}' --output=output.html\n`);\n}\n\nfunction parseVars(varsStr: string): Record<string, string> {\n const vars: Record<string, string> = {};\n for (const pair of varsStr.split(',')) {\n const [key, ...rest] = pair.split('=');\n if (key && rest.length > 0) {\n vars[key.trim()] = rest.join('=').trim();\n }\n }\n return vars;\n}\n\nasync function cmdInit(): Promise<void> {\n const manifest: ScaffoldOptions = {\n engine: 'EJS',\n templateDir: './templates',\n outputDir: './generated/{{name}}',\n variables: { name: 'MyComponent' },\n structure: [\n { template: 'component.ejs', output: '{{name}}.tsx' },\n { template: 'test.ejs', output: '{{name}}.test.tsx' },\n { template: 'index.ejs', output: 'index.ts' }\n ]\n };\n const filePath = 'scaffold.json';\n fs.writeFileSync(filePath, JSON.stringify(manifest, null, 2), 'utf8');\n console.log(`Created ${filePath}`);\n console.log('Edit the manifest and run: scg generate');\n}\n\nasync function cmdGenerate(): Promise<void> {\n const flags = parseFlags(args);\n const manifestPath = flags['manifest'] ?? 'scaffold.json';\n const dryRun = args.includes('--dry-run');\n\n if (!fs.existsSync(manifestPath)) {\n console.error(`Manifest not found: ${manifestPath}`);\n console.error('Run \"scg init\" to create one.');\n process.exit(1);\n }\n\n const manifest = JSON.parse(\n fs.readFileSync(manifestPath, 'utf8')\n ) as ScaffoldOptions;\n\n if (flags['vars']) {\n Object.assign(manifest.variables, parseVars(flags['vars']));\n }\n\n manifest.dryRun = dryRun;\n\n const result = await Scaffold.from(manifest);\n\n if (dryRun) {\n console.log('Dry run - files that would be created:');\n } else {\n console.log('Generated files:');\n }\n\n for (const file of result.files) {\n console.log(` ${file}`);\n }\n}\n\nasync function cmdRender(): Promise<void> {\n const templatePath = args[1];\n if (!templatePath) {\n console.error('Usage: scg render <template> [--data=<json>] [--engine=<name>] [--output=<path>]');\n process.exit(1);\n }\n\n const flags = parseFlags(args);\n const engine = flags['engine'] ?? extToEngine(templatePath);\n const dataStr = flags['data'] ?? '{}';\n const outputPath = flags['output'];\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(dataStr);\n } catch {\n console.error('Invalid JSON in --data flag');\n process.exit(1);\n }\n\n const builder = new TemplateBuilder(engine);\n const result = await builder.renderFile(templatePath, data, {});\n\n if (outputPath) {\n const dir = path.dirname(outputPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(outputPath, result, 'utf8');\n console.log(`Written to ${outputPath}`);\n } else {\n console.log(result);\n }\n}\n\nfunction extToEngine(filePath: string): string {\n const ext = path.extname(filePath).toLowerCase();\n switch (ext) {\n case '.ejs':\n return 'EJS';\n case '.hbs':\n case '.handlebars':\n return 'HANDLEBARS';\n case '.pug':\n case '.jade':\n return 'PUG';\n default:\n return 'HANDLEBARS';\n }\n}\n\nasync function main(): Promise<void> {\n switch (command) {\n case 'init':\n await cmdInit();\n break;\n case 'generate':\n await cmdGenerate();\n break;\n case 'render':\n await cmdRender();\n break;\n case '--help':\n case '-h':\n case undefined:\n printHelp();\n break;\n default:\n console.error(`Unknown command: ${command}`);\n printHelp();\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(err.message);\n process.exit(1);\n});\n","import Handlebars from 'handlebars';\nimport { FileHelper } from './file_helper.js';\n\nexport class HandlebarsHelper {\n static render(\n source: string,\n data: Record<string, unknown>,\n options?: CompileOptions\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const template = Handlebars.compile(source, options);\n const res = template(data);\n resolve(res);\n } catch (error) {\n reject(error);\n }\n });\n }\n\n static renderFile(\n fileName: string,\n data: Record<string, unknown>,\n options?: CompileOptions\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const source = FileHelper.readFileToString(fileName);\n const template = Handlebars.compile(source, options);\n const res = template(data);\n resolve(res);\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport readline from 'readline';\nimport { StringHelper } from './string_helper.js';\n\n/** Defines a single token replacement with optional template-based dynamic replacement. */\nexport interface Replacement {\n /** The token string to search for in the template (e.g., `'{{name}}'`). */\n token: string;\n /** The static value to replace the token with. */\n value?: string;\n /** Path to a sub-template for dynamic replacement. */\n template?: string;\n /** Variables for dynamic replacement keyed by identifier. */\n variables?: Record<string, Replacement[]>;\n}\n\n/** Options for creating a file from a template with variable replacements. */\nexport interface CreateFileOptions {\n /** Path to the template file. */\n template: string;\n /** Path for the output file. */\n newFile: string;\n /** Array of token replacements to apply. */\n variables: Replacement[];\n}\n\n/** Options for creating a string from a template with variable replacements. */\nexport interface CreateStringOptions {\n /** Path to the template file. */\n template: string;\n /** Array of token replacements to apply. */\n variables: Replacement[];\n}\n\n/**\n * Utility class for file system operations, both synchronous and asynchronous.\n *\n * Provides methods for reading, writing, creating, and removing files and directories,\n * as well as template-based file generation with variable replacement.\n *\n * @example\n * ```typescript\n * // Sync\n * const content = FileHelper.readFileToString('config.txt');\n * const config = FileHelper.convertJsonFileToObject('config.json');\n *\n * // Async\n * const data = await FileHelper.readFileAsync('config.txt');\n * await FileHelper.writeFileAsync('output.txt', 'content');\n * ```\n */\nexport class FileHelper {\n // --- Sync methods ---\n\n /**\n * Reads a file synchronously and returns its content as a UTF-8 string.\n *\n * @param fileName - Path to the file to read\n * @returns The file content as a string\n */\n static readFileToString(fileName: string): string {\n return fs.readFileSync(fileName, 'utf8');\n }\n\n /**\n * Reads a JSON file synchronously and parses it into an object.\n *\n * @typeParam T - The expected type of the parsed object\n * @param fileName - Path to the JSON file\n * @returns The parsed object\n */\n static convertJsonFileToObject<T = unknown>(fileName: string): T {\n const rawString = FileHelper.readFileToString(fileName);\n return JSON.parse(rawString) as T;\n }\n\n /**\n * Creates a directory (and any parent directories) if it doesn't exist.\n *\n * @param folderName - Path to the directory to create\n */\n static createFolder(folderName: string): void {\n const resolved = path.resolve(folderName);\n if (!fs.existsSync(resolved)) {\n fs.mkdirSync(resolved, { recursive: true });\n }\n }\n\n /**\n * Removes a directory and all its contents recursively.\n *\n * @param folderName - Path to the directory to remove\n */\n static removeFolder(folderName: string): void {\n const resolved = path.resolve(folderName);\n if (fs.existsSync(resolved)) {\n fs.rmSync(resolved, { recursive: true, force: true });\n }\n }\n\n /**\n * Removes a file if it exists.\n *\n * @param filename - Path to the file to remove\n */\n static removeFile(filename: string): void {\n const resolved = path.resolve(filename);\n if (fs.existsSync(resolved)) {\n fs.rmSync(resolved, { force: true });\n }\n }\n\n // --- Async methods ---\n\n /**\n * Reads a file asynchronously and returns its content as a UTF-8 string.\n *\n * @param fileName - Path to the file to read\n * @returns A promise resolving to the file content\n */\n static async readFileAsync(fileName: string): Promise<string> {\n return fs.promises.readFile(fileName, 'utf8');\n }\n\n /**\n * Reads a JSON file asynchronously and parses it into an object.\n *\n * @typeParam T - The expected type of the parsed object\n * @param fileName - Path to the JSON file\n * @returns A promise resolving to the parsed object\n */\n static async readJsonFileAsync<T = unknown>(fileName: string): Promise<T> {\n const raw = await fs.promises.readFile(fileName, 'utf8');\n return JSON.parse(raw) as T;\n }\n\n /**\n * Writes content to a file asynchronously, creating parent directories as needed.\n *\n * @param fileName - Path to the file to write\n * @param content - The string content to write\n */\n static async writeFileAsync(\n fileName: string,\n content: string\n ): Promise<void> {\n const dir = path.dirname(fileName);\n await fs.promises.mkdir(dir, { recursive: true });\n await fs.promises.writeFile(fileName, content, 'utf8');\n }\n\n /**\n * Creates a directory asynchronously (with recursive parent creation).\n *\n * @param folderName - Path to the directory to create\n */\n static async createFolderAsync(folderName: string): Promise<void> {\n const resolved = path.resolve(folderName);\n await fs.promises.mkdir(resolved, { recursive: true });\n }\n\n /**\n * Removes a directory and its contents recursively (async).\n *\n * @param folderName - Path to the directory to remove\n */\n static async removeFolderAsync(folderName: string): Promise<void> {\n const resolved = path.resolve(folderName);\n await fs.promises.rm(resolved, { recursive: true, force: true });\n }\n\n /**\n * Removes a file asynchronously.\n *\n * @param filename - Path to the file to remove\n */\n static async removeFileAsync(filename: string): Promise<void> {\n const resolved = path.resolve(filename);\n await fs.promises.rm(resolved, { force: true });\n }\n\n /**\n * Checks whether a file or directory exists asynchronously.\n *\n * @param filePath - Path to check\n * @returns `true` if the path exists, `false` otherwise\n */\n static async existsAsync(filePath: string): Promise<boolean> {\n try {\n await fs.promises.access(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n // --- Template processing methods ---\n\n /**\n * Performs a simple token replacement on a single line.\n *\n * @param line - The source line\n * @param replacement - The replacement definition (uses `token` and `value`)\n * @returns The line with the token replaced\n */\n static simpleReplace(line: string, replacement: Replacement): string {\n return StringHelper.replace(line, replacement.token, replacement.value!);\n }\n\n /**\n * Performs dynamic replacement using a sub-template and variables.\n * Reads the sub-template line by line and applies all variable replacements.\n *\n * @param replacement - The replacement definition with `template` and `variables`\n * @returns A promise resolving to the processed string\n */\n static async dynamicReplace(replacement: Replacement): Promise<string> {\n let res = '';\n for (const v in replacement.variables) {\n const properties = replacement.variables[v];\n await FileHelper.readLineByLine(\n replacement.template!,\n (line: string) => {\n let newLine = line;\n for (const x in properties) {\n const property = properties[x];\n if (line.indexOf(property.token) >= 0) {\n if (property.value) {\n newLine = FileHelper.simpleReplace(newLine, property);\n }\n }\n }\n res += newLine;\n }\n );\n }\n return res;\n }\n\n /**\n * Creates a new file from a template file, applying variable replacements line by line.\n * The special token `@date` is automatically replaced with the current UTC date.\n *\n * @param options - The template path, output path, and variables to apply\n *\n * @example\n * ```typescript\n * await FileHelper.createFileFromFile({\n * template: 'templates/component.txt',\n * newFile: 'output/Button.tsx',\n * variables: [\n * { token: '{{name}}', value: 'Button' },\n * { token: '{{style}}', value: 'primary' }\n * ]\n * });\n * ```\n */\n static async createFileFromFile({\n template,\n newFile,\n variables\n }: CreateFileOptions): Promise<void> {\n const writer = FileHelper.writer(newFile);\n\n await FileHelper.readLineByLine(template, async (line: string) => {\n let newLine = StringHelper.replace(\n line,\n '@date',\n new Date().toUTCString()\n );\n\n for (const v in variables) {\n const replacement = variables[v];\n\n if (newLine.indexOf(replacement.token) > 0) {\n if (replacement.template) {\n newLine = await FileHelper.dynamicReplace(replacement);\n break;\n } else if (replacement.value) {\n newLine = FileHelper.simpleReplace(newLine, replacement);\n }\n }\n }\n\n await FileHelper.writeLineByLine(writer, newLine);\n });\n writer.end();\n }\n\n /**\n * Creates a string from a template file, applying variable replacements line by line.\n * The special token `@date` is automatically replaced with the current UTC date.\n *\n * @param options - The template path and variables to apply\n * @returns A promise resolving to the processed string\n */\n static async createStringFromFile({\n template,\n variables\n }: CreateStringOptions): Promise<string> {\n let res = '';\n\n await FileHelper.readLineByLine(template, async (line: string) => {\n let newLine = StringHelper.replace(\n line,\n '@date',\n new Date().toUTCString()\n );\n\n for (const v in variables) {\n const replacement = variables[v];\n\n if (newLine.indexOf(replacement.token) > 0) {\n if (replacement.template) {\n newLine = await FileHelper.dynamicReplace(replacement);\n break;\n } else if (replacement.value) {\n newLine = FileHelper.simpleReplace(newLine, replacement);\n }\n }\n }\n res += newLine + '\\n';\n });\n return res;\n }\n\n /**\n * Reads a file line by line and invokes a callback for each line.\n *\n * @param fileName - Path to the file to read\n * @param callback - Function called for each line\n */\n static async readLineByLine(\n fileName: string,\n callback: (line: string) => void | Promise<void>\n ): Promise<void> {\n const fileStream = fs.createReadStream(fileName);\n\n const rl = readline.createInterface({\n input: fileStream,\n crlfDelay: Infinity\n });\n\n for await (const line of rl) {\n await callback(line);\n }\n }\n\n /**\n * Creates a writable stream for appending to a file.\n *\n * @param filename - Path to the file\n * @returns A writable stream in append mode\n */\n static writer(filename: string): fs.WriteStream {\n return fs.createWriteStream(filename, {\n flags: 'a'\n });\n }\n\n /**\n * Writes a single line to a writable stream with CRLF line ending.\n *\n * @param writer - The writable stream\n * @param newLine - The line content to write\n */\n static async writeLineByLine(\n writer: fs.WriteStream,\n newLine: string\n ): Promise<void> {\n writer.write(`${newLine}\\r\\n`);\n }\n}\n","/**\n * Utility class for common string manipulation operations.\n *\n * @example\n * ```typescript\n * StringHelper.replace('Hello {{name}}!', '{{name}}', 'World');\n * // => \"Hello World!\"\n *\n * StringHelper.capitalize('hello');\n * // => \"Hello\"\n * ```\n */\nexport class StringHelper {\n /**\n * Escapes all regex special characters in a string.\n *\n * @param string - The string to escape\n * @returns The escaped string safe for use in `new RegExp()`\n *\n * @example\n * ```typescript\n * StringHelper.escapeRegex('$100.00 (test)');\n * // => \"\\\\$100\\\\.00 \\\\(test\\\\)\"\n * ```\n */\n static escapeRegex(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n\n /**\n * Replaces all occurrences of a token in a string. The token is treated\n * as a literal string (regex special characters are escaped automatically).\n *\n * @param line - The source string to search in. Returns `''` if not a string.\n * @param token - The token to search for. Returns `line` unchanged if not a string.\n * @param value - The replacement value\n * @returns The string with all occurrences replaced\n *\n * @example\n * ```typescript\n * StringHelper.replace('Price: $10.00', '$10.00', '$20.00');\n * // => \"Price: $20.00\"\n * ```\n */\n static replace(line: unknown, token: unknown, value: string): string {\n if (typeof line !== 'string') return '';\n if (typeof token !== 'string') return line;\n return line.replace(\n new RegExp(StringHelper.escapeRegex(token), 'g'),\n value\n );\n }\n\n /**\n * Capitalizes the first character of a string.\n *\n * @param s - The string to capitalize. Returns `''` if not a string.\n * @returns The string with the first character uppercased\n *\n * @example\n * ```typescript\n * StringHelper.capitalize('hello world');\n * // => \"Hello world\"\n * ```\n */\n static capitalize(s: unknown): string {\n if (typeof s !== 'string') return '';\n return s.charAt(0).toUpperCase() + s.slice(1);\n }\n}\n","import ejs from 'ejs';\n\nexport class EjsHelper {\n static render(\n source: string,\n data: Record<string, unknown>,\n options?: ejs.Options\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const template = ejs.render(source, data, options);\n resolve(template);\n } catch (error) {\n reject(error);\n }\n });\n }\n\n static renderFile(\n fileName: string,\n data: Record<string, unknown>,\n options?: ejs.Options\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n ejs.renderFile(fileName, data, options ?? {}, (err, str) => {\n if (err) {\n reject(err);\n return;\n }\n resolve(str!);\n });\n });\n }\n}\n","import pug from 'pug';\n\nexport class PugHelper {\n static render(\n source: string,\n data: Record<string, unknown>,\n options?: pug.Options\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const template = pug.compile(source, options);\n resolve(template(data));\n } catch (error) {\n reject(error);\n }\n });\n }\n\n static renderFile(\n fileName: string,\n data: Record<string, unknown>,\n options?: pug.Options\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const template = pug.compileFile(fileName, options);\n resolve(template(data));\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n","/**\n * Enum-like object defining the built-in template engine identifiers.\n *\n * @example\n * ```typescript\n * const builder = new TemplateBuilder(TEMPLATE_HANDLERS.EJS);\n * ```\n */\nexport const TEMPLATE_HANDLERS = {\n HANDLEBARS: 'HANDLEBARS',\n EJS: 'EJS',\n PUG: 'PUG'\n} as const;\n\n/**\n * Union type of all valid built-in template handler names.\n */\nexport type TemplateHandler =\n (typeof TEMPLATE_HANDLERS)[keyof typeof TEMPLATE_HANDLERS];\n","import { HandlebarsHelper } from './handlebars_helper.js';\nimport { EjsHelper } from './ejs_helper.js';\nimport { PugHelper } from './pug_helper.js';\nimport { TEMPLATE_HANDLERS, type TemplateHandler } from './template_handlers.js';\n\n/**\n * Interface that custom template engines must implement to be registered\n * with {@link TemplateBuilder.registerEngine}.\n */\nexport interface TemplateEngine {\n /** Renders a template from a source string with the given data. */\n render: (\n source: string,\n data: Record<string, unknown>,\n options?: Record<string, unknown>\n ) => Promise<string>;\n /** Renders a template from a file path with the given data. */\n renderFile: (\n fileName: string,\n data: Record<string, unknown>,\n options?: Record<string, unknown>\n ) => Promise<string>;\n}\n\nconst builtInEngines: Record<string, TemplateEngine> = {\n [TEMPLATE_HANDLERS.HANDLEBARS]: HandlebarsHelper,\n [TEMPLATE_HANDLERS.EJS]: EjsHelper,\n [TEMPLATE_HANDLERS.PUG]: PugHelper\n};\n\nconst customEngines: Record<string, TemplateEngine> = {};\n\n/**\n * Unified interface to render templates with EJS, Handlebars, Pug, or any custom engine.\n *\n * Supports a plugin system for registering custom template engines at runtime.\n *\n * @example\n * ```typescript\n * // Built-in engines\n * const builder = new TemplateBuilder(TEMPLATE_HANDLERS.EJS);\n * const html = await builder.render('Hello <%= name %>', { name: 'World' });\n *\n * // Custom engine\n * TemplateBuilder.registerEngine('nunjucks', {\n * render: async (source, data) => nunjucks.renderString(source, data),\n * renderFile: async (file, data) => nunjucks.render(file, data),\n * });\n * const nj = new TemplateBuilder('nunjucks');\n * ```\n */\nexport class TemplateBuilder {\n private templateHandler: string;\n\n /**\n * Creates a new TemplateBuilder for the specified engine.\n *\n * @param templateHandler - The engine name (e.g., `'EJS'`, `'HANDLEBARS'`, `'PUG'`, or a custom name)\n */\n constructor(templateHandler: TemplateHandler | string) {\n this.templateHandler = templateHandler;\n }\n\n /**\n * Registers a custom template engine that can be used with `new TemplateBuilder(name)`.\n *\n * @param name - A unique name for the engine\n * @param engine - An object implementing the {@link TemplateEngine} interface\n * @throws If `name` is empty or `engine` doesn't implement `render()` and `renderFile()`\n *\n * @example\n * ```typescript\n * TemplateBuilder.registerEngine('nunjucks', {\n * render: async (source, data) => nunjucks.renderString(source, data),\n * renderFile: async (file, data) => nunjucks.render(file, data),\n * });\n * ```\n */\n static registerEngine(name: string, engine: TemplateEngine): void {\n if (!name || typeof name !== 'string') {\n throw new Error('engine name must be a non-empty string');\n }\n if (!engine || typeof engine.render !== 'function' || typeof engine.renderFile !== 'function') {\n throw new Error('engine must implement render() and renderFile() methods');\n }\n customEngines[name] = engine;\n }\n\n /**\n * Retrieves a registered engine by name (custom engines take precedence over built-in).\n *\n * @param name - The engine name to look up\n * @returns The engine implementation, or `undefined` if not found\n */\n static getEngine(name: string): TemplateEngine | undefined {\n return customEngines[name] ?? builtInEngines[name];\n }\n\n /**\n * Returns an array of all registered engine names (built-in + custom).\n *\n * @returns Array of engine name strings\n *\n * @example\n * ```typescript\n * TemplateBuilder.getRegisteredEngines();\n * // => ['HANDLEBARS', 'EJS', 'PUG']\n * ```\n */\n static getRegisteredEngines(): string[] {\n return [\n ...Object.keys(builtInEngines),\n ...Object.keys(customEngines)\n ];\n }\n\n private resolveEngine(): TemplateEngine {\n const engine =\n customEngines[this.templateHandler] ??\n builtInEngines[this.templateHandler] ??\n builtInEngines[TEMPLATE_HANDLERS.HANDLEBARS];\n return engine;\n }\n\n /**\n * Renders a template from a source string.\n *\n * @param source - The template source string\n * @param data - Data object to pass to the template\n * @param options - Optional engine-specific options\n * @returns A promise resolving to the rendered string\n */\n render(\n source: string,\n data: Record<string, unknown>,\n options?: Record<string, unknown>\n ): Promise<string> {\n return this.resolveEngine().render(source, data, options);\n }\n\n /**\n * Renders a template from a file path.\n *\n * @param fileName - Path to the template file\n * @param data - Data object to pass to the template\n * @param options - Optional engine-specific options\n * @returns A promise resolving to the rendered string\n */\n renderFile(\n fileName: string,\n data: Record<string, unknown>,\n options?: Record<string, unknown>\n ): Promise<string> {\n return this.resolveEngine().renderFile(fileName, data, options);\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { TemplateBuilder } from './template_builder.js';\nimport { StringHelper } from './string_helper.js';\n\n/** Defines a single file in a scaffold structure. */\nexport interface ScaffoldFile {\n /** Relative path to the template file (within `templateDir`). */\n template: string;\n /** Output filename pattern (supports `{{variable}}` interpolation). */\n output: string;\n}\n\n/** Configuration options for scaffold generation. */\nexport interface ScaffoldOptions {\n /** Template engine to use (e.g., `'EJS'`, `'HANDLEBARS'`, `'PUG'`). */\n engine: string;\n /** Base directory containing the template files. */\n templateDir: string;\n /** Output directory pattern (supports `{{variable}}` interpolation). */\n outputDir: string;\n /** Variables for template rendering and path interpolation. */\n variables: Record<string, string>;\n /** List of files to generate. */\n structure: ScaffoldFile[];\n /** If `true`, returns the file list without writing files. */\n dryRun?: boolean;\n}\n\n/** Result of a scaffold generation operation. */\nexport interface ScaffoldResult {\n /** List of file paths that were created (or would be created in dry-run mode). */\n files: string[];\n /** Whether this was a dry-run execution. */\n dryRun: boolean;\n}\n\n/**\n * Generates directory structures from a manifest configuration.\n *\n * Reads template files, renders them with the specified engine, and writes\n * the output to a directory structure with variable-interpolated paths.\n *\n * @example\n * ```typescript\n * const result = await Scaffold.from({\n * engine: 'EJS',\n * templateDir: './templates/react-component',\n * outputDir: './src/components/{{name}}',\n * variables: { name: 'UserProfile', style: 'module' },\n * structure: [\n * { template: 'component.ejs', output: '{{name}}.tsx' },\n * { template: 'styles.ejs', output: '{{name}}.module.css' },\n * { template: 'test.ejs', output: '{{name}}.test.tsx' },\n * ]\n * });\n *\n * console.log(result.files); // List of created file paths\n * ```\n */\nexport class Scaffold {\n /**\n * Generates files from a scaffold manifest.\n *\n * @param options - The scaffold configuration\n * @returns A promise resolving to a {@link ScaffoldResult} with the list of created files\n */\n static async from(options: ScaffoldOptions): Promise<ScaffoldResult> {\n const {\n engine,\n templateDir,\n outputDir,\n variables,\n structure,\n dryRun = false\n } = options;\n\n const builder = new TemplateBuilder(engine);\n const resolvedOutputDir = resolveVariables(outputDir, variables);\n const createdFiles: string[] = [];\n\n for (const file of structure) {\n const templatePath = path.join(templateDir, file.template);\n const outputFileName = resolveVariables(file.output, variables);\n const outputPath = path.join(resolvedOutputDir, outputFileName);\n\n if (dryRun) {\n createdFiles.push(outputPath);\n continue;\n }\n\n const dir = path.dirname(outputPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n const content = await builder.renderFile(\n templatePath,\n variables as unknown as Record<string, unknown>,\n {}\n );\n fs.writeFileSync(outputPath, content, 'utf8');\n createdFiles.push(outputPath);\n }\n\n return { files: createdFiles, dryRun };\n }\n}\n\n/** @internal Replaces `{{key}}` tokens in a string with variable values. */\nfunction resolveVariables(\n template: string,\n variables: Record<string, string>\n): string {\n let result = template;\n for (const [key, value] of Object.entries(variables)) {\n result = StringHelper.replace(result, `{{${key}}}`, value);\n }\n return result;\n}\n"],"mappings":"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","names":["import_fs","import_path","fs","path","readline","Handlebars","ejs","pug","import_fs","import_path","path","fs","args","fs","path"]}
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
Scaffold,
|
|
4
|
+
TemplateBuilder
|
|
5
|
+
} from "./chunk-XKYTW4HW.js";
|
|
6
|
+
|
|
7
|
+
// src/cli.ts
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import path from "path";
|
|
10
|
+
var args = process.argv.slice(2);
|
|
11
|
+
var command = args[0];
|
|
12
|
+
function parseFlags(args2) {
|
|
13
|
+
const flags = {};
|
|
14
|
+
for (const arg of args2) {
|
|
15
|
+
const match = arg.match(/^--([a-zA-Z0-9_-]+)=(.*)$/);
|
|
16
|
+
if (match) {
|
|
17
|
+
flags[match[1]] = match[2].replace(/^['"]/, "").replace(/['"]$/, "");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return flags;
|
|
21
|
+
}
|
|
22
|
+
function printHelp() {
|
|
23
|
+
console.log(`
|
|
24
|
+
SCG - Simple Code Generator
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
scg <command> [options]
|
|
28
|
+
|
|
29
|
+
Commands:
|
|
30
|
+
init Initialize a scaffold manifest (scaffold.json)
|
|
31
|
+
generate Generate files from a scaffold manifest
|
|
32
|
+
render <template> Render a single template file
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
--manifest=<path> Path to scaffold manifest (default: scaffold.json)
|
|
36
|
+
--vars=<key=val,...> Comma-separated variables (e.g. name=Button,style=module)
|
|
37
|
+
--data=<json> JSON data for template rendering
|
|
38
|
+
--engine=<name> Template engine (EJS, HANDLEBARS, PUG)
|
|
39
|
+
--output=<path> Output file path (for render command)
|
|
40
|
+
--dry-run Preview without writing files
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
scg init
|
|
44
|
+
scg generate --manifest=scaffold.json --vars=name=Button
|
|
45
|
+
scg render template.ejs --data='{"name": "World"}'
|
|
46
|
+
scg render template.ejs --data='{"name": "World"}' --output=output.html
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
function parseVars(varsStr) {
|
|
50
|
+
const vars = {};
|
|
51
|
+
for (const pair of varsStr.split(",")) {
|
|
52
|
+
const [key, ...rest] = pair.split("=");
|
|
53
|
+
if (key && rest.length > 0) {
|
|
54
|
+
vars[key.trim()] = rest.join("=").trim();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return vars;
|
|
58
|
+
}
|
|
59
|
+
async function cmdInit() {
|
|
60
|
+
const manifest = {
|
|
61
|
+
engine: "EJS",
|
|
62
|
+
templateDir: "./templates",
|
|
63
|
+
outputDir: "./generated/{{name}}",
|
|
64
|
+
variables: { name: "MyComponent" },
|
|
65
|
+
structure: [
|
|
66
|
+
{ template: "component.ejs", output: "{{name}}.tsx" },
|
|
67
|
+
{ template: "test.ejs", output: "{{name}}.test.tsx" },
|
|
68
|
+
{ template: "index.ejs", output: "index.ts" }
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
const filePath = "scaffold.json";
|
|
72
|
+
fs.writeFileSync(filePath, JSON.stringify(manifest, null, 2), "utf8");
|
|
73
|
+
console.log(`Created ${filePath}`);
|
|
74
|
+
console.log("Edit the manifest and run: scg generate");
|
|
75
|
+
}
|
|
76
|
+
async function cmdGenerate() {
|
|
77
|
+
const flags = parseFlags(args);
|
|
78
|
+
const manifestPath = flags["manifest"] ?? "scaffold.json";
|
|
79
|
+
const dryRun = args.includes("--dry-run");
|
|
80
|
+
if (!fs.existsSync(manifestPath)) {
|
|
81
|
+
console.error(`Manifest not found: ${manifestPath}`);
|
|
82
|
+
console.error('Run "scg init" to create one.');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
const manifest = JSON.parse(
|
|
86
|
+
fs.readFileSync(manifestPath, "utf8")
|
|
87
|
+
);
|
|
88
|
+
if (flags["vars"]) {
|
|
89
|
+
Object.assign(manifest.variables, parseVars(flags["vars"]));
|
|
90
|
+
}
|
|
91
|
+
manifest.dryRun = dryRun;
|
|
92
|
+
const result = await Scaffold.from(manifest);
|
|
93
|
+
if (dryRun) {
|
|
94
|
+
console.log("Dry run - files that would be created:");
|
|
95
|
+
} else {
|
|
96
|
+
console.log("Generated files:");
|
|
97
|
+
}
|
|
98
|
+
for (const file of result.files) {
|
|
99
|
+
console.log(` ${file}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function cmdRender() {
|
|
103
|
+
const templatePath = args[1];
|
|
104
|
+
if (!templatePath) {
|
|
105
|
+
console.error("Usage: scg render <template> [--data=<json>] [--engine=<name>] [--output=<path>]");
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
const flags = parseFlags(args);
|
|
109
|
+
const engine = flags["engine"] ?? extToEngine(templatePath);
|
|
110
|
+
const dataStr = flags["data"] ?? "{}";
|
|
111
|
+
const outputPath = flags["output"];
|
|
112
|
+
let data;
|
|
113
|
+
try {
|
|
114
|
+
data = JSON.parse(dataStr);
|
|
115
|
+
} catch {
|
|
116
|
+
console.error("Invalid JSON in --data flag");
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const builder = new TemplateBuilder(engine);
|
|
120
|
+
const result = await builder.renderFile(templatePath, data, {});
|
|
121
|
+
if (outputPath) {
|
|
122
|
+
const dir = path.dirname(outputPath);
|
|
123
|
+
if (!fs.existsSync(dir)) {
|
|
124
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
125
|
+
}
|
|
126
|
+
fs.writeFileSync(outputPath, result, "utf8");
|
|
127
|
+
console.log(`Written to ${outputPath}`);
|
|
128
|
+
} else {
|
|
129
|
+
console.log(result);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function extToEngine(filePath) {
|
|
133
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
134
|
+
switch (ext) {
|
|
135
|
+
case ".ejs":
|
|
136
|
+
return "EJS";
|
|
137
|
+
case ".hbs":
|
|
138
|
+
case ".handlebars":
|
|
139
|
+
return "HANDLEBARS";
|
|
140
|
+
case ".pug":
|
|
141
|
+
case ".jade":
|
|
142
|
+
return "PUG";
|
|
143
|
+
default:
|
|
144
|
+
return "HANDLEBARS";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async function main() {
|
|
148
|
+
switch (command) {
|
|
149
|
+
case "init":
|
|
150
|
+
await cmdInit();
|
|
151
|
+
break;
|
|
152
|
+
case "generate":
|
|
153
|
+
await cmdGenerate();
|
|
154
|
+
break;
|
|
155
|
+
case "render":
|
|
156
|
+
await cmdRender();
|
|
157
|
+
break;
|
|
158
|
+
case "--help":
|
|
159
|
+
case "-h":
|
|
160
|
+
case void 0:
|
|
161
|
+
printHelp();
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
console.error(`Unknown command: ${command}`);
|
|
165
|
+
printHelp();
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
main().catch((err) => {
|
|
170
|
+
console.error(err.message);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
|
173
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport fs from 'fs';\nimport path from 'path';\nimport { TemplateBuilder } from './template_builder.js';\nimport { Scaffold, type ScaffoldOptions } from './scaffold.js';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nfunction parseFlags(args: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (const arg of args) {\n const match = arg.match(/^--([a-zA-Z0-9_-]+)=(.*)$/);\n if (match) {\n flags[match[1]] = match[2].replace(/^['\"]/, '').replace(/['\"]$/, '');\n }\n }\n return flags;\n}\n\nfunction printHelp(): void {\n console.log(`\nSCG - Simple Code Generator\n\nUsage:\n scg <command> [options]\n\nCommands:\n init Initialize a scaffold manifest (scaffold.json)\n generate Generate files from a scaffold manifest\n render <template> Render a single template file\n\nOptions:\n --manifest=<path> Path to scaffold manifest (default: scaffold.json)\n --vars=<key=val,...> Comma-separated variables (e.g. name=Button,style=module)\n --data=<json> JSON data for template rendering\n --engine=<name> Template engine (EJS, HANDLEBARS, PUG)\n --output=<path> Output file path (for render command)\n --dry-run Preview without writing files\n\nExamples:\n scg init\n scg generate --manifest=scaffold.json --vars=name=Button\n scg render template.ejs --data='{\"name\": \"World\"}'\n scg render template.ejs --data='{\"name\": \"World\"}' --output=output.html\n`);\n}\n\nfunction parseVars(varsStr: string): Record<string, string> {\n const vars: Record<string, string> = {};\n for (const pair of varsStr.split(',')) {\n const [key, ...rest] = pair.split('=');\n if (key && rest.length > 0) {\n vars[key.trim()] = rest.join('=').trim();\n }\n }\n return vars;\n}\n\nasync function cmdInit(): Promise<void> {\n const manifest: ScaffoldOptions = {\n engine: 'EJS',\n templateDir: './templates',\n outputDir: './generated/{{name}}',\n variables: { name: 'MyComponent' },\n structure: [\n { template: 'component.ejs', output: '{{name}}.tsx' },\n { template: 'test.ejs', output: '{{name}}.test.tsx' },\n { template: 'index.ejs', output: 'index.ts' }\n ]\n };\n const filePath = 'scaffold.json';\n fs.writeFileSync(filePath, JSON.stringify(manifest, null, 2), 'utf8');\n console.log(`Created ${filePath}`);\n console.log('Edit the manifest and run: scg generate');\n}\n\nasync function cmdGenerate(): Promise<void> {\n const flags = parseFlags(args);\n const manifestPath = flags['manifest'] ?? 'scaffold.json';\n const dryRun = args.includes('--dry-run');\n\n if (!fs.existsSync(manifestPath)) {\n console.error(`Manifest not found: ${manifestPath}`);\n console.error('Run \"scg init\" to create one.');\n process.exit(1);\n }\n\n const manifest = JSON.parse(\n fs.readFileSync(manifestPath, 'utf8')\n ) as ScaffoldOptions;\n\n if (flags['vars']) {\n Object.assign(manifest.variables, parseVars(flags['vars']));\n }\n\n manifest.dryRun = dryRun;\n\n const result = await Scaffold.from(manifest);\n\n if (dryRun) {\n console.log('Dry run - files that would be created:');\n } else {\n console.log('Generated files:');\n }\n\n for (const file of result.files) {\n console.log(` ${file}`);\n }\n}\n\nasync function cmdRender(): Promise<void> {\n const templatePath = args[1];\n if (!templatePath) {\n console.error('Usage: scg render <template> [--data=<json>] [--engine=<name>] [--output=<path>]');\n process.exit(1);\n }\n\n const flags = parseFlags(args);\n const engine = flags['engine'] ?? extToEngine(templatePath);\n const dataStr = flags['data'] ?? '{}';\n const outputPath = flags['output'];\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(dataStr);\n } catch {\n console.error('Invalid JSON in --data flag');\n process.exit(1);\n }\n\n const builder = new TemplateBuilder(engine);\n const result = await builder.renderFile(templatePath, data, {});\n\n if (outputPath) {\n const dir = path.dirname(outputPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(outputPath, result, 'utf8');\n console.log(`Written to ${outputPath}`);\n } else {\n console.log(result);\n }\n}\n\nfunction extToEngine(filePath: string): string {\n const ext = path.extname(filePath).toLowerCase();\n switch (ext) {\n case '.ejs':\n return 'EJS';\n case '.hbs':\n case '.handlebars':\n return 'HANDLEBARS';\n case '.pug':\n case '.jade':\n return 'PUG';\n default:\n return 'HANDLEBARS';\n }\n}\n\nasync function main(): Promise<void> {\n switch (command) {\n case 'init':\n await cmdInit();\n break;\n case 'generate':\n await cmdGenerate();\n break;\n case 'render':\n await cmdRender();\n break;\n case '--help':\n case '-h':\n case undefined:\n printHelp();\n break;\n default:\n console.error(`Unknown command: ${command}`);\n printHelp();\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(err.message);\n process.exit(1);\n});\n"],"mappings":";;;;;;;AAEA,OAAO,QAAQ;AACf,OAAO,UAAU;AAIjB,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,UAAU,KAAK,CAAC;AAEtB,SAAS,WAAWA,OAAwC;AAC1D,QAAM,QAAgC,CAAC;AACvC,aAAW,OAAOA,OAAM;AACtB,UAAM,QAAQ,IAAI,MAAM,2BAA2B;AACnD,QAAI,OAAO;AACT,YAAM,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,EAAE,QAAQ,SAAS,EAAE,EAAE,QAAQ,SAAS,EAAE;AAAA,IACrE;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAkB;AACzB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAwBb;AACD;AAEA,SAAS,UAAU,SAAyC;AAC1D,QAAM,OAA+B,CAAC;AACtC,aAAW,QAAQ,QAAQ,MAAM,GAAG,GAAG;AACrC,UAAM,CAAC,KAAK,GAAG,IAAI,IAAI,KAAK,MAAM,GAAG;AACrC,QAAI,OAAO,KAAK,SAAS,GAAG;AAC1B,WAAK,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,GAAG,EAAE,KAAK;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,UAAyB;AACtC,QAAM,WAA4B;AAAA,IAChC,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,WAAW;AAAA,IACX,WAAW,EAAE,MAAM,cAAc;AAAA,IACjC,WAAW;AAAA,MACT,EAAE,UAAU,iBAAiB,QAAQ,eAAe;AAAA,MACpD,EAAE,UAAU,YAAY,QAAQ,oBAAoB;AAAA,MACpD,EAAE,UAAU,aAAa,QAAQ,WAAW;AAAA,IAC9C;AAAA,EACF;AACA,QAAM,WAAW;AACjB,KAAG,cAAc,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,MAAM;AACpE,UAAQ,IAAI,WAAW,QAAQ,EAAE;AACjC,UAAQ,IAAI,yCAAyC;AACvD;AAEA,eAAe,cAA6B;AAC1C,QAAM,QAAQ,WAAW,IAAI;AAC7B,QAAM,eAAe,MAAM,UAAU,KAAK;AAC1C,QAAM,SAAS,KAAK,SAAS,WAAW;AAExC,MAAI,CAAC,GAAG,WAAW,YAAY,GAAG;AAChC,YAAQ,MAAM,uBAAuB,YAAY,EAAE;AACnD,YAAQ,MAAM,+BAA+B;AAC7C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,WAAW,KAAK;AAAA,IACpB,GAAG,aAAa,cAAc,MAAM;AAAA,EACtC;AAEA,MAAI,MAAM,MAAM,GAAG;AACjB,WAAO,OAAO,SAAS,WAAW,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAC5D;AAEA,WAAS,SAAS;AAElB,QAAM,SAAS,MAAM,SAAS,KAAK,QAAQ;AAE3C,MAAI,QAAQ;AACV,YAAQ,IAAI,wCAAwC;AAAA,EACtD,OAAO;AACL,YAAQ,IAAI,kBAAkB;AAAA,EAChC;AAEA,aAAW,QAAQ,OAAO,OAAO;AAC/B,YAAQ,IAAI,KAAK,IAAI,EAAE;AAAA,EACzB;AACF;AAEA,eAAe,YAA2B;AACxC,QAAM,eAAe,KAAK,CAAC;AAC3B,MAAI,CAAC,cAAc;AACjB,YAAQ,MAAM,kFAAkF;AAChG,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,WAAW,IAAI;AAC7B,QAAM,SAAS,MAAM,QAAQ,KAAK,YAAY,YAAY;AAC1D,QAAM,UAAU,MAAM,MAAM,KAAK;AACjC,QAAM,aAAa,MAAM,QAAQ;AAEjC,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,YAAQ,MAAM,6BAA6B;AAC3C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,UAAU,IAAI,gBAAgB,MAAM;AAC1C,QAAM,SAAS,MAAM,QAAQ,WAAW,cAAc,MAAM,CAAC,CAAC;AAE9D,MAAI,YAAY;AACd,UAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,QAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,SAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,IACvC;AACA,OAAG,cAAc,YAAY,QAAQ,MAAM;AAC3C,YAAQ,IAAI,cAAc,UAAU,EAAE;AAAA,EACxC,OAAO;AACL,YAAQ,IAAI,MAAM;AAAA,EACpB;AACF;AAEA,SAAS,YAAY,UAA0B;AAC7C,QAAM,MAAM,KAAK,QAAQ,QAAQ,EAAE,YAAY;AAC/C,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,eAAe,OAAsB;AACnC,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,YAAM,QAAQ;AACd;AAAA,IACF,KAAK;AACH,YAAM,YAAY;AAClB;AAAA,IACF,KAAK;AACH,YAAM,UAAU;AAChB;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,gBAAU;AACV;AAAA,IACF;AACE,cAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,gBAAU;AACV,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,IAAI,OAAO;AACzB,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["args"]}
|