diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a46b257..98fb2763 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [5.5.0] - 2024-09-28 + +- Support for nested at-rules + ## [5.4.0] - 2024-09-01 - Update `RTLCSS` to version `4.3.0` diff --git a/src/@types/index.ts b/src/@types/index.ts index 20b4076d..75163b35 100644 --- a/src/@types/index.ts +++ b/src/@types/index.ts @@ -4,6 +4,8 @@ import { Declaration } from 'postcss'; +export type DeclarationContainer = Rule | AtRule; + export enum Mode { combined = 'combined', override = 'override', diff --git a/src/data/store.ts b/src/data/store.ts index ccb0bfb5..5d4e64a3 100644 --- a/src/data/store.ts +++ b/src/data/store.ts @@ -1,7 +1,8 @@ -import { Rule, AtRule } from 'postcss'; +import { AtRule } from 'postcss'; import { PluginOptions, PluginOptionsNormalized, + DeclarationContainer, DeclarationPlugin, DeclarationPluginProcessor, AtRulesObject, @@ -31,7 +32,7 @@ interface Store { keyframesStringMap: AtRulesStringMap; keyframesRegExp: RegExp; rules: RulesObject[]; - rulesToRemove: Rule[]; + containersToRemove: DeclarationContainer[]; rulesPrefixRegExp: RegExp; unmodifiedRules: UnmodifiedRulesObject[]; } @@ -169,7 +170,7 @@ const store: Store = { keyframesStringMap: {}, keyframesRegExp: defaultRegExp, rules: [], - rulesToRemove: [], + containersToRemove: [], rulesPrefixRegExp: defaultRegExp, unmodifiedRules: [] }; @@ -248,7 +249,7 @@ const initStore = (options: PluginOptions): void => { store.keyframesStringMap = {}; store.keyframesRegExp = defaultRegExp; store.rules = []; - store.rulesToRemove = []; + store.containersToRemove = []; store.rulesPrefixRegExp = createRulesPrefixesRegExp(store.options); store.unmodifiedRules = []; }; diff --git a/src/parsers/atrules.ts b/src/parsers/atrules.ts index 25252369..977d50d1 100644 --- a/src/parsers/atrules.ts +++ b/src/parsers/atrules.ts @@ -29,8 +29,13 @@ import { import { isAtRule } from '@utilities/predicates'; import { vendor } from '@utilities/vendor'; import { parseRules } from '@parsers/rules'; +import { parseDeclarations } from './declarations'; -export const parseAtRules = (container: Container): void => { +export const parseAtRules = ( + container: Container, + parentSourceDirective: string = undefined, + hasParentRule = false +): void => { const controlDirectives: Record = {}; @@ -56,11 +61,35 @@ export const parseAtRules = (container: Container): void => { if (vendor.unprefixed(node.name) === KEYFRAMES_NAME) return; - const sourceDirectiveValue = getSourceDirectiveValue(controlDirectives); + const sourceDirectiveValue = getSourceDirectiveValue( + controlDirectives, + parentSourceDirective + ); + + if ( + hasParentRule && + node.nodes + ) { + parseDeclarations( + node, + hasParentRule, + sourceDirectiveValue, + checkDirective(controlDirectives, CONTROL_DIRECTIVE.RULES), + checkDirective(controlDirectives, CONTROL_DIRECTIVE.URLS) + ); + } - parseRules(node, sourceDirectiveValue); + parseAtRules( + node, + parentSourceDirective, + hasParentRule + ); - parseAtRules(node); + parseRules( + node, + sourceDirectiveValue, + hasParentRule + ); } ); diff --git a/src/parsers/declarations.ts b/src/parsers/declarations.ts index 1c45f93c..cf5534d1 100644 --- a/src/parsers/declarations.ts +++ b/src/parsers/declarations.ts @@ -6,9 +6,10 @@ import postcss, { } from 'postcss'; import rtlcss from 'rtlcss'; import { - Mode, ControlDirective, - DeclarationHashMap + DeclarationContainer, + DeclarationHashMap, + Mode } from '@types'; import { TYPE, @@ -33,17 +34,17 @@ import { hasMirrorDeclaration, hasSameUpcomingDeclarationWithoutMirror } from '@utilities/declarations'; -import { isDeclaration } from '@utilities/predicates'; +import { isDeclaration, isRule } from '@utilities/predicates'; import { walkContainer } from '@utilities/containers'; import { cleanRuleRawsBefore, insertRuleIntoStore, - appendParentRuleToStore + appendParentContainerToStore } from '@utilities/rules'; import { vendor } from '@utilities/vendor'; export const parseDeclarations = ( - rule: Rule, + container: DeclarationContainer, hasParentRule: boolean, ruleSourceDirectiveValue: string, processRule: boolean, @@ -65,14 +66,14 @@ export const parseDeclarations = ( } = store.options; const deleteDeclarations: Declaration[] = []; - const ruleFlipped = rule.clone().removeAll(); - const ruleFlippedSecond = ruleFlipped.clone(); - const ruleBoth = ruleFlipped.clone(); - const ruleSafe = ruleFlipped.clone(); + const containerFlipped = container.clone().removeAll(); + const containerFlippedSecond = containerFlipped.clone(); + const containerBoth = containerFlipped.clone(); + const containerSafe = containerFlipped.clone(); - const declarationHashMap = Array.prototype.reduce.call(rule.nodes, (obj: DeclarationHashMap, node: Node): DeclarationHashMap => { + const declarationHashMap = Array.prototype.reduce.call(container.nodes, (obj: DeclarationHashMap, node: Node): DeclarationHashMap => { if (isDeclaration(node)) { - const index = rule.index(node); + const index = container.index(node); obj[node.prop] = obj[node.prop] || { ignore: false, indexes: {} }; obj[node.prop].indexes[index] = { decl: node, @@ -88,7 +89,7 @@ export const parseDeclarations = ( let simetricRules = false; walkContainer( - rule, + container, [ TYPE.DECLARATION ], (comment: Comment, controlDirective: ControlDirective) => { @@ -108,7 +109,7 @@ export const parseDeclarations = ( const root = postcss.parse( controlDirective.option, { - from: rule.source?.input?.from + from: container.source?.input?.from } ); if ( @@ -130,9 +131,9 @@ export const parseDeclarations = ( ) ) ) { - ruleFlippedSecond.append(root.nodes); + containerFlippedSecond.append(root.nodes); } else { - ruleFlipped.append(root.nodes); + containerFlipped.append(root.nodes); } } @@ -167,7 +168,7 @@ export const parseDeclarations = ( const root = postcss.parse( declFlippedString, { - from: rule.source?.input?.from + from: container.source?.input?.from } ); const declFlipped = root.first as Declaration; @@ -231,7 +232,7 @@ export const parseDeclarations = ( declarationHashMap[decl.prop].ignore && !isConflictedDeclaration ) || - hasSameUpcomingDeclarationWithoutMirror(rule, decl, declFlipped, declarationHashMap) + hasSameUpcomingDeclarationWithoutMirror(container, decl, declFlipped, declarationHashMap) ) { return; } @@ -248,9 +249,9 @@ export const parseDeclarations = ( ) { if (safeBothPrefix && !hasIgnoreDirectiveInRaws(decl)) { if (mode === Mode.diff) { - appendDeclarationToRule(decl, ruleFlipped); + appendDeclarationToRule(decl, containerFlipped); } else { - appendDeclarationToRule(decl, ruleSafe); + appendDeclarationToRule(decl, containerSafe); } deleteDeclarations.push(decl); } @@ -274,23 +275,23 @@ export const parseDeclarations = ( declClone.value = animationDeclValue; declCloneFlipped.value = animationDeclValueFlipped; if (normalFlip) { - ruleFlipped.append(declClone); - ruleFlippedSecond.append(declCloneFlipped); + containerFlipped.append(declClone); + containerFlippedSecond.append(declCloneFlipped); } else { - ruleFlipped.append(declCloneFlipped); - ruleFlippedSecond.append(declClone); + containerFlipped.append(declCloneFlipped); + containerFlippedSecond.append(declClone); } deleteDeclarations.push(decl); } else { decl.value = animationDeclValue; declCloneFlipped.value = animationDeclValueFlipped; if (normalFlip) { - ruleFlipped.append(declCloneFlipped); + containerFlipped.append(declCloneFlipped); } else { - ruleFlippedSecond.append(declCloneFlipped); + containerFlippedSecond.append(declCloneFlipped); } if (safeBothPrefix && mode !== Mode.diff) { - appendDeclarationToRule(decl, ruleSafe); + appendDeclarationToRule(decl, containerSafe); deleteDeclarations.push(decl); } } @@ -311,25 +312,25 @@ export const parseDeclarations = ( !hasIgnoreDirectiveInRaws(decl) ) { if (mode === Mode.diff) { - appendDeclarationToRule(decl, ruleFlipped); + appendDeclarationToRule(decl, containerFlipped); } else { appendDeclarationToRule( decl, hasBeenOverriden || overridesPrevious - ? ruleBoth - : ruleSafe + ? containerBoth + : containerSafe ); } deleteDeclarations.push(decl); } return; - } else if (hasMirrorDeclaration(rule, declFlipped, declarationHashMap)) { + } else if (hasMirrorDeclaration(container, declFlipped, declarationHashMap)) { simetricRules = true; if (isConflictedDeclaration && !hasIgnoreDirectiveInRaws(decl)) { if (mode === Mode.diff) { - appendDeclarationToRule(decl, ruleFlipped); + appendDeclarationToRule(decl, containerFlipped); } else { - appendDeclarationToRule(decl, ruleSafe); + appendDeclarationToRule(decl, containerSafe); } deleteDeclarations.push(decl); } @@ -338,18 +339,18 @@ export const parseDeclarations = ( if (mode === Mode.combined) { if (normalFlip) { - appendDeclarationToRule(decl, ruleFlipped); - ruleFlippedSecond.append(declFlipped); + appendDeclarationToRule(decl, containerFlipped); + containerFlippedSecond.append(declFlipped); } else { - appendDeclarationToRule(decl, ruleFlippedSecond); - ruleFlipped.append(declFlipped); + appendDeclarationToRule(decl, containerFlippedSecond); + containerFlipped.append(declFlipped); } deleteDeclarations.push(decl); } else { if ( FLIP_PROPERTY_REGEXP.test(decl.prop) && !declarationHashMap[declFlipped.prop] && - rule.index(decl) === declIndexes[0] + container.index(decl) === declIndexes[0] ) { const declClone = decl.clone(); /* If for some reason the initial value is not covered in the code it should be unset */ @@ -357,9 +358,9 @@ export const parseDeclarations = ( /* istanbul ignore next */ declClone.value = initialValues[decl.prop] || 'unset'; if (normalFlip) { - ruleFlipped.append(declClone); + containerFlipped.append(declClone); } else { - ruleFlippedSecond.append(declClone); + containerFlippedSecond.append(declClone); } } if ( @@ -367,13 +368,13 @@ export const parseDeclarations = ( !hasIgnoreDirectiveInRaws(decl) && mode !== Mode.diff ) { - appendDeclarationToRule(decl, ruleSafe); + appendDeclarationToRule(decl, containerSafe); deleteDeclarations.push(decl); } if (normalFlip) { - ruleFlipped.append(declFlipped); + containerFlipped.append(declFlipped); } else { - ruleFlippedSecond.append(declFlipped); + containerFlippedSecond.append(declFlipped); } } @@ -390,41 +391,42 @@ export const parseDeclarations = ( } if ( - ruleFlipped.nodes.length || - ruleFlippedSecond.nodes.length || - ruleBoth.nodes.length || - ruleSafe.nodes.length + containerFlipped.nodes.length || + containerFlippedSecond.nodes.length || + containerBoth.nodes.length || + containerSafe.nodes.length ) { if (hasParentRule) { - appendParentRuleToStore( - rule, - ruleFlipped, - ruleFlippedSecond, - ruleBoth, - ruleSafe + appendParentContainerToStore( + container, + containerFlipped, + containerFlippedSecond, + containerBoth, + containerSafe ); } else { insertRuleIntoStore( - rule, - ruleFlipped, - ruleFlippedSecond, - ruleBoth, - ruleSafe + container as Rule, + containerFlipped as Rule, + containerFlippedSecond as Rule, + containerBoth as Rule, + containerSafe as Rule ); } } else if ( - ( + isRule(container) + && ( processRuleNames || processRule - ) && - !simetricRules + ) + && !simetricRules ) { store.unmodifiedRules.push({ - rule, + rule: container, hasParentRule }); } else if (mode === Mode.diff) { - store.rulesToRemove.push(rule); + store.containersToRemove.push(container); } }; \ No newline at end of file diff --git a/src/parsers/rules.ts b/src/parsers/rules.ts index e23a437f..17676402 100644 --- a/src/parsers/rules.ts +++ b/src/parsers/rules.ts @@ -18,18 +18,19 @@ import { import { walkContainer } from '@utilities/containers'; import { cleanRuleRawsBefore } from '@utilities/rules'; import { addSelectorPrefixes, hasSelectorsPrefixed } from '@utilities/selectors'; +import { parseAtRules } from './atrules'; import { parseDeclarations } from './declarations'; const addToIgnoreRulesInDiffMode = (rule: Rule): void => { if (store.options.mode === Mode.diff) { - store.rulesToRemove.push(rule); + store.containersToRemove.push(rule); } }; export const parseRules = ( container: Container, parentSourceDirective: string = undefined, - hasParentRule = false, + hasParentRule = false ): void => { const controlDirectives: Record = {}; @@ -114,6 +115,12 @@ export const parseRules = ( checkDirective(controlDirectives, CONTROL_DIRECTIVE.URLS) ); } + + parseAtRules( + node, + parentSourceDirective, + true + ); parseRules( node, diff --git a/src/utilities/clean.ts b/src/utilities/clean.ts index a069dd3b..6f0b42da 100644 --- a/src/utilities/clean.ts +++ b/src/utilities/clean.ts @@ -19,7 +19,7 @@ export const clean = (css: Container): void => { const { options, rules, - rulesToRemove, + containersToRemove, keyframes, keyframesToRemove } = store; @@ -28,7 +28,7 @@ export const clean = (css: Container): void => { rules.forEach((rulesObject: RulesObject): void => { rulesObject.rule.remove(); }); - rulesToRemove.forEach((rule: Rule) => { + containersToRemove.forEach((rule: Rule) => { rule.remove(); }); keyframes.forEach(({atRule}): void => { diff --git a/src/utilities/declarations.ts b/src/utilities/declarations.ts index 1b2c0cd6..e92b022d 100644 --- a/src/utilities/declarations.ts +++ b/src/utilities/declarations.ts @@ -1,5 +1,6 @@ -import { Rule, Declaration } from 'postcss'; +import { Declaration } from 'postcss'; import { + DeclarationContainer, DeclarationsData, DeclarationHashMap } from '@types'; @@ -74,15 +75,15 @@ Object.keys(initialValuesData).forEach((value: string): void => { }); }); -const appendDeclarationToRule = (decl: Declaration, rule: Rule): void => { +const appendDeclarationToRule = (decl: Declaration, container: DeclarationContainer): void => { const declClone = decl.clone(); const declPrev = decl.prev(); if (declPrev && isComment(declPrev)) { const commentClone = declPrev.clone(); - rule.append(commentClone); + container.append(commentClone); declPrev.remove(); } - rule.append(declClone); + container.append(declClone); }; const hasIgnoreDirectiveInRaws = (decl: Declaration): boolean => { @@ -98,12 +99,12 @@ const checkOverrides = (decl: string, decls: string[]): boolean => { }; const hasSameUpcomingDeclarationWithoutMirror = ( - rule: Rule, + container: DeclarationContainer, decl: Declaration, declFlipped: Declaration, declarationHashMap: DeclarationHashMap ): boolean => { - const index = rule.index(decl); + const index = container.index(decl); const hashMapData = declarationHashMap[decl.prop]; const indexes = Object.keys(hashMapData.indexes).map(Number).sort(); if (indexes.length === 1) { @@ -131,11 +132,11 @@ const hasSameUpcomingDeclarationWithoutMirror = ( }; const hasSameUpcomingDeclaration = ( - rule: Rule, + container: DeclarationContainer, decl: Declaration, declarationHashMap: DeclarationHashMap ): boolean => { - const index = rule.index(decl); + const index = container.index(decl); const indexes = Object.keys(declarationHashMap[decl.prop].indexes).map(Number); if (indexes.length === 1) { return false; @@ -144,7 +145,7 @@ const hasSameUpcomingDeclaration = ( }; const hasMirrorDeclaration = ( - rule: Rule, + container: DeclarationContainer, declFlipped: Declaration, declarationHashMap: DeclarationHashMap ): boolean => { @@ -153,7 +154,7 @@ const hasMirrorDeclaration = ( return entries.some((entry) => { return ( entry[1].value === declFlipped.value.trim() && - !hasSameUpcomingDeclaration(rule, entry[1].decl, declarationHashMap) + !hasSameUpcomingDeclaration(container, entry[1].decl, declarationHashMap) ); }); } diff --git a/src/utilities/predicates.ts b/src/utilities/predicates.ts index 37c8c421..c2a5964c 100644 --- a/src/utilities/predicates.ts +++ b/src/utilities/predicates.ts @@ -5,6 +5,7 @@ import { Node, Rule } from 'postcss'; +import { DeclarationContainer } from '@types'; import { TYPE, TYPEOF } from '@constants'; type FunctionType = (...args: unknown[]) => unknown; @@ -13,6 +14,7 @@ export const isAtRule = (node: Node): node is AtRule => node.type === TYPE.AT_RU export const isComment = (node: Node): node is Comment => node.type === TYPE.COMMENT; export const isDeclaration = (node: Node): node is Declaration => node.type === TYPE.DECLARATION; export const isRule = (node: Node): node is Rule => node.type === TYPE.RULE; +export const isDeclarationContainer = (node: Node): node is DeclarationContainer => isRule(node) || isAtRule(node); export const isBoolean = (value: unknown): value is boolean => typeof value === TYPEOF.BOOLEAN; export const isFunction = (value: unknown): value is FunctionType => typeof value === TYPEOF.FUNCTION; diff --git a/src/utilities/rules.ts b/src/utilities/rules.ts index 3217f390..e1fae4fa 100644 --- a/src/utilities/rules.ts +++ b/src/utilities/rules.ts @@ -1,11 +1,11 @@ import { Container, Rule, - AtRule, Node, Declaration } from 'postcss'; import { + DeclarationContainer, RulesObject, UnmodifiedRulesObject, StringMap, @@ -17,13 +17,14 @@ import { isAtRule, isComment, isDeclaration, + isDeclarationContainer, isRule, isString } from '@utilities/predicates'; import { addProperSelectorPrefixes } from '@utilities/selectors'; -export const ruleHasDeclarations = (rule: Rule): boolean => { - return rule.some( +export const containerHasDeclarations = (container: DeclarationContainer): boolean => { + return container.some( (node: Node) => isDeclaration(node) ); }; @@ -45,73 +46,74 @@ export const ruleHasChildren = (rule: Container): boolean => { ); }; -export const getParentRules = (rule: Rule): Rule[] => { - const rules: Rule[] = []; - while (isRule(rule)) { - rules.push(rule); - rule = rule.parent as Rule; +export const getParentContainers = (container: DeclarationContainer): DeclarationContainer[] => { + const containers: DeclarationContainer[] = []; + while (isDeclarationContainer(container)) { + containers.unshift(container); + container = container.parent as DeclarationContainer; } - rules.shift(); - return rules.reverse(); + containers.pop(); + return containers; }; export const insertRules = ( - parent: Rule, - rule: Rule, - rules: Rule[] + parent: DeclarationContainer, + container: DeclarationContainer, + containers: DeclarationContainer[] ): void => { - if (ruleHasDeclarations(rule)) { - rules = [...rules]; - let parentRule: Rule; - while (rules.length) { - parentRule = rules.shift(); + if (containerHasDeclarations(container)) { + containers = [...containers]; + let parentContainer: DeclarationContainer; + while (containers.length) { + parentContainer = containers.shift(); const innerRule = parent.nodes.find((node: Node): boolean => { if ( - isRule(node) && - node.selector === parentRule.selector + isRule(node) + && isRule(parentContainer) + && node.selector === parentContainer.selector ) { return true; } - }) as Rule | undefined; + }) as DeclarationContainer | undefined; if (innerRule) { - parentRule = innerRule; + parentContainer = innerRule; } else { - parentRule = parentRule.clone().removeAll(); - parent.append(parentRule); + parentContainer = parentContainer.clone().removeAll(); + parent.append(parentContainer); } - parent = parentRule; + parent = parentContainer; } - parent.append(rule); + parent.append(container); } }; -export const appendRulesToRuleObject = ( - ruleFlipped: Rule, - ruleFlippedSecond: Rule, - ruleBoth: Rule, - ruleSafe: Rule, +export const appendContainersToRuleObject = ( + containerFlipped: DeclarationContainer, + containerFlippedSecond: DeclarationContainer, + containerBoth: DeclarationContainer, + containerSafe: DeclarationContainer, ruleObject: RulesObject, - rules: Rule[] + containers: DeclarationContainer[] ): void => { insertRules( ruleObject.ruleLTR, - ruleFlipped, - rules + containerFlipped, + containers ); insertRules( ruleObject.ruleRTL, - ruleFlippedSecond, - rules + containerFlippedSecond, + containers ); insertRules( ruleObject.ruleBoth, - ruleBoth, - rules + containerBoth, + containers ); insertRules( ruleObject.ruleSafe, - ruleSafe, - rules + containerSafe, + containers ); }; @@ -141,16 +143,16 @@ export const insertRuleIntoStore = ( return rulesObject; }; -export const appendParentRuleToStore = ( - rule: Rule, - ruleFlipped: Rule, - ruleFlippedSecond: Rule, - ruleBoth: Rule, - ruleSafe: Rule +export const appendParentContainerToStore = ( + container: DeclarationContainer, + containerFlipped: DeclarationContainer, + containerFlippedSecond: DeclarationContainer, + containerBoth: DeclarationContainer, + containerSafe: DeclarationContainer ): void => { - const rules = getParentRules(rule); - const root = rules.shift(); + const containers = getParentContainers(container); + const root = containers.shift() as Rule; let rootRulesObject: RulesObject | undefined = store.rules.find( (rObject: RulesObject) => rObject.rule === root @@ -169,13 +171,13 @@ export const appendParentRuleToStore = ( ); } - appendRulesToRuleObject( - ruleFlipped, - ruleFlippedSecond, - ruleBoth, - ruleSafe, + appendContainersToRuleObject( + containerFlipped, + containerFlippedSecond, + containerBoth, + containerSafe, rootRulesObject, - rules + containers ); }; @@ -196,8 +198,8 @@ export const cleanRuleRawsBefore = (node: Node | undefined, prefix = '\n\n'): vo } }; -export const cleanRules = (...rules: (Rule | AtRule)[]): void => { - rules.forEach((rule: Rule | AtRule | undefined | null): void => { +export const cleanRules = (...rules: DeclarationContainer[]): void => { + rules.forEach((rule: DeclarationContainer | undefined | null): void => { const prev = rule.prev(); if (prev && !isComment(prev)) { cleanRuleRawsBefore(rule); @@ -295,7 +297,7 @@ export const parseRuleNames = (): void => { if (process) { rulesToProcess.push(ruleObject); } else if (store.options.mode === Mode.diff) { - store.rulesToRemove.push(ruleObject.rule); + store.containersToRemove.push(ruleObject.rule); } }); @@ -322,7 +324,7 @@ export const parseRuleNames = (): void => { if (hasParentRule) { - appendParentRuleToStore( + appendParentContainerToStore( rule.removeAll(), ruleFlipped, ruleFlippedSecond, @@ -346,7 +348,7 @@ export const parseRuleNames = (): void => { if (hasParentRule) { - appendParentRuleToStore( + appendParentContainerToStore( store.options.mode === Mode.override ? rule : rule.removeAll(), @@ -375,7 +377,7 @@ export const parseRuleNames = (): void => { } if (store.options.mode === Mode.diff) { - store.rulesToRemove.push(rule); + store.containersToRemove.push(rule); } }); diff --git a/tests/__snapshots__/nested-rules/combined/source-ltr-process-rule-names-true.snapshot b/tests/__snapshots__/nested-rules/combined/source-ltr-process-rule-names-true.snapshot index 169eb588..d6069bf4 100644 --- a/tests/__snapshots__/nested-rules/combined/source-ltr-process-rule-names-true.snapshot +++ b/tests/__snapshots__/nested-rules/combined/source-ltr-process-rule-names-true.snapshot @@ -165,13 +165,35 @@ exports[`[[Mode: combined]] Nested rules tests: {source: ltr} processRuleNames: .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; } } } [dir="ltr"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 5px 20px 2px; + } + } + + @media screen and (min-width: 800px) { + left: 10px; + } + } + .test13 { text-align: right; } @@ -186,6 +208,18 @@ exports[`[[Mode: combined]] Nested rules tests: {source: ltr} processRuleNames: } [dir="rtl"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/combined/source-ltr.snapshot b/tests/__snapshots__/nested-rules/combined/source-ltr.snapshot index 5f419e76..09ce73a7 100644 --- a/tests/__snapshots__/nested-rules/combined/source-ltr.snapshot +++ b/tests/__snapshots__/nested-rules/combined/source-ltr.snapshot @@ -165,7 +165,17 @@ exports[`[[Mode: combined]] Nested rules tests: {source: ltr} 1`] = ` .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; } } @@ -180,12 +190,36 @@ exports[`[[Mode: combined]] Nested rules tests: {source: ltr} 1`] = ` } [dir="ltr"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 5px 20px 2px; + } + } + + @media screen and (min-width: 800px) { + left: 10px; + } + } + .test13 { text-align: right; } } [dir="rtl"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/combined/source-rtl-process-rule-names-true.snapshot b/tests/__snapshots__/nested-rules/combined/source-rtl-process-rule-names-true.snapshot index 4d3c9cbe..1c08c251 100644 --- a/tests/__snapshots__/nested-rules/combined/source-rtl-process-rule-names-true.snapshot +++ b/tests/__snapshots__/nested-rules/combined/source-rtl-process-rule-names-true.snapshot @@ -165,13 +165,35 @@ exports[`[[Mode: combined]] Nested rules tests: {source: rtl} processRuleNames: .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; } } } [dir="rtl"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 5px 20px 2px; + } + } + + @media screen and (min-width: 800px) { + left: 10px; + } + } + .test13 { text-align: right; } @@ -186,6 +208,18 @@ exports[`[[Mode: combined]] Nested rules tests: {source: rtl} processRuleNames: } [dir="ltr"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/combined/source-rtl.snapshot b/tests/__snapshots__/nested-rules/combined/source-rtl.snapshot index c2d8b786..8a01a465 100644 --- a/tests/__snapshots__/nested-rules/combined/source-rtl.snapshot +++ b/tests/__snapshots__/nested-rules/combined/source-rtl.snapshot @@ -165,7 +165,17 @@ exports[`[[Mode: combined]] Nested rules tests: {source: rtl} 1`] = ` .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; } } @@ -180,12 +190,36 @@ exports[`[[Mode: combined]] Nested rules tests: {source: rtl} 1`] = ` } [dir="rtl"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 5px 20px 2px; + } + } + + @media screen and (min-width: 800px) { + left: 10px; + } + } + .test13 { text-align: right; } } [dir="ltr"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/diff/source-ltr-process-rule-names-true.snapshot b/tests/__snapshots__/nested-rules/diff/source-ltr-process-rule-names-true.snapshot index 3f3c23d3..8190e795 100644 --- a/tests/__snapshots__/nested-rules/diff/source-ltr-process-rule-names-true.snapshot +++ b/tests/__snapshots__/nested-rules/diff/source-ltr-process-rule-names-true.snapshot @@ -70,6 +70,19 @@ exports[`[[Mode: diff]] Nested rules tests: {source: ltr} processRuleNames: tru } .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/diff/source-ltr.snapshot b/tests/__snapshots__/nested-rules/diff/source-ltr.snapshot index 856443ba..78148caa 100644 --- a/tests/__snapshots__/nested-rules/diff/source-ltr.snapshot +++ b/tests/__snapshots__/nested-rules/diff/source-ltr.snapshot @@ -70,6 +70,19 @@ exports[`[[Mode: diff]] Nested rules tests: {source: ltr} 1`] = ` } .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/diff/source-rtl-process-rule-names-true.snapshot b/tests/__snapshots__/nested-rules/diff/source-rtl-process-rule-names-true.snapshot index f56f4802..d6a3d90b 100644 --- a/tests/__snapshots__/nested-rules/diff/source-rtl-process-rule-names-true.snapshot +++ b/tests/__snapshots__/nested-rules/diff/source-rtl-process-rule-names-true.snapshot @@ -70,6 +70,19 @@ exports[`[[Mode: diff]] Nested rules tests: {source: rtl} processRuleNames: tru } .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/diff/source-rtl.snapshot b/tests/__snapshots__/nested-rules/diff/source-rtl.snapshot index 51432798..2f957705 100644 --- a/tests/__snapshots__/nested-rules/diff/source-rtl.snapshot +++ b/tests/__snapshots__/nested-rules/diff/source-rtl.snapshot @@ -70,6 +70,19 @@ exports[`[[Mode: diff]] Nested rules tests: {source: rtl} 1`] = ` } .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/override/source-ltr-process-rule-names-true.snapshot b/tests/__snapshots__/nested-rules/override/source-ltr-process-rule-names-true.snapshot index 6966bcba..7ed04293 100644 --- a/tests/__snapshots__/nested-rules/override/source-ltr-process-rule-names-true.snapshot +++ b/tests/__snapshots__/nested-rules/override/source-ltr-process-rule-names-true.snapshot @@ -140,8 +140,20 @@ exports[`[[Mode: override]] Nested rules tests: {source: ltr} processRuleNames: .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + padding: 10px 5px 20px 2px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; + left: 10px; } } @@ -159,6 +171,19 @@ exports[`[[Mode: override]] Nested rules tests: {source: ltr} processRuleNames: } [dir="rtl"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/override/source-ltr.snapshot b/tests/__snapshots__/nested-rules/override/source-ltr.snapshot index c9691393..f8202bcd 100644 --- a/tests/__snapshots__/nested-rules/override/source-ltr.snapshot +++ b/tests/__snapshots__/nested-rules/override/source-ltr.snapshot @@ -140,8 +140,20 @@ exports[`[[Mode: override]] Nested rules tests: {source: ltr} 1`] = ` .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + padding: 10px 5px 20px 2px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; + left: 10px; } } @@ -159,6 +171,19 @@ exports[`[[Mode: override]] Nested rules tests: {source: ltr} 1`] = ` } [dir="rtl"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/override/source-rtl-process-rule-names-true.snapshot b/tests/__snapshots__/nested-rules/override/source-rtl-process-rule-names-true.snapshot index e5b1e482..eff9b81b 100644 --- a/tests/__snapshots__/nested-rules/override/source-rtl-process-rule-names-true.snapshot +++ b/tests/__snapshots__/nested-rules/override/source-rtl-process-rule-names-true.snapshot @@ -140,8 +140,20 @@ exports[`[[Mode: override]] Nested rules tests: {source: rtl} processRuleNames: .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + padding: 10px 5px 20px 2px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; + left: 10px; } } @@ -159,6 +171,19 @@ exports[`[[Mode: override]] Nested rules tests: {source: rtl} processRuleNames: } [dir="ltr"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/__snapshots__/nested-rules/override/source-rtl.snapshot b/tests/__snapshots__/nested-rules/override/source-rtl.snapshot index 71e25ffc..1dcebaa7 100644 --- a/tests/__snapshots__/nested-rules/override/source-rtl.snapshot +++ b/tests/__snapshots__/nested-rules/override/source-rtl.snapshot @@ -140,8 +140,20 @@ exports[`[[Mode: override]] Nested rules tests: {source: rtl} 1`] = ` .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + padding: 10px 5px 20px 2px; + } + } + @media screen and (min-width: 800px) { + background: none; color: red; + left: 10px; } } @@ -159,6 +171,19 @@ exports[`[[Mode: override]] Nested rules tests: {source: rtl} 1`] = ` } [dir="ltr"] .test11 { + .test12 { + @media (orientation: landscape) { + @media (min-width: 1024px) { + padding: 10px 2px 20px 5px; + } + } + + @media screen and (min-width: 800px) { + left: auto; + right: 10px; + } + } + .test13 { text-align: left; } diff --git a/tests/css/input-nested.scss b/tests/css/input-nested.scss index 10d24d70..c53b79c7 100644 --- a/tests/css/input-nested.scss +++ b/tests/css/input-nested.scss @@ -68,8 +68,18 @@ .test11 { .test12 { + @media (orientation: landscape) { + grid-auto-flow: column; + @media (min-width: 1024px) { + position: relative; + max-inline-size: 1024px; + padding: 10px 5px 20px 2px; + } + } @media screen and (min-width: 800px) { + background: none; color: red; + left: 10px; } } .test13 {