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

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: 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 * @param {string} url
9 * @param {string} text
10 * @param {!WebInspector.TokenizerFactory} tokenizerFactory
11 * @return {!WebInspector.SASSSupport.AST}
12 */
13 WebInspector.SASSSupport.parseSCSS = function(url, text, tokenizerFactory)
14 {
15 var result = WebInspector.SASSSupport._innerParseSCSS(text, tokenizerFactory );
16
17 var rules = [
18 new WebInspector.SASSSupport.Rule("variables", result.variables),
19 new WebInspector.SASSSupport.Rule("properties", result.properties),
20 new WebInspector.SASSSupport.Rule("mixins", result.mixins)
21 ];
22
23 return new WebInspector.SASSSupport.AST(url, text, rules);
24 }
25
26 /** @enum {string} */
27 WebInspector.SASSSupport.SCSSParserStates = {
28 Initial: "Initial",
29 PropertyName: "PropertyName",
30 PropertyValue: "PropertyValue",
31 VariableName: "VariableName",
32 VariableValue: "VariableValue",
33 MixinName: "MixinName",
34 MixinValue: "MixinValue",
35 Media: "Media",
36 }
37
38 /**
39 * @param {string} text
40 * @param {!WebInspector.TokenizerFactory} tokenizerFactory
41 * @return {!{variables: !Array<!WebInspector.SASSSupport.Property>, properties: !Array<!WebInspector.SASSSupport.Property>, mixins: !Array<!WebInspector.SASSSu pport.Property>}}
42 */
43 WebInspector.SASSSupport._innerParseSCSS = function(text, tokenizerFactory)
44 {
45 var lines = text.split("\n");
46 var properties = [];
47 var variables = [];
48 var mixins = [];
49
50 var States = WebInspector.SASSSupport.SCSSParserStates;
51 var state = States.Initial;
52 var propertyName, propertyValue;
53 var variableName, variableValue;
54 var mixinName, mixinValue;
55 var UndefTokenType = {};
56
57 /**
58 * @param {string} tokenValue
59 * @param {?string} tokenTypes
60 * @param {number} column
61 * @param {number} newColumn
62 */
63 function processToken(tokenValue, tokenTypes, column, newColumn)
64 {
65 var tokenType = tokenTypes ? tokenTypes.split(" ").keySet() : UndefToken Type;
66 switch (state) {
67 case States.Initial:
68 if (tokenType["css-variable-2"]) {
69 variableName = new WebInspector.SASSSupport.TextNode(tokenValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn));
70 state = States.VariableName;
71 } else if (tokenType["css-property"] || tokenType["css-meta"]) {
72 propertyName = new WebInspector.SASSSupport.TextNode(tokenValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn));
73 state = States.PropertyName;
74 } else if (tokenType["css-def"] && tokenValue === "@include") {
75 mixinName = new WebInspector.SASSSupport.TextNode(tokenValue, ne w WebInspector.TextRange(lineNumber, column, lineNumber, newColumn));
76 state = States.MixinName;
77 } else if (tokenType["css-comment"]) {
78 // The |processToken| is called per-line, so no token spans more then one line.
pfeldman 2015/12/09 03:50:59 huh?
79 // Support only a one-line comments.
80 if (tokenValue.substring(0, 2) !== "/*" || tokenValue.substring( tokenValue.length - 2) !== "*/")
81 break;
82 var uncommentedText = tokenValue.substring(2, tokenValue.length - 2);
83 var fakeRule = "a{\n" + uncommentedText + "}";
84 var result = WebInspector.SASSSupport._innerParseSCSS(fakeRule, tokenizerFactory);
85 if (result.properties.length === 1 && result.variables.length == = 0 && result.mixins.length === 0) {
86 var disabledProperty = result.properties[0];
87 // We should offset property to current coordinates.
88 var offset = column + 2;
89 disabledProperty.disabled = true;
90 disabledProperty.range = WebInspector.TextRange.createFromLo cation(lineNumber, column);
91 disabledProperty.range.endColumn = newColumn;
92 disabledProperty.name.range.startLine = lineNumber;
93 disabledProperty.name.range.startColumn += offset;
94 disabledProperty.name.range.endLine = lineNumber;
95 disabledProperty.name.range.endColumn += offset;
96 disabledProperty.value.range.startLine = lineNumber;
97 disabledProperty.value.range.startColumn += offset;
98 disabledProperty.value.range.endLine = lineNumber;
99 disabledProperty.value.range.endColumn += offset;
100 properties.push(disabledProperty);
101 }
102 } else if (tokenType["css-def"] && tokenValue === "@media") {
103 state = States.Media;
104 }
105 break;
106 case States.VariableName:
107 if (tokenValue === ")" && tokenType === UndefTokenType) {
108 state = States.Initial;
109 } else if (tokenValue === ":" && tokenType === UndefTokenType) {
110 state = States.VariableValue;
111 variableValue = new WebInspector.SASSSupport.TextNode("", WebIns pector.TextRange.createFromLocation(lineNumber, newColumn));
112 } else if (tokenType !== UndefTokenType) {
113 state = States.Initial;
114 }
115 break;
116 case States.VariableValue:
117 if (tokenValue === ";" && tokenType === UndefTokenType) {
118 variableValue.range.endLine = lineNumber;
119 variableValue.range.endColumn = column;
120 var variable = new WebInspector.SASSSupport.Property(variableNam e, variableValue, variableName.range.clone(), false);
121 variable.range.endLine = lineNumber;
122 variable.range.endColumn = newColumn;
123 variables.push(variable);
124 state = States.Initial;
125 } else {
126 variableValue.text += tokenValue;
127 }
128 break;
129 case States.PropertyName:
130 if (tokenValue === ":" && tokenType === UndefTokenType) {
131 state = States.PropertyValue;
132 propertyName.range.endLine = lineNumber;
133 propertyName.range.endColumn = column;
134 propertyValue = new WebInspector.SASSSupport.TextNode("", WebIns pector.TextRange.createFromLocation(lineNumber, newColumn));
135 } else if (tokenType["css-property"]) {
136 propertyName.text += tokenValue;
137 }
138 break;
139 case States.PropertyValue:
140 if ((tokenValue === "}" || tokenValue === ";") && tokenType === Unde fTokenType) {
141 propertyValue.range.endLine = lineNumber;
142 propertyValue.range.endColumn = column;
143 var property = new WebInspector.SASSSupport.Property(propertyNam e, propertyValue, propertyName.range.clone(), false);
144 property.range.endLine = lineNumber;
145 property.range.endColumn = newColumn;
146 properties.push(property);
147 state = States.Initial;
148 } else {
149 propertyValue.text += tokenValue;
150 }
151 break;
152 case States.MixinName:
153 if (tokenValue === "(" && tokenType === UndefTokenType) {
154 state = States.MixinValue;
155 mixinName.range.endLine = lineNumber;
156 mixinName.range.endColumn = column;
157 mixinValue = new WebInspector.SASSSupport.TextNode("", WebInspec tor.TextRange.createFromLocation(lineNumber, newColumn));
158 } else if (tokenValue === ";" && tokenType === UndefTokenType) {
159 state = States.Initial;
160 mixinValue = null;
161 } else {
162 mixinName.text += tokenValue;
163 }
164 break;
165 case States.MixinValue:
166 if (tokenValue === ")" && tokenType === UndefTokenType) {
167 mixinValue.range.endLine = lineNumber;
168 mixinValue.range.endColumn = column;
169 var mixin = new WebInspector.SASSSupport.Property(mixinName, /** @type {!WebInspector.SASSSupport.TextNode} */(mixinValue), mixinName.range.clon e(), false);
170 mixin.range.endLine = lineNumber;
171 mixin.range.endColumn = newColumn;
172 mixins.push(mixin);
173 state = States.Initial;
174 } else {
175 mixinValue.text += tokenValue;
176 }
177 break;
178 case States.Media:
179 if (tokenValue === "{" && tokenType === UndefTokenType)
180 state = States.Initial;
181 break;
182 default:
183 console.assert(false, "Unknown SASS parser state.");
184 }
185 }
186 var tokenizer = tokenizerFactory.createTokenizer("text/x-scss");
187 var lineNumber;
188 for (lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
189 var line = lines[lineNumber];
190 tokenizer(line, processToken);
191 processToken("\n", null, line.length, line.length + 1);
192 }
193 return {
194 variables: variables,
195 properties: properties,
196 mixins: mixins
197 };
198 }
199
200 /**
201 * @constructor
202 */
203 WebInspector.SASSSupport.Node = function()
204 {
205 this.parent = null;
pfeldman 2015/12/09 03:50:59 Why is the AST tree not reflective? I.e. why can't
lushnikov 2015/12/09 07:04:57 Because it's structure is simple enough to avoid r
206 }
207
208 WebInspector.SASSSupport.Node.prototype = {
209 /**
210 * @return {!WebInspector.SASSSupport.AST}
211 */
212 root: function()
213 {
214 if (this._root)
215 return this._root;
216 this._root = this;
217 while (this._root.parent)
218 this._root = this._root.parent;
219 return /** @type {!WebInspector.SASSSupport.AST} */(this._root);
220 }
221 }
222
223 /**
224 * @constructor
225 * @extends {WebInspector.SASSSupport.Node}
226 * @param {string} text
227 * @param {!WebInspector.TextRange} range
228 */
229 WebInspector.SASSSupport.TextNode = function(text, range)
230 {
231 WebInspector.SASSSupport.Node.call(this);
232 this.text = text;
233 this.range = range;
234 }
235
236 WebInspector.SASSSupport.TextNode.prototype = {
237 /**
238 * @return {!WebInspector.SASSSupport.TextNode}
239 */
240 clone: function()
241 {
242 return new WebInspector.SASSSupport.TextNode(this.text, this.range.clone ());
243 },
244
245 __proto__: WebInspector.SASSSupport.Node.prototype
246 }
247
248 /**
249 * @constructor
250 * @extends {WebInspector.SASSSupport.Node}
251 * @param {!WebInspector.SASSSupport.TextNode} name
252 * @param {!WebInspector.SASSSupport.TextNode} value
253 * @param {!WebInspector.TextRange} range
254 * @param {boolean} disabled
255 */
256 WebInspector.SASSSupport.Property = function(name, value, range, disabled)
257 {
258 WebInspector.SASSSupport.Node.call(this);
259 this.name = name;
260 this.value = value;
261 this.range = range;
262 this.name.parent = this;
263 this.value.parent = this;
264 this.disabled = disabled;
265 }
266
267 WebInspector.SASSSupport.Property.prototype = {
268 /**
269 * @return {!WebInspector.SASSSupport.Property}
270 */
271 clone: function()
272 {
273 return new WebInspector.SASSSupport.Property(this.name.clone(), this.val ue.clone(), this.range.clone(), this.disabled);
274 },
275
276 __proto__: WebInspector.SASSSupport.Node.prototype
277 }
278
279 /**
280 * @constructor
281 * @extends {WebInspector.SASSSupport.Node}
282 * @param {string} selector
283 * @param {!Array<!WebInspector.SASSSupport.Property>} properties
284 */
285 WebInspector.SASSSupport.Rule = function(selector, properties)
286 {
287 WebInspector.SASSSupport.Node.call(this);
288 this.selector = selector;
289 this.properties = properties;
290 for (var i = 0; i < this.properties.length; ++i)
291 this.properties[i].parent = this;
292 }
293
294 WebInspector.SASSSupport.Rule.prototype = {
295 /**
296 * @return {!WebInspector.SASSSupport.Rule}
297 */
298 clone: function()
299 {
300 var properties = [];
301 for (var i = 0; i < this.properties.length; ++i)
302 properties.push(this.properties[i].clone());
303 return new WebInspector.SASSSupport.Rule(this.selector, properties);
304 },
305
306 __proto__: WebInspector.SASSSupport.Node.prototype
307 }
308
309 /**
310 * @constructor
311 * @extends {WebInspector.SASSSupport.Node}
312 * @param {string} url
313 * @param {string} text
314 * @param {!Array<!WebInspector.SASSSupport.Rule>} rules
315 */
316 WebInspector.SASSSupport.AST = function(url, text, rules)
317 {
318 WebInspector.SASSSupport.Node.call(this);
319 this.url = url;
320 this.rules = rules;
321 for (var i = 0; i < rules.length; ++i)
322 rules[i].parent = this;
323 this.text = text;
324 }
325
326 WebInspector.SASSSupport.AST.prototype = {
327 /**
328 * @return {!WebInspector.SASSSupport.AST}
329 */
330 clone: function()
331 {
332 var rules = [];
333 for (var i = 0; i < this.rules.length; ++i)
334 rules.push(this.rules[i].clone());
335 return new WebInspector.SASSSupport.AST(this.url, this.text, rules);
336 },
337
338 __proto__: WebInspector.SASSSupport.Node.prototype
339 }
340
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698