const decoder = new TextDecoder("utf-8");
export class Jae { public views_path = "";
constructor(viewsPath: string) { this.views_path = viewsPath; }
public render(template: string, data: unknown): string { let code = "with(obj) { var r=[];\n"; let cursor = 0; let match; let filepath = this.views_path; if (this.views_path.endsWith("/") && template.startsWith("/")) { filepath += template.slice(1); } else if (!this.views_path.endsWith("/") && !template.startsWith("/")) { filepath += `/${template}`; } else { filepath += template; }
let html: string = decoder.decode( Deno.readFileSync(filepath), );
const extended = html.match(/<% extends.* %>/g); if (extended) { extended.forEach((m: string) => { html = html.replace(m, ""); let template = m.replace('<% extends("', "").replace('") %>', ""); template = decoder.decode( Deno.readFileSync(this.views_path + template), ); html = template.replace("<% yield %>", html); }); }
let partials; while ((partials = html.match(/<% include_partial.* %>/g))) { partials.forEach((m: string) => { let template = m .replace('<% include_partial("', "") .replace('") %>', ""); template = decoder.decode( Deno.readFileSync(this.views_path + template), ); html = html.replace(m, template); }); }
const re = /<%(.+?)\%>/g; const reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g; let result; function add(line: string, js: unknown | null = null) { js ? (code += line.match(reExp) ? line + "\n" : "r.push(" + line + ");\n") : (code += line != "" ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : ""); return add; }
while ((match = re.exec(html))) { add(html.slice(cursor, match.index)); add(match[1], true); cursor = match.index + match[0].length; }
add(html.substr(cursor, html.length - cursor)); code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, " ");
try { if (!data) { data = {}; } result = new Function("obj", code).apply(data, [data]); } catch (err) { console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n"); }
return result; }}