puffer_pages 0.1.0 → 0.1.1

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 (46) hide show
  1. data/.gitignore +1 -2
  2. data/.rvmrc +1 -0
  3. data/.travis.yml +6 -0
  4. data/CHANGELOG.md +12 -0
  5. data/Gemfile.lock +83 -78
  6. data/app/assets/javascripts/puffer/codemirror.js +1382 -818
  7. data/app/assets/javascripts/puffer/codemirror/htmlmixed.js +4 -5
  8. data/app/assets/javascripts/puffer/codemirror/javascript.js +12 -4
  9. data/app/assets/javascripts/puffer/codemirror/xml.js +35 -14
  10. data/app/assets/javascripts/puffer/liquid.js +15 -0
  11. data/app/assets/javascripts/puffer/puffer_pages.js +56 -6
  12. data/app/assets/stylesheets/puffer/codemirror.css +50 -14
  13. data/app/assets/stylesheets/puffer/codemirror/cobalt.css +1 -0
  14. data/app/assets/stylesheets/puffer/codemirror/eclipse.css +3 -2
  15. data/app/assets/stylesheets/puffer/codemirror/elegant.css +1 -0
  16. data/app/assets/stylesheets/puffer/codemirror/monokai.css +28 -0
  17. data/app/assets/stylesheets/puffer/codemirror/neat.css +1 -0
  18. data/app/assets/stylesheets/puffer/codemirror/night.css +1 -0
  19. data/app/assets/stylesheets/puffer/codemirror/rubyblue.css +21 -0
  20. data/app/assets/stylesheets/puffer/puffer_pages.css +59 -3
  21. data/app/components/codemirror/form.html.erb +16 -0
  22. data/app/components/codemirror_component.rb +9 -0
  23. data/app/components/page_parts/form.html.erb +13 -4
  24. data/app/controllers/pages_controller.rb +1 -10
  25. data/app/controllers/puffer_pages/layouts_base.rb +1 -1
  26. data/app/controllers/puffer_pages/pages_base.rb +1 -1
  27. data/app/controllers/puffer_pages/snippets_base.rb +1 -1
  28. data/app/models/puffer_pages/page.rb +4 -3
  29. data/app/views/layouts/puffer_pages_layout.html.erb +2 -1
  30. data/gemfiles/Gemfile-rails-3.1 +5 -0
  31. data/gemfiles/Gemfile-rails-3.1.lock +173 -0
  32. data/gemfiles/Gemfile-rails-3.2 +5 -0
  33. data/gemfiles/Gemfile-rails-3.2.lock +171 -0
  34. data/lib/puffer_pages.rb +5 -0
  35. data/lib/puffer_pages/extensions/controller.rb +12 -16
  36. data/lib/puffer_pages/extensions/mapper.rb +7 -13
  37. data/lib/puffer_pages/liquid/tags/page_attribute.rb +39 -0
  38. data/lib/puffer_pages/version.rb +1 -1
  39. data/puffer_pages.gemspec +7 -4
  40. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  41. data/spec/lib/tags_spec.rb +25 -3
  42. data/spec/models/page_spec.rb +2 -3
  43. metadata +75 -43
  44. data/app/assets/stylesheets/puffer/codemirror/default.css +0 -19
  45. data/app/components/page_part_body/form.html.erb +0 -3
  46. data/app/components/page_part_body_component.rb +0 -3
@@ -1,8 +1,3 @@
1
- //= require ./xml
2
- //= require ./css
3
- //= require ./javascript
4
- //= require_self
5
-
6
1
  CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
7
2
  var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
8
3
  var jsMode = CodeMirror.getMode(config, "javascript");
@@ -77,6 +72,10 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
77
72
  return cssMode.indent(state.localState, textAfter);
78
73
  },
79
74
 
75
+ compareStates: function(a, b) {
76
+ return htmlMode.compareStates(a.htmlState, b.htmlState);
77
+ },
78
+
80
79
  electricChars: "/{}:"
81
80
  }
82
81
  });
@@ -11,7 +11,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
11
11
  return {
12
12
  "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
13
13
  "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
14
- "var": kw("var"), "function": kw("function"), "catch": kw("catch"),
14
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
15
+ "function": kw("function"), "catch": kw("catch"),
15
16
  "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
16
17
  "in": operator, "typeof": operator, "instanceof": operator,
17
18
  "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
@@ -54,7 +55,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
54
55
  return ret("number", "number");
55
56
  }
