codemirror-rails 2.22 → 2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. data/lib/codemirror/rails/version.rb +2 -2
  2. data/vendor/assets/javascripts/codemirror.js +164 -83
  3. data/vendor/assets/javascripts/codemirror/modes/clojure.js +13 -13
  4. data/vendor/assets/javascripts/codemirror/modes/css.js +1 -1
  5. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/modes/javascript.js +3 -3
  7. data/vendor/assets/javascripts/codemirror/modes/less.js +86 -57
  8. data/vendor/assets/javascripts/codemirror/modes/markdown.js +29 -60
  9. data/vendor/assets/javascripts/codemirror/modes/properties.js +17 -11
  10. data/vendor/assets/javascripts/codemirror/modes/smarty.js +148 -0
  11. data/vendor/assets/javascripts/codemirror/modes/stex.js +15 -2
  12. data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +41 -31
  13. data/vendor/assets/javascripts/codemirror/modes/vbscript.js +26 -0
  14. data/vendor/assets/javascripts/codemirror/modes/xml.js +2 -1
  15. data/vendor/assets/javascripts/codemirror/modes/xquery.js +448 -0
  16. data/vendor/assets/javascripts/codemirror/utils/closetag.js +174 -0
  17. data/vendor/assets/javascripts/codemirror/utils/foldcode.js +1 -1
  18. data/vendor/assets/javascripts/codemirror/utils/formatting.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +4 -2
  20. data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +6 -0
  21. data/vendor/assets/stylesheets/codemirror.css +2 -0
  22. data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +1 -1
  23. data/vendor/assets/stylesheets/codemirror/themes/eclipse.css +1 -1
  24. data/vendor/assets/stylesheets/codemirror/themes/elegant.css +2 -2
  25. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +45 -0
  26. data/vendor/assets/stylesheets/codemirror/themes/neat.css +3 -3
  27. data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +1 -1
  28. data/vendor/assets/stylesheets/codemirror/themes/xq-dark.css +46 -0
  29. metadata +10 -6
  30. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +0 -5
  31. data/vendor/assets/stylesheets/codemirror/modes/properties.css +0 -3
@@ -4,7 +4,7 @@
4
4
  */
