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

Side by Side Diff: Source/devtools/front_end/bindings/SASSStructureMapping.js

Issue 1307063005: DevTools: edit SASS through SourceMaps. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: improvements Created 5 years, 3 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 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 /**
6 * @constructor
7 * @param {!Map<string, string>} sassSources
8 */
9 WebInspector.SASSStructureMapping = function(cssStruct, sassSources)
10 {
11 this._sources = sassSources;
12 this._cssStruct = cssStruct;
13 this._sassStructs = new Map();
14 }
15
16 WebInspector.SASSStructureMapping.prototype = {
17 cssPropertyValueToSASS: function(cssValueRange, sourceMap)
18 {
19 var entry = sourceMap.findEntry(cssValueRange.endLine, cssValueRange.end Column);
20 var url = entry.sourceURL;
21 var struct = this._structForURL(url);
22 if (!struct) {
23 console.error("Failed to get structure of " + url);
24 return null;
25 }
26 var sassValue = this._sassValue(struct, entry);
27 if (!sassValue)
28 return null;
29 return {
30 url: url,
31 range: sassValue.range
32 };
33 },
34
35 cssPropertyToSASS: function(cssPropertyRange, sourceMap)
36 {
37 var entry = sourceMap.findEntry(cssPropertyRange.startLine, cssPropertyR ange.startColumn);
38 var struct = this._structForURL(entry.sourceURL);
39 if (!struct) {
40 console.error("Failed to get structure of " + entry.sourceURL);
41 return null;
42 }
43 var sassProperty = this._sassProperty(struct, entry);
44 if (!sassProperty)
45 return null;
46 return {
47 url: entry.sourceURL,
48 range: sassProperty.range
49 };
50 },
51
52 sassPropertyValueToCSS: function(sassURL, sassValueRange, sourceMap)
53 {
54 var reversedEntries = sourceMap.findEntriesReversed(sassURL, sassValueRa nge.endLine, sassValueRange.endColumn - 1);
55 var result = [];
56 for (var i = 0; i < reversedEntries.length; ++i) {
57 var value = this._cssValue(reversedEntries[i]);
58 console.assert(value, "Failed to find reversed mapped property value .");
59 result.push(value);
60 }
61 return result;
62 },
63
64 _sassProperty: function(struct, entry)
65 {
66 for (var i = 0; i < struct.properties.length; ++i) {
67 var property = struct.properties[i];
68 if (this._rangeContainsSourceMapping(property.range, entry))
69 return property;
70 }
71 return null;
72 },
73
74 _sassVariable: function(struct, entry)
75 {
76 for (var i = 0; i < struct.variables.length; ++i) {
77 var variable = struct.variables[i];
78 if (this._rangeContainsSourceMapping(variable.range, entry))
79 return variable;
80 }
81 return null;
82 },
83
84 _sassValue: function(struct, entry)
85 {
86 var sassProperty = this._sassProperty(struct, entry);
87 if (sassProperty && this._rangeContainsSourceMapping(sassProperty.value. range, entry))
88 return sassProperty.value;
89
90 var sassVariable = this._sassVariable(struct, entry);
91 if (sassVariable && this._rangeContainsSourceMapping(sassVariable.value. range, entry))
92 return sassVariable.value;
93 for (var i = 0; i < struct.mixinValues.length; ++i) {
94 var mixinValue = struct.mixinValues[i];
95 if (this._rangeContainsSourceMapping(mixinValue.range, entry))
96 return mixinValue;
97 }
98 return null;
99 },
100
101 _cssProperty: function(entry)
102 {
103 for (var i = 0; i < this._cssStruct.length; ++i) {
104 var rule = this._cssStruct[i];
105 for (var j = 0; j < rule.properties.length; ++j) {
106 var property = rule.properties[j];
107 if (this._rangeContainsCompiledMapping(property.range, entry))
108 return property;
109 }
110 }
111 return null;
112 },
113
114 _cssValue: function(entry)
115 {
116 var cssProperty = this._cssProperty(entry);
117 if (cssProperty && this._rangeContainsCompiledMapping(cssProperty.valueR ange, entry))
118 return cssProperty;
119 return null;
120 },
121
122 _rangeContainsSourceMapping: function(range, entry)
123 {
124 if (range.startLine === range.endLine)
125 return range.startLine === entry.sourceLineNumber && range.startColu mn <= entry.sourceColumnNumber && entry.sourceColumnNumber <= range.endColumn;
126 if (range.startLine === entry.sourceLineNumber)
127 return range.startColumn <= entry.sourceColumnNumber;
128 if (range.endLine === entry.sourceLineNumber)
129 return entry.sourceColumnNumber <= range.endColumn;
130 return range.startLine < entry.sourceLineNumber && entry.sourceLineNumbe r < range.endLine;
131 },
132
133 _rangeContainsCompiledMapping: function(range, entry)
134 {
135 if (range.startLine === range.endLine)
136 return range.startLine === entry.lineNumber && range.startColumn <= entry.columnNumber && entry.columnNumber <= range.endColumn;
137 if (range.startLine === entry.lineNumber)
138 return range.startColumn <= entry.columnNumber;
139 if (range.endLine === entry.lineNumber)
140 return entry.columnNumber <= range.endColumn;
141 return range.startLine < entry.lineNumber && entry.lineNumber < range.en dLine;
142 },
143
144 _structForURL: function(sassURL)
145 {
146 if (this._sassStructs.has(sassURL))
147 return this._sassStructs.get(sassURL);
148 var source = this._sources.get(sassURL);
149 if (!source)
150 return null;
151 var result = WebInspector.SASSStructureMapping.parseSASS(source);
152 this._sassStructs.set(sassURL, result);
153 return result;
154 }
155 }
156
157
158 WebInspector.SASSStructureMapping.SCSSParserStates = {
159 Initial: "Initial",
160 PropertyName: "PropertyName",
161 PropertyValue: "PropertyValue",
162 VariableName: "VariableName",
163 VariableValue: "VariableValue",
164 MixinInclude: "MixinInclude",
165 MixinValue: "MixinValue"
166 }
167
168 WebInspector.SASSStructureMapping.parseSASS = function(text)
169 {
170 var lines = text.split("\n");
171 var properties = [];
172 var variables = [];
173 var mixinValues = [];
174
175 var States = WebInspector.SASSStructureMapping.SCSSParserStates;
176 var state = States.Initial;
177 var property;
178 var variable;
179 var mixin;
180 var UndefTokenType = {};
181
182 /**
183 * @param {string} tokenValue
184 * @param {?string} tokenTypes
185 * @param {number} column
186 * @param {number} newColumn
187 */
188 function processToken(tokenValue, tokenTypes, column, newColumn)
189 {
190 var tokenType = tokenTypes ? tokenTypes.split(" ").keySet() : UndefToken Type;
191 switch (state) {
192 case States.Initial:
193 if (tokenType["css-variable-2"]) {
194 variable = {
195 name: {
196 content: tokenValue,
197 range: new WebInspector.TextRange(lineNumber, column, li neNumber, newColumn)
198 },
199 value: {
200 content: "",
201 },
202 range: WebInspector.TextRange.createFromLocation(lineNumber, column)
203 }
204 state = States.VariableName;
205 } else if (tokenType["css-property"] || tokenType["css-meta"]) {
206 property = {
207 name: {
208 content: tokenValue,
209 range: new WebInspector.TextRange(lineNumber, column, li neNumber, newColumn)
210 },
211 value: {
212 content: "",
213 },
214 range: WebInspector.TextRange.createFromLocation(lineNumber, column)
215 }
216 state = States.PropertyName;
217 } else if (tokenType["css-def"] && tokenValue === "@include") {
218 state = States.MixinInclude;
219 }
220 break;
221 case States.VariableName:
222 if (tokenValue === ")" && tokenType === UndefTokenType) {
223 state = States.Initial;
224 } else if (tokenValue === ":" && tokenType === UndefTokenType) {
225 state = States.VariableValue;
226 variable.value.range = WebInspector.TextRange.createFromLocation (lineNumber, newColumn);
227 } else if (tokenType !== UndefTokenType) {
228 state = States.Initial;
229 }
230 break;
231 case States.VariableValue:
232 if (tokenValue === ";" && tokenType === UndefTokenType) {
233 variable.value.range.endLine = lineNumber;
234 variable.value.range.endColumn = column;
235 variable.range.endLine = lineNumber;
236 variable.range.endColumn = newColumn;
237 variables.push(variable);
238 state = States.Initial;
239 } else {
240 variable.value.content += tokenValue;
241 }
242 break;
243 case States.PropertyName:
244 if (tokenValue === ":" && tokenType === UndefTokenType) {
245 state = States.PropertyValue;
246 property.value.range = WebInspector.TextRange.createFromLocation (lineNumber, newColumn);
247 } else if (tokenType["property"]) {
248 property.name.contet += tokenValue;
249 }
250 break;
251 case States.PropertyValue:
252 if (tokenValue === ";" && tokenType === UndefTokenType) {
253 property.value.range.endLine = lineNumber;
254 property.value.range.endColumn = column;
255 property.range.endLine = lineNumber;
256 property.range.endColumn = newColumn;
257 properties.push(property);
258 state = States.Initial;
259 } else {
260 property.value.content += tokenValue;
261 }
262 break;
263 case States.MixinInclude:
264 if (tokenValue === "(" && tokenType === UndefTokenType) {
265 state = States.MixinValue;
266 mixin = {
267 range: WebInspector.TextRange.createFromLocation(lineNumber, newColumn),
268 value: ""
269 };
270 } else if (tokenValue === ";" && tokenType === UndefTokenType) {
271 state = States.Initial;
272 if (mixin)
273 mixinValues.push(mixin);
274 mixin = null;
275 }
276 break;
277 case States.MixinValue:
278 if (tokenValue === ")" && tokenType === UndefTokenType) {
279 state = States.MixinInclude;
280 mixin.range.endLine = lineNumber;
281 mixin.range.endColumn = column;
282 } else {
283 mixin.value += tokenValue;
284 }
285 break;
286 default:
287 console.assert(false, "Unknown CSS parser state.");
288 }
289 }
290 var tokenizer = new WebInspector.CodeMirrorUtils.TokenizerFactory().createTo kenizer("text/x-scss");
291 var lineNumber;
292 for (lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
293 var line = lines[lineNumber];
294 tokenizer(line, processToken);
295 }
296 return {
297 variables: variables,
298 properties: properties,
299 mixinValues: mixinValues
300 };
301 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/bindings/SASSSourceMapping.js ('k') | Source/devtools/front_end/bindings/SourceMapEditor.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698