void-css
Advanced tools
Comparing version 1.0.37 to 1.0.38
17
index.js
@@ -13,19 +13,16 @@ "use strict"; | ||
const css = ` | ||
body { | ||
test { | ||
color: red; | ||
} | ||
:not(:last-child) { | ||
color: green | ||
@media screen and (max-width: 992px) { | ||
@media screen and (max-width: 992px) { | ||
.test { | ||
background: green | ||
} | ||
} | ||
* { | ||
} | ||
} | ||
` | ||
`; | ||
console.log(compile(css)?.static); */ | ||
exports.default = VoidCSS; |
22
index.ts
@@ -8,3 +8,4 @@ import { compileScope } from "./src/compiler/lexer"; | ||
return (css: string) => compileScope(css, configInstance, [autoVar(), autoCalc()]); | ||
return (css: string) => | ||
compileScope(css, configInstance, [autoVar(), autoCalc()]); | ||
} | ||
@@ -15,20 +16,17 @@ | ||
const css = ` | ||
body { | ||
test { | ||
color: red; | ||
} | ||
:not(:last-child) { | ||
color: green | ||
@media screen and (max-width: 992px) { | ||
@media screen and (max-width: 992px) { | ||
.test { | ||
background: green | ||
} | ||
} | ||
* { | ||
} | ||
} | ||
` | ||
`; | ||
console.log(compile(css)?.static); */ | ||
export default VoidCSS; | ||
export default VoidCSS; |
{ | ||
"name": "void-css", | ||
"version": "1.0.37", | ||
"version": "1.0.38", | ||
"description": "A JIT & statically compiled CSS processor", | ||
@@ -16,2 +16,3 @@ "main": "index.js", | ||
"license": "ISC", | ||
"types": "declarations.d.ts", | ||
"dependencies": { | ||
@@ -18,0 +19,0 @@ "chalk": "^4.1.2" |
@@ -10,3 +10,3 @@ "use strict"; | ||
const abstractSyntaxTree = createTree(ctx, ctx.strippedTokens); | ||
//console.log(ctx.strippedTokens); | ||
//console.log(ctx.tokens); | ||
//console.log(JSON.stringify(abstractSyntaxTree, null, 2)) | ||
@@ -13,0 +13,0 @@ return createCss(abstractSyntaxTree, ctx); |
@@ -24,3 +24,3 @@ import Context, { Token } from "../context"; | ||
const abstractSyntaxTree = createTree(ctx, ctx.strippedTokens); | ||
//console.log(ctx.strippedTokens); | ||
//console.log(ctx.tokens); | ||
//console.log(JSON.stringify(abstractSyntaxTree, null, 2)) | ||
@@ -27,0 +27,0 @@ |
@@ -13,4 +13,3 @@ "use strict"; | ||
const resolvedCSS = css.replace(/\r/g, ""); | ||
const ctx = new context_1.default(resolvedCSS, config) | ||
.register(extensions); | ||
const ctx = new context_1.default(resolvedCSS, config).register(extensions); | ||
return lex(ctx, expect(ctx.css, tokens_1.whiteSpaceOrNothing)); | ||
@@ -37,3 +36,4 @@ } | ||
if (!token?.match) { | ||
if (index !== preTokenizedCSS.length || 0 !== (attributes?.depth ?? 0)) { | ||
if (index !== preTokenizedCSS.length || | ||
0 !== (attributes?.depth ?? 0)) { | ||
if (attributes?.onError) { | ||
@@ -53,26 +53,46 @@ throw new SyntaxError((0, errors_1.createCompilationError)(ctx, attributes.onError)); | ||
/** The depth refers to the css rule or "scope" nesting level */ | ||
const depth = (attributes?.depth ?? 0) + (() => { | ||
// The only way to descend a depth is to close it with the `}` token `styleScopeEnd` | ||
const descend = lastToken?.name === "styleScopeEnd"; | ||
if (descend) | ||
return -1; | ||
// If the previous token isn't a selector and the current one is, | ||
// it must mean that a new scope is defined. | ||
const ascend = lastToken?.domain !== "selector" && token.domain === "selector"; | ||
if (ascend) | ||
return 1; | ||
return 0; | ||
})(); | ||
const depth = (attributes?.depth ?? 0) + | ||
(() => { | ||
// The only way to descend a depth is to close it with the `}` token `styleScopeEnd` | ||
const descend = lastToken?.name === "styleScopeEnd"; | ||
if (descend) | ||
return -1; | ||
// If the previous token isn't a selector and the current one is, | ||
// it must mean that a new scope is defined. | ||
const ascend = lastToken?.domain !== "selector" && token.domain === "selector"; | ||
if (ascend) | ||
return 1; | ||
return 0; | ||
})(); | ||
const { slice, css } = ctx.tokenize(token, depth); | ||
const resolvedType = token?.renamed || token.type; | ||
const globals = (0, tokens_1.renameTokens)(globalTokens, resolvedType); | ||
const afterStyleScopeTokens = [ | ||
...globals, | ||
(0, tokens_1.renameToken)(tokens_1.whiteSpace, "styleScopeWhiteSpace"), | ||
tokens_1.notOperator, | ||
tokens_1.selectorCombinator, | ||
tokens_1.keyframes, | ||
tokens_1.atSymbol, | ||
tokens_1.styleScopeEnd, | ||
tokens_1.propertyName, | ||
tokens_1.selectorName, | ||
tokens_1.attributeSelectorClose, | ||
tokens_1.wildcard, | ||
tokens_1.idInitiator, | ||
tokens_1.classNameInitiator, | ||
tokens_1.currentSelector, | ||
]; | ||
switch (resolvedType) { | ||
case "skip": | ||
const [start, end] = [ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)]; | ||
const [start, end] = [ | ||
ctx.index, | ||
ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice), | ||
]; | ||
const section = css.substring(start, end); | ||
const hint = enclosures.length === 0 && /&/.test(section) ? | ||
"Root level selectors cannot contain current selector ('&')." : | ||
/^\s*(?:~|>|\+|\|\|)/.test(section) ? | ||
"Root level selectors cannot begin with a selector combinator ('~', '>', '+', '||'). Did you forget to add left side selector combinator operand?" : | ||
"Instead found invalid or missing selector."; | ||
const hint = enclosures.length === 0 && /&/.test(section) | ||
? "Root level selectors cannot contain current selector ('&')." | ||
: /^\s*(?:~|>|\+|\|\|)/.test(section) | ||
? "Root level selectors cannot begin with a selector combinator ('~', '>', '+', '||'). Did you forget to add left side selector combinator operand?" | ||
: "Instead found invalid or missing selector."; | ||
return lex(ctx, expect(slice, ...globals, tokens_1.atSymbol, tokens_1.whiteSpace, ...enclosures, ..._if(enclosures.length === 0, [tokens_1.rootSelector]), ..._if(depth > 0, [tokens_1.currentSelector]), tokens_1.attributeSelectorInitiator, tokens_1.classNameInitiator, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.wildcard, tokens_1.notOperator), { | ||
@@ -100,7 +120,8 @@ onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: [css selector]. " + hint, start, end), | ||
case "notOperatorParenthesisEnd": | ||
const newDepth = notOperatorDepth - (resolvedType === "notOperatorParenthesisEnd" ? 1 : 0); | ||
return lex(ctx, expect(slice, ...globals, (0, tokens_1.renameToken)(tokens_1.whiteSpace, "notOperatorParenthesisEndWhiteSpace"), ..._if(enclosures.length === 0, [tokens_1.rootSelector]), ..._if(depth > 0, [tokens_1.currentSelector]), ..._if(newDepth > 0, [tokens_1.notOperatorParenthesisEnd]), tokens_1.colon, tokens_1.selectorSeparator, tokens_1.styleScope, tokens_1.attributeSelectorInitiator, tokens_1.classNameInitiator, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.wildcard), { | ||
onError: (0, errors_1.createErrorContext)(newDepth === 0 ? | ||
"Unexpected token. Expected: [selector]." : | ||
"Unexpected token. Expected: ')' or [selector].", ctx.index, ctx.index + 1), | ||
const newDepth = notOperatorDepth - | ||
(resolvedType === "notOperatorParenthesisEnd" ? 1 : 0); | ||
return lex(ctx, expect(slice, ...globals, (0, tokens_1.renameToken)(tokens_1.whiteSpace, "notOperatorParenthesisEndWhiteSpace"), ..._if(enclosures.length === 0, [tokens_1.rootSelector]), ..._if(depth > 0, [tokens_1.currentSelector]), ..._if(newDepth > 0, [tokens_1.notOperatorParenthesisEnd]), tokens_1.notOperator, tokens_1.colon, tokens_1.selectorSeparator, tokens_1.styleScope, tokens_1.attributeSelectorInitiator, tokens_1.classNameInitiator, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.wildcard), { | ||
onError: (0, errors_1.createErrorContext)(newDepth === 0 | ||
? "Unexpected token. Expected: [selector]." | ||
: "Unexpected token. Expected: ')' or [selector].", ctx.index, ctx.index + 1), | ||
enclosures, | ||
@@ -112,3 +133,3 @@ depth, | ||
return lex(ctx, expect(slice, ...globals, ...(0, tokens_1.kf)(tokens_1.keyframes), tokens_1.nestedAtRuleName), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: 'color-profile', 'counter-style', 'document', 'font-face', 'font-feature-values', 'keyframes', 'media', 'page', 'property' or 'supports'. It's possible that this list is outdated, if so please make an issue on the repository.", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: 'color-profile', 'counter-style', 'document', 'font-face', 'font-feature-values', 'media', 'page', 'property' or 'supports'. It's possible that this list is outdated, if so please make an issue on the repository.", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
enclosures, | ||
@@ -136,3 +157,4 @@ depth, | ||
case "keyframesName": | ||
if (resolvedType === "keyframesName" && ["None", "initial"].includes(token.match.toString())) { | ||
if (resolvedType === "keyframesName" && | ||
["None", "initial"].includes(token.match.toString())) { | ||
return lex(ctx, expect(slice, ...globals), { | ||
@@ -168,3 +190,3 @@ onError: (0, errors_1.createErrorContext)(`Invalid keyframes name. A keyframes name cannot be '${token.match}' as per "CSS Animations Level 2" w3c specification. You can wrap '${token.match}' in double quotes ('"') like this: '"${token.match}"' to still use this name.`, Math.max(ctx.index - token.match.toString().length, 0), ctx.index), | ||
case "keyframesScopeEnd": | ||
return lex(ctx, expect(slice, ...(0, tokens_1.kf)((0, tokens_1.renameToken)(tokens_1.whiteSpace, "keyframesScopeEnd")), ..._if(depth > 0, [tokens_1.styleScopeEnd]), tokens_1.currentSelector, tokens_1.propertyName, tokens_1.attributeSelectorClose, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.classNameInitiator, tokens_1.atSymbol, tokens_1.whiteSpaceOrNothing), { | ||
return lex(ctx, expect(slice, ...(0, tokens_1.kf)((0, tokens_1.renameToken)(tokens_1.whiteSpace, "keyframesScopeEnd")), ..._if(depth > 0, [tokens_1.styleScopeEnd]), tokens_1.currentSelector, tokens_1.propertyName, tokens_1.attributeSelectorClose, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.classNameInitiator, tokens_1.keyframes, tokens_1.atSymbol, tokens_1.whiteSpaceOrNothing), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: [css].", ctx.index, ctx.index + 1), | ||
@@ -205,3 +227,6 @@ enclosures, | ||
case "keyframesPropertyColon": | ||
return lex(ctx, expect(slice, ...globals, ...(0, tokens_1.kf)((0, tokens_1.renameToken)(tokens_1.whiteSpace, "keyframesPropertyColon"), ...(0, tokens_1.renameTokens)([tokens_1.propertyValueWithSemiColon, tokens_1.propertyValueWithoutSemiColon], "keyframesPropertyValue"))), { | ||
return lex(ctx, expect(slice, ...globals, ...(0, tokens_1.kf)((0, tokens_1.renameToken)(tokens_1.whiteSpace, "keyframesPropertyColon"), ...(0, tokens_1.renameTokens)([ | ||
tokens_1.propertyValueWithSemiColon, | ||
tokens_1.propertyValueWithoutSemiColon, | ||
], "keyframesPropertyValue"))), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: [property value]. Did you forget ';'?", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
@@ -215,5 +240,5 @@ enclosures, | ||
return lex(ctx, expect(slice, ...globals, ...(0, tokens_1.kf)((0, tokens_1.renameToken)(tokens_1.whiteSpace, "keyframesPropertyValue"), (0, tokens_1.renameToken)(tokens_1.valueSemiColon, "keyframesValueSemiColon"), (0, tokens_1.renameToken)(tokens_1.styleScopeEnd, "keyframesBlockEnd"))), { | ||
onError: (0, errors_1.createErrorContext)(hasSemiColon ? | ||
"Unexpected token. Expected: '}'." : | ||
"Unexpected token. Expected: ';' or '}'.", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
onError: (0, errors_1.createErrorContext)(hasSemiColon | ||
? "Unexpected token. Expected: '}'." | ||
: "Unexpected token. Expected: ';' or '}'.", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
enclosures, | ||
@@ -239,3 +264,3 @@ depth, | ||
case "nestedAtRule": | ||
return lex(ctx, expect(slice, ...globals, tokens_1.styleScope), { | ||
return lex(ctx, expect(slice, ...globals, (0, tokens_1.renameToken)(tokens_1.styleScope, "nestedAtRuleStyleScope")), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: '{'.", ctx.index, ctx.index + (0, errors_1.resolveEndOfPropertyValue)(slice)), | ||
@@ -246,2 +271,17 @@ enclosures, | ||
}); | ||
case "nestedAtRuleStyleScopeWhiteSpace": | ||
case "nestedAtRuleStyleScope": | ||
if (enclosures.length > 0) | ||
return lex(ctx, expect(slice, ...afterStyleScopeTokens), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: '{'.", ctx.index, ctx.index + (0, errors_1.resolveEndOfPropertyValue)(slice)), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
return lex(ctx, expect(slice, ...globals, (0, tokens_1.renameToken)(tokens_1.whiteSpace, "nestedAtRuleStyleScopeWhiteSpace"), tokens_1.selectorName, tokens_1.classNameInitiator, tokens_1.idInitiator, tokens_1.attributeSelectorInitiator, tokens_1.rootSelector, tokens_1.wildcard, tokens_1.atSymbol, tokens_1.styleScopeEnd), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: '{'.", ctx.index, ctx.index + (0, errors_1.resolveEndOfPropertyValue)(slice)), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
case "idInitiator": | ||
@@ -256,3 +296,3 @@ return lex(ctx, expect(slice, ...globals, tokens_1.selectorName), { | ||
case "currentSelector": | ||
return lex(ctx, expect(slice, ...globals, ...(0, tokens_1.renameTokens)([tokens_1.whiteSpace], "currentSelectorWhiteSpace", "selector"), tokens_1.notOperator, tokens_1.selectorChild, tokens_1.classNameInitiator, tokens_1.colon, tokens_1.selectorName, tokens_1.selectorCombinator, tokens_1.selectorSeparator, tokens_1.styleScope, tokens_1.wildcard), { | ||
return lex(ctx, expect(slice, ...globals, ...(0, tokens_1.renameTokens)([tokens_1.whiteSpace], "currentSelectorWhiteSpace", "selector"), tokens_1.attributeSelectorInitiator, tokens_1.notOperator, tokens_1.selectorChild, tokens_1.classNameInitiator, tokens_1.colon, tokens_1.selectorName, tokens_1.selectorCombinator, tokens_1.selectorSeparator, tokens_1.styleScope, tokens_1.wildcard), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: ' ', '>', '+', '||', '.', ':', '::', '[...]', ',' or '{' directly proceeding current selector ('&').", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
@@ -286,3 +326,3 @@ enclosures, | ||
return lex(ctx, expect(slice, ...globals, tokens_1.attributeSelectorSingleQuoteBody), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Expected: \"'\"", ctx.index, ctx.index + 1), | ||
onError: (0, errors_1.createErrorContext)('Unexpected token. Expected: "\'"', ctx.index, ctx.index + 1), | ||
enclosures, | ||
@@ -309,5 +349,5 @@ depth, | ||
return lex(ctx, expect(slice, ...globals, (0, tokens_1.renameToken)(tokens_1.whiteSpace, "attributeSelectorClose"), ..._if(notOperatorDepth > 0, [tokens_1.notOperatorParenthesisEnd]), tokens_1.notOperator, tokens_1.selectorCombinator, tokens_1.wildcard, tokens_1.classNameInitiator, tokens_1.colon, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.selectorSeparator, tokens_1.attributeSelectorInitiator, tokens_1.styleScope), { | ||
onError: (0, errors_1.createErrorContext)(notOperatorDepth === 0 ? | ||
"Unexpected token. Expected: [css selector] or '{'" : | ||
"Unexpected token. Expected: ')', [css selector] or '{'", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
onError: (0, errors_1.createErrorContext)(notOperatorDepth === 0 | ||
? "Unexpected token. Expected: [css selector] or '{'" | ||
: "Unexpected token. Expected: ')', [css selector] or '{'", ctx.index, ctx.index + (0, errors_1.resolveSelectorNameNotFound)(slice)), | ||
enclosures, | ||
@@ -339,4 +379,7 @@ depth, | ||
case "combinator": | ||
const previousIsCombinator = ctx.strippedTokens?.[ctx.strippedTokens.length - 2]?.name === "combinator"; | ||
const combinatorHint = previousIsCombinator ? "Combinators ('~', '>', '+', '||') cannot directly follow previous combinator. " : ""; | ||
const previousIsCombinator = ctx.strippedTokens?.[ctx.strippedTokens.length - 2]?.name === | ||
"combinator"; | ||
const combinatorHint = previousIsCombinator | ||
? "Combinators ('~', '>', '+', '||') cannot directly follow previous combinator. " | ||
: ""; | ||
return lex(ctx, expect(slice, ...globals, ...(0, tokens_1.renameTokens)([tokens_1.whiteSpace], "combinator", "selector"), tokens_1.notOperator, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.attributeSelectorInitiator, tokens_1.classNameInitiator, tokens_1.wildcard), { | ||
@@ -395,5 +438,8 @@ onError: (0, errors_1.createErrorContext)(`Unexpected token proceeding selector combinator. Expected: [combinator operand]. ${combinatorHint}Did you forgot a [combinator operand] after the selector combinator?`, ctx.index, ctx.index + 1), | ||
} | ||
return lex(ctx, expect(slice, ...globals, (0, tokens_1.renameToken)(tokens_1.whiteSpace, "styleScopeWhiteSpace"), tokens_1.notOperator, tokens_1.selectorCombinator, tokens_1.atSymbol, tokens_1.styleScopeEnd, tokens_1.propertyName, tokens_1.selectorName, tokens_1.attributeSelectorClose, tokens_1.wildcard, tokens_1.idInitiator, tokens_1.classNameInitiator, tokens_1.currentSelector), { | ||
return lex(ctx, expect(slice, ...afterStyleScopeTokens), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token in style scope. Expected: '}', [css selector] or [css property].", ctx.index, ctx.index + 1), | ||
enclosures: [...(resolvedType === "styleScope" ? [tokens_1.styleScopeEnd] : []), ...enclosures], | ||
enclosures: [ | ||
...(resolvedType === "styleScope" ? [tokens_1.styleScopeEnd] : []), | ||
...enclosures, | ||
], | ||
depth, | ||
@@ -405,4 +451,10 @@ notOperatorDepth, | ||
// add non ending condition? | ||
expect(slice, (0, tokens_1.renameToken)(tokens_1.whiteSpace, "styleScopeEnd"), ..._if(depth > 0, [tokens_1.styleScopeEnd, tokens_1.selectorCombinator, tokens_1.currentSelector, tokens_1.notOperator, tokens_1.colon]), tokens_1.propertyName, tokens_1.attributeSelectorClose, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.classNameInitiator, tokens_1.atSymbol, tokens_1.whiteSpaceOrNothing), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Undefined behavior." + (depth), ctx.index, ctx.index + 1), | ||
expect(slice, (0, tokens_1.renameToken)(tokens_1.whiteSpace, "styleScopeEnd"), ..._if(depth > 0, [ | ||
tokens_1.styleScopeEnd, | ||
tokens_1.selectorCombinator, | ||
tokens_1.currentSelector, | ||
tokens_1.notOperator, | ||
tokens_1.colon, | ||
]), tokens_1.propertyName, tokens_1.attributeSelectorClose, tokens_1.selectorName, tokens_1.idInitiator, tokens_1.classNameInitiator, tokens_1.keyframes, tokens_1.atSymbol, tokens_1.whiteSpaceOrNothing), { | ||
onError: (0, errors_1.createErrorContext)("Unexpected token. Undefined behavior." + depth, ctx.index, ctx.index + 1), | ||
enclosures: enclosures.slice(1), | ||
@@ -409,0 +461,0 @@ depth, |
@@ -1,15 +0,70 @@ | ||
import { whiteSpace, Match, currentSelector, classNameInitiator, selectorName, idInitiator, wildcard, selectorChild, selectorCombinator, selectorSeparator, styleScope, renameToken, attributeSelectorCloseWithoutOperator, attributeSelectorModifier, attributeSelectorSingleQuoteInitiator, attributeSelectorDoubleQuoteInitiator, attributeSelectorSingleQuoteBody, attributeSelectorDoubleQuoteBody, attributeSelectorClose, attributeSelectorInitiator, styleScopeEnd, propertyName, valueSemiColon, propertyColon, propertyValueWithSemiColon, propertyValueWithoutSemiColon, TokenMatcher, inlineComment, renameTokens, blockComment, atSymbol, nestedAtRuleName, nestedAtRule, endStyleSheet, whiteSpaceOrNothing, exportClassName, colon, pseudoSelector, rootSelector, notOperatorParenthesis, notOperator, notOperatorParenthesisEnd, keyframes, requiredWhiteSpace, keyframesSpecialNames, keyframesSelector, kf, atKeyframes } from "../tokens"; | ||
import { | ||
whiteSpace, | ||
Match, | ||
currentSelector, | ||
classNameInitiator, | ||
selectorName, | ||
idInitiator, | ||
wildcard, | ||
selectorChild, | ||
selectorCombinator, | ||
selectorSeparator, | ||
styleScope, | ||
renameToken, | ||
attributeSelectorCloseWithoutOperator, | ||
attributeSelectorModifier, | ||
attributeSelectorSingleQuoteInitiator, | ||
attributeSelectorDoubleQuoteInitiator, | ||
attributeSelectorSingleQuoteBody, | ||
attributeSelectorDoubleQuoteBody, | ||
attributeSelectorClose, | ||
attributeSelectorInitiator, | ||
styleScopeEnd, | ||
propertyName, | ||
valueSemiColon, | ||
propertyColon, | ||
propertyValueWithSemiColon, | ||
propertyValueWithoutSemiColon, | ||
TokenMatcher, | ||
inlineComment, | ||
renameTokens, | ||
blockComment, | ||
keyframes, | ||
atSymbol, | ||
nestedAtRuleName, | ||
nestedAtRule, | ||
endStyleSheet, | ||
whiteSpaceOrNothing, | ||
exportClassName, | ||
colon, | ||
pseudoSelector, | ||
rootSelector, | ||
notOperatorParenthesis, | ||
notOperator, | ||
notOperatorParenthesisEnd, | ||
requiredWhiteSpace, | ||
keyframesSpecialNames, | ||
keyframesSelector, | ||
kf, | ||
atKeyframes, | ||
} from "../tokens"; | ||
import { Config } from "../config"; | ||
import Context from "../context"; | ||
import { createErrorContext, createCompilationError, resolveSelectorNameNotFound, resolveEndOfPropertyValue } from "../errors/errors"; | ||
import { | ||
createErrorContext, | ||
createCompilationError, | ||
resolveSelectorNameNotFound, | ||
resolveEndOfPropertyValue, | ||
} from "../errors/errors"; | ||
import { Extension } from "../extensions/extentions"; | ||
import compile from "./compiler"; | ||
export function compileScope(css: string, config: Config, extensions: Extension[]) { | ||
export function compileScope( | ||
css: string, | ||
config: Config, | ||
extensions: Extension[] | ||
) { | ||
const resolvedCSS = css.replace(/\r/g, ""); | ||
const ctx = new Context(resolvedCSS, config) | ||
.register(extensions); | ||
const ctx = new Context(resolvedCSS, config).register(extensions); | ||
@@ -21,13 +76,11 @@ return lex(ctx, expect(ctx.css, whiteSpaceOrNothing)); | ||
/** | ||
* Void CSS lexer — Tokenizes given Void CSS input and then, if valid, compiles it, | ||
* otherwise throws syntax error. | ||
* | ||
* | ||
* Recursive and declarative design. Each case on the main switch statement represents the next step | ||
* after the given (current token). Each self call of the lex function represents what the lexer should | ||
* expect after the current token. Using attributes which live on the function recursively (as an argument), | ||
* the lexer can call itself with possibly conditional expectations using helper functions such as `_if`. | ||
* | ||
* the lexer can call itself with possibly conditional expectations using helper functions such as `_if`. | ||
* | ||
* @param ctx Compile context | ||
@@ -38,21 +91,32 @@ * @param token Current token (unless beginning) | ||
*/ | ||
function lex(ctx: Context, token: Match | undefined, attributes?: { | ||
onError: ReturnType<typeof createErrorContext>; | ||
function lex( | ||
ctx: Context, | ||
token: Match | undefined, | ||
attributes?: { | ||
onError: ReturnType<typeof createErrorContext>; | ||
/** Requires enclosures to resolve such as a rule which resolve with '}' */ | ||
enclosures: TokenMatcher[]; | ||
/** Requires enclosures to resolve such as a rule which resolve with '}' */ | ||
enclosures: TokenMatcher[]; | ||
/** The current css rule or "scope" depth (levels nested) */ | ||
depth: number; | ||
/** The current css rule or "scope" depth (levels nested) */ | ||
depth: number; | ||
/** The depth of the :not() syntax. Required since you can nest them */ | ||
notOperatorDepth: number; | ||
}): ReturnType<typeof compile> | undefined { | ||
/** The depth of the :not() syntax. Required since you can nest them */ | ||
notOperatorDepth: number; | ||
} | ||
): ReturnType<typeof compile> | undefined { | ||
const { lastToken, index, css: preTokenizedCSS } = ctx; | ||
if (!token?.match) { | ||
if (index !== preTokenizedCSS.length || 0 !== (attributes?.depth ?? 0)) { | ||
if ( | ||
index !== preTokenizedCSS.length || | ||
0 !== (attributes?.depth ?? 0) | ||
) { | ||
if (attributes?.onError) { | ||
throw new SyntaxError(createCompilationError(ctx, attributes.onError)); | ||
throw new SyntaxError( | ||
createCompilationError(ctx, attributes.onError) | ||
); | ||
} else { | ||
throw new SyntaxError("Something went wrong during compilation"); | ||
throw new SyntaxError( | ||
"Something went wrong during compilation" | ||
); | ||
} | ||
@@ -68,14 +132,17 @@ } else { | ||
/** The depth refers to the css rule or "scope" nesting level */ | ||
const depth = (attributes?.depth ?? 0) + (() => { | ||
// The only way to descend a depth is to close it with the `}` token `styleScopeEnd` | ||
const descend = lastToken?.name === "styleScopeEnd"; | ||
if (descend) return -1; | ||
const depth = | ||
(attributes?.depth ?? 0) + | ||
(() => { | ||
// The only way to descend a depth is to close it with the `}` token `styleScopeEnd` | ||
const descend = lastToken?.name === "styleScopeEnd"; | ||
if (descend) return -1; | ||
// If the previous token isn't a selector and the current one is, | ||
// it must mean that a new scope is defined. | ||
const ascend = lastToken?.domain !== "selector" && token.domain === "selector"; | ||
if (ascend) return 1; | ||
// If the previous token isn't a selector and the current one is, | ||
// it must mean that a new scope is defined. | ||
const ascend = | ||
lastToken?.domain !== "selector" && token.domain === "selector"; | ||
if (ascend) return 1; | ||
return 0; | ||
})(); | ||
return 0; | ||
})(); | ||
@@ -85,15 +152,49 @@ const { slice, css } = ctx.tokenize(token, depth); | ||
const globals = renameTokens(globalTokens, resolvedType); | ||
const afterStyleScopeTokens = [ | ||
...globals, | ||
renameToken(whiteSpace, "styleScopeWhiteSpace"), | ||
notOperator, | ||
selectorCombinator, | ||
keyframes, | ||
atSymbol, | ||
styleScopeEnd, | ||
propertyName, | ||
selectorName, | ||
attributeSelectorClose, | ||
wildcard, | ||
idInitiator, | ||
classNameInitiator, | ||
currentSelector, | ||
]; | ||
switch (resolvedType) { | ||
case "skip": | ||
const [start, end] = [ctx.index, ctx.index + resolveSelectorNameNotFound(slice)] as const; | ||
const [start, end] = [ | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
] as const; | ||
const section = css.substring(start, end); | ||
const hint = enclosures.length === 0 && /&/.test(section) ? | ||
"Root level selectors cannot contain current selector ('&')." : | ||
/^\s*(?:~|>|\+|\|\|)/.test(section) ? | ||
"Root level selectors cannot begin with a selector combinator ('~', '>', '+', '||'). Did you forget to add left side selector combinator operand?" : | ||
"Instead found invalid or missing selector."; | ||
const hint = | ||
enclosures.length === 0 && /&/.test(section) | ||
? "Root level selectors cannot contain current selector ('&')." | ||
: /^\s*(?:~|>|\+|\|\|)/.test(section) | ||
? "Root level selectors cannot begin with a selector combinator ('~', '>', '+', '||'). Did you forget to add left side selector combinator operand?" | ||
: "Instead found invalid or missing selector."; | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, atSymbol, whiteSpace, ...enclosures, ..._if(enclosures.length === 0, [rootSelector]), ..._if(depth > 0, [currentSelector]), attributeSelectorInitiator, classNameInitiator, selectorName, idInitiator, wildcard, notOperator), | ||
expect( | ||
slice, | ||
...globals, | ||
atSymbol, | ||
whiteSpace, | ||
...enclosures, | ||
..._if(enclosures.length === 0, [rootSelector]), | ||
..._if(depth > 0, [currentSelector]), | ||
attributeSelectorInitiator, | ||
classNameInitiator, | ||
selectorName, | ||
idInitiator, | ||
wildcard, | ||
notOperator | ||
), | ||
{ | ||
@@ -103,3 +204,3 @@ onError: createErrorContext( | ||
start, | ||
end, | ||
end | ||
), | ||
@@ -109,23 +210,31 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "notOperator": | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, notOperatorParenthesis), | ||
{ | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: '('.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}, | ||
); | ||
return lex(ctx, expect(slice, ...globals, notOperatorParenthesis), { | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: '('.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
case "notOperatorParenthesis": | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, ..._if(enclosures.length === 0, [rootSelector]), ..._if(depth > 0, [currentSelector]), notOperator, colon, attributeSelectorInitiator, classNameInitiator, selectorName, idInitiator, wildcard), | ||
expect( | ||
slice, | ||
...globals, | ||
..._if(enclosures.length === 0, [rootSelector]), | ||
..._if(depth > 0, [currentSelector]), | ||
notOperator, | ||
colon, | ||
attributeSelectorInitiator, | ||
classNameInitiator, | ||
selectorName, | ||
idInitiator, | ||
wildcard | ||
), | ||
{ | ||
@@ -135,3 +244,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -141,17 +250,38 @@ enclosures, | ||
notOperatorDepth: notOperatorDepth + 1, | ||
}, | ||
} | ||
); | ||
case "notOperatorParenthesisEndWhiteSpace": | ||
case "notOperatorParenthesisEnd": | ||
const newDepth = notOperatorDepth - (resolvedType === "notOperatorParenthesisEnd" ? 1 : 0); | ||
const newDepth = | ||
notOperatorDepth - | ||
(resolvedType === "notOperatorParenthesisEnd" ? 1 : 0); | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, renameToken(whiteSpace, "notOperatorParenthesisEndWhiteSpace"), ..._if(enclosures.length === 0, [rootSelector]), ..._if(depth > 0, [currentSelector]), ..._if(newDepth > 0, [notOperatorParenthesisEnd]), colon, selectorSeparator, styleScope, attributeSelectorInitiator, classNameInitiator, selectorName, idInitiator, wildcard), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken( | ||
whiteSpace, | ||
"notOperatorParenthesisEndWhiteSpace" | ||
), | ||
..._if(enclosures.length === 0, [rootSelector]), | ||
..._if(depth > 0, [currentSelector]), | ||
..._if(newDepth > 0, [notOperatorParenthesisEnd]), | ||
notOperator, | ||
colon, | ||
selectorSeparator, | ||
styleScope, | ||
attributeSelectorInitiator, | ||
classNameInitiator, | ||
selectorName, | ||
idInitiator, | ||
wildcard | ||
), | ||
{ | ||
onError: createErrorContext( | ||
newDepth === 0 ? | ||
"Unexpected token. Expected: [selector]." : | ||
"Unexpected token. Expected: ')' or [selector].", | ||
newDepth === 0 | ||
? "Unexpected token. Expected: [selector]." | ||
: "Unexpected token. Expected: ')' or [selector].", | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -161,3 +291,3 @@ enclosures, | ||
notOperatorDepth: newDepth, | ||
}, | ||
} | ||
); | ||
@@ -170,5 +300,5 @@ case "atSymbol": | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: 'color-profile', 'counter-style', 'document', 'font-face', 'font-feature-values', 'keyframes', 'media', 'page', 'property' or 'supports'. It's possible that this list is outdated, if so please make an issue on the repository.", | ||
"Unexpected token. Expected: 'color-profile', 'counter-style', 'document', 'font-face', 'font-feature-values', 'media', 'page', 'property' or 'supports'. It's possible that this list is outdated, if so please make an issue on the repository.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -178,3 +308,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -185,3 +315,7 @@ case "atKeyframes": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(selectorChild, "keyframesWhiteSpace"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf(renameToken(selectorChild, "keyframesWhiteSpace")) | ||
), | ||
{ | ||
@@ -191,3 +325,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -197,3 +331,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -203,3 +337,10 @@ case "keyframesWhiteSpace": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(selectorName, "keyframesName"), keyframesSpecialNames)), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(selectorName, "keyframesName"), | ||
keyframesSpecialNames | ||
) | ||
), | ||
{ | ||
@@ -209,3 +350,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -215,3 +356,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -221,21 +362,27 @@ case "keyframesSpecialNames": | ||
case "keyframesName": | ||
if (resolvedType === "keyframesName" && ["None", "initial"].includes(token.match.toString())) { | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals), | ||
{ | ||
onError: createErrorContext( | ||
`Invalid keyframes name. A keyframes name cannot be '${token.match}' as per "CSS Animations Level 2" w3c specification. You can wrap '${token.match}' in double quotes ('"') like this: '"${token.match}"' to still use this name.`, | ||
Math.max(ctx.index - token.match.toString().length, 0), | ||
ctx.index, | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}, | ||
); | ||
if ( | ||
resolvedType === "keyframesName" && | ||
["None", "initial"].includes(token.match.toString()) | ||
) { | ||
return lex(ctx, expect(slice, ...globals), { | ||
onError: createErrorContext( | ||
`Invalid keyframes name. A keyframes name cannot be '${token.match}' as per "CSS Animations Level 2" w3c specification. You can wrap '${token.match}' in double quotes ('"') like this: '"${token.match}"' to still use this name.`, | ||
Math.max(ctx.index - token.match.toString().length, 0), | ||
ctx.index | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
} | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(selectorChild, "keyframesNameWhiteSpace"), renameToken(styleScope, "keyframesScope"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(selectorChild, "keyframesNameWhiteSpace"), | ||
renameToken(styleScope, "keyframesScope") | ||
) | ||
), | ||
{ | ||
@@ -245,3 +392,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -251,3 +398,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -258,3 +405,11 @@ case "keyframesScopeWhitespace": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesScopeWhitespace"), keyframesSelector, renameToken(styleScopeEnd, "keyframesScopeEnd"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesScopeWhitespace"), | ||
keyframesSelector, | ||
renameToken(styleScopeEnd, "keyframesScopeEnd") | ||
) | ||
), | ||
{ | ||
@@ -264,3 +419,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -270,3 +425,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -277,3 +432,10 @@ case "keyframesBlockEndWhitespace": | ||
ctx, | ||
expect(slice, ...kf(renameToken(whiteSpace, "keyframesBlockEndWhitespace"), renameToken(styleScopeEnd, "keyframesScopeEnd"), keyframesSelector)), | ||
expect( | ||
slice, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesBlockEndWhitespace"), | ||
renameToken(styleScopeEnd, "keyframesScopeEnd"), | ||
keyframesSelector | ||
) | ||
), | ||
{ | ||
@@ -283,3 +445,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -289,3 +451,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -295,3 +457,16 @@ case "keyframesScopeEnd": | ||
ctx, | ||
expect(slice, ...kf(renameToken(whiteSpace, "keyframesScopeEnd")), ..._if(depth > 0, [styleScopeEnd]), currentSelector, propertyName, attributeSelectorClose, selectorName, idInitiator, classNameInitiator, atSymbol, whiteSpaceOrNothing), | ||
expect( | ||
slice, | ||
...kf(renameToken(whiteSpace, "keyframesScopeEnd")), | ||
..._if(depth > 0, [styleScopeEnd]), | ||
currentSelector, | ||
propertyName, | ||
attributeSelectorClose, | ||
selectorName, | ||
idInitiator, | ||
classNameInitiator, | ||
keyframes, | ||
atSymbol, | ||
whiteSpaceOrNothing | ||
), | ||
{ | ||
@@ -301,3 +476,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -307,3 +482,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -313,3 +488,11 @@ case "keyframesSelector": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesSelector"), renameToken(selectorSeparator, "keyframesSeparator"), renameToken(styleScope, "keyframesBlock"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesSelector"), | ||
renameToken(selectorSeparator, "keyframesSeparator"), | ||
renameToken(styleScope, "keyframesBlock") | ||
) | ||
), | ||
{ | ||
@@ -319,3 +502,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -325,3 +508,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -331,3 +514,10 @@ case "keyframesSeparator": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesSeparator"), keyframesSelector)), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesSeparator"), | ||
keyframesSelector | ||
) | ||
), | ||
{ | ||
@@ -337,3 +527,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -343,3 +533,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -350,3 +540,11 @@ case "keyframesBlockWhitespace": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesBlockWhitespace"), renameToken(propertyName, "keyframesBlockPropertyName"), renameToken(styleScopeEnd, "keyframesBlockEnd"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesBlockWhitespace"), | ||
renameToken(propertyName, "keyframesBlockPropertyName"), | ||
renameToken(styleScopeEnd, "keyframesBlockEnd") | ||
) | ||
), | ||
{ | ||
@@ -356,3 +554,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -362,3 +560,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -368,3 +566,10 @@ case "keyframesBlockPropertyName": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesBlockPropertyName"), renameToken(propertyColon, "keyframesPropertyColon"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesBlockPropertyName"), | ||
renameToken(propertyColon, "keyframesPropertyColon") | ||
) | ||
), | ||
{ | ||
@@ -374,3 +579,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -380,3 +585,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -386,3 +591,16 @@ case "keyframesPropertyColon": | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesPropertyColon"), ...renameTokens([propertyValueWithSemiColon, propertyValueWithoutSemiColon], "keyframesPropertyValue"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesPropertyColon"), | ||
...renameTokens( | ||
[ | ||
propertyValueWithSemiColon, | ||
propertyValueWithoutSemiColon, | ||
], | ||
"keyframesPropertyValue" | ||
) | ||
) | ||
), | ||
{ | ||
@@ -392,3 +610,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -398,3 +616,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -405,10 +623,18 @@ case "keyframesPropertyValue": { | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesPropertyValue"), renameToken(valueSemiColon, "keyframesValueSemiColon"), renameToken(styleScopeEnd, "keyframesBlockEnd"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesPropertyValue"), | ||
renameToken(valueSemiColon, "keyframesValueSemiColon"), | ||
renameToken(styleScopeEnd, "keyframesBlockEnd") | ||
) | ||
), | ||
{ | ||
onError: createErrorContext( | ||
hasSemiColon ? | ||
"Unexpected token. Expected: '}'." : | ||
"Unexpected token. Expected: ';' or '}'.", | ||
hasSemiColon | ||
? "Unexpected token. Expected: '}'." | ||
: "Unexpected token. Expected: ';' or '}'.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -418,3 +644,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -425,3 +651,11 @@ } | ||
ctx, | ||
expect(slice, ...globals, ...kf(renameToken(whiteSpace, "keyframesValueSemiColon"), renameToken(propertyName, "keyframesBlockPropertyName"), renameToken(styleScopeEnd, "keyframesBlockEnd"))), | ||
expect( | ||
slice, | ||
...globals, | ||
...kf( | ||
renameToken(whiteSpace, "keyframesValueSemiColon"), | ||
renameToken(propertyName, "keyframesBlockPropertyName"), | ||
renameToken(styleScopeEnd, "keyframesBlockEnd") | ||
) | ||
), | ||
{ | ||
@@ -431,3 +665,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -437,13 +671,28 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "nestedAtRuleName": | ||
return lex(ctx, expect(slice, ...globals, nestedAtRule), { | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: [at rule]", | ||
ctx.index, | ||
ctx.index + resolveEndOfPropertyValue(slice) | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
case "nestedAtRule": | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, nestedAtRule), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(styleScope, "nestedAtRuleStyleScope") | ||
), | ||
{ | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: [at rule]", | ||
"Unexpected token. Expected: '{'.", | ||
ctx.index, | ||
ctx.index + resolveEndOfPropertyValue(slice), | ||
ctx.index + resolveEndOfPropertyValue(slice) | ||
), | ||
@@ -453,13 +702,12 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "nestedAtRule": | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, styleScope), | ||
{ | ||
case "nestedAtRuleStyleScopeWhiteSpace": | ||
case "nestedAtRuleStyleScope": | ||
if (enclosures.length > 0) | ||
return lex(ctx, expect(slice, ...afterStyleScopeTokens), { | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: '{'.", | ||
ctx.index, | ||
ctx.index + resolveEndOfPropertyValue(slice), | ||
ctx.index + resolveEndOfPropertyValue(slice) | ||
), | ||
@@ -469,13 +717,23 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
); | ||
case "idInitiator": | ||
}); | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, selectorName), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(whiteSpace, "nestedAtRuleStyleScopeWhiteSpace"), | ||
selectorName, | ||
classNameInitiator, | ||
idInitiator, | ||
attributeSelectorInitiator, | ||
rootSelector, | ||
wildcard, | ||
atSymbol, | ||
styleScopeEnd | ||
), | ||
{ | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: ID name.", | ||
"Unexpected token. Expected: '{'.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveEndOfPropertyValue(slice) | ||
), | ||
@@ -485,4 +743,15 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "idInitiator": | ||
return lex(ctx, expect(slice, ...globals, selectorName), { | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: ID name.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
case "currentSelectorWhiteSpace": | ||
@@ -492,3 +761,21 @@ case "currentSelector": | ||
ctx, | ||
expect(slice, ...globals, ...renameTokens([whiteSpace], "currentSelectorWhiteSpace", "selector"), notOperator, selectorChild, classNameInitiator, colon, selectorName, selectorCombinator, selectorSeparator, styleScope, wildcard), | ||
expect( | ||
slice, | ||
...globals, | ||
...renameTokens( | ||
[whiteSpace], | ||
"currentSelectorWhiteSpace", | ||
"selector" | ||
), | ||
attributeSelectorInitiator, | ||
notOperator, | ||
selectorChild, | ||
classNameInitiator, | ||
colon, | ||
selectorName, | ||
selectorCombinator, | ||
selectorSeparator, | ||
styleScope, | ||
wildcard | ||
), | ||
{ | ||
@@ -498,3 +785,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -504,3 +791,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -510,3 +797,7 @@ case "attributeSelectorInitiator": | ||
ctx, | ||
expect(slice, ...globals, renameToken(selectorName, "attributeSelectorName")), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(selectorName, "attributeSelectorName") | ||
), | ||
{ | ||
@@ -516,3 +807,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -522,3 +813,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -528,3 +819,8 @@ case "attributeSelectorName": | ||
ctx, | ||
expect(slice, ...globals, attributeSelectorCloseWithoutOperator, attributeSelectorModifier), | ||
expect( | ||
slice, | ||
...globals, | ||
attributeSelectorCloseWithoutOperator, | ||
attributeSelectorModifier | ||
), | ||
{ | ||
@@ -534,3 +830,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -540,3 +836,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -546,3 +842,8 @@ case "attributeSelectorModifier": | ||
ctx, | ||
expect(slice, ...globals, attributeSelectorSingleQuoteInitiator, attributeSelectorDoubleQuoteInitiator), | ||
expect( | ||
slice, | ||
...globals, | ||
attributeSelectorSingleQuoteInitiator, | ||
attributeSelectorDoubleQuoteInitiator | ||
), | ||
{ | ||
@@ -552,3 +853,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -558,3 +859,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -567,5 +868,5 @@ case "attributeSelectorSingleQuoteInitiator": | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: \"'\"", | ||
'Unexpected token. Expected: "\'"', | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -575,3 +876,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -586,3 +887,3 @@ case "attributeSelectorDoubleQuoteInitiator": | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -592,31 +893,42 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "attributeSelectorDoubleQuoteBody": | ||
case "attributeSelectorSingleQuoteBody": | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, attributeSelectorClose), | ||
{ | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: 'i]', 'I]', 's]', 'S]', or ']'.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}, | ||
); | ||
return lex(ctx, expect(slice, ...globals, attributeSelectorClose), { | ||
onError: createErrorContext( | ||
"Unexpected token. Expected: 'i]', 'I]', 's]', 'S]', or ']'.", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
case "attributeSelectorClose": | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, renameToken(whiteSpace, "attributeSelectorClose"), ..._if(notOperatorDepth > 0, [notOperatorParenthesisEnd]), notOperator, selectorCombinator, wildcard, classNameInitiator, colon, selectorName, idInitiator, selectorSeparator, attributeSelectorInitiator, styleScope), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(whiteSpace, "attributeSelectorClose"), | ||
..._if(notOperatorDepth > 0, [notOperatorParenthesisEnd]), | ||
notOperator, | ||
selectorCombinator, | ||
wildcard, | ||
classNameInitiator, | ||
colon, | ||
selectorName, | ||
idInitiator, | ||
selectorSeparator, | ||
attributeSelectorInitiator, | ||
styleScope | ||
), | ||
{ | ||
onError: createErrorContext( | ||
notOperatorDepth === 0 ? | ||
"Unexpected token. Expected: [css selector] or '{'" : | ||
"Unexpected token. Expected: ')', [css selector] or '{'", | ||
notOperatorDepth === 0 | ||
? "Unexpected token. Expected: [css selector] or '{'" | ||
: "Unexpected token. Expected: ')', [css selector] or '{'", | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -626,3 +938,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -632,3 +944,8 @@ case "classNameInitiator": | ||
ctx, | ||
expect(slice, ...globals, exportClassName, renameToken(selectorName, "className")), | ||
expect( | ||
slice, | ||
...globals, | ||
exportClassName, | ||
renameToken(selectorName, "className") | ||
), | ||
{ | ||
@@ -638,3 +955,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -644,3 +961,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -650,3 +967,7 @@ case "exportClassName": | ||
ctx, | ||
expect(slice, ...globals, renameToken(selectorName, "className")), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(selectorName, "className") | ||
), | ||
{ | ||
@@ -656,3 +977,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -662,3 +983,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -668,3 +989,12 @@ case "wildcard": | ||
ctx, | ||
expect(slice, ...globals, notOperator, styleScope, colon, selectorChild, selectorSeparator, selectorCombinator), | ||
expect( | ||
slice, | ||
...globals, | ||
notOperator, | ||
styleScope, | ||
colon, | ||
selectorChild, | ||
selectorSeparator, | ||
selectorCombinator | ||
), | ||
{ | ||
@@ -674,3 +1004,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + (/\s/.exec(slice)?.index || 1), | ||
ctx.index + (/\s/.exec(slice)?.index || 1) | ||
), | ||
@@ -680,11 +1010,25 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "combinator": | ||
const previousIsCombinator = ctx.strippedTokens?.[ctx.strippedTokens.length - 2]?.name === "combinator"; | ||
const combinatorHint = previousIsCombinator ? "Combinators ('~', '>', '+', '||') cannot directly follow previous combinator. " : ""; | ||
const previousIsCombinator = | ||
ctx.strippedTokens?.[ctx.strippedTokens.length - 2]?.name === | ||
"combinator"; | ||
const combinatorHint = previousIsCombinator | ||
? "Combinators ('~', '>', '+', '||') cannot directly follow previous combinator. " | ||
: ""; | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, ...renameTokens([whiteSpace], "combinator", "selector"), notOperator, selectorName, idInitiator, attributeSelectorInitiator, classNameInitiator, wildcard), | ||
expect( | ||
slice, | ||
...globals, | ||
...renameTokens([whiteSpace], "combinator", "selector"), | ||
notOperator, | ||
selectorName, | ||
idInitiator, | ||
attributeSelectorInitiator, | ||
classNameInitiator, | ||
wildcard | ||
), | ||
{ | ||
@@ -694,3 +1038,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -700,3 +1044,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -706,3 +1050,9 @@ case "rootSelector": | ||
ctx, | ||
expect(slice, ...globals, renameToken(whiteSpace, "rootSelector"), styleScope, selectorCombinator), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(whiteSpace, "rootSelector"), | ||
styleScope, | ||
selectorCombinator | ||
), | ||
{ | ||
@@ -712,3 +1062,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + (/\s/.exec(slice)?.index || 1), | ||
ctx.index + (/\s/.exec(slice)?.index || 1) | ||
), | ||
@@ -718,3 +1068,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -725,3 +1075,15 @@ case "className": | ||
ctx, | ||
expect(slice, ...globals, notOperator, ..._if(notOperatorDepth > 0, [notOperatorParenthesisEnd]), attributeSelectorInitiator, colon, styleScope, selectorChild, selectorSeparator, classNameInitiator, selectorCombinator), | ||
expect( | ||
slice, | ||
...globals, | ||
notOperator, | ||
..._if(notOperatorDepth > 0, [notOperatorParenthesisEnd]), | ||
attributeSelectorInitiator, | ||
colon, | ||
styleScope, | ||
selectorChild, | ||
selectorSeparator, | ||
classNameInitiator, | ||
selectorCombinator | ||
), | ||
{ | ||
@@ -731,3 +1093,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -737,24 +1099,30 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "selectorSeparator": | ||
if (notOperatorDepth !== 0) { | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals), | ||
{ | ||
onError: createErrorContext( | ||
`Unexpected selector separator ','. Selector branching is not valid inside ':not(...)' and ':has(...)' operators. Did you forget '${")".repeat(Math.max(1, notOperatorDepth))}'?`, | ||
Math.max(0, ctx.index - 1), | ||
ctx.index, | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}, | ||
); | ||
return lex(ctx, expect(slice, ...globals), { | ||
onError: createErrorContext( | ||
`Unexpected selector separator ','. Selector branching is not valid inside ':not(...)' and ':has(...)' operators. Did you forget '${")".repeat( | ||
Math.max(1, notOperatorDepth) | ||
)}'?`, | ||
Math.max(0, ctx.index - 1), | ||
ctx.index | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
} | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, ..._if(enclosures.length === 0, [rootSelector]), currentSelector, classNameInitiator, selectorName, idInitiator), | ||
expect( | ||
slice, | ||
...globals, | ||
..._if(enclosures.length === 0, [rootSelector]), | ||
currentSelector, | ||
classNameInitiator, | ||
selectorName, | ||
idInitiator | ||
), | ||
{ | ||
@@ -764,3 +1132,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -770,3 +1138,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -776,3 +1144,14 @@ case "selectorChild": | ||
ctx, | ||
expect(slice, ...globals, styleScope, attributeSelectorInitiator, selectorSeparator, selectorName, classNameInitiator, idInitiator, wildcard, selectorCombinator), | ||
expect( | ||
slice, | ||
...globals, | ||
styleScope, | ||
attributeSelectorInitiator, | ||
selectorSeparator, | ||
selectorName, | ||
classNameInitiator, | ||
idInitiator, | ||
wildcard, | ||
selectorCombinator | ||
), | ||
{ | ||
@@ -782,3 +1161,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -788,35 +1167,31 @@ enclosures, | ||
notOperatorDepth, | ||
}); | ||
} | ||
); | ||
case "styleScopeWhiteSpace": | ||
case "styleScope": | ||
if (notOperatorDepth !== 0) { | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals), | ||
{ | ||
onError: createErrorContext( | ||
"Unexpected token in style scope. Expected: ')'. Did you forget to end your ':not(...)' or ':has(...)' operator?", | ||
Math.max(0, ctx.index - 1), | ||
ctx.index, | ||
), | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}, | ||
); | ||
} | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, renameToken(whiteSpace, "styleScopeWhiteSpace"), notOperator, selectorCombinator, atSymbol, styleScopeEnd, propertyName, selectorName, attributeSelectorClose, wildcard, idInitiator, classNameInitiator, currentSelector), | ||
{ | ||
return lex(ctx, expect(slice, ...globals), { | ||
onError: createErrorContext( | ||
"Unexpected token in style scope. Expected: '}', [css selector] or [css property].", | ||
ctx.index, | ||
ctx.index + 1, | ||
"Unexpected token in style scope. Expected: ')'. Did you forget to end your ':not(...)' or ':has(...)' operator?", | ||
Math.max(0, ctx.index - 1), | ||
ctx.index | ||
), | ||
enclosures: [...(resolvedType === "styleScope" ? [styleScopeEnd] : []), ...enclosures], | ||
enclosures, | ||
depth, | ||
notOperatorDepth, | ||
}, | ||
); | ||
}); | ||
} | ||
return lex(ctx, expect(slice, ...afterStyleScopeTokens), { | ||
onError: createErrorContext( | ||
"Unexpected token in style scope. Expected: '}', [css selector] or [css property].", | ||
ctx.index, | ||
ctx.index + 1 | ||
), | ||
enclosures: [ | ||
...(resolvedType === "styleScope" ? [styleScopeEnd] : []), | ||
...enclosures, | ||
], | ||
depth, | ||
notOperatorDepth, | ||
}); | ||
case "styleScopeEnd": | ||
@@ -826,8 +1201,26 @@ return lex( | ||
// add non ending condition? | ||
expect(slice, renameToken(whiteSpace, "styleScopeEnd"), ..._if(depth > 0, [styleScopeEnd, selectorCombinator, currentSelector, notOperator, colon]), propertyName, attributeSelectorClose, selectorName, idInitiator, classNameInitiator, atSymbol, whiteSpaceOrNothing), | ||
expect( | ||
slice, | ||
renameToken(whiteSpace, "styleScopeEnd"), | ||
..._if(depth > 0, [ | ||
styleScopeEnd, | ||
selectorCombinator, | ||
currentSelector, | ||
notOperator, | ||
colon, | ||
]), | ||
propertyName, | ||
attributeSelectorClose, | ||
selectorName, | ||
idInitiator, | ||
classNameInitiator, | ||
keyframes, | ||
atSymbol, | ||
whiteSpaceOrNothing | ||
), | ||
{ | ||
onError: createErrorContext( | ||
"Unexpected token. Undefined behavior." + (depth), | ||
"Unexpected token. Undefined behavior." + depth, | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -837,6 +1230,12 @@ enclosures: enclosures.slice(1), | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "colon": | ||
return lex(ctx, expect(slice, ...globals, renameToken(pseudoSelector, "selectorName")), | ||
return lex( | ||
ctx, | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(pseudoSelector, "selectorName") | ||
), | ||
{ | ||
@@ -846,3 +1245,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + resolveSelectorNameNotFound(slice), | ||
ctx.index + resolveSelectorNameNotFound(slice) | ||
), | ||
@@ -852,6 +1251,13 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "propertyName": | ||
return lex(ctx, expect(slice, ...globals, renameToken(whiteSpace, "propertyName"), propertyColon), | ||
return lex( | ||
ctx, | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(whiteSpace, "propertyName"), | ||
propertyColon | ||
), | ||
{ | ||
@@ -861,3 +1267,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -867,9 +1273,15 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "propertyColon": | ||
const errorStartEstimate = resolveEndOfPropertyValue(slice) + ctx.index; | ||
const errorStartEstimate = | ||
resolveEndOfPropertyValue(slice) + ctx.index; | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, propertyValueWithSemiColon, propertyValueWithoutSemiColon), | ||
expect( | ||
slice, | ||
...globals, | ||
propertyValueWithSemiColon, | ||
propertyValueWithoutSemiColon | ||
), | ||
{ | ||
@@ -879,3 +1291,3 @@ onError: createErrorContext( | ||
errorStartEstimate, | ||
errorStartEstimate, | ||
errorStartEstimate | ||
), | ||
@@ -885,6 +1297,7 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
case "propertyValue": | ||
return lex(ctx, | ||
return lex( | ||
ctx, | ||
expect(slice, ...globals, styleScopeEnd, valueSemiColon), | ||
@@ -895,3 +1308,3 @@ { | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -901,3 +1314,3 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
@@ -907,3 +1320,17 @@ case "valueSemiColon": | ||
ctx, | ||
expect(slice, ...globals, renameToken(whiteSpace, "valueSemiColon"), atKeyframes, selectorCombinator, currentSelector, notOperator, valueSemiColon, propertyName, styleScopeEnd, classNameInitiator, idInitiator, selectorName), | ||
expect( | ||
slice, | ||
...globals, | ||
renameToken(whiteSpace, "valueSemiColon"), | ||
atKeyframes, | ||
selectorCombinator, | ||
currentSelector, | ||
notOperator, | ||
valueSemiColon, | ||
propertyName, | ||
styleScopeEnd, | ||
classNameInitiator, | ||
idInitiator, | ||
selectorName | ||
), | ||
{ | ||
@@ -913,3 +1340,3 @@ onError: createErrorContext( | ||
ctx.index, | ||
ctx.index + 1, | ||
ctx.index + 1 | ||
), | ||
@@ -919,8 +1346,9 @@ enclosures, | ||
notOperatorDepth, | ||
}, | ||
} | ||
); | ||
default: | ||
throw new SyntaxError("Something internally went wrong during the lexical analysis. This error indicates one or more token matchers are not recognized by the lexer."); | ||
throw new SyntaxError( | ||
"Something internally went wrong during the lexical analysis. This error indicates one or more token matchers are not recognized by the lexer." | ||
); | ||
} | ||
} | ||
@@ -932,10 +1360,12 @@ | ||
/** | ||
* Conditionally expect tokens | ||
* @param condition | ||
* @param condition | ||
* @param tokens token matchers which will be outputted given condition is truthy | ||
* @returns Empty array or input array of token matcher(s) | ||
*/ | ||
function _if(condition: boolean | null | undefined, tokens: TokenMatcher[]): TokenMatcher[] { | ||
function _if( | ||
condition: boolean | null | undefined, | ||
tokens: TokenMatcher[] | ||
): TokenMatcher[] { | ||
return condition ? tokens : []; | ||
@@ -942,0 +1372,0 @@ } |
@@ -25,3 +25,3 @@ "use strict"; | ||
function renameTokens(tokenMatchers, renamed, newDomain) { | ||
return tokenMatchers.map(tokenMatcher => { | ||
return tokenMatchers.map((tokenMatcher) => { | ||
return (input) => { | ||
@@ -50,3 +50,3 @@ const prev = tokenMatcher(input); | ||
function attributeAdder(attribute, tokens) { | ||
return tokens.map(token => { | ||
return tokens.map((token) => { | ||
return (input) => { | ||
@@ -58,3 +58,5 @@ const match = token(input); | ||
...match, | ||
attributes: [...new Set(["keyframes", ...(match.attributes ?? [])])], | ||
attributes: [ | ||
...new Set(["keyframes", ...(match.attributes ?? [])]), | ||
], | ||
}; | ||
@@ -112,3 +114,3 @@ }; | ||
domain: "selector", | ||
attributes: ["keyframes"], | ||
attributes: ["atRule"], | ||
match: input.match(/^@/), | ||
@@ -123,3 +125,3 @@ }; | ||
attributes: ["keyframes"], | ||
match: input.match(/^keyframes/i), | ||
match: input.match(/^@keyframes/i), | ||
}; | ||
@@ -355,2 +357,3 @@ } | ||
function valueSemiColon(input) { | ||
// todo: rename to Semicolon | ||
return { | ||
@@ -357,0 +360,0 @@ type: "valueSemiColon", |
@@ -8,3 +8,3 @@ export type Domains = "selector" | "style" | "void" | "flow"; | ||
match: RegExpMatchArray | null; | ||
} | ||
}; | ||
@@ -15,3 +15,3 @@ export type TokenMatcher = (input: string) => Match | undefined; | ||
* Renames a token. Useful for borrowing logic while preserving the current grammar branch. | ||
* | ||
* | ||
* **Note:** this doesn't actually change the name of token, it merely sets the | ||
@@ -23,3 +23,7 @@ * renamed property to the new name which the lexer understands. | ||
*/ | ||
export function renameToken(tokenMatcher: (input: string) => Match, renamed: string, newDomain?: Domains): TokenMatcher { | ||
export function renameToken( | ||
tokenMatcher: (input: string) => Match, | ||
renamed: string, | ||
newDomain?: Domains | ||
): TokenMatcher { | ||
return (input: string) => { | ||
@@ -31,8 +35,12 @@ const prev = tokenMatcher(input); | ||
renamed, | ||
} | ||
} | ||
}; | ||
}; | ||
} | ||
export function renameTokens(tokenMatchers: ((input: string) => Match)[], renamed: string, newDomain?: Domains): TokenMatcher[] { | ||
return tokenMatchers.map(tokenMatcher => { | ||
export function renameTokens( | ||
tokenMatchers: ((input: string) => Match)[], | ||
renamed: string, | ||
newDomain?: Domains | ||
): TokenMatcher[] { | ||
return tokenMatchers.map((tokenMatcher) => { | ||
return (input: string) => { | ||
@@ -44,4 +52,4 @@ const prev = tokenMatcher(input); | ||
renamed, | ||
} | ||
} | ||
}; | ||
}; | ||
}); | ||
@@ -61,5 +69,7 @@ } | ||
function attributeAdder(attribute: string, tokens: TokenMatcher[]): TokenMatcher[] { | ||
return tokens.map(token => { | ||
function attributeAdder( | ||
attribute: string, | ||
tokens: TokenMatcher[] | ||
): TokenMatcher[] { | ||
return tokens.map((token) => { | ||
return (input: string) => { | ||
@@ -70,5 +80,7 @@ const match = token(input); | ||
...match, | ||
attributes: [...new Set(["keyframes", ...(match.attributes ?? [])])], | ||
attributes: [ | ||
...new Set(["keyframes", ...(match.attributes ?? [])]), | ||
], | ||
}; | ||
} | ||
}; | ||
}); | ||
@@ -83,3 +95,2 @@ } | ||
export function ifOperator(input: string): Match { | ||
@@ -91,3 +102,3 @@ return { | ||
match: input.match(/^@if/), | ||
} | ||
}; | ||
} | ||
@@ -100,3 +111,3 @@ export function notOperator(input: string): Match { | ||
match: input.match(/^:(?:not|has)/i), | ||
} | ||
}; | ||
} | ||
@@ -109,3 +120,3 @@ export function notOperatorParenthesis(input: string): Match { | ||
match: input.match(/^\(/), | ||
} | ||
}; | ||
} | ||
@@ -118,3 +129,3 @@ export function notOperatorParenthesisEnd(input: string): Match { | ||
match: input.match(/^\)/), | ||
} | ||
}; | ||
} | ||
@@ -126,5 +137,5 @@ | ||
domain: "selector", | ||
attributes: ["keyframes"], | ||
attributes: ["atRule"], | ||
match: input.match(/^@/), | ||
} | ||
}; | ||
} | ||
@@ -136,4 +147,4 @@ export function keyframes(input: string): Match { | ||
attributes: ["keyframes"], | ||
match: input.match(/^keyframes/i), | ||
} | ||
match: input.match(/^@keyframes/i), | ||
}; | ||
} | ||
@@ -146,3 +157,3 @@ export function atKeyframes(input: string): Match { | ||
match: input.match(/^@keyframes/i), | ||
} | ||
}; | ||
} | ||
@@ -155,3 +166,3 @@ export function keyframesSpecialNames(input: string): Match { | ||
match: input.match(/^"initial"|^"None"/), | ||
} | ||
}; | ||
} | ||
@@ -166,3 +177,3 @@ | ||
match: input.match(/^\d+%|^to|^from/i), | ||
} | ||
}; | ||
} | ||
@@ -176,4 +187,6 @@ | ||
attributes: ["atRule"], | ||
match: input.match(/^(?:color-profile|counter-style|document|font-face|font-feature-values|media|page|property|supports)/i), | ||
} | ||
match: input.match( | ||
/^(?:color-profile|counter-style|document|font-face|font-feature-values|media|page|property|supports)/i | ||
), | ||
}; | ||
} | ||
@@ -189,6 +202,5 @@ | ||
match: input.match(/^.*?(?={)/), | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -202,3 +214,3 @@ * Capture only whitespace start to finish indicating end of stylesheet | ||
match: input.match(/^\s+$/), | ||
} | ||
}; | ||
} | ||
@@ -211,3 +223,3 @@ | ||
match: input.match(/^:root/), | ||
} | ||
}; | ||
} | ||
@@ -220,3 +232,3 @@ | ||
match: input.match(/^\/\/.*/), | ||
} | ||
}; | ||
} | ||
@@ -229,6 +241,5 @@ | ||
match: input.match(/^\/\*[\S\s]*?\*\//), | ||
} | ||
}; | ||
} | ||
export function whiteSpace(input: string): Match { | ||
@@ -239,3 +250,3 @@ return { | ||
match: input.match(/^[\s\n\r]+/), | ||
} | ||
}; | ||
} | ||
@@ -248,3 +259,3 @@ | ||
match: input.match(/^::?/), | ||
} | ||
}; | ||
} | ||
@@ -256,3 +267,3 @@ export function pseudoSelector(input: string): Match { | ||
match: input.match(/^[a-zA-Z-]+/), | ||
} | ||
}; | ||
} | ||
@@ -265,3 +276,3 @@ | ||
match: input.match(/^[\s\n\r]*/), | ||
} | ||
}; | ||
} | ||
@@ -274,3 +285,3 @@ | ||
match: input.match(/^\./), | ||
} | ||
}; | ||
} | ||
@@ -282,3 +293,3 @@ export function exportClassName(input: string): Match { | ||
match: input.match(/^\./), | ||
} | ||
}; | ||
} | ||
@@ -290,3 +301,3 @@ export function idInitiator(input: string): Match { | ||
match: input.match(/^#/), | ||
} | ||
}; | ||
} | ||
@@ -298,3 +309,3 @@ export function selectorSeparator(input: string): Match { | ||
match: input.match(/^,\s*/), | ||
} | ||
}; | ||
} | ||
@@ -306,3 +317,3 @@ export function selectorChild(input: string): Match { | ||
match: input.match(/^\s+/), | ||
} | ||
}; | ||
} | ||
@@ -314,3 +325,3 @@ export function selectorName(input: string): Match { | ||
match: input.match(/^[a-zA-Z0-9_-]+/), | ||
} | ||
}; | ||
} | ||
@@ -322,3 +333,3 @@ export function styleScope(input: string): Match { | ||
match: input.match(/^{/), | ||
} | ||
}; | ||
} | ||
@@ -330,3 +341,3 @@ export function requiredWhiteSpace(input: string): Match { | ||
match: input.match(/^\s+/), | ||
} | ||
}; | ||
} | ||
@@ -338,5 +349,5 @@ export function styleScopeEnd(input: string): Match { | ||
match: input.match(/^\s*}/), | ||
} | ||
}; | ||
} | ||
/** | ||
/** | ||
* Problematic token because it conflicts with selector name. | ||
@@ -352,3 +363,3 @@ * The implemented solution here is using a positive look ahead, | ||
match: input.match(/^[a-zA-Z0-9-_]+(?=:)/), | ||
} | ||
}; | ||
} | ||
@@ -360,3 +371,3 @@ export function propertyColon(input: string): Match { | ||
match: input.match(/^:/), | ||
} | ||
}; | ||
} | ||
@@ -368,3 +379,3 @@ export function propertyValueWithSemiColon(input: string): Match { | ||
match: serializePropertyValues(input.match(/(.|\r|\n)*?(?=;)/)), | ||
} | ||
}; | ||
} | ||
@@ -376,5 +387,6 @@ export function propertyValueWithoutSemiColon(input: string): Match { | ||
match: serializePropertyValues(input.match(/(.|\r|\n)*?(?=})/)), | ||
} | ||
}; | ||
} | ||
export function valueSemiColon(input: string): Match { // todo: rename to Semicolon | ||
export function valueSemiColon(input: string): Match { | ||
// todo: rename to Semicolon | ||
return { | ||
@@ -384,3 +396,3 @@ type: "valueSemiColon", | ||
match: input.match(/^;/), | ||
} | ||
}; | ||
} | ||
@@ -393,3 +405,3 @@ | ||
match: input.match(/^\[/), | ||
} | ||
}; | ||
} | ||
@@ -401,3 +413,3 @@ export function attributeSelectorModifier(input: string): Match { | ||
match: input.match(/^\s*[!|~^$*]{0,1}=/), | ||
} | ||
}; | ||
} | ||
@@ -409,3 +421,3 @@ export function attributeSelectorSingleQuoteInitiator(input: string): Match { | ||
match: input.match(/^\s*'/), | ||
} | ||
}; | ||
} | ||
@@ -417,3 +429,3 @@ export function attributeSelectorSingleQuoteBody(input: string): Match { | ||
match: input.match(/^.*?(?:[^\\]+?')|^'/), | ||
} | ||
}; | ||
} | ||
@@ -425,3 +437,3 @@ export function attributeSelectorDoubleQuoteInitiator(input: string): Match { | ||
match: input.match(/^\s*"/), | ||
} | ||
}; | ||
} | ||
@@ -433,3 +445,3 @@ export function attributeSelectorDoubleQuoteBody(input: string): Match { | ||
match: input.match(/^.*?(?:[^\\]+?")|^"/), | ||
} | ||
}; | ||
} | ||
@@ -441,3 +453,3 @@ export function attributeSelectorClose(input: string): Match { | ||
match: input.match(/^\s*[iIsS]{0,1}\]/), | ||
} | ||
}; | ||
} | ||
@@ -449,3 +461,3 @@ export function attributeSelectorCloseWithoutOperator(input: string): Match { | ||
match: input.match(/^\s*\]/), | ||
} | ||
}; | ||
} | ||
@@ -458,3 +470,3 @@ | ||
match: input.match(/(^>|^~|^\+|^\|\|)/), | ||
} | ||
}; | ||
} | ||
@@ -467,3 +479,3 @@ | ||
match: input.match(/^\*/), | ||
} | ||
}; | ||
} | ||
@@ -476,3 +488,3 @@ | ||
match: input.match(/^&/), | ||
} | ||
} | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
224672
89
4989