@peter.naydenov/morph 3.1.3 → 3.1.5
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.
- package/Changelog.md +10 -0
- package/dist/main.d.ts +100 -0
- package/dist/methods/_actionSupply.d.ts +18 -0
- package/dist/methods/_chopTemplates.d.ts +22 -0
- package/dist/methods/_defineData.d.ts +25 -0
- package/dist/methods/_defineType.d.ts +15 -0
- package/dist/methods/_readTemplate.d.ts +24 -0
- package/dist/methods/_renderHolder.d.ts +17 -0
- package/dist/methods/_setupActions.d.ts +19 -0
- package/dist/methods/build.d.ts +35 -0
- package/dist/methods/render.d.ts +25 -0
- package/dist/methods/settings.d.ts +7 -0
- package/package.json +11 -9
- package/src/main.js +70 -32
- package/src/methods/_actionSupply.js +16 -0
- package/src/methods/_chopTemplates.js +22 -1
- package/src/methods/_defineData.js +33 -1
- package/src/methods/_defineType.js +13 -0
- package/src/methods/_readTemplate.js +24 -0
- package/src/methods/_renderHolder.js +15 -0
- package/src/methods/_setupActions.js +17 -0
- package/src/methods/render.js +25 -7
- package/src/methods/settings.js +11 -0
- package/tsconfig.json +27 -0
- package/types/index.d.ts +0 -60
package/Changelog.md
CHANGED
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export default morphAPI;
|
|
2
|
+
declare namespace morphAPI {
|
|
3
|
+
export { build };
|
|
4
|
+
export { get };
|
|
5
|
+
export { add };
|
|
6
|
+
export { list };
|
|
7
|
+
export { clear };
|
|
8
|
+
export { remove };
|
|
9
|
+
}
|
|
10
|
+
import build from "./methods/build.js";
|
|
11
|
+
/**
|
|
12
|
+
* Retrieves a template from storage.
|
|
13
|
+
*
|
|
14
|
+
* @param {string[]} location - The location of the template. Array of two elements:
|
|
15
|
+
* - First element: The name of the template
|
|
16
|
+
* - Second element (optional): The name of the storage. Defaults to 'default'
|
|
17
|
+
*
|
|
18
|
+
* @returns {Function} The template (render function) if found, or an error function that returns
|
|
19
|
+
* an error message if the storage or template doesn't exist.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Get template from default storage
|
|
23
|
+
* const template = get(['myTemplate']);
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Get template from custom storage
|
|
27
|
+
* const template = get(['myTemplate', 'customStorage']);
|
|
28
|
+
*/
|
|
29
|
+
declare function get(location: string[]): Function;
|
|
30
|
+
/**
|
|
31
|
+
* Adds a template to storage.
|
|
32
|
+
*
|
|
33
|
+
* If the template is already a function, it's added directly to storage.
|
|
34
|
+
* If it's a template description object, it's built first and then added.
|
|
35
|
+
* If the template is null or broken, a warning/error is logged and it's not added.
|
|
36
|
+
*
|
|
37
|
+
* @param {string[]} location - The location to add the template to. Array of two elements:
|
|
38
|
+
* - First element: The name of the template
|
|
39
|
+
* - Second element (optional): The name of the storage. Defaults to 'default'
|
|
40
|
+
* @param {object|function|null} tplfn - The template description object, pre-built template function, or null
|
|
41
|
+
* @param {...any} args - Additional arguments passed to the build function (only used when tplfn is a template description)
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // Add a pre-built template function
|
|
45
|
+
* add(['myTemplate'], templateFunction);
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Add and build a template description
|
|
49
|
+
* add(['myTemplate'], {
|
|
50
|
+
* template: 'Hello {{name}}!',
|
|
51
|
+
* helpers: { name: (data) => data.data.name }
|
|
52
|
+
* });
|
|
53
|
+
*/
|
|
54
|
+
declare function add(location: string[], tplfn: object | Function | null, ...args: any[]): void;
|
|
55
|
+
/**
|
|
56
|
+
* Returns an array of template names from specified storages.
|
|
57
|
+
*
|
|
58
|
+
* @param {string[]} [storageNames=['default']] - Array of storage names to retrieve template names from.
|
|
59
|
+
* Defaults to ['default'] if not provided.
|
|
60
|
+
*
|
|
61
|
+
* @returns {string[]} Array of all template names from the specified storages.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // List templates from default storage
|
|
65
|
+
* const templates = list();
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // List templates from multiple storages
|
|
69
|
+
* const templates = list(['default', 'customStorage']);
|
|
70
|
+
*/
|
|
71
|
+
declare function list(storageNames?: string[]): string[];
|
|
72
|
+
/**
|
|
73
|
+
* Clears all templates from all storages.
|
|
74
|
+
*
|
|
75
|
+
* Deletes all custom storages and resets the 'default' storage to an empty object.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Clear all templates
|
|
79
|
+
* clear();
|
|
80
|
+
*/
|
|
81
|
+
declare function clear(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Removes a template from storage.
|
|
84
|
+
*
|
|
85
|
+
* @param {string[]} location - The location of the template to remove. Array of two elements:
|
|
86
|
+
* - First element: The name of the template
|
|
87
|
+
* - Second element (optional): The name of the storage. Defaults to 'default'
|
|
88
|
+
*
|
|
89
|
+
* @returns {void|string} Returns an error message if the storage or template doesn't exist,
|
|
90
|
+
* otherwise returns undefined.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Remove template from default storage
|
|
94
|
+
* remove(['myTemplate']);
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* // Remove template from custom storage
|
|
98
|
+
* remove(['myTemplate', 'customStorage']);
|
|
99
|
+
*/
|
|
100
|
+
declare function remove(location: string[]): void | string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default _actionSupply;
|
|
2
|
+
/**
|
|
3
|
+
* Generator function that supplies actions in a controlled sequence using a stack.
|
|
4
|
+
*
|
|
5
|
+
* Manages the flow of actions through different processing levels, allowing for
|
|
6
|
+
* dynamic action insertion during processing.
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} act - Object containing action arrays organized by level
|
|
9
|
+
* @param {number} level - Maximum processing level
|
|
10
|
+
* @returns {Generator} Generator that yields action objects in sequence
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const generator = _actionSupply(actionSetup, 2);
|
|
14
|
+
* for (const action of generator) {
|
|
15
|
+
* // Process each action
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
declare function _actionSupply(act: any, level: number): Generator;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export default _chopTemplate;
|
|
2
|
+
/**
|
|
3
|
+
* Creates a template chopping function that splits text into parts and placeholders.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} settings - Configuration object containing template delimiters
|
|
6
|
+
* @param {string} settings.TG_PRX - Opening delimiter (e.g., '{{')
|
|
7
|
+
* @param {string} settings.TG_SFX - Closing delimiter (e.g., '}}')
|
|
8
|
+
* @param {number} settings.TG_SIZE_P - Length of opening delimiter
|
|
9
|
+
* @param {number} settings.TG_SIZE_S - Length of closing delimiter
|
|
10
|
+
*
|
|
11
|
+
* @returns {Function} Function that chops template text into array parts
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const chop = _chopTemplate(settings);
|
|
15
|
+
* const result = chop('Hello {{name}}!');
|
|
16
|
+
*/
|
|
17
|
+
declare function _chopTemplate(settings: {
|
|
18
|
+
TG_PRX: string;
|
|
19
|
+
TG_SFX: string;
|
|
20
|
+
TG_SIZE_P: number;
|
|
21
|
+
TG_SIZE_S: number;
|
|
22
|
+
}): Function;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default _defineData;
|
|
2
|
+
/**
|
|
3
|
+
* Processes data source based on action requirements and creates nested data structure.
|
|
4
|
+
*
|
|
5
|
+
* Analyzes the data source and action to determine if nested data processing is needed.
|
|
6
|
+
* If action contains '#', it walks through the data structure to collect nested objects.
|
|
7
|
+
*
|
|
8
|
+
* @param {any} dSource - The data source to process (function, null, string, or object)
|
|
9
|
+
* @param {string} action - Action string that may contain '#' indicating nested processing
|
|
10
|
+
*
|
|
11
|
+
* @returns {object} Data processing result containing:
|
|
12
|
+
* - dataDeepLevel: Maximum nesting level found
|
|
13
|
+
* - nestedData: Array of nested data arrays organized by level
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Simple data without nesting
|
|
17
|
+
* const result = _defineData('hello', 'render');
|
|
18
|
+
* // Returns: { dataDeepLevel: 0, nestedData: [['hello']] }
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Nested data with '#' action
|
|
22
|
+
* const result = _defineData({ user: { name: 'John' } }, 'render:#');
|
|
23
|
+
* // Returns: { dataDeepLevel: 1, nestedData: [[{ name: 'John' }]] }
|
|
24
|
+
*/
|
|
25
|
+
declare function _defineData(dSource: any, action: string): object;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default _defineDataType;
|
|
2
|
+
/**
|
|
3
|
+
* Determines the data type of a value for template processing.
|
|
4
|
+
*
|
|
5
|
+
* @param {any} data - Value to type-check
|
|
6
|
+
* @returns {string|undefined} Returns one of: 'null', 'primitive', 'function', 'array', 'object', or undefined
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* _defineDataType(null); // 'null'
|
|
10
|
+
* _defineDataType('hello'); // 'primitive'
|
|
11
|
+
* _defineDataType([1,2,3]); // 'array'
|
|
12
|
+
* _defineDataType({}); // 'object'
|
|
13
|
+
* _defineDataType(() => {}); // 'function'
|
|
14
|
+
*/
|
|
15
|
+
declare function _defineDataType(data: any): string | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default _readTemplate;
|
|
2
|
+
/**
|
|
3
|
+
* Parses and validates a template description object.
|
|
4
|
+
*
|
|
5
|
+
* Extracts placeholders, validates helpers, and prepares template for building.
|
|
6
|
+
*
|
|
7
|
+
* @param {object} tpl - Template description object
|
|
8
|
+
* @param {string} tpl.template - Template string with placeholders
|
|
9
|
+
* @param {object} [tpl.helpers={}] - Optional helper functions
|
|
10
|
+
* @param {object} [tpl.handshake] - Optional example data
|
|
11
|
+
*
|
|
12
|
+
* @returns {object} Template parsing result containing:
|
|
13
|
+
* - hasError: Error message or null
|
|
14
|
+
* - placeholders: Array of placeholder objects
|
|
15
|
+
* - chop: Array of template parts
|
|
16
|
+
* - helpers: Helper functions object
|
|
17
|
+
* - handshake: Example data object
|
|
18
|
+
* - snippets: Object mapping snippet names to placeholders
|
|
19
|
+
*/
|
|
20
|
+
declare function _readTemplate(tpl: {
|
|
21
|
+
template: string;
|
|
22
|
+
helpers?: object;
|
|
23
|
+
handshake?: object;
|
|
24
|
+
}): object;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default _renderHolder;
|
|
2
|
+
/**
|
|
3
|
+
* Renders a simple template by replacing placeholders with data values.
|
|
4
|
+
*
|
|
5
|
+
* Processes templates with basic placeholder substitution without actions or helpers.
|
|
6
|
+
* Only supports direct field replacement from the data object.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} template - Template string with placeholders
|
|
9
|
+
* @param {object} data - Data object containing values for placeholder replacement
|
|
10
|
+
*
|
|
11
|
+
* @returns {string|null} Rendered template string or null if data is null
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const result = _renderHolder('Hello {{name}}!', { name: 'World' });
|
|
15
|
+
* // Returns: 'Hello World!'
|
|
16
|
+
*/
|
|
17
|
+
declare function _renderHolder(template: string, data: object): string | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default _setupActions;
|
|
2
|
+
/**
|
|
3
|
+
* Parses and organizes template actions into a structured setup by processing level.
|
|
4
|
+
*
|
|
5
|
+
* Converts action strings into structured objects with types and levels. Validates that
|
|
6
|
+
* there are enough level markers (#) for the data depth.
|
|
7
|
+
*
|
|
8
|
+
* @param {string[]} actions - Array of action strings to process
|
|
9
|
+
* @param {number} [dataDeepLevel=10] - Maximum depth level for nested data processing
|
|
10
|
+
*
|
|
11
|
+
* @returns {Object} Object with numeric keys containing arrays of action objects by level
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const setup = _setupActions(['render', '#', 'save:var'], 2);
|
|
15
|
+
* // Returns: { 0: [{type: 'render', name: 'render', level: 0}],
|
|
16
|
+
* // 1: [{type: 'save', name: 'var', level: 1}],
|
|
17
|
+
* // 2: [] }
|
|
18
|
+
*/
|
|
19
|
+
declare function _setupActions(actions: string[], dataDeepLevel?: number): any;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export default build;
|
|
2
|
+
export type Template = {
|
|
3
|
+
/**
|
|
4
|
+
* - Data to be rendered;
|
|
5
|
+
*/
|
|
6
|
+
template: string;
|
|
7
|
+
/**
|
|
8
|
+
* - Optional. Object with helper functions or simple templates for this template;
|
|
9
|
+
*/
|
|
10
|
+
helpers?: object;
|
|
11
|
+
/**
|
|
12
|
+
* - Optional. Example for data to be rendered with;
|
|
13
|
+
*/
|
|
14
|
+
handshake?: object;
|
|
15
|
+
};
|
|
16
|
+
export type tupleResult = any[];
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} Template
|
|
19
|
+
* @property {string} template - Data to be rendered;
|
|
20
|
+
* @property {object} [helpers] - Optional. Object with helper functions or simple templates for this template;
|
|
21
|
+
* @property {object} [handshake] - Optional. Example for data to be rendered with;
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {Array} tupleResult
|
|
25
|
+
* @property {boolean} 0 - Indicates success (true) or failure (false).
|
|
26
|
+
* @property {function} 1 - The rendering function or an error function.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param {Template} tpl - template definition;
|
|
31
|
+
* @param {boolean} [extra] - Optional. How to receive the answer - false:as a string(answer) or true: as tuple[success, answer];
|
|
32
|
+
* @param {object} [buildDependencies] - Optional. External dependencies injected;
|
|
33
|
+
* @returns {function|tupleResult} - rendering function
|
|
34
|
+
*/
|
|
35
|
+
declare function build(tpl: Template, extra?: boolean, buildDependencies?: object): Function | tupleResult;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default render;
|
|
2
|
+
/**
|
|
3
|
+
* Executes rendering and returns the rendered result.
|
|
4
|
+
*
|
|
5
|
+
* Handles both function-based and template-based rendering. Normalizes data objects
|
|
6
|
+
* by converting nested objects to their 'text' properties and arrays to their first elements.
|
|
7
|
+
*
|
|
8
|
+
* @param {object|string} theData - Data to be rendered. If string, becomes the 'text' property value.
|
|
9
|
+
* @param {string} name - Name of the render helper/template to execute
|
|
10
|
+
* @param {object} helpers - Object containing helper functions and templates
|
|
11
|
+
* @param {object} original - Original data context for full data access
|
|
12
|
+
* @param {object} dependencies - External dependencies available to helpers
|
|
13
|
+
* @param {...any} args - Additional arguments passed to the render function
|
|
14
|
+
*
|
|
15
|
+
* @returns {string} Rendered string result
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Render with function helper
|
|
19
|
+
* const result = render(data, 'myHelper', helpers, originalData, deps);
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Render with template
|
|
23
|
+
* const result = render(data, 'myTemplate', helpers, originalData, deps);
|
|
24
|
+
*/
|
|
25
|
+
declare function render(theData: object | string, name: string, helpers: object, original: object, dependencies: object, ...args: any[]): string;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/morph",
|
|
3
3
|
"description": "Template engine",
|
|
4
|
-
"version": "3.1.
|
|
4
|
+
"version": "3.1.5",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Peter Naydenov",
|
|
7
7
|
"main": "./src/main.js",
|
|
8
8
|
"type": "module",
|
|
9
|
-
"types": "./
|
|
9
|
+
"types": "./dist/main.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"import": "./src/main.js",
|
|
@@ -20,20 +20,22 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"test": "mocha test",
|
|
22
22
|
"cover": "c8 mocha",
|
|
23
|
-
"build": "rollup -c"
|
|
23
|
+
"build": "npm run build:types && rollup -c",
|
|
24
|
+
"build:types": "tsc"
|
|
24
25
|
},
|
|
25
26
|
"dependencies": {
|
|
26
27
|
"@peter.naydenov/stack": "^3.0.0",
|
|
27
|
-
"@peter.naydenov/walk": "^5.0.
|
|
28
|
+
"@peter.naydenov/walk": "^5.0.2"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
|
-
"@rollup/plugin-commonjs": "^
|
|
31
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
31
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
32
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
32
33
|
"@rollup/plugin-terser": "^0.4.4",
|
|
33
34
|
"c8": "^10.1.3",
|
|
34
|
-
"chai": "
|
|
35
|
-
"mocha": "11.7.
|
|
36
|
-
"rollup": "^4.
|
|
35
|
+
"chai": "6.2.1",
|
|
36
|
+
"mocha": "11.7.5",
|
|
37
|
+
"rollup": "^4.53.2",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
37
39
|
},
|
|
38
40
|
"repository": {
|
|
39
41
|
"type": "git",
|
package/src/main.js
CHANGED
|
@@ -24,15 +24,22 @@ const storage = ( () => ({default: {}}) ) ();
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Retrieves a template from storage.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* @param {string[]} location - The location of the template. Array of two elements:
|
|
30
|
+
* - First element: The name of the template
|
|
31
|
+
* - Second element (optional): The name of the storage. Defaults to 'default'
|
|
32
32
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* @returns {Function} The template (render function) if found, or an error function that returns
|
|
34
|
+
* an error message if the storage or template doesn't exist.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Get template from default storage
|
|
38
|
+
* const template = get(['myTemplate']);
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // Get template from custom storage
|
|
42
|
+
* const template = get(['myTemplate', 'customStorage']);
|
|
36
43
|
*/
|
|
37
44
|
function get ( location ) {
|
|
38
45
|
if ( !(location instanceof Array) ) {
|
|
@@ -61,20 +68,28 @@ function get ( location ) {
|
|
|
61
68
|
|
|
62
69
|
|
|
63
70
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
71
|
+
* Adds a template to storage.
|
|
72
|
+
*
|
|
73
|
+
* If the template is already a function, it's added directly to storage.
|
|
74
|
+
* If it's a template description object, it's built first and then added.
|
|
75
|
+
* If the template is null or broken, a warning/error is logged and it's not added.
|
|
76
|
+
*
|
|
77
|
+
* @param {string[]} location - The location to add the template to. Array of two elements:
|
|
78
|
+
* - First element: The name of the template
|
|
79
|
+
* - Second element (optional): The name of the storage. Defaults to 'default'
|
|
80
|
+
* @param {object|function|null} tplfn - The template description object, pre-built template function, or null
|
|
81
|
+
* @param {...any} args - Additional arguments passed to the build function (only used when tplfn is a template description)
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* // Add a pre-built template function
|
|
85
|
+
* add(['myTemplate'], templateFunction);
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Add and build a template description
|
|
89
|
+
* add(['myTemplate'], {
|
|
90
|
+
* template: 'Hello {{name}}!',
|
|
91
|
+
* helpers: { name: (data) => data.data.name }
|
|
92
|
+
* });
|
|
78
93
|
*/
|
|
79
94
|
function add ( location, tplfn, ...args ) {
|
|
80
95
|
const [ name, strName='default'] = location
|
|
@@ -98,11 +113,20 @@ function add ( location, tplfn, ...args ) {
|
|
|
98
113
|
|
|
99
114
|
|
|
100
115
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
116
|
+
* Returns an array of template names from specified storages.
|
|
117
|
+
*
|
|
118
|
+
* @param {string[]} [storageNames=['default']] - Array of storage names to retrieve template names from.
|
|
119
|
+
* Defaults to ['default'] if not provided.
|
|
103
120
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
121
|
+
* @returns {string[]} Array of all template names from the specified storages.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* // List templates from default storage
|
|
125
|
+
* const templates = list();
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* // List templates from multiple storages
|
|
129
|
+
* const templates = list(['default', 'customStorage']);
|
|
106
130
|
*/
|
|
107
131
|
function list ( storageNames=['default'] ) {
|
|
108
132
|
let r = storageNames.map ( strName => {
|
|
@@ -115,8 +139,13 @@ function list ( storageNames=['default'] ) {
|
|
|
115
139
|
|
|
116
140
|
|
|
117
141
|
/**
|
|
118
|
-
* Clears all templates from
|
|
119
|
-
*
|
|
142
|
+
* Clears all templates from all storages.
|
|
143
|
+
*
|
|
144
|
+
* Deletes all custom storages and resets the 'default' storage to an empty object.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* // Clear all templates
|
|
148
|
+
* clear();
|
|
120
149
|
*/
|
|
121
150
|
function clear ( ) {
|
|
122
151
|
const keys = Object.keys ( storage )
|
|
@@ -130,13 +159,22 @@ function clear ( ) {
|
|
|
130
159
|
|
|
131
160
|
|
|
132
161
|
/**
|
|
133
|
-
*
|
|
162
|
+
* Removes a template from storage.
|
|
163
|
+
*
|
|
164
|
+
* @param {string[]} location - The location of the template to remove. Array of two elements:
|
|
165
|
+
* - First element: The name of the template
|
|
166
|
+
* - Second element (optional): The name of the storage. Defaults to 'default'
|
|
167
|
+
*
|
|
168
|
+
* @returns {void|string} Returns an error message if the storage or template doesn't exist,
|
|
169
|
+
* otherwise returns undefined.
|
|
134
170
|
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
171
|
+
* @example
|
|
172
|
+
* // Remove template from default storage
|
|
173
|
+
* remove(['myTemplate']);
|
|
138
174
|
*
|
|
139
|
-
*
|
|
175
|
+
* @example
|
|
176
|
+
* // Remove template from custom storage
|
|
177
|
+
* remove(['myTemplate', 'customStorage']);
|
|
140
178
|
*/
|
|
141
179
|
function remove ( location ) {
|
|
142
180
|
const [name, strName='default'] = location;
|
|
@@ -2,6 +2,22 @@ import stack from "@peter.naydenov/stack"
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Generator function that supplies actions in a controlled sequence using a stack.
|
|
7
|
+
*
|
|
8
|
+
* Manages the flow of actions through different processing levels, allowing for
|
|
9
|
+
* dynamic action insertion during processing.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} act - Object containing action arrays organized by level
|
|
12
|
+
* @param {number} level - Maximum processing level
|
|
13
|
+
* @returns {Generator} Generator that yields action objects in sequence
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const generator = _actionSupply(actionSetup, 2);
|
|
17
|
+
* for (const action of generator) {
|
|
18
|
+
* // Process each action
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
5
21
|
function* _actionSupply ( act, level ) {
|
|
6
22
|
let action = stack ({ type:'LIFO' });
|
|
7
23
|
for ( let i=0; i<=level; i++ ) {
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a template chopping function that splits text into parts and placeholders.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} settings - Configuration object containing template delimiters
|
|
5
|
+
* @param {string} settings.TG_PRX - Opening delimiter (e.g., '{{')
|
|
6
|
+
* @param {string} settings.TG_SFX - Closing delimiter (e.g., '}}')
|
|
7
|
+
* @param {number} settings.TG_SIZE_P - Length of opening delimiter
|
|
8
|
+
* @param {number} settings.TG_SIZE_S - Length of closing delimiter
|
|
9
|
+
*
|
|
10
|
+
* @returns {Function} Function that chops template text into array parts
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const chop = _chopTemplate(settings);
|
|
14
|
+
* const result = chop('Hello {{name}}!');
|
|
15
|
+
*/
|
|
1
16
|
function _chopTemplate ( settings ) {
|
|
2
17
|
return function _chopTemplate ( text ) {
|
|
3
18
|
const { TG_PRX, TG_SFX, TG_SIZE_P, TG_SIZE_S } = settings;
|
|
@@ -38,7 +53,13 @@ function _chopTemplate ( settings ) {
|
|
|
38
53
|
|
|
39
54
|
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Returns error messages for template parsing failures.
|
|
58
|
+
*
|
|
59
|
+
* @param {string} type - Error type identifier
|
|
60
|
+
* @returns {string} Human-readable error message
|
|
61
|
+
*/
|
|
62
|
+
function showError (type) {
|
|
42
63
|
switch (type) {
|
|
43
64
|
case 'notAString':
|
|
44
65
|
return `Error: Template is not a string.`
|
|
@@ -2,6 +2,29 @@ import walk from '@peter.naydenov/walk'
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Processes data source based on action requirements and creates nested data structure.
|
|
7
|
+
*
|
|
8
|
+
* Analyzes the data source and action to determine if nested data processing is needed.
|
|
9
|
+
* If action contains '#', it walks through the data structure to collect nested objects.
|
|
10
|
+
*
|
|
11
|
+
* @param {any} dSource - The data source to process (function, null, string, or object)
|
|
12
|
+
* @param {string} action - Action string that may contain '#' indicating nested processing
|
|
13
|
+
*
|
|
14
|
+
* @returns {object} Data processing result containing:
|
|
15
|
+
* - dataDeepLevel: Maximum nesting level found
|
|
16
|
+
* - nestedData: Array of nested data arrays organized by level
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Simple data without nesting
|
|
20
|
+
* const result = _defineData('hello', 'render');
|
|
21
|
+
* // Returns: { dataDeepLevel: 0, nestedData: [['hello']] }
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Nested data with '#' action
|
|
25
|
+
* const result = _defineData({ user: { name: 'John' } }, 'render:#');
|
|
26
|
+
* // Returns: { dataDeepLevel: 1, nestedData: [[{ name: 'John' }]] }
|
|
27
|
+
*/
|
|
5
28
|
function _defineData ( dSource, action ) {
|
|
6
29
|
const nestedData = [];
|
|
7
30
|
let dataDeepLevel = 0;
|
|
@@ -18,7 +41,16 @@ function _defineData ( dSource, action ) {
|
|
|
18
41
|
return { dataDeepLevel:0, nestedData }
|
|
19
42
|
}
|
|
20
43
|
|
|
21
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Callback function for walking through data structure to collect nested objects.
|
|
46
|
+
*
|
|
47
|
+
* @param {object} params - Walk parameters
|
|
48
|
+
* @param {string} params.key - Current key being processed
|
|
49
|
+
* @param {any} params.value - Current value being processed
|
|
50
|
+
* @param {string} params.breadcrumbs - Path to current value as breadcrumb string
|
|
51
|
+
* @returns {any} Returns the value unchanged
|
|
52
|
+
*/
|
|
53
|
+
function findObjects ({key, value, breadcrumbs}) {
|
|
22
54
|
if ( key === breadcrumbs ) {
|
|
23
55
|
nestedData[0] = [ value ]
|
|
24
56
|
return value
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines the data type of a value for template processing.
|
|
3
|
+
*
|
|
4
|
+
* @param {any} data - Value to type-check
|
|
5
|
+
* @returns {string|undefined} Returns one of: 'null', 'primitive', 'function', 'array', 'object', or undefined
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* _defineDataType(null); // 'null'
|
|
9
|
+
* _defineDataType('hello'); // 'primitive'
|
|
10
|
+
* _defineDataType([1,2,3]); // 'array'
|
|
11
|
+
* _defineDataType({}); // 'object'
|
|
12
|
+
* _defineDataType(() => {}); // 'function'
|
|
13
|
+
*/
|
|
1
14
|
function _defineDataType ( data ) {
|
|
2
15
|
|
|
3
16
|
if ( data == null ) return 'null'
|
|
@@ -3,12 +3,36 @@ import _chopTemplate from "./_chopTemplates.js"
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes field data by returning null for falsy values.
|
|
8
|
+
*
|
|
9
|
+
* @param {any} field - Field value to normalize
|
|
10
|
+
* @returns {any|null} Returns the field if truthy, null otherwise
|
|
11
|
+
*/
|
|
6
12
|
function readData ( field ) {
|
|
7
13
|
return field ? field : null
|
|
8
14
|
} // readData func.
|
|
9
15
|
|
|
10
16
|
|
|
11
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Parses and validates a template description object.
|
|
20
|
+
*
|
|
21
|
+
* Extracts placeholders, validates helpers, and prepares template for building.
|
|
22
|
+
*
|
|
23
|
+
* @param {object} tpl - Template description object
|
|
24
|
+
* @param {string} tpl.template - Template string with placeholders
|
|
25
|
+
* @param {object} [tpl.helpers={}] - Optional helper functions
|
|
26
|
+
* @param {object} [tpl.handshake] - Optional example data
|
|
27
|
+
*
|
|
28
|
+
* @returns {object} Template parsing result containing:
|
|
29
|
+
* - hasError: Error message or null
|
|
30
|
+
* - placeholders: Array of placeholder objects
|
|
31
|
+
* - chop: Array of template parts
|
|
32
|
+
* - helpers: Helper functions object
|
|
33
|
+
* - handshake: Example data object
|
|
34
|
+
* - snippets: Object mapping snippet names to placeholders
|
|
35
|
+
*/
|
|
12
36
|
function _readTemplate ( tpl ) {
|
|
13
37
|
const
|
|
14
38
|
{ template, helpers={}, handshake } = tpl
|
|
@@ -3,6 +3,21 @@ import settings from './settings.js'
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Renders a simple template by replacing placeholders with data values.
|
|
8
|
+
*
|
|
9
|
+
* Processes templates with basic placeholder substitution without actions or helpers.
|
|
10
|
+
* Only supports direct field replacement from the data object.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} template - Template string with placeholders
|
|
13
|
+
* @param {object} data - Data object containing values for placeholder replacement
|
|
14
|
+
*
|
|
15
|
+
* @returns {string|null} Rendered template string or null if data is null
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const result = _renderHolder('Hello {{name}}!', { name: 'World' });
|
|
19
|
+
* // Returns: 'Hello World!'
|
|
20
|
+
*/
|
|
6
21
|
function _renderHolder ( template, data ) {
|
|
7
22
|
// Data should be an object. No array, no string.
|
|
8
23
|
if ( data == null ) return null
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses and organizes template actions into a structured setup by processing level.
|
|
3
|
+
*
|
|
4
|
+
* Converts action strings into structured objects with types and levels. Validates that
|
|
5
|
+
* there are enough level markers (#) for the data depth.
|
|
6
|
+
*
|
|
7
|
+
* @param {string[]} actions - Array of action strings to process
|
|
8
|
+
* @param {number} [dataDeepLevel=10] - Maximum depth level for nested data processing
|
|
9
|
+
*
|
|
10
|
+
* @returns {Object} Object with numeric keys containing arrays of action objects by level
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const setup = _setupActions(['render', '#', 'save:var'], 2);
|
|
14
|
+
* // Returns: { 0: [{type: 'render', name: 'render', level: 0}],
|
|
15
|
+
* // 1: [{type: 'save', name: 'var', level: 1}],
|
|
16
|
+
* // 2: [] }
|
|
17
|
+
*/
|
|
1
18
|
function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
2
19
|
let
|
|
3
20
|
actSetup = {}
|
package/src/methods/render.js
CHANGED
|
@@ -3,15 +3,27 @@ import _renderHolder from "./_renderHolder.js"
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
+
* Executes rendering and returns the rendered result.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
+
* Handles both function-based and template-based rendering. Normalizes data objects
|
|
9
|
+
* by converting nested objects to their 'text' properties and arrays to their first elements.
|
|
8
10
|
*
|
|
9
|
-
* @param {object|string} theData - Data to be rendered. If
|
|
10
|
-
* @param {string} name - Name of the render to
|
|
11
|
-
* @param {object} helpers - Object
|
|
12
|
-
* @param {
|
|
11
|
+
* @param {object|string} theData - Data to be rendered. If string, becomes the 'text' property value.
|
|
12
|
+
* @param {string} name - Name of the render helper/template to execute
|
|
13
|
+
* @param {object} helpers - Object containing helper functions and templates
|
|
14
|
+
* @param {object} original - Original data context for full data access
|
|
15
|
+
* @param {object} dependencies - External dependencies available to helpers
|
|
16
|
+
* @param {...any} args - Additional arguments passed to the render function
|
|
13
17
|
*
|
|
14
|
-
* @returns {string}
|
|
18
|
+
* @returns {string} Rendered string result
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Render with function helper
|
|
22
|
+
* const result = render(data, 'myHelper', helpers, originalData, deps);
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Render with template
|
|
26
|
+
* const result = render(data, 'myTemplate', helpers, originalData, deps);
|
|
15
27
|
*/
|
|
16
28
|
function render ( theData, name, helpers, original, dependencies, ...args ) {
|
|
17
29
|
// *** Executes rendering and return the results
|
|
@@ -21,7 +33,13 @@ function render ( theData, name, helpers, original, dependencies, ...args ) {
|
|
|
21
33
|
if ( value instanceof Array ) theData[key] = value[0]
|
|
22
34
|
})
|
|
23
35
|
}
|
|
24
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Normalizes render data by wrapping strings in text objects.
|
|
38
|
+
*
|
|
39
|
+
* @param {any} d - Data to normalize
|
|
40
|
+
* @returns {object} Returns { text: d } if d is string, otherwise returns d unchanged
|
|
41
|
+
*/
|
|
42
|
+
function setRenderData ( d={} ) {
|
|
25
43
|
if ( typeof d === 'string' ) return { text: d }
|
|
26
44
|
else return d
|
|
27
45
|
} // setRenderData func.
|
package/src/methods/settings.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template engine configuration settings.
|
|
3
|
+
*
|
|
4
|
+
* Defines the delimiters and sizes used for template placeholder parsing.
|
|
5
|
+
*
|
|
6
|
+
* @type {Object}
|
|
7
|
+
* @property {string} TG_PRX - Opening tag prefix for placeholders ('{{')
|
|
8
|
+
* @property {string} TG_SFX - Closing tag suffix for placeholders ('}}')
|
|
9
|
+
* @property {number} TG_SIZE_P - Length of opening tag prefix (2)
|
|
10
|
+
* @property {number} TG_SIZE_S - Length of closing tag suffix (2)
|
|
11
|
+
*/
|
|
1
12
|
export default {
|
|
2
13
|
TG_PRX: '{{'
|
|
3
14
|
, TG_SFX: '}}'
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"emitDeclarationOnly": true,
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"target": "ES2020",
|
|
10
|
+
"lib": ["ES2020"],
|
|
11
|
+
"strict": false,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"esModuleInterop": true,
|
|
15
|
+
"allowSyntheticDefaultImports": true,
|
|
16
|
+
"resolveJsonModule": true
|
|
17
|
+
},
|
|
18
|
+
"include": [
|
|
19
|
+
"src/**/*"
|
|
20
|
+
],
|
|
21
|
+
"exclude": [
|
|
22
|
+
"node_modules",
|
|
23
|
+
"dist",
|
|
24
|
+
"test",
|
|
25
|
+
"types"
|
|
26
|
+
]
|
|
27
|
+
}
|
package/types/index.d.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
declare module '@peter.naydenov/morph' {
|
|
2
|
-
/**
|
|
3
|
-
* Template description object
|
|
4
|
-
*/
|
|
5
|
-
interface TemplateDescription {
|
|
6
|
-
/**
|
|
7
|
-
* Template string with placeholders
|
|
8
|
-
*/
|
|
9
|
-
template: string;
|
|
10
|
-
/**
|
|
11
|
-
* Optional helper functions or templates
|
|
12
|
-
*/
|
|
13
|
-
helpers?: Record<string, any>;
|
|
14
|
-
/**
|
|
15
|
-
* Optional example data for rendering
|
|
16
|
-
*/
|
|
17
|
-
handshake?: Record<string, any>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Build a component from template description
|
|
22
|
-
*/
|
|
23
|
-
function build(tpl: TemplateDescription, extra?: boolean, buildDependencies?: Record<string, any>): Function;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Get a component from component storage
|
|
27
|
-
*/
|
|
28
|
-
function get(location: [string, string?]): Function;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Add a component to component storage
|
|
32
|
-
*/
|
|
33
|
-
function add(location: [string, string?], tplfn: Function | TemplateDescription, ...args: any[]): void;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* List the names of all components in the component storage
|
|
37
|
-
*/
|
|
38
|
-
function list(storageNames?: string[]): string[];
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Clear up all the components in the storage
|
|
42
|
-
*/
|
|
43
|
-
function clear(): void;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Remove a template from component storage
|
|
47
|
-
*/
|
|
48
|
-
function remove(location: [string, string?]): void | string;
|
|
49
|
-
|
|
50
|
-
const morphAPI: {
|
|
51
|
-
build: typeof build;
|
|
52
|
-
get: typeof get;
|
|
53
|
-
add: typeof add;
|
|
54
|
-
list: typeof list;
|
|
55
|
-
clear: typeof clear;
|
|
56
|
-
remove: typeof remove;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export default morphAPI;
|
|
60
|
-
}
|