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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/gonzales/SCSSParser.js

Issue 1938313002: DevTools: [SASS] parse SCSS rules and their selectors. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments Created 4 years, 7 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @constructor 6 * @constructor
7 * @implements {WebInspector.FormatterWorkerContentParser} 7 * @implements {WebInspector.FormatterWorkerContentParser}
8 */ 8 */
9 WebInspector.SCSSParser = function() 9 WebInspector.SCSSParser = function()
10 { 10 {
11 } 11 }
12 12
13 /**
14 * @constructor
15 */
16 WebInspector.SCSSParser.Result = function()
17 {
18 this.properties = [];
19 this.variables = [];
20 this.mixins = [];
21 }
22
23 WebInspector.SCSSParser.prototype = { 13 WebInspector.SCSSParser.prototype = {
24 /** 14 /**
25 * @override 15 * @override
26 * @param {string} content 16 * @param {string} content
27 * @return {!WebInspector.SCSSParser.Result} 17 * @return {!Array<!WebInspector.SCSSParser.Rule>}
28 */ 18 */
29 parse: function(content) 19 parse: function(content)
30 { 20 {
31 var result = new WebInspector.SCSSParser.Result();
32 var ast = null; 21 var ast = null;
33 try { 22 try {
34 ast = gonzales.parse(content, {syntax: "scss"}); 23 ast = gonzales.parse(content, {syntax: "scss"});
35 } catch (e) { 24 } catch (e) {
36 return result; 25 return [];
37 } 26 }
38 27
39 var extractedNodes = []; 28 /** @type {!{properties: !Array<!Gonzales.Node>, node: !Gonzales.Node}} */
40 WebInspector.SCSSParser.extractNodes(ast, extractedNodes); 29 var rootBlock = {
30 properties: [],
31 node: ast
32 };
33 /** @type {!Array<!{properties: !Array<!Gonzales.Node>, node: !Gonzales. Node}>} */
34 var blocks = [rootBlock];
35 ast.selectors = [];
36 WebInspector.SCSSParser.extractNodes(ast, blocks, rootBlock);
41 37
42 for (var node of extractedNodes) { 38 var rules = [];
39 for (var block of blocks)
40 this._handleBlock(block, rules);
41 return rules;
42 },
43
44 /**
45 * @param {!{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}} bloc k
46 * @param {!Array<!WebInspector.SCSSParser.Rule>} output
47 */
48 _handleBlock: function(block, output)
49 {
50 var selectors = block.node.selectors.map(WebInspector.SCSSParser.rangeFr omNode);
51 var properties = [];
52 var styleRange = WebInspector.SCSSParser.rangeFromNode(block.node);
53 styleRange.startColumn += 1;
54 styleRange.endColumn -= 1;
55 for (var node of block.properties) {
43 if (node.type === "declaration") 56 if (node.type === "declaration")
44 this._handleDeclaration(node, result); 57 this._handleDeclaration(node, properties);
45 else if (node.type === "include") 58 else if (node.type === "include")
46 this._handleInclude(node, result); 59 this._handleInclude(node, properties);
47 else if (node.type === "multilineComment" && node.start.line === nod e.end.line) 60 else if (node.type === "multilineComment" && node.start.line === nod e.end.line)
48 this._handleComment(node, result); 61 this._handleComment(node, properties);
49 } 62 }
50 return result; 63 if (!selectors.length && !properties.length)
64 return;
65 var rule = new WebInspector.SCSSParser.Rule(selectors, properties, style Range);
66 output.push(rule);
51 }, 67 },
52 68
53 /** 69 /**
54 * @param {!Gonzales.Node} node 70 * @param {!Gonzales.Node} node
55 * @param {!WebInspector.SCSSParser.Result} result 71 * @param {!Array<!WebInspector.SCSSParser.Property>} output
56 */ 72 */
57 _handleDeclaration: function(node, result) 73 _handleDeclaration: function(node, output)
58 { 74 {
59 var propertyNode = node.content.find(node => node.type === "property"); 75 var propertyNode = node.content.find(node => node.type === "property");
60 var delimeterNode = node.content.find(node => node.type === "propertyDel imiter"); 76 var delimeterNode = node.content.find(node => node.type === "propertyDel imiter");
61 var valueNode = node.content.find(node => node.type === "value"); 77 var valueNode = node.content.find(node => node.type === "value");
62 if (!propertyNode || !delimeterNode || !valueNode) 78 if (!propertyNode || !delimeterNode || !valueNode)
63 return; 79 return;
64 80
65 var nameRange = new WebInspector.TextRange(propertyNode.start.line - 1, propertyNode.start.column - 1, delimeterNode.start.line - 1, delimeterNode.start .column - 1); 81 var nameRange = new WebInspector.TextRange(propertyNode.start.line - 1, propertyNode.start.column - 1, delimeterNode.start.line - 1, delimeterNode.start .column - 1);
66 var valueRange = new WebInspector.TextRange(delimeterNode.end.line - 1, delimeterNode.end.column, valueNode.end.line - 1, valueNode.end.column); 82 var valueRange = new WebInspector.TextRange(delimeterNode.end.line - 1, delimeterNode.end.column, valueNode.end.line - 1, valueNode.end.column);
67 var range = /** @type {!WebInspector.TextRange} */(node.declarationRange ); 83 var range = /** @type {!WebInspector.TextRange} */(node.declarationRange );
68 84
69 var property = new WebInspector.SCSSParser.Property(range, nameRange, va lueRange, false); 85 var property = new WebInspector.SCSSParser.Property(range, nameRange, va lueRange, false);
70 var isVariable = !!propertyNode.content.find(node => node.type === "vari able"); 86 output.push(property);
71 if (isVariable)
72 result.variables.push(property);
73 else
74 result.properties.push(property);
75 }, 87 },
76 88
77 /** 89 /**
78 * @param {!Gonzales.Node} node 90 * @param {!Gonzales.Node} node
79 * @param {!WebInspector.SCSSParser.Result} result 91 * @param {!Array<!WebInspector.SCSSParser.Property>} output
80 */ 92 */
81 _handleInclude: function(node, result) 93 _handleInclude: function(node, output)
82 { 94 {
83 var mixinName = node.content.find(node => node.type === "ident"); 95 var mixinName = node.content.find(node => node.type === "ident");
84 if (!mixinName) 96 if (!mixinName)
85 return; 97 return;
86 var nameRange = WebInspector.SCSSParser.rangeFromNode(mixinName); 98 var nameRange = WebInspector.SCSSParser.rangeFromNode(mixinName);
87 var mixinArguments = node.content.find(node => node.type === "arguments" ); 99 var mixinArguments = node.content.find(node => node.type === "arguments" );
88 if (!mixinArguments) 100 if (!mixinArguments)
89 return; 101 return;
90 var parameters = mixinArguments.content.filter(node => node.type !== "de limiter" && node.type !== "space"); 102 var parameters = mixinArguments.content.filter(node => node.type !== "de limiter" && node.type !== "space");
91 for (var parameter of parameters) { 103 for (var parameter of parameters) {
92 var range = WebInspector.SCSSParser.rangeFromNode(node); 104 var range = WebInspector.SCSSParser.rangeFromNode(node);
93 var valueRange = WebInspector.SCSSParser.rangeFromNode(parameter); 105 var valueRange = WebInspector.SCSSParser.rangeFromNode(parameter);
94 var property = new WebInspector.SCSSParser.Property(range, nameRange , valueRange, false); 106 var property = new WebInspector.SCSSParser.Property(range, nameRange , valueRange, false);
95 result.mixins.push(property); 107 output.push(property);
96 } 108 }
97 }, 109 },
98 110
99 /** 111 /**
100 * @param {!Gonzales.Node} node 112 * @param {!Gonzales.Node} node
101 * @param {!WebInspector.SCSSParser.Result} result 113 * @param {!Array<!WebInspector.SCSSParser.Property>} output
102 */ 114 */
103 _handleComment: function(node, result) 115 _handleComment: function(node, output)
104 { 116 {
105 if (node.start.line !== node.end.line) 117 if (node.start.line !== node.end.line)
106 return; 118 return;
107 var innerText = /** @type {string} */(node.content); 119 var innerText = /** @type {string} */(node.content);
108 var innerResult = this.parse(innerText); 120 var innerResult = this.parse(innerText);
109 if (innerResult.properties.length !== 1 || innerResult.variables.length !== 0 || innerResult.mixins.length !== 0) 121 if (innerResult.length !== 1 || innerResult[0].properties.length !== 1)
110 return; 122 return;
111 var property = innerResult.properties[0]; 123 var property = innerResult[0].properties[0];
112 var disabledProperty = property.rebaseInsideOneLineComment(node); 124 var disabledProperty = property.rebaseInsideOneLineComment(node);
113 result.properties.push(disabledProperty); 125 output.push(disabledProperty);
114 }, 126 },
115 } 127 }
116 128
117 /** 129 /**
118 * @param {!Gonzales.Node} node 130 * @param {!Gonzales.Node} node
119 * @return {!WebInspector.TextRange} 131 * @return {!WebInspector.TextRange}
120 */ 132 */
121 WebInspector.SCSSParser.rangeFromNode = function(node) 133 WebInspector.SCSSParser.rangeFromNode = function(node)
122 { 134 {
123 return new WebInspector.TextRange(node.start.line - 1, node.start.column - 1 , node.end.line - 1, node.end.column); 135 return new WebInspector.TextRange(node.start.line - 1, node.start.column - 1 , node.end.line - 1, node.end.column);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 * @return {!WebInspector.TextRange} 172 * @return {!WebInspector.TextRange}
161 */ 173 */
162 function rebaseRange(range, lineOffset, columnOffset) 174 function rebaseRange(range, lineOffset, columnOffset)
163 { 175 {
164 return new WebInspector.TextRange(range.startLine + lineOffset, rang e.startColumn + columnOffset, range.endLine + lineOffset, range.endColumn + colu mnOffset); 176 return new WebInspector.TextRange(range.startLine + lineOffset, rang e.startColumn + columnOffset, range.endLine + lineOffset, range.endColumn + colu mnOffset);
165 } 177 }
166 } 178 }
167 } 179 }
168 180
169 /** 181 /**
182 * @constructor
183 * @param {!Array<!WebInspector.TextRange>} selectors
184 * @param {!Array<!WebInspector.SCSSParser.Property>} properties
185 * @param {!WebInspector.TextRange} styleRange
186 */
187 WebInspector.SCSSParser.Rule = function(selectors, properties, styleRange)
188 {
189 this.selectors = selectors;
190 this.properties = properties;
191 this.styleRange = styleRange;
192 }
193
194 /**
170 * @param {!Gonzales.Node} node 195 * @param {!Gonzales.Node} node
171 * @param {!Array<!Gonzales.Node>} output 196 * @param {!Array<{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}>} b locks
197 * @param {!{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}} lastBloc k
172 */ 198 */
173 WebInspector.SCSSParser.extractNodes = function(node, output) 199 WebInspector.SCSSParser.extractNodes = function(node, blocks, lastBlock)
174 { 200 {
175 if (!Array.isArray(node.content)) 201 if (!Array.isArray(node.content))
176 return; 202 return;
203 if (node.type === "block") {
204 lastBlock = {
205 node: node,
206 properties: []
207 };
208 blocks.push(lastBlock);
209 }
177 var lastDeclaration = null; 210 var lastDeclaration = null;
211 var selectors = [];
178 for (var i = 0; i < node.content.length; ++i) { 212 for (var i = 0; i < node.content.length; ++i) {
179 var child = node.content[i]; 213 var child = node.content[i];
180 if (child.type === "declarationDelimiter" && lastDeclaration) { 214 if (child.type === "declarationDelimiter" && lastDeclaration) {
181 lastDeclaration.declarationRange.endLine = child.end.line - 1; 215 lastDeclaration.declarationRange.endLine = child.end.line - 1;
182 lastDeclaration.declarationRange.endColumn = child.end.column; 216 lastDeclaration.declarationRange.endColumn = child.end.column;
183 lastDeclaration = null; 217 lastDeclaration = null;
218 } else if (child.type === "selector") {
219 selectors.push(child);
220 } else if (child.type === "block") {
221 child.selectors = selectors;
222 selectors = [];
184 } 223 }
185 if (child.type === "include" || child.type === "declaration" || child.ty pe === "multilineComment") 224 if (child.type === "include" || child.type === "declaration" || child.ty pe === "multilineComment")
186 output.push(child); 225 lastBlock.properties.push(child);
187 if (child.type === "declaration") { 226 if (child.type === "declaration") {
188 lastDeclaration = child; 227 lastDeclaration = child;
189 lastDeclaration.declarationRange = WebInspector.TextRange.createFrom Location(child.start.line - 1, child.start.column - 1); 228 lastDeclaration.declarationRange = WebInspector.TextRange.createFrom Location(child.start.line - 1, child.start.column - 1);
190 } 229 }
191 WebInspector.SCSSParser.extractNodes(child, output); 230 WebInspector.SCSSParser.extractNodes(child, blocks, lastBlock);
192 } 231 }
193 if (lastDeclaration) { 232 if (lastDeclaration) {
194 lastDeclaration.declarationRange.endLine = node.end.line - 1; 233 lastDeclaration.declarationRange.endLine = node.end.line - 1;
195 lastDeclaration.declarationRange.endColumn = node.end.column - 1; 234 lastDeclaration.declarationRange.endColumn = node.end.column - 1;
196 } 235 }
197 } 236 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698