@peter.naydenov/morph 3.1.4 → 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 CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
 
4
4
 
5
+ ### 3.1.5 (2025-11-14)
6
+ - [x] Types improvements;
7
+
8
+
9
+
5
10
  ### 3.1.4 (2025-10-13)
6
11
  - [x] Dependencies update. Dev deps update. @peter.naydenov/walk - v.5.0.2;
7
12
 
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;
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ TG_PRX: string;
3
+ TG_SFX: string;
4
+ TG_SIZE_P: number;
5
+ TG_SIZE_S: number;
6
+ };
7
+ export default _default;
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",
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": "./types/index.d.ts",
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
28
  "@peter.naydenov/walk": "^5.0.2"
28
29
  },
29
30
  "devDependencies": {
30
- "@rollup/plugin-commonjs": "^28.0.6",
31
+ "@rollup/plugin-commonjs": "^29.0.0",
31
32
  "@rollup/plugin-node-resolve": "^16.0.3",
32
33
  "@rollup/plugin-terser": "^0.4.4",
33
34
  "c8": "^10.1.3",
34
- "chai": "6.2.0",
35
- "mocha": "11.7.4",
36
- "rollup": "^4.52.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
- * Get a template from a storage.
27
+ * Retrieves a template from storage.
28
28
  *
29
- * @param {string[]} location - The location of the template. Array of two elements.
30
- * The first element is the name of the template. The second element
31
- * is optional and is the name of the storage. Defaults to 'default'.
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
- * @returns {function } The template (a render function) if it exists in the storage.
34
- * An function that returns an error message if
35
- * either the storage or template does not exist.
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
- * Add a template to a storage.
65
- *
66
- * If the template is already a function, it is added to the storage.
67
- * If the template is a template description (an object), it is built and
68
- * added to the storage.
69
- * If the template is broken, an error message is printed in the console
70
- * and the template is not added to the storage.
71
- *
72
- * @param {string[]} location - The location to add the template to. Array of two elements.
73
- * The first element is the name of the template. The second element
74
- * is optional and is the name of the storage. Defaults to 'default'.
75
- * @param {object|function|null} tplfn - The template description or the already built template function.
76
- * @param {...any} args - Additional arguments to be passed to the build function.
77
- * Only used if the first argument is a template description.
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
- * Returns an array of all the names of the templates in the given storages.
102
- * No arguments - will return the list of templates in the 'default' storage.
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
- * @param {string[]} [storageNames=['default']] - The names of the storages to retrieve template names from;
105
- * @returns {string[]} An array of all the template names in the given storages;
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 the storages.
119
- * This function deletes all storages. Storage 'default' will be reset to an empty object.
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
- * Removes a template from the storage.
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
- * @param {string[]} location - The location to remove the template from. Array of two elements.
136
- * The first element is the name of the template. The second element
137
- * is optional and is the name of the storage. Defaults to 'default'.
171
+ * @example
172
+ * // Remove template from default storage
173
+ * remove(['myTemplate']);
138
174
  *
139
- * @returns {void|string} An error message if the storage or template does not exist.
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
- function showError (type) {
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
- function findObjects ({key, value, breadcrumbs}) {
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 = {}
@@ -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
- * Execute rendering and return the results
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 it's a string, it's the value of 'text' property.
10
- * @param {string} name - Name of the render to be executed.
11
- * @param {object} helpers - Object with helper functions or templates.
12
- * @param {...any} args - Extra arguments to be passed to the render function.
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} - Rendered 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
- function setRenderData ( d={} ) {
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.
@@ -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
- }