@csstools/cascade-layer-name-parser
Version:
Parse CSS Cascade Layer names.
2 lines (1 loc) • 3.38 kB
JavaScript
;var e=require("@csstools/css-tokenizer"),r=require("@csstools/css-parser-algorithms");class LayerName{parts;constructor(e){this.parts=e}tokens(){return[...this.parts]}slice(r,n){const t=[];for(let r=0;r<this.parts.length;r++)e.isTokenIdent(this.parts[r])&&t.push(r);const s=t.slice(r,n);return new LayerName(this.parts.slice(s[0],s[s.length-1]+1))}concat(r){const n=[e.TokenType.Delim,".",-1,-1,{value:"."}];return new LayerName([...this.parts.filter((r=>e.isTokenIdent(r)||e.isTokenDelim(r))),n,...r.parts.filter((r=>e.isTokenIdent(r)||e.isTokenDelim(r)))])}segments(){return this.parts.filter((r=>e.isTokenIdent(r))).map((e=>e[4].value))}name(){return this.parts.filter((r=>e.isTokenIdent(r)||e.isTokenDelim(r))).map((e=>e[1])).join("")}equal(e){const r=this.segments(),n=e.segments();if(r.length!==n.length)return!1;for(let e=0;e<r.length;e++){if(r[e]!==n[e])return!1}return!0}toString(){return e.stringify(...this.parts)}toJSON(){return{parts:this.parts,segments:this.segments(),name:this.name()}}}function parseFromTokens(n,t){const s=r.parseCommaSeparatedListOfComponentValues(n,{onParseError:t?.onParseError}),a=t?.onParseError??(()=>{}),o=["6.4.2. Layer Naming and Nesting","Layer name syntax","<layer-name> = <ident> [ '.' <ident> ]*"],i=n[0][2],l=n[n.length-1][3],m=[];for(let n=0;n<s.length;n++){const t=s[n];for(let n=0;n<t.length;n++){const s=t[n];if(!r.isTokenNode(s)&&!r.isCommentNode(s)&&!r.isWhitespaceNode(s))return a(new e.ParseError(`Invalid cascade layer name. Invalid layer name part "${s.toString()}"`,i,l,o)),[]}const c=t.flatMap((e=>e.tokens()));let d=!1,p=!1,u=null;for(let r=0;r<c.length;r++){const n=c[r];if(!(e.isTokenWhiteSpaceOrComment(n)||e.isTokenIdent(n)||e.isTokenDelim(n)&&"."===n[4].value))return a(new e.ParseError(`Invalid cascade layer name. Invalid character "${n[1]}"`,i,l,o)),[];if(!d&&e.isTokenDelim(n))return a(new e.ParseError("Invalid cascade layer name. Layer names can not start with a dot.",i,l,o)),[];if(d){if(e.isTokenWhitespace(n)){p=!0;continue}if(p&&e.isTokenComment(n))continue;if(p)return a(new e.ParseError("Invalid cascade layer name. Encountered unexpected whitespace between layer name parts.",i,l,o)),[];if(e.isTokenIdent(u)&&e.isTokenIdent(n))return a(new e.ParseError("Invalid cascade layer name. Layer name parts must be separated by dots.",i,l,o)),[];if(e.isTokenDelim(u)&&e.isTokenDelim(n))return a(new e.ParseError("Invalid cascade layer name. Layer name parts must not be empty.",i,l,o)),[]}e.isTokenIdent(n)&&(d=!0),(e.isTokenIdent(n)||e.isTokenDelim(n))&&(u=n)}if(!u)return a(new e.ParseError("Invalid cascade layer name. Empty layer name.",i,l,o)),[];if(e.isTokenDelim(u))return a(new e.ParseError("Invalid cascade layer name. Layer name must not end with a dot.",i,l,o)),[];m.push(new LayerName(c))}return m}exports.LayerName=LayerName,exports.addLayerToModel=function addLayerToModel(e,r){r.forEach((r=>{const n=r.segments();e:for(let t=0;t<n.length;t++){const n=r.slice(0,t+1),s=n.segments();let a=-1,o=0;for(let r=0;r<e.length;r++){const n=e[r].segments();let t=0;r:for(let e=0;e<n.length;e++){const r=n[e],a=s[e];if(a===r&&e+1===s.length)continue e;if(a!==r){if(a!==r)break r}else t++}t>=o&&(a=r,o=t)}-1===a?e.push(n):e.splice(a+1,0,n)}}))},exports.parse=function parse(r,n){return parseFromTokens(e.tokenize({css:r},{onParseError:n?.onParseError}),n)},exports.parseFromTokens=parseFromTokens;