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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js

Issue 1511073002: DevTools: [SASS] introduce sass module, implement SCSS AST-builder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: introduce ASTDocument Created 5 years 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
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 WebInspector.SASSSupport = {}
6
7 /**
8 * @constructor
9 * @param {string} url
10 * @param {string} text
11 */
12 WebInspector.SASSSupport.ASTDocument = function(url, text)
13 {
14 this.url = url;
15 this.text = text;
16 }
17
18 /**
19 * @param {string} url
20 * @param {string} text
21 * @param {!WebInspector.TokenizerFactory} tokenizerFactory
22 * @return {!WebInspector.SASSSupport.AST}
23 */
24 WebInspector.SASSSupport.parseSCSS = function(url, text, tokenizerFactory)
25 {
26 var document = new WebInspector.SASSSupport.ASTDocument(url, text);
27 var result = WebInspector.SASSSupport._innerParseSCSS(document, tokenizerFac tory);
28
29 var rules = [
30 new WebInspector.SASSSupport.Rule(document, "variables", result.variable s),
31 new WebInspector.SASSSupport.Rule(document, "properties", result.propert ies),
32 new WebInspector.SASSSupport.Rule(document, "mixins", result.mixins)
33 ];
34
35 return new WebInspector.SASSSupport.AST(document, rules);
36 }
37
38 /** @enum {string} */
39 WebInspector.SASSSupport.SCSSParserStates = {
40 Initial: "Initial",
41 PropertyName: "PropertyName",
42 PropertyValue: "PropertyValue",
43 VariableName: "VariableName",
44 VariableValue: "VariableValue",
45 MixinName: "MixinName",
46 MixinValue: "MixinValue",
47 Media: "Media",
48 }
49
50 /**
51 * @param {!WebInspector.SASSSupport.ASTDocument} document
52 * @param {!WebInspector.TokenizerFactory} tokenizerFactory
53 * @return {!{variables: !Array<!WebInspector.SASSSupport.Property>, properties: !Array<!WebInspector.SASSSupport.Property>, mixins: !Array<!WebInspector.SASSSu pport.Property>}}
54 */
55 WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory)
56 {
57 var lines = document.text.split("\n");
58 var properties = [];
59 var variables = [];
60 var mixins = [];
61
62 var States = WebInspector.SASSSupport.SCSSParserStates;
63 var state = States.Initial;
64 var propertyName, propertyValue;
65 var variableName, variableValue;
66 var mixinName, mixinValue;
67 var UndefTokenType = {};
68
69 /**
70 * @param {string} tokenValue
71 * @param {?string} tokenTypes
72 * @param {number} column
73 * @param {number} newColumn
74 */
75 function processToken(tokenValue, tokenTypes, column, newColumn)
76 {
77 var tokenType = tokenTypes ? tokenTypes.split(" ").keySet() : UndefToken Type;
78 switch (state) {
79 case States.Initial:
80 if (tokenType["css-variable-2"]) {
81 variableName = new WebInspector.SASSSupport.TextNode(document, t okenValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn) );
82 state = States.VariableName;
83 } else if (tokenType["css-property"] || tokenType["css-meta"]) {
84 propertyName = new WebInspector.SASSSupport.TextNode(document, t okenValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn) );
85 state = States.PropertyName;
86 } else if (tokenType["css-def"] && tokenValue === "@include") {
87 mixinName = new WebInspector.SASSSupport.TextNode(document, toke nValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn));
88 state = States.MixinName;
89 } else if (tokenType["css-comment"]) {
90 // Support only a one-line comments.
91 if (tokenValue.substring(0, 2) !== "/*" || tokenValue.substring( tokenValue.length - 2) !== "*/")
92 break;
93 var uncommentedText = tokenValue.substring(2, tokenValue.length - 2);
94 var fakeRuleText = "a{\n" + uncommentedText + "}";
95 var fakeDocument = new WebInspector.SASSSupport.ASTDocument("", fakeRuleText);
96 var result = WebInspector.SASSSupport._innerParseSCSS(fakeDocume nt, tokenizerFactory);
97 if (result.properties.length === 1 && result.variables.length == = 0 && result.mixins.length === 0) {
98 var disabledProperty = result.properties[0];
99 // We should offset property to current coordinates.
100 var offset = column + 2;
101 var nameRange = new WebInspector.TextRange(lineNumber, disab ledProperty.name.range.startColumn + offset,
102 lineNumber, disabledProperty.name.range.endColumn + offset);
103 var valueRange = new WebInspector.TextRange(lineNumber, disa bledProperty.value.range.startColumn + offset,
104 lineNumber, disabledProperty.value.range.endColumn + offset);
105 var name = new WebInspector.SASSSupport.TextNode(document, d isabledProperty.name.text, nameRange);
106 var value = new WebInspector.SASSSupport.TextNode(document, disabledProperty.value.text, valueRange);
107 var range = new WebInspector.TextRange(lineNumber, column, l ineNumber, newColumn);
108 var property = new WebInspector.SASSSupport.Property(documen t, name, value, range, true);
109 properties.push(property);
110 }
111 } else if (tokenType["css-def"] && tokenValue === "@media") {
112 state = States.Media;
113 }
114 break;
115 case States.VariableName:
116 if (tokenValue === ")" && tokenType === UndefTokenType) {
117 state = States.Initial;
118 } else if (tokenValue === ":" && tokenType === UndefTokenType) {
119 state = States.VariableValue;
120 variableValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(lineNumber, newColumn));
121 } else if (tokenType !== UndefTokenType) {
122 state = States.Initial;
123 }
124 break;
125 case States.VariableValue:
126 if (tokenValue === ";" && tokenType === UndefTokenType) {
127 variableValue.range.endLine = lineNumber;
128 variableValue.range.endColumn = column;
129 var variable = new WebInspector.SASSSupport.Property(document, v ariableName, variableValue, variableName.range.clone(), false);
130 variable.range.endLine = lineNumber;
131 variable.range.endColumn = newColumn;
132 variables.push(variable);
133 state = States.Initial;
134 } else {
135 variableValue.text += tokenValue;
136 }
137 break;
138 case States.PropertyName:
139 if (tokenValue === ":" && tokenType === UndefTokenType) {
140 state = States.PropertyValue;
141 propertyName.range.endLine = lineNumber;
142 propertyName.range.endColumn = column;
143 propertyValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(lineNumber, newColumn));
144 } else if (tokenType["css-property"]) {
145 propertyName.text += tokenValue;
146 }
147 break;
148 case States.PropertyValue:
149 if ((tokenValue === "}" || tokenValue === ";") && tokenType === Unde fTokenType) {
150 propertyValue.range.endLine = lineNumber;
151 propertyValue.range.endColumn = column;
152 var property = new WebInspector.SASSSupport.Property(document, p ropertyName, propertyValue, propertyName.range.clone(), false);
153 property.range.endLine = lineNumber;
154 property.range.endColumn = newColumn;
155 properties.push(property);
156 state = States.Initial;
157 } else {
158 propertyValue.text += tokenValue;
159 }
160 break;
161 case States.MixinName:
162 if (tokenValue === "(" && tokenType === UndefTokenType) {
163 state = States.MixinValue;
164 mixinName.range.endLine = lineNumber;
165 mixinName.range.endColumn = column;
166 mixinValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(lineNumber, newColumn));
167 } else if (tokenValue === ";" && tokenType === UndefTokenType) {
168 state = States.Initial;
169 mixinValue = null;
170 } else {
171 mixinName.text += tokenValue;
172 }
173 break;
174 case States.MixinValue:
175 if (tokenValue === ")" && tokenType === UndefTokenType) {
176 mixinValue.range.endLine = lineNumber;
177 mixinValue.range.endColumn = column;
178 var mixin = new WebInspector.SASSSupport.Property(document, mixi nName, /** @type {!WebInspector.SASSSupport.TextNode} */(mixinValue), mixinName. range.clone(), false);
179 mixin.range.endLine = lineNumber;
180 mixin.range.endColumn = newColumn;
181 mixins.push(mixin);
182 state = States.Initial;
183 } else {
184 mixinValue.text += tokenValue;
185 }
186 break;
187 case States.Media:
188 if (tokenValue === "{" && tokenType === UndefTokenType)
189 state = States.Initial;
190 break;
191 default:
192 console.assert(false, "Unknown SASS parser state.");
193 }
194 }
195 var tokenizer = tokenizerFactory.createTokenizer("text/x-scss");
196 var lineNumber;
197 for (lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
198 var line = lines[lineNumber];
199 tokenizer(line, processToken);
200 processToken("\n", null, line.length, line.length + 1);
201 }
202 return {
203 variables: variables,
204 properties: properties,
205 mixins: mixins
206 };
207 }
208
209 /**
210 * @constructor
211 * @param {!WebInspector.SASSSupport.ASTDocument} document
212 */
213 WebInspector.SASSSupport.Node = function(document)
214 {
215 this.document = document;
216 }
217
218 /**
219 * @constructor
220 * @extends {WebInspector.SASSSupport.Node}
221 * @param {!WebInspector.SASSSupport.ASTDocument} document
222 * @param {string} text
223 * @param {!WebInspector.TextRange} range
224 */
225 WebInspector.SASSSupport.TextNode = function(document, text, range)
226 {
227 WebInspector.SASSSupport.Node.call(this, document);
228 this.text = text;
pfeldman 2015/12/09 20:13:43 Why is text necessary? You can fetch it at any mom
lushnikov 2015/12/09 21:41:54 I want to modify AST tree later, adding properties
229 this.range = range;
230 }
231
232 WebInspector.SASSSupport.TextNode.prototype = {
233 /**
234 * @return {!WebInspector.SASSSupport.TextNode}
235 */
236 clone: function()
237 {
238 return new WebInspector.SASSSupport.TextNode(this.document, this.text, t his.range.clone());
239 },
240
241 __proto__: WebInspector.SASSSupport.Node.prototype
242 }
243
244 /**
245 * @constructor
246 * @extends {WebInspector.SASSSupport.Node}
247 * @param {!WebInspector.SASSSupport.ASTDocument} document
248 * @param {!WebInspector.SASSSupport.TextNode} name
249 * @param {!WebInspector.SASSSupport.TextNode} value
250 * @param {!WebInspector.TextRange} range
251 * @param {boolean} disabled
252 */
253 WebInspector.SASSSupport.Property = function(document, name, value, range, disab led)
254 {
255 WebInspector.SASSSupport.Node.call(this, document);
256 this.name = name;
257 this.value = value;
258 this.range = range;
259 this.name.parent = this;
260 this.value.parent = this;
261 this.disabled = disabled;
262 }
263
264 WebInspector.SASSSupport.Property.prototype = {
265 /**
266 * @return {!WebInspector.SASSSupport.Property}
267 */
268 clone: function()
269 {
270 return new WebInspector.SASSSupport.Property(this.document, this.name.cl one(), this.value.clone(), this.range.clone(), this.disabled);
271 },
272
273 __proto__: WebInspector.SASSSupport.Node.prototype
274 }
275
276 /**
277 * @constructor
278 * @extends {WebInspector.SASSSupport.Node}
279 * @param {!WebInspector.SASSSupport.ASTDocument} document
280 * @param {string} selector
281 * @param {!Array<!WebInspector.SASSSupport.Property>} properties
282 */
283 WebInspector.SASSSupport.Rule = function(document, selector, properties)
284 {
285 WebInspector.SASSSupport.Node.call(this, document);
286 this.selector = selector;
287 this.properties = properties;
288 for (var i = 0; i < this.properties.length; ++i)
289 this.properties[i].parent = this;
290 }
291
292 WebInspector.SASSSupport.Rule.prototype = {
293 /**
294 * @return {!WebInspector.SASSSupport.Rule}
295 */
296 clone: function()
297 {
298 var properties = [];
299 for (var i = 0; i < this.properties.length; ++i)
300 properties.push(this.properties[i].clone());
301 return new WebInspector.SASSSupport.Rule(this.document, this.selector, p roperties);
302 },
303
304 __proto__: WebInspector.SASSSupport.Node.prototype
305 }
306
307 /**
308 * @constructor
309 * @extends {WebInspector.SASSSupport.Node}
310 * @param {!WebInspector.SASSSupport.ASTDocument} document
311 * @param {!Array<!WebInspector.SASSSupport.Rule>} rules
312 */
313 WebInspector.SASSSupport.AST = function(document, rules)
314 {
315 WebInspector.SASSSupport.Node.call(this, document);
316 this.rules = rules;
317 for (var i = 0; i < rules.length; ++i)
318 rules[i].parent = this;
319 }
320
321 WebInspector.SASSSupport.AST.prototype = {
322 /**
323 * @return {!WebInspector.SASSSupport.AST}
324 */
325 clone: function()
326 {
327 var rules = [];
328 for (var i = 0; i < this.rules.length; ++i)
329 rules.push(this.rules[i].clone());
330 return new WebInspector.SASSSupport.AST(this.document, rules);
331 },
332
333 __proto__: WebInspector.SASSSupport.Node.prototype
334 }
335
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698