UNPKG

parsel-js

Version:

A tiny, permissive CSS selector parser

2 lines (1 loc) 5.48 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).parsel={})}(this,(function(e){"use strict";const t={attribute:/\[\s*(?:(?<namespace>\*|[-\w\P{ASCII}]*)\|)?(?<name>[-\w\P{ASCII}]+)\s*(?:(?<operator>\W?=)\s*(?<value>.+?)\s*(\s(?<caseSensitive>[iIsS]))?\s*)?\]/gu,id:/#(?<name>[-\w\P{ASCII}]+)/gu,class:/\.(?<name>[-\w\P{ASCII}]+)/gu,comma:/\s*,\s*/g,combinator:/\s*[\s>+~]\s*/g,"pseudo-element":/::(?<name>[-\w\P{ASCII}]+)(?:\((?<argument>¶*)\))?/gu,"pseudo-class":/:(?<name>[-\w\P{ASCII}]+)(?:\((?<argument>¶*)\))?/gu,universal:/(?:(?<namespace>\*|[-\w\P{ASCII}]*)\|)?\*/gu,type:/(?:(?<namespace>\*|[-\w\P{ASCII}]*)\|)?(?<name>[-\w\P{ASCII}]+)/gu},n=new Set(["combinator","comma"]),s=new Set(["not","is","where","has","matches","-moz-any","-webkit-any","nth-child","nth-last-child"]),o=/(?<index>[\dn+-]+)\s+of\s+(?<subtree>.+)/,r={"nth-child":o,"nth-last-child":o},c=e=>{switch(e){case"pseudo-element":case"pseudo-class":return new RegExp(t[e].source.replace("(?<argument>¶*)","(?<argument>.*)"),"gu");default:return t[e]}};function i(e,t){let n=0,s="";for(;t<e.length;t++){const o=e[t];switch(o){case"(":++n;break;case")":--n}if(s+=o,0===n)return s}return s}function a(e,s=t){if(!e)return[];const o=[e];for(const[e,t]of Object.entries(s))for(let n=0;n<o.length;n++){const s=o[n];if("string"!=typeof s)continue;t.lastIndex=0;const r=t.exec(s);if(!r)continue;const c=r.index-1,i=[],a=r[0],l=s.slice(0,c+1);l&&i.push(l),i.push({...r.groups,type:e,content:a});const u=s.slice(c+a.length+1);u&&i.push(u),o.splice(n,1,...i)}let r=0;for(const e of o)switch(typeof e){case"string":throw new Error(`Unexpected sequence ${e} found at index ${r}`);case"object":r+=e.content.length,e.pos=[r-e.content.length,r],n.has(e.type)&&(e.content=e.content.trim()||" ")}return o}const l=/(['"])([^\\\n]+?)\1/g,u=/\\./g;function f(e,n=t){if(""===(e=e.trim()))return[];const s=[];e=(e=e.replace(u,((e,t)=>(s.push({value:e,offset:t}),"".repeat(e.length))))).replace(l,((e,t,n,o)=>(s.push({value:e,offset:o}),`${t}${"".repeat(n.length)}${t}`)));{let t,n=0;for(;(t=e.indexOf("(",n))>-1;){const o=i(e,t);s.push({value:o,offset:t}),e=`${e.substring(0,t)}(${"¶".repeat(o.length-2)})${e.substring(t+o.length)}`,n=t+o.length}}const o=a(e,n),r=new Set;for(const e of s.reverse())for(const t of o){const{offset:n,value:s}=e;if(!(t.pos[0]<=n&&n+s.length<=t.pos[1]))continue;const{content:o}=t,c=n-t.pos[0];t.content=o.slice(0,c)+s+o.slice(c+s.length),t.content!==o&&r.add(t)}for(const e of r){const t=c(e.type);if(!t)throw new Error(`Unknown token type: ${e.type}`);t.lastIndex=0;const n=t.exec(e.content);if(!n)throw new Error(`Unable to parse content for ${e.type}: ${e.content}`);Object.assign(e,n.groups)}return o}function p(e,{list:t=!0}={}){if(t&&e.find((e=>"comma"===e.type))){const t=[],n=[];for(let s=0;s<e.length;s++)if("comma"===e[s].type){if(0===n.length)throw new Error("Incorrect comma at "+s);t.push(p(n,{list:!1})),n.length=0}else n.push(e[s]);if(0===n.length)throw new Error("Trailing comma");return t.push(p(n,{list:!1})),{type:"list",list:t}}for(let t=e.length-1;t>=0;t--){let n=e[t];if("combinator"===n.type){let s=e.slice(0,t),o=e.slice(t+1);return 0===s.length?{type:"relative",combinator:n.content,right:p(o)}:{type:"complex",combinator:n.content,left:p(s),right:p(o)}}}switch(e.length){case 0:throw new Error("Could not build AST.");case 1:return e[0];default:return{type:"compound",list:[...e]}}}function*h(e,t){switch(e.type){case"list":for(let t of e.list)yield*h(t,e);break;case"complex":yield*h(e.left,e),yield*h(e.right,e);break;case"relative":yield*h(e.right,e);break;case"compound":yield*e.list.map((t=>[t,e]));break;default:yield[e,t]}}function m(e,{recursive:t=!0,list:n=!0}={}){const o=f(e);if(!o)return;const c=p(o,{list:n});if(!t)return c;for(const[e]of h(c)){if("pseudo-class"!==e.type||!e.argument)continue;if(!s.has(e.name))continue;let t=e.argument;const n=r[e.name];if(n){const s=n.exec(t);if(!s)continue;Object.assign(e,s.groups),t=s.groups.subtree}t&&Object.assign(e,{subtree:m(t,{recursive:!0,list:!0})})}return c}function g(e,t){return t=t||Math.max(...e)+1,e[0]*(t<<1)+e[1]*t+e[2]}e.RECURSIVE_PSEUDO_CLASSES=s,e.RECURSIVE_PSEUDO_CLASSES_ARGS=r,e.TOKENS=t,e.TRIM_TOKENS=n,e.flatten=h,e.gobbleParens=i,e.parse=m,e.specificity=function e(t){let n=t;if("string"==typeof n&&(n=m(n,{recursive:!0})),!n)return[];if("list"===n.type&&"list"in n){let t=10;const s=n.list.map((n=>{const s=e(n);return t=Math.max(t,...e(n)),s})),o=s.map((e=>g(e,t)));return s[o.indexOf(Math.max(...o))]}const o=[0,0,0];for(const[t]of h(n))switch(t.type){case"id":o[0]++;break;case"class":case"attribute":o[1]++;break;case"pseudo-element":case"type":o[2]++;break;case"pseudo-class":if("where"===t.name)break;if(!s.has(t.name)||!t.subtree){o[1]++;break}e(t.subtree).forEach(((e,t)=>o[t]+=e)),"nth-child"!==t.name&&"nth-last-child"!==t.name||o[1]++}return o},e.specificityToNumber=g,e.stringify=function e(t){if(Array.isArray(t))return t.map((e=>e.content)).join("");switch(t.type){case"list":return t.list.map(e).join(",");case"relative":return t.combinator+e(t.right);case"complex":return e(t.left)+t.combinator+e(t.right);case"compound":return t.list.map(e).join("");default:return t.content}},e.tokenize=f,e.tokenizeBy=a,e.walk=function(e,t,n){if(e)for(const[s,o]of h(e,n))t(s,o)},Object.defineProperty(e,"__esModule",{value:!0})}));