173 changes: 114 additions & 59 deletions doc/manual.html

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion doc/realworld.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://cargocollective.com/">Cargo Collective</a> (creative publishing platform)</li>
<li><a href="http://www.codebugapp.com/">Codebug</a> (PHP Xdebug front-end)</li>
<li><a href="http://code.google.com/p/codemirror2-gwt/">CodeMirror2-GWT</a> (Google Web Toolkit wrapper)</li>
<li><a href="http://codepen.io">Codepen</a> (gallery of animations)</li>
<li><a href="http://codev.it/">Codev</a> (collaborative IDE)</li>
<li><a href="http://ot.substance.io/demo/">Collaborative CodeMirror demo</a> (CodeMirror + operational transforms)</li>
<li><a href="http://www.ckwnc.com/">CKWNC</a> (UML editor)</li>
Expand All @@ -36,6 +37,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://elm-lang.org/Examples.elm">Elm language examples</a></li>
<li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a> (book)</li>
<li><a href="http://www.fastfig.com/">Fastfig</a> (online computation/math tool)</li>
<li><a href="https://metacpan.org/module/Farabi">Farabi</a> (Perl editor)</li>
<li><a href="http://blog.pamelafox.org/2012/02/interactive-html5-slides-with-fathomjs.html">FathomJS integration</a> (slides with editors, again)</li>
<li><a href="http://tour.golang.org">Go language tour</a></li>
<li><a href="https://github.com/github/android">GitHub's Android app</a></li>
Expand All @@ -44,27 +46,32 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://megafonweblab.github.com/histone-javascript/">Histone template engine playground</a></li>
<li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li>
<li><a href="http://extensions.joomla.org/extensions/edition/editors/8723">Joomla plugin</a></li>
<li><a href="http://jqfundamentals.com/">jQuery fundamentals</a> (interactive tutorial)</li>
<li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>
<li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>
<li><a href="http://jumpseller.com/">Jumpseller</a> (online store builder)</li>
<li><a href="http://kl1p.com/cmtest/1">kl1p</a> (paste service)</li>
<li><a href="http://www.chris-granger.com/2012/04/12/light-table---a-new-ide-concept/">Light Table</a> (experimental IDE)</li>
<li><a href="http://www.mergely.com/">Mergely</a> (interactive diffing)</li>
<li><a href="https://notex.ch">NoTex</a> (rST authoring)</li>
<li><a href="http://clrhome.org/asm/">ORG</a> (z80 assembly IDE)</li>
<li><a href="https://github.com/mamacdon/orion-codemirror">Orion-CodeMirror integration</a> (running CodeMirror modes in Orion)</li>
<li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
<li><a href="http://prose.io/">Prose.io</a> (github content editor)</li>
<li><a href="http://ql.io/">ql.io</a> (http API query helper)</li>
<li><a href="http://qyapp.com">QiYun web app platform</a></li>
<li><a href="http://ariya.ofilabs.com/2011/09/hybrid-webnative-desktop-codemirror.html">Qt+Webkit integration</a> (building a desktop CodeMirror app)</li>
<li><a href="http://www.sketchpatch.net/labs/livecodelabIntro.html">sketchPatch Livecodelab</a></li>
<li><a href="http://www.skulpt.org/">Skulpt</a> (in-browser Python environment)</li.
<li><a href="http://www.skulpt.org/">Skulpt</a> (in-browser Python environment)</li>
<li><a href="http://www.solidshops.com/">SolidShops</a> (hosted e-commerce platform)</li>
<li><a href="http://sqlfiddle.com">SQLFiddle</a> (SQL playground)</li>
<li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>
<li><a href="http://enjalot.com/tributary/2636296/sinwaves.js">Tributary</a> (augmented editing)</li>
<li><a href="http://turbopy.com/">TurboPY</a> (web publishing framework)</li>
<li><a href="http://webglplayground.net/">WebGL playground</a></li>
<li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>
<li><a href="http://wordpress.org/extend/plugins/codemirror-for-codeeditor/">WordPress plugin</a></li>
<li><a href="http://www.xosystem.org/home/applications_websites/xosystem_website/xoside_EN.php">XOSide</a> (online editor)</li>
<li><a href="http://media.chikuyonok.ru/codemirror2/">Zen Coding</a> (fast XML editing)</li>
</ul>

Expand Down
26 changes: 20 additions & 6 deletions doc/upgrade_v3.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,30 @@ <h2 id=events>Event handling</h2>
which act more as hooks than as event handlers, are still there in
their old form.)</p>

<h2 id=marktext>markText method arguments</h2>

<p>The <a href="manual.html#markText"><code>markText</code></a> method
(which has gained some interesting new features, such as creating
atomic and read-only spans, or replacing spans with widgets) no longer
takes the CSS class name as a separate argument, but makes it an
optional field in the options object instead.</p>

<h2 id=folding>Line folding</h2>

<p>The interface for folding lines has been overhauled to deal with
regions of lines rather than individual lines, and to allow
auto-expansion when the cursor enters the folded region.
See <a href="manual.html#foldLines"><code>foldLines</code></a>
and <a href="manual.html#unfoldLines"><code>unfoldLines</code></a> for
the new API.</p>
<p>The interface for hiding lines has been
removed. <a href="manual.html#markText"><code>markText</code></a> can
now be used to do the same in a more flexible and powerful way.</p>

<p>The <a href="../demo/folding.html">folding script</a> has been
updated to use the new interface, and should now be more robust.</p>

<h2 id=lineclass>Line CSS classes</h2>

<p>The <code>setLineClass</code> method has been replaced
by <a href="manual.html#addLineClass"><code>addLineClass</code></a>
and <a href="manual.html#removeLineClass"><code>removeLineClass</code></a>,
which allow more modular control over the classes attached to a line.</p>

<h2 id=positions>Position properties</h2>

<p>All methods that take or return objects that represent screen
Expand Down Expand Up @@ -137,6 +149,8 @@ <h2>Contents</h2>
<li><a href="#gutters">Gutter model</a></li>
<li><a href="#events">Event handling</a></li>
<li><a href="#folding">Line folding</a></li>
<li><a href="#marktext">markText method arguments</a></li>
<li><a href="#lineclass">Line CSS classes</a></li>
<li><a href="#positions">Position properties</a></li>
<li><a href="#matchbrackets">Bracket matching</a></li>
<li><a href="#modes">Mode management</a></li>
Expand Down
55 changes: 41 additions & 14 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<title>CodeMirror</title>
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold"/>
<link rel="stylesheet" type="text/css" href="doc/docs.css"/>
<link rel="alternate" href="http://twitter.com/statuses/user_timeline/242283288.rss" type="application/rss+xml"/>
<link rel="alternate" href="https://groups.google.com/group/codemirror-announce/feed/atom_v1_0_topics.xml" type="application/atom+xml"/>
</head>
<body>

Expand Down Expand Up @@ -54,7 +54,7 @@ <h2 style="margin-top: 0">Supported modes:</h2>
<li><a href="mode/jinja2/index.html">Jinja2</a></li>
<li><a href="mode/less/index.html">LESS</a></li>
<li><a href="mode/lua/index.html">Lua</a></li>
<li><a href="mode/markdown/index.html">Markdown</a> (<a href="mode/gfm/index.html">Github-flavour</a>)</li>
<li><a href="mode/markdown/index.html">Markdown</a> (<a href="mode/gfm/index.html">GitHub-flavour</a>)</li>
<li><a href="mode/mysql/index.html">MySQL</a></li>
<li><a href="mode/ntriples/index.html">NTriples</a></li>
<li><a href="mode/ocaml/index.html">OCaml</a></li>
Expand Down Expand Up @@ -87,6 +87,7 @@ <h2 style="margin-top: 0">Supported modes:</h2>
<li><a href="mode/xml/index.html">XML/HTML</a></li>
<li><a href="mode/xquery/index.html">XQuery</a></li>
<li><a href="mode/yaml/index.html">YAML</a></li>
<li><a href="mode/z80/index.html">Z80</a></li>
</ul>

</div><div class="left2 blk">
Expand Down Expand Up @@ -199,7 +200,7 @@ <h2 id="support">Support and bug reports</h2>

<p>Though bug reports through e-mail are responded to, the preferred
way to report bugs is to use
the <a href="http://github.com/marijnh/CodeMirror/issues">Github
the <a href="http://github.com/marijnh/CodeMirror/issues">GitHub
issue tracker</a>. Before reporting a
bug, <a href="doc/reporting.html">read these pointers</a>. Also,
the issue tracker is for <em>bugs</em>, not requests for help.</p>
Expand Down Expand Up @@ -290,11 +291,47 @@ <h2>Reading material</h2>

<h2 id=releases>Releases</h2>

<p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-2.36.zip">Version 2.36</a>:</p>

<ul class="rel-note">
<li>New mode: <a href="mode/z80/index.html">Z80 assembly</a>.</li>
<li>New theme: <a href="demo/theme.html?twilight">Twilight</a>.</li>
<li>Add command-line compression helper.</li>
<li>Make <a href="doc/manual.html#scrollIntoView"><code>scrollIntoView</code></a> public.</li>
<li>Add <a href="doc/manual.html#defaultTextHeight"><code>defaultTextHeight</code></a> method.</li>
<li>Various extensions to the vim keymap.</li>
<li>Make <a href="mode/php/index.html">PHP mode</a> build on <a href="mode/htmlmixed/index.html">mixed HTML mode</a>.</li>
<li>Add <a href="doc/manual.html#util_continuecomment">comment-continuing</a> add-on.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v2.35...v2.36">list of patches</a>.</li>
</ul>

<p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc1.zip">Version 3.0, release candidate 1</a>:</p>

<p class="rel-note"><strong>New major version</strong>. Only partially
backwards-compatible. See
the <a href="doc/upgrade_v3.html">upgrading
guide</a> for more information. Changes since beta 2:</p>

