Skip to main content
Module

x/eta/compile-string.ts

Embedded JS template engine for Node, Deno, and the browser. Lighweight, fast, and pluggable. Written in TypeScript
Go to Latest
File
import Parse from './parse.ts'
/* TYPES */
import type { EtaConfig } from './config.ts'import type { AstObject } from './parse.ts'
/* END TYPES */
/** * Compiles a template string to a function string. Most often users just use `compile()`, which calls `compileToString` and creates a new function using the result * * **Example** * * ```js * compileToString("Hi <%= it.user %>", eta.config) * // "var tR='',include=E.include.bind(E),includeFile=E.includeFile.bind(E);tR+='Hi ';tR+=E.e(it.user);if(cb){cb(null,tR)} return tR" * ``` */
export default function compileToString(str: string, config: EtaConfig): string { const buffer: Array<AstObject> = Parse(str, config)
let res = "var tR='',__l,__lP" + (config.include ? ',include=E.include.bind(E)' : '') + (config.includeFile ? ',includeFile=E.includeFile.bind(E)' : '') + '\nfunction layout(p,d){__l=p;__lP=d}\n' + (config.useWith ? 'with(' + config.varName + '||{}){' : '') + compileScope(buffer, config) + (config.includeFile ? 'if(__l)tR=' + (config.async ? 'await ' : '') + `includeFile(__l,Object.assign(${config.varName},{body:tR},__lP))\n` : config.include ? 'if(__l)tR=' + (config.async ? 'await ' : '') + `include(__l,Object.assign(${config.varName},{body:tR},__lP))\n` : '') + 'if(cb){cb(null,tR)} return tR' + (config.useWith ? '}' : '')
if (config.plugins) { for (let i = 0; i < config.plugins.length; i++) { const plugin = config.plugins[i] if (plugin.processFnString) { res = plugin.processFnString(res, config) } } }
return res}
/** * Loops through the AST generated by `parse` and transform each item into JS calls * * **Example** * * ```js * // AST version of 'Hi <%= it.user %>' * let templateAST = ['Hi ', { val: 'it.user', t: 'i' }] * compileScope(templateAST, eta.config) * // "tR+='Hi ';tR+=E.e(it.user);" * ``` */
function compileScope(buff: Array<AstObject>, config: EtaConfig) { let i = 0 const buffLength = buff.length let returnStr = ''
for (i; i < buffLength; i++) { const currentBlock = buff[i] if (typeof currentBlock === 'string') { const str = currentBlock
// we know string exists returnStr += "tR+='" + str + "'\n" } else { const type = currentBlock.t // ~, s, !, ?, r let content = currentBlock.val || ''
if (type === 'r') { // raw
if (config.filter) { content = 'E.filter(' + content + ')' }
returnStr += 'tR+=' + content + '\n' } else if (type === 'i') { // interpolate
if (config.filter) { content = 'E.filter(' + content + ')' }
if (config.autoEscape) { content = 'E.e(' + content + ')' } returnStr += 'tR+=' + content + '\n' // reference } else if (type === 'e') { // execute returnStr += content + '\n' // you need a \n in case you have <% } %> } } }
return returnStr}