##// END OF EJS Templates
ported string format traits to typescript
cin -
r55:4eaaaa5c1cf3 di-typescript
parent child
Show More
@@ -0,0 +1,8
1 import * as module from "module";
2 import { TraceSource } from "../log/TraceSource";
3
4 const logger = TraceSource.get(module.id);
5
6 logger.warn("The module is deprecated, use StringFormat.compile() method directly");
7
8 export { compile } from "./StringFormat";
@@ -0,0 +1,47
1 import { format as dojoFormatNumber } from "dojo/number";
2 import { format as dojoFormatDate } from "dojo/date/locale";
3 import { Formatter } from "./StringFormat";
4
5 import { isNumber } from "../safe";
6
7 interface NumberFormatOptions {
8 round?: number;
9 pattern?: string;
10 }
11
12 function convertNumber(value: any, pattern: string) {
13 if (isNumber(value)) {
14 const nopt = {} as NumberFormatOptions;
15 if (pattern.indexOf("!") === 0) {
16 nopt.round = -1;
17 pattern = pattern.substr(1);
18 }
19 nopt.pattern = pattern;
20
21 return dojoFormatNumber(value, nopt);
22 }
23 }
24
25 function convertDate(value: any, pattern: string) {
26 if (value instanceof Date) {
27 const m = pattern.match(/^(\w+)-(\w+)$/);
28 if (m)
29 return dojoFormatDate(value, {
30 selector: m[2],
31 formatLength: m[1]
32 });
33 else if (pattern === "iso")
34 return value.toISOString();
35 else
36 return dojoFormatDate(value, {
37 selector: "date",
38 datePattern: pattern
39 });
40 }
41 }
42
43 const _formatter = new Formatter([convertNumber, convertDate]);
44
45 export = function format(msg: string, ...args: any[]) {
46 return _formatter.format.apply(msg, ...args);
47 };
@@ -0,0 +1,173
1 import { isPrimitive, isNull, each } from "../safe";
2 import { MapOf } from "../interfaces";
3
4 type SubstFn = (name: string, format?: string) => string;
5 type TemplateFn = (subst: SubstFn) => string;
6 type ConvertFn = (value: any, format?: string) => string;
7
8 const map = {
9 "\\{": "&curlopen;",
10 "\\}": "&curlclose;",
11 "&": "&",
12 "\\:": ":"
13 };
14
15 const rev = {
16 curlopen: "{",
17 curlclose: "}",
18 amp: "&",
19 colon: ":"
20 };
21
22 function espaceString(s: string) {
23 if (!s)
24 return s;
25 return "'" + s.replace(/('|\\)/g, "\\$1").replace("\n", "\\n") + "'";
26 }
27
28 function encode(s: string) {
29 if (!s)
30 return s;
31 return s.replace(/\\{|\\}|&|\\:|\n/g, m => map[m] || m);
32 }
33
34 function decode(s: string) {
35 if (!s)
36 return s;
37 return s.replace(/&(\w+);/g, (m, $1) => rev[$1] || m);
38 }
39
40 function subst(s: string) {
41 const i = s.indexOf(":");
42 let name: string;
43 let pattern: string;
44 if (i >= 0) {
45 name = s.substr(0, i);
46 pattern = s.substr(i + 1);
47 } else {
48 name = s;
49 }
50
51 if (pattern)
52 return [
53 espaceString(decode(name)),
54 espaceString(decode(pattern))];
55 else
56 return [espaceString(decode(name))];
57 }
58
59 function _compile(str: string) {
60 if (!str)
61 return () => void 0;
62
63 const chunks = encode(str).split("{");
64 let chunk: string;
65
66 const code = ["var result=[];"];
67
68 for (let i = 0; i < chunks.length; i++) {
69 chunk = chunks[i];
70
71 if (i === 0) {
72 if (chunk)
73 code.push("result.push(" + espaceString(decode(chunk)) +
74 ");");
75 } else {
76 const len = chunk.indexOf("}");
77 if (len < 0)
78 throw new Error("Unbalanced substitution #" + i);
79
80 code.push("result.push(subst(" +
81 subst(chunk.substr(0, len)).join(",") + "));");
82 if (chunk.length > len + 1)
83 code.push("result.push(" +
84 espaceString(decode(chunk.substr(len + 1))) + ");");
85 }
86 }
87
88 code.push("return result.join('');");
89
90 // the code for this function is generated from the template
91 // tslint:disable-next-line:function-constructor
92 return new Function("subst", code.join("\n")) as TemplateFn;
93 }
94
95 const cache: MapOf<TemplateFn> = {};
96
97 export function compile(template: string) {
98 let compiled = cache[template];
99 if (!compiled) {
100 compiled = _compile(template);
101 cache[template] = compiled;
102 }
103 return compiled;
104 }
105
106 function defaultConverter(value: any, pattern: string) {
107 if (pattern && pattern.toLocaleLowerCase() === "json") {
108 const seen = [];
109 return JSON.stringify(value, (k, v) => {
110 if (!isPrimitive(v)) {
111 const id = seen.indexOf(v);
112 if (id >= 0)
113 return "@ref-" + id;
114 else {
115 seen.push(v);
116 return v;
117 }
118 } else {
119 return v;
120 }
121 }, 2);
122 } else if (isNull(value)) {
123 return "";
124 } else if (value instanceof Date) {
125 return value.toISOString();
126 } else {
127 return pattern ? value.toString(pattern) : value.toString();
128 }
129 }
130
131 export class Formatter {
132 _converters: ConvertFn[];
133
134 constructor(converters?: ConvertFn[]) {
135 this._converters = converters || [];
136 this._converters.push(defaultConverter);
137 }
138
139 convert(value: any, pattern: string) {
140 for (const c of this._converters) {
141 const res = c(value, pattern);
142 if (!isNull(res))
143 return res;
144 }
145 return "";
146 }
147
148 format(msg: string, ...args: any[]) {
149 const template = compile(msg);
150
151 return template((name, pattern) => {
152 const value = args[name];
153 return !isNull(value) ? this.convert(value, pattern) : "";
154 });
155
156 }
157
158 compile(msg: string) {
159 const template = compile(msg);
160 return (...args: any[]) => {
161 return template((name, pattern) => {
162 const value = args[name];
163 return !isNull(value) ? this.convert(value, pattern) : "";
164 });
165 };
166 }
167 }
168
169 const _default = new Formatter();
170
171 export function format(msg: string, ...args: any[]) {
172 return _default.format(msg, ...args);
173 }
@@ -1,80 +1,84
1 export type Constructor<T = {}> = new (...args: any[]) => T;
1 export type Constructor<T = {}> = new (...args: any[]) => T;
2
2
3 export type Factory<T = {}> = (...args: any[]) => T;
3 export type Factory<T = {}> = (...args: any[]) => T;
4
4
5 export interface MapOf<T> {
6 [key: string]: T;
7 }
8
5 export interface IDestroyable {
9 export interface IDestroyable {
6 destroy();
10 destroy();
7 }
11 }
8
12
9 export interface ICancellation {
13 export interface ICancellation {
10 throwIfRequested(): void;
14 throwIfRequested(): void;
11 isRequested(): boolean;
15 isRequested(): boolean;
12 isSupported(): boolean;
16 isSupported(): boolean;
13 register(cb: (e: any) => void): IDestroyable;
17 register(cb: (e: any) => void): IDestroyable;
14 }
18 }
15
19
16 /**
20 /**
17 * Интерфейс поддерживающий асинхронную активацию
21 * Интерфейс поддерживающий асинхронную активацию
18 */
22 */
19 export interface IActivatable {
23 export interface IActivatable {
20 /**
24 /**
21 * @returns Boolean indicates the current state
25 * @returns Boolean indicates the current state
22 */
26 */
23 isActive(): boolean;
27 isActive(): boolean;
24
28
25 /**
29 /**
26 * Starts the component activation
30 * Starts the component activation
27 * @param ct cancellation token for this operation
31 * @param ct cancellation token for this operation
28 */
32 */
29 activate(ct?: ICancellation): Promise<void>;
33 activate(ct?: ICancellation): Promise<void>;
30
34
31 /**
35 /**
32 * Starts the component deactivation
36 * Starts the component deactivation
33 * @param ct cancellation token for this operation
37 * @param ct cancellation token for this operation
34 */
38 */
35 deactivate(ct?: ICancellation): Promise<void>;
39 deactivate(ct?: ICancellation): Promise<void>;
36
40
37 /**
41 /**
38 * Sets the activation controller for this component
42 * Sets the activation controller for this component
39 * @param controller The activation controller
43 * @param controller The activation controller
40 *
44 *
41 * Activation controller checks whether this component
45 * Activation controller checks whether this component
42 * can be activated and manages the active state of the
46 * can be activated and manages the active state of the
43 * component
47 * component
44 */
48 */
45 setActivationController(controller: IActivationController);
49 setActivationController(controller: IActivationController);
46
50
47 /**
51 /**
48 * Gets the current activation controller for this component
52 * Gets the current activation controller for this component
49 */
53 */
50 getActivationController(): IActivationController;
54 getActivationController(): IActivationController;
51 }
55 }
52
56
53 export interface IActivationController {
57 export interface IActivationController {
54 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
58 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
55
59
56 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
60 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
57
61
58 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
62 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
59
63
60 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
64 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
61
65
62 deactivate(ct?: ICancellation): Promise<void>;
66 deactivate(ct?: ICancellation): Promise<void>;
63
67
64 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
68 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
65
69
66 getActive(): IActivatable;
70 getActive(): IActivatable;
67 }
71 }
68
72
69 export interface IAsyncComponent {
73 export interface IAsyncComponent {
70 getCompletion(): Promise<void>;
74 getCompletion(): Promise<void>;
71 }
75 }
72
76
73 export interface ICancellable {
77 export interface ICancellable {
74 cancel(reason?: any): void;
78 cancel(reason?: any): void;
75 }
79 }
76
80
77 export interface IObservable<T> {
81 export interface IObservable<T> {
78 on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable;
82 on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable;
79 next(ct?: ICancellation): Promise<T>;
83 next(ct?: ICancellation): Promise<T>;
80 }
84 }
@@ -1,128 +1,128
1 import { Observable } from "../Observable";
1 import { Observable } from "../Observable";
2 import { Registry } from "./Registry";
2 import { Registry } from "./Registry";
3 import { format } from "../text/FormatString";
3 import { format } from "../text/StringFormat";
4
4
5 export const DebugLevel = 400;
5 export const DebugLevel = 400;
6
6
7 export const LogLevel = 300;
7 export const LogLevel = 300;
8
8
9 export const WarnLevel = 200;
9 export const WarnLevel = 200;
10
10
11 export const ErrorLevel = 100;
11 export const ErrorLevel = 100;
12
12
13 export const SilentLevel = 0;
13 export const SilentLevel = 0;
14
14
15 export interface TraceEvent {
15 export interface TraceEvent {
16 readonly source: TraceSource;
16 readonly source: TraceSource;
17
17
18 readonly level: number;
18 readonly level: number;
19
19
20 readonly arg: any;
20 readonly arg: any;
21 }
21 }
22
22
23 export class TraceSource {
23 export class TraceSource {
24 readonly id: any;
24 readonly id: any;
25
25
26 level: number;
26 level: number;
27
27
28 readonly events: Observable<TraceEvent>;
28 readonly events: Observable<TraceEvent>;
29
29
30 _notifyNext: (arg: TraceEvent) => void;
30 _notifyNext: (arg: TraceEvent) => void;
31
31
32 constructor(id: any) {
32 constructor(id: any) {
33
33
34 this.id = id || new Object();
34 this.id = id || new Object();
35 this.events = new Observable(next => {
35 this.events = new Observable(next => {
36 this._notifyNext = next;
36 this._notifyNext = next;
37 });
37 });
38 }
38 }
39
39
40 protected emit(level: number, arg: any) {
40 protected emit(level: number, arg: any) {
41 this._notifyNext({ source: this, level, arg});
41 this._notifyNext({ source: this, level, arg });
42 }
42 }
43
43
44 isDebugEnabled() {
44 isDebugEnabled() {
45 return this.level >= DebugLevel;
45 return this.level >= DebugLevel;
46 }
46 }
47
47
48 debug(msg: string, ...args: any[]) {
48 debug(msg: string, ...args: any[]) {
49 if (this.isEnabled(DebugLevel))
49 if (this.isEnabled(DebugLevel))
50 this.emit(DebugLevel, format(msg, args));
50 this.emit(DebugLevel, format(msg, args));
51 }
51 }
52
52
53 isLogEnabled() {
53 isLogEnabled() {
54 return this.level >= LogLevel;
54 return this.level >= LogLevel;
55 }
55 }
56
56
57 log(msg: string, ...args: any[]) {
57 log(msg: string, ...args: any[]) {
58 if (this.isEnabled(LogLevel))
58 if (this.isEnabled(LogLevel))
59 this.emit(LogLevel, format(msg, args));
59 this.emit(LogLevel, format(msg, args));
60 }
60 }
61
61
62 isWarnEnabled() {
62 isWarnEnabled() {
63 return this.level >= WarnLevel;
63 return this.level >= WarnLevel;
64 }
64 }
65
65
66 warn(msg: string, ...args: any[]) {
66 warn(msg: string, ...args: any[]) {
67 if (this.isEnabled(WarnLevel))
67 if (this.isEnabled(WarnLevel))
68 this.emit(WarnLevel, format(msg, args));
68 this.emit(WarnLevel, format(msg, args));
69 }
69 }
70
70
71 /**
71 /**
72 * returns true if errors will be recorded.
72 * returns true if errors will be recorded.
73 */
73 */
74 isErrorEnabled() {
74 isErrorEnabled() {
75 return this.level >= ErrorLevel;
75 return this.level >= ErrorLevel;
76 }
76 }
77
77
78 /**
78 /**
79 * Traces a error.
79 * Traces a error.
80 *
80 *
81 * @param msg the message.
81 * @param msg the message.
82 * @param args parameters which will be substituted in the message.
82 * @param args parameters which will be substituted in the message.
83 */
83 */
84 error(msg: string, ...args: any[]) {
84 error(msg: string, ...args: any[]) {
85 if (this.isEnabled(ErrorLevel))
85 if (this.isEnabled(ErrorLevel))
86 this.emit(ErrorLevel, format.apply(null, arguments));
86 this.emit(ErrorLevel, format.apply(null, arguments));
87 }
87 }
88
88
89 /**
89 /**
90 * Checks whether the specified level is enabled for this
90 * Checks whether the specified level is enabled for this
91 * trace source.
91 * trace source.
92 *
92 *
93 * @param level the trace level which should be checked.
93 * @param level the trace level which should be checked.
94 */
94 */
95 isEnabled(level: number) {
95 isEnabled(level: number) {
96 return (this.level >= level);
96 return (this.level >= level);
97 }
97 }
98
98
99 /**
99 /**
100 * Traces a raw event, passing data as it is to the underlying listeners
100 * Traces a raw event, passing data as it is to the underlying listeners
101 *
101 *
102 * @param level the level of the event
102 * @param level the level of the event
103 * @param arg the data of the event, can be a simple string or any object.
103 * @param arg the data of the event, can be a simple string or any object.
104 */
104 */
105 traceEvent(level: number, arg: any) {
105 traceEvent(level: number, arg: any) {
106 if (this.isEnabled(level))
106 if (this.isEnabled(level))
107 this.emit(level, arg);
107 this.emit(level, arg);
108 }
108 }
109
109
110 /**
110 /**
111 * Register the specified handler to be called for every new and already
111 * Register the specified handler to be called for every new and already
112 * created trace source.
112 * created trace source.
113 *
113 *
114 * @param handler the handler which will be called for each trace source
114 * @param handler the handler which will be called for each trace source
115 */
115 */
116 static on(handler: (source: TraceSource) => void) {
116 static on(handler: (source: TraceSource) => void) {
117 return Registry.instance.on(handler);
117 return Registry.instance.on(handler);
118 }
118 }
119
119
120 /**
120 /**
121 * Creates or returns already created trace source for the specified id.
121 * Creates or returns already created trace source for the specified id.
122 *
122 *
123 * @param id the id for the trace source
123 * @param id the id for the trace source
124 */
124 */
125 static get(id: any) {
125 static get(id: any) {
126 return Registry.instance.get(id);
126 return Registry.instance.get(id);
127 }
127 }
128 }
128 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now