From 1b013f6b1d9c197f2336b77478157c41a7d047d4 Mon Sep 17 00:00:00 2001 From: Aleen Date: Thu, 9 May 2024 11:38:59 +0800 Subject: [PATCH 1/8] Support specifying processors during processing CSS declarations --- README.md | 57 ++ src/@types/index.ts | 6 + src/data/store.ts | 8 +- src/parsers/declarations.ts | 5 +- .../process-declaration-plugins.snapshot | 616 ++++++++++++++++++ tests/basic-options.test.ts | 21 +- 6 files changed, 708 insertions(+), 5 deletions(-) create mode 100644 tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot diff --git a/README.md b/README.md index 94ca95a9..5bc6a117 100644 --- a/README.md +++ b/README.md @@ -382,6 +382,7 @@ All the options are optional, and a default value will be used if any of them is | stringMap | `PluginStringMap[]` | Check below | An array of strings maps that will be used to make the replacements of the declarations' URLs and to match the names of the rules if `processRuleNames` is `true` | | greedy | `boolean` | `false` | When greedy is `true`, the matches of `stringMap` will not take into account word boundaries | | aliases | `Record` | `{}` | A strings map to treat some declarations as others | +| processDeclarationPlugins | `Array<{name: string, priority: number, processors: PluginProcessor[]}>` | `[]` | Plugins applied when processing CSS declarations | --- @@ -1447,6 +1448,62 @@ const options = { --- +#### processDeclarationPlugins + +
Expand +

+ +Sometimes, we can register some plugins when processing CSS declarations via the `processDeclarationPlugins` options, which is helpful when we need to avoid unexpected flipping situations like `background-position`. + +##### input + +```css +.test { + background-position: 0 100%; +} +``` + +##### Convert `0` to `100%` (default) + +##### output + +```css +.test { + background-position: 100% 100%; +} +``` + +##### Set a plugin to avoid flipping + +```javascript +const options = { + processDeclarationPlugins: [ + { + name: 'avoid-flipping-background', + priority: 99, // above the core RTLCSS plugin which has a priority value of 100 + processors: [{ + expr: /(background|object)(-position(-x)?|-image)?$/i, + action: (prop, value) => ({prop, value})} + ] + } + ] +}; +``` + +##### output + +```css +.test { + background-position: 0 100%; +} +``` + +

