@symbo.ls/utils 3.14.777 → 3.14.779
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/cjs/state.js +1 -1
- package/dist/cjs/string.js +3 -3
- package/dist/esm/state.js +1 -1
- package/dist/esm/string.js +3 -3
- package/package.json +1 -1
- package/state.js +61 -5
- package/string.js +14 -2
package/dist/cjs/state.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var d=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var E=(e,r)=>{for(var n in r)d(e,n,{get:r[n],enumerable:!0})},A=(e,r,n,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of v(r))!x.call(e,o)&&o!==n&&d(e,o,{get:()=>r[o],enumerable:!(t=j(r,o))||t.enumerable});return e};var I=e=>A(d({},"__esModule",{value:!0}),e);var U={};E(U,{applyDependentState:()=>B,checkForStateTypes:()=>D,checkIfInherits:()=>O,createInheritedState:()=>K,createNestedObjectByKeyPath:()=>T,findInheritedState:()=>m,getChildStateInKey:()=>w,getParentStateInKey:()=>P,getRootStateInKey:()=>b,isPolyglotRetranslatableKey:()=>F,isPolyglotWritableKey:()=>M,isState:()=>R,markPolyglotSeeded:()=>L,overwriteState:()=>C,polyglotSeededKeys:()=>p});module.exports=I(U);var S=require("./array.js"),f=require("./keys.js"),c=require("./object.js"),l=require("./types.js");const D=e=>{const{state:r,props:n,__ref:t}=e,o=n?.state||r;return(0,l.is)(o)("string","number")?(t.__state=o,{value:o}):o===!0?(t.__state=e.key,{}):o?(t.__hasRootState=!0,o):!1},b=(e,r)=>{if(!e.includes("~/"))return;if(e.split("~/").length>1)return r.root},P=(e,r)=>{if(!e.includes("../"))return;const t=e.split("../").length-1;for(let o=0;o<t;o++){if(!r.parent)return null;r=r.parent}return r},w=(e,r,n={})=>{const t=(0,l.isString)(e)?e.split("/"):[e],o=t.length-1;for(let i=0;i<o;i++){const s=t[i],u=t[i+1];if(s==="__proto__"||u==="__proto__")return;let a=r[s];a||(a=r[s]={}),a[u]||(a[u]={}),e=u,r=a}return n.returnParent?r:r[e]},m=(e,r,n={})=>{let o=e.__ref.__state;if(!O(e))return;const i=b(o,r.state);let s=r.state;if(i)s=i,o=o.replaceAll("~/","");else{const u=P(o,r.state);u&&(s=u,o=o.replaceAll("../",""))}if(s)return w(o,s,n)},K=(e,r)=>{const n=e.__ref,t=m(e,r);if(t===void 0)return e.state;if((0,l.is)(t)("object","array"))return(0,c.deepClone)(t);if((0,l.is)(t)("string","number","boolean"))return n.__stateType=typeof t,{value:t};console.warn(n.__state,"is not present. Replacing with",{})},O=e=>{const{__ref:r}=e,n=r?.__state;return!!(n&&(0,l.is)(n)("number","string","boolean"))},R=function(e){return(0,l.isObjectLike)(e)?!!(e.update&&e.parse&&e.clean&&e.create&&e.parent&&e.destroy&&e.rootUpdate&&e.parentUpdate&&e.keys&&e.values&&e.toggle&&e.replace&&e.quietUpdate&&e.quietReplace&&e.add&&e.apply&&e.applyReplace&&e.setByPath&&e.setPathCollection&&e.removeByPath&&e.removePathCollection&&e.getByPath&&e.applyFunction&&e.__element&&e.__children):!1},T=(e,r)=>{if(!e)return r||{};const n=e.split("/"),t={};let o=t;const i=n.length-1;for(let s=0;s<=i;s++)o[n[s]]=s===i?r||{}:{},o=o[n[s]];return t},B=(e,r)=>{const{__element:n}=r,t=n?.state;if(!t)return;const o=(0,c.deepClone)(t,f.STATE_METHODS),i={[e.key]:o},s=(0,l.isObject)(t.__depends)?{...t.__depends,...i}:i;return Array.isArray(t)?(0,S.addProtoToArray)(t,{...Object.getPrototypeOf(t),__depends:s}):Object.setPrototypeOf(t,{...Object.getPrototypeOf(t),__depends:s}),o},C=(e,r,n={})=>{const{overwrite:t}=n;if(!t)return;const o=t==="shallow";if(t==="merge"){(0,c.deepMerge)(e,r,f.STATE_METHODS);return}(o?c.overwriteShallow:c.overwriteDeep)(e,r,f.STATE_METHODS)},_="__polyglotSeededKeys",p=e=>{if(!(0,l.isObject)(e))return new Set;let r=e[_];if(!(r instanceof Set)){r=new Set;try{Object.defineProperty(e,_,{value:r,enumerable:!1,writable:!0,configurable:!0})}catch{}}return r},M=(e,r,n)=>p(e).has(r)?!0:!(0,l.isObject)(n)||n[r]===void 0,g="__polyglotSeededValues",y=e=>{if(!(0,l.isObject)(e))return new Map;let r=e[g];if(!(r instanceof Map)){r=new Map;try{Object.defineProperty(e,g,{value:r,enumerable:!1,writable:!0,configurable:!0})}catch{}}return r},h=e=>{if(e===null||typeof e!="object")return typeof e+":"+String(e);try{return"json:"+JSON.stringify(e)}catch{return null}},F=(e,r,n)=>{if(!p(e).has(r))return!1;const t=y(e);if(!t.has(r))return!0;const o=(0,l.isObject)(n)||Array.isArray(n)?n[r]:void 0,i=h(o);return i!==null&&i===t.get(r)},L=(e,r,...n)=>(p(e).add(r),n.length&&y(e).set(r,h(n[0])),r);
|
package/dist/cjs/string.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`);let s=-1,c=-1,
|
|
3
|
-
`).replace(/\/\/\/\/\/tilde/g,"`").replace(/\/\/\/\/\/dlrsgn/g,"$"),
|
|
1
|
+
"use strict";var w=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var O=(e,n)=>{for(var t in n)w(e,t,{get:n[t],enumerable:!0})},R=(e,n,t,s)=>{if(n&&typeof n=="object"||typeof n=="function")for(let c of j(n))!N.call(e,c)&&c!==t&&w(e,c,{get:()=>n[c],enumerable:!(s=L(n,c))||s.enumerable});return e};var I=e=>R(w({},"__esModule",{value:!0}),e);var W={};O(W,{customDecodeURIComponent:()=>M,customEncodeURIComponent:()=>z,decodeNewlines:()=>P,encodeNewlines:()=>K,findKeyPosition:()=>U,lowercaseFirstLetter:()=>v,replaceLiteralsWithObjectFields:()=>T,replaceOctalEscapeSequences:()=>D,stringIncludesAny:()=>k,trimStringFromSymbols:()=>E});module.exports=I(W);const k=(e,n)=>{for(const t of n)if(e.includes(t))return!0;return!1},E=(e,n)=>{const t=new RegExp(`[${n.join("\\")}]`,"g");return e.replace(t,"")},$={2:/{{\s*((?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}/g,3:/{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}}/g},m=(e,n)=>n.split(".").reduce((t,s)=>t?.[s],e),F=(e,n)=>{if(!e||!e.__ref)return!0;let t=e;for(;t;){if(t.allowRuntimeTemplates===!0)return!0;const s=t.__ref&&t.__ref.__authoredTemplates;if(s&&s.has(n))return!0;t=t.parent}return!1};function T(e,n,t={}){const{bracketsLength:s=2,authored:c=!1}=t,h=s===3?"{{{":"{{";if(!e.includes(h)||c!==!0&&!F(this,e))return e;const p=$[s],f=n||this.state||{},l=this;return e.replace(p,(x,r,b,g)=>{const i=b.trim();if(g){const a=l?.context,o=a?.functions?.[g]||a?.utils?.[g]||a?.methods?.[g]||a?.snippets?.[g]||l?.[g];if(o&&typeof o=="function")try{return String(o.call(l,i)??"")}catch{return""}return""}if(r){const a=(r.match(/\.\.\//g)||[]).length;let o=f;for(let u=0;u<a;u++){if(!o||!o.parent)return"";o=o.parent}if(i==="parent")return String(o.value??"");const d=m(o,i);return d!=null&&typeof d=="object"?"":String(d??"")}else{const a=m(f,i);if(a!=null&&typeof a!="object")return String(a);const o=l?.context?.polyglot;if(o?.translations){const d=f?.root?.lang||f?.lang||l?.context?.state?.lang||o.defaultLang||"en",u=o.translations[d];if(u){const S=m(u,i);if(S!=null&&typeof S!="object")return String(S);for(const A in u){const y=u[A];if(y&&typeof y=="object"&&!Array.isArray(y)){const _=m(y,i);if(_!=null&&typeof _!="object")return String(_)}}}const C=m(o.translations,i);if(C!=null&&typeof C!="object")return String(C)}return""}})}const v=e=>`${e.charAt(0).toLowerCase()}${e.slice(1)}`,U=(e,n)=>{const t=e.split(`
|
|
2
|
+
`);let s=-1,c=-1,h=-1,p=-1;const f=new RegExp(`\\b${n}\\b\\s*:\\s*`);let l=0,x=!1;for(let r=0;r<t.length;r++)if(f.test(t[r])&&!x){if(x=!0,s=r+1,h=t[r].indexOf(n)+1,t[r].includes("{}")){c=s,p=t[r].indexOf("{}")+3;break}const b=t[r].slice(h+n.length);if(b.includes("{")||b.includes("["))l=1;else{c=r+1,p=t[r].length+1;break}}else if(x&&(l+=(t[r].match(/{/g)||[]).length,l+=(t[r].match(/\[/g)||[]).length,l-=(t[r].match(/}/g)||[]).length,l-=(t[r].match(/]/g)||[]).length,l===0)){c=r+1,p=t[r].lastIndexOf("}")!==-1?t[r].lastIndexOf("}")+2:t[r].length+1;break}return{startColumn:h,endColumn:p,startLineNumber:s,endLineNumber:c}},V=/\\([0-7]{1,3})/g,D=e=>e.replace(V,(n,t)=>String.fromCharCode(parseInt(t,8))),K=e=>e.replace(/\n/g,"/////n").replace(/`/g,"/////tilde").replace(/\$/g,"/////dlrsgn"),P=e=>e.replace(/\/\/\/\/\/n/g,`
|
|
3
|
+
`).replace(/\/\/\/\/\/tilde/g,"`").replace(/\/\/\/\/\/dlrsgn/g,"$"),q=/[^a-zA-Z0-9\s]/g,z=e=>e.replace(q,n=>"%"+n.charCodeAt(0).toString(16).toUpperCase()),M=e=>e.replace(/%[0-9A-Fa-f]{2}/g,n=>String.fromCharCode(parseInt(n.slice(1),16)));
|
package/dist/esm/state.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{addProtoToArray as
|
|
1
|
+
import{addProtoToArray as S}from"./array.js";import{STATE_METHODS as f}from"./keys.js";import{deepClone as d,deepMerge as b,overwriteDeep as P,overwriteShallow as w}from"./object.js";import{is as a,isObject as u,isObjectLike as m,isString as O}from"./types.js";const T=e=>{const{state:r,props:n,__ref:t}=e,o=n?.state||r;return a(o)("string","number")?(t.__state=o,{value:o}):o===!0?(t.__state=e.key,{}):o?(t.__hasRootState=!0,o):!1},j=(e,r)=>{if(!e.includes("~/"))return;if(e.split("~/").length>1)return r.root},v=(e,r)=>{if(!e.includes("../"))return;const t=e.split("../").length-1;for(let o=0;o<t;o++){if(!r.parent)return null;r=r.parent}return r},x=(e,r,n={})=>{const t=O(e)?e.split("/"):[e],o=t.length-1;for(let i=0;i<o;i++){const s=t[i],l=t[i+1];if(s==="__proto__"||l==="__proto__")return;let c=r[s];c||(c=r[s]={}),c[l]||(c[l]={}),e=l,r=c}return n.returnParent?r:r[e]},E=(e,r,n={})=>{let o=e.__ref.__state;if(!A(e))return;const i=j(o,r.state);let s=r.state;if(i)s=i,o=o.replaceAll("~/","");else{const l=v(o,r.state);l&&(s=l,o=o.replaceAll("../",""))}if(s)return x(o,s,n)},B=(e,r)=>{const n=e.__ref,t=E(e,r);if(t===void 0)return e.state;if(a(t)("object","array"))return d(t);if(a(t)("string","number","boolean"))return n.__stateType=typeof t,{value:t};console.warn(n.__state,"is not present. Replacing with",{})},A=e=>{const{__ref:r}=e,n=r?.__state;return!!(n&&a(n)("number","string","boolean"))},C=function(e){return m(e)?!!(e.update&&e.parse&&e.clean&&e.create&&e.parent&&e.destroy&&e.rootUpdate&&e.parentUpdate&&e.keys&&e.values&&e.toggle&&e.replace&&e.quietUpdate&&e.quietReplace&&e.add&&e.apply&&e.applyReplace&&e.setByPath&&e.setPathCollection&&e.removeByPath&&e.removePathCollection&&e.getByPath&&e.applyFunction&&e.__element&&e.__children):!1},M=(e,r)=>{if(!e)return r||{};const n=e.split("/"),t={};let o=t;const i=n.length-1;for(let s=0;s<=i;s++)o[n[s]]=s===i?r||{}:{},o=o[n[s]];return t},F=(e,r)=>{const{__element:n}=r,t=n?.state;if(!t)return;const o=d(t,f),i={[e.key]:o},s=u(t.__depends)?{...t.__depends,...i}:i;return Array.isArray(t)?S(t,{...Object.getPrototypeOf(t),__depends:s}):Object.setPrototypeOf(t,{...Object.getPrototypeOf(t),__depends:s}),o},L=(e,r,n={})=>{const{overwrite:t}=n;if(!t)return;const o=t==="shallow";if(t==="merge"){b(e,r,f);return}(o?w:P)(e,r,f)},_="__polyglotSeededKeys",p=e=>{if(!u(e))return new Set;let r=e[_];if(!(r instanceof Set)){r=new Set;try{Object.defineProperty(e,_,{value:r,enumerable:!1,writable:!0,configurable:!0})}catch{}}return r},U=(e,r,n)=>p(e).has(r)?!0:!u(n)||n[r]===void 0,g="__polyglotSeededValues",y=e=>{if(!u(e))return new Map;let r=e[g];if(!(r instanceof Map)){r=new Map;try{Object.defineProperty(e,g,{value:r,enumerable:!1,writable:!0,configurable:!0})}catch{}}return r},h=e=>{if(e===null||typeof e!="object")return typeof e+":"+String(e);try{return"json:"+JSON.stringify(e)}catch{return null}},k=(e,r,n)=>{if(!p(e).has(r))return!1;const t=y(e);if(!t.has(r))return!0;const o=u(n)||Array.isArray(n)?n[r]:void 0,i=h(o);return i!==null&&i===t.get(r)},V=(e,r,...n)=>(p(e).add(r),n.length&&y(e).set(r,h(n[0])),r);export{F as applyDependentState,T as checkForStateTypes,A as checkIfInherits,B as createInheritedState,M as createNestedObjectByKeyPath,E as findInheritedState,x as getChildStateInKey,v as getParentStateInKey,j as getRootStateInKey,k as isPolyglotRetranslatableKey,U as isPolyglotWritableKey,C as isState,V as markPolyglotSeeded,L as overwriteState,p as polyglotSeededKeys};
|
package/dist/esm/string.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const
|
|
2
|
-
`);let
|
|
3
|
-
`).replace(/\/\/\/\/\/tilde/g,"`").replace(/\/\/\/\/\/dlrsgn/g,"$"),
|
|
1
|
+
const O=(t,r)=>{for(const e of r)if(t.includes(e))return!0;return!1},R=(t,r)=>{const e=new RegExp(`[${r.join("\\")}]`,"g");return t.replace(e,"")},A={2:/{{\s*((?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}/g,3:/{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}}/g},m=(t,r)=>r.split(".").reduce((e,c)=>e?.[c],t),L=(t,r)=>{if(!t||!t.__ref)return!0;let e=t;for(;e;){if(e.allowRuntimeTemplates===!0)return!0;const c=e.__ref&&e.__ref.__authoredTemplates;if(c&&c.has(r))return!0;e=e.parent}return!1};function I(t,r,e={}){const{bracketsLength:c=2,authored:u=!1}=e,h=c===3?"{{{":"{{";if(!t.includes(h)||u!==!0&&!L(this,t))return t;const p=A[c],f=r||this.state||{},s=this;return t.replace(p,(x,n,b,g)=>{const a=b.trim();if(g){const l=s?.context,o=l?.functions?.[g]||l?.utils?.[g]||l?.methods?.[g]||l?.snippets?.[g]||s?.[g];if(o&&typeof o=="function")try{return String(o.call(s,a)??"")}catch{return""}return""}if(n){const l=(n.match(/\.\.\//g)||[]).length;let o=f;for(let i=0;i<l;i++){if(!o||!o.parent)return"";o=o.parent}if(a==="parent")return String(o.value??"");const d=m(o,a);return d!=null&&typeof d=="object"?"":String(d??"")}else{const l=m(f,a);if(l!=null&&typeof l!="object")return String(l);const o=s?.context?.polyglot;if(o?.translations){const d=f?.root?.lang||f?.lang||s?.context?.state?.lang||o.defaultLang||"en",i=o.translations[d];if(i){const S=m(i,a);if(S!=null&&typeof S!="object")return String(S);for(const w in i){const y=i[w];if(y&&typeof y=="object"&&!Array.isArray(y)){const _=m(y,a);if(_!=null&&typeof _!="object")return String(_)}}}const C=m(o.translations,a);if(C!=null&&typeof C!="object")return String(C)}return""}})}const k=t=>`${t.charAt(0).toLowerCase()}${t.slice(1)}`,E=(t,r)=>{const e=t.split(`
|
|
2
|
+
`);let c=-1,u=-1,h=-1,p=-1;const f=new RegExp(`\\b${r}\\b\\s*:\\s*`);let s=0,x=!1;for(let n=0;n<e.length;n++)if(f.test(e[n])&&!x){if(x=!0,c=n+1,h=e[n].indexOf(r)+1,e[n].includes("{}")){u=c,p=e[n].indexOf("{}")+3;break}const b=e[n].slice(h+r.length);if(b.includes("{")||b.includes("["))s=1;else{u=n+1,p=e[n].length+1;break}}else if(x&&(s+=(e[n].match(/{/g)||[]).length,s+=(e[n].match(/\[/g)||[]).length,s-=(e[n].match(/}/g)||[]).length,s-=(e[n].match(/]/g)||[]).length,s===0)){u=n+1,p=e[n].lastIndexOf("}")!==-1?e[n].lastIndexOf("}")+2:e[n].length+1;break}return{startColumn:h,endColumn:p,startLineNumber:c,endLineNumber:u}},j=/\\([0-7]{1,3})/g,$=t=>t.replace(j,(r,e)=>String.fromCharCode(parseInt(e,8))),F=t=>t.replace(/\n/g,"/////n").replace(/`/g,"/////tilde").replace(/\$/g,"/////dlrsgn"),T=t=>t.replace(/\/\/\/\/\/n/g,`
|
|
3
|
+
`).replace(/\/\/\/\/\/tilde/g,"`").replace(/\/\/\/\/\/dlrsgn/g,"$"),N=/[^a-zA-Z0-9\s]/g,v=t=>t.replace(N,r=>"%"+r.charCodeAt(0).toString(16).toUpperCase()),U=t=>t.replace(/%[0-9A-Fa-f]{2}/g,r=>String.fromCharCode(parseInt(r.slice(1),16)));export{U as customDecodeURIComponent,v as customEncodeURIComponent,T as decodeNewlines,F as encodeNewlines,E as findKeyPosition,k as lowercaseFirstLetter,I as replaceLiteralsWithObjectFields,$ as replaceOctalEscapeSequences,O as stringIncludesAny,R as trimStringFromSymbols};
|
package/package.json
CHANGED
package/state.js
CHANGED
|
@@ -250,10 +250,14 @@ export const polyglotSeededKeys = (context) => {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
/**
|
|
253
|
-
* May
|
|
254
|
-
* before, or when nothing declares it yet. A key a project, an app or a
|
|
253
|
+
* May BOOT seeding write `key` into the root state? Only when polyglot seeded
|
|
254
|
+
* it before, or when nothing declares it yet. A key a project, an app or a
|
|
255
255
|
* shared library declares is never polyglot's to overwrite.
|
|
256
256
|
*
|
|
257
|
+
* A language SWITCH asks `isPolyglotRetranslatableKey` instead: "nothing
|
|
258
|
+
* declares it yet" is true of every app flag that is not in state.js, so on a
|
|
259
|
+
* switch it handed any such flag whose NAME matched a text key that key's text.
|
|
260
|
+
*
|
|
257
261
|
* @param {object} context - the app context carrying the seeded-key record
|
|
258
262
|
* @param {string} key - the translation key about to be written
|
|
259
263
|
* @param {object} [declared] - the state to test the key against
|
|
@@ -263,11 +267,63 @@ export const isPolyglotWritableKey = (context, key, declared) => {
|
|
|
263
267
|
return !isObject(declared) || declared[key] === undefined
|
|
264
268
|
}
|
|
265
269
|
|
|
270
|
+
// What polyglot last wrote into each key it seeded — a signature, so a store
|
|
271
|
+
// proxy over the same array or object still matches. Non-enumerable on the
|
|
272
|
+
// context, like SEEDED_KEYS.
|
|
273
|
+
const SEEDED_VALUES = '__polyglotSeededValues'
|
|
274
|
+
const seededValues = (context) => {
|
|
275
|
+
if (!isObject(context)) return new Map()
|
|
276
|
+
let values = context[SEEDED_VALUES]
|
|
277
|
+
if (!(values instanceof Map)) {
|
|
278
|
+
values = new Map()
|
|
279
|
+
try {
|
|
280
|
+
Object.defineProperty(context, SEEDED_VALUES, {
|
|
281
|
+
value: values,
|
|
282
|
+
enumerable: false,
|
|
283
|
+
writable: true,
|
|
284
|
+
configurable: true
|
|
285
|
+
})
|
|
286
|
+
} catch (e) { /* a frozen context keeps no record — see polyglotSeededKeys */ }
|
|
287
|
+
}
|
|
288
|
+
return values
|
|
289
|
+
}
|
|
290
|
+
const seededSignature = (value) => {
|
|
291
|
+
if (value === null || typeof value !== 'object') return typeof value + ':' + String(value)
|
|
292
|
+
try { return 'json:' + JSON.stringify(value) } catch (e) { return null }
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* May a language SWITCH (setLang) write `key` into the root state? Only when
|
|
297
|
+
* polyglot seeded the key itself AND the slot still holds exactly what
|
|
298
|
+
* polyglot wrote. Never by name alone:
|
|
299
|
+
* - a key polyglot never seeded is the app's, even when it is empty — an
|
|
300
|
+
* undeclared app flag whose name matches a text key stays untouched
|
|
301
|
+
* (measured on dev, CRM app 1.0.87, 2026-10-01: an en <-> ka switch wrote
|
|
302
|
+
* "Delete deal" into the `crmDealDelete` open flag and opened the dialog);
|
|
303
|
+
* - a seeded key the app has since set to its own value is the app's now.
|
|
304
|
+
* A bare `{{ key }}` template still translates: the template resolver falls
|
|
305
|
+
* back to the active translation map when the state holds nothing.
|
|
306
|
+
*
|
|
307
|
+
* @param {object} context - the app context carrying the seeded-key record
|
|
308
|
+
* @param {string} key - the translation key about to be written
|
|
309
|
+
* @param {object} [current] - the root state holding the key now
|
|
310
|
+
*/
|
|
311
|
+
export const isPolyglotRetranslatableKey = (context, key, current) => {
|
|
312
|
+
if (!polyglotSeededKeys(context).has(key)) return false
|
|
313
|
+
const values = seededValues(context)
|
|
314
|
+
if (!values.has(key)) return true // seeded by a caller that recorded no value
|
|
315
|
+
const now = isObject(current) || Array.isArray(current) ? current[key] : undefined
|
|
316
|
+
const sig = seededSignature(now)
|
|
317
|
+
return sig !== null && sig === values.get(key)
|
|
318
|
+
}
|
|
319
|
+
|
|
266
320
|
/**
|
|
267
|
-
* Record that polyglot seeded `key
|
|
268
|
-
* it
|
|
321
|
+
* Record that polyglot seeded `key` (and, when given, the value it wrote), so
|
|
322
|
+
* a later language switch may retranslate it while the slot still holds that
|
|
323
|
+
* value. Returns the key, for use inline.
|
|
269
324
|
*/
|
|
270
|
-
export const markPolyglotSeeded = (context, key) => {
|
|
325
|
+
export const markPolyglotSeeded = (context, key, ...written) => {
|
|
271
326
|
polyglotSeededKeys(context).add(key)
|
|
327
|
+
if (written.length) seededValues(context).set(key, seededSignature(written[0]))
|
|
272
328
|
return key
|
|
273
329
|
}
|
package/string.js
CHANGED
|
@@ -60,6 +60,16 @@ const getNestedValue = (obj, path) => {
|
|
|
60
60
|
* function invocation from that element's content — never set it on an
|
|
61
61
|
* element that renders text a user or a model produced.
|
|
62
62
|
*
|
|
63
|
+
* `{ authored: true }` in `replaceLiteralsWithObjectFields`' options is the
|
|
64
|
+
* one other authority, and it is per CALL: the caller states that it read
|
|
65
|
+
* THIS string as a literal out of a project definition, so it is author-time
|
|
66
|
+
* by construction. `@symbo.ls/helmet`'s `extractMetadata` is that caller — it
|
|
67
|
+
* reads page and app `metadata` straight out of project data and resolves
|
|
68
|
+
* them against the ROOT element (brender's SSR head), while a page literal is
|
|
69
|
+
* only ever recorded on the page element `create()` built. Never pass it for
|
|
70
|
+
* a string a factory returned, a state value or any other data: the flag is
|
|
71
|
+
* a claim about where the string came from, and nothing checks it.
|
|
72
|
+
*
|
|
63
73
|
* This reads `this` by duck-typing (`__ref`, `parent`), exactly as the state
|
|
64
74
|
* and polyglot lookups below already do — `utils` never imports `element`.
|
|
65
75
|
* A caller with no `__ref` is not an element (a bare util call, a test) and
|
|
@@ -78,10 +88,12 @@ const isAuthoredTemplate = (element, str) => {
|
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
export function replaceLiteralsWithObjectFields (str, state, options = {}) {
|
|
81
|
-
const { bracketsLength = 2 } = options
|
|
91
|
+
const { bracketsLength = 2, authored = false } = options
|
|
82
92
|
const bracketPattern = bracketsLength === 3 ? '{{{' : '{{'
|
|
83
93
|
if (!str.includes(bracketPattern)) return str
|
|
84
|
-
|
|
94
|
+
// `authored` — see isAuthoredTemplate: a caller holding the definition
|
|
95
|
+
// vouches for this one literal. Anything else needs the element record.
|
|
96
|
+
if (authored !== true && !isAuthoredTemplate(this, str)) return str
|
|
85
97
|
|
|
86
98
|
const reg = brackRegex[bracketsLength]
|
|
87
99
|
const obj = state || this.state || {}
|