Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
Split the the output generated by Css Mirroring into common, nativeDi…
Browse files Browse the repository at this point in the history
…r and flippedDir subparts.
  • Loading branch information
MonamAgarwal committed May 25, 2016
1 parent ccbf618 commit 2873219
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 59 deletions.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -20,7 +20,8 @@ most of them are disabled or optimized for speed with `pub serve` in debug mode.
- Given `foo { color: blue; float: left }`, it generates:

```css
foo { color: blue; float: left }
foo { color: blue; }
:host-context([dir="ltr"]) foo { float: left }
:host-context([dir="rtl"]) foo { float: right }
```

Expand Down
44 changes: 32 additions & 12 deletions lib/src/css_mirroring/bidi_css_generator.dart
Expand Up @@ -22,7 +22,7 @@ import 'package:source_maps/refactor.dart' show TextEditTransaction;
import 'package:source_span/source_span.dart' show SourceFile;

import 'buffered_transaction.dart';
import 'css_utils.dart' show Direction, flipDirection;
import 'css_utils.dart' show Direction;
import 'directive_processors.dart' show editFlippedDirectiveWithNestedRuleSets;
import 'mirrored_entities.dart';
import 'rulesets_processor.dart' show editFlippedRuleSet;
Expand All @@ -43,35 +43,55 @@ typedef Future<String> CssFlipper(String inputCss);
/// See BidirectionalCss.md for more details.
Future<String> bidirectionalizeCss(String originalCss, CssFlipper cssFlipper,
[Direction nativeDirection = Direction.ltr]) async {
var flippedDirection = flipDirection(nativeDirection);
var flippedCss = await cssFlipper(originalCss);

var topLevelEntities = new MirroredEntities(originalCss,
parse(originalCss).topLevels, flippedCss, parse(flippedCss).topLevels);

var trans =
var flippedDirTrans =
new TextEditTransaction(flippedCss, new SourceFile(flippedCss, url: ''));
var bufferedTrans = new BufferedTransaction(trans);
var bufferedFlippedDirTrans = new BufferedTransaction(flippedDirTrans);

var nativeDirTrans = new TextEditTransaction(
originalCss, new SourceFile(originalCss, url: ''));
var bufferedNativeDirTrans = new BufferedTransaction(nativeDirTrans);

var commonTrans = new TextEditTransaction(
originalCss, new SourceFile(originalCss, url: ''));
var bufferedCommonTrans = new BufferedTransaction(commonTrans);

topLevelEntities.forEach((MirroredEntity<TreeNode> entity) {
if (entity.isRuleSet) {
editFlippedRuleSet(entity, flippedDirection, bufferedTrans);
editFlippedRuleSet(entity, nativeDirection, bufferedCommonTrans,
bufferedNativeDirTrans, bufferedFlippedDirTrans);
} else if (entity.hasNestedRuleSets) {
editFlippedDirectiveWithNestedRuleSets(
entity,
entity.getChildren((d) => d.rulesets),
flippedDirection,
bufferedTrans);
nativeDirection,
bufferedCommonTrans,
bufferedNativeDirTrans,
bufferedFlippedDirTrans);
} else if (entity.isDirectionInsensitiveDirective) {
entity.flipped.remove(bufferedTrans);
entity.original.remove(bufferedNativeDirTrans);
entity.flipped.remove(bufferedFlippedDirTrans);
} else {
throw new StateError('Node type not handled: $entity');
}
});
bufferedTrans.commit();
bufferedCommonTrans.commit();
bufferedNativeDirTrans.commit();
bufferedFlippedDirTrans.commit();

var resultCss = _cleanupCss(originalCss);
var taggedFlippedCss = _cleanupCss((trans.commit()..build('')).text);
if (taggedFlippedCss.trim().isNotEmpty) resultCss += "\n" + taggedFlippedCss;
var resultCss = _cleanupCss((commonTrans.commit()..build('')).text);
var taggedOriginalDirCss =
_cleanupCss((nativeDirTrans.commit()..build('')).text);
var taggedFlippedDirCss =
_cleanupCss((flippedDirTrans.commit()..build('')).text);
if (taggedOriginalDirCss.trim().isNotEmpty) resultCss +=
"\n" + taggedOriginalDirCss;
if (taggedFlippedDirCss.trim().isNotEmpty) resultCss +=
"\n" + taggedFlippedDirCss;
return resultCss;
}

