@truto/replace-placeholders 1.0.5 → 1.0.6

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/dist/main.cjs CHANGED
@@ -111,9 +111,11 @@ function $72af1098ef591494$export$2e2bcd8739ae039(obj, context) {
111
111
  if ((0, $g5Y9E$lodashes.isString)(obj)) return (0, $a169b0c20575e4d3$export$2e2bcd8739ae039)(obj, context);
112
112
  if ((0, $g5Y9E$lodashes.isArray)(obj)) return obj.map((item)=>$72af1098ef591494$export$2e2bcd8739ae039(item, context));
113
113
  if ((0, $g5Y9E$lodashes.isPlainObject)(obj)) {
114
- // First pass: replace all string placeholders
114
+ // First pass: replace all string placeholders and track if $truto_merge exists
115
+ let hasMergeKey = false;
115
116
  const replaced = (0, ($parcel$interopDefault($g5Y9E$traverse)))(obj).map(function(value) {
116
117
  if (this.circular) this.remove();
118
+ else if ((0, $g5Y9E$lodashes.isPlainObject)(value) && "$truto_merge" in value) hasMergeKey = true;
117
119
  else if ((0, $g5Y9E$lodashes.isString)(value)) this.update((0, $a169b0c20575e4d3$export$2e2bcd8739ae039)(value, context));
118
120
  else if ((0, $g5Y9E$lodashes.isArrayBuffer)(value) || value instanceof Blob) {
119
121
  const val = (0, $g5Y9E$lodashes.get)(obj, this.path);
@@ -121,7 +123,8 @@ function $72af1098ef591494$export$2e2bcd8739ae039(obj, context) {
121
123
  this.block();
122
124
  }
123
125
  });
124
- // Second pass: handle $truto_merge
126
+ // Second pass: handle $truto_merge (only if needed)
127
+ if (!hasMergeKey) return replaced;
125
128
  return (0, ($parcel$interopDefault($g5Y9E$traverse)))(replaced).map(function(value) {
126
129
  if (this.circular) this.remove();
127
130
  else if ((0, $g5Y9E$lodashes.isPlainObject)(value) && "$truto_merge" in value) {
package/dist/main.cjs.map CHANGED
@@ -1 +1 @@
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"}
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 and track if $truto_merge exists\n let hasMergeKey = false\n const replaced = traverse(obj).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isPlainObject(value) && '$truto_merge' in value) {\n hasMergeKey = true\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 (only if needed)\n if (!hasMergeKey) {\n return replaced as T\n }\n\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
@@ -98,9 +98,11 @@ function $4e62acd4800cacd9$export$2e2bcd8739ae039(obj, context) {
98
98
  if ((0, $hCgyA$isString)(obj)) return (0, $67f2b908c91abfcc$export$2e2bcd8739ae039)(obj, context);
99
99
  if ((0, $hCgyA$isArray)(obj)) return obj.map((item)=>$4e62acd4800cacd9$export$2e2bcd8739ae039(item, context));
100
100
  if ((0, $hCgyA$isPlainObject)(obj)) {
101
- // First pass: replace all string placeholders
101
+ // First pass: replace all string placeholders and track if $truto_merge exists
102
+ let hasMergeKey = false;
102
103
  const replaced = (0, $hCgyA$traverse)(obj).map(function(value) {
103
104
  if (this.circular) this.remove();
105
+ else if ((0, $hCgyA$isPlainObject)(value) && "$truto_merge" in value) hasMergeKey = true;
104
106
  else if ((0, $hCgyA$isString)(value)) this.update((0, $67f2b908c91abfcc$export$2e2bcd8739ae039)(value, context));
105
107
  else if ((0, $hCgyA$isArrayBuffer)(value) || value instanceof Blob) {
106
108
  const val = (0, $hCgyA$get)(obj, this.path);
@@ -108,7 +110,8 @@ function $4e62acd4800cacd9$export$2e2bcd8739ae039(obj, context) {
108
110
  this.block();
109
111
  }
110
112
  });
111
- // Second pass: handle $truto_merge
113
+ // Second pass: handle $truto_merge (only if needed)
114
+ if (!hasMergeKey) return replaced;
112
115
  return (0, $hCgyA$traverse)(replaced).map(function(value) {
113
116
  if (this.circular) this.remove();
114
117
  else if ((0, $hCgyA$isPlainObject)(value) && "$truto_merge" in value) {
@@ -1 +1 @@
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"}
1
+ {"mappings":";;;;;ACAA;;;ACAA;;AAGA,SAAS,8BACP,MAAM,EAAE,EACR,MAAc,CAAC,CAAC,EAQN;IACV,MAAM,QAAQ;IACd,MAAM,iBAAiB;IACvB,MAAM,UAAU,IAAI,KAAK,CAAC;IAC1B,IAAI,SAAuB;IAE3B,IAAI,SACF,QAAQ,OAAO,CAAC,CAAA,QAAS;QACvB,MAAM,CAAC,UAAU,WAAW,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC;QACxD,MAAM,QAAQ,SAAS,KAAK,CAAC;QAC7B,MAAM,gBAAgB,MAAM,IAAI,CAAC,CAAA,OAAQ,KAAK,QAAQ,CAAC;QACvD,MAAM,oBAAoB,MAAM,IAAI,CAAC,CAAA,OACnC,KAAK,QAAQ,CAAC;QAEhB,MAAM,eAAe,MAAM,IAAI,CAAC,CAAA,OAAQ,KAAK,QAAQ,CAAC;QAEtD,MAAM,gBAAgB,UAAU;QAEhC,IAAI,QAAa;QACjB,KAAK,MAAM,QAAQ,MAAO;YACxB,MAAM,CAAC,MAAM,GAAG,UAAU,GAAG,KAAK,KAAK,CAAC;YACxC,MAAM,OAAe,AAAC,CAAA,SAAS,CAAC,EAAE,IAAI,KAAI,EAAG,IAAI;YAEjD,MAAM,YAAY,CAAA,GAAA,WAAO,AAAD,EAAE,KAAK,KAAK,IAAI;YACxC,IAAI,cAAc,MAAM,mBACtB,QAAQ;YAEV,IAAI,cAAc,WAAW;gBAC3B,QAAQ,+BAAS,WAAW,MAAM;gBAClC,KAAK;YACP,CAAC;QACH;QAEA,IAAI,UAAU,aAAa,YAAY;YACrC,MAAM,CAAC,cAAc,YAAY,GAAG,WAAW,KAAK,CAAC;YACrD,MAAM,OAAO,eAAe;YAC5B,QAAQ,+BAAS,cAAc,MAAM;QACvC,OAAO,IAAI,UAAU,WAAW;YAC9B,IAAI;gBACF,IAAI,eACF,QAAQ;qBAER,QAAQ;mBAEL,IAAI,eACT,QAAQ,IAAI;iBAEZ,QAAQ,MAAM,8BAA8B;;QAEhD,CAAC;QAED,IAAI,UAAU,KACZ,SAAS;aAET,SAAS,OAAO,OAAO,CAAC,OAAO;IAEnC;IAGF,OAAO;AACT;AAEA,SAAS,+BACP,KAAc,EACd,IAAY,EACZ,aAAsB,EAQZ;IACV,IAAI,UAAU,aAAa,UAAU,IAAI,EAAE,OAAO;IAElD,IAAI,eAAe;IACnB,IAAI,CAAA,GAAA,eAAQ,AAAD,EAAE,UAAU,SAAS,OAC9B,eAAe,CAAA,GAAA,WAAG,EAAE;IAGtB,IACE,wBAAwB,QACxB,wBAAwB,kBACxB,wBAAwB,kBACxB,wBAAwB,iBAExB,OAAO;IAGT,IAAI;IACJ,OAAQ;QACN,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,IAAI,iBAAiB,UAAU,iBAAiB,IAAI,EAAE,OAAO,IAAI;YACjE,OAAO,gBAAgB,eAAe,MAAM;QAC9C,KAAK;YACH,YAAY,SAAS;YACrB,OAAO,MAAM,aAAa,eAAe,SAAS;QACpD,KAAK;YACH,YAAY,WAAW;YACvB,OAAO,MAAM,aAAa,eAAe,SAAS;QACpD,KAAK;YACH,OAAO,CAAA,GAAA,eAAO,EAAE;QAClB,KAAK;YACH,IAAI,iBAAiB,UAAU,iBAAiB,IAAI,EAAE,OAAO,IAAI;YACjE,IAAI,iBAAiB,WAAW,iBAAiB,KAAK,EAAE,OAAO,KAAK;YACpE,OAAO,aAAa,0DAA0D;;QAChF,KAAK;YACH,IAAI,eAAe;gBACjB,IAAI,CAAA,GAAA,oBAAY,EAAE,iBAAiB,CAAA,GAAA,cAAO,AAAD,EAAE,eACzC,OAAO;gBACT,IAAI;oBACF,OAAO,KAAK,KAAK,CAAC;gBACpB,EAAE,OAAO,KAAK;oBACZ,OAAO;gBACT;YACF,CAAC;YACD,OAAO;QACT,KAAK;YACH,OAAO;QACT;YACE,MAAM,IAAI,MAAM,CAAC,kBAAkB,EAAE,KAAK,CAAC,EAAC;IAChD;AACF;IAEA,2CAAe;;;AD1IA,kDACb,GAAsE,EACtE,OAAgC,EAC7B;IACH,IAAI,CAAA,GAAA,eAAO,EAAE,MACX,OAAO,CAAA,GAAA,wCAAM,EAAE,KAAK;IAGtB,IAAI,CAAA,GAAA,cAAO,AAAD,EAAE,MACV,OAAO,IAAI,GAAG,CAAC,CAAA,OAAQ,yCAAoB,MAAM;IAGnD,IAAI,CAAA,GAAA,oBAAa,AAAD,EAAE,MAAM;QACtB,+EAA+E;QAC/E,IAAI,cAAc,KAAK;QACvB,MAAM,WAAW,CAAA,GAAA,eAAQ,AAAD,EAAE,KAAK,GAAG,CAAC,SAAU,KAAK,EAAE;YAClD,IAAI,IAAI,CAAC,QAAQ,EACf,IAAI,CAAC,MAAM;iBACN,IAAI,CAAA,GAAA,oBAAY,EAAE,UAAU,kBAAkB,OACnD,cAAc,IAAI;iBACb,IAAI,CAAA,GAAA,eAAQ,AAAD,EAAE,QAClB,IAAI,CAAC,MAAM,CAAC,CAAA,GAAA,wCAAO,AAAD,EAAE,OAAO;iBACtB,IAAI,CAAA,GAAA,oBAAY,EAAE,UAAU,iBAAiB,MAAM;gBACxD,MAAM,MAAM,CAAA,GAAA,UAAE,EAAE,KAAK,IAAI,CAAC,IAAI;gBAC9B,IAAI,CAAC,MAAM,CAAC;gBACZ,IAAI,CAAC,KAAK;YACZ,CAAC;QACH;QAEA,oDAAoD;QACpD,IAAI,CAAC,aACH,OAAO;QAGT,OAAO,CAAA,GAAA,eAAO,EAAE,UAAU,GAAG,CAAC,SAAU,KAAK,EAAE;YAC7C,IAAI,IAAI,CAAC,QAAQ,EACf,IAAI,CAAC,MAAM;iBACN,IAAI,CAAA,GAAA,oBAAY,EAAE,UAAU,kBAAkB,OAAO;gBAC1D,MAAM,aAAa,KAAK,CAAC,eAAe;gBACxC,MAAM,cAAc,CAAA,GAAA,cAAO,AAAD,EAAE,cAAc,aAAa;oBAAC;iBAAW;gBAEnE,wDAAwD;gBACxD,IAAI,SAAkC,CAAC;gBACvC,IAAK,MAAM,OAAO,MAChB,IAAI,QAAQ,gBACV,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI;gBAI5B,6DAA6D;gBAC7D,KAAK,MAAM,iBAAiB,YAC1B,oCAAoC;gBACpC,IAAI,CAAA,GAAA,oBAAY,EAAE,gBAChB,SAAS,CAAA,GAAA,gBAAQ,EAAE,QAAQ;gBAK/B,IAAI,CAAC,MAAM,CAAC;YACd,CAAC;QACH;IACF,CAAC;IAED,MAAM,IAAI,MAAM,gBAAe;AACjC;;ADpEA;IACA,2CAAe,CAAA,GAAA,wCAAkB","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 and track if $truto_merge exists\n let hasMergeKey = false\n const replaced = traverse(obj).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isPlainObject(value) && '$truto_merge' in value) {\n hasMergeKey = true\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 (only if needed)\n if (!hasMergeKey) {\n return replaced as T\n }\n\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"}
@@ -1 +1 @@
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"}
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,CA6DH;ACnED,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 and track if $truto_merge exists\n let hasMergeKey = false\n const replaced = traverse(obj).map(function (value) {\n if (this.circular) {\n this.remove()\n } else if (isPlainObject(value) && '$truto_merge' in value) {\n hasMergeKey = true\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 (only if needed)\n if (!hasMergeKey) {\n return replaced as T\n }\n\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,6 +1,6 @@
1
1
  {
2
2
  "name": "@truto/replace-placeholders",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
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": {