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

Side by Side Diff: Source/devtools/front_end/cm/xml.js

Issue 354833004: DevTools: [CodeMirror] roll CodeMirror to version @e20d175 (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: address comments Created 6 years, 6 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
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
3
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11 })(function(CodeMirror) {
12 "use strict";
13
1 CodeMirror.defineMode("xml", function(config, parserConfig) { 14 CodeMirror.defineMode("xml", function(config, parserConfig) {
2 var indentUnit = config.indentUnit; 15 var indentUnit = config.indentUnit;
3 var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; 16 var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
4 var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag || true ; 17 var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
18 if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
5 19
6 var Kludges = parserConfig.htmlMode ? { 20 var Kludges = parserConfig.htmlMode ? {
7 autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'comm and': true, 21 autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'comm and': true,
8 'embed': true, 'frame': true, 'hr': true, 'img': true, 'in put': true, 22 'embed': true, 'frame': true, 'hr': true, 'img': true, 'in put': true,
9 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, 23 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
10 'track': true, 'wbr': true}, 24 'track': true, 'wbr': true},
11 implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, 25 implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
12 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot ': true, 26 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot ': true,
13 'th': true, 'tr': true}, 27 'th': true, 'tr': true},
14 contextGrabbers: { 28 contextGrabbers: {
(...skipping 11 matching lines...) Expand all
26 'rt': {'rp': true, 'rt': true}, 40 'rt': {'rp': true, 'rt': true},
27 'tbody': {'tbody': true, 'tfoot': true}, 41 'tbody': {'tbody': true, 'tfoot': true},
28 'td': {'td': true, 'th': true}, 42 'td': {'td': true, 'th': true},
29 'tfoot': {'tbody': true}, 43 'tfoot': {'tbody': true},
30 'th': {'td': true, 'th': true}, 44 'th': {'td': true, 'th': true},
31 'thead': {'tbody': true, 'tfoot': true}, 45 'thead': {'tbody': true, 'tfoot': true},
32 'tr': {'tr': true} 46 'tr': {'tr': true}
33 }, 47 },
34 doNotIndent: {"pre": true}, 48 doNotIndent: {"pre": true},
35 allowUnquoted: true, 49 allowUnquoted: true,
36 allowMissing: true 50 allowMissing: true,
51 caseFold: true
37 } : { 52 } : {
38 autoSelfClosers: {}, 53 autoSelfClosers: {},
39 implicitlyClosed: {}, 54 implicitlyClosed: {},
40 contextGrabbers: {}, 55 contextGrabbers: {},
41 doNotIndent: {}, 56 doNotIndent: {},
42 allowUnquoted: false, 57 allowUnquoted: false,
43 allowMissing: false 58 allowMissing: false,
59 caseFold: false
44 }; 60 };
45 var alignCDATA = parserConfig.alignCDATA; 61 var alignCDATA = parserConfig.alignCDATA;
46 62
47 // Return variables for tokenizers 63 // Return variables for tokenizers
48 var tagName, type; 64 var type, setStyle;
49 65
50 function inText(stream, state) { 66 function inText(stream, state) {
51 function chain(parser) { 67 function chain(parser) {
52 state.tokenize = parser; 68 state.tokenize = parser;
53 return parser(stream, state); 69 return parser(stream, state);
54 } 70 }
55 71
56 var ch = stream.next(); 72 var ch = stream.next();
57 if (ch == "<") { 73 if (ch == "<") {
58 if (stream.eat("!")) { 74 if (stream.eat("!")) {
59 if (stream.eat("[")) { 75 if (stream.eat("[")) {
60 if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); 76 if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
61 else return null; 77 else return null;
62 } else if (stream.match("--")) { 78 } else if (stream.match("--")) {
63 return chain(inBlock("comment", "-->")); 79 return chain(inBlock("comment", "-->"));
64 } else if (stream.match("DOCTYPE", true, true)) { 80 } else if (stream.match("DOCTYPE", true, true)) {
65 stream.eatWhile(/[\w\._\-]/); 81 stream.eatWhile(/[\w\._\-]/);
66 return chain(doctype(1)); 82 return chain(doctype(1));
67 } else { 83 } else {
68 return null; 84 return null;
69 } 85 }
70 } else if (stream.eat("?")) { 86 } else if (stream.eat("?")) {
71 stream.eatWhile(/[\w\._\-]/); 87 stream.eatWhile(/[\w\._\-]/);
72 state.tokenize = inBlock("meta", "?>"); 88 state.tokenize = inBlock("meta", "?>");
73 return "meta"; 89 return "meta";
74 } else { 90 } else {
75 var isClose = stream.eat("/"); 91 type = stream.eat("/") ? "closeTag" : "openTag";
76 tagName = "";
77 var c;
78 while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
79 if (!tagName) return "tag error";
80 type = isClose ? "closeTag" : "openTag";
81 state.tokenize = inTag; 92 state.tokenize = inTag;
82 return "tag"; 93 return "tag bracket";
83 } 94 }
84 } else if (ch == "&") { 95 } else if (ch == "&") {
85 var ok; 96 var ok;
86 if (stream.eat("#")) { 97 if (stream.eat("#")) {
87 if (stream.eat("x")) { 98 if (stream.eat("x")) {
88 ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); 99 ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
89 } else { 100 } else {
90 ok = stream.eatWhile(/[\d]/) && stream.eat(";"); 101 ok = stream.eatWhile(/[\d]/) && stream.eat(";");
91 } 102 }
92 } else { 103 } else {
93 ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); 104 ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
94 } 105 }
95 return ok ? "atom" : "error"; 106 return ok ? "atom" : "error";
96 } else { 107 } else {
97 stream.eatWhile(/[^&<]/); 108 stream.eatWhile(/[^&<]/);
98 return null; 109 return null;
99 } 110 }
100 } 111 }
101 112
102 function inTag(stream, state) { 113 function inTag(stream, state) {
103 var ch = stream.next(); 114 var ch = stream.next();
104 if (ch == ">" || (ch == "/" && stream.eat(">"))) { 115 if (ch == ">" || (ch == "/" && stream.eat(">"))) {
105 state.tokenize = inText; 116 state.tokenize = inText;
106 type = ch == ">" ? "endTag" : "selfcloseTag"; 117 type = ch == ">" ? "endTag" : "selfcloseTag";
107 return "tag"; 118 return "tag bracket";
108 } else if (ch == "=") { 119 } else if (ch == "=") {
109 type = "equals"; 120 type = "equals";
110 return null; 121 return null;
111 } else if (ch == "<") { 122 } else if (ch == "<") {
112 state.tokenize = inText; 123 state.tokenize = inText;
124 state.state = baseState;
125 state.tagName = state.tagStart = null;
113 var next = state.tokenize(stream, state); 126 var next = state.tokenize(stream, state);
114 return next ? next + " error" : "error"; 127 return next ? next + " tag error" : "tag error";
115 } else if (/[\'\"]/.test(ch)) { 128 } else if (/[\'\"]/.test(ch)) {
116 state.tokenize = inAttribute(ch); 129 state.tokenize = inAttribute(ch);
117 state.stringStartCol = stream.column(); 130 state.stringStartCol = stream.column();
118 return state.tokenize(stream, state); 131 return state.tokenize(stream, state);
119 } else { 132 } else {
120 stream.eatWhile(/[^\s\u00a0=<>\"\']/); 133 stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
121 return "word"; 134 return "word";
122 } 135 }
123 } 136 }
124 137
125 function inAttribute(quote) { 138 function inAttribute(quote) {
126 var closure = function(stream, state) { 139 var closure = function(stream, state) {
127 while (!stream.eol()) { 140 while (!stream.eol()) {
128 if (stream.next() == quote) { 141 if (stream.next() == quote) {
129 state.tokenize = inTag; 142 state.tokenize = inTag;
130 break; 143 break;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 } else { 175 } else {
163 state.tokenize = doctype(depth - 1); 176 state.tokenize = doctype(depth - 1);
164 return state.tokenize(stream, state); 177 return state.tokenize(stream, state);
165 } 178 }
166 } 179 }
167 } 180 }
168 return "meta"; 181 return "meta";
169 }; 182 };
170 } 183 }
171 184
172 var curState, curStream, setStyle; 185 function Context(state, tagName, startOfLine) {
173 function pass() { 186 this.prev = state.context;
174 for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i ]); 187 this.tagName = tagName;
188 this.indent = state.indented;
189 this.startOfLine = startOfLine;
190 if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.c ontext.noIndent))
191 this.noIndent = true;
175 } 192 }
176 function cont() { 193 function popContext(state) {
177 pass.apply(null, arguments); 194 if (state.context) state.context = state.context.prev;
178 return true;
179 } 195 }
180 196 function maybePopContext(state, nextTagName) {
181 function pushContext(tagName, startOfLine) {
182 var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.cont ext && curState.context.noIndent);
183 curState.context = {
184 prev: curState.context,
185 tagName: tagName,
186 indent: curState.indented,
187 startOfLine: startOfLine,
188 noIndent: noIndent
189 };
190 }
191 function popContext() {
192 if (curState.context) curState.context = curState.context.prev;
193 }
194
195 function element(type) {
196 if (type == "openTag") {
197 curState.tagName = tagName;
198 curState.tagStart = curStream.column();
199 return cont(attributes, endtag(curState.startOfLine));
200 } else if (type == "closeTag") {
201 var err = false;
202 if (curState.context) {
203 if (curState.context.tagName != tagName) {
204 if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.t oLowerCase())) {
205 popContext();
206 }
207 err = !curState.context || curState.context.tagName != tagName;
208 }
209 } else {
210 err = true;
211 }
212 if (err) setStyle = "error";
213 return cont(endclosetag(err));
214 }
215 return cont();
216 }
217 function endtag(startOfLine) {
218 return function(type) {
219 var tagName = curState.tagName;
220 curState.tagName = curState.tagStart = null;
221 if (type == "selfcloseTag" ||
222 (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.to LowerCase()))) {
223 maybePopContext(tagName.toLowerCase());
224 return cont();
225 }
226 if (type == "endTag") {
227 maybePopContext(tagName.toLowerCase());
228 pushContext(tagName, startOfLine);
229 return cont();
230 }
231 return cont();
232 };
233 }
234 function endclosetag(err) {
235 return function(type) {
236 if (err) setStyle = "error";
237 if (type == "endTag") { popContext(); return cont(); }
238 setStyle = "error";
239 return cont(arguments.callee);
240 };
241 }
242 function maybePopContext(nextTagName) {
243 var parentTagName; 197 var parentTagName;
244 while (true) { 198 while (true) {
245 if (!curState.context) { 199 if (!state.context) {
246 return; 200 return;
247 } 201 }
248 parentTagName = curState.context.tagName.toLowerCase(); 202 parentTagName = state.context.tagName;
249 if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || 203 if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
250 !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { 204 !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
251 return; 205 return;
252 } 206 }
253 popContext(); 207 popContext(state);
254 } 208 }
255 } 209 }
256 210
257 function attributes(type) { 211 function baseState(type, stream, state) {
258 if (type == "word") {setStyle = "attribute"; return cont(attribute, attribut es);} 212 if (type == "openTag") {
259 if (type == "endTag" || type == "selfcloseTag") return pass(); 213 state.tagStart = stream.column();
214 return tagNameState;
215 } else if (type == "closeTag") {
216 return closeTagNameState;
217 } else {
218 return baseState;
219 }
220 }
221 function tagNameState(type, stream, state) {
222 if (type == "word") {
223 state.tagName = stream.current();
224 setStyle = "tag";
225 return attrState;
226 } else {
227 setStyle = "error";
228 return tagNameState;
229 }
230 }
231 function closeTagNameState(type, stream, state) {
232 if (type == "word") {
233 var tagName = stream.current();
234 if (state.context && state.context.tagName != tagName &&
235 Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
236 popContext(state);
237 if (state.context && state.context.tagName == tagName) {
238 setStyle = "tag";
239 return closeState;
240 } else {
241 setStyle = "tag error";
242 return closeStateErr;
243 }
244 } else {
245 setStyle = "error";
246 return closeStateErr;
247 }
248 }
249
250 function closeState(type, _stream, state) {
251 if (type != "endTag") {
252 setStyle = "error";
253 return closeState;
254 }
255 popContext(state);
256 return baseState;
257 }
258 function closeStateErr(type, stream, state) {
260 setStyle = "error"; 259 setStyle = "error";
261 return cont(attributes); 260 return closeState(type, stream, state);
262 } 261 }
263 function attribute(type) { 262
264 if (type == "equals") return cont(attvalue, attributes); 263 function attrState(type, _stream, state) {
264 if (type == "word") {
265 setStyle = "attribute";
266 return attrEqState;
267 } else if (type == "endTag" || type == "selfcloseTag") {
268 var tagName = state.tagName, tagStart = state.tagStart;
269 state.tagName = state.tagStart = null;
270 if (type == "selfcloseTag" ||
271 Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
272 maybePopContext(state, tagName);
273 } else {
274 maybePopContext(state, tagName);
275 state.context = new Context(state, tagName, tagStart == state.indented);
276 }
277 return baseState;
278 }
279 setStyle = "error";
280 return attrState;
281 }
282 function attrEqState(type, stream, state) {
283 if (type == "equals") return attrValueState;
265 if (!Kludges.allowMissing) setStyle = "error"; 284 if (!Kludges.allowMissing) setStyle = "error";
266 else if (type == "word") {setStyle = "attribute"; return cont(attribute, att ributes);} 285 return attrState(type, stream, state);
267 return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
268 } 286 }
269 function attvalue(type) { 287 function attrValueState(type, stream, state) {
270 if (type == "string") return cont(attvaluemaybe); 288 if (type == "string") return attrContinuedState;
271 if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return co nt();} 289 if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return at trState;}
272 setStyle = "error"; 290 setStyle = "error";
273 return (type == "endTag" || type == "selfCloseTag") ? pass() : cont(); 291 return attrState(type, stream, state);
274 } 292 }
275 function attvaluemaybe(type) { 293 function attrContinuedState(type, stream, state) {
276 if (type == "string") return cont(attvaluemaybe); 294 if (type == "string") return attrContinuedState;
277 else return pass(); 295 return attrState(type, stream, state);
278 } 296 }
279 297
280 return { 298 return {
281 startState: function() { 299 startState: function() {
282 return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, tagStart: null, context: null}; 300 return {tokenize: inText,
301 state: baseState,
302 indented: 0,
303 tagName: null, tagStart: null,
304 context: null};
283 }, 305 },
284 306
285 token: function(stream, state) { 307 token: function(stream, state) {
286 if (!state.tagName && stream.sol()) { 308 if (!state.tagName && stream.sol())
287 state.startOfLine = true;
288 state.indented = stream.indentation(); 309 state.indented = stream.indentation();
310
311 if (stream.eatSpace()) return null;
312 type = null;
313 var style = state.tokenize(stream, state);
314 if ((style || type) && style != "comment") {
315 setStyle = null;
316 state.state = state.state(type || style, stream, state);
317 if (setStyle)
318 style = setStyle == "error" ? style + " error" : setStyle;
289 } 319 }
290 if (stream.eatSpace()) return null;
291
292 setStyle = type = tagName = null;
293 var style = state.tokenize(stream, state);
294 state.type = type;
295 if ((style || type) && style != "comment") {
296 curState = state; curStream = stream;
297 while (true) {
298 var comb = state.cc.pop() || element;
299 if (comb(type || style)) break;
300 }
301 }
302 state.startOfLine = false;
303 if (setStyle)
304 style = setStyle == "error" ? style + " error" : setStyle;
305 return style; 320 return style;
306 }, 321 },
307 322
308 indent: function(state, textAfter, fullLine) { 323 indent: function(state, textAfter, fullLine) {
309 var context = state.context; 324 var context = state.context;
310 // Indent multi-line strings (e.g. css). 325 // Indent multi-line strings (e.g. css).
311 if (state.tokenize.isInAttribute) { 326 if (state.tokenize.isInAttribute) {
312 return state.stringStartCol + 1; 327 if (state.tagStart == state.indented)
328 return state.stringStartCol + 1;
329 else
330 return state.indented + indentUnit;
313 } 331 }
314 if ((state.tokenize != inTag && state.tokenize != inText) || 332 if (context && context.noIndent) return CodeMirror.Pass;
315 context && context.noIndent) 333 if (state.tokenize != inTag && state.tokenize != inText)
316 return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; 334 return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
317 // Indent the starts of attribute names. 335 // Indent the starts of attribute names.
318 if (state.tagName) { 336 if (state.tagName) {
319 if (multilineTagIndentPastTag) 337 if (multilineTagIndentPastTag)
320 return state.tagStart + state.tagName.length + 2; 338 return state.tagStart + state.tagName.length + 2;
321 else 339 else
322 return state.tagStart + indentUnit * multilineTagIndentFactor; 340 return state.tagStart + indentUnit * multilineTagIndentFactor;
323 } 341 }
324 if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0; 342 if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
325 if (context && /^<\//.test(textAfter)) 343 var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
326 context = context.prev; 344 if (tagAfter && tagAfter[1]) { // Closing tag spotted
345 while (context) {
346 if (context.tagName == tagAfter[2]) {
347 context = context.prev;
348 break;
349 } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
350 context = context.prev;
351 } else {
352 break;
353 }
354 }
355 } else if (tagAfter) { // Opening tag spotted
356 while (context) {
357 var grabbers = Kludges.contextGrabbers[context.tagName];
358 if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
359 context = context.prev;
360 else
361 break;
362 }
363 }
327 while (context && !context.startOfLine) 364 while (context && !context.startOfLine)
328 context = context.prev; 365 context = context.prev;
329 if (context) return context.indent + indentUnit; 366 if (context) return context.indent + indentUnit;
330 else return 0; 367 else return 0;
331 }, 368 },
332 369
333 electricChars: "/", 370 electricInput: /<\/[\s\w:]+>$/,
334 blockCommentStart: "<!--", 371 blockCommentStart: "<!--",
335 blockCommentEnd: "-->", 372 blockCommentEnd: "-->",
336 373
337 configuration: parserConfig.htmlMode ? "html" : "xml", 374 configuration: parserConfig.htmlMode ? "html" : "xml",
338 helperType: parserConfig.htmlMode ? "html" : "xml" 375 helperType: parserConfig.htmlMode ? "html" : "xml"
339 }; 376 };
340 }); 377 });
341 378
342 CodeMirror.defineMIME("text/xml", "xml"); 379 CodeMirror.defineMIME("text/xml", "xml");
343 CodeMirror.defineMIME("application/xml", "xml"); 380 CodeMirror.defineMIME("application/xml", "xml");
344 if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) 381 if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
345 CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); 382 CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
383
384 });
OLDNEW
« no previous file with comments | « Source/devtools/front_end/cm/shell.js ('k') | Source/devtools/front_end/script_formatter_worker/ScriptFormatterWorker.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698