@@ -4,7 +4,7 @@
<meta charset="utf-8">
<title>CodeMirror: Lua mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="../../lib/codemirror.js"></script>
<script src="lua.js"></script>
<link rel="stylesheet" href="../../theme/neat.css">
@@ -5,7 +5,7 @@
<title>CodeMirror: Markdown mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/continuelist.js"></script>
<script src="../../addon/edit/continuelist.js"></script>
<script src="../xml/xml.js"></script>
<script src="markdown.js"></script>
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
@@ -10,7 +10,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
"c++": "text/x-c++src",
java: "text/x-java",
csharp: "text/x-csharp",
"c#": "text/x-csharp"
"c#": "text/x-csharp",
scala: "text/x-scala"
};

var getMode = (function () {
@@ -246,8 +247,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
return getType(state);
}

if (ch === '!' && stream.match(/\[.*\] ?(?:\(|\[)/, false)) {
stream.match(/\[.*\]/);
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
stream.match(/\[[^\]]*\]/);
state.inline = state.f = linkHref;
return image;
}
@@ -456,10 +457,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
var difference = Math.floor((indentation - state.indentation) / 4) * 4;
if (difference > 4) difference = 4;
indentation = state.indentation + difference;
state.indentationDiff = indentation - state.indentation;
state.indentation = indentation;
if (indentation > 0) { return null; }
var adjustedIndentation = state.indentation + difference;
state.indentationDiff = adjustedIndentation - state.indentation;
state.indentation = adjustedIndentation;
if (indentation > 0) return null;
}
return state.f(stream, state);
},

Large diffs are not rendered by default.

@@ -0,0 +1,71 @@
CodeMirror.modeInfo = [
{name: 'APL', mime: 'text/apl', mode: 'apl'},
{name: 'Asterisk', mime: 'text/x-asterisk', mode: 'asterisk'},
{name: 'C', mime: 'text/x-csrc', mode: 'clike'},
{name: 'C++', mime: 'text/x-c++src', mode: 'clike'},
{name: 'Java', mime: 'text/x-java', mode: 'clike'},
{name: 'C#', mime: 'text/x-csharp', mode: 'clike'},
{name: 'Scala', mime: 'text/x-scala', mode: 'clike'},
{name: 'Clojure', mime: 'text/x-clojure', mode: 'clojure'},
{name: 'CoffeeScript', mime: 'text/x-coffeescript', mode: 'coffeescript'},
{name: 'Common Lisp', mime: 'text/x-common-lisp', mode: 'commonlisp'},
{name: 'CSS', mime: 'text/css', mode: 'css'},
{name: 'D', mime: 'text/x-d', mode: 'd'},
{name: 'diff', mime: 'text/x-diff', mode: 'diff'},
{name: 'ECL', mime: 'text/x-ecl', mode: 'ecl'},
{name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'},
{name: 'GitHub Flavored Markdown', mode: 'gfm'},
{name: 'GO', mime: 'text/x-go', mode: 'go'},
{name: 'Groovy', mime: 'text/x-groovy', mode: 'groovy'},
{name: 'Haskell', mime: 'text/x-haskell', mode: 'haskell'},
{name: 'Haxe', mime: 'text/x-haxe', mode: 'haxe'},
{name: 'ASP.NET', mime: 'application/x-aspx', mode: 'htmlembedded'},
{name: 'Embedded Javascript', mime: 'application/x-ejs', mode: 'htmlembedded'},
{name: 'JavaServer Pages', mime: 'application/x-jsp', mode: 'htmlembedded'},
{name: 'HTML', mime: 'text/html', mode: 'htmlmixed'},
{name: 'HTTP', mime: 'message/http', mode: 'http'},
{name: 'JavaScript', mime: 'text/javascript', mode: 'javascript'},
{name: 'JSON', mime: 'application/json', mode: 'javascript'},
{name: 'TypeScript', mime: 'application/typescript', mode: 'javascript'},
{name: 'Jinja2', mime: 'jinja2', mode: 'jinja2'},
{name: 'LESS', mime: 'text/x-less', mode: 'less'},
{name: 'Lua', mime: 'text/x-lua', mode: 'lua'},
{name: 'Markdown (GitHub-flavour)', mime: 'text/x-markdown', mode: 'markdown'},
{name: 'NTriples', mime: 'text/n-triples', mode: 'ntriples'},
{name: 'OCaml', mime: 'text/x-ocaml', mode: 'ocaml'},
{name: 'Pascal', mime: 'text/x-pascal', mode: 'pascal'},
{name: 'Perl', mime: 'text/x-perl', mode: 'perl'},
{name: 'PHP', mime: 'text/x-php', mode: 'php'},
{name: 'PHP(HTML)', mime: 'application/x-httpd-php', mode: 'php'},
{name: 'Pig', mime: 'text/x-pig', mode: 'pig'},
{name: 'Properties files', mime: 'text/x-properties', mode: 'clike'},
{name: 'Python', mime: 'text/x-python', mode: 'python'},
{name: 'R', mime: 'text/x-rsrc', mode: 'r'},
{name: 'reStructuredText', mime: 'text/x-rst', mode: 'rst'},
{name: 'Ruby', mime: 'text/x-ruby', mode: 'ruby'},
{name: 'Rust', mime: 'text/x-rustsrc', mode: 'rust'},
{name: 'Sass', mime: 'text/x-sass', mode: 'sass'},
{name: 'Scheme', mime: 'text/x-scheme', mode: 'scheme'},
{name: 'Shell', mime: 'text/x-sh', mode: 'shell'},
{name: 'Sieve', mime: 'application/sieve', mode: 'sieve'},
{name: 'Smalltalk', mime: 'text/x-stsrc', mode: 'smalltalk'},
{name: 'Smarty', mime: 'text/x-smarty', mode: 'smarty'},
{name: 'SPARQL', mime: 'application/x-sparql-query', mode: 'sparql'},
{name: 'SQL', mime: 'text/x-sql', mode: 'sql'},
{name: 'MySQL', mime: 'text/x-mysql', mode: 'sql'},
{name: 'MariaDB', mime: 'text/x-mariadb', mode: 'sql'},
{name: 'PL/SQL', mime: 'text/x-plsql', mode: 'sql'},
{name: 'sTeX', mime: 'text/x-stex', mode: 'stex'},
{name: 'LaTeX', mime: 'text/x-latex', mode: 'stex'},
{name: 'TiddlyWiki ', mime: 'text/x-tiddlywiki', mode: 'tiddlwiki'},
{name: 'Tiki wiki', mime: 'text/tiki', mode: 'tiki'},
{name: 'VB.NET', mime: 'text/x-vb', mode: 'vb'},
{name: 'VBScript', mime: 'text/vbscript', mode: 'vbscript'},
{name: 'Velocity', mime: 'text/velocity', mode: 'velocity'},
{name: 'Verilog', mime: 'text/x-verilog', mode: 'verilog'},
{name: 'XML', mime: 'application/xml', mode: 'xml'},
{name: 'HTML', mime: 'text/html', mode: 'xml'},
{name: 'XQuery', mime: 'application/xquery', mode: 'xquery'},
{name: 'YAML', mime: 'text/x-yaml', mode: 'yaml'},
{name: 'Z80', mime: 'text/x-z80', mode: 'z80'}
];
@@ -35,6 +35,8 @@ <h1>CodeMirror: MySQL mode</h1>
});
</script>