+ +
+ +--- + Control Directives --- diff --git a/src/@types/index.ts b/src/@types/index.ts index 4bcc49e0..93a14478 100644 --- a/src/@types/index.ts +++ b/src/@types/index.ts @@ -39,6 +39,11 @@ export interface PluginStringMap { replace: strings; } +export interface PluginProcessor { + expr: RegExp; + action: (prop: string, value: string, context: object) => object; +} + export type PrefixSelectorTransformer = (prefix: string, selector: string) => string | void; export interface PluginOptions { @@ -58,6 +63,7 @@ export interface PluginOptions { stringMap?: PluginStringMap[]; greedy?: boolean; aliases?: Record; + processDeclarationPlugins?: Array<{ name: string, priority: number, processors: PluginProcessor[] }>; } export interface PluginOptionsNormalized extends Omit, 'stringMap' | 'prefixSelectorTransformer'> { diff --git a/src/data/store.ts b/src/data/store.ts index 8d23ee7f..ed7558dd 100644 --- a/src/data/store.ts +++ b/src/data/store.ts @@ -143,7 +143,8 @@ const defaultOptions = (): PluginOptionsNormalized => ({ useCalc: false, stringMap: getRTLCSSStringMap(defaultStringMap), greedy: false, - aliases: {} + aliases: {}, + processDeclarationPlugins: [] }); const store: Store = { @@ -217,7 +218,10 @@ const normalizeOptions = (options: PluginOptions): PluginOptionsNormalized => { if (options.aliases && isObjectWithStringKeys(options.aliases)) { returnOptions.aliases = options.aliases; } - return returnOptions; + return { + ...returnOptions, + processDeclarationPlugins: (options.processDeclarationPlugins || []).map(plugin => ({...plugin, directives: {control: {}, value: []}})) + }; }; const initStore = (options: PluginOptions): void => { diff --git a/src/parsers/declarations.ts b/src/parsers/declarations.ts index 5e5b9b7c..5394a65a 100644 --- a/src/parsers/declarations.ts +++ b/src/parsers/declarations.ts @@ -59,7 +59,8 @@ export const parseDeclarations = ( useCalc, stringMap, greedy, - aliases + aliases, + processDeclarationPlugins } = store.options; const deleteDeclarations: Declaration[] = []; @@ -160,7 +161,7 @@ export const parseDeclarations = ( stringMap, greedy, aliases - }); + }, processDeclarationPlugins); /* the source could be undefined in certain cases but not during the tests */ /* istanbul ignore next */ diff --git a/tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot b/tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot new file mode 100644 index 00000000..05794ce4 --- /dev/null +++ b/tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot @@ -0,0 +1,616 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`[[Mode: combined]] Basic Options Tests: {processDeclarationPlugins} 1`] = ` +".test1, .test2 { + background: url("/folder/subfolder/icons/ltr/chevron-left.png"); + background-color: #FFF; + background-position: 10px 20px; + color: #666; + width: 100%; +} + +[dir="ltr"] .test1, [dir="ltr"] .test2 { + border-radius: 0 2px 0 8px; + padding-right: 20px; + text-align: left; + transform: translate(-50%, 50%); +} + +[dir="rtl"] .test1, [dir="rtl"] .test2 { + border-radius: 2px 0 8px 0; + padding-left: 20px; + text-align: right; + transform: translate(50%, 50%); +} + +.test2 { + color: red; + text-align: left; + text-align: center; +} + +/* Comment not related to rtl */ +.test3 { + margin: 1px 2px 3px; + padding: 10px 20px; + /* Property comment not related to rtl */ + text-align: center; +} + +[dir="ltr"] .test3 { + direction: ltr; +} + +[dir="rtl"] .test3 { + direction: rtl; +} + +.test4 { + font-size: 10px; + border-color: red; + transform-origin: 10px 20px; + transform: scale(0.5, 0.5); +} + +[dir="ltr"] .test4 { + border-radius: 2px 4px 8px 16px; + text-shadow: red 99px -1px 1px, blue 99px 2px 1px; +} + +[dir="rtl"] .test4 { + border-radius: 4px 2px 16px 8px; + text-shadow: red -99px -1px 1px, blue -99px 2px 1px; +} + +.test5, +.test6, +.test7 { + background: linear-gradient(0.25turn, #3F87A6, #EBF8E1, #F69D3C); + border: 1px solid 2px; + box-sizing: border-box; + position: absolute; +} + +[dir="ltr"] .test5, +[dir="ltr"] .test6, +[dir="ltr"] .test7 { + border-color: #666 #777 #888 #999; + border-width: 1px 2px 3px 4px; + left: 100px; + transform: translateX(5px); +} + +[dir="rtl"] .test5, +[dir="rtl"] .test6, +[dir="rtl"] .test7 { + border-color: #666 #999 #888 #777; + border-width: 1px 4px 3px 2px; + right: 100px; + transform: translateX(-5px); +} + +/*rtl:novalid:ignore*/ +.test8 { + background: linear-gradient(to left, #333, #333 50%, #EEE 75%, #333 75%); + display: flex; + padding-left: 10%; +} + +.test9, .test10 { + background: linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%), + linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%), + linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%); + padding: 0px 2px 3px 4px; +} + +[dir="ltr"] .test9, [dir="ltr"] .test10 { + left: 5px; +} + +[dir="rtl"] .test9, [dir="rtl"] .test10 { + right: 5px; +} + +[dir="ltr"] .test11:hover, +[dir="ltr"] .test11:active { + font-family: Arial, Helvetica; + font-size: 20px; + color: '#FFF'; + transform: translateY(10px); + padding: 10px; +} + +[dir="rtl"] .test11:hover, +[dir="rtl"] .test11:active { + font-family: "Droid Arabic Kufi", Arial, Helvetica; + font-size: 30px; + color: #000; + transform: translateY(10px) scaleX(-1); + padding: 10px 20px; +} + +#test12, #test13 { + left: 10px; + position: relative; + text-align: right; +} + +.test14 .test15 span { + border-left-color: #777; + margin: 10px 20px 30px 40px; + transform: translate(100%, 10%); +} + +.test16 { + padding-right: 10px; +} + +[dir="ltr"] .test16:hover { + padding-right: 20px; +} + +[dir="rtl"] .test16:hover { + padding-left: 20px; +} + +.test17 { + cursor: pointer; + padding: 10px 20px 40px 10px; + text-align: right; +} + +@media only screen and (min-device-width: 320px) { + .test17 { + cursor: wait; + } +} + +.test18 { + animation: 5s flip 1s ease-in-out, + 3s my-animation 6s ease-in-out; + font-size: 10px; +} + +[dir="ltr"] .test18 { + padding: 10px 20px 40px 10px; +} + +[dir="rtl"] .test18 { + 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); + } + + to { + transform: translateX(0); + } +} + +@media only screen and (min-device-width: 320px) { + .test18 { + width: 100%; + } + + [dir="ltr"] .test18 { + padding: 1px 2px 3px 4px; + } + + [dir="rtl"] .test18 { + padding: 1px 4px 3px 2px; + } +} + +.test19 { + animation-delay: 1s; + animation-duration: 3s; + animation-name: my-animation; + animation-timing-function: ease-in-out; +} + +.test20 { + animation-delay: 2s; + animation-duration: 4s; + animation-name: my-animation, no-flip; + animation-timing-function: ease; +} + +@keyframes my-animation { + from { + left: 0%; + } + + to { + left: 100%; + } +} + +.test21 { + animation-delay: 1s; + animation-duration: 3s; + animation-name: no-flip; + animation-timing-function: ease-in-out; + width: 100%; +} + +@keyframes no-flip { + from { + color: #000; + } + + to { + color: #FFF; + } +} + +/* Do not add reset values in override mode */ +[dir="ltr"] .test22 { + left: 5px; + right: 10px; +} + +[dir="rtl"] .test22 { + right: 5px; + left: 10px; +} + +/* Do not create the RTL version if the result is the same */ +.test23 { + left: 10px; + right: 10px; +} + +/* Chain override */ +.test24 { + padding: 10px; +} + +[dir="ltr"] .test24 { + border: 1px solid #FFF; +} + +[dir="rtl"] .test24 { + border: 1px solid #000; +} + +[dir] .test24 { + border-bottom-color: #666; +} + +/* Automatic rename */ +.test25-ltr { + box-sizing: border-box; + color: #FFF; + font-size: 10px; + width: 100%; +} + +[dir="ltr"] .test25, [dir="ltr"] .test26-ltr, [dir="ltr"] .test27 { + background-image: url("/icons/icon-l.png") +} + +[dir="rtl"] .test25, [dir="rtl"] .test26-ltr, [dir="rtl"] .test27 { + background-image: url("/icons/icon-r.png") +} + +[dir="ltr"] .test26-rtl { + background-image: url("/icons/icon-r.png") +} + +[dir="rtl"] .test26-rtl { + background-image: url("/icons/icon-l.png") +} + +.test27-prev { + background-image: url("/icons/icon-p.png") +} + +.test27-next { + background-image: url("/icons/icon-n.png") +} + +.test28 { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; +} + +.test28-left::before { + background-image: url("/folder/subfolder/arrow-left.png"); +} + +.test28-right::before { + background-image: url("/folder/subfolder/arrow-right.png"); +} + +.testleft29 { + border: 1px solid gray; +} + +.testleft30 { + background: url("/folder/subfolder/icon-ltr.png"); +} + +.testright30 { + background: url("/folder/subfolder/icon-rtl.png"); +} + +.test31 { + background-image: url("/icons/icon-left.png"); + border: 1px solid gray; +} + +.test32 { + align-items: center; + background-image: url("/icons/icon-left.png"); + background-repeat: no-repeat; + border: 1px solid gray; +} + +.test33 { + color: #EFEFEF; +} + +[dir="ltr"] .test33 { + left: 10px; +} + +[dir="rtl"] .test33 { + right: 10px; + height: 50px; + width: 100px; +} + +[dir="rtl"] .example34 { + color: #EFEFEF; + left: 10px; + width: 100%; +} + +[dir="rtl"] .example35 { + transform: translate(10px, 20px); +} + +.test36 { + color: #FFF; + width: 100%; +} + +[dir="ltr"] .test36 { + border-right: 1px solid #666; + padding: 10px 20px 10px 5px; + text-align: right; +} + +[dir="rtl"] .test36 { + border-left: 1px solid #666; + padding: 10px 5px 10px 20px; + text-align: left; +} + +.test37 { + color: #FFF; + width: 100%; +} + +[dir="ltr"] .test37 { + border-left: 1px solid #666; + padding: 10px 5px 10px 20px; + text-align: right; +} + +[dir="rtl"] .test37 { + border-right: 1px solid #666; + padding: 10px 20px 10px 5px; + text-align: left; +} + +.test38 { + color: #FFF; + width: 100%; +} + +[dir="ltr"] .test38 { + border-left: 1px solid #666; + padding: 10px 20px 10px 5px; + text-align: right; +} + +[dir="rtl"] .test38 { + border-right: 1px solid #666; + padding: 10px 5px 10px 20px; + text-align: left; +} + +.test39 { + width: 50%; +} + +[dir="ltr"] .test39 { + margin-right: 10px; +} + +[dir="rtl"] .test39 { + margin-left: 10px; +} + +.test40 { + color: transparent; + padding: 10px; +} + +[dir="ltr"] .test40 { + right: 5px; +} + +[dir="rtl"] .test40 { + left: 5px; +} + +.test41 { + color: #EFEFEF; +} + +[dir="ltr"] .test41 { + right: 10px; + height: 50px; + width: 100px; +} + +[dir="rtl"] .test41 { + left: 10px; +} + +[dir="ltr"] .test42 { + color: #EFEFEF; + left: 10px; + width: 100%; +} + +[dir="ltr"] .test43 { + transform: translate(10px, 20px); +} + +@keyframes normalFlip { + from { + left: 0px; + top: 0px; + } + + to { + left: 100px; + top: -100px; + } +} + +.test44 { + animation: 5s normalFlip 1s ease-in-out; +} + +@keyframes inversedFlip { + from { + left: 0px; + top: 0px; + } + + to { + left: 100px; + top: -100px; + } +} + +.test45 { + animation: 5s inversedFlip 1s ease-in-out; +} + +@media only screen and (min-device-width: 320px) { + .test46 { + cursor: wait; + } + + [dir="ltr"] .test46 { + text-align: left; + } + + [dir="rtl"] .test46 { + text-align: right; + } + + .test47 { + color: white; + } + + .test47left { + content: "\\f007"; + } + + .test47right { + content: "\\f010"; + } +} + +@media only screen and (min-device-width: 320px) { + .test48 { + cursor: wait; + } + + [dir="ltr"] .test48 { + text-align: right; + } + + [dir="rtl"] .test48 { + text-align: left; + } + + .test49 { + color: white; + } +} + +[dir="ltr"]:root { + text-align: right; +} + +[dir="rtl"]:root { + text-align: left; +} + +html .test50 { + color: red; +} + +html[dir="ltr"] .test50 { + left: 10px; +} + +html[dir="rtl"] .test50 { + right: 10px; +} + +[dir="ltr"] .test51 { + border-left: 1px solid #FFF; +} + +[dir="rtl"] .test51 { + border-right: 1px solid #FFF; +} + +[dir] .test51 { + border: none; +} + +.test52 { + color: red; + padding-block: 1px 2px; +} + +.test53 { + margin-block-start: 10px; + margin-block-end: 5px; +}" +`; diff --git a/tests/basic-options.test.ts b/tests/basic-options.test.ts index d5f353dc..0af0edf4 100644 --- a/tests/basic-options.test.ts +++ b/tests/basic-options.test.ts @@ -73,7 +73,26 @@ runTests({}, (pluginOptions: PluginOptions): void => { ); expect(output.warnings()).toHaveLength(0); }); - + + it('{processDeclarationPlugins}', (): void => { + const options: PluginOptions = { + ...pluginOptions, + processDeclarationPlugins: [{ + name: 'avoid-flipping-background', + priority: 99, // above the core RTLCSS plugin which has a priority value of 100 + processors: [{ + expr: /(background|object)(-position(-x)?|-image)?$/i, + action: (prop: string, value: string) => ({prop, value}) + }] + }] + }; + const output = postcss([postcssRTLCSS(options)]).process(input); + expect(output.css).toMatchSpecificSnapshot( + createSnapshotFileName(BASE_NAME,'process-declaration-plugins', pluginOptions.mode) + ); + expect(output.warnings()).toHaveLength(0); + }) + }); }); \ No newline at end of file From 3037e0b2ee3db0091cab1062a97200bde1a41b5d Mon Sep 17 00:00:00 2001 From: Aleen Date: Mon, 13 May 2024 14:19:05 +0800 Subject: [PATCH 2/8] Validate `options.processDeclarationPlugins` --- README.md | 2 +- src/@types/index.ts | 10 ++++++++-- src/constants/index.ts | 1 + src/data/store.ts | 26 ++++++++++++++++++++++---- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5bc6a117..6cdd914f 100644 --- a/README.md +++ b/README.md @@ -382,7 +382,7 @@ All the options are optional, and a default value will be used if any of them is | stringMap | `PluginStringMap[]` | Check below | An array of strings maps that will be used to make the replacements of the declarations' URLs and to match the names of the rules if `processRuleNames` is `true` | | greedy | `boolean` | `false` | When greedy is `true`, the matches of `stringMap` will not take into account word boundaries | | aliases | `Record` | `{}` | A strings map to treat some declarations as others | -| processDeclarationPlugins | `Array<{name: string, priority: number, processors: PluginProcessor[]}>` | `[]` | Plugins applied when processing CSS declarations | +| processDeclarationPlugins | `DeclarationPlugin[]` | `[]` | Plugins applied when processing CSS declarations | --- diff --git a/src/@types/index.ts b/src/@types/index.ts index 93a14478..07d66f8d 100644 --- a/src/@types/index.ts +++ b/src/@types/index.ts @@ -39,11 +39,17 @@ export interface PluginStringMap { replace: strings; } -export interface PluginProcessor { +export interface DeclarationPluginProcessor { expr: RegExp; action: (prop: string, value: string, context: object) => object; } +export type DeclarationPlugin = { + name: string; + priority: number; + processors: DeclarationPluginProcessor[]; +} + export type PrefixSelectorTransformer = (prefix: string, selector: string) => string | void; export interface PluginOptions { @@ -63,7 +69,7 @@ export interface PluginOptions { stringMap?: PluginStringMap[]; greedy?: boolean; aliases?: Record; - processDeclarationPlugins?: Array<{ name: string, priority: number, processors: PluginProcessor[] }>; + processDeclarationPlugins?: DeclarationPlugin[]; } export interface PluginOptionsNormalized extends Omit, 'stringMap' | 'prefixSelectorTransformer'> { diff --git a/src/constants/index.ts b/src/constants/index.ts index db354487..4222254b 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -3,6 +3,7 @@ export const DECLARATION_TYPE = 'decl'; export const RULE_TYPE = 'rule'; export const AT_RULE_TYPE = 'atrule'; export const STRING_TYPE = 'string'; +export const NUMBER_TYPE = 'number'; export const BOOLEAN_TYPE = 'boolean'; export const FUNCTION_TYPE = 'function'; export const KEYFRAMES_NAME = 'keyframes'; diff --git a/src/data/store.ts b/src/data/store.ts index ed7558dd..46d21137 100644 --- a/src/data/store.ts +++ b/src/data/store.ts @@ -2,6 +2,8 @@ import { Rule, AtRule } from 'postcss'; import { PluginOptions, PluginOptionsNormalized, + DeclarationPlugin, + DeclarationPluginProcessor, AtRulesObject, AtRulesStringMap, RulesObject, @@ -16,6 +18,8 @@ import { } from '@types'; import { BOOLEAN_TYPE, + STRING_TYPE, + NUMBER_TYPE, FUNCTION_TYPE, REG_EXP_CHARACTERS_REG_EXP, LAST_WORD_CHARACTER_REG_EXP @@ -99,6 +103,18 @@ const isNotAcceptedStringMap = (stringMap: PluginStringMap[]): boolean => { ); }; +const isAcceptedProcessDeclarationPlugins = (plugins: DeclarationPlugin[]): boolean => + Array.isArray(plugins) + && plugins.every((plugin: DeclarationPlugin) => + typeof plugin.name == STRING_TYPE + && typeof plugin.priority == NUMBER_TYPE + && Array.isArray(plugin.processors) + && plugin.processors.every((processor: DeclarationPluginProcessor) => + ({}).toString.call(processor.expr) === '[object RegExp]' + && typeof processor.action === FUNCTION_TYPE + ) + ); + const isObjectWithStringKeys = (obj: Record): boolean => !Object.entries(obj).some( (entry: [string, unknown]): boolean => @@ -215,13 +231,15 @@ const normalizeOptions = (options: PluginOptions): PluginOptionsNormalized => { } }); } + if (isAcceptedProcessDeclarationPlugins(options.processDeclarationPlugins)) { + returnOptions.processDeclarationPlugins = options.processDeclarationPlugins.map(plugin => ({ + ...plugin, directives: {control: {}, value: []}, + })); + } if (options.aliases && isObjectWithStringKeys(options.aliases)) { returnOptions.aliases = options.aliases; } - return { - ...returnOptions, - processDeclarationPlugins: (options.processDeclarationPlugins || []).map(plugin => ({...plugin, directives: {control: {}, value: []}})) - }; + return returnOptions; }; const initStore = (options: PluginOptions): void => { From 81834d3cf61ebb3eb994dabaa4366da052e523f7 Mon Sep 17 00:00:00 2001 From: Aleen Date: Mon, 13 May 2024 14:30:59 +0800 Subject: [PATCH 3/8] Declare `RTLCSSPlugin` and rename the property of `PluginOptionsNormalized` --- src/@types/index.ts | 12 +++++++++++- src/data/store.ts | 4 ++-- src/parsers/declarations.ts | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/@types/index.ts b/src/@types/index.ts index 07d66f8d..cde967af 100644 --- a/src/@types/index.ts +++ b/src/@types/index.ts @@ -39,6 +39,15 @@ export interface PluginStringMap { replace: strings; } +export type RTLCSSPlugin = { + name: string; + priority: number; + directives: { + control: Object, + value: Array + }; +} + export interface DeclarationPluginProcessor { expr: RegExp; action: (prop: string, value: string, context: object) => object; @@ -72,8 +81,9 @@ export interface PluginOptions { processDeclarationPlugins?: DeclarationPlugin[]; } -export interface PluginOptionsNormalized extends Omit, 'stringMap' | 'prefixSelectorTransformer'> { +export interface PluginOptionsNormalized extends Omit, 'stringMap' | 'processDeclarationPlugins' | 'prefixSelectorTransformer'> { stringMap: StringMap[]; + plugins: RTLCSSPlugin[]; prefixSelectorTransformer: PrefixSelectorTransformer | null; } diff --git a/src/data/store.ts b/src/data/store.ts index 46d21137..0daba513 100644 --- a/src/data/store.ts +++ b/src/data/store.ts @@ -160,7 +160,7 @@ const defaultOptions = (): PluginOptionsNormalized => ({ stringMap: getRTLCSSStringMap(defaultStringMap), greedy: false, aliases: {}, - processDeclarationPlugins: [] + plugins: [] }); const store: Store = { @@ -232,7 +232,7 @@ const normalizeOptions = (options: PluginOptions): PluginOptionsNormalized => { }); } if (isAcceptedProcessDeclarationPlugins(options.processDeclarationPlugins)) { - returnOptions.processDeclarationPlugins = options.processDeclarationPlugins.map(plugin => ({ + returnOptions.plugins = options.processDeclarationPlugins.map(plugin => ({ ...plugin, directives: {control: {}, value: []}, })); } diff --git a/src/parsers/declarations.ts b/src/parsers/declarations.ts index 5394a65a..eba89b05 100644 --- a/src/parsers/declarations.ts +++ b/src/parsers/declarations.ts @@ -60,7 +60,7 @@ export const parseDeclarations = ( stringMap, greedy, aliases, - processDeclarationPlugins + plugins } = store.options; const deleteDeclarations: Declaration[] = []; @@ -161,7 +161,7 @@ export const parseDeclarations = ( stringMap, greedy, aliases - }, processDeclarationPlugins); + }, plugins); /* the source could be undefined in certain cases but not during the tests */ /* istanbul ignore next */ From fdc721a3a612647295fc700ecc42f108fb80aba8 Mon Sep 17 00:00:00 2001 From: Aleen Date: Mon, 13 May 2024 15:18:57 +0800 Subject: [PATCH 4/8] Add more test cases --- .../process-declaration-plugins.snapshot | 616 ------------------ .../combined/flip.snapshot | 174 +++++ .../combined/noflip.snapshot | 130 ++++ .../diff/flip.snapshot | 37 ++ .../diff/noflip.snapshot | 3 + .../override/flip.snapshot | 162 +++++ .../override/noflip.snapshot | 130 ++++ tests/basic-options.test.ts | 21 +- .../css/input-process-declaration-plugins.css | 122 ++++ tests/process-declaration-plugins.test.ts | 52 ++ 10 files changed, 811 insertions(+), 636 deletions(-) delete mode 100644 tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot create mode 100644 tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot create mode 100644 tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot create mode 100644 tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot create mode 100644 tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot create mode 100644 tests/__snapshots__/process-declaration-plugins/override/flip.snapshot create mode 100644 tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot create mode 100644 tests/css/input-process-declaration-plugins.css create mode 100644 tests/process-declaration-plugins.test.ts diff --git a/tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot b/tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot deleted file mode 100644 index 05794ce4..00000000 --- a/tests/__snapshots__/basic-options/combined/process-declaration-plugins.snapshot +++ /dev/null @@ -1,616 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`[[Mode: combined]] Basic Options Tests: {processDeclarationPlugins} 1`] = ` -".test1, .test2 { - background: url("/folder/subfolder/icons/ltr/chevron-left.png"); - background-color: #FFF; - background-position: 10px 20px; - color: #666; - width: 100%; -} - -[dir="ltr"] .test1, [dir="ltr"] .test2 { - border-radius: 0 2px 0 8px; - padding-right: 20px; - text-align: left; - transform: translate(-50%, 50%); -} - -[dir="rtl"] .test1, [dir="rtl"] .test2 { - border-radius: 2px 0 8px 0; - padding-left: 20px; - text-align: right; - transform: translate(50%, 50%); -} - -.test2 { - color: red; - text-align: left; - text-align: center; -} - -/* Comment not related to rtl */ -.test3 { - margin: 1px 2px 3px; - padding: 10px 20px; - /* Property comment not related to rtl */ - text-align: center; -} - -[dir="ltr"] .test3 { - direction: ltr; -} - -[dir="rtl"] .test3 { - direction: rtl; -} - -.test4 { - font-size: 10px; - border-color: red; - transform-origin: 10px 20px; - transform: scale(0.5, 0.5); -} - -[dir="ltr"] .test4 { - border-radius: 2px 4px 8px 16px; - text-shadow: red 99px -1px 1px, blue 99px 2px 1px; -} - -[dir="rtl"] .test4 { - border-radius: 4px 2px 16px 8px; - text-shadow: red -99px -1px 1px, blue -99px 2px 1px; -} - -.test5, -.test6, -.test7 { - background: linear-gradient(0.25turn, #3F87A6, #EBF8E1, #F69D3C); - border: 1px solid 2px; - box-sizing: border-box; - position: absolute; -} - -[dir="ltr"] .test5, -[dir="ltr"] .test6, -[dir="ltr"] .test7 { - border-color: #666 #777 #888 #999; - border-width: 1px 2px 3px 4px; - left: 100px; - transform: translateX(5px); -} - -[dir="rtl"] .test5, -[dir="rtl"] .test6, -[dir="rtl"] .test7 { - border-color: #666 #999 #888 #777; - border-width: 1px 4px 3px 2px; - right: 100px; - transform: translateX(-5px); -} - -/*rtl:novalid:ignore*/ -.test8 { - background: linear-gradient(to left, #333, #333 50%, #EEE 75%, #333 75%); - display: flex; - padding-left: 10%; -} - -.test9, .test10 { - background: linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%), - linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%), - linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%); - padding: 0px 2px 3px 4px; -} - -[dir="ltr"] .test9, [dir="ltr"] .test10 { - left: 5px; -} - -[dir="rtl"] .test9, [dir="rtl"] .test10 { - right: 5px; -} - -[dir="ltr"] .test11:hover, -[dir="ltr"] .test11:active { - font-family: Arial, Helvetica; - font-size: 20px; - color: '#FFF'; - transform: translateY(10px); - padding: 10px; -} - -[dir="rtl"] .test11:hover, -[dir="rtl"] .test11:active { - font-family: "Droid Arabic Kufi", Arial, Helvetica; - font-size: 30px; - color: #000; - transform: translateY(10px) scaleX(-1); - padding: 10px 20px; -} - -#test12, #test13 { - left: 10px; - position: relative; - text-align: right; -} - -.test14 .test15 span { - border-left-color: #777; - margin: 10px 20px 30px 40px; - transform: translate(100%, 10%); -} - -.test16 { - padding-right: 10px; -} - -[dir="ltr"] .test16:hover { - padding-right: 20px; -} - -[dir="rtl"] .test16:hover { - padding-left: 20px; -} - -.test17 { - cursor: pointer; - padding: 10px 20px 40px 10px; - text-align: right; -} - -@media only screen and (min-device-width: 320px) { - .test17 { - cursor: wait; - } -} - -.test18 { - animation: 5s flip 1s ease-in-out, - 3s my-animation 6s ease-in-out; - font-size: 10px; -} - -[dir="ltr"] .test18 { - padding: 10px 20px 40px 10px; -} - -[dir="rtl"] .test18 { - 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); - } - - to { - transform: translateX(0); - } -} - -@media only screen and (min-device-width: 320px) { - .test18 { - width: 100%; - } - - [dir="ltr"] .test18 { - padding: 1px 2px 3px 4px; - } - - [dir="rtl"] .test18 { - padding: 1px 4px 3px 2px; - } -} - -.test19 { - animation-delay: 1s; - animation-duration: 3s; - animation-name: my-animation; - animation-timing-function: ease-in-out; -} - -.test20 { - animation-delay: 2s; - animation-duration: 4s; - animation-name: my-animation, no-flip; - animation-timing-function: ease; -} - -@keyframes my-animation { - from { - left: 0%; - } - - to { - left: 100%; - } -} - -.test21 { - animation-delay: 1s; - animation-duration: 3s; - animation-name: no-flip; - animation-timing-function: ease-in-out; - width: 100%; -} - -@keyframes no-flip { - from { - color: #000; - } - - to { - color: #FFF; - } -} - -/* Do not add reset values in override mode */ -[dir="ltr"] .test22 { - left: 5px; - right: 10px; -} - -[dir="rtl"] .test22 { - right: 5px; - left: 10px; -} - -/* Do not create the RTL version if the result is the same */ -.test23 { - left: 10px; - right: 10px; -} - -/* Chain override */ -.test24 { - padding: 10px; -} - -[dir="ltr"] .test24 { - border: 1px solid #FFF; -} - -[dir="rtl"] .test24 { - border: 1px solid #000; -} - -[dir] .test24 { - border-bottom-color: #666; -} - -/* Automatic rename */ -.test25-ltr { - box-sizing: border-box; - color: #FFF; - font-size: 10px; - width: 100%; -} - -[dir="ltr"] .test25, [dir="ltr"] .test26-ltr, [dir="ltr"] .test27 { - background-image: url("/icons/icon-l.png") -} - -[dir="rtl"] .test25, [dir="rtl"] .test26-ltr, [dir="rtl"] .test27 { - background-image: url("/icons/icon-r.png") -} - -[dir="ltr"] .test26-rtl { - background-image: url("/icons/icon-r.png") -} - -[dir="rtl"] .test26-rtl { - background-image: url("/icons/icon-l.png") -} - -.test27-prev { - background-image: url("/icons/icon-p.png") -} - -.test27-next { - background-image: url("/icons/icon-n.png") -} - -.test28 { - font-family: 'Material Icons'; - font-weight: normal; - font-style: normal; - font-size: 24px; - display: inline-block; - line-height: 1; - text-transform: none; - letter-spacing: normal; - word-wrap: normal; - white-space: nowrap; -} - -.test28-left::before { - background-image: url("/folder/subfolder/arrow-left.png"); -} - -.test28-right::before { - background-image: url("/folder/subfolder/arrow-right.png"); -} - -.testleft29 { - border: 1px solid gray; -} - -.testleft30 { - background: url("/folder/subfolder/icon-ltr.png"); -} - -.testright30 { - background: url("/folder/subfolder/icon-rtl.png"); -} - -.test31 { - background-image: url("/icons/icon-left.png"); - border: 1px solid gray; -} - -.test32 { - align-items: center; - background-image: url("/icons/icon-left.png"); - background-repeat: no-repeat; - border: 1px solid gray; -} - -.test33 { - color: #EFEFEF; -} - -[dir="ltr"] .test33 { - left: 10px; -} - -[dir="rtl"] .test33 { - right: 10px; - height: 50px; - width: 100px; -} - -[dir="rtl"] .example34 { - color: #EFEFEF; - left: 10px; - width: 100%; -} - -[dir="rtl"] .example35 { - transform: translate(10px, 20px); -} - -.test36 { - color: #FFF; - width: 100%; -} - -[dir="ltr"] .test36 { - border-right: 1px solid #666; - padding: 10px 20px 10px 5px; - text-align: right; -} - -[dir="rtl"] .test36 { - border-left: 1px solid #666; - padding: 10px 5px 10px 20px; - text-align: left; -} - -.test37 { - color: #FFF; - width: 100%; -} - -[dir="ltr"] .test37 { - border-left: 1px solid #666; - padding: 10px 5px 10px 20px; - text-align: right; -} - -[dir="rtl"] .test37 { - border-right: 1px solid #666; - padding: 10px 20px 10px 5px; - text-align: left; -} - -.test38 { - color: #FFF; - width: 100%; -} - -[dir="ltr"] .test38 { - border-left: 1px solid #666; - padding: 10px 20px 10px 5px; - text-align: right; -} - -[dir="rtl"] .test38 { - border-right: 1px solid #666; - padding: 10px 5px 10px 20px; - text-align: left; -} - -.test39 { - width: 50%; -} - -[dir="ltr"] .test39 { - margin-right: 10px; -} - -[dir="rtl"] .test39 { - margin-left: 10px; -} - -.test40 { - color: transparent; - padding: 10px; -} - -[dir="ltr"] .test40 { - right: 5px; -} - -[dir="rtl"] .test40 { - left: 5px; -} - -.test41 { - color: #EFEFEF; -} - -[dir="ltr"] .test41 { - right: 10px; - height: 50px; - width: 100px; -} - -[dir="rtl"] .test41 { - left: 10px; -} - -[dir="ltr"] .test42 { - color: #EFEFEF; - left: 10px; - width: 100%; -} - -[dir="ltr"] .test43 { - transform: translate(10px, 20px); -} - -@keyframes normalFlip { - from { - left: 0px; - top: 0px; - } - - to { - left: 100px; - top: -100px; - } -} - -.test44 { - animation: 5s normalFlip 1s ease-in-out; -} - -@keyframes inversedFlip { - from { - left: 0px; - top: 0px; - } - - to { - left: 100px; - top: -100px; - } -} - -.test45 { - animation: 5s inversedFlip 1s ease-in-out; -} - -@media only screen and (min-device-width: 320px) { - .test46 { - cursor: wait; - } - - [dir="ltr"] .test46 { - text-align: left; - } - - [dir="rtl"] .test46 { - text-align: right; - } - - .test47 { - color: white; - } - - .test47left { - content: "\\f007"; - } - - .test47right { - content: "\\f010"; - } -} - -@media only screen and (min-device-width: 320px) { - .test48 { - cursor: wait; - } - - [dir="ltr"] .test48 { - text-align: right; - } - - [dir="rtl"] .test48 { - text-align: left; - } - - .test49 { - color: white; - } -} - -[dir="ltr"]:root { - text-align: right; -} - -[dir="rtl"]:root { - text-align: left; -} - -html .test50 { - color: red; -} - -html[dir="ltr"] .test50 { - left: 10px; -} - -html[dir="rtl"] .test50 { - right: 10px; -} - -[dir="ltr"] .test51 { - border-left: 1px solid #FFF; -} - -[dir="rtl"] .test51 { - border-right: 1px solid #FFF; -} - -[dir] .test51 { - border: none; -} - -.test52 { - color: red; - padding-block: 1px 2px; -} - -.test53 { - margin-block-start: 10px; - margin-block-end: 5px; -}" -`; diff --git a/tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot b/tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot new file mode 100644 index 00000000..b3009ced --- /dev/null +++ b/tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot @@ -0,0 +1,174 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`[[Mode: combined]] Combined Tests: flip background by default 1`] = ` +"[dir="ltr"] .test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +[dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +.test2 { + background-image: url("/icons/icon-left.png"); +} + +[dir="ltr"] .test2 { + background-position: 0 100%; +} + +[dir="rtl"] .test2 { + background-position: 100% 100%; +} + +.test3 { + background-image: url("/icons/icon-left.png"); + background-position-y: 100%; +} + +[dir="ltr"] .test3 { + background-position-x: 0; +} + +[dir="rtl"] .test3 { + background-position-x: 100%; +} + +[dir="ltr"] .test4 { + object-position: 0 100%; +} + +[dir="rtl"] .test4 { + object-position: 100% 100%; +} + +/* inside a nested rule */ +[dir="ltr"] .test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +[dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +[dir="ltr"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +[dir="rtl"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; +} + +[dir="ltr"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +[dir="rtl"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; +} + +[dir="ltr"] .test4 { + object-position: 0 100%; +} + +[dir="rtl"] .test4 { + object-position: 100% 100%; +} + +/* inside a keyframe animation */ +@keyframes flip1 { + from { + background: url("/icons/icon-left.png") 0 100%; + } + + to { + background: url("/icons/icon-left.png") 100% 100%; + } +} + +@keyframes flip2 { + from { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; + } +} + +@keyframes flip3 { + from { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; + } +} + +@keyframes flip4 { + from { + object-position: 0 100%; + } + + to { + object-position: 100% 100%; + } +} + +/* inside a media-query */ +@media screen and (max-width: 800px) { + [dir="ltr"] .test1 { + background: url("/icons/icon-left.png") 0 100%; + } + + [dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; + } + + .test2 { + background-image: url("/icons/icon-left.png"); + } + + [dir="ltr"] .test2 { + background-position: 0 100%; + } + + [dir="rtl"] .test2 { + background-position: 100% 100%; + } + + .test3 { + background-image: url("/icons/icon-left.png"); + background-position-y: 100%; + } + + [dir="ltr"] .test3 { + background-position-x: 0; + } + + [dir="rtl"] .test3 { + background-position-x: 100%; + } + + [dir="ltr"] .test4 { + object-position: 0 100%; + } + + [dir="rtl"] .test4 { + object-position: 100% 100%; + } +}" +`; diff --git a/tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot b/tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot new file mode 100644 index 00000000..49fac589 --- /dev/null +++ b/tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot @@ -0,0 +1,130 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`[[Mode: combined]] Combined Tests: use {processDeclarationPlugins} to avoid flipping background 1`] = ` +".test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +.test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +.test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +.test4 { + object-position: 0 100%; +} + +/* inside a nested rule */ +[dir="ltr"] .test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +[dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +[dir="ltr"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +[dir="rtl"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; +} + +[dir="ltr"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +[dir="rtl"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; +} + +[dir="ltr"] .test4 { + object-position: 0 100%; +} + +[dir="rtl"] .test4 { + object-position: 100% 100%; +} + +/* inside a keyframe animation */ +@keyframes flip1 { + from { + background: url("/icons/icon-left.png") 0 100%; + } + + to { + background: url("/icons/icon-left.png") 100% 100%; + } +} + +@keyframes flip2 { + from { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; + } +} + +@keyframes flip3 { + from { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; + } +} + +@keyframes flip4 { + from { + object-position: 0 100%; + } + + to { + object-position: 100% 100%; + } +} + +/* inside a media-query */ +@media screen and (max-width: 800px) { + .test1 { + background: url("/icons/icon-left.png") 0 100%; + } + + .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + .test4 { + object-position: 0 100%; + } +}" +`; diff --git a/tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot b/tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot new file mode 100644 index 00000000..336cb7bb --- /dev/null +++ b/tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`[[Mode: diff]] Combined Tests: flip background by default 1`] = ` +".test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +.test2 { + background-position: 100% 100%; +} + +.test3 { + background-position-x: 100%; +} + +.test4 { + object-position: 100% 100%; +} + +@media screen and (max-width: 800px) { + .test1 { + background: url("/icons/icon-left.png") 100% 100%; + } + + .test2 { + background-position: 100% 100%; + } + + .test3 { + background-position-x: 100%; + } + + .test4 { + object-position: 100% 100%; + } +}" +`; diff --git a/tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot b/tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot new file mode 100644 index 00000000..42d8c597 --- /dev/null +++ b/tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`[[Mode: diff]] Combined Tests: use {processDeclarationPlugins} to avoid flipping background 1`] = `""`; diff --git a/tests/__snapshots__/process-declaration-plugins/override/flip.snapshot b/tests/__snapshots__/process-declaration-plugins/override/flip.snapshot new file mode 100644 index 00000000..874a7003 --- /dev/null +++ b/tests/__snapshots__/process-declaration-plugins/override/flip.snapshot @@ -0,0 +1,162 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`[[Mode: override]] Combined Tests: flip background by default 1`] = ` +".test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +[dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +.test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +[dir="rtl"] .test2 { + background-position: 100% 100%; +} + +.test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +[dir="rtl"] .test3 { + background-position-x: 100%; +} + +.test4 { + object-position: 0 100%; +} + +[dir="rtl"] .test4 { + object-position: 100% 100%; +} + +/* inside a nested rule */ +[dir="ltr"] .test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +[dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +[dir="ltr"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +[dir="rtl"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; +} + +[dir="ltr"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +[dir="rtl"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; +} + +[dir="ltr"] .test4 { + object-position: 0 100%; +} + +[dir="rtl"] .test4 { + object-position: 100% 100%; +} + +/* inside a keyframe animation */ +@keyframes flip1 { + from { + background: url("/icons/icon-left.png") 0 100%; + } + + to { + background: url("/icons/icon-left.png") 100% 100%; + } +} + +@keyframes flip2 { + from { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; + } +} + +@keyframes flip3 { + from { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; + } +} + +@keyframes flip4 { + from { + object-position: 0 100%; + } + + to { + object-position: 100% 100%; + } +} + +/* inside a media-query */ +@media screen and (max-width: 800px) { + .test1 { + background: url("/icons/icon-left.png") 0 100%; + } + + [dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; + } + + .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + [dir="rtl"] .test2 { + background-position: 100% 100%; + } + + .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + [dir="rtl"] .test3 { + background-position-x: 100%; + } + + .test4 { + object-position: 0 100%; + } + + [dir="rtl"] .test4 { + object-position: 100% 100%; + } +}" +`; diff --git a/tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot b/tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot new file mode 100644 index 00000000..c9c11c68 --- /dev/null +++ b/tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot @@ -0,0 +1,130 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`[[Mode: override]] Combined Tests: use {processDeclarationPlugins} to avoid flipping background 1`] = ` +".test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +.test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +.test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +.test4 { + object-position: 0 100%; +} + +/* inside a nested rule */ +[dir="ltr"] .test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +[dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +[dir="ltr"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +[dir="rtl"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; +} + +[dir="ltr"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +[dir="rtl"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; +} + +[dir="ltr"] .test4 { + object-position: 0 100%; +} + +[dir="rtl"] .test4 { + object-position: 100% 100%; +} + +/* inside a keyframe animation */ +@keyframes flip1 { + from { + background: url("/icons/icon-left.png") 0 100%; + } + + to { + background: url("/icons/icon-left.png") 100% 100%; + } +} + +@keyframes flip2 { + from { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; + } +} + +@keyframes flip3 { + from { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + to { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; + } +} + +@keyframes flip4 { + from { + object-position: 0 100%; + } + + to { + object-position: 100% 100%; + } +} + +/* inside a media-query */ +@media screen and (max-width: 800px) { + .test1 { + background: url("/icons/icon-left.png") 0 100%; + } + + .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + .test4 { + object-position: 0 100%; + } +}" +`; diff --git a/tests/basic-options.test.ts b/tests/basic-options.test.ts index 0af0edf4..d5f353dc 100644 --- a/tests/basic-options.test.ts +++ b/tests/basic-options.test.ts @@ -73,26 +73,7 @@ runTests({}, (pluginOptions: PluginOptions): void => { ); expect(output.warnings()).toHaveLength(0); }); - - it('{processDeclarationPlugins}', (): void => { - const options: PluginOptions = { - ...pluginOptions, - processDeclarationPlugins: [{ - name: 'avoid-flipping-background', - priority: 99, // above the core RTLCSS plugin which has a priority value of 100 - processors: [{ - expr: /(background|object)(-position(-x)?|-image)?$/i, - action: (prop: string, value: string) => ({prop, value}) - }] - }] - }; - const output = postcss([postcssRTLCSS(options)]).process(input); - expect(output.css).toMatchSpecificSnapshot( - createSnapshotFileName(BASE_NAME,'process-declaration-plugins', pluginOptions.mode) - ); - expect(output.warnings()).toHaveLength(0); - }) - + }); }); \ No newline at end of file diff --git a/tests/css/input-process-declaration-plugins.css b/tests/css/input-process-declaration-plugins.css new file mode 100644 index 00000000..7bf16b38 --- /dev/null +++ b/tests/css/input-process-declaration-plugins.css @@ -0,0 +1,122 @@ +.test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +.test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +.test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +.test4 { + object-position: 0 100%; +} + +/* inside a nested rule */ +[dir="ltr"] .test1 { + background: url("/icons/icon-left.png") 0 100%; +} + +[dir="rtl"] .test1 { + background: url("/icons/icon-left.png") 100% 100%; +} + +[dir="ltr"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; +} + +[dir="rtl"] .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; +} + +[dir="ltr"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; +} + +[dir="rtl"] .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; +} + +[dir="ltr"] .test4 { + object-position: 0 100%; +} + +[dir="rtl"] .test4 { + object-position: 100% 100%; +} + +/* inside a keyframe animation */ +@keyframes flip1 { + from { + background: url("/icons/icon-left.png") 0 100%; + } + to { + background: url("/icons/icon-left.png") 100% 100%; + } +} + +@keyframes flip2 { + from { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + to { + background-image: url("/icons/icon-left.png"); + background-position: 100% 100%; + } +} + +@keyframes flip3 { + from { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + to { + background-image: url("/icons/icon-left.png"); + background-position-x: 100%; + background-position-y: 100%; + } +} + +@keyframes flip4 { + from { + object-position: 0 100%; + } + to { + object-position: 100% 100%; + } +} + +/* inside a media-query */ +@media screen and (max-width: 800px) { + .test1 { + background: url("/icons/icon-left.png") 0 100%; + } + + .test2 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + .test3 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + .test4 { + object-position: 0 100%; + } +} \ No newline at end of file diff --git a/tests/process-declaration-plugins.test.ts b/tests/process-declaration-plugins.test.ts new file mode 100644 index 00000000..402a263c --- /dev/null +++ b/tests/process-declaration-plugins.test.ts @@ -0,0 +1,52 @@ +import postcss from 'postcss'; +import postcssRTLCSS from '../src'; +import { PluginOptions, Mode } from '../src/@types'; +import { + readCSSFile, + runTests, + createSnapshotFileName +} from './utils'; +import 'jest-specific-snapshot'; + +const BASE_NAME = 'process-declaration-plugins'; + +runTests({}, (pluginOptions: PluginOptions): void => { + + describe(`[[Mode: ${pluginOptions.mode}]] Combined Tests: `, (): void => { + + let input = ''; + + beforeEach(async (): Promise => { + input = input || await readCSSFile(`input-${BASE_NAME}.css`); + }); + + it('flip background by default', (): void => { + const output = postcss([postcssRTLCSS(pluginOptions)]).process(input); + expect(output.css).toMatchSpecificSnapshot( + createSnapshotFileName(BASE_NAME,'flip', pluginOptions.mode) + ); + expect(output.warnings()).toHaveLength(0); + }); + + it('use {processDeclarationPlugins} to avoid flipping background', (): void => { + const options: PluginOptions = { + ...pluginOptions, + processDeclarationPlugins: [{ + name: 'avoid-flipping-background', + priority: 99, // above the core RTLCSS plugin which has a priority value of 100 + processors: [{ + expr: /(background|object)(-position(-x)?|-image)?$/i, + action: (prop: string, value: string) => ({prop, value}) + }] + }] + }; + const output = postcss([postcssRTLCSS(options)]).process(input); + expect(output.css).toMatchSpecificSnapshot( + createSnapshotFileName(BASE_NAME,'noflip', pluginOptions.mode) + ); + expect(output.warnings()).toHaveLength(0); + }); + + }); + +}); \ No newline at end of file From 2eb4204ca943c58a93bfe95b6056f1a08864336a Mon Sep 17 00:00:00 2001 From: Aleen Date: Mon, 13 May 2024 15:30:45 +0800 Subject: [PATCH 5/8] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6cdd914f..95392f3f 100644 --- a/README.md +++ b/README.md @@ -1453,7 +1453,7 @@ const options = {
Expand

-Sometimes, we can register some plugins when processing CSS declarations via the `processDeclarationPlugins` options, which is helpful when we need to avoid unexpected flipping situations like `background-position`. +The intention of the processDeclarationPlugins option is to process the declarations to extend or override RTLCSS functionality. For example, we can avoid automatically flipping of `background-potion`. ##### input From 711806be8265edac685250c202134e5b25d46ecf Mon Sep 17 00:00:00 2001 From: Aleen Date: Wed, 15 May 2024 13:54:38 +0800 Subject: [PATCH 6/8] Simplify regular expression detection --- src/data/store.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/store.ts b/src/data/store.ts index 0daba513..0d51b2e9 100644 --- a/src/data/store.ts +++ b/src/data/store.ts @@ -110,7 +110,7 @@ const isAcceptedProcessDeclarationPlugins = (plugins: DeclarationPlugin[]): bool && typeof plugin.priority == NUMBER_TYPE && Array.isArray(plugin.processors) && plugin.processors.every((processor: DeclarationPluginProcessor) => - ({}).toString.call(processor.expr) === '[object RegExp]' + processor.expr instanceof RegExp && typeof processor.action === FUNCTION_TYPE ) ); @@ -272,4 +272,4 @@ const initKeyframesData = (): void => { store.keyframesRegExp = getKeyFramesRegExp(store.keyframesStringMap); }; -export { store, initStore, initKeyframesData }; \ No newline at end of file +export { store, initStore, initKeyframesData }; From bea1d60ba5870a8ff0c6acce20d57b2f500573f3 Mon Sep 17 00:00:00 2001 From: Aleen Date: Wed, 15 May 2024 14:10:30 +0800 Subject: [PATCH 7/8] Change test cases --- .../combined/flip.snapshot | 65 +++++++++++-------- .../combined/noflip.snapshot | 51 +++++---------- .../diff/flip.snapshot | 20 +++++- .../diff/noflip.snapshot | 2 +- .../override/flip.snapshot | 59 ++++++++--------- .../override/noflip.snapshot | 51 +++++---------- ...=> input-process-declaration-plugins.scss} | 54 +++++---------- tests/process-declaration-plugins.test.ts | 4 +- 8 files changed, 141 insertions(+), 165 deletions(-) rename tests/css/{input-process-declaration-plugins.css => input-process-declaration-plugins.scss} (68%) diff --git a/tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot b/tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot index b3009ced..3a1cf678 100644 --- a/tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot +++ b/tests/__snapshots__/process-declaration-plugins/combined/flip.snapshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`[[Mode: combined]] Combined Tests: flip background by default 1`] = ` +exports[`[[Mode: combined]] flip background by default 1`] = ` "[dir="ltr"] .test1 { background: url("/icons/icon-left.png") 0 100%; } @@ -43,42 +43,51 @@ exports[`[[Mode: combined]] Combined Tests: flip background by default 1`] = ` } /* inside a nested rule */ -[dir="ltr"] .test1 { - background: url("/icons/icon-left.png") 0 100%; -} +.test1 { + .test3 { + background-image: url("/icons/icon-left.png"); + } -[dir="rtl"] .test1 { - background: url("/icons/icon-left.png") 100% 100%; + > .test4 { + background-image: url("/icons/icon-left.png"); + background-position-y: 100%; + } } -[dir="ltr"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 0 100%; -} +[dir="ltr"] .test1 { + &.test2 { + background: url("/icons/icon-left.png") 0 100%; + } -[dir="rtl"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 100% 100%; -} + .test3 { + background-position: 0 100%; + } -[dir="ltr"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 0; - background-position-y: 100%; -} + > .test4 { + background-position-x: 0; + } -[dir="rtl"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 100%; - background-position-y: 100%; + + .test5 { + object-position: 0 100%; + } } -[dir="ltr"] .test4 { - object-position: 0 100%; -} +[dir="rtl"] .test1 { + &.test2 { + background: url("/icons/icon-left.png") 100% 100%; + } -[dir="rtl"] .test4 { - object-position: 100% 100%; + .test3 { + background-position: 100% 100%; + } + + > .test4 { + background-position-x: 100%; + } + + + .test5 { + object-position: 100% 100%; + } } /* inside a keyframe animation */ diff --git a/tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot b/tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot index 49fac589..718aeca4 100644 --- a/tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot +++ b/tests/__snapshots__/process-declaration-plugins/combined/noflip.snapshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`[[Mode: combined]] Combined Tests: use {processDeclarationPlugins} to avoid flipping background 1`] = ` +exports[`[[Mode: combined]] use {processDeclarationPlugins} to avoid flipping background 1`] = ` ".test1 { background: url("/icons/icon-left.png") 0 100%; } @@ -21,42 +21,25 @@ exports[`[[Mode: combined]] Combined Tests: use {processDeclarationPlugins} to } /* inside a nested rule */ -[dir="ltr"] .test1 { - background: url("/icons/icon-left.png") 0 100%; -} - -[dir="rtl"] .test1 { - background: url("/icons/icon-left.png") 100% 100%; -} - -[dir="ltr"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 0 100%; -} - -[dir="rtl"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 100% 100%; -} - -[dir="ltr"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 0; - background-position-y: 100%; -} +.test1 { + &.test2 { + background: url("/icons/icon-left.png") 0 100%; + } -[dir="rtl"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 100%; - background-position-y: 100%; -} + .test3 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } -[dir="ltr"] .test4 { - object-position: 0 100%; -} + > .test4 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } -[dir="rtl"] .test4 { - object-position: 100% 100%; + + .test5 { + object-position: 0 100%; + } } /* inside a keyframe animation */ diff --git a/tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot b/tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot index 336cb7bb..b6be268d 100644 --- a/tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot +++ b/tests/__snapshots__/process-declaration-plugins/diff/flip.snapshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`[[Mode: diff]] Combined Tests: flip background by default 1`] = ` +exports[`[[Mode: diff]] flip background by default 1`] = ` ".test1 { background: url("/icons/icon-left.png") 100% 100%; } @@ -17,6 +17,24 @@ exports[`[[Mode: diff]] Combined Tests: flip background by default 1`] = ` object-position: 100% 100%; } +.test1 { + &.test2 { + background: url("/icons/icon-left.png") 100% 100%; + } + + .test3 { + background-position: 100% 100%; + } + + > .test4 { + background-position-x: 100%; + } + + + .test5 { + object-position: 100% 100%; + } +} + @media screen and (max-width: 800px) { .test1 { background: url("/icons/icon-left.png") 100% 100%; diff --git a/tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot b/tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot index 42d8c597..955e5075 100644 --- a/tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot +++ b/tests/__snapshots__/process-declaration-plugins/diff/noflip.snapshot @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`[[Mode: diff]] Combined Tests: use {processDeclarationPlugins} to avoid flipping background 1`] = `""`; +exports[`[[Mode: diff]] use {processDeclarationPlugins} to avoid flipping background 1`] = `""`; diff --git a/tests/__snapshots__/process-declaration-plugins/override/flip.snapshot b/tests/__snapshots__/process-declaration-plugins/override/flip.snapshot index 874a7003..96b2d465 100644 --- a/tests/__snapshots__/process-declaration-plugins/override/flip.snapshot +++ b/tests/__snapshots__/process-declaration-plugins/override/flip.snapshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`[[Mode: override]] Combined Tests: flip background by default 1`] = ` +exports[`[[Mode: override]] flip background by default 1`] = ` ".test1 { background: url("/icons/icon-left.png") 0 100%; } @@ -37,42 +37,43 @@ exports[`[[Mode: override]] Combined Tests: flip background by default 1`] = ` } /* inside a nested rule */ -[dir="ltr"] .test1 { - background: url("/icons/icon-left.png") 0 100%; -} +.test1 { + &.test2 { + background: url("/icons/icon-left.png") 0 100%; + } -[dir="rtl"] .test1 { - background: url("/icons/icon-left.png") 100% 100%; -} + .test3 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } -[dir="ltr"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 0 100%; -} + > .test4 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } -[dir="rtl"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 100% 100%; + + .test5 { + object-position: 0 100%; + } } -[dir="ltr"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 0; - background-position-y: 100%; -} +[dir="rtl"] .test1 { + &.test2 { + background: url("/icons/icon-left.png") 100% 100%; + } -[dir="rtl"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 100%; - background-position-y: 100%; -} + .test3 { + background-position: 100% 100%; + } -[dir="ltr"] .test4 { - object-position: 0 100%; -} + > .test4 { + background-position-x: 100%; + } -[dir="rtl"] .test4 { - object-position: 100% 100%; + + .test5 { + object-position: 100% 100%; + } } /* inside a keyframe animation */ diff --git a/tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot b/tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot index c9c11c68..beaad981 100644 --- a/tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot +++ b/tests/__snapshots__/process-declaration-plugins/override/noflip.snapshot @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`[[Mode: override]] Combined Tests: use {processDeclarationPlugins} to avoid flipping background 1`] = ` +exports[`[[Mode: override]] use {processDeclarationPlugins} to avoid flipping background 1`] = ` ".test1 { background: url("/icons/icon-left.png") 0 100%; } @@ -21,42 +21,25 @@ exports[`[[Mode: override]] Combined Tests: use {processDeclarationPlugins} to } /* inside a nested rule */ -[dir="ltr"] .test1 { - background: url("/icons/icon-left.png") 0 100%; -} - -[dir="rtl"] .test1 { - background: url("/icons/icon-left.png") 100% 100%; -} - -[dir="ltr"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 0 100%; -} - -[dir="rtl"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 100% 100%; -} - -[dir="ltr"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 0; - background-position-y: 100%; -} +.test1 { + &.test2 { + background: url("/icons/icon-left.png") 0 100%; + } -[dir="rtl"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 100%; - background-position-y: 100%; -} + .test3 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } -[dir="ltr"] .test4 { - object-position: 0 100%; -} + > .test4 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } -[dir="rtl"] .test4 { - object-position: 100% 100%; + + .test5 { + object-position: 0 100%; + } } /* inside a keyframe animation */ diff --git a/tests/css/input-process-declaration-plugins.css b/tests/css/input-process-declaration-plugins.scss similarity index 68% rename from tests/css/input-process-declaration-plugins.css rename to tests/css/input-process-declaration-plugins.scss index 7bf16b38..a58b4472 100644 --- a/tests/css/input-process-declaration-plugins.css +++ b/tests/css/input-process-declaration-plugins.scss @@ -18,42 +18,24 @@ } /* inside a nested rule */ -[dir="ltr"] .test1 { - background: url("/icons/icon-left.png") 0 100%; -} - -[dir="rtl"] .test1 { - background: url("/icons/icon-left.png") 100% 100%; -} - -[dir="ltr"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 0 100%; -} - -[dir="rtl"] .test2 { - background-image: url("/icons/icon-left.png"); - background-position: 100% 100%; -} - -[dir="ltr"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 0; - background-position-y: 100%; -} - -[dir="rtl"] .test3 { - background-image: url("/icons/icon-left.png"); - background-position-x: 100%; - background-position-y: 100%; -} - -[dir="ltr"] .test4 { - object-position: 0 100%; -} - -[dir="rtl"] .test4 { - object-position: 100% 100%; +.test1 { + &.test2 { + background: url("/icons/icon-left.png") 0 100%; + } + .test3 { + background-image: url("/icons/icon-left.png"); + background-position: 0 100%; + } + + > .test4 { + background-image: url("/icons/icon-left.png"); + background-position-x: 0; + background-position-y: 100%; + } + + + .test5 { + object-position: 0 100%; + } } /* inside a keyframe animation */ diff --git a/tests/process-declaration-plugins.test.ts b/tests/process-declaration-plugins.test.ts index 402a263c..a92c4892 100644 --- a/tests/process-declaration-plugins.test.ts +++ b/tests/process-declaration-plugins.test.ts @@ -12,12 +12,12 @@ const BASE_NAME = 'process-declaration-plugins'; runTests({}, (pluginOptions: PluginOptions): void => { - describe(`[[Mode: ${pluginOptions.mode}]] Combined Tests: `, (): void => { + describe(`[[Mode: ${pluginOptions.mode}]]`, (): void => { let input = ''; beforeEach(async (): Promise => { - input = input || await readCSSFile(`input-${BASE_NAME}.css`); + input = input || await readCSSFile(`input-${BASE_NAME}.scss`); }); it('flip background by default', (): void => { From dd78fd02c406bb9c8781732cf1ec61239863dd21 Mon Sep 17 00:00:00 2001 From: Aleen Date: Mon, 20 May 2024 10:32:46 +0800 Subject: [PATCH 8/8] Fix lint --- src/@types/index.ts | 4 +- src/data/store.ts | 2 +- tests/process-declaration-plugins.test.ts | 74 +++++++++++------------ 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/@types/index.ts b/src/@types/index.ts index cde967af..20b4076d 100644 --- a/src/@types/index.ts +++ b/src/@types/index.ts @@ -43,8 +43,8 @@ export type RTLCSSPlugin = { name: string; priority: number; directives: { - control: Object, - value: Array + control: object, + value: Array }; } diff --git a/src/data/store.ts b/src/data/store.ts index 0d51b2e9..b20d3157 100644 --- a/src/data/store.ts +++ b/src/data/store.ts @@ -106,7 +106,7 @@ const isNotAcceptedStringMap = (stringMap: PluginStringMap[]): boolean => { const isAcceptedProcessDeclarationPlugins = (plugins: DeclarationPlugin[]): boolean => Array.isArray(plugins) && plugins.every((plugin: DeclarationPlugin) => - typeof plugin.name == STRING_TYPE + typeof plugin.name == STRING_TYPE && typeof plugin.priority == NUMBER_TYPE && Array.isArray(plugin.processors) && plugin.processors.every((processor: DeclarationPluginProcessor) => diff --git a/tests/process-declaration-plugins.test.ts b/tests/process-declaration-plugins.test.ts index a92c4892..8016ec9e 100644 --- a/tests/process-declaration-plugins.test.ts +++ b/tests/process-declaration-plugins.test.ts @@ -1,10 +1,10 @@ import postcss from 'postcss'; import postcssRTLCSS from '../src'; -import { PluginOptions, Mode } from '../src/@types'; +import {PluginOptions} from '../src/@types'; import { - readCSSFile, - runTests, - createSnapshotFileName + readCSSFile, + runTests, + createSnapshotFileName } from './utils'; import 'jest-specific-snapshot'; @@ -12,41 +12,41 @@ const BASE_NAME = 'process-declaration-plugins'; runTests({}, (pluginOptions: PluginOptions): void => { - describe(`[[Mode: ${pluginOptions.mode}]]`, (): void => { + describe(`[[Mode: ${pluginOptions.mode}]]`, (): void => { - let input = ''; - - beforeEach(async (): Promise => { - input = input || await readCSSFile(`input-${BASE_NAME}.scss`); - }); - - it('flip background by default', (): void => { - const output = postcss([postcssRTLCSS(pluginOptions)]).process(input); - expect(output.css).toMatchSpecificSnapshot( - createSnapshotFileName(BASE_NAME,'flip', pluginOptions.mode) - ); - expect(output.warnings()).toHaveLength(0); - }); + let input = ''; + + beforeEach(async (): Promise => { + input = input || await readCSSFile(`input-${BASE_NAME}.scss`); + }); + + it('flip background by default', (): void => { + const output = postcss([postcssRTLCSS(pluginOptions)]).process(input); + expect(output.css).toMatchSpecificSnapshot( + createSnapshotFileName(BASE_NAME, 'flip', pluginOptions.mode) + ); + expect(output.warnings()).toHaveLength(0); + }); + + it('use {processDeclarationPlugins} to avoid flipping background', (): void => { + const options: PluginOptions = { + ...pluginOptions, + processDeclarationPlugins: [{ + name: 'avoid-flipping-background', + priority: 99, // above the core RTLCSS plugin which has a priority value of 100 + processors: [{ + expr: /(background|object)(-position(-x)?|-image)?$/i, + action: (prop: string, value: string) => ({prop, value}) + }] + }] + }; + const output = postcss([postcssRTLCSS(options)]).process(input); + expect(output.css).toMatchSpecificSnapshot( + createSnapshotFileName(BASE_NAME, 'noflip', pluginOptions.mode) + ); + expect(output.warnings()).toHaveLength(0); + }); - it('use {processDeclarationPlugins} to avoid flipping background', (): void => { - const options: PluginOptions = { - ...pluginOptions, - processDeclarationPlugins: [{ - name: 'avoid-flipping-background', - priority: 99, // above the core RTLCSS plugin which has a priority value of 100 - processors: [{ - expr: /(background|object)(-position(-x)?|-image)?$/i, - action: (prop: string, value: string) => ({prop, value}) - }] - }] - }; - const output = postcss([postcssRTLCSS(options)]).process(input); - expect(output.css).toMatchSpecificSnapshot( - createSnapshotFileName(BASE_NAME,'noflip', pluginOptions.mode) - ); - expect(output.warnings()).toHaveLength(0); }); - - }); }); \ No newline at end of file