56
57
  else if (/\d/.test(ch)) {
57
- stream.match(/^\d*(?:\.\d*)?(?:e[+\-]?\d+)?/);
58
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
58
59
  return ret("number", "number");
59
60
  }
60
61
  else if (ch == "/") {
@@ -86,7 +87,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
86
87
  else {
87
88
  stream.eatWhile(/[\w\$_]/);
88
89
  var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
89
- return known ? ret(known.type, known.style, word) :
90
+ return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
90
91
  ret("variable", "variable", word);
91
92
  }
92
93
  }
@@ -228,13 +229,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
228
229
  function expression(type) {
229
230
  if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
230
231
  if (type == "function") return cont(functiondef);
231
- if (type == "keyword c") return cont(expression);
232
+ if (type == "keyword c") return cont(maybeexpression);
232
233
  if (type == "(") return cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator);
233
234
  if (type == "operator") return cont(expression);
234
235
  if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
235
236
  if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
236
237
  return cont();
237
238
  }
239
+ function maybeexpression(type) {
240
+ if (type.match(/[;\}\)\],]/)) return pass();
241
+ return pass(expression);
242
+ }
243
+
238
244
  function maybeoperator(type, value) {
239
245
  if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
240
246
  if (type == "operator") return cont(expression);
@@ -310,6 +316,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
310
316
  return {
311
317
  tokenize: jsTokenBase,
312
318
  reAllowed: true,
319
+ kwAllowed: true,
313
320
  cc: [],
314
321
  lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
315
322
  localVars: null,
@@ -328,6 +335,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
328
335
  var style = state.tokenize(stream, state);
329
336
  if (type == "comment") return style;
330
337
  state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/);
338
+ state.kwAllowed = type != '.';
331
339
  return parseJS(state, style, type, content, stream);
332
340
  },
333
341
 
@@ -3,9 +3,9 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
3
3
  var Kludges = parserConfig.htmlMode ? {
4
4
  autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
5
5
  "meta": true, "col": true, "frame": true, "base": true, "area": true},
6
- doNotIndent: {"pre": true, "!cdata": true},
6
+ doNotIndent: {"pre": true},
7
7
  allowUnquoted: true
8
- } : {autoSelfClosers: {}, doNotIndent: {"!cdata": true}, allowUnquoted: false};
8
+ } : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false};
9
9
  var alignCDATA = parserConfig.alignCDATA;
10
10
 
11
11
  // Return variables for tokenizers
@@ -27,7 +27,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
27
27
  else if (stream.match("--")) return chain(inBlock("comment", "-->"));
28
28
  else if (stream.match("DOCTYPE", true, true)) {
29
29
  stream.eatWhile(/[\w\._\-]/);
30
- return chain(inBlock("meta", ">"));
30
+ return chain(doctype(1));
31
31
  }
32
32
  else return null;
33
33
  }
@@ -102,6 +102,26 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
102
102
  return style;
103
103
  };
104
104
  }
105
+ function doctype(depth) {
106
+ return function(stream, state) {
107
+ var ch;
108
+ while ((ch = stream.next()) != null) {
109
+ if (ch == "<") {
110
+ state.tokenize = doctype(depth + 1);
111
+ return state.tokenize(stream, state);
112
+ } else if (ch == ">") {
113
+ if (depth == 1) {
114
+ state.tokenize = inText;
115
+ break;
116
+ } else {
117
+ state.tokenize = doctype(depth - 1);
118
+ return state.tokenize(stream, state);
119
+ }
120
+ }
121
+ }
122
+ return "meta";
123
+ };
124
+ }
105
125
 
106
126
  var curState, setStyle;
107
127
  function pass() {
@@ -127,8 +147,10 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
127
147
  }
128
148
 
