UNPKG

string-match-left-right

Version:

Match substrings on the left or right of a given index, ignoring whitespace

14 lines (12 loc) 5.65 kB
/** * @name string-match-left-right * @fileoverview Match substrings on the left or right of a given index, ignoring whitespace * @version 9.0.23 * @author Roy Revelt, Codsen Ltd * @license MIT * {@link https://codsen.com/os/string-match-left-right/} */ import{arrayiffy as N}from"arrayiffy-if-string";import{isPlainObject as R,isStr as d,hasOwnProp as k}from"codsen-utils";var O="9.0.23";var F=O,w={cb:void 0,i:!1,trimBeforeMatching:!1,trimCharsBeforeMatching:[],maxMismatches:0,firstMustMatch:!1,lastMustMatch:!1,hungry:!1},L=t=>t+1;function A(t,s,n,a,u=!1,o=L){let l=typeof n=="function"?n():n;if(+s<0&&u&&l==="EOL")return l;let r={...w,...a};if(s>=t.length&&!u)return!1;let c=u?1:n.length,E=0,h=!1,i=!1,g=!1,b=r.maxMismatches,e=s,$=!1,f=!1,m=!1;function p(){return E===1&&b<r.maxMismatches-1}for(;t[e];){let T=o(e);if(r.trimBeforeMatching&&t[e].trim()===""){if(!t[T]&&u&&n==="EOL")return!0;e=o(e);continue}if(r&&!r.i&&r?.trimCharsBeforeMatching?.includes(t[e])||r?.i&&r.trimCharsBeforeMatching&&r.trimCharsBeforeMatching.map(D=>D.toLowerCase()).includes(t[e].toLowerCase())){if(u&&n==="EOL"&&!t[T])return!0;e=o(e);continue}let y=T>e?n[n.length-c]:n[c-1];if(!r.i&&t[e]===y||r.i&&t[e].toLowerCase()===y.toLowerCase()){if($||($=!0),g||(g=!0),c===n.length){if(f=!0,b!==r.maxMismatches)return!1}else c===1&&(m=!0);if(c-=1,E++,p())return!1;if(!c)return E!==n.length||b===r.maxMismatches||!h?e:!1}else if(!h&&!E&&(h=!0),r.maxMismatches&&b&&e){b-=1;for(let D=0;D<=b;D++){let C=T>e?n[n.length-c+1+D]:n[c-2-D],M=t[o(e)];if(C&&(!r.i&&t[e]===C||r.i&&t[e].toLowerCase()===C.toLowerCase())&&(!r.firstMustMatch||c!==n.length)){if(E++,p())return!1;c-=2,$=!0;break}else if(M&&C&&(!r.i&&M===C||r.i&&M.toLowerCase()===C.toLowerCase())&&(!r.firstMustMatch||c!==n.length)){if(!E&&!r.hungry)return!1;c-=1,$=!0;break}else if(C===void 0&&b>=0&&$&&(!r.firstMustMatch||f)&&(!r.lastMustMatch||m))return e}$||(i=e)}else return e===0&&c===1&&!r.lastMustMatch&&g?0:!1;if(i!==!1&&i!==e&&(i=!1),c<1)return e;e=o(e)}if(c>0)return u&&l==="EOL"?!0:r&&r.maxMismatches>=c&&g?i||0:!1}function V(t,s,n,a,u){if(R(u)&&k(u,"trimBeforeMatching")&&u&&typeof u.trimBeforeMatching!="boolean")throw new Error(`string-match-left-right/${t}(): [THROW_ID_09] opts.trimBeforeMatching should be boolean!${Array.isArray(u.trimBeforeMatching)?" Did you mean to use opts.trimCharsBeforeMatching?":""}`);let o={...w,...u};if(typeof o.trimCharsBeforeMatching=="string"&&(o.trimCharsBeforeMatching=N(o.trimCharsBeforeMatching)),o.trimCharsBeforeMatching=o.trimCharsBeforeMatching.map(h=>d(h)?h:String(h)),!d(s)||!s.length)return!1;if(!Number.isInteger(n)||n<0)throw new Error(`string-match-left-right/${t}(): [THROW_ID_03] the second argument should be a natural number. Currently it's of a type: ${typeof n}, equal to: ${JSON.stringify(n,null,4)}`);let l,r;if(d(a))l=[a];else if(Array.isArray(a))l=a;else if(!a)l=a;else if(typeof a=="function")l=[],l.push(a);else throw new Error(`string-match-left-right/${t}(): [THROW_ID_05] the third argument, whatToMatch, is neither string nor array of strings! It's ${typeof a}, equal to: ${JSON.stringify(a,null,4)}`);if(u&&!R(u))throw new Error(`string-match-left-right/${t}(): [THROW_ID_06] the fourth argument, options object, should be a plain object. Currently it's of a type "${typeof u}", and equal to: ${JSON.stringify(u,null,4)}`);let c=0,E="";if(o?.trimCharsBeforeMatching?.some((h,i)=>h.length>1?(c=i,E=h,!0):!1))throw new Error(`string-match-left-right/${t}(): [THROW_ID_07] the fourth argument, options object contains trimCharsBeforeMatching. It was meant to list the single characters but one of the entries at index ${c} is longer than 1 character, ${E.length} (equals to ${E}). Please split it into separate characters and put into array as separate elements.`);if(!l||!Array.isArray(l)||Array.isArray(l)&&!l.length||Array.isArray(l)&&l.length===1&&d(l[0])&&!l[0].trim()){if(typeof o.cb=="function"){let i,g=n;if((t==="matchLeftIncl"||t==="matchRight")&&(g+=1),t[5]==="L")for(let f=g;f--;){let m=s[f];if((!o.trimBeforeMatching||o.trimBeforeMatching&&m?.trim())&&(!o.trimCharsBeforeMatching?.length||m!==void 0&&!o.trimCharsBeforeMatching.includes(m))){i=f;break}}else if(t.startsWith("matchRight"))for(let f=g;f<s.length;f++){let m=s[f];if((!o.trimBeforeMatching||o.trimBeforeMatching&&m.trim())&&(!o.trimCharsBeforeMatching?.length||!o.trimCharsBeforeMatching.includes(m))){i=f;break}}if(i===void 0)return!1;let b=s[i],e=i+1,$="";return e&&e>0&&($=s.slice(0,e)),t[5]==="L"||i&&i>0&&($=s.slice(i)),o.cb(b,$,i)}let h="";throw u||(h=" More so, the whole options object, the fourth input argument, is missing!"),new Error(`string-match-left-right/${t}(): [THROW_ID_08] the third argument, "whatToMatch", was given as an empty string. This means, you intend to match purely by a callback. The callback was not set though, the opts key "cb" is not set!${h}`)}for(let h=0,i=l.length;h<i;h++){r=typeof l[h]=="function";let g=l[h],b,e,$="",f=n;t==="matchRight"?f+=1:t==="matchLeft"&&(f-=1);let m=A(s,f,g,o,r,p=>t[5]==="L"?p-1:p+1);if(m&&r&&typeof g=="function"&&g()==="EOL")return g()&&(!o.cb||o.cb(b,$,e))?g():!1;if(Number.isInteger(m)&&(e=t.startsWith("matchLeft")?m-1:m+1,t[5]==="L"?$=s.slice(0,m):$=s.slice(e)),e<0&&(e=void 0),s[e]&&(b=s[e]),Number.isInteger(m)&&(!o.cb||o.cb(b,$,e)))return g}return!1}function H(t,s,n,a){return V("matchLeftIncl",t,s,n,a)}function P(t,s,n,a){return V("matchLeft",t,s,n,a)}function U(t,s,n,a){return V("matchRightIncl",t,s,n,a)}function j(t,s,n,a){return V("matchRight",t,s,n,a)}export{L as defaultGetNextIdx,w as defaults,P as matchLeft,H as matchLeftIncl,j as matchRight,U as matchRightIncl,F as version};