<ul class="rel-note">
<li>New theme: <a href="demo/theme.html?solarized%20light">Solarized</a>.</li>
<li>Introduce <a href="doc/manual.html#addLineClass"><code>addLineClass</code></a>
and <a href="doc/manual.html#removeLineClass"><code>removeLineClass</code></a>,
drop <code>setLineClass</code>.</li>
<li>Add a <em>lot</em> of
new <a href="doc/manual.html#markText">options for marked text</a>
(read-only, atomic, collapsed, widget replacement).</li>
<li>Remove the old code folding interface in favour of these new ranges.</li>
<li>Add <a href="doc/manual.html#isClean"><code>isClean</code></a>/<a href="doc/manual.html#markClean"><code>markClean</code></a> methods.</li>
<li>Remove <code>compoundChange</code> method, use better undo-event-combining heuristic.</li>
<li>Improve scrolling performance smoothness.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0beta2...v3.0rc1">list of patches</a>.</li>
</ul>

<p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-2.35.zip">Version 2.35</a>:</p>

<ul class="rel-note">
<li>New (sub) mode: <a href="mode/javascript/typescript.html">TypeScript</a>.</li>
<li>Don't overwrite (insert key) when pasing.</li>
<li>Don't overwrite (insert key) when pasting.</li>
<li>Fix several bugs in <a href="doc/manual.html#markText"><code>markText</code></a>/undo interaction.</li>
<li>Better indentation of JavaScript code without semicolons.</li>
<li>Add <a href="doc/manual.html#defineInitHook"><code>defineInitHook</code></a> function.</li>
Expand All @@ -303,11 +340,6 @@ <h2 id=releases>Releases</h2>

<p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-3.0beta2.zip">Version 3.0, beta 2</a>:</p>

<p class="rel-note"><strong>BETA release, new major version</strong>. Only partially
backwards-compatible. See
the <a href="doc/upgrade_v3.html">upgrading
guide</a> for more information. Changes since beta1:</p>

<ul class="rel-note">
<li>Fix page-based coordinate computation.</li>
<li>Fix firing of <a href="doc/manual.html#event_gutterClick"><code>gutterClick</code></a> event.</li>
Expand Down Expand Up @@ -337,11 +369,6 @@ <h2 id=releases>Releases</h2>

<p class="rel">19-09-2012: <a href="http://codemirror.net/codemirror-3.0beta1.zip">Version 3.0, beta 1</a>:</p>

<p class="rel-note"><strong>BETA release, new major version</strong>. Only partially
backwards-compatible. See
the <a href="doc/upgrade_v3.html">upgrading
guide</a> for more information. Major new features are:</p>

<ul class="rel-note">
<li>Bi-directional text support.</li>
<li>More powerful gutter model.</li>
Expand Down
3 changes: 2 additions & 1 deletion keymap/emacs.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"Alt-Y": function(cm) {cm.replaceSelection(popFromRing());},
"Ctrl-/": "undo", "Shift-Ctrl--": "undo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
"Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete",
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete", "Alt-V": "goPageUp",
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
fallthrough: ["basic", "emacsy"]
};

Expand Down
417 changes: 263 additions & 154 deletions keymap/vim.js

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion lib/codemirror.css
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
}
.CodeMirror-gutter {
height: 100%;
float: left;
display: inline-block;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-elt {
position: absolute;
Expand Down Expand Up @@ -223,6 +226,9 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
background: rgba(255, 255, 0, .4);
}

/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }

