##// END OF EJS Templates
wip migrating on new typescript build plugin
wip migrating on new typescript build plugin

File last commit:

r115:691199f665e0 ioc ts support
r174:b00d3153045c default
Show More
TemplateCompiler.ts
136 lines | 3.7 KiB | video/mp2t | TypeScriptLexer
/ src / amd / ts / text / TemplateCompiler.ts
import * as format from "./format";
import { TraceSource, DebugLevel } from "../log/TraceSource";
import { ITemplateParser, TokenType } from "./TemplateParser";
import m = require("module");
import { isKeyof } from "../safe";
const trace = TraceSource.get(m.id);
type TemplateFn = (obj: object) => string;
const htmlEscapes = {
"&": "&",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#x27;",
"/": "&#x2F;"
};
// Regex containing the keys listed immediately above.
const htmlEscaper = /[&<>"'\/]/g;
// Escape a string for HTML interpolation.
function escapeHtml(string: any) {
return ("" + string).replace(htmlEscaper, match => isKeyof(match, htmlEscapes) ? htmlEscapes[match] : "");
}
export class TemplateCompiler {
_data: string[];
_code: string[];
_wrapWith = true;
constructor() {
this._code = [];
this._data = [];
}
compile(parser: ITemplateParser): TemplateFn {
this.preamble();
this.visitTemplate(parser);
this.postamble();
const text = this._code.join("\n");
try {
// tslint:disable-next-line:function-constructor
const compiled = new Function("obj, format, $data, escapeHtml", text);
/**
* Функция форматирования по шаблону
*
* @type{Function}
* @param{Object} obj объект с параметрами для подстановки
*/
return (obj: object) => compiled(obj || {}, format, this._data, escapeHtml);
} catch (e) {
trace.traceEvent(DebugLevel, [e, text, this._data]);
throw e;
}
}
preamble() {
this._code.push(
"var $p = [];",
"var print = function(){",
" $p.push(format.apply(null,arguments));",
"};"
);
if (this._wrapWith)
this._code.push("with(obj){");
}
postamble() {
if (this._wrapWith)
this._code.push("}");
this._code.push("return $p.join('');");
}
visitTemplate(parser: ITemplateParser) {
while (parser.next()) {
switch (parser.token()) {
case TokenType.OpenBlock:
this.visitCode(parser);
break;
case TokenType.OpenInlineBlock:
this.visitInline(parser);
break;
case TokenType.OpenFilterBlock:
this.visitFilter(parser);
break;
default:
this.visitTextFragment(parser);
break;
}
}
}
visitInline(parser: ITemplateParser) {
const code = ["$p.push("];
while (parser.next()) {
if (parser.token() === TokenType.CloseBlock)
break;
code.push(parser.value());
}
code.push(");");
this._code.push(code.join(""));
}
visitFilter(parser: ITemplateParser) {
const code = ["$p.push(escapeHtml("];
while (parser.next()) {
if (parser.token() === TokenType.CloseBlock)
break;
code.push(parser.value());
}
code.push("));");
this._code.push(code.join(""));
}
visitCode(parser: ITemplateParser) {
const code = [];
while (parser.next()) {
if (parser.token() === TokenType.CloseBlock)
break;
code.push(parser.value());
}
this._code.push(code.join(""));
}
visitTextFragment(parser: ITemplateParser) {
const i = this._data.push(parser.value()) - 1;
this._code.push("$p.push($data[" + i + "]);");
}
}