Skip to content

Commit

Permalink
Fix issue #64
Browse files Browse the repository at this point in the history
  • Loading branch information
evilaliv3 committed May 17, 2020
1 parent 6cb1a8c commit a347e6c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 74 deletions.
2 changes: 0 additions & 2 deletions src/prefixes-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ module.exports = ({prefix}) => ({
prefixes: {
ltr: `[${prefix}=ltr]`,
rtl: `[${prefix}=rtl]`,
dir: `[${prefix}]`,
},
regex: new RegExp(`\\[${prefix}(=(\\w+|"\\w+"))?\\]`),
},
class: {
prefixes: {
ltr: `.${prefix}-ltr`,
rtl: `.${prefix}-rtl`,
dir: `.${prefix}`,
},
regex: new RegExp(`\\.${prefix}(-\\w+)?`),
},
Expand Down
7 changes: 7 additions & 0 deletions src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ const isRootSelector = (selector = '') => !!selector.match(/:root/);

const addDirToSelectors = (selectors = '', dir, options = {}) => {
const {addPrefixToSelector, prefixType} = options;

if (options.prefix === 'dir' && (options.onlyDirection !== 'rtl' && ((options.fromRTL && dir === 'rtl') || (!options.fromRTL && dir === 'ltr')))) {
return selectors;
}

// we swap direction prefixes if we are converting rtl styles to ltr
if (options.fromRTL) {
switch (dir) {
Expand All @@ -20,7 +25,9 @@ const addDirToSelectors = (selectors = '', dir, options = {}) => {
default:
}
}

const prefix = generatePrefixes(options)[prefixType].prefixes[dir];

if (!prefix) return selectors;

return selectors
Expand Down
104 changes: 32 additions & 72 deletions src/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,72 +16,38 @@ const run = (t, input, output, opts) => postcss([
t.is(result.warnings().length, 0);
});

test('Should NOT add [dir] prefix to symmetric rules', t => run(t,
test('Should NOT vary symmetric rules', t => run(t,
'a { font-size: 1em }',
'a { font-size: 1em }'));

test('Should ONLY create LTR & RTL rules to asymmetric rules', t => run(t,
test('Should ONLY split LTR & RTL rules in case of presence of asymmetric rules', t => run(t,
'a { font-size: 1em; text-align: left }',
'a { font-size: 1em }'
+ '[dir=ltr] a { text-align: left }'
+ '[dir=rtl] a { text-align: right }'));

test('Should add [dir] prefix to symmetric rules with direction related declarations', t => run(t,
'a { text-align: center }',
'[dir] a { text-align: center }'));

test('Should add [dir] prefix to symmetric rules with direction related declarations (2)', t => run(t,
'a { font-size: 1em; text-align: center }',
'a { font-size: 1em }'
+ '[dir] a { text-align: center }'));

test('Should add [dir] prefix to symmetric rules with direction related declarations (3)', t => run(t,
'a { text-align: left }'
+ 'a { text-align: center }',
'[dir=ltr] a { text-align: left }'
+ '[dir=rtl] a { text-align: right }'
+ '[dir] a { text-align: center }'));

test('Should add [dir] prefix to symmetric rules with direction related declarations (4)', t => run(t,
'a { margin: 0 10px 0 0 }'
+ 'a { margin-top: 20px }',
'[dir=ltr] a { margin: 0 10px 0 0 }'
+ '[dir=rtl] a { margin: 0 0 0 10px }'
+ '[dir] a { margin-top: 20px }'));

test('Creates both LTR & RTL rules for asymmetric declarations', t => run(t,
'a { text-align: left }',
'[dir=ltr] a { text-align: left }'
+ '[dir=rtl] a { text-align: right }'));

test('Removes original rule without symmetric declarations', t => run(t,
'a { text-align: left }',
'[dir=ltr] a { text-align: left }'
'a { font-size: 1em; text-align: left }'
+ '[dir=rtl] a { text-align: right }'));

test('Adds prefix to the html element', t => run(t,
'html { text-align: left }',
'html[dir=ltr] { text-align: left }'
'html { text-align: left }'
+ 'html[dir=rtl] { text-align: right }'));

test('Adds prefix to the html element with class', t => run(t,
'html.foo { text-align: left }',
'html[dir=ltr].foo { text-align: left }'
'html.foo { text-align: left }'
+ 'html[dir=rtl].foo { text-align: right }'));

test('Adds prefix to the :root element', t => run(t,
':root { text-align: left }',
'[dir=ltr]:root { text-align: left }'
':root { text-align: left }'
+ '[dir=rtl]:root { text-align: right }'));

test('Adds prefix to the :root element with class', t => run(t,
':root.foo { text-align: left }',
'[dir=ltr]:root.foo { text-align: left }'
':root.foo { text-align: left }'
+ '[dir=rtl]:root.foo { text-align: right }'));

test('Use custom `addPrefixToSelector` function', t => run(t,
'a { text-align: left }',
'[dir=ltr] > a { text-align: left }'
'a { text-align: left }'
+ '[dir=rtl] > a { text-align: right }',
{
addPrefixToSelector(selector, prefix) {
Expand All @@ -91,13 +57,13 @@ test('Use custom `addPrefixToSelector` function', t => run(t,

test('Should correctly process values containing commas', t => run(t,
'div { background: url(\'http://placecage.com/400/400\') 0 0 }',
'[dir=ltr] div { background: url(\'http://placecage.com/400/400\') 0 0 }'
'div { background: url(\'http://placecage.com/400/400\') 0 0 }'
+ '[dir=rtl] div { background: url(\'http://placecage.com/400/400\') 100% 0 }'));

test('Should correctly process values containing !important', t => run(t,
'.test { margin-left: 0 !important; padding-left: 0 !important }',

'[dir=ltr] .test { margin-left: 0 !important; padding-left: 0 !important }'
'.test { margin-left: 0 !important; padding-left: 0 !important }'
+ '[dir=rtl] .test { margin-right: 0 !important; padding-right: 0 !important }'));

test('Shouldn not create unnecessary duplications with !important', t => run(t,
Expand All @@ -108,8 +74,7 @@ test('Shouldn not create unnecessary duplications with !important', t => run(t,
test('Should correctly process values containing _display', t => run(t,
'.test { float: left; _display: inline }',

'.test { _display: inline }'
+ '[dir=ltr] .test { float: left }'
'.test { _display: inline; float: left }'
+ '[dir=rtl] .test { float: right }'));

test('Should ignore declarations prefixed with /* rtl:ignore */', t => run(t,
Expand All @@ -121,15 +86,15 @@ test('/* rtl:ignore */: Should leave other selectors alone', t => run(t,
+ '.rtled { margin-left:0; padding-left:0 }',

'.test { margin-left:0 } '
+ '[dir=ltr] .rtled { margin-left:0; padding-left:0 } '
+ '.rtled { margin-left:0; padding-left:0 } '
+ '[dir=rtl] .rtled { margin-right:0; padding-right:0 }'));

test('/* rtl:ignore */: should understand overrides', t => run(t,
'.x { left: 0 } '
+ '/* rtl:ignore */'
+ '.x { direction: ltr }',

'[dir=ltr] .x { left: 0 }'
'.x { left: 0 }'
+ '[dir=rtl] .x { right: 0 }'
+ '.x { direction: ltr }'));

Expand All @@ -148,7 +113,7 @@ test('/* rtl:end:ignore */ stops ignore mode', t => run(t,
+ '.bar { direction: ltr }',

'.foo { padding-left: 0 }'
+ '[dir=ltr] .bar { direction: ltr }'
+ '.bar { direction: ltr }'
+ '[dir=rtl] .bar { direction: rtl }'));

test('/* rtl:ignore */ can be used inside /* rtl:begin:ignore */ and /* rtl:end:ignore */', t => run(t,
Expand All @@ -165,12 +130,11 @@ test('/* rtl:ignore */ can be used inside /* rtl:begin:ignore */ and /* rtl:end:

test('that it ignores normal comments ', t => run(t,
'/* some comment */ .foo { padding-left: 0 }',
'/* some comment */ [dir=ltr] .foo { padding-left: 0 } [dir=rtl] .foo { padding-right: 0 }'));
'/* some comment */ .foo { padding-left: 0 } [dir=rtl] .foo { padding-right: 0 }'));

test('Value based ignore comments are honored', t => run(t,
'.foo { margin-left: 12px; padding-left: 12px /* rtl:ignore */; }',
'.foo { padding-left: 12px /* rtl:ignore */; }'
+ '[dir=ltr] .foo { margin-left: 12px; }'
'.foo { padding-left: 12px /* rtl:ignore */; margin-left: 12px; }'
+ '[dir=rtl] .foo { margin-right: 12px; }'));

test('/*! rtl:ignore */ should consider as a valid directive', t => run(t,
Expand All @@ -184,7 +148,7 @@ test('/*! rtl:begin:ignore */ and /*! rtl:end:ignore */ should consider as a val
+ '.bar { direction: ltr }',

'.foo { padding-left: 0 }'
+ '[dir=ltr] .bar { direction: ltr }'
+ '.bar { direction: ltr }'
+ '[dir=rtl] .bar { direction: rtl }'));

test('Should add direction to flippable keyframes-animations', t => run(t,
Expand All @@ -197,7 +161,7 @@ test('Should handle multiple keyframes-animations', t => run(t,
+ '@keyframes load6 { 100% { transform: rotate(1deg) } }'
+ '@keyframes spinner { 100% { transform: rotate(-1deg) } }',

'[dir=ltr] .loader {animation: load6-ltr 1.7s infinite ease, spinner-ltr 1.7s infinite ease;}'
'.loader {animation: load6-ltr 1.7s infinite ease, spinner-ltr 1.7s infinite ease;}'
+ '[dir=rtl] .loader {animation: load6-rtl 1.7s infinite ease, spinner-rtl 1.7s infinite ease;}'
+ '@keyframes load6-ltr { 100% { transform: rotate(1deg) } }'
+ '@keyframes load6-rtl { 100% { transform: rotate(-1deg) } }'
Expand All @@ -216,15 +180,14 @@ test('/* rtl:end:ignore */ stops ignore mode for keyframes', t => run(t,
'/* rtl:begin:ignore */ @keyframes bar { 100% { transform: rotate(360deg); } } /* rtl:end:ignore */'
+ '.foo { left: 5px }',
'@keyframes bar { 100% { transform: rotate(360deg); } }'
+ '[dir=ltr] .foo { left: 5px }'
+ '.foo { left: 5px }'
+ '[dir=rtl] .foo { right: 5px }'));

test('Should create only LTR version', t => run(t,
'a { font-size: 1em; text-align: left }'
+ '@keyframes bar { 100% { transform: rotate(360deg); } }',

'a { font-size: 1em }'
+ '[dir=ltr] a { text-align: left }'
'a { font-size: 1em; text-align: left }'
+ '@keyframes bar-ltr { 100% { transform: rotate(360deg); } }',
{onlyDirection: 'ltr'}));

Expand All @@ -239,33 +202,32 @@ test('Should create only RTL version', t => run(t,

test('Value replacement directives are honored', t => run(t,
'.foo { font-weight: bold; flex-direction: row/* rtl:row-reverse */; }',
'.foo { font-weight: bold; }[dir=ltr] .foo { flex-direction: row/* rtl:row-reverse */; }[dir=rtl] .foo { flex-direction: row-reverse; }'));
'.foo { font-weight: bold; flex-direction: row/* rtl:row-reverse */; }[dir=rtl] .foo { flex-direction: row-reverse; }'));

test('Value prepend directives are honored', t => run(t,
'.foo { font-weight: bold; font-family: "Droid Sans", "Helvetica Neue", Arial, sans-serif/*rtl:prepend:"Droid Arabic Kufi",*/; }',
'.foo { font-weight: bold; }[dir=ltr] .foo { font-family: "Droid Sans", "Helvetica Neue", Arial, sans-serif/*rtl:prepend:"Droid Arabic Kufi",*/; }[dir=rtl] .foo { font-family: "Droid Arabic Kufi", "Droid Sans", "Helvetica Neue", Arial, sans-serif; }'));
'.foo { font-weight: bold; font-family: "Droid Sans", "Helvetica Neue", Arial, sans-serif/*rtl:prepend:"Droid Arabic Kufi",*/; }[dir=rtl] .foo { font-family: "Droid Arabic Kufi", "Droid Sans", "Helvetica Neue", Arial, sans-serif; }'));

test('Value append directives are honored', t => run(t,
'.foo { font-weight: bold; transform: rotate(45deg)/* rtl:append: scaleX(-1) */; }',
'.foo { font-weight: bold; }[dir=ltr] .foo { transform: rotate(45deg)/* rtl:append: scaleX(-1) */; }[dir=rtl] .foo { transform: rotate(45deg) scaleX(-1); }'));
'.foo { font-weight: bold; transform: rotate(45deg)/* rtl:append: scaleX(-1) */; }[dir=rtl] .foo { transform: rotate(45deg) scaleX(-1); }'));

test('Value based ignore important comments are honored', t => run(t,
'.foo { margin-left: 12px; padding-left: 12px /*! rtl:ignore */; }',
'.foo { padding-left: 12px /*! rtl:ignore */; }'
+ '[dir=ltr] .foo { margin-left: 12px; }'
'.foo { padding-left: 12px /*! rtl:ignore */; margin-left: 12px; }'
+ '[dir=rtl] .foo { margin-right: 12px; }'));

test('Value replacement directives with important comments are honored', t => run(t,
'.foo { font-weight: bold; flex-direction: row/*! rtl:row-reverse */; }',
'.foo { font-weight: bold; }[dir=ltr] .foo { flex-direction: row/*! rtl:row-reverse */; }[dir=rtl] .foo { flex-direction: row-reverse; }'));
'.foo { font-weight: bold; flex-direction: row/*! rtl:row-reverse */; }[dir=rtl] .foo { flex-direction: row-reverse; }'));

test('Value prepend directives with important comments are honored', t => run(t,
'.foo { font-weight: bold; font-family: "Droid Sans", "Helvetica Neue", Arial, sans-serif/*!rtl:prepend:"Droid Arabic Kufi",*/; }',
'.foo { font-weight: bold; }[dir=ltr] .foo { font-family: "Droid Sans", "Helvetica Neue", Arial, sans-serif/*!rtl:prepend:"Droid Arabic Kufi",*/; }[dir=rtl] .foo { font-family: "Droid Arabic Kufi", "Droid Sans", "Helvetica Neue", Arial, sans-serif; }'));
'.foo { font-weight: bold; font-family: "Droid Sans", "Helvetica Neue", Arial, sans-serif/*!rtl:prepend:"Droid Arabic Kufi",*/; }[dir=rtl] .foo { font-family: "Droid Arabic Kufi", "Droid Sans", "Helvetica Neue", Arial, sans-serif; }'));

test('Value append directives with important comments are honored', t => run(t,
'.foo { font-weight: bold; transform: rotate(45deg)/*! rtl:append: scaleX(-1) */; }',
'.foo { font-weight: bold; }[dir=ltr] .foo { transform: rotate(45deg)/*! rtl:append: scaleX(-1) */; }[dir=rtl] .foo { transform: rotate(45deg) scaleX(-1); }'));
'.foo { font-weight: bold; transform: rotate(45deg)/*! rtl:append: scaleX(-1) */; }[dir=rtl] .foo { transform: rotate(45deg) scaleX(-1); }'));

test('Should keep comments', t => run(t,
'/* rtl:ignore */ a { text-align: left }',
Expand All @@ -287,7 +249,7 @@ test('Should respect custom prefix (class)', t => run(t,
test('Should not swap "left" and "right" subparts of selectors', t => run(t,
'.arrowLeft { margin-right: -3px }',

'[dir=ltr] .arrowLeft { margin-right: -3px }'
'.arrowLeft { margin-right: -3px }'
+ '[dir=rtl] .arrowLeft { margin-left: -3px }'));

test('Should respect multiline values', t => run(t,
Expand All @@ -296,7 +258,7 @@ test('Should respect multiline values', t => run(t,
linear-gradient(to right, transparent, #000);
}`,

`[dir=ltr] .multiline {
`.multiline {
background: rgba(0, 0, 0, 0, .5),
linear-gradient(to right, transparent, #000);
}`
Expand All @@ -308,7 +270,7 @@ test('Should respect multiline values', t => run(t,
test('rtl:as: directive', t => run(t,
':root { --padding /* rtl:as:padding */: 1px 2px 3px 4px }',

'[dir=ltr]:root { --padding /* rtl:as:padding */: 1px 2px 3px 4px }'
':root { --padding /* rtl:as:padding */: 1px 2px 3px 4px }'
+ '[dir=rtl]:root { --padding /* rtl:as:padding */: 1px 4px 3px 2px }'));

test('should ignore ignored @import', t => run(t,
Expand All @@ -321,15 +283,13 @@ test('should ignore ignored @import', t => run(t,
test('should ignore blacklist properties', t => run(t,
'.test {padding-left: 1rem;padding: 1rem 2rem 3rem 4rem}',

'.test {padding: 1rem 2rem 3rem 4rem}'
+ '[dir=ltr] .test {padding-left: 1rem}'
'.test {padding: 1rem 2rem 3rem 4rem;padding-left: 1rem}'
+ '[dir=rtl] .test {padding-right: 1rem}',
{blacklist: ['padding']}));

test('should process whitelist properties only', t => run(t,
'.test {padding-left: 1rem;padding: 1rem 2rem 3rem 4rem}',

'.test {padding-left: 1rem}'
+ '[dir=ltr] .test {padding: 1rem 2rem 3rem 4rem}'
'.test {padding-left: 1rem;padding: 1rem 2rem 3rem 4rem}'
+ '[dir=rtl] .test {padding: 1rem 4rem 3rem 2rem}',
{whitelist: ['padding']}));

0 comments on commit a347e6c

Please sign in to comment.