@media print {
/* Hide the cursor when printing */
.CodeMirror pre.CodeMirror-cursor {
Expand Down
2,030 changes: 1,175 additions & 855 deletions lib/codemirror.js

Large diffs are not rendered by default.

27 changes: 3 additions & 24 deletions lib/util/closetag.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,6 @@
if (!cm.getOption('closeTagEnabled')) {
throw CodeMirror.Pass;
}

/*
* Relevant structure of token:
*
* htmlmixed
* className
* state
* htmlState
* type
* tagName
* context
* tagName
* mode
*
* xml
* className
* state
* tagName
* type
*/

var pos = cm.getCursor();
var tok = cm.getTokenAt(pos);
var state = innerState(cm, tok.state);
Expand All @@ -73,7 +52,7 @@
if (ch == '>') {
var type = state.type;

if (tok.className == 'tag' && type == 'closeTag') {
if (tok.type == 'tag' && type == 'closeTag') {
throw CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.
}

Expand All @@ -86,7 +65,7 @@
if (!state) throw CodeMirror.Pass;
var type = state.type;

if (tok.className == 'tag' && type != 'selfcloseTag') {
if (tok.type == 'tag' && type != 'selfcloseTag') {
var tagName = state.tagName;
if (tagName.length > 0 && shouldClose(cm, vd, tagName)) {
insertEndTag(cm, indent, pos, tagName);
Expand All @@ -99,7 +78,7 @@
cm.replaceSelection("");

} else if (ch == '/') {
if (tok.className == 'tag' && tok.string == '<') {
if (tok.type == 'tag' && tok.string == '<') {
var ctx = state.context, tagName = ctx ? ctx.tagName : '';
if (tagName.length > 0) {
completeEndTag(cm, pos, tagName);
Expand Down
36 changes: 36 additions & 0 deletions lib/util/continuecomment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
(function() {
var modes = ["clike", "css", "javascript"];
for (var i = 0; i < modes.length; ++i)
CodeMirror.extendMode(modes[i], {blockCommentStart: "/*",
blockCommentEnd: "*/",
blockCommentContinue: " * "});

CodeMirror.commands.newlineAndIndentContinueComment = function(cm) {
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode;
var space;

if (token.type == "comment" && mode.blockCommentStart) {
var end = token.string.indexOf(mode.blockCommentEnd);
var full = cm.getRange({line: pos.line, ch: 0}, {line: pos.line, ch: token.end}), found;
if (end != -1 && end == token.string.length - mode.blockCommentEnd.length) {
// Comment ended, don't continue it
} else if (token.string.indexOf(mode.blockCommentStart) == 0) {
space = full.slice(0, token.start);
if (!/^\s*$/.test(space)) {
space = "";
for (var i = 0; i < token.start; ++i) space += " ";
}
} else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
found + mode.blockCommentContinue.length > token.start &&
/^\s*$/.test(full.slice(0, found))) {
space = full.slice(0, found);
}
}

if (space != null)
cm.replaceSelection("\n" + space + mode.blockCommentContinue, "end");
else
cm.execCommand("newlineAndIndent");
};
})();
137 changes: 60 additions & 77 deletions lib/util/foldcode.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// the tagRangeFinder function is
// Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
// released under the MIT license (../../LICENSE) like the rest of CodeMirror
CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
CodeMirror.tagRangeFinder = function(cm, start) {
var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");

var lineText = cm.getLine(line);
var lineText = cm.getLine(start.line);
var found = false;
var tag = null;
var pos = 0;
var pos = start.ch;
while (!found) {
pos = lineText.indexOf("<", pos);
if (-1 == pos) // no tag on line
Expand All @@ -18,28 +18,26 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
pos++;
continue;
}
// ok we weem to have a start tag
// ok we seem to have a start tag
if (!lineText.substr(pos + 1).match(xmlNAMERegExp)) { // not a tag name...
pos++;
continue;
}
var gtPos = lineText.indexOf(">", pos + 1);
if (-1 == gtPos) { // end of start tag not in line
var l = line + 1;
var l = start.line + 1;
var foundGt = false;
var lastLine = cm.lineCount();
while (l < lastLine && !foundGt) {
var lt = cm.getLine(l);
var gt = lt.indexOf(">");
if (-1 != gt) { // found a >
gtPos = lt.indexOf(">");
if (-1 != gtPos) { // found a >
foundGt = true;
var slash = lt.lastIndexOf("/", gt);
if (-1 != slash && slash < gt) {
var str = lineText.substr(slash, gt - slash + 1);
if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
if (hideEnd === true) l++;
return l;
}
var slash = lt.lastIndexOf("/", gtPos);
if (-1 != slash && slash < gtPos) {
var str = lineText.substr(slash, gtPos - slash + 1);
if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
return;
}
}
l++;
Expand Down Expand Up @@ -83,10 +81,10 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {

if (found) {
var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
var startTagRegExp = new RegExp(startTag, "g");
var startTagRegExp = new RegExp(startTag);
var endTag = "</" + tag + ">";
var depth = 1;
var l = line + 1;
var l = start.line + 1;
var lastLine = cm.lineCount();
while (l < lastLine) {
lineText = cm.getLine(l);
Expand All @@ -97,10 +95,8 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
depth--;
else
depth++;
if (!depth) {
if (hideEnd === true) l++;
return l;
}
if (!depth) return {from: {line: start.line, ch: gtPos + 1},
to: {line: l, ch: match.index}};
}
}
l++;
Expand All @@ -109,17 +105,18 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
}
};

CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
var lineText = cm.getLine(line), at = lineText.length, startChar, tokenType;
CodeMirror.braceRangeFinder = function(cm, start) {
var line = start.line, lineText = cm.getLine(line);
var at = lineText.length, startChar, tokenType;
for (;;) {
var found = lineText.lastIndexOf("{", at);
if (found < 0) break;
tokenType = cm.getTokenAt({line: line, ch: found}).className;
if (found < start.ch) break;
tokenType = cm.getTokenAt({line: line, ch: found}).type;
if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
at = found - 1;
}
if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
var count = 1, lastLine = cm.lineCount(), end;
var count = 1, lastLine = cm.lineCount(), end, endCh;
outer: for (var i = line + 1; i < lastLine; ++i) {
var text = cm.getLine(i), pos = 0;
for (;;) {
Expand All @@ -128,72 +125,58 @@ CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
if (nextClose < 0) nextClose = text.length;
pos = Math.min(nextOpen, nextClose);
if (pos == text.length) break;
if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {
if (cm.getTokenAt({line: i, ch: pos + 1}).type == tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; break outer; }
else if (!--count) { end = i; endCh = pos; break outer; }
}
++pos;
}
}
if (end == null || end == line + 1) return;
if (hideEnd === true) end++;
return end;
return {from: {line: line, ch: startChar + 1},
to: {line: end, ch: endCh}};
};

CodeMirror.indentRangeFinder = function(cm, line) {
var tabSize = cm.getOption("tabSize");
var myIndent = cm.getLineHandle(line).indentation(tabSize), last;
for (var i = line + 1, end = cm.lineCount(); i < end; ++i) {
var handle = cm.getLineHandle(i);
if (!/^\s*$/.test(handle.text)) {
if (handle.indentation(tabSize) <= myIndent) break;
last = i;
}
CodeMirror.indentRangeFinder = function(cm, start) {
var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
var myIndent = CodeMirror.countColumn(firstLine, null, tabSize);
for (var i = start.line + 1, end = cm.lineCount(); i < end; ++i) {
var curLine = cm.getLine(i);
if (CodeMirror.countColumn(curLine, null, tabSize) < myIndent)
return {from: {line: start.line, ch: firstLine.length},
to: {line: i, ch: curLine.length}};
}
if (!last) return null;
return last + 1;
};

CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
var folded = [];
if (markText == null) markText = "\u25bc";

function isFolded(handle) {
for (var i = 0; i < folded.length; ++i) {
if (folded[i].start == handle) return {pos: i, region: folded[i]};
if (!folded[i].start.parent) folded.splice(i--, 1);
}
CodeMirror.newFoldFunction = function(rangeFinder, widget) {
if (widget == null) widget = "\u2194";
if (typeof widget == "string") {
var text = document.createTextNode(widget);
widget = document.createElement("span");
widget.appendChild(text);
widget.className = "CodeMirror-foldmarker";
}

return function(cm, line) {
cm.operation(function() {
var l = cm.getLineHandle(line), known = isFolded(l);
if (known) {
folded.splice(known.pos, 1);
cm.unfoldLines(known.region.handle);
cm.setGutterMarker(l, "CodeMirror-folded", null);
} else {
var end = rangeFinder(cm, line, hideEnd);
if (end == null) return;
var handle = cm.foldLines(line + 1, end, {unfoldOnEnter: true});
CodeMirror.on(handle, "unfold", function() {
cm.setGutterMarker(l, "CodeMirror-folded", null);
});
var elt = document.createElement("div");
elt.className = "CodeMirror-foldmarker";
elt.innerHTML = markText;
var first = cm.setGutterMarker(line, "CodeMirror-folded", elt);
function clear() {
var known = isFolded(first);
if (!known) return;
cm.unfoldLines(known.region.handle);
folded.splice(known.pos, 1);
}
CodeMirror.on(first, "delete", clear);
CodeMirror.on(first, "change", clear);
CodeMirror.on(cm.getLineHandle(line + 1), "delete", clear);
folded.push({start: first, handle: handle});
return function(cm, pos) {
if (typeof pos == "number") pos = {line: pos, ch: 0};
var range = rangeFinder(cm, pos);
if (!range) return;

var present = cm.findMarksAt(range.from), cleared = 0;
for (var i = 0; i < present.length; ++i) {
if (present[i].__isFold) {
++cleared;
present[i].clear();
}
}
if (cleared) return;

var myWidget = widget.cloneNode(true);
CodeMirror.on(myWidget, "mousedown", function() {myRange.clear();});
var myRange = cm.markText(range.from, range.to, {
replacedWith: myWidget,
clearOnEnter: true,
__isFold: true
});
};
};
17 changes: 10 additions & 7 deletions lib/util/formatting.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@

autoFormatLineBreaks: function (text) {
var curPos = 0;
var reLinesSplitter = /(;|\{|\})([^\r\n;])/g;
var nonBreakableBlocks = jsNonBreakableBlocks(text);
var split = this.jsonMode ? function(str) {
return str.replace(/([,{])/g, "$1\n").replace(/}/g, "\n}");
} : function(str) {
return str.replace(/(;|\{|\})([^\r\n;])/g, "$1\n$2");
};
var nonBreakableBlocks = jsNonBreakableBlocks(text), res = "";
if (nonBreakableBlocks != null) {
var res = "";
for (var i = 0; i < nonBreakableBlocks.length; i++) {
if (nonBreakableBlocks[i].start > curPos) { // Break lines till the block
res += text.substring(curPos, nonBreakableBlocks[i].start).replace(reLinesSplitter, "$1\n$2");
res += split(text.substring(curPos, nonBreakableBlocks[i].start));
curPos = nonBreakableBlocks[i].start;
}
if (nonBreakableBlocks[i].start <= curPos
Expand All @@ -63,11 +66,11 @@
}
}
if (curPos < text.length)
res += text.substr(curPos).replace(reLinesSplitter, "$1\n$2");
return res;
res += split(text.substr(curPos));
} else {
return text.replace(reLinesSplitter, "$1\n$2");
res = split(text);
}
return res.replace(/^\n*|\n*$/, "");
}
});

Expand Down
22 changes: 11 additions & 11 deletions lib/util/javascript-hint.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
// If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) {
token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
className: token.string == "." ? "property" : null};
type: token.string == "." ? "property" : null};
}
// If it is a property, find out what it is a property of.
while (tprop.className == "property") {
while (tprop.type == "property") {
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
if (tprop.string != ".") return;
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
Expand All @@ -40,9 +40,9 @@
}
} while (level > 0);
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
if (tprop.className == 'variable')
tprop.className = 'function';
else return; // no clue
if (tprop.type == 'variable')
tprop.type = 'function';
else return; // no clue
}
if (!context) var context = [];
context.push(tprop);
Expand All @@ -65,10 +65,10 @@
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
token.end = token.start;
token.string = '.';
token.className = "property";
token.type = "property";
}
else if (/^\.[\w$_]*$/.test(token.string)) {
token.className = "property";
token.type = "property";
token.start++;
token.string = token.string.replace(/\./, '');
}
Expand Down Expand Up @@ -105,13 +105,13 @@
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.className == "variable")
if (obj.type == "variable")
base = window[obj.string];
else if (obj.className == "string")
else if (obj.type == "string")
base = "";
else if (obj.className == "atom")
else if (obj.type == "atom")
base = 1;
else if (obj.className == "function") {
else if (obj.type == "function") {
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof window.jQuery == 'function'))
base = window.jQuery();
Expand Down
6 changes: 4 additions & 2 deletions lib/util/match-highlighter.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
if (cm.lineCount() < 2000) { // This is too expensive on big documents.
for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
//Only apply matchhighlight to the matches other than the one actually selected
if (!(cursor.from().line === cm.getCursor(true).line && cursor.from().ch === cm.getCursor(true).ch))
state.marked.push(cm.markText(cursor.from(), cursor.to(), className));
if (cursor.from().line !== cm.getCursor(true).line ||
cursor.from().ch !== cm.getCursor(true).ch)
state.marked.push(cm.markText(cursor.from(), cursor.to(),
{className: className}));
}
}
});
Expand Down
12 changes: 7 additions & 5 deletions lib/util/matchbrackets.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
var cur = cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
if (!match) return null;
var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1;
var style = cm.getTokenAt({line: cur.line, ch: pos + 1}).className;
var forward = match.charAt(1) == ">", d = forward ? 1 : -1;
var style = cm.getTokenAt({line: cur.line, ch: pos + 1}).type;

var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
function scan(line, lineNo, start) {
Expand All @@ -14,7 +14,7 @@
if (start != null) pos = start + d;
for (; pos != end; pos += d) {
var ch = line.text.charAt(pos);
if (re.test(ch) && cm.getTokenAt({line: lineNo, ch: pos + 1}).className == style) {
if (re.test(ch) && cm.getTokenAt({line: lineNo, ch: pos + 1}).type == style) {
var match = matching[ch];
if (match.charAt(1) == ">" == forward) stack.push(ch);
else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
Expand All @@ -34,8 +34,10 @@
var found = findMatchingBracket(cm);
if (!found) return;
var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
var one = cm.markText(found.from, {line: found.from.line, ch: found.from.ch + 1}, style);
var two = found.to && cm.markText(found.to, {line: found.to.line, ch: found.to.ch + 1}, style);
var one = cm.markText(found.from, {line: found.from.line, ch: found.from.ch + 1},
{className: style});
var two = found.to && cm.markText(found.to, {line: found.to.line, ch: found.to.ch + 1},
{className: style});
var clear = function() {
cm.operation(function() { one.clear(); two && two.clear(); });
};
Expand Down
12 changes: 3 additions & 9 deletions lib/util/pig-hint.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
return arr.indexOf(item) != -1;
}

function scriptHint(editor, keywords, getToken) {
function scriptHint(editor, _keywords, getToken) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
// If it's not a 'word-style' token, ignore the token.
Expand Down Expand Up @@ -45,12 +45,6 @@
return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
};

function toTitleCase(str) {
return str.replace(/(?:^|\s)\w/g, function(match) {
return match.toUpperCase();
});
}

var pigKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
+ "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
+ "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
Expand Down Expand Up @@ -109,9 +103,9 @@
// find in the current environment.
var obj = context.pop(), base;

if (obj.className == "pig-word")
if (obj.type == "variable")
base = obj.string;
else if(obj.className == "pig-type")
else if(obj.type == "variable-3")
base = ":" + obj.string;

while (base != null && context.length)
Expand Down
11 changes: 6 additions & 5 deletions lib/util/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
state.query = parseQuery(query);
if (cm.lineCount() < 2000) { // This is too expensive on big documents.
for (var cursor = getSearchCursor(cm, state.query); cursor.findNext();)
state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
state.marked.push(cm.markText(cursor.from(), cursor.to(),
{className: "CodeMirror-searching"}));
}
state.posFrom = state.posTo = cm.getCursor();
findNext(cm, rev);
Expand Down Expand Up @@ -76,14 +77,14 @@
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
if (all) {
cm.compoundChange(function() { cm.operation(function() {
cm.operation(function() {
for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
if (typeof query != "string") {
var match = cm.getRange(cursor.from(), cursor.to()).match(query);
cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
cursor.replace(text.replace(/\$(\d)/, function(_, i) {return match[i];}));
} else cursor.replace(text);
}
});});
});
} else {
clearSearch(cm);
var cursor = getSearchCursor(cm, query, cm.getCursor());
Expand All @@ -100,7 +101,7 @@
}
function doReplace(match) {
cursor.replace(typeof query == "string" ? text :
text.replace(/\$(\d)/, function(w, i) {return match[i];}));
text.replace(/\$(\d)/, function(_, i) {return match[i];}));
advance();
}
advance();
Expand Down
2 changes: 1 addition & 1 deletion lib/util/simple-hint.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

// Don't show completions if token has changed and the option is set.
if (options.closeOnTokenChange && previousToken != null &&
(tempToken.start != previousToken.start || tempToken.className != previousToken.className)) {
(tempToken.start != previousToken.start || tempToken.type != previousToken.type)) {
return;
}

Expand Down
10 changes: 2 additions & 8 deletions lib/util/xml-hint.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@
cm.setCursor(cursor);
}

// dirty hack for simple-hint to receive getHint event on space
var getTokenAt = editor.getTokenAt;

editor.getTokenAt = function() { return 'disabled'; };
CodeMirror.simpleHint(cm, getHint);

editor.getTokenAt = getTokenAt;
};

var getHint = function(cm) {
Expand All @@ -42,7 +36,7 @@

text = text.slice(0, text.length - typed.length);

var path = getActiveElement(cm, text) + simbol;
var path = getActiveElement(text) + simbol;
var hints = CodeMirror.xmlHints[path];

if(typeof hints === 'undefined')
Expand All @@ -63,7 +57,7 @@
};
};

var getActiveElement = function(codeMirror, text) {
var getActiveElement = function(text) {

var element = '';

Expand Down
9 changes: 4 additions & 5 deletions mode/clike/clike.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,14 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
while (ctx.type == "statement") ctx = popContext(state);
}
else if (curPunc == ctx.type) popContext(state);
else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
pushContext(state, stream.column(), "statement");
state.startOfLine = false;
return style;
},

indent: function(state, textAfter) {
if (state.tokenize == tokenComment) return CodeMirror.Pass;
if (state.tokenize != tokenBase && state.tokenize != null) return 0;
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
var closing = firstChar == ctx.type;
Expand Down Expand Up @@ -213,7 +212,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords: words("catch class do else finally for if switch try while"),
atoms: words("true false null"),
hooks: {
"@": function(stream, state) {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
}
Expand Down Expand Up @@ -276,7 +275,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords: words("catch class do else finally for forSome if match switch try while"),
atoms: words("true false null"),
hooks: {
"@": function(stream, state) {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
}
Expand Down
8 changes: 4 additions & 4 deletions mode/clojure/clojure.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
* Author: Hans Engel
* Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
*/
CodeMirror.defineMode("clojure", function (config, mode) {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", TAG = "tag",
CodeMirror.defineMode("clojure", function () {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword";
var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
var INDENT_WORD_SKIP = 2;

function makeKeywords(str) {
var obj = {}, words = str.split(" ");
Expand Down Expand Up @@ -196,7 +196,7 @@ CodeMirror.defineMode("clojure", function (config, mode) {
return returnType;
},

indent: function (state, textAfter) {
indent: function (state) {
if (state.indentStack == null) return state.indentation;
return state.indentStack.indent;
}
Expand Down
2 changes: 1 addition & 1 deletion mode/coffeescript/coffeescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ CodeMirror.defineMode('coffeescript', function(conf) {
return style;
},

indent: function(state, textAfter) {
indent: function(state) {
if (state.tokenize != tokenBase) {
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion mode/commonlisp/commonlisp.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ CodeMirror.defineMode("commonlisp", function (config) {
return style;
},

indent: function (state, textAfter) {
indent: function (state, _textAfter) {
var i = state.ctx.indentTo;
return typeof i == "number" ? i : state.ctx.start + 1;
}
Expand Down
11 changes: 0 additions & 11 deletions mode/ecl/ecl.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,6 @@ CodeMirror.defineMode("ecl", function(config) {
return "meta";
}

function tokenAtString(stream, state) {
var next;
while ((next = stream.next()) != null) {
if (next == '"' && !stream.eat('"')) {
state.tokenize = null;
break;
}
}
return "string";
}

var indentUnit = config.indentUnit;
var keyword = words("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode");
var variable = words("apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait");
Expand Down
2 changes: 1 addition & 1 deletion mode/erlang/erlang.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

CodeMirror.defineMIME("text/x-erlang", "erlang");

CodeMirror.defineMode("erlang", function(cmCfg, modeCfg) {
CodeMirror.defineMode("erlang", function(cmCfg) {

function rval(state,stream,type) {
// distinguish between "." as terminator and record field operator
Expand Down
4 changes: 2 additions & 2 deletions mode/gfm/gfm.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("gfm", function(config, parserConfig) {
CodeMirror.defineMode("gfm", function(config) {
var codeDepth = 0;
function blankLine(state) {
state.code = false;
Expand Down Expand Up @@ -91,4 +91,4 @@ CodeMirror.defineMode("gfm", function(config, parserConfig) {
fencedCodeBlocks: true
});
return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
});
}, "markdown");
2 changes: 1 addition & 1 deletion mode/gfm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ <h1>CodeMirror: GFM mode</h1>

Underscores_are_allowed_between_words.

## Fenced code blocks (and syntax highlighting... someday)
## Fenced code blocks (and syntax highlighting)

```javascript
for (var i = 0; i &lt; items.length; i++) {
Expand Down
7 changes: 1 addition & 6 deletions mode/go/go.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("go", function(config, parserConfig) {
CodeMirror.defineMode("go", function(config) {
var indentUnit = config.indentUnit;

var keywords = {
Expand All @@ -20,11 +20,6 @@ CodeMirror.defineMode("go", function(config, parserConfig) {
"println":true, "real":true, "recover":true
};

var blockKeywords = {
"else":true, "for":true, "func":true, "if":true, "interface":true,
"select":true, "struct":true, "switch":true
};

var isOperatorChar = /[+\-*&^%:=<>!|\/]/;

var curPunc;
Expand Down
2 changes: 1 addition & 1 deletion mode/groovy/groovy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("groovy", function(config, parserConfig) {
CodeMirror.defineMode("groovy", function(config) {
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
Expand Down
2 changes: 1 addition & 1 deletion mode/haskell/haskell.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("haskell", function(cmCfg, modeCfg) {
CodeMirror.defineMode("haskell", function() {

function switchState(source, setState, f) {
setState(f);
Expand Down
26 changes: 13 additions & 13 deletions mode/haxe/haxe.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,19 +288,19 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
}

function maybeattribute(type, value) {
function maybeattribute(type) {
if (type == "attribute") return cont(maybeattribute);
if (type == "function") return cont(functiondef);
if (type == "var") return cont(vardef1);
}

function metadef(type, value) {
function metadef(type) {
if(type == ":") return cont(metadef);
if(type == "variable") return cont(metadef);
if(type == "(") return cont(pushlex(")"), comasep(metaargs, ")"), poplex, statement);
}
function metaargs(type, value) {
if(typ == "variable") return cont();
function metaargs(type) {
if(type == "variable") return cont();
}

function importdef (type, value) {
Expand Down Expand Up @@ -353,24 +353,24 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
}
return cont(pushlex(")"), pushcontext, forin, expression, poplex, statement, popcontext);
}
function forin(type, value) {
function forin(_type, value) {
if (value == "in") return cont();
}
function functiondef(type, value) {
if (type == "variable") {register(value); return cont(functiondef);}
if (value == "new") return cont(functiondef);
if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext);
}
function typeuse(type, value) {
if(type == ":") return cont(typestring);
function typeuse(type) {
if(type == ":") return cont(typestring);
}
function typestring(type, value) {
if(type == "type") return cont();
if(type == "variable") return cont();
if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
function typestring(type) {
if(type == "type") return cont();
if(type == "variable") return cont();
if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
}
function typeprop(type, value) {
if(type == "variable") return cont(typeuse);
function typeprop(type) {
if(type == "variable") return cont(typeuse);
}
function funarg(type, value) {
if (type == "variable") {register(value); return cont(typeuse);}
Expand Down
2 changes: 1 addition & 1 deletion mode/htmlmixed/htmlmixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ CodeMirror.defineMode("htmlmixed", function(config) {
var close = cur.search(pat), m;
if (close > -1) stream.backUp(cur.length - close);
else if (m = cur.match(/<\/?$/)) {
stream.backUp(cur[0].length);
stream.backUp(cur.length);
if (!stream.match(pat, false)) stream.match(cur[0]);
}
return style;
Expand Down
4 changes: 3 additions & 1 deletion mode/javascript/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../lib/util/continuecomment.js"></script>
<script src="javascript.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
Expand Down Expand Up @@ -66,7 +67,8 @@ <h1>CodeMirror: JavaScript mode</h1>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true
matchBrackets: true,
extraKeys: {"Enter": "newlineAndIndentContinueComment"}
});
</script>

Expand Down
6 changes: 4 additions & 2 deletions mode/javascript/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "variable") return cont(formaybein);
return cont(forspec2);
}
function formaybein(type, value) {
function formaybein(_type, value) {
if (value == "in") return cont(expression);
return cont(maybeoperator, forspec2);
}
Expand Down Expand Up @@ -399,7 +399,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
else return lexical.indented + (closing ? 0 : indentUnit);
},

electricChars: ":{}"
electricChars: ":{}",

jsonMode: jsonMode
};
});

Expand Down
2 changes: 1 addition & 1 deletion mode/jinja2/jinja2.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("jinja2", function(config, parserConf) {
CodeMirror.defineMode("jinja2", function() {
var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
"loop", "none", "self", "super", "if", "as", "not", "and",
"else", "import", "with", "without", "context"];
Expand Down
12 changes: 0 additions & 12 deletions mode/markdown/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
}
}

function codeBlock(stream, state) {
if(stream.match(codeBlockRE, true)){
state.f = inlineNormal;
state.block = blockNormal;
switchInline(stream, state, state.inline);
return code;
}
stream.skipToEnd();
return code;
}

// Inline
function getType(state) {
var styles = [];
Expand Down Expand Up @@ -284,7 +273,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
}

if (ch === '<' && stream.match(/^\w/, false)) {
var md_inside = false;
if (stream.string.indexOf(">")!=-1) {
var atts = stream.string.substring(1,stream.string.indexOf(">"));
if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
Expand Down
33 changes: 25 additions & 8 deletions mode/mysql/mysql.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@ CodeMirror.defineMode("mysql", function(config) {
curPunc = ch;
return null;
}
else if (ch == "-") {
var ch2 = stream.next();
if (ch2=="-") {
stream.skipToEnd();
return "comment";
}
else if (ch == "-" && stream.eat("-")) {
stream.skipToEnd();
return "comment";
}
else if (ch == "/" && stream.eat("*")) {
state.tokenize = tokenComment;
return state.tokenize(stream, state);
}
else if (operatorChars.test(ch)) {
stream.eatWhile(operatorChars);
Expand All @@ -77,7 +78,7 @@ CodeMirror.defineMode("mysql", function(config) {
stream.eatWhile(/[\w\d_\-]/);
return "atom";
}
var word = stream.current(), type;
var word = stream.current();
if (ops.test(word))
return null;
else if (keywords.test(word))
Expand Down Expand Up @@ -115,6 +116,22 @@ CodeMirror.defineMode("mysql", function(config) {
};
}

function tokenComment(stream, state) {
for (;;) {
if (stream.skipTo("*")) {
stream.next();
if (stream.eat("/")) {
state.tokenize = tokenBase;
break;
}
} else {
stream.skipToEnd();
break;
}
}
return "comment";
}


function pushContext(state, type, col) {
state.context = {prev: state.context, indent: state.indent, col: col, type: type};
Expand All @@ -125,7 +142,7 @@ CodeMirror.defineMode("mysql", function(config) {
}

return {
startState: function(base) {
startState: function() {
return {tokenize: tokenBase,
context: null,
indent: 0,
Expand Down
2 changes: 0 additions & 2 deletions mode/ntriples/ntriples.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ CodeMirror.defineMode("ntriples", function() {
currState.location=ret;
}

var untilSpace = function(c) { return c != ' '; };
var untilEndURI = function(c) { return c != '>'; };
return {
startState: function() {
return {
Expand Down
3 changes: 1 addition & 2 deletions mode/ocaml/ocaml.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode('ocaml', function(config) {
CodeMirror.defineMode('ocaml', function() {

var words = {
'true': 'atom',
Expand Down Expand Up @@ -37,7 +37,6 @@ CodeMirror.defineMode('ocaml', function(config) {
};

function tokenBase(stream, state) {
var sol = stream.sol();
var ch = stream.next();

if (ch === '"') {
Expand Down
4 changes: 2 additions & 2 deletions mode/pascal/pascal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("pascal", function(config) {
CodeMirror.defineMode("pascal", function() {
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
Expand Down Expand Up @@ -76,7 +76,7 @@ CodeMirror.defineMode("pascal", function(config) {
// Interface

return {
startState: function(basecolumn) {
startState: function() {
return {tokenize: null};
},

Expand Down
2 changes: 1 addition & 1 deletion mode/perl/perl.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)
// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)
CodeMirror.defineMode("perl",function(config,parserConfig){
CodeMirror.defineMode("perl",function(){
// http://perldoc.perl.org
var PERL={ // null - magic touch
// 1 - keyword
Expand Down
1 change: 1 addition & 0 deletions mode/php/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../htmlmixed/htmlmixed.js"></script>
<script src="../xml/xml.js"></script>
<script src="../javascript/javascript.js"></script>
<script src="../css/css.js"></script>
Expand Down
52 changes: 16 additions & 36 deletions mode/php/php.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
atoms: keywords("true false null TRUE FALSE NULL"),
multiLineStrings: true,
hooks: {
"$": function(stream, state) {
"$": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "variable-2";
},
Expand All @@ -35,11 +35,11 @@
}
return false;
},
"#": function(stream, state) {
"#": function(stream) {
while (!stream.eol() && !stream.match("?>", false)) stream.next();
return "comment";
},
"/": function(stream, state) {
"/": function(stream) {
if (stream.eat("/")) {
while (!stream.eol() && !stream.match("?>", false)) stream.next();
return "comment";
Expand All @@ -50,19 +50,16 @@
};

CodeMirror.defineMode("php", function(config, parserConfig) {
var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
var jsMode = CodeMirror.getMode(config, "javascript");
var cssMode = CodeMirror.getMode(config, "css");
var htmlMode = CodeMirror.getMode(config, "text/html");
var phpMode = CodeMirror.getMode(config, phpConfig);

function dispatch(stream, state) { // TODO open PHP inside text/css
function dispatch(stream, state) {
var isPHP = state.curMode == phpMode;
if (stream.sol() && state.pending != '"') state.pending = null;
if (state.curMode == htmlMode) {
if (!isPHP) {
if (stream.match(/^<\?\w*/)) {
state.curMode = phpMode;
state.curState = state.php;
state.curClose = "?>";
return "meta";
}
if (state.pending == '"') {
Expand All @@ -80,51 +77,33 @@
if (style == "string" && /\"$/.test(cur) && !/\?>/.test(cur)) state.pending = '"';
else state.pending = {end: stream.pos, style: style};
stream.backUp(cur.length - openPHP);
} else if (style == "tag" && stream.current() == ">" && state.curState.context) {
if (/^script$/i.test(state.curState.context.tagName)) {
state.curMode = jsMode;
state.curState = jsMode.startState(htmlMode.indent(state.curState, ""));
state.curClose = /^<\/\s*script\s*>/i;
}
else if (/^style$/i.test(state.curState.context.tagName)) {
state.curMode = cssMode;
state.curState = cssMode.startState(htmlMode.indent(state.curState, ""));
state.curClose = /^<\/\s*style\s*>/i;
}
}
return style;
} else if ((!isPHP || state.php.tokenize == null) &&
stream.match(state.curClose, isPHP)) {
} else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
state.curMode = htmlMode;
state.curState = state.html;
state.curClose = null;
if (isPHP) return "meta";
else return dispatch(stream, state);
return "meta";
} else {
return state.curMode.token(stream, state.curState);
return phpMode.token(stream, state.curState);
}
}

return {
startState: function() {
var html = htmlMode.startState();
var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
return {html: html,
php: phpMode.startState(),
php: php,
curMode: parserConfig.startOpen ? phpMode : htmlMode,
curState: parserConfig.startOpen ? phpMode.startState() : html,
curClose: parserConfig.startOpen ? /^\?>/ : null,
mode: parserConfig.startOpen ? "php" : "html",
curState: parserConfig.startOpen ? php : html,
pending: null};
},

copyState: function(state) {
var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
if (state.curState == html) cur = htmlNew;
else if (state.curState == php) cur = phpNew;
else cur = CodeMirror.copyState(state.curMode, state.curState);
if (state.curMode == htmlMode) cur = htmlNew;
else cur = phpNew;
return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
curClose: state.curClose, mode: state.mode,
pending: state.pending};
},

Expand All @@ -141,7 +120,8 @@

innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
};
}, "xml", "clike", "javascript", "css");
}, "htmlmixed");

CodeMirror.defineMIME("application/x-httpd-php", "php");
CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
CodeMirror.defineMIME("text/x-php", phpConfig);
Expand Down
7 changes: 3 additions & 4 deletions mode/pig/pig.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
* @link https://github.com/prasanthj/pig-codemirror-2
* This implementation is adapted from PL/SQL mode in CodeMirror 2.
*/
CodeMirror.defineMode("pig", function(config, parserConfig) {
var indentUnit = config.indentUnit,
keywords = parserConfig.keywords,
CodeMirror.defineMode("pig", function(_config, parserConfig) {
var keywords = parserConfig.keywords,
builtins = parserConfig.builtins,
types = parserConfig.types,
multiLineStrings = parserConfig.multiLineStrings;
Expand Down Expand Up @@ -119,7 +118,7 @@ CodeMirror.defineMode("pig", function(config, parserConfig) {

// Interface
return {
startState: function(basecolumn) {
startState: function() {
return {
tokenize: tokenBase,
startOfLine: true
Expand Down
7 changes: 3 additions & 4 deletions mode/plsql/plsql.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
CodeMirror.defineMode("plsql", function(config, parserConfig) {
var indentUnit = config.indentUnit,
keywords = parserConfig.keywords,
CodeMirror.defineMode("plsql", function(_config, parserConfig) {
var keywords = parserConfig.keywords,
functions = parserConfig.functions,
types = parserConfig.types,
sqlplus = parserConfig.sqlplus,
Expand Down Expand Up @@ -105,7 +104,7 @@ CodeMirror.defineMode("plsql", function(config, parserConfig) {
// Interface

return {
startState: function(basecolumn) {
startState: function() {
return {
tokenize: tokenBase,
startOfLine: true
Expand Down
10 changes: 6 additions & 4 deletions mode/python/python.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
var singleline = delimiter.length == 1;
var OUTCLASS = 'string';

return function tokenString(stream, state) {
function tokenString(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"\\]/);
if (stream.eat('\\')) {
Expand All @@ -183,7 +183,9 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
}
}
return OUTCLASS;
};
}
tokenString.isString = true;
return tokenString;
}

function indent(stream, state, type) {
Expand Down Expand Up @@ -323,9 +325,9 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
return style;
},

indent: function(state, textAfter) {
indent: function(state) {
if (state.tokenize != tokenBase) {
return 0;
return state.tokenize.isString ? CodeMirror.Pass : 0;
}

return state.scopes[0].offset;
Expand Down
2 changes: 1 addition & 1 deletion mode/r/r.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ CodeMirror.defineMode("r", function(config) {
}

return {
startState: function(base) {
startState: function() {
return {tokenize: tokenBase,
ctx: {type: "top",
indent: -config.indentUnit,
Expand Down
2 changes: 1 addition & 1 deletion mode/rpm/changes/changes.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("changes", function(config, modeConfig) {
CodeMirror.defineMode("changes", function() {
var headerSeperator = /^-+$/;
var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /;
var simpleEmail = /^[\w+.-]+@[\w.-]+/;
Expand Down
2 changes: 1 addition & 1 deletion mode/rpm/spec/spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Quick and dirty spec file highlighting

CodeMirror.defineMode("spec", function(config, modeConfig) {
CodeMirror.defineMode("spec", function() {
var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;

var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
Expand Down
2 changes: 0 additions & 2 deletions mode/rst/rst.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ CodeMirror.defineMode('rst', function(config, options) {
var reVerbatimMarker = /^::\s*$/;
var rePreInline = /^[-\s"([{</:]/;
var rePostInline = /^[-\s`'")\]}>/:.,;!?\\_]/;
var reEnumeratedList = /^\s*((\d+|[A-Za-z#])[.)]|\((\d+|[A-Z-a-z#])\))\s/;
var reBulletedList = /^\s*[-\+\*]\s/;
var reExamples = /^\s+(>>>|In \[\d+\]:)\s/;

function normal(stream, state) {
Expand Down
2 changes: 1 addition & 1 deletion mode/ruby/ruby.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("ruby", function(config, parserConfig) {
CodeMirror.defineMode("ruby", function(config) {
function wordObj(words) {
var o = {};
for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
Expand Down
6 changes: 3 additions & 3 deletions mode/rust/rust.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ CodeMirror.defineMode("rust", function() {
if (type == "(" || type == "[") return matchBrackets(type, expression);
return pass();
}
function maybeprop(type) {
function maybeprop() {
if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}
return pass(expression);
}
Expand Down Expand Up @@ -304,7 +304,7 @@ CodeMirror.defineMode("rust", function() {
if (type == "{") return cont(pushlex("}"), block, poplex);
return pass();
}
function typarams(type) {
function typarams() {
if (content == ">") return cont();
if (content == ",") return cont(typarams);
if (content == ":") return cont(rtype, typarams);
Expand All @@ -324,7 +324,7 @@ CodeMirror.defineMode("rust", function() {
if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex);
return matchBrackets(type, rtype);
}
function rtypemaybeparam(type) {
function rtypemaybeparam() {
if (content == "<") return cont(typarams);
return pass();
}
Expand Down
8 changes: 4 additions & 4 deletions mode/scheme/scheme.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/**
* Author: Koh Zi Han, based on implementation by Koh Zi Chun
*/
CodeMirror.defineMode("scheme", function (config, mode) {
CodeMirror.defineMode("scheme", function () {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD="keyword";
var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
ATOM = "atom", NUMBER = "number", BRACKET = "bracket";
var INDENT_WORD_SKIP = 2;

function makeKeywords(str) {
var obj = {}, words = str.split(" ");
Expand Down Expand Up @@ -220,7 +220,7 @@ CodeMirror.defineMode("scheme", function (config, mode) {
return (typeof state.sExprComment == "number") ? COMMENT : returnType;
},

indent: function (state, textAfter) {
indent: function (state) {
if (state.indentStack == null) return state.indentation;
return state.indentStack.indent;
}
Expand Down
2 changes: 1 addition & 1 deletion mode/shell/shell.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode('shell', function(config) {
CodeMirror.defineMode('shell', function() {

var words = {};
function define(style, string) {
Expand Down
2 changes: 1 addition & 1 deletion mode/sieve/sieve.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ CodeMirror.defineMode("sieve", function(config) {
return (state.tokenize || tokenBase)(stream, state);;
},

indent: function(state, textAfter) {
indent: function(state, _textAfter) {
return state.baseIndent + state._indent * indentUnit;
},

Expand Down
4 changes: 2 additions & 2 deletions mode/smalltalk/smalltalk.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode('smalltalk', function(config, modeConfig) {
CodeMirror.defineMode('smalltalk', function(config) {

var specialChars = /[+\-/\\*~<>=@%|&?!.:;^]/;
var keywords = /true|false|nil|self|super|thisContext/;
Expand Down Expand Up @@ -86,7 +86,7 @@ CodeMirror.defineMode('smalltalk', function(config, modeConfig) {
return new Token('string', stream.eat('\'') ? context.parent : context, false);
};

var nextTemporaries = function(stream, context, state) {
var nextTemporaries = function(stream, context) {
var token = new Token(null, context, false);
var aChar = stream.next();

Expand Down
2 changes: 1 addition & 1 deletion mode/smarty/smarty.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode("smarty", function(config, parserConfig) {
CodeMirror.defineMode("smarty", function(config) {
var keyFuncs = ["debug", "extends", "function", "include", "literal"];
var last;
var regs = {
Expand Down
4 changes: 2 additions & 2 deletions mode/sparql/sparql.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ CodeMirror.defineMode("sparql", function(config) {
stream.eatWhile(/[\w\d_\-]/);
return "atom";
}
var word = stream.current(), type;
var word = stream.current();
if (ops.test(word))
return null;
else if (keywords.test(word))
Expand Down Expand Up @@ -82,7 +82,7 @@ CodeMirror.defineMode("sparql", function(config) {
}

return {
startState: function(base) {
startState: function() {
return {tokenize: tokenBase,
context: null,
indent: 0,
Expand Down
19 changes: 6 additions & 13 deletions mode/stex/stex.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licence: MIT
*/

CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
CodeMirror.defineMode("stex", function()
{
function pushCommand(state, command) {
state.cmdState.push(command);
Expand Down Expand Up @@ -42,18 +42,17 @@ CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
this.styles = styles;
this.brackets = brackets;

this.styleIdentifier = function(content) {
this.styleIdentifier = function() {
if (this.bracketNo<=this.styles.length)
return this.styles[this.bracketNo-1];
else
return null;
};
this.openBracket = function(content) {
this.openBracket = function() {
this.bracketNo++;
return "bracket";
};
this.closeBracket = function(content) {
};
this.closeBracket = function() {};
};
}

Expand All @@ -69,12 +68,7 @@ CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
this.name="DEFAULT";
this.style="tag";

this.styleIdentifier = function(content) {
};
this.openBracket = function(content) {
};
this.closeBracket = function(content) {
};
this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
};

function setState(state, f) {
Expand Down Expand Up @@ -149,7 +143,7 @@ CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
var ch = source.peek();
if (ch == '{' || ch == '[') {
var lastPlug = peekCommand(state);
var style = lastPlug.openBracket(ch);
lastPlug.openBracket(ch);
source.eat(ch);
setState(state, normal);
return "bracket";
Expand All @@ -172,7 +166,6 @@ CodeMirror.defineMode("stex", function(cmCfg, modeCfg)

token: function(stream, state) {
var t = state.f(stream, state);
var w = stream.current();
return t;
}
};
Expand Down
43 changes: 6 additions & 37 deletions mode/tiddlywiki/tiddlywiki.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,9 @@
CoreVersion parameter is needed for TiddlyWiki only!
***/
//{{{
CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
var indentUnit = config.indentUnit;

CodeMirror.defineMode("tiddlywiki", function () {
// Tokenizer
var textwords = function () {
function kw(type) {
return {
type: type,
style: "text"
};
}
return {};
}();
var textwords = {};

var keywords = function () {
function kw(type) {
Expand Down Expand Up @@ -60,25 +50,13 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start
reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop

reCodeStart = /\{\{\{/, // {{{ code span start
reUntilCodeStop = /.*?\}\}\}/;

function chain(stream, state, f) {
state.tokenize = f;
return f(stream, state);
}

// used for strings
function nextUntilUnescaped(stream, end) {
var escaped = false,
next;
while ((next = stream.next()) != null) {
if (next == end && !escaped) return false;
escaped = !escaped && next == "\\";
}
return escaped;
}

// Used as scratch variables to communicate multiple values without
// consing up tons of objects.
var type, content;
Expand All @@ -90,8 +68,7 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
}

function jsTokenBase(stream, state) {
var sol = stream.sol(),
ch, tch;
var sol = stream.sol(), ch;

state.block = false; // indicates the start of a code block.

Expand Down Expand Up @@ -226,13 +203,6 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {

} // jsTokenBase()

function twTokenString(quote) {
return function (stream, state) {
if (!nextUntilUnescaped(stream, quote)) state.tokenize = jsTokenBase;
return ret("string", "string");
};
}

// tw invisible comment
function twTokenComment(stream, state) {
var maybeEnd = false,
Expand Down Expand Up @@ -314,8 +284,7 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
// tw strike through text looks ugly
// change CSS if needed
function twTokenStrike(stream, state) {
var maybeEnd = false,
ch, nr;
var maybeEnd = false, ch;

while (ch = stream.next()) {
if (ch == "-" && maybeEnd) {
Expand All @@ -329,7 +298,7 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {

// macro
function twTokenMacro(stream, state) {
var ch, tmp, word, known;
var ch, word, known;

if (stream.current() == '<<') {
return ret('brace', 'macro');
Expand Down Expand Up @@ -362,7 +331,7 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {

// Interface
return {
startState: function (basecolumn) {
startState: function () {
return {
tokenize: jsTokenBase,
indented: 0,
Expand Down
6 changes: 3 additions & 3 deletions mode/tiki/tiki.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CodeMirror.defineMode('tiki', function(config, parserConfig) {
CodeMirror.defineMode('tiki', function(config) {
function inBlock(style, terminator, returnTokenizer) {
return function(stream, state) {
while (!stream.eol()) {
Expand All @@ -15,7 +15,7 @@ CodeMirror.defineMode('tiki', function(config, parserConfig) {
};
}

function inLine(style, terminator) {
function inLine(style) {
return function(stream, state) {
while(!stream.eol()) {
stream.next();
Expand All @@ -37,7 +37,7 @@ CodeMirror.defineMode('tiki', function(config, parserConfig) {
//non start of line
switch (ch) { //switch is generally much faster than if, so it is used here
case "{": //plugin
var type = stream.eat("/") ? "closeTag" : "openTag";
stream.eat("/");
stream.eatSpace();
var tagName = "";
var c;
Expand Down
6 changes: 3 additions & 3 deletions mode/vb/vb.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ CodeMirror.defineMode("vb", function(conf, parserConf) {



function indent(stream, state) {
function indent(_stream, state) {
state.currentIndent++;
}

function dedent(stream, state) {
function dedent(_stream, state) {
state.currentIndent--;
}
// tokenizers
Expand Down Expand Up @@ -218,7 +218,7 @@ CodeMirror.defineMode("vb", function(conf, parserConf) {

var external = {
electricChars:"dDpPtTfFeE ",
startState: function(basecolumn) {
startState: function() {
return {
tokenize: tokenBase,
lastToken: null,
Expand Down
6 changes: 2 additions & 4 deletions mode/velocity/velocity.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
CodeMirror.defineMode("velocity", function(config) {
CodeMirror.defineMode("velocity", function() {
function parseWords(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}

var indentUnit = config.indentUnit;
var keywords = parseWords("#end #else #break #stop #[[ #]] " +
"#{end} #{else} #{break} #{stop}");
var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " +
"#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}");
var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent $velocityCount");
var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
var multiLineStrings =true;

function chain(stream, state, f) {
state.tokenize = f;
Expand Down Expand Up @@ -128,7 +126,7 @@ CodeMirror.defineMode("velocity", function(config) {
// Interface

return {
startState: function(basecolumn) {
startState: function() {
return {
tokenize: tokenBase,
beforeParams: false,
Expand Down
14 changes: 1 addition & 13 deletions mode/verilog/verilog.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,23 +167,11 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) {
"endgenerate endmodule endprimitive endspecify endtable endtask for forever function generate if ifnone " +
"macromodule module primitive repeat specify table task while";

function metaHook(stream, state) {
function metaHook(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
}

// C#-style strings where "" escapes a quote.
function tokenAtString(stream, state) {
var next;
while ((next = stream.next()) != null) {
if (next == '"' && !stream.eat('"')) {
state.tokenize = null;
break;
}
}
return "string";
}

CodeMirror.defineMIME("text/x-verilog", {
name: "verilog",
keywords: words(verilogKeywords),
Expand Down
2 changes: 1 addition & 1 deletion mode/xml/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="xml.js"></script>
<style type="text/css">.foo{border-right: 1px solid red} .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
Expand Down
8 changes: 5 additions & 3 deletions mode/xml/xml.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,12 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return "meta";
}
else {
type = stream.eat("/") ? "closeTag" : "openTag";
stream.eatSpace();
var isClose = stream.eat("/");
tagName = "";
var c;
while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
if (!tagName) return "error";
type = isClose ? "closeTag" : "openTag";
state.tokenize = inTag;
return "tag";
}
Expand Down Expand Up @@ -114,7 +115,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return state.tokenize(stream, state);
}
else {
stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);
stream.eatWhile(/[^\s\u00a0=<>\"\']/);
return "word";
}
}
Expand Down Expand Up @@ -255,6 +256,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
function attribute(type) {
if (type == "equals") return cont(attvalue, attributes);
if (!Kludges.allowMissing) setStyle = "error";
else if (type == "word") setStyle = "attribute";
return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
}
function attvalue(type) {
Expand Down
7 changes: 3 additions & 4 deletions mode/xquery/xquery.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
CodeMirror.defineMode("xquery", function(config, parserConfig) {
CodeMirror.defineMode("xquery", function() {

// The keywords object is set to the result of this self executing
// function. Each keyword is a property of the keywords object whose
Expand Down Expand Up @@ -401,7 +401,6 @@ CodeMirror.defineMode("xquery", function(config, parserConfig) {
// functions to test the current context of the state
function isInXmlBlock(state) { return isIn(state, "tag"); }
function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); }
function isInCodeBlock(state) { return isIn(state, "codeblock"); }
function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); }
function isInString(state) { return isIn(state, "string"); }

Expand All @@ -424,14 +423,14 @@ CodeMirror.defineMode("xquery", function(config, parserConfig) {
}

function popStateStack(state) {
var popped = state.stack.pop();
state.stack.pop();
var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize;
state.tokenize = reinstateTokenize || tokenBase;
}

// the interface for the mode API
return {
startState: function(basecolumn) {
startState: function() {
return {
tokenize: tokenBase,
cc: [],
Expand Down
39 changes: 39 additions & 0 deletions mode/z80/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: Z80 assembly mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="z80.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
</head>
<body>
<h1>CodeMirror: Z80 assembly mode</h1>

<div><textarea id="code" name="code">
#include "ti83plus.inc"
#define progStart $9D95
.org progStart-2
.db $BB,$6D
bcall(_ClrLCDFull)
ld HL, 0
ld (PenCol), HL
ld HL, Message
bcall(_PutS) ; Displays the string
bcall(_NewLine)
ret
Message:
.db "Hello world!",0
</textarea></div>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true
});
</script>

<p><strong>MIME type defined:</strong> <code>text/x-z80</code>.</p>
</body>
</html>
113 changes: 113 additions & 0 deletions mode/z80/z80.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
CodeMirror.defineMode('z80', function()
{
var keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\b/i;
var keywords2 = /^(call|j[pr]|ret[in]?)\b/i;
var keywords3 = /^b_?(call|jump)\b/i;
var variables1 = /^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\b/i;
var variables2 = /^(n?[zc]|p[oe]?|m)\b/i;
var errors = /^([hl][xy]|i[xy][hl]|slia|sll)\b/i;
var numbers = /^([\da-f]+h|[0-7]+o|[01]+b|\d+)\b/i;

return {startState: function()
{
return {context: 0};
}, token: function(stream, state)
{
if (!stream.column())
state.context = 0;

if (stream.eatSpace())
return null;

var w;

if (stream.eatWhile(/\w/))
{
w = stream.current();

if (stream.indentation())
{
if (state.context == 1 && variables1.test(w))
return 'variable-2';

if (state.context == 2 && variables2.test(w))
return 'variable-3';

if (keywords1.test(w))
{
state.context = 1;
return 'keyword';
}
else if (keywords2.test(w))
{
state.context = 2;
return 'keyword';
}
else if (keywords3.test(w))
{
state.context = 3;
return 'keyword';
}

if (errors.test(w))
return 'error';
}
else if (numbers.test(w))
{
return 'number';
}
else
{
return null;
}
}
else if (stream.eat(';'))
{
stream.skipToEnd();
return 'comment';
}
else if (stream.eat('"'))
{
while (w = stream.next())
{
if (w == '"')
break;

if (w == '\\')
stream.next();
}

return 'string';
}
else if (stream.eat('\''))
{
if (stream.match(/\\?.'/))
return 'number';
}
else if (stream.eat('.') || stream.sol() && stream.eat('#'))
{
state.context = 4;

if (stream.eatWhile(/\w/))
return 'def';
}
else if (stream.eat('$'))
{
if (stream.eatWhile(/[\da-f]/i))
return 'number';
}
else if (stream.eat('%'))
{
if (stream.eatWhile(/[01]/))
return 'number';
}
else
{
stream.next();
}

return null;
}};
});

CodeMirror.defineMIME("text/x-z80", "z80");
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codemirror",
"version":"3.0.2",
"version":"3.0.11",
"main": "codemirror.js",
"description": "In-browser code editing made bearable",
"licenses": [{"type": "MIT",
Expand Down
1,593 changes: 1,593 additions & 0 deletions test/lint/acorn.js

Large diffs are not rendered by default.

154 changes: 69 additions & 85 deletions test/lint/lint.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Simple linter, based on UglifyJS's [1] parse-js module
Simple linter, based on the Acorn [1] parser module

All of the existing linters either cramp my style or have huge
dependencies (Closure). So here's a very simple, non-invasive one
Expand All @@ -9,104 +9,88 @@
- variables or properties that are reserved words
- assigning to a variable you didn't declare

[1]: https://github.com/mishoo/UglifyJS/
[1]: https://github.com/marijnh/acorn/
*/

var fs = require("fs"), parse_js = require("./parse-js").parse;
var fs = require("fs"), acorn = require("./acorn.js"), walk = require("./walk.js");

var reserved = {};
"break case catch continue debugger default delete do else false finally for function if in\
instanceof new null return switch throw true try typeof var void while with abstract enum\
int short boolean export interface static byte extends long super char final native\
synchonized class float package throws const goto private transient implements protected\
volatile double import public const".split(" ").forEach(function(word) { reserved[word] = true; });
var scopePasser = walk.make({
ScopeBody: function(node, prev, c) { c(node, node.scope); }
});

function checkVariable(scope, name, pos) {
while (scope) {
if (scope.cur.hasOwnProperty(name)) return;
scope = scope.prev;
function checkFile(fileName) {
var file = fs.readFileSync(fileName, "utf8");
var badChar = file.match(/[\x00-\x08\x0b\x0c\x0e-\x19\uFEFF]/);
if (badChar)
fail("Undesirable character " + badChar[0].charCodeAt(0) + " at position " + badChar.index,
{source: fileName});

try {
var parsed = acorn.parse(file, {
locations: true,
ecmaVersion: 3,
strictSemicolons: true,
forbidReserved: true,
sourceFile: fileName
});
} catch (e) {
fail(e.message, {source: fileName});
return;
}
fail("Accidental global: " + name, pos);
}
function checkProperty(name, pos) {
if (reserved.hasOwnProperty(name)) {
fail("Using a keyword or reserved word as a property: " + name, pos);

var scopes = [];

walk.simple(parsed, {
ScopeBody: function(node, scope) {
node.scope = scope;
scopes.push(scope);
}
}, walk.scopeVisitor, {vars: Object.create(null)});

var ignoredGlobals = Object.create(null);

function inScope(name, scope) {
for (var cur = scope; cur; cur = cur.prev)
if (name in cur.vars) return true;
}
function checkLHS(node, scope) {
if (node.type == "Identifier" && !(node.name in ignoredGlobals) &&
!inScope(node.name, scope)) {
ignoredGlobals[node.name] = true;
fail("Assignment to global variable", node.loc);
}
}
}

function walk(ast, scope) {
var tp = ast[0];
if (typeof tp != "string") tp = tp.name;
function sub(ast) { if (ast) walk(ast, scope); }
function subn(array) { if (array) array.forEach(sub); }
if (tp == "block" || tp == "splice" || tp == "toplevel" || tp == "array") {
subn(ast[1]);
} else if (tp == "var" || tp == "const") {
ast[1].forEach(function(def) { scope.cur[def[0]] = true; if (def[1]) sub(def[1]); });
} else if (tp == "try") {
subn(ast[1]);
if (ast[2]) { scope.cur[ast[2][0]] = true; subn(ast[2][1]); }
subn(ast[3]);
} else if (tp == "throw" || tp == "return" || tp == "dot" || tp == "stat") {
sub(ast[1]);
} else if (tp == "dot") {
sub(ast[1]);
checkProperty(ast[2], ast[0]);
} else if (tp == "new" || tp == "call") {
sub(ast[1]); subn(ast[2]);
} else if (tp == "switch") {
sub(ast[1]);
ast[2].forEach(function(part) { sub(part[0]); subn(part[1]); });
} else if (tp == "conditional" || tp == "if" || tp == "for" || tp == "for-in") {
sub(ast[1]); sub(ast[2]); sub(ast[3]); sub(ast[4]);
} else if (tp == "assign") {
if (ast[2][0].name == "name") checkVariable(scope, ast[2][1], ast[2][0]);
sub(ast[2]); sub(ast[3]);
} else if (tp == "function" || tp == "defun") {
if (tp == "defun") scope.cur[ast[1]] = true;
var nscope = {prev: scope, cur: {}};
ast[2].forEach(function(arg) { nscope.cur[arg] = true; });
ast[3].forEach(function(ast) { walk(ast, nscope); });
} else if (tp == "while" || tp == "do" || tp == "sub" || tp == "with") {
sub(ast[1]); sub(ast[2]);
} else if (tp == "binary" || tp == "unary-prefix" || tp == "unary-postfix" || tp == "label") {
if (/\+\+|--/.test(ast[1]) && ast[2][0].name == "name") checkVariable(scope, ast[2][1], ast[2][0]);
sub(ast[2]); sub(ast[3]);
} else if (tp == "object") {
ast[1].forEach(function(prop) {
if (prop.type != "string") checkProperty(prop[0], ast[0]);
sub(prop[1]); sub(prop[2]);
});
} else if (tp == "seq") {
subn(ast.slice(1));
} else if (tp == "name") {
if (reserved.hasOwnProperty(ast[1]) && !/^(?:null|true|false)$/.test(ast[1]))
fail("Using reserved word as variable name: " + ast[1], ast[0]);
walk.simple(parsed, {
UpdateExpression: function(node, scope) {checkLHS(node.argument, scope);},
AssignmentExpression: function(node, scope) {checkLHS(node.left, scope);},
Identifier: function(node, scope) {
// Mark used identifiers
for (var cur = scope; cur; cur = cur.prev)
if (node.name in cur.vars) {
cur.vars[node.name].used = true;
return;
}
}
}, scopePasser);

for (var i = 0; i < scopes.length; ++i) {
var scope = scopes[i];
for (var name in scope.vars) {
var info = scope.vars[name];
if (!info.used && info.type != "catch clause" && info.type != "function name" && name.charAt(0) != "_")
fail("Unused " + info.type + " " + name, info.node.loc);
}
}
}

var failed = false, curFile;
var failed = false;
function fail(msg, pos) {
if (typeof pos == "object") pos = pos.start.line + 1;
console.log(curFile + ": " + msg + (typeof pos == "number" ? " (" + pos + ")" : ""));
if (pos.start) msg += " (" + pos.start.line + ":" + pos.start.column + ")";
console.log(pos.source.match(/[^\/]+$/)[0] + ": " + msg);
failed = true;
}

function checkFile(fileName) {
curFile = fileName.match(/[^\/+]*\.js$/)[0];
var file = fs.readFileSync(fileName, "utf8");
var badChar = file.match(/[\x00-\x08\x0b\x0c\x0e-\x19\uFEFF]/);
if (badChar) fail("Undesirable character " + badChar[0].charCodeAt(0) + " at position " + badChar.index);
if (/^#!/.test(file)) file = file.slice(file.indexOf("\n") + 1);
try {
var parsed = parse_js(file, true, true);
} catch(e) {
fail(e.message, e.line);
return;
}
walk(parsed, {prev: null, cur: {}});
}

function checkDir(dir) {
fs.readdirSync(dir).forEach(function(file) {
var fname = dir + "/" + file;
Expand Down
216 changes: 216 additions & 0 deletions test/lint/walk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// AST walker module for Mozilla Parser API compatible trees

(function(exports) {
"use strict";

// A simple walk is one where you simply specify callbacks to be
// called on specific nodes. The last two arguments are optional. A
// simple use would be
//
// walk.simple(myTree, {
// Expression: function(node) { ... }
// });
//
// to do something with all expressions. All Parser API node types
// can be used to identify node types, as well as Expression,
// Statement, and ScopeBody, which denote categories of nodes.
//
// The base argument can be used to pass a custom (recursive)
// walker, and state can be used to give this walked an initial
// state.
exports.simple = function(node, visitors, base, state) {
if (!base) base = exports;
function c(node, st, override) {
var type = override || node.type, found = visitors[type];
if (found) found(node, st);
base[type](node, st, c);
}
c(node, state);
};

// A recursive walk is one where your functions override the default
// walkers. They can modify and replace the state parameter that's
// threaded through the walk, and can opt how and whether to walk
// their child nodes (by calling their third argument on these
// nodes).
exports.recursive = function(node, state, funcs, base) {
var visitor = exports.make(funcs, base);
function c(node, st, override) {
visitor[override || node.type](node, st, c);
}
c(node, state);
};

// Used to create a custom walker. Will fill in all missing node
// type properties with the defaults.
exports.make = function(funcs, base) {
if (!base) base = exports;
var visitor = {};
for (var type in base)
visitor[type] = funcs.hasOwnProperty(type) ? funcs[type] : base[type];
return visitor;
};

function skipThrough(node, st, c) { c(node, st); }
function ignore(node, st, c) {}

// Node walkers.

exports.Program = exports.BlockStatement = function(node, st, c) {
for (var i = 0; i < node.body.length; ++i)
c(node.body[i], st, "Statement");
};
exports.Statement = skipThrough;
exports.EmptyStatement = ignore;
exports.ExpressionStatement = function(node, st, c) {
c(node.expression, st, "Expression");
};
exports.IfStatement = function(node, st, c) {
c(node.test, st, "Expression");
c(node.consequent, st, "Statement");
if (node.alternate) c(node.alternate, st, "Statement");
};
exports.LabeledStatement = function(node, st, c) {
c(node.body, st, "Statement");
};
exports.BreakStatement = exports.ContinueStatement = ignore;
exports.WithStatement = function(node, st, c) {
c(node.object, st, "Expression");
c(node.body, st, "Statement");
};
exports.SwitchStatement = function(node, st, c) {
c(node.discriminant, st, "Expression");
for (var i = 0; i < node.cases.length; ++i) {
var cs = node.cases[i];
if (cs.test) c(cs.test, st, "Expression");
for (var j = 0; j < cs.consequent.length; ++j)
c(cs.consequent[j], st, "Statement");
}
};
exports.ReturnStatement = function(node, st, c) {
if (node.argument) c(node.argument, st, "Expression");
};
exports.ThrowStatement = function(node, st, c) {
c(node.argument, st, "Expression");
};
exports.TryStatement = function(node, st, c) {
c(node.block, st, "Statement");
for (var i = 0; i < node.handlers.length; ++i)
c(node.handlers[i].body, st, "ScopeBody");
if (node.finalizer) c(node.finalizer, st, "Statement");
};
exports.WhileStatement = function(node, st, c) {
c(node.test, st, "Expression");
c(node.body, st, "Statement");
};
exports.DoWhileStatement = exports.WhileStatement;
exports.ForStatement = function(node, st, c) {
if (node.init) c(node.init, st, "ForInit");
if (node.test) c(node.test, st, "Expression");
if (node.update) c(node.update, st, "Expression");
c(node.body, st, "Statement");
};
exports.ForInStatement = function(node, st, c) {
c(node.left, st, "ForInit");
c(node.right, st, "Expression");
c(node.body, st, "Statement");
};
exports.ForInit = function(node, st, c) {
if (node.type == "VariableDeclaration") c(node, st);
else c(node, st, "Expression");
};
exports.DebuggerStatement = ignore;

exports.FunctionDeclaration = function(node, st, c) {
c(node, st, "Function");
};
exports.VariableDeclaration = function(node, st, c) {
for (var i = 0; i < node.declarations.length; ++i) {
var decl = node.declarations[i];
if (decl.init) c(decl.init, st, "Expression");
}
};

exports.Function = function(node, st, c) {
c(node.body, st, "ScopeBody");
};
exports.ScopeBody = function(node, st, c) {
c(node, st, "Statement");
};

exports.Expression = skipThrough;
exports.ThisExpression = ignore;
exports.ArrayExpression = function(node, st, c) {
for (var i = 0; i < node.elements.length; ++i) {
var elt = node.elements[i];
if (elt) c(elt, st, "Expression");
}
};
exports.ObjectExpression = function(node, st, c) {
for (var i = 0; i < node.properties.length; ++i)
c(node.properties[i].value, st, "Expression");
};
exports.FunctionExpression = exports.FunctionDeclaration;
exports.SequenceExpression = function(node, st, c) {
for (var i = 0; i < node.expressions.length; ++i)
c(node.expressions[i], st, "Expression");
};
exports.UnaryExpression = exports.UpdateExpression = function(node, st, c) {
c(node.argument, st, "Expression");
};
exports.BinaryExpression = exports.AssignmentExpression = exports.LogicalExpression = function(node, st, c) {
c(node.left, st, "Expression");
c(node.right, st, "Expression");
};
exports.ConditionalExpression = function(node, st, c) {
c(node.test, st, "Expression");
c(node.consequent, st, "Expression");
c(node.alternate, st, "Expression");
};
exports.NewExpression = exports.CallExpression = function(node, st, c) {
c(node.callee, st, "Expression");
if (node.arguments) for (var i = 0; i < node.arguments.length; ++i)
c(node.arguments[i], st, "Expression");
};
exports.MemberExpression = function(node, st, c) {
c(node.object, st, "Expression");
if (node.computed) c(node.property, st, "Expression");
};
exports.Identifier = exports.Literal = ignore;

// A custom walker that keeps track of the scope chain and the
// variables defined in it.
function makeScope(prev) {
return {vars: Object.create(null), prev: prev};
}
exports.scopeVisitor = exports.make({
Function: function(node, scope, c) {
var inner = makeScope(scope);
for (var i = 0; i < node.params.length; ++i)
inner.vars[node.params[i].name] = {type: "argument", node: node.params[i]};
if (node.id) {
var decl = node.type == "FunctionDeclaration";
(decl ? scope : inner).vars[node.id.name] =
{type: decl ? "function" : "function name", node: node.id};
}
c(node.body, inner, "ScopeBody");
},
TryStatement: function(node, scope, c) {
c(node.block, scope, "Statement");
for (var i = 0; i < node.handlers.length; ++i) {
var handler = node.handlers[i], inner = makeScope(scope);
inner.vars[handler.param.name] = {type: "catch clause", node: handler.param};
c(handler.body, inner, "ScopeBody");
}
if (node.finalizer) c(node.finalizer, scope, "Statement");
},
VariableDeclaration: function(node, scope, c) {
for (var i = 0; i < node.declarations.length; ++i) {
var decl = node.declarations[i];
scope.vars[decl.id.name] = {type: "var", node: decl.id};
if (decl.init) c(decl.init, scope, "Expression");
}
}
});

})(typeof exports == "undefined" ? acorn.walk = {} : exports);
3 changes: 2 additions & 1 deletion test/phantom_driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ page.open("http://localhost:3000/test/index.html", function (status) {
}, function () {
var failed = page.evaluate(function () { return window.failed; });
var output = page.evaluate(function () {
return document.getElementById('status').innerText;
return document.getElementById('output').innerText + "\n" +
document.getElementById('status').innerText;
});
console.log(output);
phantom.exit(failed > 0 ? 1 : 0);
Expand Down
Loading