<p><strong><span style="color: red">!!</span> This mode is deprecated in favor of the <a href="../sql/index.html">generic SQL mode</a> (which can be configured to handle MySQL).</strong></p>

<p><strong>MIME types defined:</strong> <code>text/x-mysql</code>.</p>

</body>
@@ -10,7 +10,7 @@
</style>

<script src=../../lib/codemirror.js></script>
<script src=../../lib/util/matchbrackets.js></script>
<script src=../../addon/edit/matchbrackets.js></script>
<script src=ocaml.js></script>

<h1>CodeMirror: OCaml mode</h1>
@@ -5,7 +5,7 @@
<title>CodeMirror: PHP mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="../htmlmixed/htmlmixed.js"></script>
<script src="../xml/xml.js"></script>
<script src="../javascript/javascript.js"></script>
@@ -53,6 +53,8 @@ <h1>CodeMirror: Oracle PL/SQL mode</h1>
});
</script>

<p><strong><span style="color: red">!!</span> This mode is deprecated in favor of the <a href="../sql/index.html">generic SQL mode</a> (which can be configured to handle PL/SQL).</strong></p>

<p>
Simple mode that handles Oracle PL/SQL language (and Oracle SQL, of course).
</p>
@@ -5,7 +5,7 @@
<title>CodeMirror: Python mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="python.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>
@@ -5,7 +5,7 @@
<title>CodeMirror: Ruby mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="ruby.js"></script>
<style>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
@@ -0,0 +1,54 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: Sass mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="sass.js"></script>
<style>.CodeMirror {border: 1px solid #ddd; font-size:12px; height: 400px}</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: Sass mode</h1>
<form><textarea id="code" name="code">// Variable Definitions

$page-width: 800px
$sidebar-width: 200px
$primary-color: #eeeeee

// Global Attributes

body
font:
family: sans-serif
size: 30em
weight: bold

// Scoped Styles

#contents
width: $page-width
#sidebar
float: right
width: $sidebar-width
#main
width: $page-width - $sidebar-width
background: $primary-color
h2
color: blue

#footer
height: 200px
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers : true,
matchBrackets : true
});
</script>

<p><strong>MIME types defined:</strong> <code>text/x-sass</code>.</p>
</body>
</html>
@@ -0,0 +1,349 @@
CodeMirror.defineMode("sass", function(config) {
var tokenRegexp = function(words){
return new RegExp("^" + words.join("|"));
};

var tags = ["&", "a","abbr","acronym","address","applet","area","article","aside","audio","b","base","basefont","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","command","datalist","dd","del","details","dfn","dir","div","dl","dt","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","keygen","kbd","label","legend","li","link","map","mark","menu","meta","meter","nav","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strike","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","tt","u","ul","var","video","wbr"];
var keywords = ["true", "false", "null", "auto"];
var keywordsRegexp = new RegExp("^" + keywords.join("|"));

var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-", "\\!=", "/", "\\*", "%", "and", "or", "not"];
var opRegexp = tokenRegexp(operators);

function htmlTag(val){
for(var i=0; i<tags.length; i++){
if(val === tags[i]){
return true;
}
}
}


var pseudoElements = [':first-line', ':hover', ':first-letter', ':active', ':visited', ':before', ':after', ':link', ':focus', ':first-child', ':lang'];
var pseudoElementsRegexp = new RegExp("^(" + pseudoElements.join("\\b|") + ")");

var urlTokens = function(stream, state){
var ch = stream.peek();

if (ch === ")"){
stream.next();
state.tokenizer = tokenBase;
return "operator";
}else if (ch === "("){
stream.next();
stream.eatSpace();

return "operator";
}else if (ch === "'" || ch === '"'){
state.tokenizer = buildStringTokenizer(stream.next());
return "string";
}else{
state.tokenizer = buildStringTokenizer(")", false);
return "string";
}
};
var multilineComment = function(stream, state) {
if (stream.skipTo("*/")){
stream.next();
stream.next();
state.tokenizer = tokenBase;
}else {
stream.next();
}

return "comment";
};

var buildStringTokenizer = function(quote, greedy){
if(greedy == null){ greedy = true; }

function stringTokenizer(stream, state){
var nextChar = stream.next();
var peekChar = stream.peek();
var previousChar = stream.string.charAt(stream.pos-2);

var endingString = ((nextChar !== "\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\"));

/*
console.log("previousChar: " + previousChar);
console.log("nextChar: " + nextChar);
console.log("peekChar: " + peekChar);
console.log("ending: " + endingString);
*/

if (endingString){
if (nextChar !== quote && greedy) { stream.next(); }
state.tokenizer = tokenBase;
return "string";
}else if (nextChar === "#" && peekChar === "{"){
state.tokenizer = buildInterpolationTokenizer(stringTokenizer);
stream.next();
return "operator";
}else {
return "string";
}
}

return stringTokenizer;
};

var buildInterpolationTokenizer = function(currentTokenizer){
return function(stream, state){
if (stream.peek() === "}"){
stream.next();
state.tokenizer = currentTokenizer;
return "operator";
}else{
return tokenBase(stream, state);
}
};
};

var indent = function(state){
if (state.indentCount == 0){
state.indentCount++;
var lastScopeOffset = state.scopes[0].offset;
var currentOffset = lastScopeOffset + config.indentUnit;
state.scopes.unshift({ offset:currentOffset });
}
};

var dedent = function(state){
if (state.scopes.length == 1) { return; }

state.scopes.shift();
};

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

// Single line Comment
if (stream.match('//')) {
stream.skipToEnd();
return "comment";
}

// Multiline Comment
if (stream.match('/*')){
state.tokenizer = multilineComment;
return state.tokenizer(stream, state);
}

// Interpolation
if (stream.match('#{')){
state.tokenizer = buildInterpolationTokenizer(tokenBase);
return "operator";
}

if (ch === "."){
stream.next();

// Match class selectors
if (stream.match(/^[\w-]+/)){
indent(state);
return "atom";
}else if (stream.peek() === "#"){
indent(state);
return "atom";
}else{
return "operator";
}
}

if (ch === "#"){
stream.next();

// Hex numbers
if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){
return "number";
}

// ID selectors
if (stream.match(/^[\w-]+/)){
indent(state);
return "atom";
}

if (stream.peek() === "#"){
indent(state);
return "atom";
}
}

// Numbers
if (stream.match(/^-?[0-9\.]+/)){
return "number";
}

// Units
if (stream.match(/^(px|em|in)\b/)){
return "unit";
}

if (stream.match(keywordsRegexp)){
return "keyword";
}

if (stream.match(/^url/) && stream.peek() === "("){
state.tokenizer = urlTokens;
return "atom";
}

// Variables
if (ch === "$"){
stream.next();
stream.eatWhile(/[\w-]/);

if (stream.peek() === ":"){
stream.next();
return "variable-2";
}else{
return "variable-3";
}
}

if (ch === "!"){
stream.next();

if (stream.match(/^[\w]+/)){
return "keyword";
}

return "operator";
}

if (ch === "="){
stream.next();

// Match shortcut mixin definition
if (stream.match(/^[\w-]+/)){
indent(state);
return "meta";
}else {
return "operator";
}
}

if (ch === "+"){
stream.next();

// Match shortcut mixin definition
if (stream.match(/^[\w-]+/)){
return "variable-3";
}else {
return "operator";
}
}

// Indent Directives
if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)){
indent(state);
return "meta";
}

// Other Directives
if (ch === "@"){
stream.next();
stream.eatWhile(/[\w-]/);
return "meta";
}

// Strings
if (ch === '"' || ch === "'"){
stream.next();
state.tokenizer = buildStringTokenizer(ch);
return "string";
}

// Pseudo element selectors
if (stream.match(pseudoElementsRegexp)){
return "keyword";
}

// atoms
if (stream.eatWhile(/[\w-&]/)){

var current = stream.current();
// matches a property definition
if (stream.peek() === ":"){
// if this is an html tag and it has a pseudo selector, then it's an atom
if (htmlTag(current) && stream.match(pseudoElementsRegexp, false)){
return "atom";
}else{
stream.next();
return "property";
}
}
return "atom";
}

if (stream.match(opRegexp)){
return "operator";
}

// If we haven't returned by now, we move 1 character
// and return an error
stream.next();
return 'error';
};

