Skip to content

Commit 357fd93

Browse files
committed
d272f96 feat(i18n): implement an i18n-aware html parser
1 parent 6b87892 commit 357fd93

17 files changed

Lines changed: 1387 additions & 602 deletions

‎BUILD_INFO‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
Thu Mar 24 20:48:44 UTC 2016
2-
aa966f5de2efbaa9b1dc55836b0006315f010576
1+
Thu Mar 24 20:52:26 UTC 2016
2+
d272f96e23f379e1b565435b3af010138e710ab9

‎_analyzer.dart‎

Lines changed: 323 additions & 320 deletions
Large diffs are not rendered by default.

‎lib/src/compiler/html_ast.dart‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ class HtmlElementAst implements HtmlAst {
3232
List<HtmlAttrAst> attrs;
3333
List<HtmlAst> children;
3434
ParseSourceSpan sourceSpan;
35-
HtmlElementAst(this.name, this.attrs, this.children, this.sourceSpan) {}
35+
ParseSourceSpan startSourceSpan;
36+
ParseSourceSpan endSourceSpan;
37+
HtmlElementAst(this.name, this.attrs, this.children, this.sourceSpan,
38+
this.startSourceSpan, this.endSourceSpan) {}
3639
dynamic visit(HtmlAstVisitor visitor, dynamic context) {
3740
return visitor.visitElement(this, context);
3841
}

‎lib/src/compiler/html_parser.dart‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,12 @@ class TreeBuilder {
162162
selfClosing = false;
163163
}
164164
var end = this.peek.sourceSpan.start;
165-
var el = new HtmlElementAst(fullName, attrs, [],
166-
new ParseSourceSpan(startTagToken.sourceSpan.start, end));
165+
var span = new ParseSourceSpan(startTagToken.sourceSpan.start, end);
166+
var el = new HtmlElementAst(fullName, attrs, [], span, span, null);
167167
this._pushElement(el);
168168
if (selfClosing) {
169169
this._popElement(fullName);
170+
el.endSourceSpan = span;
170171
}
171172
}
172173

@@ -180,8 +181,8 @@ class TreeBuilder {
180181
var tagDef = getHtmlTagDefinition(el.name);
181182
var parentEl = this._getParentElement();
182183
if (tagDef.requireExtraParent(isPresent(parentEl) ? parentEl.name : null)) {
183-
var newParent =
184-
new HtmlElementAst(tagDef.parentToAdd, [], [el], el.sourceSpan);
184+
var newParent = new HtmlElementAst(tagDef.parentToAdd, [], [el],
185+
el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
185186
this._addToParent(newParent);
186187
this.elementStack.add(newParent);
187188
this.elementStack.add(el);
@@ -194,6 +195,7 @@ class TreeBuilder {
194195
_consumeEndTag(HtmlToken endTagToken) {
195196
var fullName = getElementFullName(
196197
endTagToken.parts[0], endTagToken.parts[1], this._getParentElement());
198+
this._getParentElement().endSourceSpan = endTagToken.sourceSpan;
197199
if (getHtmlTagDefinition(fullName).isVoid) {
198200
this.errors.add(HtmlTreeError.create(fullName, endTagToken.sourceSpan,
199201
'''Void elements do not have end tags "${ endTagToken . parts [ 1 ]}"'''));

‎lib/src/compiler/legacy_template.dart‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ class LegacyHtmlAstTransformer implements HtmlAstVisitor {
5151
var attrs = ast.attrs.map((attr) => attr.visit(this, null)).toList();
5252
var children =
5353
ast.children.map((child) => child.visit(this, null)).toList();
54-
return new HtmlElementAst(ast.name, attrs, children, ast.sourceSpan);
54+
return new HtmlElementAst(ast.name, attrs, children, ast.sourceSpan,
55+
ast.startSourceSpan, ast.endSourceSpan);
5556
}
5657

5758
HtmlAttrAst visitAttr(HtmlAttrAst originalAst, dynamic context) {

‎lib/src/core/change_detection/parser/parser.dart‎

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ class ParseException extends BaseException {
6464
}
6565
}
6666

67+
class SplitInterpolation {
68+
List<String> strings;
69+
List<String> expressions;
70+
SplitInterpolation(this.strings, this.expressions) {}
71+
}
72+
6773
@Injectable()
6874
class Parser {
6975
Lexer _lexer;
@@ -128,6 +134,20 @@ class Parser {
128134
}
129135

130136
ASTWithSource parseInterpolation(String input, dynamic location) {
137+
var split = this.splitInterpolation(input, location);
138+
if (split == null) return null;
139+
var expressions = [];
140+
for (var i = 0; i < split.expressions.length; ++i) {
141+
var tokens = this._lexer.tokenize(split.expressions[i]);
142+
var ast = new _ParseAST(input, location, tokens, this._reflector, false)
143+
.parseChain();
144+
expressions.add(ast);
145+
}
146+
return new ASTWithSource(
147+
new Interpolation(split.strings, expressions), input, location);
148+
}
149+
150+
SplitInterpolation splitInterpolation(String input, String location) {
131151
var parts = StringWrapper.split(input, INTERPOLATION_REGEXP);
132152
if (parts.length <= 1) {
133153
return null;
@@ -140,10 +160,7 @@ class Parser {
140160
// fixed string
141161
strings.add(part);
142162
} else if (part.trim().length > 0) {
143-
var tokens = this._lexer.tokenize(part);
144-
var ast = new _ParseAST(input, location, tokens, this._reflector, false)
145-
.parseChain();
146-
expressions.add(ast);
163+
expressions.add(part);
147164
} else {
148165
throw new ParseException(
149166
"Blank expressions are not allowed in interpolated strings",
@@ -152,8 +169,7 @@ class Parser {
152169
location);
153170
}
154171
}
155-
return new ASTWithSource(
156-
new Interpolation(strings, expressions), input, location);
172+
return new SplitInterpolation(strings, expressions);
157173
}
158174

159175
ASTWithSource wrapLiteralPrimitive(String input, dynamic location) {

‎lib/src/facade/collection.dart‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,14 @@ class ListWrapper {
242242
static bool isImmutable(List l) {
243243
return l is UnmodifiableListView;
244244
}
245+
246+
static List flatten(List l) {
247+
final res = [];
248+
l.forEach((item) {
249+
res.addAll(item);
250+
});
251+
return res;
252+
}
245253
}
246254

247255
bool isListLikeIterable(obj) => obj is Iterable;

‎lib/src/facade/lang.dart‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,20 @@ class RegExpWrapper {
215215
static Iterator<Match> matcher(RegExp regExp, String input) {
216216
return regExp.allMatches(input).iterator;
217217
}
218+
219+
static String replaceAll(RegExp regExp, String input, Function replace) {
220+
final m = RegExpWrapper.matcher(regExp, input);
221+
var res = "";
222+
var prev = 0;
223+
while (m.moveNext()) {
224+
var c = m.current;
225+
res += input.substring(prev, c.start);
226+
res += replace(c);
227+
prev = c.start + c[0].length;
228+
}
229+
res += input.substring(prev);
230+
return res;
231+
}
218232
}
219233

220234
class RegExpMatcherWrapper {

0 commit comments

Comments
 (0)