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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: Source/devtools/front_end/bindings/SASSStructureMapping.js
diff --git a/Source/devtools/front_end/bindings/SASSStructureMapping.js b/Source/devtools/front_end/bindings/SASSStructureMapping.js
new file mode 100644
index 0000000000000000000000000000000000000000..593a9667492e0ad39147dd5cd4b9d7ab60b8fa60
--- /dev/null
+++ b/Source/devtools/front_end/bindings/SASSStructureMapping.js
@@ -0,0 +1,301 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ * @param {!Map<string, string>} sassSources
+ */
+WebInspector.SASSStructureMapping = function(cssStruct, sassSources)
+{
+ this._sources = sassSources;
+ this._cssStruct = cssStruct;
+ this._sassStructs = new Map();
+}
+
+WebInspector.SASSStructureMapping.prototype = {
+ cssPropertyValueToSASS: function(cssValueRange, sourceMap)
+ {
+ var entry = sourceMap.findEntry(cssValueRange.endLine, cssValueRange.endColumn);
+ var url = entry.sourceURL;
+ var struct = this._structForURL(url);
+ if (!struct) {
+ console.error("Failed to get structure of " + url);
+ return null;
+ }
+ var sassValue = this._sassValue(struct, entry);
+ if (!sassValue)
+ return null;
+ return {
+ url: url,
+ range: sassValue.range
+ };
+ },
+
+ cssPropertyToSASS: function(cssPropertyRange, sourceMap)
+ {
+ var entry = sourceMap.findEntry(cssPropertyRange.startLine, cssPropertyRange.startColumn);
+ var struct = this._structForURL(entry.sourceURL);
+ if (!struct) {
+ console.error("Failed to get structure of " + entry.sourceURL);
+ return null;
+ }
+ var sassProperty = this._sassProperty(struct, entry);
+ if (!sassProperty)
+ return null;
+ return {
+ url: entry.sourceURL,
+ range: sassProperty.range
+ };
+ },
+
+ sassPropertyValueToCSS: function(sassURL, sassValueRange, sourceMap)
+ {
+ var reversedEntries = sourceMap.findEntriesReversed(sassURL, sassValueRange.endLine, sassValueRange.endColumn - 1);
+ var result = [];
+ for (var i = 0; i < reversedEntries.length; ++i) {
+ var value = this._cssValue(reversedEntries[i]);
+ console.assert(value, "Failed to find reversed mapped property value.");
+ result.push(value);
+ }
+ return result;
+ },
+
+ _sassProperty: function(struct, entry)
+ {
+ for (var i = 0; i < struct.properties.length; ++i) {
+ var property = struct.properties[i];
+ if (this._rangeContainsSourceMapping(property.range, entry))
+ return property;
+ }
+ return null;
+ },
+
+ _sassVariable: function(struct, entry)
+ {
+ for (var i = 0; i < struct.variables.length; ++i) {
+ var variable = struct.variables[i];
+ if (this._rangeContainsSourceMapping(variable.range, entry))
+ return variable;
+ }
+ return null;
+ },
+
+ _sassValue: function(struct, entry)
+ {
+ var sassProperty = this._sassProperty(struct, entry);
+ if (sassProperty && this._rangeContainsSourceMapping(sassProperty.value.range, entry))
+ return sassProperty.value;
+
+ var sassVariable = this._sassVariable(struct, entry);
+ if (sassVariable && this._rangeContainsSourceMapping(sassVariable.value.range, entry))
+ return sassVariable.value;
+ for (var i = 0; i < struct.mixinValues.length; ++i) {
+ var mixinValue = struct.mixinValues[i];
+ if (this._rangeContainsSourceMapping(mixinValue.range, entry))
+ return mixinValue;
+ }
+ return null;
+ },
+
+ _cssProperty: function(entry)
+ {
+ for (var i = 0; i < this._cssStruct.length; ++i) {
+ var rule = this._cssStruct[i];
+ for (var j = 0; j < rule.properties.length; ++j) {
+ var property = rule.properties[j];
+ if (this._rangeContainsCompiledMapping(property.range, entry))
+ return property;
+ }
+ }
+ return null;
+ },
+
+ _cssValue: function(entry)
+ {
+ var cssProperty = this._cssProperty(entry);
+ if (cssProperty && this._rangeContainsCompiledMapping(cssProperty.valueRange, entry))
+ return cssProperty;
+ return null;
+ },
+
+ _rangeContainsSourceMapping: function(range, entry)
+ {
+ if (range.startLine === range.endLine)
+ return range.startLine === entry.sourceLineNumber && range.startColumn <= entry.sourceColumnNumber && entry.sourceColumnNumber <= range.endColumn;
+ if (range.startLine === entry.sourceLineNumber)
+ return range.startColumn <= entry.sourceColumnNumber;
+ if (range.endLine === entry.sourceLineNumber)
+ return entry.sourceColumnNumber <= range.endColumn;
+ return range.startLine < entry.sourceLineNumber && entry.sourceLineNumber < range.endLine;
+ },
+
+ _rangeContainsCompiledMapping: function(range, entry)
+ {
+ if (range.startLine === range.endLine)
+ return range.startLine === entry.lineNumber && range.startColumn <= entry.columnNumber && entry.columnNumber <= range.endColumn;
+ if (range.startLine === entry.lineNumber)
+ return range.startColumn <= entry.columnNumber;
+ if (range.endLine === entry.lineNumber)
+ return entry.columnNumber <= range.endColumn;
+ return range.startLine < entry.lineNumber && entry.lineNumber < range.endLine;
+ },
+
+ _structForURL: function(sassURL)
+ {
+ if (this._sassStructs.has(sassURL))
+ return this._sassStructs.get(sassURL);
+ var source = this._sources.get(sassURL);
+ if (!source)
+ return null;
+ var result = WebInspector.SASSStructureMapping.parseSASS(source);
+ this._sassStructs.set(sassURL, result);
+ return result;
+ }
+}
+
+
+WebInspector.SASSStructureMapping.SCSSParserStates = {
+ Initial: "Initial",
+ PropertyName: "PropertyName",
+ PropertyValue: "PropertyValue",
+ VariableName: "VariableName",
+ VariableValue: "VariableValue",
+ MixinInclude: "MixinInclude",
+ MixinValue: "MixinValue"
+}
+
+WebInspector.SASSStructureMapping.parseSASS = function(text)
+{
+ var lines = text.split("\n");
+ var properties = [];
+ var variables = [];
+ var mixinValues = [];
+
+ var States = WebInspector.SASSStructureMapping.SCSSParserStates;
+ var state = States.Initial;
+ var property;
+ var variable;
+ var mixin;
+ var UndefTokenType = {};
+
+ /**
+ * @param {string} tokenValue
+ * @param {?string} tokenTypes
+ * @param {number} column
+ * @param {number} newColumn
+ */
+ function processToken(tokenValue, tokenTypes, column, newColumn)
+ {
+ var tokenType = tokenTypes ? tokenTypes.split(" ").keySet() : UndefTokenType;
+ switch (state) {
+ case States.Initial:
+ if (tokenType["css-variable-2"]) {
+ variable = {
+ name: {
+ content: tokenValue,
+ range: new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn)
+ },
+ value: {
+ content: "",
+ },
+ range: WebInspector.TextRange.createFromLocation(lineNumber, column)
+ }
+ state = States.VariableName;
+ } else if (tokenType["css-property"] || tokenType["css-meta"]) {
+ property = {
+ name: {
+ content: tokenValue,
+ range: new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn)
+ },
+ value: {
+ content: "",
+ },
+ range: WebInspector.TextRange.createFromLocation(lineNumber, column)
+ }
+ state = States.PropertyName;
+ } else if (tokenType["css-def"] && tokenValue === "@include") {
+ state = States.MixinInclude;
+ }
+ break;
+ case States.VariableName:
+ if (tokenValue === ")" && tokenType === UndefTokenType) {
+ state = States.Initial;
+ } else if (tokenValue === ":" && tokenType === UndefTokenType) {
+ state = States.VariableValue;
+ variable.value.range = WebInspector.TextRange.createFromLocation(lineNumber, newColumn);
+ } else if (tokenType !== UndefTokenType) {
+ state = States.Initial;
+ }
+ break;
+ case States.VariableValue:
+ if (tokenValue === ";" && tokenType === UndefTokenType) {
+ variable.value.range.endLine = lineNumber;
+ variable.value.range.endColumn = column;
+ variable.range.endLine = lineNumber;
+ variable.range.endColumn = newColumn;
+ variables.push(variable);
+ state = States.Initial;
+ } else {
+ variable.value.content += tokenValue;
+ }
+ break;
+ case States.PropertyName:
+ if (tokenValue === ":" && tokenType === UndefTokenType) {
+ state = States.PropertyValue;
+ property.value.range = WebInspector.TextRange.createFromLocation(lineNumber, newColumn);
+ } else if (tokenType["property"]) {
+ property.name.contet += tokenValue;
+ }
+ break;
+ case States.PropertyValue:
+ if (tokenValue === ";" && tokenType === UndefTokenType) {
+ property.value.range.endLine = lineNumber;
+ property.value.range.endColumn = column;
+ property.range.endLine = lineNumber;
+ property.range.endColumn = newColumn;
+ properties.push(property);
+ state = States.Initial;
+ } else {
+ property.value.content += tokenValue;
+ }
+ break;
+ case States.MixinInclude:
+ if (tokenValue === "(" && tokenType === UndefTokenType) {
+ state = States.MixinValue;
+ mixin = {
+ range: WebInspector.TextRange.createFromLocation(lineNumber, newColumn),
+ value: ""
+ };
+ } else if (tokenValue === ";" && tokenType === UndefTokenType) {
+ state = States.Initial;
+ if (mixin)
+ mixinValues.push(mixin);
+ mixin = null;
+ }
+ break;
+ case States.MixinValue:
+ if (tokenValue === ")" && tokenType === UndefTokenType) {
+ state = States.MixinInclude;
+ mixin.range.endLine = lineNumber;
+ mixin.range.endColumn = column;
+ } else {
+ mixin.value += tokenValue;
+ }
+ break;
+ default:
+ console.assert(false, "Unknown CSS parser state.");
+ }
+ }
+ var tokenizer = new WebInspector.CodeMirrorUtils.TokenizerFactory().createTokenizer("text/x-scss");
+ var lineNumber;
+ for (lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
+ var line = lines[lineNumber];
+ tokenizer(line, processToken);
+ }
+ return {
+ variables: variables,
+ properties: properties,
+ mixinValues: mixinValues
+ };
+}
« 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