##// END OF EJS Templates
text/format refactoring
cin -
r54:2fd5aee49888 di-typescript
parent child
Show More
@@ -0,0 +1,40
1 import { format as dojoFormatNumber } from "dojo/number";
2 import { format as dojoFormatDate } from "dojo/date/locale";
3
4 import { isNumber } from "./safe";
5
6 interface NumberFormatOptions {
7 round?: number;
8 pattern?: string;
9 }
10
11 function formatNumber(value: any, pattern: string) {
12 if (isNumber(value)) {
13 const nopt = {} as NumberFormatOptions;
14 if (pattern.indexOf("!") === 0) {
15 nopt.round = -1;
16 pattern = pattern.substr(1);
17 }
18 nopt.pattern = pattern;
19
20 return dojoFormatNumber(value, nopt);
21 }
22 }
23
24 function formatDate(value: any, pattern: string) {
25 if (value instanceof Date) {
26 const m = pattern.match(/^(\w+)-(\w+)$/);
27 if (m)
28 return dojoFormatDate(value, {
29 selector: m[2],
30 formatLength: m[1]
31 });
32 else if (pattern === "iso")
33 return value.toISOString();
34 else
35 return dojoFormatDate(value, {
36 selector: "date",
37 datePattern: pattern
38 });
39 }
40 }
@@ -0,0 +1,160
1 import { isPrimitive, isNumber, isNull } from "../safe";
2
3 type SubstFn = (name: string, format?: string) => string;
4 type FormatFn = (subst: SubstFn) => string;
5 type ConvertFn = (value: any, format?: string) => string;
6
7 const map = {
8 "\\{": "&curlopen;",
9 "\\}": "&curlclose;",
10 "&": "&",
11 "\\:": ":"
12 };
13
14 const rev = {
15 curlopen: "{",
16 curlclose: "}",
17 amp: "&",
18 colon: ":"
19 };
20
21 function espaceString(s: string) {
22 if (!s)
23 return s;
24 return "'" + s.replace(/('|\\)/g, "\\$1").replace("\n", "\\n") + "'";
25 }
26
27 function encode(s: string) {
28 if (!s)
29 return s;
30 return s.replace(/\\{|\\}|&|\\:|\n/g, m => map[m] || m);
31 }
32
33 function decode(s: string) {
34 if (!s)
35 return s;
36 return s.replace(/&(\w+);/g, (m, $1) => rev[$1] || m);
37 }
38
39 function subst(s: string) {
40 const i = s.indexOf(":");
41 let name: string;
42 let pattern: string;
43 if (i >= 0) {
44 name = s.substr(0, i);
45 pattern = s.substr(i + 1);
46 } else {
47 name = s;
48 }
49
50 if (pattern)
51 return [
52 espaceString(decode(name)),
53 espaceString(decode(pattern))];
54 else
55 return [espaceString(decode(name))];
56 }
57
58 function _compile(str: string) {
59 if (!str)
60 return () => void 0;
61
62 const chunks = encode(str).split("{");
63 let chunk: string;
64
65 const code = ["var result=[];"];
66
67 for (let i = 0; i < chunks.length; i++) {
68 chunk = chunks[i];
69
70 if (i === 0) {
71 if (chunk)
72 code.push("result.push(" + espaceString(decode(chunk)) +
73 ");");
74 } else {
75 const len = chunk.indexOf("}");
76 if (len < 0)
77 throw new Error("Unbalanced substitution #" + i);
78
79 code.push("result.push(subst(" +
80 subst(chunk.substr(0, len)).join(",") + "));");
81 if (chunk.length > len + 1)
82 code.push("result.push(" +
83 espaceString(decode(chunk.substr(len + 1))) + ");");
84 }
85 }
86
87 code.push("return result.join('');");
88
89 // the code for this function is generated from the template
90 // tslint:disable-next-line:function-constructor
91 return new Function("subst", code.join("\n")) as FormatFn;
92 }
93
94 const cache = {} as {
95 [i: string]: FormatFn
96 };
97
98 export function compile(template: string) {
99 let compiled = cache[template];
100 if (!compiled) {
101 compiled = _compile(template);
102 cache[template] = compiled;
103 }
104 return compiled;
105 }
106
107 function convert(value: any, pattern) {
108 if (!pattern)
109 return value.toString();
110
111 if (pattern.toLocaleLowerCase() === "json") {
112 const seen = [];
113 return JSON.stringify(value, (k, v) => {
114 if (!isPrimitive(v)) {
115 const id = seen.indexOf(v);
116 if (id >= 0)
117 return "@ref-" + id;
118 else {
119 seen.push(v);
120 return v;
121 }
122 } else {
123 return v;
124 }
125 }, 2);
126 }
127
128 defaultFormatter(value, pattern);
129 }
130
131 function defaultFormatter(value: any, pattern: string) {
132 if (value instanceof Date) {
133 return value.toISOString();
134 } else {
135 return value.toString(pattern);
136 }
137 }
138
139 export function format(fmt: string, ...args: any[]) {
140 if (args.length === 0)
141 return fmt;
142
143 const template = compile(fmt);
144
145 return template((name, pattern) => {
146 const value = args[name];
147 return !isNull(value) ? convert(value, pattern) : "";
148 });
149 }
150
151 export function compileFormat(fmt: string) {
152 const template = compile(fmt);
153
154 return (...args: any[]) => {
155 return template((name, pattern) => {
156 const value = args[name];
157 return !isNull(value) ? convert(value, pattern) : "";
158 });
159 };
160 }
@@ -7,19 +7,19 export class AsyncComponent implements I
7 7
8 8 _completion: Promise<void> = Promise.resolve();
9 9
10 getCompletion() { return this._completion };
10 getCompletion() { return this._completion; }
11 11
12 12 runOperation(op: (ct: ICancellation) => any, ct: ICancellation = Cancellation.none) {
13 13 // create inner cancellation bound to the passed cancellation token
14 14 let h: IDestroyable;
15 let inner = new Cancellation(cancel => {
15 const inner = new Cancellation(cancel => {
16 16
17 17 this._cancel = cancel;
18 18 h = ct.register(cancel);
19 19 });
20 20
21 21 // TODO create cancellation source here
22 let guard = async () => {
22 const guard = async () => {
23 23 try {
24 24 await op(inner);
25 25 } finally {
@@ -28,7 +28,7 export class AsyncComponent implements I
28 28 destroy(h);
29 29 this._cancel = null;
30 30 }
31 }
31 };
32 32
33 33 return this._completion = guard();
34 34 }
@@ -37,4 +37,4 export class AsyncComponent implements I
37 37 if (this._cancel)
38 38 this._cancel(reason);
39 39 }
40 } No newline at end of file
40 }
@@ -1,6 +1,6
1 import * as format from "../text/format";
2 1 import { Observable } from "../Observable";
3 2 import { Registry } from "./Registry";
3 import { format } from "../text/FormatString";
4 4
5 5 export const DebugLevel = 400;
6 6
@@ -47,7 +47,7 export class TraceSource {
47 47
48 48 debug(msg: string, ...args: any[]) {
49 49 if (this.isEnabled(DebugLevel))
50 this.emit(DebugLevel, format.apply(null, arguments));
50 this.emit(DebugLevel, format(msg, args));
51 51 }
52 52
53 53 isLogEnabled() {
@@ -56,7 +56,7 export class TraceSource {
56 56
57 57 log(msg: string, ...args: any[]) {
58 58 if (this.isEnabled(LogLevel))
59 this.emit(LogLevel, format.apply(null, arguments));
59 this.emit(LogLevel, format(msg, args));
60 60 }
61 61
62 62 isWarnEnabled() {
@@ -65,7 +65,7 export class TraceSource {
65 65
66 66 warn(msg: string, ...args: any[]) {
67 67 if (this.isEnabled(WarnLevel))
68 this.emit(WarnLevel, format.apply(null, arguments));
68 this.emit(WarnLevel, format(msg, args));
69 69 }
70 70
71 71 /**
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now