Skip to content

Commit bd6bdcd

Browse files
committed
Implemented /*rtl:source:{source}*/, /*rtl:begin:source:{source}*/, and /*rtl:end:source*/
1 parent 7f820b7 commit bd6bdcd

20 files changed

+8018
-120
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## [3.3.0] - 2021-03-14
4+
5+
- Implemented /*rtl:source:{source}*/, /*rtl:begin:source:{source}*/, and /*rtl:end:source*/
6+
37
## [3.2.0] - 2021-03-13
48

59
- Add basic support for nested rules (SCSS)

README.md

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,12 +1064,15 @@ Control directives are placed between rules or declarations. They can target a s
10641064
10651065
| Directive | Description |
10661066
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
1067-
| `/*rtl:ignore*/` | Ignores processing of the following rule or declaration |
1068-
| `/*rtl:begin:ignore*/` | Starts an ignoring block |
1069-
| `/*rtl:end:ignore*/` | Ends an ignoring block |
1070-
| `/*rtl:rename*/` | This directive forces renaming in the next rule or declaration no mattering the value of the properties `processUrls` or `autoRename` |
1071-
| `/*rtl:begin:rename*/` | Starts a renaming block |
1072-
| `/*rtl:end:rename*/` | Ends a renaming block |
1067+
| `/*rtl:ignore*/` | Ignores processing of the following rule or declaration |
1068+
| `/*rtl:begin:ignore*/` | Starts an ignoring block |
1069+
| `/*rtl:end:ignore*/` | Ends an ignoring block |
1070+
| `/*rtl:rename*/` | This directive forces renaming in the next rule or declaration no mattering the value of the properties `processUrls` or `autoRename` |
1071+
| `/*rtl:begin:rename*/` | Starts a renaming block |
1072+
| `/*rtl:end:rename*/` | Ends a renaming block |
1073+
| `/*rtl:source:{source}*/`| Set the source of a rule or a declaration no mattering the value of the `source` property |
1074+
| `/*rtl:begin:source:{source}*/` | Starts a source block |
1075+
| `/*rtl:end:source*/` | Ends a source block |
10731076
| `/*rtl:raw:{CSS}*/` | Parses the `CSS` parameter and inserts it in its place. Depending on the `source` parameter the parsed `CSS` will be treated as `rtl` or `ltr` |
10741077
10751078
---
@@ -1312,6 +1315,101 @@ These directives should be used together, they will provide the beginning and th
13121315
13131316
---
13141317
1318+
#### `/*rtl:source:{source}*/`
1319+
1320+
<details><summary>Expand</summary>
1321+
<p>
1322+
1323+
This directive sets the source of a rule or a directive ignoring the value of the `source` property:
1324+
1325+
##### input
1326+
1327+
```css
1328+
/*rtl:source:rtl*/
1329+
.test {
1330+
color: #FFF;
1331+
border-left: 1px solid #666;
1332+
padding: 10px 5px 10px 20px;
1333+
text-align: left;
1334+
width: 100%;
1335+
}
1336+
```
1337+
1338+
##### output
1339+
1340+
```css
1341+
.test {
1342+
color: #FFF;
1343+
width: 100%;
1344+
}
1345+
1346+
[dir="ltr"] .test {
1347+
border-right: 1px solid #666;
1348+
padding: 10px 20px 10px 5px;
1349+
text-align: right;
1350+
}
1351+
1352+
[dir="rtl"] .test {
1353+
border-left: 1px solid #666;
1354+
padding: 10px 5px 10px 20px;
1355+
text-align: left;
1356+
}
1357+
```
1358+
1359+
</p>
1360+
1361+
</details>
1362+
1363+
---
1364+
1365+
#### `/*rtl:begin:source:{source}*/` and `/*rtl:end:source*/`
1366+
1367+
<details><summary>Expand</summary>
1368+
<p>
1369+
1370+
These directives should be used together, they will provide the beginning and the end of source blocks for rules or declarations:
1371+
1372+
##### input
1373+
1374+
```css
1375+
.test {
1376+
color: #FFF;
1377+
border-left: 1px solid #666;
1378+
/*rtl:begin:source:rtl*/
1379+
padding: 10px 5px 10px 20px;
1380+
text-align: left;
1381+
/*rtl:end:source*/
1382+
width: 100%;
1383+
}
1384+
```
1385+
1386+
##### output
1387+
1388+
```css
1389+
.test {
1390+
color: #FFF;
1391+
width: 100%;
1392+
}
1393+
1394+
[dir="ltr"] .test {
1395+
border-left: 1px solid #666;
1396+
padding: 10px 20px 10px 5px;
1397+
text-align: right;
1398+
}
1399+
1400+
[dir="rtl"] .test {
1401+
border-right: 1px solid #666;
1402+
padding: 10px 5px 10px 20px;
1403+
text-align: left;
1404+
}
1405+
```
1406+
1407+
</p>
1408+
1409+
</details>
1410+
1411+
---
1412+
13151413
#### `/*rtl:raw:{CSS}*/`
13161414
13171415
<details><summary>Expand</summary>

