##// END OF EJS Templates
text/format refactoring
text/format refactoring

File last commit:

r54:2fd5aee49888 di-typescript
r54:2fd5aee49888 di-typescript
Show More
FormatString.ts
160 lines | 3.8 KiB | video/mp2t | TypeScriptLexer
/ src / main / ts / text / FormatString.ts
cin
text/format refactoring
r54 import { isPrimitive, isNumber, isNull } from "../safe";
type SubstFn = (name: string, format?: string) => string;
type FormatFn = (subst: SubstFn) => string;
type ConvertFn = (value: any, format?: string) => string;
const map = {
"\\{": "&curlopen;",
"\\}": "&curlclose;",
"&": "&",
"\\:": ":"
};
const rev = {
curlopen: "{",
curlclose: "}",
amp: "&",
colon: ":"
};
function espaceString(s: string) {
if (!s)
return s;
return "'" + s.replace(/('|\\)/g, "\\$1").replace("\n", "\\n") + "'";
}
function encode(s: string) {
if (!s)
return s;
return s.replace(/\\{|\\}|&|\\:|\n/g, m => map[m] || m);
}
function decode(s: string) {
if (!s)
return s;
return s.replace(/&(\w+);/g, (m, $1) => rev[$1] || m);
}
function subst(s: string) {
const i = s.indexOf(":");
let name: string;
let pattern: string;
if (i >= 0) {
name = s.substr(0, i);
pattern = s.substr(i + 1);
} else {
name = s;
}
if (pattern)
return [
espaceString(decode(name)),
espaceString(decode(pattern))];
else
return [espaceString(decode(name))];
}
function _compile(str: string) {
if (!str)
return () => void 0;
const chunks = encode(str).split("{");
let chunk: string;
const code = ["var result=[];"];
for (let i = 0; i < chunks.length; i++) {
chunk = chunks[i];
if (i === 0) {
if (chunk)
code.push("result.push(" + espaceString(decode(chunk)) +
");");
} else {
const len = chunk.indexOf("}");
if (len < 0)
throw new Error("Unbalanced substitution #" + i);
code.push("result.push(subst(" +
subst(chunk.substr(0, len)).join(",") + "));");
if (chunk.length > len + 1)
code.push("result.push(" +
espaceString(decode(chunk.substr(len + 1))) + ");");
}
}
code.push("return result.join('');");
// the code for this function is generated from the template
// tslint:disable-next-line:function-constructor
return new Function("subst", code.join("\n")) as FormatFn;
}
const cache = {} as {
[i: string]: FormatFn
};
export function compile(template: string) {
let compiled = cache[template];
if (!compiled) {
compiled = _compile(template);
cache[template] = compiled;
}
return compiled;
}
function convert(value: any, pattern) {
if (!pattern)
return value.toString();
if (pattern.toLocaleLowerCase() === "json") {
const seen = [];
return JSON.stringify(value, (k, v) => {
if (!isPrimitive(v)) {
const id = seen.indexOf(v);
if (id >= 0)
return "@ref-" + id;
else {
seen.push(v);
return v;
}
} else {
return v;
}
}, 2);
}
defaultFormatter(value, pattern);
}
function defaultFormatter(value: any, pattern: string) {
if (value instanceof Date) {
return value.toISOString();
} else {
return value.toString(pattern);
}
}
export function format(fmt: string, ...args: any[]) {
if (args.length === 0)
return fmt;
const template = compile(fmt);
return template((name, pattern) => {
const value = args[name];
return !isNull(value) ? convert(value, pattern) : "";
});
}
export function compileFormat(fmt: string) {
const template = compile(fmt);
return (...args: any[]) => {
return template((name, pattern) => {
const value = args[name];
return !isNull(value) ? convert(value, pattern) : "";
});
};
}