@@ -29,10 +32,11 @@
click Compress to download the minified script
file.
-
diff --git a/doc/manual.html b/doc/manual.html
index f47e437ede..77d1cc3404 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -63,7 +63,7 @@
User manual and reference guide
- version 4.1.0
+ version 4.2.0
CodeMirror is a code-editor component that can be embedded in
@@ -1228,6 +1228,14 @@
Cursor and selection methods
old one. When it starts with *, it will always
replace the previous event (if that had the same origin).
Built-in motion uses the "+move" origin.
+
bias: number
+
Determine the direction into which the selection endpoints
+ should be adjusted when they fall inside
+ an atomic range. Can be either -1
+ (backward) or 1 (forward). When not given, the bias will be
+ based on the relative position of the old selection—the editor
+ will try to move further away from that, to prevent getting
+ stuck.
A string that will be inserted after opening and before
- closing comment markers. Defaults to a single space.
+
A string that will be inserted after opening and leading
+ markers, and before closing comment markers. Defaults to a
+ single space.
commentBlankLines: boolean
Whether, when adding line comments, to also comment lines
that contain only whitespace.
@@ -2254,6 +2263,8 @@
Static properties
given, CodeMirror.fold.auto
will be used as default.
+ The foldOptions editor option can be set to an
+ object to provide an editor-wide default configuration.
Demo here.
Provides a framework for showing autocompletion hints.
- Defines CodeMirror.showHint, which takes a
- CodeMirror instance, a hinting function, and optionally an
+ Defines editor.showHint, which takes an optional
options object, and pops up a widget that allows the user to
- select a completion. Hinting functions are function that take an
- editor instance and an optional options object, and return
+ select a completion. Finding hints is done with a hinting
+ functions (the hint option), which is a function
+ that take an editor instance and options object, and return
a {list, from, to} object, where list
is an array of strings or objects (the completions),
and from and to give the start and end
of the token that is being completed as {line, ch}
objects.
If no hinting function is given, the addon will
- use CodeMirror.hint.auto, with
+ use CodeMirror.hint.auto, which
calls getHelpers with
the "hint" type to find applicable hinting
functions, and tries them one by one. If that fails, it looks
@@ -2334,9 +2345,8 @@
Static properties
completable words for the mode, and
uses CodeMirror.hint.fromList to complete from
those.
-
When completions
- aren't simple strings, they should be objects with the following
- properties:
+
When completions aren't simple strings, they should be
+ objects with the following properties:
text: string
The completion text. This is the only required
@@ -2363,11 +2373,13 @@
Static properties
will also be passed along to the hinting function, which may
understand additional options):
-
async: boolean
-
When set to true, the hinting function's signature should
- be (cm, callback, ?options), and the completion
- interface will only be popped up when the hinting function
- calls the callback, passing it the object holding the
+
hint: function
+
A hinting function, as specified above. It is possible to
+ set the async property on a hinting function to
+ true, in which case it will be called with
+ arguments (cm, callback, ?options), and the
+ completion interface will only be popped up when the hinting
+ function calls the callback, passing it the object holding the
completions.
completeSingle: boolean
Determines whether, when only a single completion is
@@ -2555,12 +2567,13 @@
Adds a rulers option, which can be used to show
one or more vertical rulers in the editor. The option, if
- defined, should be given an array of {column,
- className} objects or numbers. The ruler will be
- displayed at the column indicated by the number or
- the column property. The className
- property can be used to assign a custom style to a
- ruler. Demo here.
+ defined, should be given an array of {column [, className,
+ color, lineStyle, width]} objects or numbers (wich
+ indicate a column). The ruler will be displayed at the column
+ indicated by the number or the column property.
+ The className property can be used to assign a
+ custom style to a ruler. Demo
+ here.
Addon to perform hard line wrapping/breaking for paragraphs
diff --git a/doc/realworld.html b/doc/realworld.html
index ceb1b8ca2c..d3e4c07f6a 100644
--- a/doc/realworld.html
+++ b/doc/realworld.html
@@ -27,7 +27,9 @@
]",
+ "[link ]",
+ "[tag&bracket <][tag div][tag&bracket >]",
+ "[tag&bracket ][tag div][tag&bracket >]");
+
})();
diff --git a/mode/meta.js b/mode/meta.js
index b8bfebda2e..281028d7ab 100644
--- a/mode/meta.js
+++ b/mode/meta.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../lib/codemirror"));
@@ -20,6 +23,7 @@ CodeMirror.modeInfo = [
{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: 'Cypher', mime: 'application/x-cypher-query', mode: 'cypher'},
{name: 'CSS', mime: 'text/css', mode: 'css'},
{name: 'D', mime: 'text/x-d', mode: 'd'},
{name: 'diff', mime: 'text/x-diff', mode: 'diff'},
diff --git a/mode/mirc/mirc.js b/mode/mirc/mirc.js
index 6b2a23a16c..f0d5c6ad50 100644
--- a/mode/mirc/mirc.js
+++ b/mode/mirc/mirc.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
//mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara
(function(mod) {
diff --git a/mode/mllike/mllike.js b/mode/mllike/mllike.js
index d4d59fceb7..04ab1c98ec 100644
--- a/mode/mllike/mllike.js
+++ b/mode/mllike/mllike.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/nginx/nginx.js b/mode/nginx/nginx.js
index 4e17cdb3c4..135b9cc7f8 100644
--- a/mode/nginx/nginx.js
+++ b/mode/nginx/nginx.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/ntriples/ntriples.js b/mode/ntriples/ntriples.js
index cd5eb24f07..0524b1e8ab 100644
--- a/mode/ntriples/ntriples.js
+++ b/mode/ntriples/ntriples.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/**********************************************************
* This script provides syntax highlighting support for
* the Ntriples format.
diff --git a/mode/octave/octave.js b/mode/octave/octave.js
index 16fe4dfd78..94314c4822 100644
--- a/mode/octave/octave.js
+++ b/mode/octave/octave.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/pascal/pascal.js b/mode/pascal/pascal.js
index 642dd9bf79..2d0c3d4240 100644
--- a/mode/pascal/pascal.js
+++ b/mode/pascal/pascal.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/pegjs/pegjs.js b/mode/pegjs/pegjs.js
index f74f2a4f22..306e3768c9 100644
--- a/mode/pegjs/pegjs.js
+++ b/mode/pegjs/pegjs.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../javascript/javascript"));
diff --git a/mode/perl/perl.js b/mode/perl/perl.js
index 84392e4a81..ab86e846a4 100644
--- a/mode/perl/perl.js
+++ b/mode/perl/perl.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// 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)
@@ -788,6 +791,8 @@ CodeMirror.defineMode("perl",function(){
return (state.tokenize||tokenPerl)(stream,state);},
electricChars:"{}"};});
+CodeMirror.registerHelper("wordChars", "perl", /[\\w$]/);
+
CodeMirror.defineMIME("text/x-perl", "perl");
// it's like "peek", but need for look-ahead or look-behind if index < 0
diff --git a/mode/php/php.js b/mode/php/php.js
index db3672d88f..72c19d8d11 100644
--- a/mode/php/php.js
+++ b/mode/php/php.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike"));
@@ -94,6 +97,7 @@
var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";
var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once";
CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" "));
+ CodeMirror.registerHelper("wordChars", "php", /[\\w$]/);
var phpConfig = {
name: "clike",
@@ -183,8 +187,7 @@
state.curState = state.html;
return "meta";
} else {
- var result = phpMode.token(stream, state.curState);
- return (stream.pos <= stream.start) ? phpMode.token(stream, state.curState) : result;
+ return phpMode.token(stream, state.curState);
}
}
diff --git a/mode/php/test.js b/mode/php/test.js
index db68d75de3..8305496571 100644
--- a/mode/php/test.js
+++ b/mode/php/test.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "php");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
diff --git a/mode/pig/pig.js b/mode/pig/pig.js
index 64ac506a79..c74b2cc866 100644
--- a/mode/pig/pig.js
+++ b/mode/pig/pig.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/*
* Pig Latin Mode for CodeMirror 2
* @author Prasanth Jayachandran
diff --git a/mode/properties/properties.js b/mode/properties/properties.js
index 6dfe06f128..0740084209 100644
--- a/mode/properties/properties.js
+++ b/mode/properties/properties.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/puppet/puppet.js b/mode/puppet/puppet.js
index da8823e5ed..66698bb6ad 100644
--- a/mode/puppet/puppet.js
+++ b/mode/puppet/puppet.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/python/python.js b/mode/python/python.js
index f5530bcfdb..3a86c278a1 100644
--- a/mode/python/python.js
+++ b/mode/python/python.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
@@ -6,383 +9,336 @@
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
-"use strict";
-
-
-CodeMirror.defineMode("python", function(conf, parserConf) {
- var ERRORCLASS = 'error';
-
- function wordRegexp(words) {
- return new RegExp("^((" + words.join(")|(") + "))\\b");
- }
+ "use strict";
+
+ function wordRegexp(words) {
+ return new RegExp("^((" + words.join(")|(") + "))\\b");
+ }
+
+ var wordOperators = wordRegexp(["and", "or", "not", "is", "in"]);
+ var commonKeywords = ["as", "assert", "break", "class", "continue",
+ "def", "del", "elif", "else", "except", "finally",
+ "for", "from", "global", "if", "import",
+ "lambda", "pass", "raise", "return",
+ "try", "while", "with", "yield"];
+ var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
+ "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
+ "enumerate", "eval", "filter", "float", "format", "frozenset",
+ "getattr", "globals", "hasattr", "hash", "help", "hex", "id",
+ "input", "int", "isinstance", "issubclass", "iter", "len",
+ "list", "locals", "map", "max", "memoryview", "min", "next",
+ "object", "oct", "open", "ord", "pow", "property", "range",
+ "repr", "reversed", "round", "set", "setattr", "slice",
+ "sorted", "staticmethod", "str", "sum", "super", "tuple",
+ "type", "vars", "zip", "__import__", "NotImplemented",
+ "Ellipsis", "__debug__"];
+ var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
+ "file", "intern", "long", "raw_input", "reduce", "reload",
+ "unichr", "unicode", "xrange", "False", "True", "None"],
+ keywords: ["exec", "print"]};
+ var py3 = {builtins: ["ascii", "bytes", "exec", "print"],
+ keywords: ["nonlocal", "False", "True", "None"]};
+
+ CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));
+
+ function top(state) {
+ return state.scopes[state.scopes.length - 1];
+ }
+
+ CodeMirror.defineMode("python", function(conf, parserConf) {
+ var ERRORCLASS = "error";
var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
- var singleDelimiters = parserConf.singleDelimiters || new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
+ var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]");
var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
- var hangingIndent = parserConf.hangingIndent || parserConf.indentUnit;
-
- var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);
- var commonkeywords = ['as', 'assert', 'break', 'class', 'continue',
- 'def', 'del', 'elif', 'else', 'except', 'finally',
- 'for', 'from', 'global', 'if', 'import',
- 'lambda', 'pass', 'raise', 'return',
- 'try', 'while', 'with', 'yield'];
- var commonBuiltins = ['abs', 'all', 'any', 'bin', 'bool', 'bytearray', 'callable', 'chr',
- 'classmethod', 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod',
- 'enumerate', 'eval', 'filter', 'float', 'format', 'frozenset',
- 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id',
- 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len',
- 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next',
- 'object', 'oct', 'open', 'ord', 'pow', 'property', 'range',
- 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
- 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple',
- 'type', 'vars', 'zip', '__import__', 'NotImplemented',
- 'Ellipsis', '__debug__'];
- var py2 = {'builtins': ['apply', 'basestring', 'buffer', 'cmp', 'coerce', 'execfile',
- 'file', 'intern', 'long', 'raw_input', 'reduce', 'reload',
- 'unichr', 'unicode', 'xrange', 'False', 'True', 'None'],
- 'keywords': ['exec', 'print']};
- var py3 = {'builtins': ['ascii', 'bytes', 'exec', 'print'],
- 'keywords': ['nonlocal', 'False', 'True', 'None']};
+ var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
+ var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
if(parserConf.extra_keywords != undefined){
- commonkeywords = commonkeywords.concat(parserConf.extra_keywords);
+ myKeywords = myKeywords.concat(parserConf.extra_keywords);
}
if(parserConf.extra_builtins != undefined){
- commonBuiltins = commonBuiltins.concat(parserConf.extra_builtins);
+ myBuiltins = myBuiltins.concat(parserConf.extra_builtins);
}
- if (!!parserConf.version && parseInt(parserConf.version, 10) === 3) {
- commonkeywords = commonkeywords.concat(py3.keywords);
- commonBuiltins = commonBuiltins.concat(py3.builtins);
- var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
+ if (parserConf.version && parseInt(parserConf.version, 10) == 3) {
+ myKeywords = myKeywords.concat(py3.keywords);
+ myBuiltins = myBuiltins.concat(py3.builtins);
+ var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
} else {
- commonkeywords = commonkeywords.concat(py2.keywords);
- commonBuiltins = commonBuiltins.concat(py2.builtins);
- var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
+ myKeywords = myKeywords.concat(py2.keywords);
+ myBuiltins = myBuiltins.concat(py2.builtins);
+ var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
}
- var keywords = wordRegexp(commonkeywords);
- var builtins = wordRegexp(commonBuiltins);
-
- var indentInfo = null;
+ var keywords = wordRegexp(myKeywords);
+ var builtins = wordRegexp(myBuiltins);
// tokenizers
function tokenBase(stream, state) {
- // Handle scope changes
- if (stream.sol()) {
- var scopeOffset = state.scopes[0].offset;
- if (stream.eatSpace()) {
- var lineOffset = stream.indentation();
- if (lineOffset > scopeOffset) {
- indentInfo = 'indent';
- } else if (lineOffset < scopeOffset) {
- indentInfo = 'dedent';
- }
- return null;
- } else {
- if (scopeOffset > 0) {
- dedent(stream, state);
- }
- }
- }
+ // Handle scope changes
+ if (stream.sol() && top(state).type == "py") {
+ var scopeOffset = top(state).offset;
if (stream.eatSpace()) {
- return null;
+ var lineOffset = stream.indentation();
+ if (lineOffset > scopeOffset)
+ pushScope(stream, state, "py");
+ else if (lineOffset < scopeOffset && dedent(stream, state))
+ state.errorToken = true;
+ return null;
+ } else {
+ var style = tokenBaseInner(stream, state);
+ if (scopeOffset > 0 && dedent(stream, state))
+ style += " " + ERRORCLASS;
+ return style;
}
+ }
+ return tokenBaseInner(stream, state);
+ }
- var ch = stream.peek();
-
- // Handle Comments
- if (ch === '#') {
- stream.skipToEnd();
- return 'comment';
+ function tokenBaseInner(stream, state) {
+ if (stream.eatSpace()) return null;
+
+ var ch = stream.peek();
+
+ // Handle Comments
+ if (ch == "#") {
+ stream.skipToEnd();
+ return "comment";
+ }
+
+ // Handle Number Literals
+ if (stream.match(/^[0-9\.]/, false)) {
+ var floatLiteral = false;
+ // Floats
+ if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; }
+ if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
+ if (stream.match(/^\.\d+/)) { floatLiteral = true; }
+ if (floatLiteral) {
+ // Float literals may be "imaginary"
+ stream.eat(/J/i);
+ return "number";
}
-
- // Handle Number Literals
- if (stream.match(/^[0-9\.]/, false)) {
- var floatLiteral = false;
- // Floats
- if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; }
- if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
- if (stream.match(/^\.\d+/)) { floatLiteral = true; }
- if (floatLiteral) {
- // Float literals may be "imaginary"
- stream.eat(/J/i);
- return 'number';
- }
- // Integers
- var intLiteral = false;
- // Hex
- if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; }
- // Binary
- if (stream.match(/^0b[01]+/i)) { intLiteral = true; }
- // Octal
- if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; }
- // Decimal
- if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
- // Decimal literals may be "imaginary"
- stream.eat(/J/i);
- // TODO - Can you have imaginary longs?
- intLiteral = true;
- }
- // Zero by itself with no other piece of number.
- if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
- if (intLiteral) {
- // Integer literals may be "long"
- stream.eat(/L/i);
- return 'number';
- }
+ // Integers
+ var intLiteral = false;
+ // Hex
+ if (stream.match(/^0x[0-9a-f]+/i)) intLiteral = true;
+ // Binary
+ if (stream.match(/^0b[01]+/i)) intLiteral = true;
+ // Octal
+ if (stream.match(/^0o[0-7]+/i)) intLiteral = true;
+ // Decimal
+ if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
+ // Decimal literals may be "imaginary"
+ stream.eat(/J/i);
+ // TODO - Can you have imaginary longs?
+ intLiteral = true;
}
-
- // Handle Strings
- if (stream.match(stringPrefixes)) {
- state.tokenize = tokenStringFactory(stream.current());
- return state.tokenize(stream, state);
+ // Zero by itself with no other piece of number.
+ if (stream.match(/^0(?![\dx])/i)) intLiteral = true;
+ if (intLiteral) {
+ // Integer literals may be "long"
+ stream.eat(/L/i);
+ return "number";
}
+ }
- // Handle operators and Delimiters
- if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
- return null;
- }
- if (stream.match(doubleOperators)
- || stream.match(singleOperators)
- || stream.match(wordOperators)) {
- return 'operator';
- }
- if (stream.match(singleDelimiters)) {
- return null;
- }
+ // Handle Strings
+ if (stream.match(stringPrefixes)) {
+ state.tokenize = tokenStringFactory(stream.current());
+ return state.tokenize(stream, state);
+ }
- if (stream.match(keywords)) {
- return 'keyword';
- }
+ // Handle operators and Delimiters
+ if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))
+ return null;
- if (stream.match(builtins)) {
- return 'builtin';
- }
+ if (stream.match(doubleOperators)
+ || stream.match(singleOperators)
+ || stream.match(wordOperators))
+ return "operator";
- if (stream.match(/^(self|cls)\b/)) {
- return "variable-2";
- }
+ if (stream.match(singleDelimiters))
+ return null;
- if (stream.match(identifiers)) {
- if (state.lastToken == 'def' || state.lastToken == 'class') {
- return 'def';
- }
- return 'variable';
- }
+ if (stream.match(keywords))
+ return "keyword";
+
+ if (stream.match(builtins))
+ return "builtin";
+
+ if (stream.match(/^(self|cls)\b/))
+ return "variable-2";
- // Handle non-detected items
- stream.next();
- return ERRORCLASS;
+ if (stream.match(identifiers)) {
+ if (state.lastToken == "def" || state.lastToken == "class")
+ return "def";
+ return "variable";
+ }
+
+ // Handle non-detected items
+ stream.next();
+ return ERRORCLASS;
}
function tokenStringFactory(delimiter) {
- while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
- delimiter = delimiter.substr(1);
- }
- var singleline = delimiter.length == 1;
- var OUTCLASS = 'string';
-
- function tokenString(stream, state) {
- while (!stream.eol()) {
- stream.eatWhile(/[^'"\\]/);
- if (stream.eat('\\')) {
- stream.next();
- if (singleline && stream.eol()) {
- return OUTCLASS;
- }
- } else if (stream.match(delimiter)) {
- state.tokenize = tokenBase;
- return OUTCLASS;
- } else {
- stream.eat(/['"]/);
- }
- }
- if (singleline) {
- if (parserConf.singleLineStringErrors) {
- return ERRORCLASS;
- } else {
- state.tokenize = tokenBase;
- }
- }
+ while ("rub".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
+ delimiter = delimiter.substr(1);
+
+ var singleline = delimiter.length == 1;
+ var OUTCLASS = "string";
+
+ function tokenString(stream, state) {
+ while (!stream.eol()) {
+ stream.eatWhile(/[^'"\\]/);
+ if (stream.eat("\\")) {
+ stream.next();
+ if (singleline && stream.eol())
+ return OUTCLASS;
+ } else if (stream.match(delimiter)) {
+ state.tokenize = tokenBase;
return OUTCLASS;
+ } else {
+ stream.eat(/['"]/);
+ }
}
- tokenString.isString = true;
- return tokenString;
+ if (singleline) {
+ if (parserConf.singleLineStringErrors)
+ return ERRORCLASS;
+ else
+ state.tokenize = tokenBase;
+ }
+ return OUTCLASS;
+ }
+ tokenString.isString = true;
+ return tokenString;
}
- function indent(stream, state, type) {
- type = type || 'py';
- var indentUnit = 0;
- if (type === 'py') {
- if (state.scopes[0].type !== 'py') {
- state.scopes[0].offset = stream.indentation();
- return;
- }
- for (var i = 0; i < state.scopes.length; ++i) {
- if (state.scopes[i].type === 'py') {
- indentUnit = state.scopes[i].offset + conf.indentUnit;
- break;
- }
- }
- } else if (stream.match(/\s*($|#)/, false)) {
- // An open paren/bracket/brace with only space or comments after it
- // on the line will indent the next line a fixed amount, to make it
- // easier to put arguments, list items, etc. on their own lines.
- indentUnit = stream.indentation() + hangingIndent;
- } else {
- indentUnit = stream.column() + stream.current().length;
- }
- state.scopes.unshift({
- offset: indentUnit,
- type: type
- });
+ function pushScope(stream, state, type) {
+ var offset = 0, align = null;
+ if (type == "py") {
+ while (top(state).type != "py")
+ state.scopes.pop();
+ }
+ offset = top(state).offset + (type == "py" ? conf.indentUnit : hangingIndent);
+ if (type != "py" && !stream.match(/^(\s|#.*)*$/, false))
+ align = stream.column() + 1;
+ state.scopes.push({offset: offset, type: type, align: align});
}
- function dedent(stream, state, type) {
- type = type || 'py';
- if (state.scopes.length == 1) return;
- if (state.scopes[0].type === 'py') {
- var _indent = stream.indentation();
- var _indent_index = -1;
- for (var i = 0; i < state.scopes.length; ++i) {
- if (_indent === state.scopes[i].offset) {
- _indent_index = i;
- break;
- }
- }
- if (_indent_index === -1) {
- return true;
- }
- while (state.scopes[0].offset !== _indent) {
- state.scopes.shift();
- }
- return false;
- } else {
- if (type === 'py') {
- state.scopes[0].offset = stream.indentation();
- return false;
- } else {
- if (state.scopes[0].type != type) {
- return true;
- }
- state.scopes.shift();
- return false;
- }
- }
+ function dedent(stream, state) {
+ var indented = stream.indentation();
+ while (top(state).offset > indented) {
+ if (top(state).type != "py") return true;
+ state.scopes.pop();
+ }
+ return top(state).offset != indented;
}
function tokenLexer(stream, state) {
- indentInfo = null;
- var style = state.tokenize(stream, state);
- var current = stream.current();
-
- // Handle '.' connected identifiers
- if (current === '.') {
- style = stream.match(identifiers, false) ? null : ERRORCLASS;
- if (style === null && state.lastStyle === 'meta') {
- // Apply 'meta' style to '.' connected identifiers when
- // appropriate.
- style = 'meta';
- }
- return style;
- }
-
- // Handle decorators
- if (current === '@') {
- return stream.match(identifiers, false) ? 'meta' : ERRORCLASS;
+ var style = state.tokenize(stream, state);
+ var current = stream.current();
+
+ // Handle '.' connected identifiers
+ if (current == ".") {
+ style = stream.match(identifiers, false) ? null : ERRORCLASS;
+ if (style == null && state.lastStyle == "meta") {
+ // Apply 'meta' style to '.' connected identifiers when
+ // appropriate.
+ style = "meta";
}
-
- if ((style === 'variable' || style === 'builtin')
- && state.lastStyle === 'meta') {
- style = 'meta';
- }
-
- // Handle scope changes.
- if (current === 'pass' || current === 'return') {
- state.dedent += 1;
- }
- if (current === 'lambda') state.lambda = true;
- if ((current === ':' && !state.lambda && state.scopes[0].type == 'py')
- || indentInfo === 'indent') {
- indent(stream, state);
- }
- var delimiter_index = '[({'.indexOf(current);
- if (delimiter_index !== -1) {
- indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
- }
- if (indentInfo === 'dedent') {
- if (dedent(stream, state)) {
- return ERRORCLASS;
- }
- }
- delimiter_index = '])}'.indexOf(current);
- if (delimiter_index !== -1) {
- if (dedent(stream, state, current)) {
- return ERRORCLASS;
- }
- }
- if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'py') {
- if (state.scopes.length > 1) state.scopes.shift();
- state.dedent -= 1;
- }
-
return style;
+ }
+
+ // Handle decorators
+ if (current == "@")
+ return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
+
+ if ((style == "variable" || style == "builtin")
+ && state.lastStyle == "meta")
+ style = "meta";
+
+ // Handle scope changes.
+ if (current == "pass" || current == "return")
+ state.dedent += 1;
+
+ if (current == "lambda") state.lambda = true;
+ if (current == ":" && !state.lambda && top(state).type == "py")
+ pushScope(stream, state, "py");
+
+ var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;
+ if (delimiter_index != -1)
+ pushScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
+
+ delimiter_index = "])}".indexOf(current);
+ if (delimiter_index != -1) {
+ if (top(state).type == current) state.scopes.pop();
+ else return ERRORCLASS;
+ }
+ if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
+ if (state.scopes.length > 1) state.scopes.pop();
+ state.dedent -= 1;
+ }
+
+ return style;
}
var external = {
- startState: function(basecolumn) {
- return {
- tokenize: tokenBase,
- scopes: [{offset:basecolumn || 0, type:'py'}],
- lastStyle: null,
- lastToken: null,
- lambda: false,
- dedent: 0
- };
- },
-
- token: function(stream, state) {
- var style = tokenLexer(stream, state);
-
- state.lastStyle = style;
-
- var current = stream.current();
- if (current && style) {
- state.lastToken = current;
- }
-
- if (stream.eol() && state.lambda) {
- state.lambda = false;
- }
- return style;
- },
-
- indent: function(state) {
- if (state.tokenize != tokenBase) {
- return state.tokenize.isString ? CodeMirror.Pass : 0;
- }
-
- return state.scopes[0].offset;
- },
-
- lineComment: "#",
- fold: "indent"
+ startState: function(basecolumn) {
+ return {
+ tokenize: tokenBase,
+ scopes: [{offset: basecolumn || 0, type: "py", align: null}],
+ lastStyle: null,
+ lastToken: null,
+ lambda: false,
+ dedent: 0
+ };
+ },
+
+ token: function(stream, state) {
+ var addErr = state.errorToken;
+ if (addErr) state.errorToken = false;
+ var style = tokenLexer(stream, state);
+
+ state.lastStyle = style;
+
+ var current = stream.current();
+ if (current && style)
+ state.lastToken = current;
+
+ if (stream.eol() && state.lambda)
+ state.lambda = false;
+ return addErr ? style + " " + ERRORCLASS : style;
+ },
+
+ indent: function(state, textAfter) {
+ if (state.tokenize != tokenBase)
+ return state.tokenize.isString ? CodeMirror.Pass : 0;
+
+ var scope = top(state);
+ var closing = textAfter && textAfter.charAt(0) == scope.type;
+ if (scope.align != null)
+ return scope.align - (closing ? 1 : 0);
+ else
+ return scope.offset - (closing ? conf.indentUnit : 0);
+ },
+
+ lineComment: "#",
+ fold: "indent"
};
return external;
-});
+ });
-CodeMirror.defineMIME("text/x-python", "python");
+ CodeMirror.defineMIME("text/x-python", "python");
-var words = function(str){return str.split(' ');};
+ var words = function(str) { return str.split(" "); };
-CodeMirror.defineMIME("text/x-cython", {
- name: "python",
- extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+
- "extern gil include nogil property public"+
- "readonly struct union DEF IF ELIF ELSE")
-});
+ CodeMirror.defineMIME("text/x-cython", {
+ name: "python",
+ extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+
+ "extern gil include nogil property public"+
+ "readonly struct union DEF IF ELIF ELSE")
+ });
});
diff --git a/mode/q/q.js b/mode/q/q.js
index d6e3b66610..a4af9383e7 100644
--- a/mode/q/q.js
+++ b/mode/q/q.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/r/r.js b/mode/r/r.js
index 281d7fa40f..1ab4a9565a 100644
--- a/mode/r/r.js
+++ b/mode/r/r.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/rpm/rpm.js b/mode/rpm/rpm.js
index 497997c4ff..3bb7cd2f62 100644
--- a/mode/rpm/rpm.js
+++ b/mode/rpm/rpm.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/rst/rst.js b/mode/rst/rst.js
index 0763d4b999..2a1e28b556 100644
--- a/mode/rst/rst.js
+++ b/mode/rst/rst.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay"));
diff --git a/mode/ruby/ruby.js b/mode/ruby/ruby.js
index 4ef08b1552..b68ee2912a 100644
--- a/mode/ruby/ruby.js
+++ b/mode/ruby/ruby.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/ruby/test.js b/mode/ruby/test.js
index c97d106686..cade864ff9 100644
--- a/mode/ruby/test.js
+++ b/mode/ruby/test.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "ruby");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
diff --git a/mode/rust/rust.js b/mode/rust/rust.js
index 2e6e20b231..4ca1a76af6 100644
--- a/mode/rust/rust.js
+++ b/mode/rust/rust.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/sass/sass.js b/mode/sass/sass.js
index 74ae91db12..2ff5003c0a 100644
--- a/mode/sass/sass.js
+++ b/mode/sass/sass.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/scheme/scheme.js b/mode/scheme/scheme.js
index 7124f7283b..979edc0963 100644
--- a/mode/scheme/scheme.js
+++ b/mode/scheme/scheme.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/**
* Author: Koh Zi Han, based on implementation by Koh Zi Chun
*/
diff --git a/mode/shell/shell.js b/mode/shell/shell.js
index 7753411c98..77be75b97d 100644
--- a/mode/shell/shell.js
+++ b/mode/shell/shell.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
@@ -33,10 +36,15 @@ CodeMirror.defineMode('shell', function() {
'touch vi vim wall wc wget who write yes zsh');
function tokenBase(stream, state) {
+ if (stream.eatSpace()) return null;
var sol = stream.sol();
var ch = stream.next();
+ if (ch === '\\') {
+ stream.next();
+ return null;
+ }
if (ch === '\'' || ch === '"' || ch === '`') {
state.tokens.unshift(tokenString(ch));
return tokenize(stream, state);
@@ -63,7 +71,7 @@ CodeMirror.defineMode('shell', function() {
}
if (/\d/.test(ch)) {
stream.eatWhile(/\d/);
- if(!/\w/.test(stream.peek())) {
+ if(stream.eol() || !/\w/.test(stream.peek())) {
return 'number';
}
}
@@ -119,7 +127,6 @@ CodeMirror.defineMode('shell', function() {
return {
startState: function() {return {tokens:[]};},
token: function(stream, state) {
- if (stream.eatSpace()) return null;
return tokenize(stream, state);
}
};
diff --git a/mode/shell/test.js b/mode/shell/test.js
new file mode 100644
index 0000000000..a413b5a406
--- /dev/null
+++ b/mode/shell/test.js
@@ -0,0 +1,58 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
+(function() {
+ var mode = CodeMirror.getMode({}, "shell");
+ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
+
+ MT("var",
+ "text [def $var] text");
+ MT("varBraces",
+ "text[def ${var}]text");
+ MT("varVar",
+ "text [def $a$b] text");
+ MT("varBracesVarBraces",
+ "text[def ${a}${b}]text");
+
+ MT("singleQuotedVar",
+ "[string 'text $var text']");
+ MT("singleQuotedVarBraces",
+ "[string 'text ${var} text']");
+
+ MT("doubleQuotedVar",
+ '[string "text ][def $var][string text"]');
+ MT("doubleQuotedVarBraces",
+ '[string "text][def ${var}][string text"]');
+ MT("doubleQuotedVarPunct",
+ '[string "text ][def $@][string text"]');
+ MT("doubleQuotedVarVar",
+ '[string "][def $a$b][string "]');
+ MT("doubleQuotedVarBracesVarBraces",
+ '[string "][def ${a}${b}][string "]');
+
+ MT("notAString",
+ "text\\'text");
+ MT("escapes",
+ "outside\\'\\\"\\`\\\\[string \"inside\\`\\'\\\"\\\\`\\$notAVar\"]outside\\$\\(notASubShell\\)");
+
+ MT("subshell",
+ "[builtin echo] [quote $(whoami)] s log, stardate [quote `date`].");
+ MT("doubleQuotedSubshell",
+ "[builtin echo] [string \"][quote $(whoami)][string 's log, stardate `date`.\"]");
+
+ MT("hashbang",
+ "[meta #!/bin/bash]");
+ MT("comment",
+ "text [comment # Blurb]");
+
+ MT("numbers",
+ "[number 0] [number 1] [number 2]");
+ MT("keywords",
+ "[keyword while] [atom true]; [keyword do]",
+ " [builtin sleep] [number 3]",
+ "[keyword done]");
+ MT("options",
+ "[builtin ls] [attribute -l] [attribute --human-readable]");
+ MT("operator",
+ "[def var][operator =]value");
+})();
diff --git a/mode/sieve/sieve.js b/mode/sieve/sieve.js
index 8256dda0a4..f67db2f553 100644
--- a/mode/sieve/sieve.js
+++ b/mode/sieve/sieve.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/smalltalk/smalltalk.js b/mode/smalltalk/smalltalk.js
index deb78a4f7a..50f41cc615 100644
--- a/mode/smalltalk/smalltalk.js
+++ b/mode/smalltalk/smalltalk.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/smarty/smarty.js b/mode/smarty/smarty.js
index 2a78c6d394..bb053245d3 100644
--- a/mode/smarty/smarty.js
+++ b/mode/smarty/smarty.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/**
* Smarty 2 and 3 mode.
*/
diff --git a/mode/smartymixed/smartymixed.js b/mode/smartymixed/smartymixed.js
index 7e5e12c0ec..31cfd2bdae 100644
--- a/mode/smartymixed/smartymixed.js
+++ b/mode/smartymixed/smartymixed.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/**
* @file smartymixed.js
* @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML)
diff --git a/mode/solr/solr.js b/mode/solr/solr.js
index 25d928ec1b..f7f7087891 100644
--- a/mode/solr/solr.js
+++ b/mode/solr/solr.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/sparql/sparql.js b/mode/sparql/sparql.js
index f228b1dffe..64dbb612c2 100644
--- a/mode/sparql/sparql.js
+++ b/mode/sparql/sparql.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/sql/sql.js b/mode/sql/sql.js
index 417db06282..6c02f4e947 100644
--- a/mode/sql/sql.js
+++ b/mode/sql/sql.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/stex/stex.js b/mode/stex/stex.js
index 59a395a0fe..09a33e56da 100644
--- a/mode/stex/stex.js
+++ b/mode/stex/stex.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/*
* Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
* Licence: MIT
diff --git a/mode/stex/test.js b/mode/stex/test.js
index ab629e81ea..22f027ec7b 100644
--- a/mode/stex/test.js
+++ b/mode/stex/test.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "stex");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
diff --git a/mode/tcl/tcl.js b/mode/tcl/tcl.js
index 4c29ee7d98..7be7b9b148 100644
--- a/mode/tcl/tcl.js
+++ b/mode/tcl/tcl.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
//tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara
(function(mod) {
diff --git a/mode/tiddlywiki/tiddlywiki.js b/mode/tiddlywiki/tiddlywiki.js
index ecd1d173c0..88c9768a72 100644
--- a/mode/tiddlywiki/tiddlywiki.js
+++ b/mode/tiddlywiki/tiddlywiki.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/***
|''Name''|tiddlywiki.js|
|''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
diff --git a/mode/tiki/tiki.js b/mode/tiki/tiki.js
index eb9a893fde..c90aac9ec7 100644
--- a/mode/tiki/tiki.js
+++ b/mode/tiki/tiki.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/toml/toml.js b/mode/toml/toml.js
index 2c722b3752..baeca15568 100644
--- a/mode/toml/toml.js
+++ b/mode/toml/toml.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/turtle/turtle.js b/mode/turtle/turtle.js
index de9fc2b6c7..a4727ed572 100644
--- a/mode/turtle/turtle.js
+++ b/mode/turtle/turtle.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/vb/vb.js b/mode/vb/vb.js
index 4fd80210fb..902203e0c0 100644
--- a/mode/vb/vb.js
+++ b/mode/vb/vb.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/vbscript/vbscript.js b/mode/vbscript/vbscript.js
index 4be7c7f2bb..bff2594477 100644
--- a/mode/vbscript/vbscript.js
+++ b/mode/vbscript/vbscript.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/*
For extra ASP classic objects, initialize CodeMirror instance with this option:
isASP: true
diff --git a/mode/velocity/velocity.js b/mode/velocity/velocity.js
index b64636bb43..8fc4f95d05 100644
--- a/mode/velocity/velocity.js
+++ b/mode/velocity/velocity.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/verilog/test.js b/mode/verilog/test.js
index 6f5770b848..e78860deb9 100644
--- a/mode/verilog/test.js
+++ b/mode/verilog/test.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function() {
var mode = CodeMirror.getMode({indentUnit: 4}, "verilog");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
diff --git a/mode/verilog/verilog.js b/mode/verilog/verilog.js
index d52ecea2a3..3414ec022e 100644
--- a/mode/verilog/verilog.js
+++ b/mode/verilog/verilog.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/xml/test.js b/mode/xml/test.js
index 1b9d9d1760..f48156b517 100644
--- a/mode/xml/test.js
+++ b/mode/xml/test.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml";
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); }
diff --git a/mode/xml/xml.js b/mode/xml/xml.js
index 3248c454d1..786507d2e4 100644
--- a/mode/xml/xml.js
+++ b/mode/xml/xml.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
@@ -121,7 +124,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
- return next ? next + " error" : "error";
+ return next ? next + " tag error" : "tag error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();
diff --git a/mode/xquery/test.js b/mode/xquery/test.js
index 41719dd169..1f148cdbbd 100644
--- a/mode/xquery/test.js
+++ b/mode/xquery/test.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// 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
diff --git a/mode/xquery/xquery.js b/mode/xquery/xquery.js
index 2c7faf425a..c8f3d90a9f 100644
--- a/mode/xquery/xquery.js
+++ b/mode/xquery/xquery.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/yaml/yaml.js b/mode/yaml/yaml.js
index f7b3a90c03..4ebe5c81cf 100644
--- a/mode/yaml/yaml.js
+++ b/mode/yaml/yaml.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/mode/z80/z80.js b/mode/z80/z80.js
index c778803072..ec41d050ac 100644
--- a/mode/z80/z80.js
+++ b/mode/z80/z80.js
@@ -1,3 +1,6 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
diff --git a/package.json b/package.json
index 26d7053629..ef4968b9b7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "codemirror",
- "version":"4.1.0",
+ "version":"4.2.0",
"main": "lib/codemirror.js",
"description": "In-browser code editing made bearable",
"licenses": [{"type": "MIT",
diff --git a/test/emacs_test.js b/test/emacs_test.js
index f21605bb37..c49e480375 100644
--- a/test/emacs_test.js
+++ b/test/emacs_test.js
@@ -108,10 +108,10 @@
sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\n bar"))
- sim("transposeChar", "abcd\n\ne",
- "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\n\ne"), at(0, 3),
- "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\n\ne"), at(0, 4),
- "Ctrl-F", "Ctrl-T", txt("bcd\na\ne"), at(1, 1));
+ sim("transposeChar", "abcd\ne",
+ "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\ne"), at(0, 3),
+ "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\ne"), at(0, 4),
+ "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 0));
sim("manipWordCase", "foo BAR bAZ",
"Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"),
diff --git a/test/index.html b/test/index.html
index 752971fe48..9930301eb5 100644
--- a/test/index.html
+++ b/test/index.html
@@ -96,6 +96,8 @@
+
+
diff --git a/test/lint/lint.js b/test/lint/lint.js
index a65deb60be..ef4c13bd9a 100644
--- a/test/lint/lint.js
+++ b/test/lint/lint.js
@@ -31,6 +31,8 @@ var scopePasser = walk.make({
ScopeBody: function(node, prev, c) { c(node, node.scope); }
});
+var cBlob = /^\/\/ CodeMirror, copyright \(c\) by Marijn Haverbeke and others\n\/\/ Distributed under an MIT license: http:\/\/codemirror.net\/LICENSE\n\n/;
+
function checkFile(fileName) {
var file = fs.readFileSync(fileName, "utf8"), notAllowed;
if (notAllowed = file.match(/[\x00-\x08\x0b\x0c\x0e-\x19\uFEFF\t]|[ \t]\n/)) {
@@ -41,6 +43,9 @@ function checkFile(fileName) {
var info = acorn.getLineInfo(file, notAllowed.index);
fail(msg + " at line " + info.line + ", column " + info.column, {source: fileName});
}
+
+ if (!cBlob.test(file))
+ fail("Missing license blob", {source: fileName});
var globalsSeen = Object.create(null);
@@ -152,7 +157,7 @@ function checkDir(dir) {
fs.readdirSync(dir).forEach(function(file) {
var fname = dir + "/" + file;
if (/\.js$/.test(file)) checkFile(fname);
- else if (file != "dep" && fs.lstatSync(fname).isDirectory()) checkDir(fname);
+ else if (fs.lstatSync(fname).isDirectory()) checkDir(fname);
});
}
diff --git a/test/mode_test.css b/test/mode_test.css
index 1ac66737fb..f83271b4e2 100644
--- a/test/mode_test.css
+++ b/test/mode_test.css
@@ -8,3 +8,16 @@
.mt-output .mt-style {
font-size: x-small;
}
+
+.mt-output .mt-state {
+ font-size: x-small;
+ vertical-align: top;
+}
+
+.mt-output .mt-state-row {
+ display: none;
+}
+
+.mt-state-unhide .mt-output .mt-state-row {
+ display: table-row;
+}
diff --git a/test/mode_test.js b/test/mode_test.js
index dc20a0523e..2e16eba0ee 100644
--- a/test/mode_test.js
+++ b/test/mode_test.js
@@ -52,7 +52,7 @@
pos = end;
}
text = text.replace(/\[\[|\]\]/g, function(s) {return s.charAt(0);});
- tokens.push(style, text);
+ tokens.push({style: style, text: text});
plain += text;
}
}
@@ -67,16 +67,17 @@
};
function esc(str) {
- return str.replace('&', '&').replace('<', '<');
+ return str.replace('&', '&').replace('<', '<').replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
+;
}
function compare(text, expected, mode) {
var expectedOutput = [];
- for (var i = 0; i < expected.length; i += 2) {
- var sty = expected[i];
+ for (var i = 0; i < expected.length; ++i) {
+ var sty = expected[i].style;
if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' ');
- expectedOutput.push(sty, expected[i + 1]);
+ expectedOutput.push({style: sty, text: expected[i].text});
}
var observedOutput = highlight(text, mode);
@@ -89,7 +90,7 @@
s += '
';
s += 'expected:';
s += prettyPrintOutputTable(expectedOutput, diff);
- s += 'observed:';
+ s += 'observed: [display states]';
s += prettyPrintOutputTable(observedOutput, diff);
s += '
';
s += '
';
@@ -101,8 +102,21 @@
if (s) throw new Failure(s);
}
+ function stringify(obj) {
+ function replacer(key, obj) {
+ if (typeof obj == "function") {
+ var m = obj.toString().match(/function\s*[^\s(]*/);
+ return m ? m[0] : "function";
+ }
+ return obj;
+ }
+ if (window.JSON && JSON.stringify)
+ return JSON.stringify(obj, replacer, 2);
+ return "[unsupported]"; // Fail safely if no native JSON.
+ }
+
function highlight(string, mode) {
- var state = mode.startState()
+ var state = mode.startState();
var lines = string.replace(/\r\n/g,'\n').split('\n');
var st = [], pos = 0;
@@ -119,19 +133,21 @@
if (line == "" && mode.blankLine) mode.blankLine(state);
/* Start copied code from CodeMirror.highlight */
while (!stream.eol()) {
- var compare = mode.token(stream, state), substr = stream.current();
- if (stream.start >= stream.pos)
+ for (var j = 0; j < 10 && stream.start >= stream.pos; j++)
+ var compare = mode.token(stream, state);
+ if (j == 10)
throw new Failure("Failed to advance the stream." + stream.string + " " + stream.pos);
+ var substr = stream.current();
if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');
stream.start = stream.pos;
- if (pos && st[pos-2] == compare && !newLine) {
- st[pos-1] += substr;
+ if (pos && st[pos-1].style == compare && !newLine) {
+ st[pos-1].text += substr;
} else if (substr) {
- st[pos++] = compare; st[pos++] = substr;
+ st[pos++] = {style: compare, text: substr, state: stringify(state)};
}
// Give up when line is ridiculously long
if (stream.pos > 5000) {
- st[pos++] = null; st[pos++] = this.text.slice(stream.pos);
+ st[pos++] = {style: null, text: this.text.slice(stream.pos)};
break;
}
newLine = false;
@@ -144,27 +160,33 @@
function highlightOutputsDifferent(o1, o2) {
var minLen = Math.min(o1.length, o2.length);
for (var i = 0; i < minLen; ++i)
- if (o1[i] != o2[i]) return i >> 1;
+ if (o1[i].style != o2[i].style || o1[i].text != o2[i].text) return i;
if (o1.length > minLen || o2.length > minLen) return minLen;
}
function prettyPrintOutputTable(output, diffAt) {
var s = '
';
s += '
';
- for (var i = 0; i < output.length; i += 2) {
- var style = output[i], val = output[i+1];
+ for (var i = 0; i < output.length; ++i) {
+ var style = output[i].style, val = output[i].text;
s +=
'