src/@types/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,5 @@ export interface DeclarationsData {
9393
export interface ControlDirective {
9494
block?: string;
9595
directive: string;
96-
raw?: string;
96+
option?: string;
9797
}

src/constants/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const FLIP_PROPERTY_REGEXP = /(right|left)/i;
1515
export enum CONTROL_DIRECTIVE {
1616
IGNORE = 'ignore',
1717
RENAME = 'rename',
18+
SOURCE = 'source',
1819
RAW = 'raw'
1920
}
2021

src/parsers/atrules.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import { AtRulesObject, AtRulesStringMap, Source, ControlDirective } from '@type
44
import { AT_RULE_TYPE, RULE_TYPE, KEYFRAMES_NAME, CONTROL_DIRECTIVE } from '@constants';
55
import { store, initKeyframesData } from '@data/store';
66
import { walkContainer } from '@utilities/containers';
7-
import { isIgnoreDirectiveInsideAnIgnoreBlock, checkDirective } from '@utilities/directives';
7+
import {
8+
isIgnoreDirectiveInsideAnIgnoreBlock,
9+
checkDirective,
10+
getSourceDirectiveValue
11+
} from '@utilities/directives';
812
import { vendor } from '@utilities/vendor';
913
import { parseRules } from '@parsers/rules';
1014

@@ -49,7 +53,9 @@ export const parseAtRules = (css: Root): void => {
4953

5054
if (vendor.unprefixed(atRule.name) === KEYFRAMES_NAME) return;
5155

52-
parseRules(atRule);
56+
const sourceDirectiveValue = getSourceDirectiveValue(controlDirectives);
57+
58+
parseRules(atRule, sourceDirectiveValue);
5359

5460
}
5561
);
@@ -101,9 +107,33 @@ export const parseKeyFrames = (css: Root): void => {
101107
const atRuleParams = atRule.params;
102108
const ltr = `${atRuleParams}-${Source.ltr}`;
103109
const rtl = `${atRuleParams}-${Source.rtl}`;
104-
105-
atRule.params = source === Source.ltr ? ltr : rtl;
106-
atRuleFlipped.params = source === Source.ltr ? rtl : ltr;
110+
const sourceDirectiveValue = getSourceDirectiveValue(controlDirectives);
111+
112+
atRule.params = (
113+
(
114+
!sourceDirectiveValue &&
115+
source === Source.ltr
116+
) ||
117+
(
118+
sourceDirectiveValue &&
119+
sourceDirectiveValue === Source.ltr
120+
)
121+
)
122+
? ltr
123+
: rtl;
124+
125+
atRuleFlipped.params = (
126+
(
127+
!sourceDirectiveValue &&
128+
source === Source.ltr
129+
) ||
130+
(
131+
sourceDirectiveValue &&
132+
sourceDirectiveValue === Source.ltr
133+
)
134+
)
135+
? rtl
136+
: ltr;
107137

108138
store.keyframes.push({
109139
atRuleParams,

src/parsers/declarations.ts

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import {
99
CONTROL_DIRECTIVE
1010
} from '@constants';
1111
import { store } from '@data/store';
12-
import { isIgnoreDirectiveInsideAnIgnoreBlock, checkDirective } from '@utilities/directives';
12+
import {
13+
isIgnoreDirectiveInsideAnIgnoreBlock,
14+
checkDirective,
15+
getSourceDirectiveValue
16+
} from '@utilities/directives';
1317
import {
1418
declarations,
1519
allDeclarations,
@@ -28,11 +32,13 @@ import { vendor } from '@utilities/vendor';
2832
export const parseDeclarations = (
2933
rule: Rule,
3034
hasParentRule: boolean,
31-
autorenamed = false
35+
ruleSourceDirectiveValue: string,
36+
autorenamed = false
3237
): void => {
3338

3439
const {
3540
mode,
41+
source,
3642
safeBothPrefix,
3743
processUrls,
3844
useCalc,
@@ -64,14 +70,39 @@ export const parseDeclarations = (
6470
rule,
6571
[ DECLARATION_TYPE ],
6672
(comment: Comment, controlDirective: ControlDirective) => {
67-
73+
6874
cleanRuleRawsBefore(comment.next());
69-
comment.remove();
70-
71-
if (controlDirective.directive === CONTROL_DIRECTIVE.RAW && controlDirective.raw) {
72-
const root = postcss.parse(controlDirective.raw);
73-
if (mode === Mode.combined) {
74-
ruleFlippedSecond.append(root.nodes);
75+
comment.remove();
76+
77+
if (
78+
controlDirective.directive === CONTROL_DIRECTIVE.RAW &&
79+
controlDirective.option
80+
) {
81+
const sourceDirectiveValue = getSourceDirectiveValue(
82+
controlDirectives,
83+
ruleSourceDirectiveValue
84+
);
85+
const root = postcss.parse(controlDirective.option);
86+
if (
87+
(
88+
mode === Mode.combined &&
89+
!sourceDirectiveValue
90+
) ||
91+
(
92+
sourceDirectiveValue &&
93+
(
94+
(
95+
mode === Mode.combined &&
96+
sourceDirectiveValue === source
97+
) ||
98+
(
99+
mode !== Mode.combined &&
100+
sourceDirectiveValue !== source
101+
)
102+
)
103+
)
104+
) {
105+
ruleFlippedSecond.append(root.nodes);
75106
} else {
76107
ruleFlipped.append(root.nodes);
77108
}
@@ -121,6 +152,11 @@ export const parseDeclarations = (
121152
const isConflictedDeclaration = safeBothPrefix
122153
? !!allDeclarations[declPropUnprefixed]
123154
: false;
155+
const sourceDirectiveValue = getSourceDirectiveValue(
156+
controlDirectives,
157+
ruleSourceDirectiveValue
158+
);
159+
const normalFlip = !sourceDirectiveValue || sourceDirectiveValue === source;
124160

125161
if (
126162
!hasBeenOverriden &&
@@ -133,7 +169,7 @@ export const parseDeclarations = (
133169
}
134170

135171
if (isAnimation) {
136-
172+
137173
if(
138174
declProp === declFlippedProp &&
139175
declValue === declFlippedValue &&
@@ -142,12 +178,10 @@ export const parseDeclarations = (
142178
!store.keyframesRegExp.test(declValue)
143179
)
144180
) {
145-
146181
if (safeBothPrefix && !hasIgnoreDirectiveInRaws(decl)) {
147182
appendDeclarationToRule(decl, ruleSafe);
148183
deleteDeclarations.push(decl);
149-
}
150-
184+
}
151185
} else {
152186
const animationDeclValue = decl.value.replace(
153187
store.keyframesRegExp,
@@ -167,14 +201,23 @@ export const parseDeclarations = (
167201
const declClone = decl.clone();
168202
declClone.value = animationDeclValue;
169203
declCloneFlipped.value = animationDeclValueFlipped;
170-
ruleFlipped.append(declClone);
171-
ruleFlippedSecond.append(declCloneFlipped);
204+
if (normalFlip) {
205+
ruleFlipped.append(declClone);
206+
ruleFlippedSecond.append(declCloneFlipped);
207+
} else {
208+
ruleFlipped.append(declCloneFlipped);
209+
ruleFlippedSecond.append(declClone);
210+
}
172211
deleteDeclarations.push(decl);
173212
} else {
174213
const declCloneFlipped = decl.clone();
175214
decl.value = animationDeclValue;
176215
declCloneFlipped.value = animationDeclValueFlipped;
177-
ruleFlipped.append(declCloneFlipped);
216+
if (normalFlip) {
217+
ruleFlipped.append(declCloneFlipped);
218+
} else {
219+
ruleFlippedSecond.append(declCloneFlipped);
220+
}
178221
if (safeBothPrefix) {
179222
appendDeclarationToRule(decl, ruleSafe);
180223
deleteDeclarations.push(decl);
@@ -203,21 +246,34 @@ export const parseDeclarations = (
203246
}
204247

205248
if (mode === Mode.combined) {
206-
appendDeclarationToRule(decl, ruleFlipped);
207-
ruleFlippedSecond.append(declFlipped);
249+
if (normalFlip) {
250+
appendDeclarationToRule(decl, ruleFlipped);
251+
ruleFlippedSecond.append(declFlipped);
252+
} else {
253+
appendDeclarationToRule(decl, ruleFlippedSecond);
254+
ruleFlipped.append(declFlipped);
255+
}
208256
deleteDeclarations.push(decl);
209257
} else {
210258
if (FLIP_PROPERTY_REGEXP.test(decl.prop) && !declarationHashMap[declFlipped.prop]) {
211259
const declClone = decl.clone();
212260
/* istanbul ignore next */
213261
declClone.value = initialValues[decl.prop] || 'unset';
214-
ruleFlipped.append(declClone);
262+
if (normalFlip) {
263+
ruleFlipped.append(declClone);
264+
} else {
265+
ruleFlippedSecond.append(declClone);
266+
}
215267
}
216268
if (isConflictedDeclaration && !hasIgnoreDirectiveInRaws(decl)) {
217269
appendDeclarationToRule(decl, ruleSafe);
218270
deleteDeclarations.push(decl);
219271
}
220-
ruleFlipped.append(declFlipped);
272+
if (normalFlip) {
273+
ruleFlipped.append(declFlipped);
274+
} else {
275+
ruleFlippedSecond.append(declFlipped);
276+
}
221277
}
222278

223279
declarationsProps.push(declPropUnprefixed);

0 commit comments

Comments
 (0)