mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-27 04:34:59 +01:00
Make transitive @extend work.
Loops are still kind of iffy.
This commit is contained in:
parent
9d2d8652dc
commit
9f21fa943e
@ -26,13 +26,19 @@ class Extender {
|
|||||||
|
|
||||||
static SelectorList extend(
|
static SelectorList extend(
|
||||||
SelectorList selector, SelectorList source, SimpleSelector target) =>
|
SelectorList selector, SelectorList source, SimpleSelector target) =>
|
||||||
new Extender()._extendList(
|
new Extender()._extendList(selector, {
|
||||||
selector, {target: new Set()..add(new ExtendSource(source, null))});
|
target: new Set()
|
||||||
|
..add(new ExtendSource(new CssValue(source, null), null))
|
||||||
|
});
|
||||||
|
|
||||||
static SelectorList replace(
|
static SelectorList replace(
|
||||||
SelectorList selector, SelectorList source, SimpleSelector target) =>
|
SelectorList selector, SelectorList source, SimpleSelector target) =>
|
||||||
new Extender()._extendList(
|
new Extender()._extendList(
|
||||||
selector, {target: new Set()..add(new ExtendSource(source, null))},
|
selector,
|
||||||
|
{
|
||||||
|
target: new Set()
|
||||||
|
..add(new ExtendSource(new CssValue(source, null), null))
|
||||||
|
},
|
||||||
replace: true);
|
replace: true);
|
||||||
|
|
||||||
CssStyleRule addSelector(CssValue<SelectorList> selector, FileSpan span) {
|
CssStyleRule addSelector(CssValue<SelectorList> selector, FileSpan span) {
|
||||||
@ -72,19 +78,18 @@ class Extender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addExtension(
|
void addExtension(CssValue<SelectorList> extender, SimpleSelector target,
|
||||||
SelectorList sourceList, SimpleSelector target, ExtendRule extend) {
|
ExtendRule extend) {
|
||||||
var source = new ExtendSource(sourceList, extend.span);
|
var source = new ExtendSource(extender, extend.span);
|
||||||
source.isUsed = extend.isOptional;
|
source.isUsed = extend.isOptional;
|
||||||
_extensions.putIfAbsent(target, () => new Set()).add(source);
|
_extensions.putIfAbsent(target, () => new Set()).add(source);
|
||||||
|
|
||||||
var rules = _selectors[target];
|
var rules = _selectors[target];
|
||||||
if (rules == null) return;
|
if (rules == null) return;
|
||||||
|
|
||||||
var extensions = {target: new Set()..add(source)};
|
var extensions = {target: new Set()..add(source)};
|
||||||
for (var rule in rules) {
|
for (var rule in rules.toList()) {
|
||||||
var list = rule.selector.value;
|
rule.selector.value = _extendList(rule.selector.value, extensions);
|
||||||
rule.selector.value = _extendList(list, extensions);
|
_registerSelector(rule.selector.value, rule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +168,7 @@ class Extender {
|
|||||||
}
|
}
|
||||||
if (!changed) return null;
|
if (!changed) return null;
|
||||||
|
|
||||||
return _trim(paths(extendedNotExpanded).map((path) {
|
var result = _trim(paths(extendedNotExpanded).map((path) {
|
||||||
return weave(path.map((complex) => complex.components).toList())
|
return weave(path.map((complex) => complex.components).toList())
|
||||||
.map((outputComplex) {
|
.map((outputComplex) {
|
||||||
return new ComplexSelector(outputComplex,
|
return new ComplexSelector(outputComplex,
|
||||||
@ -171,6 +176,7 @@ class Extender {
|
|||||||
path.any((inputComplex) => inputComplex.lineBreak));
|
path.any((inputComplex) => inputComplex.lineBreak));
|
||||||
});
|
});
|
||||||
}).toList());
|
}).toList());
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ComplexSelector> _extendCompound(CompoundSelector compound,
|
List<ComplexSelector> _extendCompound(CompoundSelector compound,
|
||||||
@ -203,9 +209,9 @@ class Extender {
|
|||||||
new List<SimpleSelector>(compound.components.length - 1);
|
new List<SimpleSelector>(compound.components.length - 1);
|
||||||
compoundWithoutSimple.setRange(0, i, compound.components);
|
compoundWithoutSimple.setRange(0, i, compound.components);
|
||||||
compoundWithoutSimple.setRange(
|
compoundWithoutSimple.setRange(
|
||||||
i, compound.components.length - 1, compound.components, i);
|
i, compound.components.length - 1, compound.components, i + 1);
|
||||||
for (var source in sources) {
|
for (var source in sources) {
|
||||||
for (var complex in source.extender.components) {
|
for (var complex in source.extender.value.components) {
|
||||||
var extenderBase = complex.components.last as CompoundSelector;
|
var extenderBase = complex.components.last as CompoundSelector;
|
||||||
var unified = compoundWithoutSimple.isEmpty
|
var unified = compoundWithoutSimple.isEmpty
|
||||||
? extenderBase
|
? extenderBase
|
||||||
@ -246,7 +252,6 @@ class Extender {
|
|||||||
List<PseudoSelector> _extendPseudo(
|
List<PseudoSelector> _extendPseudo(
|
||||||
PseudoSelector pseudo, Map<SimpleSelector, Set<ExtendSource>> extensions,
|
PseudoSelector pseudo, Map<SimpleSelector, Set<ExtendSource>> extensions,
|
||||||
{bool replace: false}) {
|
{bool replace: false}) {
|
||||||
// TODO: avoid recursive loops when extending.
|
|
||||||
var extended = _extendList(pseudo.selector, extensions, replace: replace);
|
var extended = _extendList(pseudo.selector, extensions, replace: replace);
|
||||||
if (extended == null) return null;
|
if (extended == null) return null;
|
||||||
|
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
import 'package:source_span/source_span.dart';
|
import 'package:source_span/source_span.dart';
|
||||||
|
|
||||||
|
import '../ast/css.dart';
|
||||||
import '../ast/selector.dart';
|
import '../ast/selector.dart';
|
||||||
|
|
||||||
class ExtendSource {
|
class ExtendSource {
|
||||||
final SelectorList extender;
|
final CssValue<SelectorList> extender;
|
||||||
|
|
||||||
final FileSpan span;
|
final FileSpan span;
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
|
|||||||
// TODO: recontextualize parse errors.
|
// TODO: recontextualize parse errors.
|
||||||
// TODO: disallow parent selectors.
|
// TODO: disallow parent selectors.
|
||||||
var target = new SimpleSelector.parse(targetText.value.trim());
|
var target = new SimpleSelector.parse(targetText.value.trim());
|
||||||
_extender.addExtension(_selector.value, target, node);
|
_extender.addExtension(_selector, target, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitAtRule(AtRule node) {
|
void visitAtRule(AtRule node) {
|
||||||
@ -498,8 +498,9 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
|
|||||||
var selector =
|
var selector =
|
||||||
new CssValue<SelectorList>(parsedSelector, node.selector.span);
|
new CssValue<SelectorList>(parsedSelector, node.selector.span);
|
||||||
|
|
||||||
_withParent(_extender.addSelector(selector, node.span), () {
|
var rule = _extender.addSelector(selector, node.span);
|
||||||
_withSelector(selector, () {
|
_withParent(rule, () {
|
||||||
|
_withSelector(rule.selector, () {
|
||||||
for (var child in node.children) {
|
for (var child in node.children) {
|
||||||
child.accept(this);
|
child.accept(this);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user