@truto/replace-placeholders 1.0.3 → 1.0.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/README.md +149 -0
- package/dist/main.cjs +74 -27
- package/dist/main.cjs.map +1 -1
- package/dist/module.js +76 -29
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ console.log(result); // Outputs: 'Foo: bar'
|
|
|
27
27
|
console.log(replacePlaceholders('{{foo}}', { foo: 'bar' })); // Outputs: 'bar'
|
|
28
28
|
console.log(replacePlaceholders('{{foo-bar.something}}', { 'foo-bar': { something: true } })); // Outputs: 'true'
|
|
29
29
|
console.log(replacePlaceholders('{{foo}} {{bar:bool}}', { foo: 'bar', bar: 'false' })); // Outputs: 'bar false'
|
|
30
|
+
console.log(replacePlaceholders('{{foo.0.bar}}', { foo: [{ bar: 'baz' }] })); // Outputs: 'baz'
|
|
30
31
|
```
|
|
31
32
|
|
|
32
33
|
#### Arrays
|
|
@@ -45,14 +46,36 @@ console.log(replacePlaceholders({ foo: '{{foo}}', bar: '{{bar:int}}' }, { foo: '
|
|
|
45
46
|
|
|
46
47
|
### Conversion Types
|
|
47
48
|
|
|
49
|
+
You can coerce values to specific types.
|
|
50
|
+
|
|
51
|
+
**Only works when the placeholder is the complete string.**
|
|
52
|
+
|
|
48
53
|
```javascript
|
|
49
54
|
console.log(replacePlaceholders('{{foo:int}}', { foo: '1' })); // Outputs: 1
|
|
50
55
|
console.log(replacePlaceholders('{{foo:num}}', { foo: '1.1' })); // Outputs: 1.1
|
|
51
56
|
console.log(replacePlaceholders('{{foo:bool}}', { foo: 'true' })); // Outputs: true
|
|
52
57
|
console.log(replacePlaceholders('{{foo:json}}', { foo: '{"foo":"bar"}' })); // Outputs: { foo: 'bar' }
|
|
58
|
+
console.log(replacePlaceholders('{{foo:json}}', { foo: { foo: 'bar' } })); // Outputs: { foo: 'bar' }
|
|
53
59
|
console.log(replacePlaceholders('{{foo:null}}', { foo: 'null' })); // Outputs: null
|
|
54
60
|
```
|
|
55
61
|
|
|
62
|
+
### Remove empty placeholders
|
|
63
|
+
|
|
64
|
+
You can use `undefined` keyword to remove placeholders that are not found in the data object.
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
console.log(replacePlaceholders('foo {{foo:undefined}} {{bar}}', { bar: 'bar' })); // Outputs: 'foo bar'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Ignoring empty strings
|
|
71
|
+
|
|
72
|
+
You can use `ignore-empty-str` keyword to ignore empty strings in the output. Useful when used with conditional replacements below.
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
console.log(replacePlaceholders('foo {{foo:ignore-empty-str}} {{bar}}', { foo: '', bar: 'bar' })) // Outputs: 'foo {{foo:ignore-empty-str}} bar'
|
|
76
|
+
console.lo(replacePlaceholders('{{foo|bar:ignore-empty-str}}', { foo: '', bar: 'bar' })) // Outputs: 'bar'
|
|
77
|
+
```
|
|
78
|
+
|
|
56
79
|
### Conditional Replacements (Fallback Values)
|
|
57
80
|
|
|
58
81
|
Using a `|` (pipe) character, you can provide fallback values right within the placeholder. The function will pick the first non-`undefined` value for the replacement.
|
|
@@ -64,6 +87,132 @@ console.log(replacePlaceholders('{{foo.bar:str|bar:str}}', { foo: { bar: 'bar' }
|
|
|
64
87
|
console.log(replacePlaceholders('{{foo.bar|bar:str}}', { foo: { bar: true } })); // Outputs: 'true'
|
|
65
88
|
```
|
|
66
89
|
|
|
90
|
+
### Default values
|
|
91
|
+
|
|
92
|
+
Using the Elvis operator `?:`, you can provide default values for placeholders that are not found in the data object.
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
console.log(replacePlaceholders('{{foo?:bar}}', { bar: 'bar' })); // Outputs: 'bar'
|
|
96
|
+
````
|
|
97
|
+
|
|
98
|
+
You can also combine it with type casting
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
console.log(replacePlaceholders('{{foo?:1:int}}', { foo: '1' })); // Outputs: 1
|
|
102
|
+
````
|
|
103
|
+
|
|
104
|
+
### Object Merging with `$truto_merge`
|
|
105
|
+
|
|
106
|
+
The `$truto_merge` special key enables deep merging of objects from placeholder values into the parent object. This is useful for dynamically extending configuration objects or combining data from multiple sources.
|
|
107
|
+
|
|
108
|
+
**Important:** The `$truto_merge` feature requires the `:json` type modifier to properly resolve object values.
|
|
109
|
+
|
|
110
|
+
#### Basic Object Merge
|
|
111
|
+
|
|
112
|
+
Merge a single object into the parent:
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
const template = {
|
|
116
|
+
query: {
|
|
117
|
+
default_value: 'foo',
|
|
118
|
+
$truto_merge: '{{user_supplied_query:json}}'
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const result = replacePlaceholders(template, {
|
|
123
|
+
user_supplied_query: { custom_value: 'bar' }
|
|
124
|
+
});
|
|
125
|
+
// Outputs: { query: { default_value: 'foo', custom_value: 'bar' } }
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Deep Merge
|
|
129
|
+
|
|
130
|
+
The merge is always deep, preserving nested properties:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
const template = {
|
|
134
|
+
config: {
|
|
135
|
+
defaults: {
|
|
136
|
+
timeout: 1000,
|
|
137
|
+
retries: 3
|
|
138
|
+
},
|
|
139
|
+
$truto_merge: '{{user_config:json}}'
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const result = replacePlaceholders(template, {
|
|
144
|
+
user_config: {
|
|
145
|
+
defaults: {
|
|
146
|
+
retries: 5 // Overrides only this nested property
|
|
147
|
+
},
|
|
148
|
+
custom: true
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
// Outputs: {
|
|
152
|
+
// config: {
|
|
153
|
+
// defaults: { timeout: 1000, retries: 5 },
|
|
154
|
+
// custom: true
|
|
155
|
+
// }
|
|
156
|
+
// }
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### Multiple Sources
|
|
160
|
+
|
|
161
|
+
Merge multiple objects in sequence by providing an array. Later values override earlier ones:
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
const template = {
|
|
165
|
+
settings: {
|
|
166
|
+
core: { enabled: true },
|
|
167
|
+
$truto_merge: ['{{base_settings:json}}', '{{user_settings:json}}']
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const result = replacePlaceholders(template, {
|
|
172
|
+
base_settings: {
|
|
173
|
+
core: { version: '1.0' },
|
|
174
|
+
features: { a: true }
|
|
175
|
+
},
|
|
176
|
+
user_settings: {
|
|
177
|
+
core: { enabled: false }, // Overrides base
|
|
178
|
+
features: { b: true }
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// Outputs: {
|
|
182
|
+
// settings: {
|
|
183
|
+
// core: { enabled: false, version: '1.0' },
|
|
184
|
+
// features: { a: true, b: true }
|
|
185
|
+
// }
|
|
186
|
+
// }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Fallback Values
|
|
190
|
+
|
|
191
|
+
Use the pipe operator `|` to specify fallback placeholders:
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const template = {
|
|
195
|
+
query: {
|
|
196
|
+
default_value: 'foo',
|
|
197
|
+
$truto_merge: '{{user_query:json|default_query:json}}'
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const result = replacePlaceholders(template, {
|
|
202
|
+
default_query: { custom_value: 'bar' }
|
|
203
|
+
});
|
|
204
|
+
// Uses default_query since user_query is undefined
|
|
205
|
+
// Outputs: { query: { default_value: 'foo', custom_value: 'bar' } }
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### Behavior Notes
|
|
209
|
+
|
|
210
|
+
- The `$truto_merge` key is automatically removed from the output
|
|
211
|
+
- Undefined or non-object placeholders are skipped (no error thrown)
|
|
212
|
+
- Arrays in placeholders are not merged (only plain objects)
|
|
213
|
+
- Empty objects have no effect on the merge
|
|
214
|
+
- Works with nested `$truto_merge` keys for hierarchical merging
|
|
215
|
+
|
|
67
216
|
## License
|
|
68
217
|
|
|
69
218
|
This project is licensed under the MIT License.
|
package/dist/main.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
var $g5Y9E$
|
|
1
|
+
var $g5Y9E$deepmerge = require("deepmerge");
|
|
2
2
|
var $g5Y9E$lodashes = require("lodash-es");
|
|
3
|
+
var $g5Y9E$traverse = require("traverse");
|
|
3
4
|
var $g5Y9E$wildwildpath = require("wild-wild-path");
|
|
4
5
|
|
|
5
6
|
function $parcel$defineInteropFlag(a) {
|
|
@@ -19,25 +20,39 @@ $parcel$export(module.exports, "default", () => $80bd448eb6ea085b$export$2e2bcd8
|
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
function $a169b0c20575e4d3$var$replace(str = "", obj = {}) {
|
|
23
|
-
const regex = /{{([\w
|
|
25
|
+
const regex = /{{([\w-./|:?\s]+)}}/gi;
|
|
26
|
+
const typeSplitRegex = /:(?=[\w\s]+)/gm;
|
|
24
27
|
const matches = str.match(regex);
|
|
25
28
|
let result = str;
|
|
26
29
|
if (matches) matches.forEach((match)=>{
|
|
27
|
-
const
|
|
30
|
+
const [matchStr, defaultStr] = match.slice(2, -2).split("?:");
|
|
31
|
+
const parts = matchStr.split("|");
|
|
28
32
|
const isNullAllowed = parts.some((part)=>part.includes(":null"));
|
|
33
|
+
const ignoreEmptyString = parts.some((part)=>part.includes(":ignore-empty-str"));
|
|
34
|
+
const setUndefined = parts.some((part)=>part.includes(":undefined"));
|
|
35
|
+
const isWholeString = match === str;
|
|
29
36
|
let value = undefined;
|
|
30
37
|
for (const part of parts){
|
|
31
|
-
const [path, ...typeParts] = part.split(
|
|
32
|
-
const type = typeParts[0] || "str";
|
|
38
|
+
const [path, ...typeParts] = part.split(typeSplitRegex);
|
|
39
|
+
const type = (typeParts[0] || "str").trim();
|
|
33
40
|
const tempValue = (0, $g5Y9E$wildwildpath.get)(obj, path.trim());
|
|
41
|
+
if (tempValue === "" && ignoreEmptyString) continue;
|
|
34
42
|
if (tempValue !== undefined) {
|
|
35
|
-
value = $a169b0c20575e4d3$var$typeCast(tempValue, type,
|
|
43
|
+
value = $a169b0c20575e4d3$var$typeCast(tempValue, type, isWholeString);
|
|
36
44
|
break;
|
|
37
45
|
}
|
|
38
46
|
}
|
|
39
|
-
if (value === undefined) {
|
|
40
|
-
|
|
47
|
+
if (value === undefined && defaultStr) {
|
|
48
|
+
const [defaultValue, defaultType] = defaultStr.split(typeSplitRegex);
|
|
49
|
+
const type = defaultType || "str";
|
|
50
|
+
value = $a169b0c20575e4d3$var$typeCast(defaultValue, type, isWholeString);
|
|
51
|
+
} else if (value === undefined) {
|
|
52
|
+
if (setUndefined) {
|
|
53
|
+
if (isWholeString) value = undefined;
|
|
54
|
+
else value = "";
|
|
55
|
+
} else if (isNullAllowed) value = null;
|
|
41
56
|
else value = match // Keep the placeholder intact
|
|
42
57
|
;
|
|
43
58
|
}
|
|
@@ -48,36 +63,43 @@ function $a169b0c20575e4d3$var$replace(str = "", obj = {}) {
|
|
|
48
63
|
}
|
|
49
64
|
function $a169b0c20575e4d3$var$typeCast(value, type, isWholeString) {
|
|
50
65
|
if (value === undefined || value === null) return value;
|
|
66
|
+
let valueToCheck = value;
|
|
67
|
+
if ((0, $g5Y9E$lodashes.isString)(value) && type !== "str") valueToCheck = (0, $g5Y9E$lodashes.trim)(value);
|
|
68
|
+
if (valueToCheck instanceof Blob || valueToCheck instanceof ReadableStream || valueToCheck instanceof WritableStream || valueToCheck instanceof TransformStream) return valueToCheck;
|
|
51
69
|
let castValue;
|
|
52
70
|
switch(type){
|
|
71
|
+
case "ignore-empty-str":
|
|
72
|
+
return valueToCheck;
|
|
73
|
+
case "undefined":
|
|
74
|
+
return valueToCheck;
|
|
53
75
|
case "null":
|
|
54
|
-
if (
|
|
55
|
-
return isWholeString ?
|
|
76
|
+
if (valueToCheck === "null" || valueToCheck === null) return null;
|
|
77
|
+
return isWholeString ? valueToCheck : "null";
|
|
56
78
|
case "int":
|
|
57
|
-
castValue = parseInt(
|
|
58
|
-
return isNaN(castValue) ?
|
|
79
|
+
castValue = parseInt(valueToCheck);
|
|
80
|
+
return isNaN(castValue) ? valueToCheck : castValue;
|
|
59
81
|
case "num":
|
|
60
|
-
castValue = parseFloat(
|
|
61
|
-
return isNaN(castValue) ?
|
|
82
|
+
castValue = parseFloat(valueToCheck);
|
|
83
|
+
return isNaN(castValue) ? valueToCheck : castValue;
|
|
62
84
|
case "str":
|
|
63
|
-
return
|
|
85
|
+
return (0, $g5Y9E$lodashes.toString)(value);
|
|
64
86
|
case "bool":
|
|
65
|
-
if (
|
|
66
|
-
if (
|
|
67
|
-
return
|
|
87
|
+
if (valueToCheck === "true" || valueToCheck === true) return true;
|
|
88
|
+
if (valueToCheck === "false" || valueToCheck === false) return false;
|
|
89
|
+
return valueToCheck // Return the original value if it's not 'true' or 'false'
|
|
68
90
|
;
|
|
69
91
|
case "json":
|
|
70
92
|
if (isWholeString) {
|
|
71
|
-
if ((0, $g5Y9E$lodashes.isPlainObject)(
|
|
93
|
+
if ((0, $g5Y9E$lodashes.isPlainObject)(valueToCheck) || (0, $g5Y9E$lodashes.isArray)(valueToCheck)) return valueToCheck;
|
|
72
94
|
try {
|
|
73
|
-
return JSON.parse(
|
|
95
|
+
return JSON.parse(valueToCheck);
|
|
74
96
|
} catch (err) {
|
|
75
|
-
return
|
|
97
|
+
return valueToCheck;
|
|
76
98
|
}
|
|
77
99
|
}
|
|
78
|
-
return
|
|
100
|
+
return valueToCheck;
|
|
79
101
|
case "any":
|
|
80
|
-
return
|
|
102
|
+
return valueToCheck;
|
|
81
103
|
default:
|
|
82
104
|
throw new Error(`Unsupported type: ${type}`);
|
|
83
105
|
}
|
|
@@ -88,10 +110,35 @@ var $a169b0c20575e4d3$export$2e2bcd8739ae039 = $a169b0c20575e4d3$var$replace;
|
|
|
88
110
|
function $72af1098ef591494$export$2e2bcd8739ae039(obj, context) {
|
|
89
111
|
if ((0, $g5Y9E$lodashes.isString)(obj)) return (0, $a169b0c20575e4d3$export$2e2bcd8739ae039)(obj, context);
|
|
90
112
|
if ((0, $g5Y9E$lodashes.isArray)(obj)) return obj.map((item)=>$72af1098ef591494$export$2e2bcd8739ae039(item, context));
|
|
91
|
-
if ((0, $g5Y9E$lodashes.isPlainObject)(obj))
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
113
|
+
if ((0, $g5Y9E$lodashes.isPlainObject)(obj)) {
|
|
114
|
+
// First pass: replace all string placeholders
|
|
115
|
+
const replaced = (0, ($parcel$interopDefault($g5Y9E$traverse)))(obj).map(function(value) {
|
|
116
|
+
if (this.circular) this.remove();
|
|
117
|
+
else if ((0, $g5Y9E$lodashes.isString)(value)) this.update((0, $a169b0c20575e4d3$export$2e2bcd8739ae039)(value, context));
|
|
118
|
+
else if ((0, $g5Y9E$lodashes.isArrayBuffer)(value) || value instanceof Blob) {
|
|
119
|
+
const val = (0, $g5Y9E$lodashes.get)(obj, this.path);
|
|
120
|
+
this.update(val);
|
|
121
|
+
this.block();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// Second pass: handle $truto_merge
|
|
125
|
+
return (0, ($parcel$interopDefault($g5Y9E$traverse)))(replaced).map(function(value) {
|
|
126
|
+
if (this.circular) this.remove();
|
|
127
|
+
else if ((0, $g5Y9E$lodashes.isPlainObject)(value) && "$truto_merge" in value) {
|
|
128
|
+
const mergeValue = value["$truto_merge"];
|
|
129
|
+
const mergeValues = (0, $g5Y9E$lodashes.isArray)(mergeValue) ? mergeValue : [
|
|
130
|
+
mergeValue
|
|
131
|
+
];
|
|
132
|
+
// Start with the base object (without $truto_merge key)
|
|
133
|
+
let result = {};
|
|
134
|
+
for(const key in value)if (key !== "$truto_merge") result[key] = value[key];
|
|
135
|
+
// Merge each resolved value (already resolved in first pass)
|
|
136
|
+
for (const resolvedValue of mergeValues)// Only merge if it's a plain object
|
|
137
|
+
if ((0, $g5Y9E$lodashes.isPlainObject)(resolvedValue)) result = (0, ($parcel$interopDefault($g5Y9E$deepmerge)))(result, resolvedValue);
|
|
138
|
+
this.update(result);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
95
142
|
throw new Error("Invalid type");
|
|
96
143
|
}
|
|
97
144
|
|
package/dist/main.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"
|
|
1
|
+
{"mappings":"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","sources":["index.ts","replacePlaceholders.ts","replace.ts"],"sourcesContent":["import replacePlaceholders from './replacePlaceholders';\nexport default replacePlaceholders;\n","import deepmerge from 'deepmerge'\nimport { get, isArray, isArrayBuffer, isPlainObject, isString } from 'lodash-es'\nimport traverse from 'traverse'\nimport replace from './replace'\nexport default function replacePlaceholders<T>(\n obj: T extends string | string[] | Record<string, unknown> ? T : never,\n context: Record<string, unknown>\n): T {\n if (isString(obj)) {\n return replace(obj, context) as T\n }\n\n if (isArray(obj)) {\n return obj.map(item => replacePlaceholders(item, context)) as T\n }\n\n if (isPlainObject(obj)) {\n // First pass: replace all string placeholders\n const replaced = traverse(obj).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isString(value)) {\n this.update(replace(value, context))\n } else if (isArrayBuffer(value) || value instanceof Blob) {\n const val = get(obj, this.path)\n this.update(val)\n this.block()\n }\n })\n\n // Second pass: handle $truto_merge\n return traverse(replaced).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isPlainObject(value) && '$truto_merge' in value) {\n const mergeValue = value['$truto_merge']\n const mergeValues = isArray(mergeValue) ? mergeValue : [mergeValue]\n\n // Start with the base object (without $truto_merge key)\n let result: Record<string, unknown> = {}\n for (const key in value) {\n if (key !== '$truto_merge') {\n result[key] = value[key]\n }\n }\n\n // Merge each resolved value (already resolved in first pass)\n for (const resolvedValue of mergeValues) {\n // Only merge if it's a plain object\n if (isPlainObject(resolvedValue)) {\n result = deepmerge(result, resolvedValue as Record<string, unknown>)\n }\n // Skip if it's undefined, null, a string (unresolved placeholder), or any non-object\n }\n\n this.update(result)\n }\n }) as T\n }\n\n throw new Error('Invalid type')\n}\n","import { isArray, isPlainObject, isString, toString, trim } from 'lodash-es'\nimport { get as getWild } from 'wild-wild-path'\n\nfunction replace(\n str = '',\n obj: object = {}\n):\n | string\n | number\n | boolean\n | Record<string, unknown>\n | null\n | undefined\n | unknown {\n const regex = /{{([\\w-./|:?\\s]+)}}/gi\n const typeSplitRegex = /:(?=[\\w\\s]+)/gm\n const matches = str.match(regex)\n let result: string | any = str\n\n if (matches) {\n matches.forEach(match => {\n const [matchStr, defaultStr] = match.slice(2, -2).split('?:')\n const parts = matchStr.split('|')\n const isNullAllowed = parts.some(part => part.includes(':null'))\n const ignoreEmptyString = parts.some(part =>\n part.includes(':ignore-empty-str')\n )\n const setUndefined = parts.some(part => part.includes(':undefined'))\n\n const isWholeString = match === str\n\n let value: any = undefined\n for (const part of parts) {\n const [path, ...typeParts] = part.split(typeSplitRegex)\n const type: string = (typeParts[0] || 'str').trim()\n\n const tempValue = getWild(obj, path.trim())\n if (tempValue === '' && ignoreEmptyString) {\n continue\n }\n if (tempValue !== undefined) {\n value = typeCast(tempValue, type, isWholeString)\n break\n }\n }\n\n if (value === undefined && defaultStr) {\n const [defaultValue, defaultType] = defaultStr.split(typeSplitRegex)\n const type = defaultType || 'str'\n value = typeCast(defaultValue, type, isWholeString)\n } else if (value === undefined) {\n if (setUndefined) {\n if (isWholeString) {\n value = undefined\n } else {\n value = ''\n }\n } else if (isNullAllowed) {\n value = null\n } else {\n value = match // Keep the placeholder intact\n }\n }\n\n if (match === str) {\n result = value\n } else {\n result = result.replace(match, value)\n }\n })\n }\n\n return result\n}\n\nfunction typeCast(\n value: unknown,\n type: string,\n isWholeString: boolean\n):\n | string\n | number\n | boolean\n | Record<string, unknown>\n | null\n | undefined\n | unknown {\n if (value === undefined || value === null) return value\n\n let valueToCheck = value\n if (isString(value) && type !== 'str') {\n valueToCheck = trim(value)\n }\n\n if (\n valueToCheck instanceof Blob ||\n valueToCheck instanceof ReadableStream ||\n valueToCheck instanceof WritableStream ||\n valueToCheck instanceof TransformStream\n ) {\n return valueToCheck\n }\n\n let castValue: any\n switch (type) {\n case 'ignore-empty-str':\n return valueToCheck\n case 'undefined':\n return valueToCheck\n case 'null':\n if (valueToCheck === 'null' || valueToCheck === null) return null\n return isWholeString ? valueToCheck : 'null'\n case 'int':\n castValue = parseInt(valueToCheck as string)\n return isNaN(castValue) ? valueToCheck : castValue\n case 'num':\n castValue = parseFloat(valueToCheck as string)\n return isNaN(castValue) ? valueToCheck : castValue\n case 'str':\n return toString(value)\n case 'bool':\n if (valueToCheck === 'true' || valueToCheck === true) return true\n if (valueToCheck === 'false' || valueToCheck === false) return false\n return valueToCheck // Return the original value if it's not 'true' or 'false'\n case 'json':\n if (isWholeString) {\n if (isPlainObject(valueToCheck) || isArray(valueToCheck))\n return valueToCheck\n try {\n return JSON.parse(valueToCheck as string)\n } catch (err) {\n return valueToCheck\n }\n }\n return valueToCheck\n case 'any':\n return valueToCheck\n default:\n throw new Error(`Unsupported type: ${type}`)\n }\n}\n\nexport default replace\n"],"names":[],"version":3,"file":"main.cjs.map"}
|
package/dist/module.js
CHANGED
|
@@ -1,30 +1,45 @@
|
|
|
1
|
+
import $hCgyA$deepmerge from "deepmerge";
|
|
2
|
+
import {isString as $hCgyA$isString, isArray as $hCgyA$isArray, isPlainObject as $hCgyA$isPlainObject, isArrayBuffer as $hCgyA$isArrayBuffer, get as $hCgyA$get, trim as $hCgyA$trim, toString as $hCgyA$toString} from "lodash-es";
|
|
1
3
|
import $hCgyA$traverse from "traverse";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
+
import {get as $hCgyA$get1} from "wild-wild-path";
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
function $67f2b908c91abfcc$var$replace(str = "", obj = {}) {
|
|
10
|
-
const regex = /{{([\w
|
|
12
|
+
const regex = /{{([\w-./|:?\s]+)}}/gi;
|
|
13
|
+
const typeSplitRegex = /:(?=[\w\s]+)/gm;
|
|
11
14
|
const matches = str.match(regex);
|
|
12
15
|
let result = str;
|
|
13
16
|
if (matches) matches.forEach((match)=>{
|
|
14
|
-
const
|
|
17
|
+
const [matchStr, defaultStr] = match.slice(2, -2).split("?:");
|
|
18
|
+
const parts = matchStr.split("|");
|
|
15
19
|
const isNullAllowed = parts.some((part)=>part.includes(":null"));
|
|
20
|
+
const ignoreEmptyString = parts.some((part)=>part.includes(":ignore-empty-str"));
|
|
21
|
+
const setUndefined = parts.some((part)=>part.includes(":undefined"));
|
|
22
|
+
const isWholeString = match === str;
|
|
16
23
|
let value = undefined;
|
|
17
24
|
for (const part of parts){
|
|
18
|
-
const [path, ...typeParts] = part.split(
|
|
19
|
-
const type = typeParts[0] || "str";
|
|
20
|
-
const tempValue = (0, $hCgyA$
|
|
25
|
+
const [path, ...typeParts] = part.split(typeSplitRegex);
|
|
26
|
+
const type = (typeParts[0] || "str").trim();
|
|
27
|
+
const tempValue = (0, $hCgyA$get1)(obj, path.trim());
|
|
28
|
+
if (tempValue === "" && ignoreEmptyString) continue;
|
|
21
29
|
if (tempValue !== undefined) {
|
|
22
|
-
value = $67f2b908c91abfcc$var$typeCast(tempValue, type,
|
|
30
|
+
value = $67f2b908c91abfcc$var$typeCast(tempValue, type, isWholeString);
|
|
23
31
|
break;
|
|
24
32
|
}
|
|
25
33
|
}
|
|
26
|
-
if (value === undefined) {
|
|
27
|
-
|
|
34
|
+
if (value === undefined && defaultStr) {
|
|
35
|
+
const [defaultValue, defaultType] = defaultStr.split(typeSplitRegex);
|
|
36
|
+
const type = defaultType || "str";
|
|
37
|
+
value = $67f2b908c91abfcc$var$typeCast(defaultValue, type, isWholeString);
|
|
38
|
+
} else if (value === undefined) {
|
|
39
|
+
if (setUndefined) {
|
|
40
|
+
if (isWholeString) value = undefined;
|
|
41
|
+
else value = "";
|
|
42
|
+
} else if (isNullAllowed) value = null;
|
|
28
43
|
else value = match // Keep the placeholder intact
|
|
29
44
|
;
|
|
30
45
|
}
|
|
@@ -35,36 +50,43 @@ function $67f2b908c91abfcc$var$replace(str = "", obj = {}) {
|
|
|
35
50
|
}
|
|
36
51
|
function $67f2b908c91abfcc$var$typeCast(value, type, isWholeString) {
|
|
37
52
|
if (value === undefined || value === null) return value;
|
|
53
|
+
let valueToCheck = value;
|
|
54
|
+
if ((0, $hCgyA$isString)(value) && type !== "str") valueToCheck = (0, $hCgyA$trim)(value);
|
|
55
|
+
if (valueToCheck instanceof Blob || valueToCheck instanceof ReadableStream || valueToCheck instanceof WritableStream || valueToCheck instanceof TransformStream) return valueToCheck;
|
|
38
56
|
let castValue;
|
|
39
57
|
switch(type){
|
|
58
|
+
case "ignore-empty-str":
|
|
59
|
+
return valueToCheck;
|
|
60
|
+
case "undefined":
|
|
61
|
+
return valueToCheck;
|
|
40
62
|
case "null":
|
|
41
|
-
if (
|
|
42
|
-
return isWholeString ?
|
|
63
|
+
if (valueToCheck === "null" || valueToCheck === null) return null;
|
|
64
|
+
return isWholeString ? valueToCheck : "null";
|
|
43
65
|
case "int":
|
|
44
|
-
castValue = parseInt(
|
|
45
|
-
return isNaN(castValue) ?
|
|
66
|
+
castValue = parseInt(valueToCheck);
|
|
67
|
+
return isNaN(castValue) ? valueToCheck : castValue;
|
|
46
68
|
case "num":
|
|
47
|
-
castValue = parseFloat(
|
|
48
|
-
return isNaN(castValue) ?
|
|
69
|
+
castValue = parseFloat(valueToCheck);
|
|
70
|
+
return isNaN(castValue) ? valueToCheck : castValue;
|
|
49
71
|
case "str":
|
|
50
|
-
return
|
|
72
|
+
return (0, $hCgyA$toString)(value);
|
|
51
73
|
case "bool":
|
|
52
|
-
if (
|
|
53
|
-
if (
|
|
54
|
-
return
|
|
74
|
+
if (valueToCheck === "true" || valueToCheck === true) return true;
|
|
75
|
+
if (valueToCheck === "false" || valueToCheck === false) return false;
|
|
76
|
+
return valueToCheck // Return the original value if it's not 'true' or 'false'
|
|
55
77
|
;
|
|
56
78
|
case "json":
|
|
57
79
|
if (isWholeString) {
|
|
58
|
-
if ((0, $hCgyA$isPlainObject)(
|
|
80
|
+
if ((0, $hCgyA$isPlainObject)(valueToCheck) || (0, $hCgyA$isArray)(valueToCheck)) return valueToCheck;
|
|
59
81
|
try {
|
|
60
|
-
return JSON.parse(
|
|
82
|
+
return JSON.parse(valueToCheck);
|
|
61
83
|
} catch (err) {
|
|
62
|
-
return
|
|
84
|
+
return valueToCheck;
|
|
63
85
|
}
|
|
64
86
|
}
|
|
65
|
-
return
|
|
87
|
+
return valueToCheck;
|
|
66
88
|
case "any":
|
|
67
|
-
return
|
|
89
|
+
return valueToCheck;
|
|
68
90
|
default:
|
|
69
91
|
throw new Error(`Unsupported type: ${type}`);
|
|
70
92
|
}
|
|
@@ -75,10 +97,35 @@ var $67f2b908c91abfcc$export$2e2bcd8739ae039 = $67f2b908c91abfcc$var$replace;
|
|
|
75
97
|
function $4e62acd4800cacd9$export$2e2bcd8739ae039(obj, context) {
|
|
76
98
|
if ((0, $hCgyA$isString)(obj)) return (0, $67f2b908c91abfcc$export$2e2bcd8739ae039)(obj, context);
|
|
77
99
|
if ((0, $hCgyA$isArray)(obj)) return obj.map((item)=>$4e62acd4800cacd9$export$2e2bcd8739ae039(item, context));
|
|
78
|
-
if ((0, $hCgyA$isPlainObject)(obj))
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
100
|
+
if ((0, $hCgyA$isPlainObject)(obj)) {
|
|
101
|
+
// First pass: replace all string placeholders
|
|
102
|
+
const replaced = (0, $hCgyA$traverse)(obj).map(function(value) {
|
|
103
|
+
if (this.circular) this.remove();
|
|
104
|
+
else if ((0, $hCgyA$isString)(value)) this.update((0, $67f2b908c91abfcc$export$2e2bcd8739ae039)(value, context));
|
|
105
|
+
else if ((0, $hCgyA$isArrayBuffer)(value) || value instanceof Blob) {
|
|
106
|
+
const val = (0, $hCgyA$get)(obj, this.path);
|
|
107
|
+
this.update(val);
|
|
108
|
+
this.block();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
// Second pass: handle $truto_merge
|
|
112
|
+
return (0, $hCgyA$traverse)(replaced).map(function(value) {
|
|
113
|
+
if (this.circular) this.remove();
|
|
114
|
+
else if ((0, $hCgyA$isPlainObject)(value) && "$truto_merge" in value) {
|
|
115
|
+
const mergeValue = value["$truto_merge"];
|
|
116
|
+
const mergeValues = (0, $hCgyA$isArray)(mergeValue) ? mergeValue : [
|
|
117
|
+
mergeValue
|
|
118
|
+
];
|
|
119
|
+
// Start with the base object (without $truto_merge key)
|
|
120
|
+
let result = {};
|
|
121
|
+
for(const key in value)if (key !== "$truto_merge") result[key] = value[key];
|
|
122
|
+
// Merge each resolved value (already resolved in first pass)
|
|
123
|
+
for (const resolvedValue of mergeValues)// Only merge if it's a plain object
|
|
124
|
+
if ((0, $hCgyA$isPlainObject)(resolvedValue)) result = (0, $hCgyA$deepmerge)(result, resolvedValue);
|
|
125
|
+
this.update(result);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
82
129
|
throw new Error("Invalid type");
|
|
83
130
|
}
|
|
84
131
|
|
package/dist/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"
|
|
1
|
+
{"mappings":"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","sources":["index.ts","replacePlaceholders.ts","replace.ts"],"sourcesContent":["import replacePlaceholders from './replacePlaceholders';\nexport default replacePlaceholders;\n","import deepmerge from 'deepmerge'\nimport { get, isArray, isArrayBuffer, isPlainObject, isString } from 'lodash-es'\nimport traverse from 'traverse'\nimport replace from './replace'\nexport default function replacePlaceholders<T>(\n obj: T extends string | string[] | Record<string, unknown> ? T : never,\n context: Record<string, unknown>\n): T {\n if (isString(obj)) {\n return replace(obj, context) as T\n }\n\n if (isArray(obj)) {\n return obj.map(item => replacePlaceholders(item, context)) as T\n }\n\n if (isPlainObject(obj)) {\n // First pass: replace all string placeholders\n const replaced = traverse(obj).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isString(value)) {\n this.update(replace(value, context))\n } else if (isArrayBuffer(value) || value instanceof Blob) {\n const val = get(obj, this.path)\n this.update(val)\n this.block()\n }\n })\n\n // Second pass: handle $truto_merge\n return traverse(replaced).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isPlainObject(value) && '$truto_merge' in value) {\n const mergeValue = value['$truto_merge']\n const mergeValues = isArray(mergeValue) ? mergeValue : [mergeValue]\n\n // Start with the base object (without $truto_merge key)\n let result: Record<string, unknown> = {}\n for (const key in value) {\n if (key !== '$truto_merge') {\n result[key] = value[key]\n }\n }\n\n // Merge each resolved value (already resolved in first pass)\n for (const resolvedValue of mergeValues) {\n // Only merge if it's a plain object\n if (isPlainObject(resolvedValue)) {\n result = deepmerge(result, resolvedValue as Record<string, unknown>)\n }\n // Skip if it's undefined, null, a string (unresolved placeholder), or any non-object\n }\n\n this.update(result)\n }\n }) as T\n }\n\n throw new Error('Invalid type')\n}\n","import { isArray, isPlainObject, isString, toString, trim } from 'lodash-es'\nimport { get as getWild } from 'wild-wild-path'\n\nfunction replace(\n str = '',\n obj: object = {}\n):\n | string\n | number\n | boolean\n | Record<string, unknown>\n | null\n | undefined\n | unknown {\n const regex = /{{([\\w-./|:?\\s]+)}}/gi\n const typeSplitRegex = /:(?=[\\w\\s]+)/gm\n const matches = str.match(regex)\n let result: string | any = str\n\n if (matches) {\n matches.forEach(match => {\n const [matchStr, defaultStr] = match.slice(2, -2).split('?:')\n const parts = matchStr.split('|')\n const isNullAllowed = parts.some(part => part.includes(':null'))\n const ignoreEmptyString = parts.some(part =>\n part.includes(':ignore-empty-str')\n )\n const setUndefined = parts.some(part => part.includes(':undefined'))\n\n const isWholeString = match === str\n\n let value: any = undefined\n for (const part of parts) {\n const [path, ...typeParts] = part.split(typeSplitRegex)\n const type: string = (typeParts[0] || 'str').trim()\n\n const tempValue = getWild(obj, path.trim())\n if (tempValue === '' && ignoreEmptyString) {\n continue\n }\n if (tempValue !== undefined) {\n value = typeCast(tempValue, type, isWholeString)\n break\n }\n }\n\n if (value === undefined && defaultStr) {\n const [defaultValue, defaultType] = defaultStr.split(typeSplitRegex)\n const type = defaultType || 'str'\n value = typeCast(defaultValue, type, isWholeString)\n } else if (value === undefined) {\n if (setUndefined) {\n if (isWholeString) {\n value = undefined\n } else {\n value = ''\n }\n } else if (isNullAllowed) {\n value = null\n } else {\n value = match // Keep the placeholder intact\n }\n }\n\n if (match === str) {\n result = value\n } else {\n result = result.replace(match, value)\n }\n })\n }\n\n return result\n}\n\nfunction typeCast(\n value: unknown,\n type: string,\n isWholeString: boolean\n):\n | string\n | number\n | boolean\n | Record<string, unknown>\n | null\n | undefined\n | unknown {\n if (value === undefined || value === null) return value\n\n let valueToCheck = value\n if (isString(value) && type !== 'str') {\n valueToCheck = trim(value)\n }\n\n if (\n valueToCheck instanceof Blob ||\n valueToCheck instanceof ReadableStream ||\n valueToCheck instanceof WritableStream ||\n valueToCheck instanceof TransformStream\n ) {\n return valueToCheck\n }\n\n let castValue: any\n switch (type) {\n case 'ignore-empty-str':\n return valueToCheck\n case 'undefined':\n return valueToCheck\n case 'null':\n if (valueToCheck === 'null' || valueToCheck === null) return null\n return isWholeString ? valueToCheck : 'null'\n case 'int':\n castValue = parseInt(valueToCheck as string)\n return isNaN(castValue) ? valueToCheck : castValue\n case 'num':\n castValue = parseFloat(valueToCheck as string)\n return isNaN(castValue) ? valueToCheck : castValue\n case 'str':\n return toString(value)\n case 'bool':\n if (valueToCheck === 'true' || valueToCheck === true) return true\n if (valueToCheck === 'false' || valueToCheck === false) return false\n return valueToCheck // Return the original value if it's not 'true' or 'false'\n case 'json':\n if (isWholeString) {\n if (isPlainObject(valueToCheck) || isArray(valueToCheck))\n return valueToCheck\n try {\n return JSON.parse(valueToCheck as string)\n } catch (err) {\n return valueToCheck\n }\n }\n return valueToCheck\n case 'any':\n return valueToCheck\n default:\n throw new Error(`Unsupported type: ${type}`)\n }\n}\n\nexport default replace\n"],"names":[],"version":3,"file":"module.js.map"}
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"
|
|
1
|
+
{"mappings":"ACIA,qCAA4C,CAAC,EAC3C,GAAG,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,EACtE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,CAAC,CAsDH;AC5DD,eAAe,mBAAmB,CAAC","sources":["replace.ts","replacePlaceholders.ts","index.ts"],"sourcesContent":["import { isArray, isPlainObject, isString, toString, trim } from 'lodash-es'\nimport { get as getWild } from 'wild-wild-path'\n\nfunction replace(\n str = '',\n obj: object = {}\n):\n | string\n | number\n | boolean\n | Record<string, unknown>\n | null\n | undefined\n | unknown {\n const regex = /{{([\\w-./|:?\\s]+)}}/gi\n const typeSplitRegex = /:(?=[\\w\\s]+)/gm\n const matches = str.match(regex)\n let result: string | any = str\n\n if (matches) {\n matches.forEach(match => {\n const [matchStr, defaultStr] = match.slice(2, -2).split('?:')\n const parts = matchStr.split('|')\n const isNullAllowed = parts.some(part => part.includes(':null'))\n const ignoreEmptyString = parts.some(part =>\n part.includes(':ignore-empty-str')\n )\n const setUndefined = parts.some(part => part.includes(':undefined'))\n\n const isWholeString = match === str\n\n let value: any = undefined\n for (const part of parts) {\n const [path, ...typeParts] = part.split(typeSplitRegex)\n const type: string = (typeParts[0] || 'str').trim()\n\n const tempValue = getWild(obj, path.trim())\n if (tempValue === '' && ignoreEmptyString) {\n continue\n }\n if (tempValue !== undefined) {\n value = typeCast(tempValue, type, isWholeString)\n break\n }\n }\n\n if (value === undefined && defaultStr) {\n const [defaultValue, defaultType] = defaultStr.split(typeSplitRegex)\n const type = defaultType || 'str'\n value = typeCast(defaultValue, type, isWholeString)\n } else if (value === undefined) {\n if (setUndefined) {\n if (isWholeString) {\n value = undefined\n } else {\n value = ''\n }\n } else if (isNullAllowed) {\n value = null\n } else {\n value = match // Keep the placeholder intact\n }\n }\n\n if (match === str) {\n result = value\n } else {\n result = result.replace(match, value)\n }\n })\n }\n\n return result\n}\n\nfunction typeCast(\n value: unknown,\n type: string,\n isWholeString: boolean\n):\n | string\n | number\n | boolean\n | Record<string, unknown>\n | null\n | undefined\n | unknown {\n if (value === undefined || value === null) return value\n\n let valueToCheck = value\n if (isString(value) && type !== 'str') {\n valueToCheck = trim(value)\n }\n\n if (\n valueToCheck instanceof Blob ||\n valueToCheck instanceof ReadableStream ||\n valueToCheck instanceof WritableStream ||\n valueToCheck instanceof TransformStream\n ) {\n return valueToCheck\n }\n\n let castValue: any\n switch (type) {\n case 'ignore-empty-str':\n return valueToCheck\n case 'undefined':\n return valueToCheck\n case 'null':\n if (valueToCheck === 'null' || valueToCheck === null) return null\n return isWholeString ? valueToCheck : 'null'\n case 'int':\n castValue = parseInt(valueToCheck as string)\n return isNaN(castValue) ? valueToCheck : castValue\n case 'num':\n castValue = parseFloat(valueToCheck as string)\n return isNaN(castValue) ? valueToCheck : castValue\n case 'str':\n return toString(value)\n case 'bool':\n if (valueToCheck === 'true' || valueToCheck === true) return true\n if (valueToCheck === 'false' || valueToCheck === false) return false\n return valueToCheck // Return the original value if it's not 'true' or 'false'\n case 'json':\n if (isWholeString) {\n if (isPlainObject(valueToCheck) || isArray(valueToCheck))\n return valueToCheck\n try {\n return JSON.parse(valueToCheck as string)\n } catch (err) {\n return valueToCheck\n }\n }\n return valueToCheck\n case 'any':\n return valueToCheck\n default:\n throw new Error(`Unsupported type: ${type}`)\n }\n}\n\nexport default replace\n","import deepmerge from 'deepmerge'\nimport { get, isArray, isArrayBuffer, isPlainObject, isString } from 'lodash-es'\nimport traverse from 'traverse'\nimport replace from './replace'\nexport default function replacePlaceholders<T>(\n obj: T extends string | string[] | Record<string, unknown> ? T : never,\n context: Record<string, unknown>\n): T {\n if (isString(obj)) {\n return replace(obj, context) as T\n }\n\n if (isArray(obj)) {\n return obj.map(item => replacePlaceholders(item, context)) as T\n }\n\n if (isPlainObject(obj)) {\n // First pass: replace all string placeholders\n const replaced = traverse(obj).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isString(value)) {\n this.update(replace(value, context))\n } else if (isArrayBuffer(value) || value instanceof Blob) {\n const val = get(obj, this.path)\n this.update(val)\n this.block()\n }\n })\n\n // Second pass: handle $truto_merge\n return traverse(replaced).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isPlainObject(value) && '$truto_merge' in value) {\n const mergeValue = value['$truto_merge']\n const mergeValues = isArray(mergeValue) ? mergeValue : [mergeValue]\n\n // Start with the base object (without $truto_merge key)\n let result: Record<string, unknown> = {}\n for (const key in value) {\n if (key !== '$truto_merge') {\n result[key] = value[key]\n }\n }\n\n // Merge each resolved value (already resolved in first pass)\n for (const resolvedValue of mergeValues) {\n // Only merge if it's a plain object\n if (isPlainObject(resolvedValue)) {\n result = deepmerge(result, resolvedValue as Record<string, unknown>)\n }\n // Skip if it's undefined, null, a string (unresolved placeholder), or any non-object\n }\n\n this.update(result)\n }\n }) as T\n }\n\n throw new Error('Invalid type')\n}\n","import replacePlaceholders from './replacePlaceholders';\nexport default replacePlaceholders;\n"],"names":[],"version":3,"file":"types.d.ts.map"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truto/replace-placeholders",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Efficiently replace placeholders in strings, arrays, and objects using data from specified paths. Powered by 'wild-wild-path' and 'lodash' for robust functionality.",
|
|
5
5
|
"repository": "https://github.com/trutohq/replace-placeholders.git",
|
|
6
6
|
"dependencies": {
|
|
7
|
+
"deepmerge": "4.3.1",
|
|
7
8
|
"lodash-es": "4.17.21",
|
|
8
9
|
"traverse": "0.6.7",
|
|
9
10
|
"wild-wild-path": "4.0.0"
|
|
@@ -38,8 +39,10 @@
|
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@parcel/packager-ts": "2.8.3",
|
|
40
41
|
"@parcel/transformer-typescript-types": "2.8.3",
|
|
42
|
+
"@types/deepmerge": "2.2.3",
|
|
41
43
|
"@types/lodash-es": "4.17.7",
|
|
42
44
|
"@types/traverse": "0.6.32",
|
|
45
|
+
"@cloudflare/workers-types": "4.20250214.0",
|
|
43
46
|
"@typescript-eslint/eslint-plugin": "5.46.1",
|
|
44
47
|
"@typescript-eslint/parser": "5.46.1",
|
|
45
48
|
"eslint": "8.29.0",
|