129
149
  function element(type) {
130
- if (type == "openTag") {curState.tagName = tagName; return cont(attributes, endtag(curState.startOfLine));}
131
- else if (type == "closeTag") {
150
+ if (type == "openTag") {
151
+ curState.tagName = tagName;
152
+ return cont(attributes, endtag(curState.startOfLine));
153
+ } else if (type == "closeTag") {
132
154
  var err = false;
133
155
  if (curState.context) {
134
156
  err = curState.context.tagName != tagName;
@@ -138,12 +160,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
138
160
  if (err) setStyle = "error";
139
161
  return cont(endclosetag(err));
140
162
  }
141
- else if (type == "string") {
142
- if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
143
- if (curState.tokenize == inText) popContext();
144
- return cont();
145
- }
146
- else return cont();
163
+ return cont();
147
164
  }
148
165
  function endtag(startOfLine) {
149
166
  return function(type) {
@@ -166,6 +183,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
166
183
  function attributes(type) {
167
184
  if (type == "word") {setStyle = "attribute"; return cont(attributes);}
168
185
  if (type == "equals") return cont(attvalue, attributes);
186
+ if (type == "string") {setStyle = "error"; return cont(attributes);}
169
187
  return pass();
170
188
  }
171
189
  function attvalue(type) {
@@ -192,6 +210,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
192
210
 
193
211
  setStyle = type = tagName = null;
194
212
  var style = state.tokenize(stream, state);
213
+ state.type = type;
195
214
  if ((style || type) && style != "comment") {
196
215
  curState = state;
197
216
  while (true) {
@@ -203,9 +222,11 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
203
222
  return setStyle || style;
204
223
  },
205
224
 
206
- indent: function(state, textAfter) {
225
+ indent: function(state, textAfter, fullLine) {
207
226
  var context = state.context;
208
- if (context && context.noIndent) return 0;
227
+ if ((state.tokenize != inTag && state.tokenize != inText) ||
228
+ context && context.noIndent)
229
+ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
209
230
  if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
210
231
  if (context && /^<\//.test(textAfter))
211
232
  context = context.prev;
@@ -216,7 +237,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
216
237
  },
217
238
 
218
239
  compareStates: function(a, b) {
219
- if (a.indented != b.indented) return false;
240
+ if (a.indented != b.indented || a.tokenize != b.tokenize) return false;
220
241
  for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {
221
242
  if (!ca || !cb) return ca == cb;
222
243
  if (ca.tagName != cb.tagName) return false;
@@ -0,0 +1,15 @@
1
+ CodeMirror.defineMode("liquid", function(config, parserConfig) {
2
+ var liquidOverlay = {
3
+ token: function(stream, state) {
4
+ if (stream.match("{{") || stream.match("{%")) {
5
+ while ((ch = stream.next()) != null)
6
+ if ((ch == "}" || ch == "%") && stream.next() == "}") break;
7
+ return "liquid";
8
+ }
9
+ while (stream.next() != null && !(stream.match("{{", false) || !stream.match("{%", false))) {}
10
+ return null;
11
+ }
12
+ };
13
+
14
+ return CodeMirror.overlayParser(CodeMirror.getMode(config, parserConfig.backdrop || "text/html"), liquidOverlay);
15
+ });
@@ -1,7 +1,11 @@
1
1
  //= require puffer/right-tabs-src
2
2
  //= require puffer/codemirror
3
3
  //= require puffer/overlay
4
+ //= require puffer/codemirror/xml
5
+ //= require puffer/codemirror/javascript
6
+ //= require puffer/codemirror/css
4
7
  //= require_tree ./codemirror
8
+ //= require puffer/liquid
5
9
 
6
10
  Tabs.include({
7
11
  initialize: function(options) {
@@ -17,6 +21,13 @@ Tabs.include({
17
21
  }
18
22
  });
19
23
 
24
+ var page_part_tab_select = function(event) {
25
+ var textarea = event.target.panel.first('textarea[data-codemirror]');
26
+ if (textarea.codemirror) {
27
+ textarea.codemirror.refresh();
28
+ }
29
+ }
30
+
20
31
  var page_part_tab_remove = function(event) {
21
32
  var destroy_mark = event.target.panel.first('.destroy_mark');
22
33
  var page_part_param = destroy_mark.next();
@@ -37,7 +48,7 @@ var page_part_tab_add = function(event) {
37
48
  _this.tabs.last().panel.first('input[type=hidden]').value(value);
38
49
  _this.tabs.last().select();
39
50
  _this.addButton.insertTo(_this.tabsList);
40
- $$('textarea[codemirror]').each(init_codemirror);
51
+ $$('textarea[data-codemirror]').each(init_codemirror);
41
52
  this.hide();
42
53
  }
43
54
  }).show();
@@ -45,14 +56,53 @@ var page_part_tab_add = function(event) {
45
56
 
46
57
  var init_codemirror = function(textarea) {
47
58
  if (!textarea.codemirror) {
48
- CodeMirror.fromTextArea(textarea._, {
49
- mode: 'text/html',
50
- lineNumbers: true
59
+ var codemirror = CodeMirror.fromTextArea(textarea._, {
60
+ mode: 'liquid',
61
+ lineNumbers: true,
62
+ lineWrapping: true,
63
+ onCursorActivity: function(editor) {
64
+ if (editor.last_active_line != undefined) {
65
+ editor.setLineClass(editor.last_active_line, null);
66
+ }
67
+ editor.last_active_line = editor.getCursor().line;
68
+ editor.setLineClass(editor.last_active_line, "active_line");
69
+ },
70
+ extraKeys: {
71
+ "Esc": codemirror_fullscreen
72
+ }
51
73
  });
52
- textarea.codemirror = true
74
+
75
+ textarea.codemirror = codemirror;
76
+ codemirror.buttons = textarea.prev('.codemirror_buttons');
53
77
  }
54
78
  }
55
79
 
56
80
  $(document).onReady(function() {
57
- $$('textarea[codemirror]').each(init_codemirror);
81
+ $$('textarea[data-codemirror]').each(init_codemirror);
82
+ });
83
+
84
+ "*[data-codemirror-button]".onClick(function(event) {
85
+ if (event.which != 1) return;
86
+ window['codemirror_' + this.data('codemirror-button')](this.parent('ul').next('textarea').codemirror);
58
87
  });
88
+
89
+ ".codemirror_buttons_fulscreen".onMouseenter('morph', {'top': '0px'});
90
+ ".codemirror_buttons_fulscreen".onMouseleave('morph', {'top': '-20px'});
91
+
92
+ var codemirror_fullscreen = function(editor) {
93
+ var scroll = $(editor.getWrapperElement()).children('.CodeMirror-scroll').first();
94
+ var body = $$('body').first();
95
+
96
+ if (scroll.hasClass('fullscreen')) {
97
+ scroll.removeClass('fullscreen');
98
+ editor.buttons.removeClass('codemirror_buttons_fulscreen');
99
+ body.setStyle('overflow', 'auto');
100
+ } else {
101
+ scroll.addClass('fullscreen');
102
+ editor.buttons.addClass('codemirror_buttons_fulscreen');
103
+ body.setStyle('overflow', 'hidden');
104
+ }
105
+
106
+ editor.refresh();
107
+ editor.focus();
108
+ }
@@ -23,6 +23,7 @@
23
23
  color: #aaa;
24
24
  text-align: right;
25
25
  padding: .4em .2em .4em .4em;
26
+ white-space: pre !important;
26
27
  }
27
28
  .CodeMirror-lines {
28
29
  padding: .4em;
@@ -41,28 +42,63 @@
41
42
  word-wrap: normal;
42
43
  }
43
44
 
45
+ .CodeMirror-wrap pre {
46
+ word-wrap: break-word;
47
+ white-space: pre-wrap;
48
+ }
49
+ .CodeMirror-wrap .CodeMirror-scroll {
50
+ overflow-x: hidden;
51
+ }
52
+
44
53
  .CodeMirror textarea {
45
- font-family: inherit !important;
46
- font-size: inherit !important;
54
+ outline: none !important;
47
55
  }
48
56
 
49
- .CodeMirror-cursor {
57
+ .CodeMirror pre.CodeMirror-cursor {
50
58
  z-index: 10;
51
59
  position: absolute;
52
60
  visibility: hidden;
53
- border-left: 1px solid black !important;
61
+ border-left: 1px solid black;
54
62
  }
55
- .CodeMirror-focused .CodeMirror-cursor {
63
+ .CodeMirror-focused pre.CodeMirror-cursor {
56
64
  visibility: visible;
57
65
  }
58
66
 
59
- span.CodeMirror-selected {
60
- background: #ccc !important;
61
- color: HighlightText !important;
62
- }
63
- .CodeMirror-focused span.CodeMirror-selected {
64
- background: Highlight !important;
65
- }
67
+ span.CodeMirror-selected { background: #d9d9d9; }
68
+ .CodeMirror-focused span.CodeMirror-selected { background: #d2dcf8; }
69
+
70
+ .CodeMirror-searching {background: #ffa;}
71
+
72
+ /* Default theme */
73
+
74
+ .cm-s-default span.cm-keyword {color: #708;}
75
+ .cm-s-default span.cm-atom {color: #219;}
76
+ .cm-s-default span.cm-number {color: #164;}
77
+ .cm-s-default span.cm-def {color: #00f;}
78
+ .cm-s-default span.cm-variable {color: black;}
79
+ .cm-s-default span.cm-variable-2 {color: #05a;}
80
+ .cm-s-default span.cm-variable-3 {color: #085;}
81
+ .cm-s-default span.cm-property {color: black;}
82
+ .cm-s-default span.cm-operator {color: black;}
83
+ .cm-s-default span.cm-comment {color: #a50;}
84
+ .cm-s-default span.cm-string {color: #a11;}
85
+ .cm-s-default span.cm-string-2 {color: #f50;}
86
+ .cm-s-default span.cm-meta {color: #555;}
87
+ .cm-s-default span.cm-error {color: #f00;}
88
+ .cm-s-default span.cm-qualifier {color: #555;}
89
+ .cm-s-default span.cm-builtin {color: #30a;}
90
+ .cm-s-default span.cm-bracket {color: #cc7;}
91
+ .cm-s-default span.cm-tag {color: #170;}
92
+ .cm-s-default span.cm-attribute {color: #00c;}
93
+ .cm-s-default span.cm-header {color: #a0a;}
94
+ .cm-s-default span.cm-quote {color: #090;}
95
+ .cm-s-default span.cm-hr {color: #999;}
96
+ .cm-s-default span.cm-link {color: #00c;}
97
+
98
+ span.cm-header, span.cm-strong {font-weight: bold;}
99
+ span.cm-em {font-style: italic;}
100
+ span.cm-emstrong {font-style: italic; font-weight: bold;}
101
+ span.cm-link {text-decoration: underline;}
66
102
 
67
- .CodeMirror-matchingbracket {color: #0f0 !important;}
68
- .CodeMirror-nonmatchingbracket {color: #f22 !important;}
103
+ div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
104
+ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
@@ -15,3 +15,4 @@
15
15
  .cm-s-cobalt span.cm-error { color: #9d1e15; }
16
16
  .cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
17
17
  .cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
18
+ .cm-s-cobalt span.cm-link { color: #845dc4; }
@@ -17,8 +17,9 @@
17
17
  .cm-s-eclipse span.cm-bracket {color: #cc7;}
18
18
  .cm-s-eclipse span.cm-tag {color: #170;}
19
19
  .cm-s-eclipse span.cm-attribute {color: #00c;}
20
+ .cm-s-eclipse span.cm-link {color: #219;}
20
21
 
21
- .CodeMirror-matchingbracket{
22
+ .cm-s-eclipse .CodeMirror-matchingbracket {
22
23
  border:1px solid grey;
23
24
  color:black !important;;
24
- }
25
+ }
@@ -7,3 +7,4 @@
7
7
  .cm-s-elegant span.cm-keyword {color: #730;}
8
8
  .cm-s-elegant span.cm-builtin {color: #30a;}
9
9
  .cm-s-elegant span.cm-error {background-color: #fdd;}
10
+ .cm-s-elegant span.cm-link {color: #762;}
@@ -0,0 +1,28 @@
1
+ /* Based on Sublime Text's Monokai theme */
2
+
3
+ .cm-s-monokai {background: #272822; color: #f8f8f2;}
4
+ .cm-s-monokai span.CodeMirror-selected {background: #ffe792 !important;}
5
+ .cm-s-monokai .CodeMirror-gutter {background: #272822; border-right: 0px;}
6
+ .cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;}
7
+ .cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
8
+
9
+ .cm-s-monokai span.cm-comment {color: #75715e;}
10
+ .cm-s-monokai span.cm-atom {color: #ae81ff;}
11
+ .cm-s-monokai span.cm-number {color: #ae81ff;}
12
+
13
+ .cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
14
+ .cm-s-monokai span.cm-keyword {color: #f92672;}
15
+ .cm-s-monokai span.cm-string {color: #e6db74;}
16
+
17
+ .cm-s-monokai span.cm-variable {color: #a6e22e;}
18
+ .cm-s-monokai span.cm-variable-2 {color: #9effff;}
19
+ .cm-s-monokai span.cm-def {color: #fd971f;}
20
+ .cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
21
+ .cm-s-monokai span.cm-bracket {color: #f8f8f2;}
22
+ .cm-s-monokai span.cm-tag {color: #f92672;}
23
+ .cm-s-monokai span.cm-link {color: #ae81ff;}
24
+
25
+ .cm-s-monokai .CodeMirror-matchingbracket {
26
+ text-decoration: underline;
27
+ color: white !important;
28
+ }
@@ -6,3 +6,4 @@
6
6
  .cm-s-neat span.cm-variable { color: black; }
7
7
  .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
8
8
  .cm-s-neat span.cm-meta {color: #555;}
9
+ .cm-s-neat span.cm-link { color: #3a3; }