@omnia/velcron 8.0.322-dev → 8.0.323-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const capitalizeFormatter: InterpolationFormatter;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.capitalizeFormatter = void 0;
4
+ const parser_1 = require("../parser");
5
+ exports.capitalizeFormatter = {
6
+ name: "capitalize",
7
+ format: (value) => {
8
+ if (typeof value === "string") {
9
+ return value.replace(/\b\w/g, (char) => char.toUpperCase());
10
+ }
11
+ return value;
12
+ }
13
+ };
14
+ parser_1.VelcronFormatters.registerFormatter(exports.capitalizeFormatter);
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const dateFormatter: InterpolationFormatter;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dateFormatter = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
6
+ const parser_1 = require("../parser");
7
+ exports.dateFormatter = {
8
+ name: "date",
9
+ format: (value, formatStr = "YYYY-MM-DD") => {
10
+ if (typeof value === "string" || value instanceof Date) {
11
+ const date = (0, dayjs_1.default)(value);
12
+ if (date.isValid()) {
13
+ return date.format(formatStr);
14
+ }
15
+ }
16
+ return value;
17
+ }
18
+ };
19
+ parser_1.VelcronFormatters.registerFormatter(exports.dateFormatter);
@@ -0,0 +1,4 @@
1
+ export interface InterpolationFormatter {
2
+ name: string;
3
+ format: (value: unknown, ...parameters: any) => string | number;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const jsonFormatter: InterpolationFormatter;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.jsonFormatter = void 0;
4
+ const parser_1 = require("../parser");
5
+ exports.jsonFormatter = {
6
+ name: "json",
7
+ format: (value) => {
8
+ return JSON.stringify(value, null, 2);
9
+ },
10
+ };
11
+ parser_1.VelcronFormatters.registerFormatter(exports.jsonFormatter);
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const lengthFormatter: InterpolationFormatter;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lengthFormatter = void 0;
4
+ const parser_1 = require("../parser");
5
+ exports.lengthFormatter = {
6
+ name: "length",
7
+ format: (value) => {
8
+ if (typeof value === "string" || Array.isArray(value)) {
9
+ return value.length;
10
+ }
11
+ return 0;
12
+ },
13
+ };
14
+ parser_1.VelcronFormatters.registerFormatter(exports.lengthFormatter);
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const replaceFormatter: InterpolationFormatter;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.replaceFormatter = void 0;
4
+ const parser_1 = require("../parser");
5
+ exports.replaceFormatter = {
6
+ name: "replace",
7
+ format: (value, search, replacement) => {
8
+ if (typeof value === "string") {
9
+ return value.split(search).join(replacement);
10
+ }
11
+ return value;
12
+ },
13
+ };
14
+ parser_1.VelcronFormatters.registerFormatter(exports.replaceFormatter);
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const substringFormatter: InterpolationFormatter;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.substringFormatter = void 0;
4
+ const parser_1 = require("../parser");
5
+ exports.substringFormatter = {
6
+ name: "substring",
7
+ format: (value, start, end) => {
8
+ if (typeof value === "string") {
9
+ return value.substring(start, end);
10
+ }
11
+ return value;
12
+ },
13
+ };
14
+ parser_1.VelcronFormatters.registerFormatter(exports.substringFormatter);
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const trimFormatter: InterpolationFormatter;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trimFormatter = void 0;
4
+ const parser_1 = require("../parser");
5
+ exports.trimFormatter = {
6
+ name: "trim",
7
+ format: (value, lengthStr = "100") => {
8
+ if (typeof value === "string") {
9
+ const maxLength = parseInt(lengthStr, 10);
10
+ if (isNaN(maxLength))
11
+ return value;
12
+ return value.length > maxLength ? value.substring(0, maxLength) + "..." : value;
13
+ }
14
+ return value;
15
+ }
16
+ };
17
+ parser_1.VelcronFormatters.registerFormatter(exports.trimFormatter);
@@ -0,0 +1,2 @@
1
+ import { InterpolationFormatter } from "./InterpolationFormatter";
2
+ export declare const uppercaseFormatter: InterpolationFormatter;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.uppercaseFormatter = void 0;
4
+ const parser_1 = require("../parser");
5
+ exports.uppercaseFormatter = {
6
+ name: "uppercase",
7
+ format: (value) => {
8
+ if (typeof value === "string") {
9
+ return value.toUpperCase();
10
+ }
11
+ return value;
12
+ }
13
+ };
14
+ parser_1.VelcronFormatters.registerFormatter(exports.uppercaseFormatter);
@@ -0,0 +1,9 @@
1
+ export * from "./InterpolationFormatter";
2
+ export * from "./DateFormatter";
3
+ export * from "./CapitalizeFormatter";
4
+ export * from "./UppercaseFormatter";
5
+ export * from "./TrimFormatter";
6
+ export * from "./JsonFormatter";
7
+ export * from "./LengthFormatter";
8
+ export * from "./ReplaceFormatter";
9
+ export * from "./SubStringFormatter";
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./InterpolationFormatter"), exports);
5
+ tslib_1.__exportStar(require("./DateFormatter"), exports);
6
+ tslib_1.__exportStar(require("./CapitalizeFormatter"), exports);
7
+ tslib_1.__exportStar(require("./UppercaseFormatter"), exports);
8
+ tslib_1.__exportStar(require("./TrimFormatter"), exports);
9
+ tslib_1.__exportStar(require("./JsonFormatter"), exports);
10
+ tslib_1.__exportStar(require("./LengthFormatter"), exports);
11
+ tslib_1.__exportStar(require("./ReplaceFormatter"), exports);
12
+ tslib_1.__exportStar(require("./SubStringFormatter"), exports);
package/index.d.ts CHANGED
@@ -7,3 +7,4 @@ export * from "./rules";
7
7
  export * from "./templatebuilder";
8
8
  export * from "./events";
9
9
  export * from "./providers";
10
+ export * from "./formatters";
package/index.js CHANGED
@@ -10,3 +10,4 @@ tslib_1.__exportStar(require("./rules"), exports);
10
10
  tslib_1.__exportStar(require("./templatebuilder"), exports);
11
11
  tslib_1.__exportStar(require("./events"), exports);
12
12
  tslib_1.__exportStar(require("./providers"), exports);
13
+ tslib_1.__exportStar(require("./formatters"), exports);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@omnia/velcron",
3
3
  "license": "MIT",
4
- "version": "8.0.322-dev",
4
+ "version": "8.0.323-dev",
5
5
  "description": "Provide Omnia Velcron Stuffs.",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -1,12 +1,62 @@
1
1
  import { VelcronRenderContext } from "../models";
2
2
  import { VelcronBindableProp } from "..";
3
3
  export declare class VelcronDataBinder {
4
+ /**
5
+ * Binds a value based on the provided binding expression.
6
+ * @param renderContext The render context containing state and other data.
7
+ * @param bindTo The binding expression or value.
8
+ * @returns The bound value after applying formatters and other logic.
9
+ */
4
10
  static bind<T = string>(renderContext: VelcronRenderContext, bindTo: VelcronBindableProp<any>): T;
11
+ /**
12
+ * Interpolates tokens within a binding string and applies formatters.
13
+ * @param bindTo The binding string containing tokens.
14
+ * @param renderContext The render context.
15
+ * @returns The interpolated string with formatters applied.
16
+ */
5
17
  private static interpolateTokens;
18
+ /**
19
+ * Parses an interpolation string to extract the variable and its formatters.
20
+ * @param match The interpolation string, e.g., "{{ variable | formatter1:'arg1','arg2' | formatter2 }}"
21
+ * @returns An Interpolation object or null if parsing fails.
22
+ */
23
+ private static parseInterpolation;
24
+ /**
25
+ * Processes a token that might represent an action or a state variable.
26
+ * @param tokenWithoutBrackets The token string without the surrounding {{ }}.
27
+ * @param renderContext The render context.
28
+ * @returns The result of processing the token.
29
+ */
6
30
  private static processToken;
31
+ /**
32
+ * Evaluates a switch expression based on the render context.
33
+ * @param expression The switch expression object.
34
+ * @param renderContext The render context.
35
+ * @returns The result of the switch expression.
36
+ */
7
37
  private static evaluateSwitchExpression;
38
+ /**
39
+ * Recursively evaluates an expression which can be a string, object, or other types.
40
+ * @param expr The expression to evaluate.
41
+ * @param renderContext The render context.
42
+ * @returns The evaluated result.
43
+ */
8
44
  private static evaluateExpression;
45
+ /**
46
+ * Attempts to update a bound value in the render context.
47
+ * @param renderContext The render context.
48
+ * @param bindPath The binding path string.
49
+ * @param value The new value to set.
50
+ */
9
51
  static tryUpdateBoundValue(renderContext: VelcronRenderContext, bindPath: string, value: unknown): void;
52
+ /**
53
+ * Binds multiple properties at once based on the provided definitions.
54
+ * @param renderContext The render context.
55
+ * @param definition The binding definitions for each property.
56
+ * @param propertiesToBind The list of property keys to bind.
57
+ * @param objectToBindTo The target object where properties will be bound.
58
+ * @returns The object with bound properties.
59
+ */
10
60
  static bindMany<T>(renderContext: VelcronRenderContext, definition: {
11
61
  [P in keyof T]?: VelcronBindableProp<T[P]>;
12
62
  }, propertiesToBind: Array<keyof T>, objectToBindTo: Partial<T>): T;
@@ -8,6 +8,12 @@ const __1 = require("..");
8
8
  // Precompiled regular expression for token replacement
9
9
  const TOKEN_REGEX = /\s*{{\s*|\s*}}\s*/g;
10
10
  class VelcronDataBinder {
11
+ /**
12
+ * Binds a value based on the provided binding expression.
13
+ * @param renderContext The render context containing state and other data.
14
+ * @param bindTo The binding expression or value.
15
+ * @returns The bound value after applying formatters and other logic.
16
+ */
11
17
  static bind(renderContext, bindTo) {
12
18
  if (typeof bindTo === "object" && bindTo !== null) {
13
19
  // Check if it's a switch expression
@@ -40,27 +46,104 @@ class VelcronDataBinder {
40
46
  // Computed String interpolation > {{@getName}}
41
47
  return VelcronDataBinder.interpolateTokens(bindTo, renderContext);
42
48
  }
49
+ /**
50
+ * Interpolates tokens within a binding string and applies formatters.
51
+ * @param bindTo The binding string containing tokens.
52
+ * @param renderContext The render context.
53
+ * @returns The interpolated string with formatters applied.
54
+ */
43
55
  static interpolateTokens(bindTo, renderContext) {
44
- const tokens = VelcronData_1.VelcronData.getTokens(bindTo, false);
45
- if (tokens.length === 0) {
46
- return bindTo;
47
- }
48
- let result = "";
49
- let lastIndex = 0;
50
- tokens.forEach((token) => {
51
- const tokenIndex = bindTo.indexOf(token, lastIndex);
52
- result += bindTo.substring(lastIndex, tokenIndex);
53
- const tokenWithoutBrackets = token.replace(TOKEN_REGEX, "");
54
- let data = this.processToken(tokenWithoutBrackets, renderContext);
55
- if (data instanceof TextValue_1.TextValue) {
56
- data = data.value;
56
+ // Regex to match all interpolations like {{ variable | formatter1:'arg1','arg2' | formatter2 }}
57
+ const interpolationRegex = /{{\s*[^{}]*?}}/g;
58
+ return bindTo.replace(interpolationRegex, (match) => {
59
+ const interpolation = this.parseInterpolation(match);
60
+ if (!interpolation) {
61
+ console.warn(`Failed to parse interpolation: ${match}`);
62
+ return match; // Return as-is if parsing fails
63
+ }
64
+ let value = VelcronData_1.VelcronData.getOrSet(renderContext, interpolation.variable);
65
+ if (value === undefined || value === null) {
66
+ console.warn(`Variable "${interpolation.variable}" is not defined in the context.`);
67
+ return "";
68
+ }
69
+ console.log(`Initial value for "${interpolation.variable}":`, value);
70
+ for (const formatter of interpolation.formatters) {
71
+ const formatterObj = __1.VelcronFormatters.getFormatter(formatter.name);
72
+ if (!formatterObj) {
73
+ console.warn(`Formatter "${formatter.name}" is not registered.`);
74
+ continue; // Skip unknown formatter
75
+ }
76
+ try {
77
+ value = formatterObj.format(value, ...formatter.args);
78
+ console.log(`After formatter "${formatter.name}":`, value);
79
+ }
80
+ catch (error) {
81
+ console.error(`Error applying formatter "${formatter.name}" to variable "${interpolation.variable}":`, error);
82
+ value = ""; // Fallback to empty string on error
83
+ break; // Optionally stop applying further formatters
84
+ }
85
+ }
86
+ if (value instanceof TextValue_1.TextValue) {
87
+ value = value.value;
57
88
  }
58
- result += data;
59
- lastIndex = tokenIndex + token.length;
89
+ return value !== undefined && value !== null ? String(value) : "";
60
90
  });
61
- result += bindTo.substring(lastIndex);
62
- return result;
63
91
  }
92
+ /**
93
+ * Parses an interpolation string to extract the variable and its formatters.
94
+ * @param match The interpolation string, e.g., "{{ variable | formatter1:'arg1','arg2' | formatter2 }}"
95
+ * @returns An Interpolation object or null if parsing fails.
96
+ */
97
+ static parseInterpolation(match) {
98
+ // Adjusted regex to handle variable names with special characters and spaces
99
+ const interpolationRegex = /^{{\s*([^|}]+?)\s*(\|.*)?}}$/;
100
+ const formatterRegex = /\|\s*(\w+)(?:\s*:\s*([^|]+))?/g;
101
+ const mainMatch = interpolationRegex.exec(match);
102
+ if (!mainMatch)
103
+ return null;
104
+ const variable = mainMatch[1].trim();
105
+ const formattersPart = mainMatch[2] || "";
106
+ const formatters = [];
107
+ let formatterMatch;
108
+ while ((formatterMatch = formatterRegex.exec(formattersPart)) !== null) {
109
+ const name = formatterMatch[1];
110
+ const rawArgs = formatterMatch[2] || "";
111
+ const args = [];
112
+ if (rawArgs) {
113
+ // Split arguments by comma and trim spaces
114
+ const argStrings = rawArgs.split(",").map(arg => arg.trim());
115
+ for (const argStr of argStrings) {
116
+ // Detect and convert argument types
117
+ let argValue;
118
+ if (/^'(.*)'$/.test(argStr)) {
119
+ // String argument enclosed in single quotes
120
+ argValue = argStr.slice(1, -1);
121
+ }
122
+ else if (/^\d+(\.\d+)?$/.test(argStr)) {
123
+ // Numeric argument
124
+ argValue = parseFloat(argStr);
125
+ }
126
+ else if (/^(true|false)$/i.test(argStr)) {
127
+ // Boolean argument
128
+ argValue = argStr.toLowerCase() === "true";
129
+ }
130
+ else {
131
+ // Treat as string (unquoted)
132
+ argValue = argStr;
133
+ }
134
+ args.push(argValue);
135
+ }
136
+ }
137
+ formatters.push({ name, args });
138
+ }
139
+ return { variable, formatters };
140
+ }
141
+ /**
142
+ * Processes a token that might represent an action or a state variable.
143
+ * @param tokenWithoutBrackets The token string without the surrounding {{ }}.
144
+ * @param renderContext The render context.
145
+ * @returns The result of processing the token.
146
+ */
64
147
  static processToken(tokenWithoutBrackets, renderContext) {
65
148
  if (__1.VelcronActions.valueIsAction(tokenWithoutBrackets)) {
66
149
  let result;
@@ -94,6 +177,12 @@ class VelcronDataBinder {
94
177
  return VelcronData_1.VelcronData.getOrSet(renderContext, tokenWithoutBrackets);
95
178
  }
96
179
  }
180
+ /**
181
+ * Evaluates a switch expression based on the render context.
182
+ * @param expression The switch expression object.
183
+ * @param renderContext The render context.
184
+ * @returns The result of the switch expression.
185
+ */
97
186
  static evaluateSwitchExpression(expression, renderContext) {
98
187
  // Evaluate the switch expression
99
188
  const switchValue = VelcronDataBinder.evaluateExpression(expression.switch, renderContext);
@@ -104,7 +193,7 @@ class VelcronDataBinder {
104
193
  const caseValue = expression.cases[switchValueStr];
105
194
  if (typeof caseValue === "string") {
106
195
  // If caseValue is a string, interpolate tokens
107
- return VelcronDataBinder.evaluateExpression(this.interpolateTokens(caseValue, renderContext), renderContext);
196
+ return VelcronDataBinder.interpolateTokens(caseValue, renderContext);
108
197
  }
109
198
  else {
110
199
  // If caseValue is an object, evaluate it directly
@@ -115,7 +204,7 @@ class VelcronDataBinder {
115
204
  const defaultValue = expression.default;
116
205
  if (typeof defaultValue === "string") {
117
206
  // If defaultValue is a string, interpolate tokens
118
- return VelcronDataBinder.evaluateExpression(this.interpolateTokens(defaultValue, renderContext), renderContext);
207
+ return VelcronDataBinder.interpolateTokens(defaultValue, renderContext);
119
208
  }
120
209
  else {
121
210
  // If defaultValue is an object, evaluate it directly
@@ -126,11 +215,17 @@ class VelcronDataBinder {
126
215
  return undefined;
127
216
  }
128
217
  }
218
+ /**
219
+ * Recursively evaluates an expression which can be a string, object, or other types.
220
+ * @param expr The expression to evaluate.
221
+ * @param renderContext The render context.
222
+ * @returns The evaluated result.
223
+ */
129
224
  static evaluateExpression(expr, renderContext) {
130
225
  if (typeof expr === "string") {
131
226
  return VelcronDataBinder.bind(renderContext, expr);
132
227
  }
133
- else if (typeof expr === "object") {
228
+ else if (typeof expr === "object" && expr !== null) {
134
229
  // If expr is another switch expression
135
230
  if ("switch" in expr) {
136
231
  return VelcronDataBinder.evaluateSwitchExpression(expr, renderContext);
@@ -151,11 +246,25 @@ class VelcronDataBinder {
151
246
  return expr;
152
247
  }
153
248
  }
249
+ /**
250
+ * Attempts to update a bound value in the render context.
251
+ * @param renderContext The render context.
252
+ * @param bindPath The binding path string.
253
+ * @param value The new value to set.
254
+ */
154
255
  static tryUpdateBoundValue(renderContext, bindPath, value) {
155
256
  if (VelcronData_1.VelcronData.isBindable(bindPath)) {
156
257
  VelcronData_1.VelcronData.getOrSet(renderContext, VelcronData_1.VelcronData.getBindPath(bindPath), value);
157
258
  }
158
259
  }
260
+ /**
261
+ * Binds multiple properties at once based on the provided definitions.
262
+ * @param renderContext The render context.
263
+ * @param definition The binding definitions for each property.
264
+ * @param propertiesToBind The list of property keys to bind.
265
+ * @param objectToBindTo The target object where properties will be bound.
266
+ * @returns The object with bound properties.
267
+ */
159
268
  static bindMany(renderContext, definition, propertiesToBind, objectToBindTo) {
160
269
  propertiesToBind.forEach((property) => {
161
270
  const definitionValue = definition[property];
@@ -167,4 +276,5 @@ class VelcronDataBinder {
167
276
  }
168
277
  }
169
278
  exports.VelcronDataBinder = VelcronDataBinder;
279
+ // Ensure the internal binding method uses the updated binder
170
280
  VelcronData_1.VelcronData.bindInternal = VelcronDataBinder.bind;
@@ -0,0 +1,6 @@
1
+ import { InterpolationFormatter } from "../formatters";
2
+ export declare class VelcronFormatters {
3
+ static _formatters: Record<string, InterpolationFormatter>;
4
+ static registerFormatter(formatter: InterpolationFormatter): void;
5
+ static getFormatter(name: string): InterpolationFormatter | undefined;
6
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VelcronFormatters = void 0;
4
+ const VelcronLogger_1 = require("./VelcronLogger");
5
+ class VelcronFormatters {
6
+ static { this._formatters = {}; }
7
+ static registerFormatter(formatter) {
8
+ const name = formatter.name.toLowerCase();
9
+ if (this._formatters && this._formatters[name]) {
10
+ VelcronLogger_1.VelcronLogger.logActionError(`The action handler with name ${name} is already registered`);
11
+ }
12
+ else if (this._formatters) {
13
+ this._formatters[name] = formatter;
14
+ }
15
+ }
16
+ static getFormatter(name) {
17
+ return this._formatters[name.toLowerCase()];
18
+ }
19
+ }
20
+ exports.VelcronFormatters = VelcronFormatters;
package/parser/index.d.ts CHANGED
@@ -7,3 +7,4 @@ export * from "./VelcronRenderers";
7
7
  export * from "./TextValue";
8
8
  export * from "./VelcronPropertyEditors";
9
9
  export * from "./VelcronDataBinder";
10
+ export * from "./VelcronFormatters";
package/parser/index.js CHANGED
@@ -10,3 +10,4 @@ tslib_1.__exportStar(require("./VelcronRenderers"), exports);
10
10
  tslib_1.__exportStar(require("./TextValue"), exports);
11
11
  tslib_1.__exportStar(require("./VelcronPropertyEditors"), exports);
12
12
  tslib_1.__exportStar(require("./VelcronDataBinder"), exports);
13
+ tslib_1.__exportStar(require("./VelcronFormatters"), exports);