diff --git a/src/index.ts b/src/index.ts index 25fa835a..25fd1a7a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,13 +8,13 @@ export { PluginOptions, Mode, Source, PluginStringMap, Autorename } from '@types const transformer = (options: PluginOptions = {}): Transformer => ( (css: Root): void => { - initStore(options); + initStore(options); parseKeyFrames(css); parseAtRules(css); parseRules(css); appendRules(); appendKeyFrames(); - appendAutorenameRules(); + appendAutorenameRules(); } ); diff --git a/src/parsers/atrules.ts b/src/parsers/atrules.ts index f4c1160e..a65be39e 100644 --- a/src/parsers/atrules.ts +++ b/src/parsers/atrules.ts @@ -1,10 +1,11 @@ -import postcss, { Root, Node, Rule, AtRule, vendor } from 'postcss'; +import postcss, { Root, Node, AtRule, Comment, vendor } from 'postcss'; import rtlcss from 'rtlcss'; -import { AtRulesObject, AtRulesStringMap, Source } from '@types'; -import { AT_RULE_TYPE, RULE_TYPE, KEYFRAMES_NAME } from '@constants'; +import { AtRulesObject, AtRulesStringMap, Source, ControlDirective, ObjectWithProps } from '@types'; +import { AT_RULE_TYPE, RULE_TYPE, KEYFRAMES_NAME, CONTROL_DIRECTIVE } from '@constants'; import { store, initKeyframesData } from '@data/store'; import { walkContainer } from '@utilities/containers'; -import { parseDeclarations } from './declarations'; +import { isIgnoreDirectiveInsideAnIgnoreBlock, checkDirective } from '@utilities/directives'; +import { parseRules } from '@parsers/rules'; export const getKeyFramesStringMap = (keyframes: AtRulesObject[]): AtRulesStringMap => { const stringMap: AtRulesStringMap = {}; @@ -21,19 +22,36 @@ export const getKeyFramesRegExp = (stringMap: AtRulesStringMap): RegExp => new R export const parseAtRules = (css: Root): void => { - walkContainer(css, [ AT_RULE_TYPE, RULE_TYPE ], false, (node: Node): void => { + const controlDirectives: ObjectWithProps = {}; + + walkContainer( + css, + [ AT_RULE_TYPE, RULE_TYPE ], + (_comment: Comment, controlDirective: ControlDirective): void => { + + if (isIgnoreDirectiveInsideAnIgnoreBlock(controlDirective, controlDirectives)) { + return; + } + + controlDirectives[controlDirective.directive] = controlDirective; + + }, + (node: Node): void => { + + if ( checkDirective(controlDirectives, CONTROL_DIRECTIVE.IGNORE) ) { + return; + } - if (node.type !== AT_RULE_TYPE) return; + if (node.type !== AT_RULE_TYPE) return; - const atRule = node as AtRule; + const atRule = node as AtRule; - if (vendor.unprefixed(atRule.name) === KEYFRAMES_NAME) return; + if (vendor.unprefixed(atRule.name) === KEYFRAMES_NAME) return; - atRule.walkRules((rule: Rule): void => { - parseDeclarations(rule); - }); + parseRules(atRule); - }); + } + ); }; @@ -45,36 +63,55 @@ export const parseKeyFrames = (css: Root): void => { return; } - walkContainer(css, [ AT_RULE_TYPE, RULE_TYPE ], false, (node: Node): void => { + const controlDirectives: ObjectWithProps = {}; - if (node.type !== AT_RULE_TYPE) return; + walkContainer( + css, + [ AT_RULE_TYPE, RULE_TYPE ], + (_comment: Comment, controlDirective: ControlDirective): void => { - const atRule = node as AtRule; - - if (vendor.unprefixed(atRule.name) !== KEYFRAMES_NAME) return; - - const atRuleString = atRule.toString(); - const atRuleFlippedString = rtlcss.process(atRuleString, { processUrls, useCalc, stringMap }); - - if (atRuleString === atRuleFlippedString) return; + if (isIgnoreDirectiveInsideAnIgnoreBlock(controlDirective, controlDirectives)) { + return; + } + + controlDirectives[controlDirective.directive] = controlDirective; + + }, + (node: Node): void => { + + if ( checkDirective(controlDirectives, CONTROL_DIRECTIVE.IGNORE) ) { + return; + } - const rootFlipped = postcss.parse(atRuleFlippedString); - const atRuleFlipped = rootFlipped.first as AtRule; + if (node.type !== AT_RULE_TYPE) return; - const atRuleParams = atRule.params; - const ltr = `${atRuleParams}-${Source.ltr}`; - const rtl = `${atRuleParams}-${Source.rtl}`; + const atRule = node as AtRule; + + if (vendor.unprefixed(atRule.name) !== KEYFRAMES_NAME) return; + + const atRuleString = atRule.toString(); + const atRuleFlippedString = rtlcss.process(atRuleString, { processUrls, useCalc, stringMap }); + + if (atRuleString === atRuleFlippedString) return; - atRule.params = source === Source.ltr ? ltr : rtl; - atRuleFlipped.params = source === Source.ltr ? rtl : ltr; + const rootFlipped = postcss.parse(atRuleFlippedString); + const atRuleFlipped = rootFlipped.first as AtRule; - store.keyframes.push({ - atRuleParams, - atRule, - atRuleFlipped - }); + const atRuleParams = atRule.params; + const ltr = `${atRuleParams}-${Source.ltr}`; + const rtl = `${atRuleParams}-${Source.rtl}`; + + atRule.params = source === Source.ltr ? ltr : rtl; + atRuleFlipped.params = source === Source.ltr ? rtl : ltr; + + store.keyframes.push({ + atRuleParams, + atRule, + atRuleFlipped + }); - }); + } + ); initKeyframesData(); diff --git a/src/parsers/declarations.ts b/src/parsers/declarations.ts index b8fa37c3..2dae1adb 100644 --- a/src/parsers/declarations.ts +++ b/src/parsers/declarations.ts @@ -1,4 +1,4 @@ -import postcss, { Rule, Node, Declaration, vendor } from 'postcss'; +import postcss, { Rule, Node, Declaration, Comment, vendor } from 'postcss'; import rtlcss from 'rtlcss'; import { Source, Mode, Autorename, ObjectWithProps, ControlDirective } from '@types'; import { @@ -6,14 +6,14 @@ import { FLIP_PROPERTY_REGEXP, ANIMATION_PROP, ANIMATION_NAME_PROP, - CONTROL_DIRECTIVE, - CONTROL_DIRECTIVE_BLOCK + CONTROL_DIRECTIVE } from '@constants'; import { store } from '@data/store'; -import { resetDirective } from '@utilities/directives'; import { addSelectorPrefixes } from '@utilities/selectors'; +import { isIgnoreDirectiveInsideAnIgnoreBlock, checkDirective } from '@utilities/directives'; import { shorthands } from '@utilities/shorthands'; import { walkContainer } from '@utilities/containers'; +import { cleanRuleRawsBefore } from '@utilities/rules'; export const parseDeclarations = (rule: Rule, autorenamed = false): void => { @@ -46,129 +46,142 @@ export const parseDeclarations = (rule: Rule, autorenamed = false): void => { const declarationsProps: string[] = []; let simetricRules = false; + + const controlDirectives: ObjectWithProps = {}; - walkContainer(rule, [ DECLARATION_TYPE ], true, (node: Node, containerDirectives?: ObjectWithProps): void => { - - let processUrlDirective = false; - const RENAME = containerDirectives[CONTROL_DIRECTIVE.RENAME]; - - if (RENAME && RENAME.directive) { - const { block } = RENAME; - resetDirective(RENAME); - if (block !== CONTROL_DIRECTIVE_BLOCK.END) { - processUrlDirective = true; + walkContainer( + rule, + [ DECLARATION_TYPE ], + (comment: Comment, controlDirective: ControlDirective) => { + + cleanRuleRawsBefore(comment.next()); + comment.remove(); + + if (isIgnoreDirectiveInsideAnIgnoreBlock(controlDirective, controlDirectives)) { + return; } - } - const decl = node as Declaration; - const declString = `${decl.toString()};`; - const declFlippedString = rtlcss.process(declString, { - processUrls: processUrls || processUrlDirective, - useCalc, - stringMap, - autoRename: autoRename !== Autorename.disabled, - autoRenameStrict: autoRename === Autorename.strict, - greedy - }); + controlDirectives[controlDirective.directive] = controlDirective; - const root = postcss.parse(declFlippedString); - const declFlipped = root.first as Declaration; - declFlipped.raws = decl.raws; - - const declProp = decl.prop.trim(); - const declPropUnprefixed = vendor.unprefixed(declProp); - const declValue = decl.value.trim(); - const isAnimation = declPropUnprefixed === ANIMATION_PROP || declPropUnprefixed === ANIMATION_NAME_PROP; - const declFlippedProp = declFlipped.prop.trim(); - const declFlippedValue = declFlipped.value.trim(); - const overridenBy = shorthands[declPropUnprefixed]; - const hasBeenOverriden = overridenBy - ? overridenBy.some((d: string): boolean => declarationsProps.indexOf(d) >= 0) - : false; - - if ( - !hasBeenOverriden && - declProp === declFlippedProp && - declValue === declFlippedValue && - ( - !isAnimation || - ( - isAnimation && - ( - store.keyframes.length === 0 || - !store.keyframesRegExp.test(declValue) - ) - ) - ) - ) { - return; - } - - if (isAnimation) { - - const declValue = decl.value.replace( - store.keyframesRegExp, - (_match: string, before: string, animation: string, after: string): string => - before + store.keyframesStringMap[animation].name + after - ); - - const declValueFlipped = decl.value.replace( - store.keyframesRegExp, - (_match: string, before: string, animation: string, after: string): string => - before + store.keyframesStringMap[animation].nameFlipped + after - ); - - const declCloneFlipped = decl.clone(); - - if (mode === Mode.combined) { - const declClone = decl.clone(); - declClone.value = declValue; - declCloneFlipped.value = declValueFlipped; - ruleFlipped.append(declClone); - ruleFlippedSecond.append(declCloneFlipped); - deleteDeclarations.push(decl); - } else { - const declCloneFlipped = decl.clone(); - decl.value = declValue; - declCloneFlipped.value = declValueFlipped; - ruleFlipped.append(declCloneFlipped); + }, + (node: Node): void => { + + if ( checkDirective(controlDirectives, CONTROL_DIRECTIVE.IGNORE) ) { + return; } - } else { + const processUrlDirective = checkDirective(controlDirectives, CONTROL_DIRECTIVE.RENAME); + const decl = node as Declaration; + const declString = `${decl.toString()};`; + const declFlippedString = rtlcss.process(declString, { + processUrls: processUrls || processUrlDirective, + useCalc, + stringMap, + autoRename: autoRename !== Autorename.disabled, + autoRenameStrict: autoRename === Autorename.strict, + greedy + }); + + const root = postcss.parse(declFlippedString); + const declFlipped = root.first as Declaration; + declFlipped.raws = decl.raws; + + const declProp = decl.prop.trim(); + const declPropUnprefixed = vendor.unprefixed(declProp); + const declValue = decl.value.trim(); + const isAnimation = declPropUnprefixed === ANIMATION_PROP || declPropUnprefixed === ANIMATION_NAME_PROP; + const declFlippedProp = declFlipped.prop.trim(); + const declFlippedValue = declFlipped.value.trim(); + const overridenBy = shorthands[declPropUnprefixed]; + const hasBeenOverriden = overridenBy + ? overridenBy.some((d: string): boolean => declarationsProps.indexOf(d) >= 0) + : false; + if ( - hasBeenOverriden && + !hasBeenOverriden && declProp === declFlippedProp && - declValue === declFlippedValue + declValue === declFlippedValue && + ( + !isAnimation || + ( + isAnimation && + ( + store.keyframes.length === 0 || + !store.keyframesRegExp.test(declValue) + ) + ) + ) ) { - const declClone = decl.clone(); - ruleBoth.append(declClone); - deleteDeclarations.push(decl); - return; - } else if (declarationHashMap[declFlipped.prop] === declFlippedValue) { - simetricRules = true; return; } + + if (isAnimation) { + + const declValue = decl.value.replace( + store.keyframesRegExp, + (_match: string, before: string, animation: string, after: string): string => + before + store.keyframesStringMap[animation].name + after + ); + + const declValueFlipped = decl.value.replace( + store.keyframesRegExp, + (_match: string, before: string, animation: string, after: string): string => + before + store.keyframesStringMap[animation].nameFlipped + after + ); + + const declCloneFlipped = decl.clone(); + + if (mode === Mode.combined) { + const declClone = decl.clone(); + declClone.value = declValue; + declCloneFlipped.value = declValueFlipped; + ruleFlipped.append(declClone); + ruleFlippedSecond.append(declCloneFlipped); + deleteDeclarations.push(decl); + } else { + const declCloneFlipped = decl.clone(); + decl.value = declValue; + declCloneFlipped.value = declValueFlipped; + ruleFlipped.append(declCloneFlipped); + } - if (mode === Mode.combined) { - const declClone = decl.clone(); - ruleFlipped.append(declClone); - ruleFlippedSecond.append(declFlipped); - deleteDeclarations.push(decl); } else { - if (FLIP_PROPERTY_REGEXP.test(decl.prop) && !declarationHashMap[declFlipped.prop]) { + + if ( + hasBeenOverriden && + declProp === declFlippedProp && + declValue === declFlippedValue + ) { + const declClone = decl.clone(); + ruleBoth.append(declClone); + deleteDeclarations.push(decl); + return; + } else if (declarationHashMap[declFlipped.prop] === declFlippedValue) { + simetricRules = true; + return; + } + + if (mode === Mode.combined) { const declClone = decl.clone(); - declClone.value = 'unset'; ruleFlipped.append(declClone); + ruleFlippedSecond.append(declFlipped); + deleteDeclarations.push(decl); + } else { + if (FLIP_PROPERTY_REGEXP.test(decl.prop) && !declarationHashMap[declFlipped.prop]) { + const declClone = decl.clone(); + declClone.value = 'unset'; + ruleFlipped.append(declClone); + } + ruleFlipped.append(declFlipped); } - ruleFlipped.append(declFlipped); - } - declarationsProps.push(declPropUnprefixed); + declarationsProps.push(declPropUnprefixed); - } + } - }); + } + ); if (deleteDeclarations.length) { deleteDeclarations.forEach((decl: Declaration): Declaration => decl.remove()); diff --git a/src/parsers/rules.ts b/src/parsers/rules.ts index 17cc769f..5eb198b7 100644 --- a/src/parsers/rules.ts +++ b/src/parsers/rules.ts @@ -1,32 +1,47 @@ -import { Root, Node, Rule } from 'postcss'; +import { Container, Node, Rule, Comment } from 'postcss'; import { ObjectWithProps, ControlDirective } from '@types'; +import { RULE_TYPE, CONTROL_DIRECTIVE } from '@constants'; import { store } from '@data/store'; -import { RULE_TYPE, CONTROL_DIRECTIVE, CONTROL_DIRECTIVE_BLOCK } from '@constants'; -import { resetDirective } from '@utilities/directives'; +import { isIgnoreDirectiveInsideAnIgnoreBlock, checkDirective } from '@utilities/directives'; import { walkContainer } from '@utilities/containers'; +import { cleanRuleRawsBefore } from '@utilities/rules'; import { parseDeclarations } from './declarations'; -export const parseRules = (css: Root): void => { +export const parseRules = (container: Container): void => { - walkContainer(css, [ RULE_TYPE ], true, (node: Node, containerDirectives?: ObjectWithProps): void => { - - const rule = node as Rule; + const controlDirectives: ObjectWithProps = {}; + + walkContainer( + container, + [ RULE_TYPE ], + (comment: Comment, controlDirective: ControlDirective): void => { + + cleanRuleRawsBefore(comment.next()); + comment.remove(); + + if (isIgnoreDirectiveInsideAnIgnoreBlock(controlDirective, controlDirectives)) { + return; + } + + controlDirectives[controlDirective.directive] = controlDirective; - const RENAME = containerDirectives[CONTROL_DIRECTIVE.RENAME]; + }, + (node: Node): void => { - if (RENAME && RENAME.directive) { - const { block } = RENAME; - resetDirective(RENAME); - if (block !== CONTROL_DIRECTIVE_BLOCK.END) { + if ( checkDirective(controlDirectives, CONTROL_DIRECTIVE.IGNORE) ) { + return; + } + + const rule = node as Rule; + + if (checkDirective(controlDirectives, CONTROL_DIRECTIVE.RENAME)) { store.rulesAutoRename.push(rule); parseDeclarations(rule, true); } else { parseDeclarations(rule); - } - } else { - parseDeclarations(rule); - } + } - }); + } + ); }; \ No newline at end of file diff --git a/src/utilities/containers.ts b/src/utilities/containers.ts index d7034fcc..4d2797b7 100644 --- a/src/utilities/containers.ts +++ b/src/utilities/containers.ts @@ -1,22 +1,18 @@ import { Container, Node, Comment } from 'postcss'; -import { ControlDirective, ObjectWithProps } from '@types'; -import { COMMENT_TYPE, CONTROL_DIRECTIVE, CONTROL_DIRECTIVE_BLOCK } from '@constants'; -import { getControlDirective, resetDirective } from '@utilities/directives'; -import { cleanRuleRawsBefore } from '@utilities/rules'; +import { ControlDirective } from '@types'; +import { COMMENT_TYPE } from '@constants'; +import { getControlDirective } from '@utilities/directives'; -type WalkContainerCallback = (node: Node, containerDirectives?: ObjectWithProps) => void; +type WalkContainerControlDirectiveCallback = (comment: Comment, controlDirective: ControlDirective) => void; +type WalkContainerNodeCallback = (node: Node) => void; export const walkContainer = ( container: Container, filter: string [], - removeComments: boolean, - callback: WalkContainerCallback + directiveCallback: WalkContainerControlDirectiveCallback, + nodeCallback: WalkContainerNodeCallback ): void => { - let controlDirective: ControlDirective; - - const containerDirectives: ObjectWithProps = {}; - container.each((node: Node): undefined | false => { if ( node.type !== COMMENT_TYPE && !filter.includes(node.type) ) return; @@ -24,36 +20,16 @@ export const walkContainer = ( if (node.type === COMMENT_TYPE) { const comment = node as Comment; - controlDirective = getControlDirective(comment); + const controlDirective = getControlDirective(comment); if (controlDirective) { - - if (removeComments) { - cleanRuleRawsBefore(comment.next()); - comment.remove(); - } - - containerDirectives[controlDirective.directive] = { ...controlDirective }; - - controlDirective = null; - - return; + directiveCallback(comment, controlDirective); } } else { - const IGNORE = containerDirectives[CONTROL_DIRECTIVE.IGNORE]; - - if (IGNORE && IGNORE.directive) { - const { block } = IGNORE; - resetDirective(IGNORE); - if (block !== CONTROL_DIRECTIVE_BLOCK.END) { - return; - } - } - - callback(node, containerDirectives); - + nodeCallback(node); + } }); diff --git a/src/utilities/directives.ts b/src/utilities/directives.ts index 9440f4fa..f7b2fe40 100644 --- a/src/utilities/directives.ts +++ b/src/utilities/directives.ts @@ -1,5 +1,5 @@ import { Comment } from 'postcss'; -import { ControlDirective } from '@types'; +import { ObjectWithProps, ControlDirective } from '@types'; import { RTL_CONTROL_DIRECTIVE_REG_EXP, CONTROL_DIRECTIVE, CONTROL_DIRECTIVE_BLOCK } from '@constants'; const CONTROL_DIRECTIVE_VALUES = Object.values(CONTROL_DIRECTIVE) as string[]; @@ -7,10 +7,10 @@ const CONTROL_DIRECTIVE_BLOCK_VALUES = Object.values(CONTROL_DIRECTIVE_BLOCK) as export const isValidMatchDirective = (match: (string | number | undefined)[]): boolean => CONTROL_DIRECTIVE_VALUES.includes(`${match[2]}`) && - ( - match[1] === undefined || - CONTROL_DIRECTIVE_BLOCK_VALUES.includes(`${match[1]}`) - ); + ( + match[1] === undefined || + CONTROL_DIRECTIVE_BLOCK_VALUES.includes(`${match[1]}`) + ); export const getControlDirective = (comment: Comment): ControlDirective | null => { const commentStr = comment.toString(); @@ -30,14 +30,34 @@ export const getControlDirective = (comment: Comment): ControlDirective | null = return null; }; -export const resetDirective = (directive: ControlDirective): void => { - if (directive.block === CONTROL_DIRECTIVE_BLOCK.END) { - directive.directive = null; - directive.block = null; - } else { - if (directive.block !== CONTROL_DIRECTIVE_BLOCK.BEGIN) { - directive.directive = null; - directive.block = null; +export const isIgnoreDirectiveInsideAnIgnoreBlock = ( + controlDirective: ControlDirective, + controlDirectives: ObjectWithProps +): boolean => ( + controlDirective.directive === CONTROL_DIRECTIVE.IGNORE && + !controlDirective.block && + controlDirectives[CONTROL_DIRECTIVE.IGNORE] && + controlDirectives[CONTROL_DIRECTIVE.IGNORE].block === CONTROL_DIRECTIVE_BLOCK.BEGIN +); + +export const checkDirective = (controlDirectives: ObjectWithProps, directiveType: string): boolean => { + + const directive = controlDirectives[directiveType]; + + if (directive) { + + const { block } = directive; + + if (block !== CONTROL_DIRECTIVE_BLOCK.BEGIN) { + delete controlDirectives[directiveType]; } + + if (block !== CONTROL_DIRECTIVE_BLOCK.END) { + return true; + } + } + + return false; + }; \ No newline at end of file diff --git a/tests/__snapshots__/combined-autorename.test.ts.snap b/tests/__snapshots__/combined-autorename.test.ts.snap index a7768126..f651666e 100644 --- a/tests/__snapshots__/combined-autorename.test.ts.snap +++ b/tests/__snapshots__/combined-autorename.test.ts.snap @@ -184,6 +184,22 @@ exports[`Combined Tests Autorename Combined Autorename: flexible 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -549,6 +565,22 @@ exports[`Combined Tests Autorename Combined Autorename: flexible with custom str padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -914,6 +946,22 @@ exports[`Combined Tests Autorename Combined Autorename: flexible, greedy: true 1 padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1279,6 +1327,22 @@ exports[`Combined Tests Autorename Combined Autorename: only control directives padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1644,6 +1708,22 @@ exports[`Combined Tests Autorename Combined Autorename: only control directives, padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -2009,6 +2089,22 @@ exports[`Combined Tests Autorename Combined Autorename: strict 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -2374,6 +2470,22 @@ exports[`Combined Tests Autorename Combined Autorename: strict, greedy: true 1`] padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/__snapshots__/combined-basic-options.test.ts.snap b/tests/__snapshots__/combined-basic-options.test.ts.snap index e04ba5d5..86678568 100644 --- a/tests/__snapshots__/combined-basic-options.test.ts.snap +++ b/tests/__snapshots__/combined-basic-options.test.ts.snap @@ -186,6 +186,22 @@ exports[`Combined Tests Basic Options Combined {processKeyFrames: true} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip-ltr { from { transform: translateX(100px); @@ -587,6 +603,22 @@ exports[`Combined Tests Basic Options Combined {processUrls: true} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -954,6 +986,22 @@ exports[`Combined Tests Basic Options Combined {source: rtl, processKeyFrames: t padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: 10px; +} + +[dir=\\"ltr\\"] .test18::after { + right: 10px; +} + @keyframes flip-rtl { from { transform: translateX(100px); @@ -1351,6 +1399,22 @@ exports[`Combined Tests Basic Options Combined {source: rtl} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: 10px; +} + +[dir=\\"ltr\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1718,6 +1782,22 @@ exports[`Combined Tests Basic Options Combined {useCalc: true} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -2083,6 +2163,22 @@ exports[`Combined Tests Basic Options Combined Basic 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/__snapshots__/combined-prefixes.test.ts.snap b/tests/__snapshots__/combined-prefixes.test.ts.snap index f7ce0ff4..fa04e632 100644 --- a/tests/__snapshots__/combined-prefixes.test.ts.snap +++ b/tests/__snapshots__/combined-prefixes.test.ts.snap @@ -184,6 +184,22 @@ exports[`Combined Tests Prefixes Combined custom ltrPrefix and rtlPrefix 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +.ltr .test18::after { + left: 10px; +} + +.rtl .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -559,6 +575,22 @@ exports[`Combined Tests Prefixes Combined custom ltrPrefix and rtlPrefix propert padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +.ltr .test18::after, .left-to-right .test18::after { + left: 10px; +} + +.rtl .test18::after, .right-to-left .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -938,6 +970,22 @@ exports[`Combined Tests Prefixes Combined custom ltrPrefix, rtlPrefix, and bothP padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +.ltr .test18::after, .left-to-right .test18::after { + left: 10px; +} + +.rtl .test18::after, .right-to-left .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/__snapshots__/combined-string-map.test.ts.snap b/tests/__snapshots__/combined-string-map.test.ts.snap index 3f657cf8..2c29e8d1 100644 --- a/tests/__snapshots__/combined-string-map.test.ts.snap +++ b/tests/__snapshots__/combined-string-map.test.ts.snap @@ -188,6 +188,22 @@ exports[`Combined Tests String Map Combined custom no-valid string map and proce padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -557,6 +573,22 @@ exports[`Combined Tests String Map Combined custom no-valid string map and proce padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -926,6 +958,22 @@ exports[`Combined Tests String Map Combined custom string map and processUrls: t padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1295,6 +1343,22 @@ exports[`Combined Tests String Map Combined custom string map without names and padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: 10px; +} + +[dir=\\"rtl\\"] .test18::after { + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/__snapshots__/override-autorename.test.ts.snap b/tests/__snapshots__/override-autorename.test.ts.snap index e3bf89fe..12c4eb6f 100644 --- a/tests/__snapshots__/override-autorename.test.ts.snap +++ b/tests/__snapshots__/override-autorename.test.ts.snap @@ -165,6 +165,20 @@ exports[`Override Tests Autorename Override Autorename: flexible 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -499,6 +513,20 @@ exports[`Override Tests Autorename Override Autorename: flexible with custom str padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -833,6 +861,20 @@ exports[`Override Tests Autorename Override Autorename: flexible, greedy: true 1 padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1167,6 +1209,20 @@ exports[`Override Tests Autorename Override Autorename: only control directives padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1501,6 +1557,20 @@ exports[`Override Tests Autorename Override Autorename: only control directives, padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1835,6 +1905,20 @@ exports[`Override Tests Autorename Override Autorename: strict 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -2169,6 +2253,20 @@ exports[`Override Tests Autorename Override Autorename: strict, greedy: true 1`] padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/__snapshots__/override-basic-options.test.ts.snap b/tests/__snapshots__/override-basic-options.test.ts.snap index 5235d1a6..f19b80a0 100644 --- a/tests/__snapshots__/override-basic-options.test.ts.snap +++ b/tests/__snapshots__/override-basic-options.test.ts.snap @@ -167,6 +167,20 @@ exports[`Override Tests Basic Options Override {processKeyFrames: true} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip-ltr { from { transform: translateX(100px); @@ -531,6 +545,20 @@ exports[`Override Tests Basic Options Override {processUrls: true} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -867,6 +895,20 @@ exports[`Override Tests Basic Options Override {source: rtl, processKeyFrames: t padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip-rtl { from { transform: translateX(100px); @@ -1227,6 +1269,20 @@ exports[`Override Tests Basic Options Override {source: rtl} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"ltr\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1563,6 +1619,20 @@ exports[`Override Tests Basic Options Override {useCalc: true} 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1897,6 +1967,20 @@ exports[`Override Tests Basic Options Override Basic 1`] = ` padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/__snapshots__/override-prefixes.test.ts.snap b/tests/__snapshots__/override-prefixes.test.ts.snap index bfd6eb6c..810e58cf 100644 --- a/tests/__snapshots__/override-prefixes.test.ts.snap +++ b/tests/__snapshots__/override-prefixes.test.ts.snap @@ -165,6 +165,20 @@ exports[`Override Tests Prefixes Override custom ltrPrefix and rtlPrefix propert padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +.rtl .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -504,6 +518,20 @@ exports[`Override Tests Prefixes Override custom ltrPrefix and rtlPrefix propert padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +.rtl .test18::after, .right-to-left .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -847,6 +875,20 @@ exports[`Override Tests Prefixes Override custom ltrPrefix, rtlPrefix, and bothP padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +.rtl .test18::after, .right-to-left .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/__snapshots__/override-string-map.test.ts.snap b/tests/__snapshots__/override-string-map.test.ts.snap index 70feee43..8d306e6d 100644 --- a/tests/__snapshots__/override-string-map.test.ts.snap +++ b/tests/__snapshots__/override-string-map.test.ts.snap @@ -169,6 +169,20 @@ exports[`Override Tests String Map Override custom no-valid string map and proce padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -507,6 +521,20 @@ exports[`Override Tests String Map Override custom no-valid string map and proce padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -845,6 +873,20 @@ exports[`Override Tests String Map Override custom string map and processUrls: t padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); @@ -1183,6 +1225,20 @@ exports[`Override Tests String Map Override custom string map without names and padding: 10px 10px 40px 20px; } +.test18::after { + content: ''; + left: 10px; + text-align: left; + padding-left: 5px; + margin-left: 15px; + transform: translateX(5px); +} + +[dir=\\"rtl\\"] .test18::after { + left: unset; + right: 10px; +} + @keyframes flip { from { transform: translateX(100px); diff --git a/tests/css/input.css b/tests/css/input.css index 4eb25a7f..d6b33091 100644 --- a/tests/css/input.css +++ b/tests/css/input.css @@ -73,6 +73,7 @@ text-align: right; } +/*rtl:ignore*/ .test14 .test15 span { border-left-color: #777; margin: 10px 20px 30px 40px; @@ -108,6 +109,18 @@ padding: 10px 20px 40px 10px; } +.test18::after { + content: ''; + left: 10px; + /*rtl:begin:ignore*/ + text-align: left; + padding-left: 5px; + /*rtl:ignore*/ + margin-left: 15px; + transform: translateX(5px); + /*rtl:end:ignore*/ +} + @keyframes flip { from { transform: translateX(100px);