var tokenLexer = function(stream, state) {
if (stream.sol()){
state.indentCount = 0;
}
var style = state.tokenizer(stream, state);
var current = stream.current();

if (current === "@return"){
dedent(state);
}

if (style === "atom" && htmlTag(current)){
indent(state);
}

if (style !== "error"){
var startOfToken = stream.pos - current.length;
var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);

var newScopes = [];

for (var i = 0; i < state.scopes.length; i++){
var scope = state.scopes[i];

if (scope.offset <= withCurrentIndent){
newScopes.push(scope);
}
}

state.scopes = newScopes;
}


return style;
};

return {
startState: function() {
return {
tokenizer: tokenBase,
scopes: [{offset: 0, type: 'sass'}],
definedVars: [],
definedMixins: [],
};
},
token: function(stream, state) {
var style = tokenLexer(stream, state);

state.lastToken = { style: style, content: stream.current() };

return style;
},

indent: function(state) {
return state.scopes[0].offset;
}
};
});

CodeMirror.defineMIME("text/x-sass", "sass");
@@ -10,7 +10,7 @@
</style>

<script src=../../lib/codemirror.js></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src=shell.js></script>

<h1>CodeMirror: Shell mode</h1>
@@ -17,7 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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.

Please note that some subdirectories of the CodeMirror distribution
include their own LICENSE files, and are released under different
licences.
@@ -31,19 +31,37 @@ CodeMirror.defineMode("sieve", function(config) {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}

if (ch === "{")
{
state._indent++;

if (ch == "(") {
state._indent.push("(");
// add virtual angel wings so that editor behaves...
// ...more sane incase of broken brackets
state._indent.push("{");
return null;
}

if (ch === "}")
{
state._indent--;
if (ch === "{") {
state._indent.push("{");
return null;
}

if (ch == ")") {
state._indent.pop();
state._indent.pop();
}

if (ch === "}") {
state._indent.pop();
return null;
}

if (ch == ",")
return null;

if (ch == ";")
return null;


if (/[{}\(\),;]/.test(ch))
return null;

@@ -62,7 +80,7 @@ CodeMirror.defineMode("sieve", function(config) {
return "operator";
}

stream.eatWhile(/[\w\$_]/);
stream.eatWhile(/\w/);
var cur = stream.current();

// "text:" *(SP / HTAB) (hash-comment / CRLF)
@@ -79,6 +97,8 @@ CodeMirror.defineMode("sieve", function(config) {

if (atoms.propertyIsEnumerable(cur))
return "atom";

return null;
}

function tokenMultiLineString(stream, state)
@@ -135,7 +155,7 @@ CodeMirror.defineMode("sieve", function(config) {
startState: function(base) {
return {tokenize: tokenBase,
baseIndent: base || 0,
_indent: 0};
_indent: []};
},

token: function(stream, state) {
@@ -146,7 +166,14 @@ CodeMirror.defineMode("sieve", function(config) {
},

indent: function(state, _textAfter) {
return state.baseIndent + state._indent * indentUnit;
var length = state._indent.length;
if (_textAfter && (_textAfter[0] == "}"))
length--;

if (length <0)
length = 0;

return length * indentUnit;
},

electricChars: "}"
@@ -5,7 +5,7 @@
<title>CodeMirror: Smalltalk mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="smalltalk.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">
<style>
@@ -5,7 +5,7 @@
<title>CodeMirror: SPARQL mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="sparql.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<link rel="stylesheet" href="../../doc/docs.css">
@@ -0,0 +1,68 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>SQL Mode for CodeMirror</title>
<link rel="stylesheet" href="../../lib/codemirror.css" />
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/continuelist.js"></script>
<script src="sql.js"></script>
<style>
.CodeMirror {
border-top: 1px solid black;
border-bottom: 1px solid black;
}
</style>
<link rel="stylesheet" href="../../doc/docs.css">
<script>
var init = function() {
var mime = 'text/x-mariadb';

// get mime type
if (window.location.href.indexOf('mime=') > -1) {
mime = window.location.href.substr(window.location.href.indexOf('mime=') + 5);
}

window.editor = CodeMirror.fromTextArea(document.getElementById('code'), {
mode: mime,
indentWithTabs: true,
smartIndent: true,
lineNumbers: true,
matchBrackets : true,
autofocus: true
});
};
</script>
</head>
<body onload="init();">
<h1>SQL Mode for CodeMirror</h1>
<form>
<textarea id="code" name="code">-- SQL Mode for CodeMirror
SELECT SQL_NO_CACHE DISTINCT
@var1 AS `val1`, @'val2', @global.'sql_mode',
1.1 AS `float_val`, .14 AS `another_float`, 0.09e3 AS `int_with_esp`,
0xFA5 AS `hex`, x'fa5' AS `hex2`, 0b101 AS `bin`, b'101' AS `bin2`,
DATE '1994-01-01' AS `sql_date`, { T "1994-01-01" } AS `odbc_date`,
'myString', UNKNOWN
FROM DUAL
-- space needed after '--'
# 1 line comment
/* multiline
comment! */
LIMIT 1 OFFSET 0;
</textarea>
</form>
<p><strong>MIME types defined:</strong>
<code><a href="?mime=text/x-sql">text/x-sql</a></code>,
<code><a href="?mime=text/x-mysql">text/x-mysql</a></code>,
<code><a href="?mime=text/x-mariadb">text/x-mariadb</a></code>,
<code><a href="?mime=text/x-plsql">text/x-plsql</a></code>.
</p>
<p>
<strong>Tests:</strong>
<a href="../../test/index.html#sql_*">normal</a>,
<a href="../../test/index.html#verbose,sql_*">verbose</a>.
</p>
</body>
</html>

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -5,7 +5,7 @@
<title>CodeMirror: TiddlyWiki mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/matchbrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="tiddlywiki.js"></script>
<link rel="stylesheet" href="tiddlywiki.css">
<link rel="stylesheet" href="../../doc/docs.css">
@@ -12,7 +12,7 @@
.CodeMirror-scroll { overflow-x: auto; overflow-y: hidden;}
.CodeMirror pre { font-family: Inconsolata; font-size: 14px}
</style>
<script type="text/javascript" src="../../lib/util/runmode.js"></script>
<script type="text/javascript" src="../../addon/runmode/runmode.js"></script>
</head>
<body onload="init()">
<h1>CodeMirror: VB.NET mode</h1>
@@ -1,77 +1,64 @@
// Initiate ModeTest and set defaults
var MT = ModeTest;
MT.modeName = "xquery";
MT.modeOptions = {};
// Don't take these too seriously -- the expected results appear to be
// based on the results of actual runs without any serious manual
// verification. If a change you made causes them to fail, the test is
// as likely to wrong as the code.

MT.testMode("eviltest",
'xquery version &quot;1.0-ml&quot;;\
(: this is\
: a \
"comment" :)\
let $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;\
let $joe:=1\
return element element {\
attribute attribute { 1 },\
element test { &#39;a&#39; }, \
attribute foo { &quot;bar&quot; },\
fn:doc()[ foo/@bar eq $let ],\
//x } \
\
(: a more \'evil\' test :)\
(: Modified Blakeley example (: with nested comment :) ... :)\
declare private function local:declare() {()};\
declare private function local:private() {()};\
declare private function local:function() {()};\
declare private function local:local() {()};\
let $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;\
return element element {\
attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },\
attribute fn:doc { &quot;bar&quot; castable as xs:string },\
element text { text { &quot;text&quot; } },\
fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],\
//fn:doc\
}', ["keyword","xquery",null," ","keyword","version",null," ","variable","&quot;1","keyword",".","atom","0","keyword","-","variable","ml&quot;","def variable",";",null," ","comment","(: this is : a \"comment\" :)",null," ","keyword","let",null," ","variable","$let",null," ","keyword",":=",null," ","variable","&lt;x",null," ","variable","attr","keyword","=","variable","&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt","def variable",";function","","()",null," ","variable","$var",null," ","","{","keyword","function","","()}",null," ","","{","variable","$var","","}","variable","&lt;","keyword","/","variable","func&gt;&lt;","keyword","/","variable","x&gt;",null," ","keyword","let",null," ","variable","$joe","keyword",":=","atom","1",null," ","keyword","return",null," ","keyword","element",null," ","variable","element",null," ","","{",null," ","keyword","attribute",null," ","variable","attribute",null," ","","{",null," ","atom","1",null," ","","},",null," ","keyword","element",null," ","variable","test",null," ","","{",null," ","variable","&#39;a&#39;",null," ","","},",null," ","keyword","attribute",null," ","variable","foo",null," ","","{",null," ","variable","&quot;bar&quot;",null," ","","},",null," ","def variable","fn:doc","","()[",null," ","variable","foo","keyword","/","variable","@bar",null," ","keyword","eq",null," ","variable","$let",null," ","","],",null," ","keyword","//","variable","x",null," ","","}",null," ","comment","(: a more 'evil' test :)",null," ","comment","(: Modified Blakeley example (: with nested comment :) ... :)",null," ","keyword","declare",null," ","keyword","private",null," ","keyword","function",null," ","def variable","local:declare","","()",null," ","","{()}","variable",";",null," ","keyword","declare",null," ","keyword","private",null," ","keyword","function",null," ","def variable","local:private","","()",null," ","","{()}","variable",";",null," ","keyword","declare",null," ","keyword","private",null," ","keyword","function",null," ","def variable","local:function","","()",null," ","","{()}","variable",";",null," ","keyword","declare",null," ","keyword","private",null," ","keyword","function",null," ","def variable","local:local","","()",null," ","","{()}","variable",";",null," ","keyword","let",null," ","variable","$let",null," ","keyword",":=",null," ","variable","&lt;let&gt;let",null," ","variable","$let",null," ","keyword",":=",null," ","variable","&quot;let&quot;&lt;","keyword","/let","variable","&gt;",null," ","keyword","return",null," ","keyword","element",null," ","variable","element",null," ","","{",null," ","keyword","attribute",null," ","variable","attribute",null," ","","{",null," ","keyword","try",null," ","","{",null," ","def variable","xdmp:version","","()",null," ","","}",null," ","keyword","catch","","(","variable","$e","",")",null," ","","{",null," ","def variable","xdmp:log","","(","variable","$e","",")",null," ","","}",null," ","","},",null," ","keyword","attribute",null," ","variable","fn:doc",null," ","","{",null," ","variable","&quot;bar&quot;",null," ","variable","castable",null," ","keyword","as",null," ","atom","xs:string",null," ","","},",null," ","keyword","element",null," ","variable","text",null," ","","{",null," ","keyword","text",null," ","","{",null," ","variable","&quot;text&quot;",null," ","","}",null," ","","},",null," ","def variable","fn:doc","","()[",null," ","qualifier","child::","variable","eq","keyword","/","","(","variable","@bar",null," ","keyword","|",null," ","qualifier","attribute::","variable","attribute","",")",null," ","keyword","eq",null," ","variable","$let",null," ","","],",null," ","keyword","//","variable","fn:doc",null," ","","}"]);
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "xquery");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }

MT.testMode("testEmptySequenceKeyword",
'"foo" instance of empty-sequence()',
["string","\"foo\"",null," ","keyword","instance",null," ","keyword","of",null," ","keyword","empty-sequence","","()"]);
MT("eviltest",
"[keyword xquery] [keyword version] [variable &quot;1][keyword .][atom 0][keyword -][variable ml&quot;][def&variable ;] [comment (: this is : a \"comment\" :)]",
" [keyword let] [variable $let] [keyword :=] [variable &lt;x] [variable attr][keyword =][variable &quot;value&quot;&gt;&quot;test&quot;&lt;func&gt][def&variable ;function]() [variable $var] {[keyword function]()} {[variable $var]}[variable &lt;][keyword /][variable func&gt;&lt;][keyword /][variable x&gt;]",
" [keyword let] [variable $joe][keyword :=][atom 1]",
" [keyword return] [keyword element] [variable element] {",
" [keyword attribute] [variable attribute] { [atom 1] },",
" [keyword element] [variable test] { [variable &#39;a&#39;] }, [keyword attribute] [variable foo] { [variable &quot;bar&quot;] },",
" [def&variable fn:doc]()[[ [variable foo][keyword /][variable @bar] [keyword eq] [variable $let] ]],",
" [keyword //][variable x] } [comment (: a more 'evil' test :)]",
" [comment (: Modified Blakeley example (: with nested comment :) ... :)]",
" [keyword declare] [keyword private] [keyword function] [def&variable local:declare]() {()}[variable ;]",
" [keyword declare] [keyword private] [keyword function] [def&variable local:private]() {()}[variable ;]",
" [keyword declare] [keyword private] [keyword function] [def&variable local:function]() {()}[variable ;]",
" [keyword declare] [keyword private] [keyword function] [def&variable local:local]() {()}[variable ;]",
" [keyword let] [variable $let] [keyword :=] [variable &lt;let&gt;let] [variable $let] [keyword :=] [variable &quot;let&quot;&lt;][keyword /let][variable &gt;]",
" [keyword return] [keyword element] [variable element] {",
" [keyword attribute] [variable attribute] { [keyword try] { [def&variable xdmp:version]() } [keyword catch]([variable $e]) { [def&variable xdmp:log]([variable $e]) } },",
" [keyword attribute] [variable fn:doc] { [variable &quot;bar&quot;] [variable castable] [keyword as] [atom xs:string] },",
" [keyword element] [variable text] { [keyword text] { [variable &quot;text&quot;] } },",
" [def&variable fn:doc]()[[ [qualifier child::][variable eq][keyword /]([variable @bar] [keyword |] [qualifier attribute::][variable attribute]) [keyword eq] [variable $let] ]],",
" [keyword //][variable fn:doc]",
" }");

MT("testEmptySequenceKeyword",
"[string \"foo\"] [keyword instance] [keyword of] [keyword empty-sequence]()");

MT.testMode("testMultiAttr",
'<p a1="foo" a2="bar">hello world</p>',
["tag","<p ","attribute","a1","","=","string","\"foo\"",null," ","attribute","a2","","=","string","\"bar\"","tag",">","variable","hello",null," ","variable","world","tag","</p>"]);
MT("testMultiAttr",
"[tag <p ][attribute a1]=[string \"foo\"] [attribute a2]=[string \"bar\"][tag >][variable hello] [variable world][tag </p>]");

MT.testMode("test namespaced variable",
'declare namespace e = "http://example.com/ANamespace";\
declare variable $e:exampleComThisVarIsNotRecognized as element(*) external;',
["keyword","declare",null," ","keyword","namespace",null," ","variable","e",null," ","keyword","=",null," ","string","\"http://example.com/ANamespace\"","variable",";declare",null," ","keyword","variable",null," ","variable","$e:exampleComThisVarIsNotRecognized",null," ","keyword","as",null," ","keyword","element","","(","keyword","*","",")",null," ","variable","external;"]);
MT("test namespaced variable",
"[keyword declare] [keyword namespace] [variable e] [keyword =] [string \"http://example.com/ANamespace\"][variable ;declare] [keyword variable] [variable $e:exampleComThisVarIsNotRecognized] [keyword as] [keyword element]([keyword *]) [variable external;]");

MT.testMode("test EQName variable",
'declare variable $"http://www.example.com/ns/my":var := 12;\
<out>{$"http://www.example.com/ns/my":var}</out>',
["keyword","declare",null," ","keyword","variable",null," ","variable","$\"http://www.example.com/ns/my\":var",null," ","keyword",":=",null," ","atom","12","variable",";","tag","<out>","","{","variable","$\"http://www.example.com/ns/my\":var","","}","tag","</out>"]);
MT("test EQName variable",
"[keyword declare] [keyword variable] [variable $\"http://www.example.com/ns/my\":var] [keyword :=] [atom 12][variable ;]",
"[tag <out>]{[variable $\"http://www.example.com/ns/my\":var]}[tag </out>]");

MT.testMode("test EQName function",
'declare function "http://www.example.com/ns/my":fn ($a as xs:integer) as xs:integer {\
$a + 2\
};\
<out>{"http://www.example.com/ns/my":fn(12)}</out>',
["keyword","declare",null," ","keyword","function",null," ","def variable","\"http://www.example.com/ns/my\":fn",null," ","","(","variable","$a",null," ","keyword","as",null," ","atom","xs:integer","",")",null," ","keyword","as",null," ","atom","xs:integer",null," ","","{",null," ","variable","$a",null," ","keyword","+",null," ","atom","2","","}","variable",";","tag","<out>","","{","def variable","\"http://www.example.com/ns/my\":fn","","(","atom","12","",")}","tag","</out>"]);
MT("test EQName function",
"[keyword declare] [keyword function] [def&variable \"http://www.example.com/ns/my\":fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {",
" [variable $a] [keyword +] [atom 2]",
"}[variable ;]",
"[tag <out>]{[def&variable \"http://www.example.com/ns/my\":fn]([atom 12])}[tag </out>]");

MT.testMode("test EQName function with single quotes",
'declare function \'http://www.example.com/ns/my\':fn ($a as xs:integer) as xs:integer {\
$a + 2\
};\
<out>{\'http://www.example.com/ns/my\':fn(12)}</out>',
["keyword","declare",null," ","keyword","function",null," ","def variable","'http://www.example.com/ns/my':fn",null," ","","(","variable","$a",null," ","keyword","as",null," ","atom","xs:integer","",")",null," ","keyword","as",null," ","atom","xs:integer",null," ","","{",null," ","variable","$a",null," ","keyword","+",null," ","atom","2","","}","variable",";","tag","<out>","","{","def variable","'http://www.example.com/ns/my':fn","","(","atom","12","",")}","tag","</out>"]);
MT("test EQName function with single quotes",
"[keyword declare] [keyword function] [def&variable 'http://www.example.com/ns/my':fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {",
" [variable $a] [keyword +] [atom 2]",
"}[variable ;]",
"[tag <out>]{[def&variable 'http://www.example.com/ns/my':fn]([atom 12])}[tag </out>]");

MT.testMode("testProcessingInstructions",
'data(<?target content?>) instance of xs:string',
["def variable","data","","(","comment meta","<?target content?>","",")",null," ","keyword","instance",null," ","keyword","of",null," ","atom","xs:string"]);
MT("testProcessingInstructions",
"[def&variable data]([comment&meta <?target content?>]) [keyword instance] [keyword of] [atom xs:string]");

MT.testMode("testQuoteEscapeDouble",
'let $rootfolder := "c:\\builds\\winnt\\HEAD\\qa\\scripts\\"\
let $keysfolder := concat($rootfolder, "keys\\")\
return\
$keysfolder',
["keyword","let",null," ","variable","$rootfolder",null," ","keyword",":=",null," ","string","\"c:\\builds\\winnt\\HEAD\\qa\\scripts\\\"","keyword","let",null," ","variable","$keysfolder",null," ","keyword",":=",null," ","def variable","concat","","(","variable","$rootfolder","",",",null," ","string","\"keys\\\"","",")","variable","return$keysfolder"]);
MT("testQuoteEscapeDouble",
"[keyword let] [variable $rootfolder] [keyword :=] [string \"c:\\builds\\winnt\\HEAD\\qa\\scripts\\\"]",
"[keyword let] [variable $keysfolder] [keyword :=] [def&variable concat]([variable $rootfolder], [string \"keys\\\"])");
})();
@@ -33,7 +33,7 @@ CodeMirror.defineMode("xquery", function() {
, C = kw("keyword c")
, operator = kw("operator")
, atom = {type: "atom", style: "atom"}
, punctuation = {type: "punctuation", style: ""}
, punctuation = {type: "punctuation", style: null}
, qualifier = {type: "axis_specifier", style: "qualifier"};

// kwObj is what is return from this function at the end
@@ -121,12 +121,12 @@ CodeMirror.defineMode("xquery", function() {
// start code block
else if(ch == "{") {
pushStateStack(state,{ type: "codeblock"});
return ret("", "");
return ret("", null);
}
// end code block
else if(ch == "}") {
popStateStack(state);
return ret("", "");
return ret("", null);
}
// if we're in an XML block
else if(isInXmlBlock(state)) {
@@ -163,22 +163,22 @@ CodeMirror.defineMode("xquery", function() {
// open paren
else if(ch === "(") {
pushStateStack(state, { type: "paren"});
return ret("", "");
return ret("", null);
}
// close paren
else if(ch === ")") {
popStateStack(state);
return ret("", "");
return ret("", null);
}
// open paren
else if(ch === "[") {
pushStateStack(state, { type: "bracket"});
return ret("", "");
return ret("", null);
}
// close paren
else if(ch === "]") {
popStateStack(state);
return ret("", "");
return ret("", null);
}
else {
var known = keywords.propertyIsEnumerable(ch) && keywords[ch];
@@ -342,7 +342,7 @@ CodeMirror.defineMode("xquery", function() {
return ret("tag", "tag");
}
if(ch == "=")
return ret("", "");
return ret("", null);
// quoted string
if (ch == '"' || ch == "'")
return chain(stream, state, tokenString(ch, tokenAttribute));
@@ -1,6 +1,6 @@
{
"name": "codemirror",
"version":"3.0.2",
"version":"3.01.00",
"main": "codemirror.js",
"description": "In-browser code editing made bearable",
"licenses": [{"type": "MIT",
@@ -32,7 +32,7 @@ function testCM(name, run, opts, expectedFail) {
successful = true;
} finally {
if ((debug && !successful) || verbose) {
place.style.visibility = "";
place.style.visibility = "visible";
} else {
place.removeChild(cm.getWrapperElement());
}
@@ -48,10 +48,6 @@ function runTests(callback) {
}
if (debug.length < 1) {
debug = null;
} else {
if (totalTests > debug.length) {
totalTests = debug.length;
}
}
}
var totalTime = 0;
@@ -67,19 +63,15 @@ function runTests(callback) {
// Remove from array for reporting incorrect tests later
debug.splice(debugIndex, 1);
} else {
var wildcardName = test.name.split("_").shift() + "_*";
var wildcardName = test.name.split("_")[0] + "_*";
debugIndex = indexOf(debug, wildcardName);
if (debugIndex !== -1) {
// Remove from array for reporting incorrect tests later
debug.splice(debugIndex, 1);
debugUsed.push(wildcardName);
} else {
debugIndex = indexOf(debugUsed, wildcardName);
if (debugIndex !== -1) {
totalTests++;
} else {
return step(i + 1);
}
if (debugIndex == -1) return step(i + 1);
}
}
}
@@ -132,3 +124,15 @@ function eqPos(a, b, msg) {
function is(a, msg) {
if (!a) throw new Failure(label("assertion failed", msg));
}

function countTests() {
if (!debug) return tests.length;
var sum = 0;
for (var i = 0; i < tests.length; ++i) {
var name = tests[i].name;
if (indexOf(debug, name) != -1 ||
indexOf(debug, name.split("_")[0] + "_*") != -1)
++sum;
}
return sum;
}
@@ -7,8 +7,8 @@
<link rel="stylesheet" href="../doc/docs.css">
<link rel="stylesheet" href="mode_test.css">
<script src="../lib/codemirror.js"></script>
<script src="../lib/util/overlay.js"></script>
<script src="../lib/util/searchcursor.js"></script>
<script src="../addon/mode/overlay.js"></script>
<script src="../addon/search/searchcursor.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../keymap/vim.js"></script>
@@ -25,6 +25,15 @@
font-weight: bold;
white-space: pre;
}
#testground {
visibility: hidden;
}
#testground.offscreen {
visibility: visible;
position: absolute;
left: -10000px;
top: -10000px;
}
.CodeMirror { border: 1px solid black; }
</style>
</head>
@@ -39,7 +48,7 @@ <h1>CodeMirror: Test Suite</h1>
<p id=status>Please enable JavaScript...</p>
<div id=output></div>

<div style="visibility: hidden" id=testground></div>
<div id=testground></div>

<script src="driver.js"></script>
<script src="test.js"></script>
@@ -98,7 +107,7 @@ <h1>CodeMirror: Test Suite</h1>
bad = "";
verbose = false;
debugUsed = Array();
totalTests = tests.length;
totalTests = countTests();
progressTotal.nodeValue = " of " + totalTests;
progressRan.nodeValue = count;
output.innerHTML = '';
@@ -132,8 +141,6 @@ <h1>CodeMirror: Test Suite</h1>
var message = "???";
if (type != "done") ++count;
progress.style.width = (count * (progress.parentNode.clientWidth - 2) / totalTests) + "px";
progressTotal.nodeValue = " of " + totalTests +
(debugUsed.length && type != "done" ? "+" : "");
progressRan.nodeValue = count;
if (type == "ok") {
message = "Test '" + name + "' succeeded";
@@ -2,191 +2,191 @@
* Helper to test CodeMirror highlighting modes. It pretty prints output of the
* highlighter and can check against expected styles.
*
* See test.html in the stex mode for examples.
*/
ModeTest = {};

ModeTest.modeOptions = {};
ModeTest.modeName = CodeMirror.defaults.mode;

/* keep track of results for printSummary */
ModeTest.testCount = 0;
ModeTest.passes = 0;

/**
* Run a test; prettyprints the results using document.write().
*
* @param name Name of test
* @param text String to highlight.
* @param expected Expected styles and tokens: Array(style, token, [style, token,...])
* @param modeName
* @param modeOptions
* @param expectedFail
* Mode tests are registered by calling test.mode(testName, mode,
* tokens), where mode is a mode object as returned by
* CodeMirror.getMode, and tokens is an array of lines that make up
* the test.
*
* These lines are strings, in which styled stretches of code are
* enclosed in brackets `[]`, and prefixed by their style. For
* example, `[keyword if]`. Brackets in the code itself must be
* duplicated to prevent them from being interpreted as token
* boundaries. For example `a[[i]]` for `a[i]`. If a token has
* multiple styles, the styles must be separated by ampersands, for
* example `[tag&error </hmtl>]`.
*
* See the test.js files in the css, markdown, gfm, and stex mode
* directories for examples.
*/
ModeTest.testMode = function(name, text, expected, modeName, modeOptions, expectedFail) {
ModeTest.testCount += 1;

if (!modeName) modeName = ModeTest.modeName;

if (!modeOptions) modeOptions = ModeTest.modeOptions;

var mode = CodeMirror.getMode(modeOptions, modeName);

if (expected.length < 0) {
throw "must have text for test (" + name + ")";
}
if (expected.length % 2 != 0) {
throw "must have text for test (" + name + ") plus expected (style, token) pairs";
(function() {
function findSingle(str, pos, ch) {
for (;;) {
var found = str.indexOf(ch, pos);
if (found == -1) return null;
if (str.charAt(found + 1) != ch) return found;
pos = found + 2;
}
}
return test(
modeName + "_" + name,
function(){
return ModeTest.compare(text, expected, mode);
},
expectedFail
);

}

ModeTest.compare = function (text, expected, mode) {

var expectedOutput = [];
for (var i = 0; i < expected.length; i += 2) {
var sty = expected[i];
if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' ');
expectedOutput.push(sty, expected[i + 1]);
var styleName = /[\w&-_]+/g;
function parseTokens(strs) {
var tokens = [], plain = "";
for (var i = 0; i < strs.length; ++i) {
if (i) plain += "\n";
var str = strs[i], pos = 0;
while (pos < str.length) {
var style = null, text;
if (str.charAt(pos) == "[" && str.charAt(pos+1) != "[") {
styleName.lastIndex = pos + 1;
var m = styleName.exec(str);
style = m[0].replace(/&/g, " ");
var textStart = pos + style.length + 2;
var end = findSingle(str, textStart, "]");
if (end == null) throw new Error("Unterminated token at " + pos + " in '" + str + "'" + style);
text = str.slice(textStart, end);
pos = end + 1;
} else {
var end = findSingle(str, pos, "[");
if (end == null) end = str.length;
text = str.slice(pos, end);
pos = end;
}
text = text.replace(/\[\[|\]\]/g, function(s) {return s.charAt(0);});
tokens.push(style, text);
plain += text;
}
}
return {tokens: tokens, plain: plain};
}

var observedOutput = ModeTest.highlight(text, mode);

var pass, passStyle = "";
pass = ModeTest.highlightOutputsEqual(expectedOutput, observedOutput);
passStyle = pass ? 'mt-pass' : 'mt-fail';
ModeTest.passes += pass ? 1 : 0;
test.mode = function(name, mode, tokens) {
var data = parseTokens(tokens);
return test(mode.name + "_" + name, function() {
return compare(data.plain, data.tokens, mode);
});
};

var s = '';
if (pass) {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + ModeTest.htmlEscape(text) + '</pre>';
s += '<div class="cm-s-default">';
s += ModeTest.prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
return s;
} else {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + ModeTest.htmlEscape(text) + '</pre>';
s += '<div class="cm-s-default">';
s += 'expected:';
s += ModeTest.prettyPrintOutputTable(expectedOutput);
s += 'observed:';
s += ModeTest.prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
throw s;
}
}
function compare(text, expected, mode) {

/**
* Emulation of CodeMirror's internal highlight routine for testing. Multi-line
* input is supported.
*
* @param string to highlight
*
* @param mode the mode that will do the actual highlighting
*
* @return array of [style, token] pairs
*/
ModeTest.highlight = function(string, mode) {
var state = mode.startState()
var expectedOutput = [];
for (var i = 0; i < expected.length; i += 2) {
var sty = expected[i];
if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' ');
expectedOutput.push(sty, expected[i + 1]);
}

var lines = string.replace(/\r\n/g,'\n').split('\n');
var st = [], pos = 0;
for (var i = 0; i < lines.length; ++i) {
var line = lines[i], newLine = true;
var stream = new CodeMirror.StringStream(line);
if (line == "" && mode.blankLine) mode.blankLine(state);
/* Start copied code from CodeMirror.highlight */
while (!stream.eol()) {
var style = mode.token(stream, state), substr = stream.current();
if (style && style.indexOf(" ") > -1) style = style.split(' ').sort().join(' ');
var observedOutput = highlight(text, mode);

var pass, passStyle = "";
pass = highlightOutputsEqual(expectedOutput, observedOutput);
passStyle = pass ? 'mt-pass' : 'mt-fail';

var s = '';
if (pass) {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + text + '</pre>';
s += '<div class="cm-s-default">';
s += prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
return s;
} else {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + text + '</pre>';
s += '<div class="cm-s-default">';
s += 'expected:';
s += prettyPrintOutputTable(expectedOutput);
s += 'observed:';
s += prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
throw s;
}
}

stream.start = stream.pos;
if (pos && st[pos-2] == style && !newLine) {
st[pos-1] += substr;
} else if (substr) {
st[pos++] = style; st[pos++] = substr;
/**
* Emulation of CodeMirror's internal highlight routine for testing. Multi-line
* input is supported.
*
* @param string to highlight
*
* @param mode the mode that will do the actual highlighting
*
* @return array of [style, token] pairs
*/
function highlight(string, mode) {
var state = mode.startState()

var lines = string.replace(/\r\n/g,'\n').split('\n');
var st = [], pos = 0;
for (var i = 0; i < lines.length; ++i) {
var line = lines[i], newLine = true;
var stream = new CodeMirror.StringStream(line);
if (line == "" && mode.blankLine) mode.blankLine(state);
/* Start copied code from CodeMirror.highlight */
while (!stream.eol()) {
var style = mode.token(stream, state), substr = stream.current();
if (style && style.indexOf(" ") > -1) style = style.split(' ').sort().join(' ');

stream.start = stream.pos;
if (pos && st[pos-2] == style && !newLine) {
st[pos-1] += substr;
} else if (substr) {
st[pos++] = style; st[pos++] = substr;
}
// Give up when line is ridiculously long
if (stream.pos > 5000) {
st[pos++] = null; st[pos++] = this.text.slice(stream.pos);
break;
}
newLine = false;
}
// Give up when line is ridiculously long
if (stream.pos > 5000) {
st[pos++] = null; st[pos++] = this.text.slice(stream.pos);
break;
}
newLine = false;
}
}

return st;
}
return st;
}

/**
* Compare two arrays of output from ModeTest.highlight.
*
* @param o1 array of [style, token] pairs
*
* @param o2 array of [style, token] pairs
*
* @return boolean; true iff outputs equal
*/
ModeTest.highlightOutputsEqual = function(o1, o2) {
if (o1.length != o2.length) return false;
for (var i = 0; i < o1.length; ++i)
if (o1[i] != o2[i]) return false;
return true;
}
/**
* Compare two arrays of output from highlight.
*
* @param o1 array of [style, token] pairs
*
* @param o2 array of [style, token] pairs
*
* @return boolean; true iff outputs equal
*/
function highlightOutputsEqual(o1, o2) {
if (o1.length != o2.length) return false;
for (var i = 0; i < o1.length; ++i)
if (o1[i] != o2[i]) return false;
return true;
}

/**
* Print tokens and corresponding styles in a table. Spaces in the token are
* replaced with 'interpunct' dots (&middot;).
*
* @param output array of [style, token] pairs
*
* @return html string
*/
ModeTest.prettyPrintOutputTable = function(output) {
var s = '<table class="mt-output">';
s += '<tr>';
for (var i = 0; i < output.length; i += 2) {
var style = output[i], val = output[i+1];
s +=
/**
* Print tokens and corresponding styles in a table. Spaces in the token are
* replaced with 'interpunct' dots (&middot;).
*
* @param output array of [style, token] pairs
*
* @return html string
*/
function prettyPrintOutputTable(output) {
var s = '<table class="mt-output">';
s += '<tr>';
for (var i = 0; i < output.length; i += 2) {
var style = output[i], val = output[i+1];
s +=
'<td class="mt-token">' +
'<span class="cm-' + String(style).replace(/ +/g, " cm-") + '">' +
ModeTest.htmlEscape(val).replace(/ /g,'&middot;') +
val.replace(/ /g,'\xb7') +
'</span>' +
'</td>';
}
s += '</tr><tr>';
for (var i = 0; i < output.length; i += 2) {
s += '<td class="mt-style"><span>' + output[i] + '</span></td>';
'</td>';
}
s += '</tr><tr>';
for (var i = 0; i < output.length; i += 2) {
s += '<td class="mt-style"><span>' + output[i] + '</span></td>';
}
s += '</table>';
return s;
}
s += '</table>';
return s;
}

/**
* Print how many tests have run so far and how many of those passed.
*/
ModeTest.printSummary = function() {
ModeTest.runTests(ModeTest.displayTest);
document.write(ModeTest.passes + ' passes for ' + ModeTest.testCount + ' tests');
}

/**
* Basic HTML escaping.
*/
ModeTest.htmlEscape = function(str) {
str = str.toString();
return str.replace(/[<&]/g,
function(str) {return str == "&" ? "&amp;" : "&lt;";});
}

})();
@@ -4,6 +4,7 @@ var lint = require("./lint/lint");

lint.checkDir("mode");
lint.checkDir("lib");
lint.checkDir("addon");

var ok = lint.success();

@@ -25,7 +25,10 @@ function byClassName(elt, cls) {
var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
var mac = /Mac/.test(navigator.platform);
var phantom = /PhantomJS/.test(navigator.userAgent);
var opera_lt10 = /Opera\/[1-9]\./.test(navigator.userAgent);
var opera = /Opera\/\./.test(navigator.userAgent);
var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/);
if (opera_version) opera_version = Number(opera_version);
var opera_lt10 = opera && (!opera_version || opera_version < 10);

test("core_fromTextArea", function() {
var te = document.getElementById("code");
@@ -484,6 +487,7 @@ testCM("doubleScrollbar", function(cm) {
dummy.style.cssText = "height: 50px; overflow: scroll; width: 50px";
var scrollbarWidth = dummy.offsetWidth + 1 - dummy.clientWidth;
document.body.removeChild(dummy);
if (scrollbarWidth < 2) return;
cm.setSize(null, 100);
addDoc(cm, 1, 300);
var wrap = cm.getWrapperElement();
@@ -539,6 +543,21 @@ testCM("collapsedLines", function(cm) {
eq(cleared, 1);
});

testCM("collapsedRangeCoordsChar", function(cm) {
var pos_1_3 = cm.charCoords({line: 1, ch: 3});
pos_1_3.left += 2; pos_1_3.top += 2;
var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true};
var m1 = cm.markText({line: 0, ch: 0}, {line: 2, ch: 0}, opts);
eqPos(cm.coordsChar(pos_1_3), {line: 3, ch: 3});
m1.clear();
var m1 = cm.markText({line: 0, ch: 0}, {line: 1, ch: 1}, opts);
var m2 = cm.markText({line: 1, ch: 1}, {line: 2, ch: 0}, opts);
eqPos(cm.coordsChar(pos_1_3), {line: 3, ch: 3});
m1.clear(); m2.clear();
var m1 = cm.markText({line: 0, ch: 0}, {line: 1, ch: 6}, opts);
eqPos(cm.coordsChar(pos_1_3), {line: 3, ch: 3});
}, {value: "123456\nabcdef\nghijkl\nmnopqr\n"});

testCM("hiddenLinesAutoUnfold", function(cm) {
var range = foldLines(cm, 1, 3, true), cleared = 0;
CodeMirror.on(range, "clear", function() {cleared++;});
@@ -882,7 +901,8 @@ testCM("verticalMovementCommandsWrapping", function(cm) {
lineWrapping: true});

testCM("rtlMovement", function(cm) {
forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج", "خحcd", "1خحcd", "abcdeح1ج"], function(line) {
forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",
"خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!"], function(line) {
var inv = line.charAt(0) == "خ";
cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");
var cursor = byClassName(cm.getWrapperElement(), "CodeMirror-cursor")[0];
@@ -901,7 +921,7 @@ testCM("rtlMovement", function(cm) {
prevX = cursor.offsetLeft;
}
});
});
}, {rtlMoveVisually: true});

// Verify that updating a line clears its bidi ordering
testCM("bidiUpdate", function(cm) {
@@ -967,6 +987,22 @@ testCM("lineWidgets", function(cm) {
eqPos(cm.getCursor(), {line: 1, ch: 1});
});

testCM("lineWidgetFocus", function(cm) {
var place = document.getElementById("testground");
place.className = "offscreen";
try {
addDoc(cm, 500, 10);
var node = document.createElement("input");
var widget = cm.addLineWidget(1, node);
node.focus();
eq(document.activeElement, node);
cm.replaceRange("new stuff", {line: 1, ch: 0});
eq(document.activeElement, node);
} finally {
place.className = "";
}
});

testCM("getLineNumber", function(cm) {
addDoc(cm, 2, 20);
var h1 = cm.getLineHandle(1);

Large diffs are not rendered by default.