Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: pkg/template_binding/lib/src/mustache_tokens.dart

Issue 132403010: big update to observe, template_binding, polymer (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library template_binding.src.mustache_tokens;
6
7 import 'package:observe/observe.dart';
8 import 'package:template_binding/template_binding.dart';
9
10 /**
11 * Represents a set of parsed tokens from a {{ mustache binding expression }}.
12 * This can be created by calling [parse].
13 *
14 * For performance reasons the data is stored in one linear array in [_tokens].
15 * This class wraps that array and provides accessors in an attempt to make the
16 * pattern easier to understand. See [length] and [getText] for example.
17 */
18 class MustacheTokens {
19 // Constants for indexing into the exploded structs in [_tokens] .
20 static const _TOKEN_TEXT = 0;
21 static const _TOKEN_ONETIME = 1;
22 static const _TOKEN_PATH = 2;
23 static const _TOKEN_PREPAREFN = 3;
24 static const _TOKEN_SIZE = 4;
25
26 // There is 1 extra entry for the end text.
27 static const _TOKEN_ENDTEXT = 1;
28
29 bool get hasOnePath => _tokens.length == _TOKEN_SIZE + _TOKEN_ENDTEXT;
30 bool get isSimplePath => hasOnePath &&
31 _tokens[_TOKEN_TEXT] == '' && _tokens[_TOKEN_SIZE + _TOKEN_TEXT] == '';
32
33 /**
34 * [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one
35 * mustache.
36 */
37 final List _tokens;
38
39 final bool onlyOneTime;
40
41 // Dart note: I think this is cached in JavaScript to avoid an extra
42 // allocation per template instance. Seems reasonable, so we do the same.
43 Function _combinator;
44 Function get combinator => _combinator;
45
46 MustacheTokens._(this._tokens, this.onlyOneTime) {
47 // Should be: [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+].
48 assert((_tokens.length - _TOKEN_ENDTEXT) % _TOKEN_SIZE == 0);
49
50 _combinator = hasOnePath ? _singleCombinator : _listCombinator;
51 }
52
53 int get length => _tokens.length ~/ _TOKEN_SIZE;
54
55 /**
56 * Gets the [i]th text entry. Note that [length] can be passed to get the
57 * final text entry.
58 */
59 String getText(int i) => _tokens[i * _TOKEN_SIZE + _TOKEN_TEXT];
60
61 /** Gets the oneTime flag for the [i]th token. */
62 bool getOneTime(int i) => _tokens[i * _TOKEN_SIZE + _TOKEN_ONETIME];
63
64 /** Gets the path for the [i]th token. */
65 PropertyPath getPath(int i) => _tokens[i * _TOKEN_SIZE + _TOKEN_PATH];
66
67 /** Gets the prepareBinding function for the [i]th token. */
68 Function getPrepareBinding(int i) =>
69 _tokens[i * _TOKEN_SIZE + _TOKEN_PREPAREFN];
70
71
72 /**
73 * Parses {{ mustache }} bindings.
74 *
75 * Returns null if there are no matches. Otherwise returns the parsed tokens.
76 */
77 static MustacheTokens parse(String s, String name, node,
78 BindingDelegate delegate) {
79 if (s == null || s.isEmpty) return null;
80
81 var tokens = null;
82 var length = s.length;
83 var lastIndex = 0;
84 var onlyOneTime = true;
85 while (lastIndex < length) {
86 var startIndex = s.indexOf('{{', lastIndex);
87 var oneTimeStart = s.indexOf('[[', lastIndex);
88 var oneTime = false;
89 var terminator = '}}';
90
91 if (oneTimeStart >= 0 &&
92 (startIndex < 0 || oneTimeStart < startIndex)) {
93 startIndex = oneTimeStart;
94 oneTime = true;
95 terminator = ']]';
96 }
97
98 var endIndex = -1;
99 if (startIndex >= 0) {
100 endIndex = s.indexOf(terminator, startIndex + 2);
101 }
102
103 if (endIndex < 0) {
104 if (tokens == null) return null;
105
106 tokens.add(s.substring(lastIndex)); // TEXT
107 break;
108 }
109
110 if (tokens == null) tokens = [];
111 tokens.add(s.substring(lastIndex, startIndex)); // TEXT
112 var pathString = s.substring(startIndex + 2, endIndex).trim();
113 tokens.add(oneTime); // ONETIME?
114 onlyOneTime = onlyOneTime && oneTime;
115 tokens.add(new PropertyPath(pathString)); // PATH
116 var delegateFn = delegate == null ? null :
117 delegate.prepareBinding(pathString, name, node);
118 tokens.add(delegateFn);
119
120 lastIndex = endIndex + 2;
121 }
122
123 if (lastIndex == length) tokens.add('');
124
125 return new MustacheTokens._(tokens, onlyOneTime);
126 }
127
128
129 // Dart note: split "combinator" into the single/list variants, so the
130 // argument can be typed.
131 String _singleCombinator(Object value) {
132 if (value == null) value = '';
133 return '${getText(0)}$value${getText(length)}';
134 }
135
136 String _listCombinator(List<Object> values) {
137 var newValue = new StringBuffer(getText(0));
138 int len = this.length;
139 for (var i = 0; i < len; i++) {
140 var value = values[i];
141 if (value != null) newValue.write(value);
142 newValue.write(getText(i + 1));
143 }
144 return newValue.toString();
145 }
146 }
OLDNEW
« no previous file with comments | « pkg/template_binding/lib/src/instance_binding_map.dart ('k') | pkg/template_binding/lib/src/node.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698