diff --git a/CHANGELOG.md b/CHANGELOG.md index f4964db0..c596644b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,18 @@ # Changelog +## v1.4.6 + +- [x] Fix if syntax expansion regression bug #134 + ## v1.4.5 -- [x] Temporarily disable if syntax expansion +- [x] Temporarily disable if syntax expansion #131 ## v1.4.4 ### Validation changes -- [x] Added the `state` and `errors` properties to nodes to expose their validation status and any associated validation errors. +- [x] Added the `state` and `errors` properties to nodes to expose their validation status and any associated validation errors. #127 - [x] Nodes that fail validation are no longer discarded. Nodes are discarded only if they are invalid, unparsed, or malformed. Unknown nodes are discarded when lenient parsing is disabled. ### Color diff --git a/README.md b/README.md index 63a24c6f..6e9655d0 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ $ deno add @tbela99/css-parser ## Syntax lowering CSS-Parser can transform these modern CSS features into lower-level CSS syntax: * **Nested CSS transpilation** to legacy-compatible syntax. +* **`if()` function transpilation** for broader browser compatibility. * **`color-mix()` function conversion** convert new color-mix() syntax to any of the supported colors. ## Benchmark diff --git a/dist/index-umd-web.js b/dist/index-umd-web.js index b5efc654..9d03e05e 100644 --- a/dist/index-umd-web.js +++ b/dist/index-umd-web.js @@ -12107,29 +12107,6 @@ if (!doNotValidate && !result?.success && result.errors.length > 0) { errors.push(...result.errors); } - if (!doNotValidate && !(success || result.success)) { - return Object.defineProperties(Object.assign(name, { - typ: exports.EnumToken.DeclarationNodeType, - nam: name.val, - val: parseTokens(tokens), - }), { - state: { - ...definedPropertySettings, - value: exports.EnumAstNodeStatus.ValidationFailed, - }, - errors: { - ...definedPropertySettings, - value: result?.errors ?? [], - }, - loc: { - ...definedPropertySettings, - value: { - ...name.loc, - end: tokens[tokens.length - 1]?.loc.end ?? name.loc.end, - }, - }, - }); - } } } for (i = 0; i < tokens.length; i++) { @@ -30131,8 +30108,6 @@ if (options.resolveImport) { options.resolveUrls = true; } - // turn off expandIfSyntax for now - options.expandIfSyntax = false; const startTime = performance.now(); const errors = []; const src = options.src; diff --git a/dist/index.cjs b/dist/index.cjs index 9bdd000b..ea9bbcad 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -9211,29 +9211,6 @@ function parseDeclaration(tokens, parent, options, errors) { if (!doNotValidate && !result?.success && result.errors.length > 0) { errors.push(...result.errors); } - if (!doNotValidate && !(success || result.success)) { - return Object.defineProperties(Object.assign(name, { - typ: exports.EnumToken.DeclarationNodeType, - nam: name.val, - val: parseTokens(tokens), - }), { - state: { - ...definedPropertySettings, - value: exports.EnumAstNodeStatus.ValidationFailed, - }, - errors: { - ...definedPropertySettings, - value: result?.errors ?? [], - }, - loc: { - ...definedPropertySettings, - value: { - ...name.loc, - end: tokens[tokens.length - 1]?.loc.end ?? name.loc.end, - }, - }, - }); - } } } for (i = 0; i < tokens.length; i++) { @@ -29896,8 +29873,6 @@ async function doParse(iter, options = {}) { if (options.resolveImport) { options.resolveUrls = true; } - // turn off expandIfSyntax for now - options.expandIfSyntax = false; const startTime = performance.now(); const errors = []; const src = options.src; diff --git a/dist/lib/parser/parse.js b/dist/lib/parser/parse.js index d84dc5c2..55f12277 100644 --- a/dist/lib/parser/parse.js +++ b/dist/lib/parser/parse.js @@ -244,8 +244,6 @@ async function doParse(iter, options = {}) { if (options.resolveImport) { options.resolveUrls = true; } - // turn off expandIfSyntax for now - options.expandIfSyntax = false; const startTime = performance.now(); const errors = []; const src = options.src; diff --git a/dist/lib/parser/utils/declaration.js b/dist/lib/parser/utils/declaration.js index 298f2821..e98b5c31 100644 --- a/dist/lib/parser/utils/declaration.js +++ b/dist/lib/parser/utils/declaration.js @@ -8,7 +8,6 @@ import { walkValues } from '../../ast/walk.js'; import { equalsIgnoreCase } from './text.js'; import { buildExpression } from '../../ast/math/expression.js'; import { splitTokenList } from '../../validation/utils/list.js'; -import { parseTokens } from '../parse.js'; /** * @@ -333,29 +332,6 @@ function parseDeclaration(tokens, parent, options, errors) { if (!doNotValidate && !result?.success && result.errors.length > 0) { errors.push(...result.errors); } - if (!doNotValidate && !(success || result.success)) { - return Object.defineProperties(Object.assign(name, { - typ: EnumToken.DeclarationNodeType, - nam: name.val, - val: parseTokens(tokens), - }), { - state: { - ...definedPropertySettings, - value: EnumAstNodeStatus.ValidationFailed, - }, - errors: { - ...definedPropertySettings, - value: result?.errors ?? [], - }, - loc: { - ...definedPropertySettings, - value: { - ...name.loc, - end: tokens[tokens.length - 1]?.loc.end ?? name.loc.end, - }, - }, - }); - } } } for (i = 0; i < tokens.length; i++) { diff --git a/files/index.md b/files/index.md index f7a27f97..9956e5da 100644 --- a/files/index.md +++ b/files/index.md @@ -34,4 +34,4 @@ children: - [Benchmark](https://tbela99.github.io/css-parser/benchmark/index.html) ------ -[About →](./about.md) \ No newline at end of file +[Getting Started →](./getting-started.md) \ No newline at end of file diff --git a/jsr.json b/jsr.json index 1a21db4f..566a5d7c 100644 --- a/jsr.json +++ b/jsr.json @@ -1,6 +1,6 @@ { "name": "@tbela99/css-parser", - "version": "1.4.5", + "version": "1.4.6", "publish": { "include": [ "src", diff --git a/package.json b/package.json index fa4c17a3..93ec5b11 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@tbela99/css-parser", "description": "CSS parser, minifier and validator for node and the browser", - "version": "1.4.5", + "version": "1.4.6", "exports": { ".": "./dist/node.js", "./node": "./dist/node.js", diff --git a/src/lib/parser/parse.ts b/src/lib/parser/parse.ts index df0cf61f..14b5ed4a 100644 --- a/src/lib/parser/parse.ts +++ b/src/lib/parser/parse.ts @@ -351,9 +351,6 @@ export async function doParse( options.resolveUrls = true; } - // turn off expandIfSyntax for now - options.expandIfSyntax = false; - const startTime: number = performance.now(); const errors: ErrorDescription[] = []; const src: string = options.src as string; diff --git a/src/lib/parser/utils/declaration.ts b/src/lib/parser/utils/declaration.ts index 13797f24..b72d8a51 100644 --- a/src/lib/parser/utils/declaration.ts +++ b/src/lib/parser/utils/declaration.ts @@ -451,33 +451,6 @@ export function parseDeclaration( if (!doNotValidate && !result?.success && result!.errors!.length > 0) { errors.push(...result!.errors); } - - if (!doNotValidate && !(success || result!.success)) { - return Object.defineProperties( - Object.assign(name, { - typ: EnumToken.DeclarationNodeType, - nam: name.val, - val: parseTokens(tokens), - }), - { - state: { - ...definedPropertySettings, - value: EnumAstNodeStatus.ValidationFailed, - }, - errors: { - ...definedPropertySettings, - value: result?.errors ?? [], - }, - loc: { - ...definedPropertySettings, - value: { - ...name.loc, - end: tokens[tokens.length - 1]?.loc!.end ?? name.loc!.end, - }, - }, - }, - ) as AstDeclaration; - } } } diff --git a/test/specs/code/at-rules.js b/test/specs/code/at-rules.js index 57e4217c..92440784 100644 --- a/test/specs/code/at-rules.js +++ b/test/specs/code/at-rules.js @@ -1333,40 +1333,40 @@ supports((selector(h2 > p)) and (font-tech(color-COLRv1))) { -// it('do not minify supports() arguments #58', function () { -// return transform(` - -// body { -// background-color: if( -// supports(color: oklch(0.7 0.185 232)): oklch(0.7 0.185 232); -// else: #00adf3; -// ); + it('do not minify supports() arguments #58', function () { + return transform(` + +body { + background-color: if( + supports(color: oklch(0.7 0.185 232)): oklch(0.7 0.185 232); + else: #00adf3; + ); -// &::after { -// content: if( -// supports(color: oklch(0.7 0.185 232)): "Your browser supports OKLCH"; -// else: "Your browser does not support OKLCH"; -// ); -// } -// } - -// `, { -// beautify: true, -// expandIfSyntax: true, -// validation: true -// }).then((result) => expect(result.code).equals(`body { -// background-color: #00adf3; -// @supports (color:oklch(.7 .185 232)) { -// background-color: #00aefc -// } -// &:after { -// content: "Your browser does not support OKLCH"; -// @supports (color:oklch(.7 .185 232)) { -// content: "Your browser supports OKLCH" -// } -// } -// }`)); -// }); + &::after { + content: if( + supports(color: oklch(0.7 0.185 232)): "Your browser supports OKLCH"; + else: "Your browser does not support OKLCH"; + ); + } +} + + `, { + beautify: true, + expandIfSyntax: true, + validation: true + }).then((result) => expect(result.code).equals(`body { + background-color: #00adf3; + @supports (color:oklch(.7 .185 232)) { + background-color: #00aefc + } + &:after { + content: "Your browser does not support OKLCH"; + @supports (color:oklch(.7 .185 232)) { + content: "Your browser supports OKLCH" + } + } +}`)); + }); diff --git a/test/specs/code/expand.js b/test/specs/code/expand.js index d5d76b98..f3a9a170 100644 --- a/test/specs/code/expand.js +++ b/test/specs/code/expand.js @@ -406,162 +406,162 @@ html { }`)); }); -// it('if(media()) #18', function () { -// const nesting1 = ` -// button { -// aspect-ratio: 1; -// width: if(media(any-pointer: fine): 30px; else: 44px); -// } -// `; -// return transform(nesting1, { -// beautify: true, expandIfSyntax: true -// }).then((result) => expect(result.code).equals(`button { -// aspect-ratio: 1; -// width: 44px; -// @media (any-pointer:fine) { -// width: 30px -// } -// }`)); -// }); + it('if(media()) #18', function () { + const nesting1 = ` +button { + aspect-ratio: 1; + width: if(media(any-pointer: fine): 30px; else: 44px); +} +`; + return transform(nesting1, { + beautify: true, expandIfSyntax: true + }).then((result) => expect(result.code).equals(`button { + aspect-ratio: 1; + width: 44px; + @media (any-pointer:fine) { + width: 30px + } +}`)); + }); -// it('if(media()) #19', function () { -// const nesting1 = ` - -// div-1 { -// background-image: if( -// else: none; -// ); -// } -// div-2 { -// background-image: if( -// style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8) ; -// else: none ; -// ); - -// div-3 { -// background-image: if( -// style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8); -// style(--scheme: fire): linear-gradient(#ffc971, white, #ffc971); -// else: none; -// ); -// } -// div-4 { -// background-image: if( + it('if(media()) #19', function () { + const nesting1 = ` + +div-1 { + background-image: if( + else: none; + ); +} +div-2 { + background-image: if( + style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8) ; + else: none ; +); + +div-3 { + background-image: if( + style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8); + style(--scheme: fire): linear-gradient(#ffc971, white, #ffc971); + else: none; + ); +} +div-4 { + background-image: if( -// ); -// } -// `; -// return transform(nesting1, { -// beautify: true, expandIfSyntax: true -// }).then((result) => expect(result.code).equals(`div-1,div-2 { -// background-image: none -// } -// div-2 { -// @container style(--scheme:ice) { -// background-image: linear-gradient(#caf0f8,#fff,#caf0f8) -// } -// div-3 { -// background-image: none; -// @container style(--scheme:ice) { -// background-image: linear-gradient(#caf0f8,#fff,#caf0f8) -// } -// @container style(--scheme:fire) { -// background-image: linear-gradient(#ffc971,#fff,#ffc971) -// } -// } -// div-4 { -// background-image: if() -// } -// }`)); -// }); + ); +} +`; + return transform(nesting1, { + beautify: true, expandIfSyntax: true + }).then((result) => expect(result.code).equals(`div-1,div-2 { + background-image: none +} +div-2 { + @container style(--scheme:ice) { + background-image: linear-gradient(#caf0f8,#fff,#caf0f8) + } + div-3 { + background-image: none; + @container style(--scheme:ice) { + background-image: linear-gradient(#caf0f8,#fff,#caf0f8) + } + @container style(--scheme:fire) { + background-image: linear-gradient(#ffc971,#fff,#ffc971) + } + } + div-4 { + background-image: if() + } +}`)); + }); -// it('if(media(), style()) #20', function () { -// const nesting1 = ` - -// button { -// background: linear-gradient( -// if(media(min-width: 768px): to right; else: to bottom), -// if(style(--dark-mode): #333; else: #fff), -// if(style(--dark-mode): #000; else: #ccc) -// ); -// } -// `; -// return transform(nesting1, { -// beautify: true, expandIfSyntax: true -// }).then((result) => expect(result.code).equals(`button { -// background: linear-gradient(#fff,#ccc); -// @media (min-width:768px) { -// background: linear-gradient(90deg,#fff,#ccc); -// @container style(--dark-mode) { -// background: linear-gradient(90deg,#333,#000) -// } -// } -// @container style(--dark-mode) { -// background: linear-gradient(#333,#000) -// } -// }`)); -// }); + it('if(media(), style()) #20', function () { + const nesting1 = ` + +button { + background: linear-gradient( + if(media(min-width: 768px): to right; else: to bottom), + if(style(--dark-mode): #333; else: #fff), + if(style(--dark-mode): #000; else: #ccc) + ); +} +`; + return transform(nesting1, { + beautify: true, expandIfSyntax: true + }).then((result) => expect(result.code).equals(`button { + background: linear-gradient(#fff,#ccc); + @media (min-width:768px) { + background: linear-gradient(90deg,#fff,#ccc); + @container style(--dark-mode) { + background: linear-gradient(90deg,#333,#000) + } + } + @container style(--dark-mode) { + background: linear-gradient(#333,#000) + } +}`)); + }); -// it('if(media(), style()) #21', function () { -// const nesting1 = ` + it('if(media(), style()) #21', function () { + const nesting1 = ` -// div-4 { -// color: if( +div-4 { + color: if( -// ); -// background: -// light-dark(if(style(--dark-mode): #333; else: #fff), if(media(min-width: 768px): white; else: black) -// ); -// } -// `; -// return transform(nesting1, { -// beautify: true, expandIfSyntax: true -// }).then((result) => expect(result.code).equals(`div-4 { -// color: if(); -// background: light-dark(#fff,#000); -// @container style(--dark-mode) { -// background: light-dark(#333,#000); -// @media (min-width:768px) { -// background: light-dark(#333,#fff) -// } -// } -// @media (min-width:768px) { -// background: light-dark(#fff,#fff) -// } -// }`)); -// }); + ); + background: + light-dark(if(style(--dark-mode): #333; else: #fff), if(media(min-width: 768px): white; else: black) + ); +} +`; + return transform(nesting1, { + beautify: true, expandIfSyntax: true + }).then((result) => expect(result.code).equals(`div-4 { + color: if(); + background: light-dark(#fff,#000); + @container style(--dark-mode) { + background: light-dark(#333,#000); + @media (min-width:768px) { + background: light-dark(#333,#fff) + } + } + @media (min-width:768px) { + background: light-dark(#fff,#fff) + } +}`)); + }); -// it('if(supports()) #22', function () { -// const nesting1 = ` - -// body { -// background-color: if( -// supports(color: oklch(0.7 0.185 232)): oklch(0.7 0.185 232); -// else: #00adf3; -// ); + it('if(supports()) #22', function () { + const nesting1 = ` + +body { + background-color: if( + supports(color: oklch(0.7 0.185 232)): oklch(0.7 0.185 232); + else: #00adf3; + ); -// &::after { -// content: if( -// supports(color: oklch(0.7 0.185 232)): "Your browser supports OKLCH"; -// else: "Your browser does not support OKLCH"; -// ); -// } -// } - -// `; -// return transform(nesting1, { -// beautify: true, -// removePrefix: true, -// validation: true -// }).then((result) => expect(result.code).equals(`body { -// background-color: if(supports(color:oklch(.7 .185 232)):#00aefc;else:#00adf3); -// &:after { -// content: if(supports(color:oklch(.7 .185 232)):"Your browser supports OKLCH";else:"Your browser does not support OKLCH") -// } -// }`)); -// }); + &::after { + content: if( + supports(color: oklch(0.7 0.185 232)): "Your browser supports OKLCH"; + else: "Your browser does not support OKLCH"; + ); + } +} + +`; + return transform(nesting1, { + beautify: true, + removePrefix: true, + validation: true + }).then((result) => expect(result.code).equals(`body { + background-color: if(supports(color:oklch(.7 .185 232)):#00aefc;else:#00adf3); + &:after { + content: if(supports(color:oklch(.7 .185 232)):"Your browser supports OKLCH";else:"Your browser does not support OKLCH") + } +}`)); + }); }); }