import { TokenStream } from './token_stream.js'; export class TemplateEngine { async render(fileName) { const ts = new TokenStream(); await ts.loadFile(fileName); let buffer = ''; while (!ts.eof()) { const token = ts.next(); switch (token.type) { case 'raw': buffer += this._renderRaw(token.value); break; case 'inline': buffer += this._renderInline(token.value); break; case 'inline_unescaped': buffer += this._renderInlineUnescaped(token.value); break; case 'inline_statement': buffer += this._renderInlineStatement(token.value); break; case 'inline_statement_unescaped': buffer += this._renderInlineStatementUnescaped(token.value); break; case 'statement': buffer += this._renderStatement(token.value); break; case 'comment': buffer += this._renderComment(token.value); break; default: throw new Error(`Unrecognized token: ${token.type}`); } } return buffer; } _renderComment(value) { return `# ${value}\n`; } _renderStatement(value) { return `${value}\n`; } _renderInline(value) { return `printf '%s' "${value}" | jq -Rrj @html;\n`; } _renderInlineUnescaped(value) { return `printf '%s' "${value}";\n`; } _renderInlineStatement(value) { return `printf '%s' "$(${value})" | jq -Rrj @html;\n`; } _renderInlineStatementUnescaped(value) { return `printf '%s' "$(${value})";\n`; } _renderRaw(value) { const lines = value.split('\n'); let buffer = ''; for (let i = 0; i < lines.length; i++) { const line = lines[i]; const isLastLine = i === lines.length - 1; if (isLastLine && !line.length) break; const formatString = isLastLine ? '%s' : '%s\\n'; buffer += `printf '${formatString}' '${line.replace("'", "'\\''")}';\n`; } return buffer; } } /* Convenience function for quickly rendering a file */ export function renderFile(fileName) { const tp = new TemplateEngine(); return tp.render(fileName); }