Skip to content

Commit b74bbe5

Browse files
committed
fix(html_extractor): correct handling of camelCased attributes
fix dart-archive#1047 closes dart-archive#1301
1 parent cdde8c4 commit b74bbe5

File tree

3 files changed

+47
-17
lines changed

3 files changed

+47
-17
lines changed

lib/tools/common.dart

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
library angular.tools.common;
22

3+
import 'dart:collection';
4+
35
class DirectiveInfo {
46
String selector;
57
String template;
68
List<String> expressionAttrs = <String>[];
79
List<String> expressions = <String>[];
810
DirectiveInfo([this.selector, this.expressionAttrs, this.expressions]) {
9-
if (expressionAttrs == null) {
10-
expressionAttrs = <String>[];
11-
}
12-
if (expressions == null) {
13-
expressions = <String>[];
14-
}
11+
expressionAttrs = expressionAttrs == null ?
12+
new _AttributeList() :
13+
new _AttributeList()..addAll(expressionAttrs);
14+
15+
if (expressions == null) expressions = <String>[];
1516
}
1617
}
1718

@@ -42,3 +43,29 @@ class DirectiveMetadata {
4243
}
4344
}
4445

46+
/**
47+
* Extends list to always returned lowercase attribute name:
48+
*
49+
* var l = new _AttributeList();
50+
* l.add('fooBar');
51+
* print(l[0]); // "foobar"
52+
*
53+
* It helps working with html5lib `Node` class which also lowercase attribute names.
54+
*
55+
* Note: attribute names are case-insensitive in HTML.
56+
*/
57+
class _AttributeList extends ListBase<String> {
58+
final List<String> _attributes = [];
59+
60+
void set length(int len) {
61+
_attributes.length = len;
62+
}
63+
64+
int get length => _attributes.length;
65+
66+
String operator [](int index) => _attributes[index].toLowerCase();
67+
68+
void operator []=(int index, String value) {
69+
_attributes[index] = value;
70+
}
71+
}

lib/tools/html_extractor.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,12 @@ class HtmlExpressionExtractor {
4949
});
5050
}
5151
if (matchesNode(node, r'[ng-repeat]')) {
52-
var expr = _NG_REPEAT_SYNTAX.
53-
firstMatch(node.attributes['ng-repeat']).group(2);
52+
var expr = _NG_REPEAT_SYNTAX.firstMatch(node.attributes['ng-repeat']).group(2);
5453
expressions.add(expr);
5554
}
5655

5756
for (DirectiveInfo directiveInfo in directiveInfos) {
58-
if (directiveInfo.selector != null &&
59-
matchesNode(node, directiveInfo.selector)) {
57+
if (directiveInfo.selector != null && matchesNode(node, directiveInfo.selector)) {
6058
directiveInfo.expressionAttrs.forEach((attr) {
6159
if (node.attributes[attr] != null && attr != 'ng-repeat') {
6260
expressions.add(node.attributes[attr]);

test/tools/html_extractor_spec.dart

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,23 @@ void main() {
6161
});
6262

6363
it('should extract expressions from expression attributes', () {
64-
var ioService = new MockIoService({
65-
'foo.html': r'''
66-
<foo bar="ctrl.baz"></foo>
67-
'''
68-
});
64+
var ioService = new MockIoService({'foo.html': r'<foo bar="ctrl.baz"></foo>'});
6965

7066
var extractor = new HtmlExpressionExtractor([
7167
new DirectiveInfo('foo', ['bar'])
7268
]);
7369
extractor.crawl('/', ioService);
74-
expect(extractor.expressions.toList()..sort(),
75-
equals(['ctrl.baz']));
70+
expect(extractor.expressions.toList()).toEqual(['ctrl.baz']);
71+
});
72+
73+
it('should extract expressions from expression attributes for camelCased attributes', () {
74+
var ioService = new MockIoService({'foo.html': r'<foo fooBar="ctrl.baz"></foo>'});
75+
76+
var extractor = new HtmlExpressionExtractor([
77+
new DirectiveInfo('foo', ['fooBar'])
78+
]);
79+
extractor.crawl('/', ioService);
80+
expect(extractor.expressions.toList()).toEqual(['ctrl.baz']);
7681
});
7782

7883
it('should ignore ng-repeat while extracting attribute expressions', () {

0 commit comments

Comments
 (0)