json-variables
Version:
Resolves custom-marked, cross-referenced paths in parsed JSON
17 lines (14 loc) • 10.3 kB
JavaScript
/**
* @name json-variables
* @fileoverview Resolves custom-marked, cross-referenced paths in parsed JSON
* @version 12.1.3
* @author Roy Revelt
* @license MIT
* {@link https://codsen.com/os/json-variables/}
*/
import{strFindHeadsTails as U}from"string-find-heads-tails";import{getByKey as F}from"ast-get-values-by-key";import{arrayiffy as ee}from"arrayiffy-if-string";import{traverse as re}from"ast-monkey-traverse";import{rApply as R}from"ranges-apply";import d from"object-path";import{Ranges as te}from"ranges-push";import{isPlainObject as E,existy as ne,isBool as J,isNull as v,isStr as p,isNum as H}from"codsen-utils";import{isStr as L}from"codsen-utils";function _(r){if(L(r)&&r.length&&r.indexOf(".")!==-1){for(let e=0,t=r.length;e<t;e++)if(r[e]===".")return r.slice(0,e)}return r}import{isStr as M}from"codsen-utils";function T(r){if(M(r)&&r.length&&r.indexOf(".")!==-1){for(let e=r.length;e--;)if(r[e]===".")return r.slice(0,e)}return r}import{isStr as K}from"codsen-utils";function A(r){if(K(r)&&r.length&&r.indexOf(".")!==-1){for(let e=r.length;e--;)if(r[e]===".")return r.slice(e+1)}return r}import{isStr as q}from"codsen-utils";function C(r){if(q(r)&&r.length&&r.indexOf(".")!==-1){for(let e=0,t=r.length;e<t;e++)if(r[e]===".")return r.slice(e+1)}return r}import{isStr as j}from"codsen-utils";function D(r,e){return!j(r)||!r.trim()?!1:!!(r.includes(e.heads)||r.includes(e.tails)||j(e.headsNoWrap)&&e.headsNoWrap.length&&r.includes(e.headsNoWrap)||j(e.tailsNoWrap)&&e.tailsNoWrap.length&&r.includes(e.tailsNoWrap))}import{isMatch as Q}from"matcher";import{remDup as X}from"string-remove-duplicate-heads-tails";import{isStr as G}from"codsen-utils";import{matchLeftIncl as z,matchRightIncl as Y}from"string-match-left-right";function x(r,e,t){let o,i;return G(r)&&r.length&&Y(r,0,e,{trimBeforeMatching:!0,cb:(n,l,a)=>(o=a,!0)})&&z(r,r.length-1,t,{trimBeforeMatching:!0,cb:(n,l,a)=>(i=(a||0)+1,!0)})?r.slice(o,i):r}import{isStr as S}from"codsen-utils";function I(r,e,t=!1,o,i,n){if(e.wrapHeadsWith||(e.wrapHeadsWith=""),e.wrapTailsWith||(e.wrapTailsWith=""),S(r)&&!t&&e.wrapGlobalFlipSwitch&&!e.dontWrapVars.some(l=>Q(n,l))&&(!e.preventDoubleWrapping||e.preventDoubleWrapping&&S(r)&&!r.includes(e.wrapHeadsWith)&&!r.includes(e.wrapTailsWith)))return`${e.wrapHeadsWith}${r}${e.wrapTailsWith}`;if(t){if(!S(r))return r;let l=X(r,{heads:e.wrapHeadsWith,tails:e.wrapTailsWith});return S(l)?x(l,e.wrapHeadsWith,e.wrapTailsWith):l}return r}var k="12.1.3";var Fe=k,le=Object.prototype.hasOwnProperty,oe={heads:"%%_",tails:"_%%",headsNoWrap:"%%-",tailsNoWrap:"-%%",lookForDataContainers:!0,dataContainerIdentifierTails:"_data",wrapHeadsWith:"",wrapTailsWith:"",dontWrapVars:[],preventDoubleWrapping:!0,wrapGlobalFlipSwitch:!0,noSingleMarkers:!1,resolveToBoolIfAnyValuesContainBool:!0,resolveToFalseIfAnyValuesContainBool:!0,throwWhenNonStringInsertedInString:!1,allowUnresolved:!1};function u(r){return p(r)?r.trim():r}function ae(r,e,t,o){let i;if(t.indexOf(".")!==-1){let n=t,l=!0;if(o.lookForDataContainers&&p(o.dataContainerIdentifierTails)&&o.dataContainerIdentifierTails.length&&!n.endsWith(o.dataContainerIdentifierTails)){let a=d.get(r,n+o.dataContainerIdentifierTails);E(a)&&d.get(a,e)&&(i=d.get(a,e),l=!1)}for(;l&&n.indexOf(".")!==-1;){if(n=T(n),A(n)===e)throw new Error(`json-variables/findValues(): [THROW_ID_20] While trying to resolve: "${e}" at path "${t}", we encountered a closed loop. The parent key "${A(n)}" is called the same as the variable "${e}" we're looking for.`);if(o.lookForDataContainers&&p(o.dataContainerIdentifierTails)&&o.dataContainerIdentifierTails.length&&!n.endsWith(o.dataContainerIdentifierTails)){let a=d.get(r,n+o.dataContainerIdentifierTails);E(a)&&d.get(a,e)&&(i=d.get(a,e),l=!1)}if(i===void 0){let a=d.get(r,n);E(a)&&d.get(a,e)&&(i=d.get(a,e),l=!1)}}}if(i===void 0){let n=d.get(r,e);n!==void 0&&(i=n)}if(i===void 0)if(e.indexOf(".")===-1){let n=F(r,e);if(n.length){for(let l=0,a=n.length;l<a;l++)if(p(n[l].val)||J(n[l].val)||v(n[l].val)){i=n[l].val;break}else if(H(n[l].val)){i=n[l].val;break}else if(Array.isArray(n[l].val)){i=n[l].val.join("");break}}}else{let n=F(r,_(e));if(n.length)for(let l=0,a=n.length;l<a;l++){let s=d.get(n[l].val,C(e));s&&p(s)&&(i=s)}}return i}function B(r,e,t,o,i=[]){if(i.includes(t)){let g="";if(i.length>1){let m=` \u2192
`;g=i.reduce((y,$,N)=>y+(N===0?"":m)+($===t?"\u{1F4A5} ":" ")+$,` Here's the path we travelled up until we hit the recursion:
`),g+=`${m}\u{1F4A5} ${t}`}throw new Error(`json-variables/resolveString(): [THROW_ID_19] While trying to resolve: "${e}" at path "${t}", we encountered a closed loop, the key is referencing itself."${g}`)}let n={},l=Array.from(i);l.push(t);let a=new te,s;function P(g,m,y){for(let $=0,N=g.length;$<N;$++){let f=g[$],h=e.slice(f.headsEndAt,f.tailsStartAt);if(h.length===0)a.push(f.headsStartAt,f.tailsEndAt);else if(le.call(n,h)&&p(n[h]))a.push(f.headsStartAt,f.tailsEndAt,n[h]);else{if(s=ae(r,h.trim(),t,o),s===void 0)if(o.allowUnresolved===!0)s="";else if(p(o.allowUnresolved))s=o.allowUnresolved;else throw new Error(`json-variables/processHeadsAndTails(): [THROW_ID_18] We couldn't find the value to resolve the variable ${e.slice(f.headsEndAt,f.tailsStartAt)}. We're at path: "${t}".`);if(!y&&o.throwWhenNonStringInsertedInString&&!p(s))throw new Error(`json-variables/processHeadsAndTails(): [THROW_ID_23] While resolving the variable ${e.slice(f.headsEndAt,f.tailsStartAt)} at path ${t}, it resolved into a non-string value, ${JSON.stringify(s,null,4)}. This is happening because options setting "throwWhenNonStringInsertedInString" is active (set to "true").`);if(J(s)){if(o.resolveToBoolIfAnyValuesContainBool)return a.wipe(),o.resolveToFalseIfAnyValuesContainBool?!1:s;s=""}else{if(v(s)&&y)return a.wipe(),s;Array.isArray(s)?s=String(s.join("")):v(s)?s="":(!H(s)||!y)&&(s=String(s))}let O=t.includes(".")?`${T(t)}.${h}`:h;if(D(s,o)){let b=I(B(r,s,O,o,l),o,m,l,O,h.trim());b!==!1&&a.push(f.headsStartAt,f.tailsEndAt,b)}else{n[h]=s;let b=I(s,o,m,l,O,h.trim());b!==!1&&a.push(f.headsStartAt,f.tailsEndAt,b)}}}}let c;try{c=U(e,o.heads,o.tails,{source:"",throwWhenSomethingWrongIsDetected:!1})}catch(g){throw new Error(`json-variables/resolveString(): [THROW_ID_17] While trying to resolve string: "${e}" at path ${t}, something wrong with heads and tails was detected! Here's the internal error message:
${g}`)}let V=!1;c.length===1&&R(e,[[c[0].headsStartAt,c[0].tailsEndAt]]).trim()===""&&(V=!0);let w=P(c,!1,V);if(typeof w=="boolean"||w===null)return w;try{c=U(e,o.headsNoWrap,o.tailsNoWrap,{source:"",throwWhenSomethingWrongIsDetected:!1})}catch(g){throw new Error(`json-variables/resolveString(): [THROW_ID_22] While trying to resolve string: "${e}" at path ${t}, something wrong with no-wrap heads and no-wrap tails was detected! Here's the internal error message:
${g}`)}c.length===1&&R(e,[[c[0].headsStartAt,c[0].tailsEndAt]]).trim()===""&&(V=!0);let W=P(c,!0,V);if(J(W)||v(W))return W;if(a?.current()){let g=a.current();if(V){if(typeof s=="number")return s;if(g?.length===1&&g[0].length===3&&H(g[0][2]))return g[0][2]}return R(e,g)}return e}function Be(r,e){if(!arguments.length)throw new Error("json-variables/jVar(): [THROW_ID_01] Alas! Inputs are missing!");if(!E(r))throw new TypeError(`json-variables/jVar(): [THROW_ID_02] Alas! The input must be a plain object! Currently it's: ${Array.isArray(r)?"array":typeof r}`);if(e&&!E(e))throw new TypeError(`json-variables/jVar(): [THROW_ID_03] Alas! An Optional Options Object must be a plain object! Currently it's: ${Array.isArray(e)?"array":typeof e}`);let t={...oe,...e};t.dontWrapVars?Array.isArray(t.dontWrapVars)||(t.dontWrapVars=ee(t.dontWrapVars)):t.dontWrapVars=[];let o,i;if(t.dontWrapVars.length&&!t.dontWrapVars.every((l,a)=>p(l)?!0:(o=l,i=a,!1)))throw new Error(`json-variables/jVar(): [THROW_ID_05] Alas! All variable names set in resolvedOpts.dontWrapVars should be of a string type. Computer detected a value "${o}" at index ${i}, which is not string but ${Array.isArray(o)?"array":typeof o}!`);if(t.heads==="")throw new Error("json-variables/jVar(): [THROW_ID_06] Alas! resolvedOpts.heads are empty!");if(t.tails==="")throw new Error("json-variables/jVar(): [THROW_ID_07] Alas! resolvedOpts.tails are empty!");if(t.lookForDataContainers&&t.dataContainerIdentifierTails==="")throw new Error("json-variables/jVar(): [THROW_ID_08] Alas! resolvedOpts.dataContainerIdentifierTails is empty!");if(t.heads===t.tails)throw new Error("json-variables/jVar(): [THROW_ID_09] Alas! resolvedOpts.heads and resolvedOpts.tails can't be equal!");if(t.heads===t.headsNoWrap)throw new Error("json-variables/jVar(): [THROW_ID_10] Alas! resolvedOpts.heads and resolvedOpts.headsNoWrap can't be equal!");if(t.tails===t.tailsNoWrap)throw new Error("json-variables/jVar(): [THROW_ID_11] Alas! resolvedOpts.tails and resolvedOpts.tailsNoWrap can't be equal!");if(t.headsNoWrap==="")throw new Error("json-variables/jVar(): [THROW_ID_12] Alas! resolvedOpts.headsNoWrap is an empty string!");if(t.tailsNoWrap==="")throw new Error("json-variables/jVar(): [THROW_ID_13] Alas! resolvedOpts.tailsNoWrap is an empty string!");if(t.headsNoWrap===t.tailsNoWrap)throw new Error("json-variables/jVar(): [THROW_ID_14] Alas! resolvedOpts.headsNoWrap and resolvedOpts.tailsNoWrap can't be equal!");let n;return re(r,(l,a,s)=>{if(ne(a)&&D(l,t))throw new Error(`json-variables/jVar(): [THROW_ID_15] Alas! Object keys can't contain variables!
Please check the following key: ${l}`);if(a!==void 0?n=a:n=l,n==="")return n;if(t.heads.length&&u(n)===u(t.heads)||t.tails.length&&u(n)===u(t.tails)||t.headsNoWrap.length&&u(n)===u(t.headsNoWrap)||t.tailsNoWrap.length&&u(n)===u(t.tailsNoWrap)){if(!t.noSingleMarkers)return n;throw new Error(`json-variables/jVar(): [THROW_ID_16] Alas! While processing the input, we stumbled upon ${u(n)} which is equal to ${u(n)===u(t.heads)?"heads":""}${u(n)===u(t.tails)?"tails":""}${p(t.headsNoWrap)&&u(n)===u(t.headsNoWrap)?"headsNoWrap":""}${p(t.tailsNoWrap)&&u(n)===u(t.tailsNoWrap)?"tailsNoWrap":""}. If you wouldn't have set resolvedOpts.noSingleMarkers to "true" this error would not happen and computer would have left the current element (${u(n)}) alone`)}return p(n)&&D(n,t)?B(r,n,s.path,t):n})}export{oe as defaults,Be as jVar,Fe as version};