Expand Down
36 changes: 27 additions & 9 deletions lib/src/css_mirroring/directive_processors.dart
Expand Up @@ -26,18 +26,36 @@ import 'rulesets_processor.dart' show editFlippedRuleSet, RemovalResult;
editFlippedDirectiveWithNestedRuleSets(
MirroredEntity<Directive> directive,
MirroredEntities<RuleSet> nestedRuleSets,
Direction flippedDirection,
BufferedTransaction trans) {
var subTransaction = trans.createSubTransaction();
bool removedAll = true;
Direction nativeDirection,
BufferedTransaction commonTrans,
BufferedTransaction nativeDirTrans,
BufferedTransaction flippedDirTrans) {
final commonSubTransaction = commonTrans.createSubTransaction();
final nativeDirSubTransaction = nativeDirTrans.createSubTransaction();
final flippedDirSubTransaction = flippedDirTrans.createSubTransaction();
int removedRulesCount = 0;
nestedRuleSets.forEach((MirroredEntity<RuleSet> ruleSet) {
var result = editFlippedRuleSet(ruleSet, flippedDirection, subTransaction);
if (result != RemovalResult.removedAll) removedAll = false;
var result = editFlippedRuleSet(
ruleSet,
nativeDirection,
commonSubTransaction,
nativeDirSubTransaction,
flippedDirSubTransaction);
if (result) {
removedRulesCount++;
}
});

if (removedAll) {
directive.flipped.remove(trans);
if (removedRulesCount == 0) {
directive.original.remove(nativeDirTrans);
directive.flipped.remove(flippedDirTrans);
} else {
subTransaction.commit();
if (removedRulesCount == nestedRuleSets.length) {
directive.original.remove(commonTrans);
} else {
commonSubTransaction.commit();
}
nativeDirSubTransaction.commit();
flippedDirSubTransaction.commit();
}
}
22 changes: 11 additions & 11 deletions lib/src/css_mirroring/mirrored_entities.dart
Expand Up @@ -23,46 +23,46 @@ class MirroredEntity<T extends TreeNode> {
final int index;
final MirroredEntity parent;

Entity<T> _original;
Entity<T> original;
Entity<T> flipped;

MirroredEntity(this._entities, this.index, this.parent) {
_original = new Entity<T>(_entities._originalSource,
_entities._originalEntities, index, parent?._original);
original = new Entity<T>(_entities._originalSource,
_entities._originalEntities, index, parent?.original);

flipped = new Entity<T>(_entities._flippedSource,
_entities._flippedEntities, index, parent?.flipped);

checkState(_original.runtimeType == flipped.runtimeType,
checkState(original.runtimeType == flipped.runtimeType,
message: () => 'Mismatching entity types: '
'original is ${_original.runtimeType}, '
'original is ${original.runtimeType}, '
'flipped is ${flipped.runtimeType}');
}

bool get hasSameTextInBothVersions =>
_original.value.span.text == flipped.value.span.text;
original.value.span.text == flipped.value.span.text;

bool get isDeclaration => _original.value is Declaration;
bool get isRuleSet => _original.value is RuleSet;
bool get isDeclaration => original.value is Declaration;
bool get isRuleSet => original.value is RuleSet;

bool get isDirectionInsensitiveDirective {
var node = _original.value;
var node = original.value;
return node is CharsetDirective ||
node is FontFaceDirective ||
node is ImportDirective ||
node is NamespaceDirective;
}

bool get hasNestedRuleSets {
var node = _original.value;
var node = original.value;
return node is MediaDirective || node is HostDirective;
}

MirroredEntities/*<C>*/ getChildren/*<C>*/(
List/*<C>*/ getEntityChildren(T _)) {
return new MirroredEntities(
_entities._originalSource,
getEntityChildren(_original.value),
getEntityChildren(original.value),
_entities._flippedSource,
getEntityChildren(flipped.value),
parent: this);
Expand Down
61 changes: 44 additions & 17 deletions lib/src/css_mirroring/rulesets_processor.dart
Expand Up @@ -21,42 +21,69 @@ import 'css_utils.dart' show Direction;
import 'entity.dart';
import 'mirrored_entities.dart';
import '../utils/enum_parser.dart';

enum RemovalResult { removedSome, removedAll }
import 'css_utils.dart'
show isDirectionInsensitive, hasNestedRuleSets, Direction, flipDirection;

/// Returns true if the [RuleSet] was completely removed, false otherwise.
RemovalResult editFlippedRuleSet(MirroredEntity<RuleSet> mirroredRuleSet,
Direction flippedDirection, BufferedTransaction trans) {
final subTransaction = trans.createSubTransaction();
bool editFlippedRuleSet(
MirroredEntity<RuleSet> mirroredRuleSet,
Direction nativeDirection,
BufferedTransaction commonTrans,
BufferedTransaction nativeDirTrans,
BufferedTransaction flippedDirTrans) {
final commonSubTransaction = commonTrans.createSubTransaction();
final nativeDirSubTransaction = nativeDirTrans.createSubTransaction();
final flippedDirSubTransaction = flippedDirTrans.createSubTransaction();

MirroredEntities<Declaration> mirroredDeclarations = mirroredRuleSet
.getChildren((RuleSet r) => r.declarationGroup.declarations);

/// Iterate over Declarations in RuleSet and store start and end points of
/// declarations to be removed.
var removedCount = 0;
var commonCount = 0;
var flippedCount = 0;
mirroredDeclarations.forEach((MirroredEntity<Declaration> decl) {
checkState(decl.flipped.value is Declaration,
message: () => 'Expected a declaration, got $decl');

if (decl.hasSameTextInBothVersions) {
decl.flipped.remove(subTransaction);
removedCount++;
decl.original.remove(nativeDirSubTransaction);
decl.flipped.remove(flippedDirSubTransaction);
commonCount++;
} else {
decl.original.remove(commonSubTransaction);
flippedCount++;
}
});

if (removedCount == mirroredDeclarations.length) {
mirroredRuleSet.flipped.remove(trans);
return RemovalResult.removedAll;
} else {
assert(commonCount + flippedCount == mirroredDeclarations.length);

bool removalResult = false;
if (flippedCount > 0) {

if (commonCount == 0) {
mirroredRuleSet.original.remove(commonTrans);
removalResult = true;
} else {
commonSubTransaction.commit();
}

/// Add direction attribute to RuleId for direction-specific RuleSet.
var dir = enumName(flippedDirection);
prependToEachSelector(
mirroredRuleSet.flipped, trans, ':host-context([dir="$dir"]) ');
var flippedDirection = flipDirection(nativeDirection);

prependToEachSelector(mirroredRuleSet.original, nativeDirTrans,
':host-context([dir="${enumName(nativeDirection)}"]) ');
prependToEachSelector(mirroredRuleSet.flipped, flippedDirTrans,
':host-context([dir="${enumName(flippedDirection)}"]) ');

subTransaction.commit();
return RemovalResult.removedSome;
flippedDirSubTransaction.commit();
nativeDirSubTransaction.commit();
} else {
mirroredRuleSet.flipped.remove(flippedDirTrans);
mirroredRuleSet.original.remove(nativeDirTrans);
}

return removalResult;
}

void prependToEachSelector(
Expand Down
34 changes: 25 additions & 9 deletions test/css_mirroring/transformer_test.dart
Expand Up @@ -43,6 +43,9 @@ void main() {
'a|foo2_unmatched_css_url.css': r'''
absent-element {
color: blue;
}
:host-context([dir="ltr"]) absent-element {
float: right;
}
Expand Down Expand Up @@ -95,11 +98,12 @@ void main() {
'''
}, {
'a|foo2_unmatched_css_url.css': r'''
absent-element {
:host-context([dir="ltr"]) absent-element {
float: left;
margin-left: 100px;
}
.usedclass {
:host-context([dir="ltr"]) .usedclass {
padding: right;
text-align: left;
}
Expand Down Expand Up @@ -156,17 +160,24 @@ void main() {
'a|foo2_unmatched_css_url.css': r'''
li + li {
color: blue;
float: right;
}
}
a ~ a {
color: purple;
margin-left: 3em;
}
}
li > a {
color: orange;
margin-left: 4em; width: 10px;
width: 10px;
}
:host-context([dir="ltr"]) li + li {
float: right;
}
:host-context([dir="ltr"]) a ~ a {
margin-left: 3em;
}
:host-context([dir="ltr"]) li > a {
margin-left: 4em; }
:host-context([dir="rtl"]) li + li {
float: left;
}
Expand Down Expand Up @@ -208,8 +219,9 @@ void main() {
'''
}, {
'a|foo2_unmatched_css_url.css': r'''
@media screen and (min-width: 401px) {
body { margin-left: 13px }
:host-context([dir="ltr"]) body { margin-left: 13px }
}
@media screen and (min-width: 401px) {
Expand All @@ -226,7 +238,8 @@ void main() {
'''
}, {
'a|foo2_unmatched_css_url.css': r'''
@host { :scope { padding: left; } }
@host { :host-context([dir="ltr"]) :scope { padding: left; } }
@host { :host-context([dir="rtl"]) :scope { padding: right; } }
'''
Expand All @@ -243,6 +256,9 @@ void main() {
'a|foo2_multiple_selectors_css_url.css': r'''
.child1, .child2 {
position: relative;
}
:host-context([dir="ltr"]) .child1, :host-context([dir="ltr"]) .child2 {
margin-right: 10px;
}
Expand Down

0 comments on commit 2873219

Please sign in to comment.