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

Side by Side Diff: Source/devtools/front_end/CSSFormatter.js

Issue 18347003: DevTools: Implement CSS pretty-printing (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebased Created 7 years, 2 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
« no previous file with comments | « Source/devtools/devtools.gyp ('k') | Source/devtools/front_end/JavaScriptFormatter.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 function CSSFormattedContentBuilder(content, mapping, originalOffset, formattedO ffset, indentString)
pfeldman 2013/09/30 12:07:26 Please annotate.
apavlov 2013/09/30 12:50:29 Done.
32 {
33 this._originalContent = content;
34 this._originalOffset = originalOffset;
35 this._lastOriginalPosition = 0;
36
37 this._formattedContent = [];
38 this._formattedContentLength = 0;
39 this._formattedOffset = formattedOffset;
40 this._lastFormattedPosition = 0;
41
42 this._mapping = mapping;
43
44 this._lineNumber = 0;
45 this._nestingLevel = 0;
46 this._needNewLines = 0;
47 this._atLineStart = true;
48 this._indentString = indentString;
49 this._cachedIndents = {};
50 }
51
52 CSSFormattedContentBuilder.prototype = {
53 addToken: function(token, startPosition, startLine, startColumn)
54 {
55 if ((this._isWhitespaceRun || this._atLineStart) && /^\s+$/.test(token))
56 return;
57
58 if (this._isWhitespaceRun && this._lineNumber === startLine && !this._ne edNewLines)
59 this._addText(" ");
60
61 this._isWhitespaceRun = false;
62 this._atLineStart = false;
63
64 while (this._lineNumber < startLine) {
65 this._addText("\n");
66 this._addIndent();
67 this._needNewLines = 0;
68 this._lineNumber += 1;
69 this._atLineStart = true;
70 }
71
72 if (this._needNewLines) {
73 this.flushNewLines();
74 this._addIndent();
75 this._atLineStart = true;
76 }
77
78 this._addMappingIfNeeded(startPosition);
79 this._addText(token);
80 this._lineNumber = startLine;
81 },
82
83 addSpace: function()
84 {
85 if (this._isWhitespaceRun)
86 return;
87 this._isWhitespaceRun = true;
88 },
89
90 addNewLine: function()
91 {
92 ++this._needNewLines;
93 },
94
95 flushNewLines: function(atLeastOne)
96 {
97 var newLineCount = atLeastOne && !this._needNewLines ? 1 : this._needNew Lines;
98 if (newLineCount)
99 this._isWhitespaceRun = false;
100 for (var i = 0; i < newLineCount; ++i)
101 this._addText("\n");
102 this._needNewLines = 0;
103 },
104
105 increaseNestingLevel: function()
106 {
107 this._nestingLevel += 1;
108 },
109
110 decreaseNestingLevel: function(addNewline)
111 {
112 if (this._nestingLevel)
113 this._nestingLevel -= 1;
114 if (addNewline)
115 this.addNewLine();
116 },
117
118 content: function()
119 {
120 return this._formattedContent.join("");
121 },
122
123 mapping: function()
124 {
125 return { original: this._originalPositions, formatted: this._formattedPo sitions };
126 },
127
128 _addIndent: function()
129 {
130 if (this._cachedIndents[this._nestingLevel]) {
131 this._addText(this._cachedIndents[this._nestingLevel]);
132 return;
133 }
134
135 var fullIndent = "";
136 for (var i = 0; i < this._nestingLevel; ++i)
137 fullIndent += this._indentString;
138 this._addText(fullIndent);
139
140 // Cache a maximum of 20 nesting level indents.
141 if (this._nestingLevel <= 20)
142 this._cachedIndents[this._nestingLevel] = fullIndent;
143 },
144
145 _addText: function(text)
146 {
147 if (!text)
148 return;
149 this._formattedContent.push(text);
150 this._formattedContentLength += text.length;
151 },
152
153 _addMappingIfNeeded: function(originalPosition)
154 {
155 if (originalPosition - this._lastOriginalPosition === this._formattedCon tentLength - this._lastFormattedPosition)
156 return;
157 this._mapping.original.push(this._originalOffset + originalPosition);
158 this._lastOriginalPosition = originalPosition;
159 this._mapping.formatted.push(this._formattedOffset + this._formattedCont entLength);
160 this._lastFormattedPosition = this._formattedContentLength;
161 }
162 }
163
164 function findAll(text, string)
165 {
166 var matches = [];
167 var i = text.indexOf(string);
168 while (i !== -1) {
169 matches.push(i);
170 i = text.indexOf(string, i + string.length);
171 }
172 return matches;
173 }
174
175 function lineEndings(text)
176 {
177 var lineEndings = text.findAll("\n");
178 lineEndings.push(text.length);
179 return lineEndings;
180 }
181
182 function CSSFormatter(content, builder)
pfeldman 2013/09/30 12:07:26 Please define public class first. You also want to
apavlov 2013/09/30 12:50:29 Done.
183 {
184 this._content = content;
185 this._builder = builder;
186 this._lastLine = -1;
187 this._state = {};
188 }
189
190 CSSFormatter.prototype = {
191 format: function()
192 {
193 this._lineEndings = lineEndings(this._content);
194 var tokenize = WebInspector.CodeMirrorUtils.createTokenizer("text/css");
195 var lines = this._content.split("\n");
196
197 for (var i = 0; i < lines.length; ++i) {
198 var line = lines[i];
199 tokenize(line, this._tokenCallback.bind(this, i));
200 }
201 this._builder.flushNewLines(true);
202 },
203
204 _tokenCallback: function(startLine, token, type, startColumn)
205 {
206 if (startLine !== this._lastLine)
207 this._state.eatWhitespace = true;
208 if (/^css-property/.test(type) && !this._state.inPropertyValue)
209 this._state.seenProperty = true;
210 this._lastLine = startLine;
211 var isWhitespace = /^\s+$/.test(token);
212 if (isWhitespace) {
213 if (!this._state.eatWhitespace)
214 this._builder.addSpace();
215 return;
216 }
217 this._state.eatWhitespace = false;
218 if (token === "\n")
219 return;
220
221 if (token !== "}") {
222 if (this._state.afterClosingBrace)
223 this._builder.addNewLine();
224 this._state.afterClosingBrace = false;
225 }
226 var startPosition = (startLine ? this._lineEndings[startLine - 1] : 0) + startColumn;
227 if (token === "}") {
228 if (this._state.inPropertyValue)
229 this._builder.addNewLine();
230 this._builder.decreaseNestingLevel();
231 this._state.afterClosingBrace = true;
232 this._state.inPropertyValue = false;
233 } else if (token === ":" && !this._state.inPropertyValue && this._state. seenProperty) {
234 this._builder.addToken(token, startPosition, startLine, startColumn) ;
235 this._builder.addSpace();
236 this._state.eatWhitespace = true;
237 this._state.inPropertyValue = true;
238 this._state.seenProperty = false;
239 return;
240 } else if (token === "{") {
241 this._builder.addSpace();
242 this._builder.addToken(token, startPosition, startLine, startColumn) ;
243 this._builder.addNewLine();
244 this._builder.increaseNestingLevel();
245 return;
246 }
247
248 this._builder.addToken(token, startPosition, startLine, startColumn);
249
250 if (type === "css-comment" && !this._state.inPropertyValue && !this._sta te.seenProperty)
251 this._builder.addNewLine();
252 if (token === ";" && this._state.inPropertyValue) {
253 this._state.inPropertyValue = false;
254 this._builder.addNewLine();
255 } else if (token === "}") {
256 this._builder.addNewLine();
257 }
258 }
259 }
OLDNEW
« no previous file with comments | « Source/devtools/devtools.gyp ('k') | Source/devtools/front_end/JavaScriptFormatter.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698