5
5
  CodeMirror.defineMode("clojure", function (config, mode) {
6
6
  var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", TAG = "tag",
7
- ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD="keyword";
7
+ ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword";
8
8
  var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
9
9
 
10
10
  function makeKeywords(str) {
@@ -14,26 +14,25 @@ CodeMirror.defineMode("clojure", function (config, mode) {
14
14
  }
15
15
 
16
16
  var atoms = makeKeywords("true false nil");
17
-
17
+
18
18
  var keywords = makeKeywords(
19
- // Control structures
20
- "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle" +
19
+ "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
21
20
 
22
- // Built-ins
21
+ var builtins = makeKeywords(
23
22
  "* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq");
24
23
 
25
24
  var indentKeys = makeKeywords(
26
25
  // Built-ins
27
- "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch" +
26
+ "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch " +
28
27
 
29
28
  // Binding forms
30
- "let letfn binding loop for doseq dotimes when-let if-let" +
29
+ "let letfn binding loop for doseq dotimes when-let if-let " +
31
30
 
32
31
  // Data structures
33
- "defstruct struct-map assoc" +
32
+ "defstruct struct-map assoc " +
34
33
 
35
34
  // clojure.test
36
- "testing deftest" +
35
+ "testing deftest " +
37
36
 
38
37
  // contrib
39
38
  "handler-case handle dotrace deftrace");
@@ -154,12 +153,11 @@ CodeMirror.defineMode("clojure", function (config, mode) {
154
153
  (;something else, bracket, etc.
155
154
  */
156
155
 
157
- while ((letter = stream.eat(tests.keyword_char)) != null) {
156
+ if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) {
158
157
  keyWord += letter;
159
158
  }
160
159
 
161
160
  if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
162
-
163
161
  pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
164
162
  } else { // non-indent word
165
163
  // we continue eating the spaces
@@ -182,13 +180,15 @@ CodeMirror.defineMode("clojure", function (config, mode) {
182
180
  }
183
181
  } else if ( ch == ":" ) {
184
182
  stream.eatWhile(tests.lang_keyword);
185
- return TAG;
183
+ return ATOM;
186
184
  } else {
187
185
  stream.eatWhile(tests.basic);
188
186
 
189
187
  if (keywords && keywords.propertyIsEnumerable(stream.current())) {
188
+ returnType = KEYWORD;
189
+ } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {
190
190
  returnType = BUILTIN;
191
- } else if ( atoms && atoms.propertyIsEnumerable(stream.current()) ) {
191
+ } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
192
192
  returnType = ATOM;
193
193
  } else returnType = null;
194
194
  }
@@ -92,7 +92,7 @@ CodeMirror.defineMode("css", function(config) {
92
92
  var style = state.tokenize(stream, state);
93
93
 
94
94
  var context = state.stack[state.stack.length-1];
95
- if (type == "hash" && context == "rule") style = "atom";
95
+ if (type == "hash" && context != "rule") style = "string-2";
96
96
  else if (style == "variable") {
97
97
  if (context == "rule") style = "number";
98
98
  else if (!context || context == "@media{") style = "tag";
@@ -28,7 +28,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
28
28
  function javascript(stream, state) {
29
29
  if (stream.match(/^<\/\s*script\s*>/i, false)) {
30
30
  state.token = html;
31
- state.curState = null;
31
+ state.localState = null;
32
32
  state.mode = "html";
33
33
  return html(stream, state);
34
34
  }
@@ -319,8 +319,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
319
319
  kwAllowed: true,
320
320
  cc: [],
321
321
  lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
322
- localVars: null,
323
- context: null,
322
+ localVars: parserConfig.localVars,
323
+ context: parserConfig.localVars && {vars: parserConfig.localVars},
324
324
  indented: 0
325
325
  };
326
326
  },
@@ -334,7 +334,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
334
334
  if (stream.eatSpace()) return null;
335
335
  var style = state.tokenize(stream, state);
336
336
  if (type == "comment") return style;
337
- state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/);
337
+ state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
338
338
  state.kwAllowed = type != '.';
339
339
  return parseJS(state, style, type, content, stream);
340
340
  },
@@ -1,21 +1,26 @@
1
- CodeMirror.defineMode("less", function(config) {
1
+ /*
2
+ LESS mode - http://www.lesscss.org/
3
+ Ported to CodeMirror by Peter Kroon
4
+ */
5
+
6
+ CodeMirror.defineMode("css", function(config) {
2
7
  var indentUnit = config.indentUnit, type;
3
8
  function ret(style, tp) {type = tp; return style;}
4
9
  //html5 tags
5
10
  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"];
6
11
 
7
12
  function inTagsArray(val){
8
- for(var i=0; i<tags.length; i++){
9
- if(val === tags[i]){
10
- return true;
11
- }
12
- }
13
+ for(var i=0; i<tags.length; i++){
14
+ if(val === tags[i]){
15
+ return true;
16
+ }
17
+ }
13
18
  }
14
19
 
15
20
  function tokenBase(stream, state) {
16
21
  var ch = stream.next();
17
22
 
18
- if (ch == "@") {stream.eatWhile(/[\w\-]/); return ret("meta", stream.current());}
23
+ if (ch == "@") {stream.eatWhile(/[\w\-]/); return ret("meta", stream.current());}
19
24
  else if (ch == "/" && stream.eat("*")) {
20
25
  state.tokenize = tokenCComment;
21
26
  return tokenCComment(stream, state);
@@ -30,15 +35,15 @@ CodeMirror.defineMode("less", function(config) {
30
35
  state.tokenize = tokenString(ch);
31
36
  return state.tokenize(stream, state);
32
37
  }
33
- else if (ch == "/") { // lesscss e.g.: .png will not be parsed as a class
34
- if(stream.eat("/")){
35
- state.tokenize = tokenSComment
38
+ else if (ch == "/") { // lesscss e.g.: .png will not be parsed as a class
39
+ if(stream.eat("/")){
40
+ state.tokenize = tokenSComment
36
41
  return tokenSComment(stream, state);
37
- }else{
38
- stream.eatWhile(/[\a-zA-Z0-9\-_.]/);
39
- if(stream.peek() == ")" || stream.peek() == "/")return ret("string", "string");//let url(/images/logo.png) without quotes return as string
42
+ }else{
43
+ stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/);
44
+ if(/\/|\)/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == ")")))return ret("string", "string");//let url(/images/logo.png) without quotes return as string
40
45
  return ret("number", "unit");
41
- }
46
+ }
42
47
  }
43
48
  else if (ch == "!") {
44
49
  stream.match(/^\s*\w*/);
@@ -48,66 +53,86 @@ CodeMirror.defineMode("less", function(config) {
48
53
  stream.eatWhile(/[\w.%]/);
49
54
  return ret("number", "unit");
50
55
  }
51
- else if (/[,+>*\/]/.test(ch)) {//removed . dot character original was [,.+>*\/]
56
+ else if (/[,+<>*\/]/.test(ch)) {//removed . dot character original was [,.+>*\/]
52
57
  return ret(null, "select-op");
53
58
  }
54
59
  else if (/[;{}:\[\]()]/.test(ch)) { //added () char for lesscss original was [;{}:\[\]]
55
60
  if(ch == ":"){
56
- stream.eatWhile(/[active|hover|link|visited]/);
57
- if( stream.current().match(/active|hover|link|visited/)){
58
- return ret("tag", "tag");
59
- }else{
60
- return ret(null, ch);
61
- }
62
- }else{
63
- return ret(null, ch);
64
- }
61
+ stream.eatWhile(/[active|hover|link|visited]/);
62
+ if( stream.current().match(/active|hover|link|visited/)){
63
+ return ret("tag", "tag");
64
+ }else{
65
+ return ret(null, ch);
66
+ }
67
+ }else{
68
+ return ret(null, ch);
69
+ }
65
70
  }
66
- else if (ch == ".") { // lesscss
67
- stream.eatWhile(/[\a-zA-Z0-9\-_]/);
71
+ else if (ch == ".") { // lesscss
72
+ stream.eatWhile(/[\a-zA-Z0-9\-_]/);
68
73
  return ret("tag", "tag");
69
74
  }
70
- else if (ch == "#") { // lesscss
71
- stream.match(/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/);
72
- if(stream.current().length >1){
73
- if(stream.current().match(/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/) != null){
74
- return ret("number", "unit");
75
- }else{
75
+ else if (ch == "#") { // lesscss
76
+ //we don't eat white-space, we want the hex color and or id only
77
+ stream.eatWhile(/[A-Za-z0-9]/);
78
+ //check if there is a proper hex color length e.g. #eee || #eeeEEE
79
+ if(stream.current().length ===4 || stream.current().length ===7){
80
+ if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream
81
+ //when not a valid hex value, parse as id
82
+ if(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret("atom", "tag");
83
+ //eat white-space
84
+ stream.eatSpace();
85
+ //when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]
86
+ if( /[\/<>.(){!$%^&*_\-\\?=+\|#'~`]/.test(stream.peek()) )return ret("atom", "tag");
87
+ //#time { color: #aaa }
88
+ else if(stream.peek() == "}" )return ret("number", "unit");
89
+ //we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa
90
+ else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret("atom", "tag");
91
+ //when a hex value is on the end of a line, parse as id
92
+ else if(stream.eol())return ret("atom", "tag");
93
+ //default
94
+ else return ret("number", "unit");
95
+ }else{//when not a valid hexvalue in the current stream e.g. #footer
96
+ stream.eatWhile(/[\w\\\-]/);
97
+ return ret("atom", "tag");
98
+ }
99
+ }else{
100
+ stream.eatWhile(/[\w\\\-]/);
101
+ return ret("atom", "tag");
102
+ }
103
+ }
104
+ else if (ch == "&") {
76
105
  stream.eatWhile(/[\w\-]/);
77
- return ret("atom", "tag");
106
+ return ret(null, ch);
107
+ }
108
+ else if (ch == "&") {
109
+ stream.eatWhile(/[\w\-]/);
110
+ return ret(null, ch);
78
111
  }
79
- }else{
80
- stream.eatWhile(/[\w\-]/);
81
- return ret("atom", "tag");
82
- }
83
- }
84
- else if (ch == "&") {
85
- stream.eatWhile(/[\w\-]/);
86
- return ret(null, ch);
87
- }
88
112
  else {
89
113
  stream.eatWhile(/[\w\\\-_.%]/);
90
- if( stream.eat("(") ){ // lesscss
91
- return ret(null, ch);
92
- }else if( stream.current().match(/\-\d|\-.\d/) ){ // lesscss match e.g.: -5px -0.4 etc...
93
- return ret("number", "unit");
94
- }else if( inTagsArray(stream.current()) ){ // lesscss match html tags
95
- return ret("tag", "tag");
96
- }else if( (stream.peek() == ")" || stream.peek() == "/") && stream.current().indexOf('.') !== -1){
97
- return ret("string", "string");//let url(logo.png) without quotes and froward slash return as string
98
- }else{
114
+ if( stream.peek().match(/\(/) != null ){// lesscss
115
+ stream.eatWhile(/[a-zA-Z\s]/);
116
+ if(stream.peek() == "(")return ret(null, ch);
117
+ }else if( stream.current().match(/\-\d|\-.\d/) ){ // lesscss match e.g.: -5px -0.4 etc...
118
+ return ret("number", "unit");
119
+ }else if( inTagsArray(stream.current()) ){ // lesscss match html tags
120
+ return ret("tag", "tag");
121
+ }else if( /\/|\)/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == ")")) && stream.current().indexOf(".") !== -1){
122
+ return ret("string", "string");//let url(/images/logo.png) without quotes return as string
123
+ }else{
99
124
  return ret("variable", "variable");
100
- }
125
+ }
101
126
  }
102
127
 
103
128
  }
104
129
 
105
130
  function tokenSComment(stream, state) {// SComment = Slash comment
106
131
  stream.skipToEnd();
107
- state.tokenize = tokenBase;
132
+ state.tokenize = tokenBase;
108
133
  return ret("comment", "comment");
109
134
  }
110
-
135
+
111
136
  function tokenCComment(stream, state) {
112
137
  var maybeEnd = false, ch;
113
138
  while ((ch = stream.next()) != null) {
@@ -146,7 +171,7 @@ CodeMirror.defineMode("less", function(config) {
146
171
  }
147
172
 
148
173
  return {
149
- startState: function(base) {
174
+ startState: function(base) {
150
175
  return {tokenize: tokenBase,
151
176
  baseIndent: base || 0,
152
177
  stack: []};
@@ -160,7 +185,11 @@ CodeMirror.defineMode("less", function(config) {
160
185
  if (type == "hash" && context == "rule") style = "atom";
161
186
  else if (style == "variable") {
162
187
  if (context == "rule") style = null; //"tag"
163
- else if (!context || context == "@media{") style = "tag";
188
+ else if (!context || context == "@media{"){
189
+ style = stream.current() == "when" ? "variable" :
190
+ stream.string.match(/#/g) != undefined ? null :
191
+ /[\s,|\s\)]/.test(stream.peek()) ? "tag" : null;
192
+ }
164
193
  }
165
194
 
166
195
  if (context == "rule" && /^[\{\};]$/.test(type))
@@ -186,4 +215,4 @@ CodeMirror.defineMode("less", function(config) {
186
215
  };
187
216
  });
188
217
 
189
- CodeMirror.defineMIME("text/less", "less");
218
+ CodeMirror.defineMIME("text/css", "css");
@@ -13,11 +13,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
13
13
  , strong = 'strong'
14
14
  , emstrong = 'emstrong';
15
15
 
16
- var hrRE = /^[*-=_]/
17
- , ulRE = /^[*-+]\s+/
16
+ var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
17
+ , ulRE = /^[*\-+]\s+/
18
18
  , olRE = /^[0-9]+\.\s+/
19
19
  , headerRE = /^(?:\={3,}|-{3,})$/
20
- , codeRE = /^(k:\t|\s{4,})/
21
20
  , textRE = /^[^\[*_\\<>`]+/;
22
21
 
23
22
  function switchInline(stream, state, f) {
@@ -33,9 +32,18 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
33
32
 
34
33
  // Blocks
35
34
 
35
+ function blankLine(state) {
36
+ // Reset EM state
37
+ state.em = false;
38
+ // Reset STRONG state
39
+ state.strong = false;
40
+ return null;
41
+ }
42
+
36
43
  function blockNormal(stream, state) {
37
44
  var match;
38
- if (stream.match(codeRE)) {
45
+ if (state.indentationDiff >= 4) {
46
+ state.indentation -= state.indentationDiff;
39
47
  stream.skipToEnd();
40
48
  return code;
41
49
  } else if (stream.eatSpace()) {
@@ -47,11 +55,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
47
55
  state.quote = true;
48
56
  } else if (stream.peek() === '[') {
49
57
  return switchInline(stream, state, footnoteLink);
50
- } else if (hrRE.test(stream.peek())) {
51
- var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$');
52
- if (stream.match(re, true)) {
53
- return hr;
54
- }
58
+ } else if (stream.match(hrRE, true)) {
59
+ return hr;
55
60
  } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
56
61
  state.indentation += match[0].length;
57
62
  return list;
@@ -72,39 +77,15 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
72
77
 
73
78
  // Inline
74
79
  function getType(state) {
80
+ var styles = [];
75
81
 
76
- // Set defaults
77
- returnValue = '';
78
-
79
- // Strong / Emphasis
80
- if(state.strong){
81
- if(state.em){
82
- returnValue += (returnValue ? ' ' : '') + emstrong;
83
- } else {
84
- returnValue += (returnValue ? ' ' : '') + strong;
85
- }
86
- } else {
87
- if(state.em){
88
- returnValue += (returnValue ? ' ' : '') + em;
89
- }
90
- }
91
-
92
- // Header
93
- if(state.header){
94
- returnValue += (returnValue ? ' ' : '') + header;
95
- }
96
-
97
- // Quotes
98
- if(state.quote){
99
- returnValue += (returnValue ? ' ' : '') + quote;
100
- }
101
-
102
- // Check valud and return
103
- if(!returnValue){
104
- returnValue = null;
105
- }
106
- return returnValue;
82
+ if (state.strong) { styles.push(state.em ? emstrong : strong); }
83
+ else if (state.em) { styles.push(em); }
107
84
 
85
+ if (state.header) { styles.push(header); }
86
+ if (state.quote) { styles.push(quote); }
87
+
88
+ return styles.length ? styles.join(' ') : null;
108
89
  }
109
90
 
110
91
  function handleText(stream, state) {
@@ -238,36 +219,24 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
238
219
 
239
220
  token: function(stream, state) {
240
221
  if (stream.sol()) {
241
- // Reset EM state
242
- state.em = false;
243
- // Reset STRONG state
244
- state.strong = false;
222
+ if (stream.match(/^\s*$/, true)) { return blankLine(state); }
223
+
245
224
  // Reset state.header
246
225
  state.header = false;
247
226
  // Reset state.quote
248
227
  state.quote = false;
249
228
 
250
229
  state.f = state.block;
251
- var previousIndentation = state.indentation
252
- , currentIndentation = 0;
253
- while (previousIndentation > 0) {
254
- if (stream.eat(' ')) {
255
- previousIndentation--;
256
- currentIndentation++;
257
- } else if (previousIndentation >= 4 && stream.eat('\t')) {
258
- previousIndentation -= 4;
259
- currentIndentation += 4;
260
- } else {
261
- break;
262
- }
263
- }
264
- state.indentation = currentIndentation;
265
-
266
- if (currentIndentation > 0) return null;
230
+ var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
231
+ state.indentationDiff = indentation - state.indentation;
232
+ state.indentation = indentation;
233
+ if (indentation > 0) { return null; }
267
234
  }
268
235
  return state.f(stream, state);
269
236
  },
270
237
 
238
+ blankLine: blankLine,
239
+
271
240
  getType: getType
272
241
  };
273
242