ledger_web 1.2

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 (128) hide show
  1. data/.gitignore +10 -0
  2. data/LICENSE +7 -0
  3. data/README.md +140 -0
  4. data/Rakefile +11 -0
  5. data/bin/ledger_web +14 -0
  6. data/ledger_web.gemspec +26 -0
  7. data/lib/ledger_web/app.rb +69 -0
  8. data/lib/ledger_web/config.rb +87 -0
  9. data/lib/ledger_web/db/migrate/20111226180900_initial_schema.rb +38 -0
  10. data/lib/ledger_web/db/migrate/20111231132900_add_views.rb +37 -0
  11. data/lib/ledger_web/db.rb +54 -0
  12. data/lib/ledger_web/helpers.rb +62 -0
  13. data/lib/ledger_web/public/bootstrap-dropdown.js +55 -0
  14. data/lib/ledger_web/public/bootstrap.min.css +356 -0
  15. data/lib/ledger_web/public/codemirror/keymap/emacs.js +29 -0
  16. data/lib/ledger_web/public/codemirror/keymap/vim.js +76 -0
  17. data/lib/ledger_web/public/codemirror/lib/codemirror.css +104 -0
  18. data/lib/ledger_web/public/codemirror/lib/codemirror.js +2761 -0
  19. data/lib/ledger_web/public/codemirror/lib/util/dialog.css +23 -0
  20. data/lib/ledger_web/public/codemirror/lib/util/dialog.js +63 -0
  21. data/lib/ledger_web/public/codemirror/lib/util/foldcode.js +66 -0
  22. data/lib/ledger_web/public/codemirror/lib/util/formatting.js +291 -0
  23. data/lib/ledger_web/public/codemirror/lib/util/javascript-hint.js +83 -0
  24. data/lib/ledger_web/public/codemirror/lib/util/overlay.js +51 -0
  25. data/lib/ledger_web/public/codemirror/lib/util/runmode.js +27 -0
  26. data/lib/ledger_web/public/codemirror/lib/util/search.js +114 -0
  27. data/lib/ledger_web/public/codemirror/lib/util/searchcursor.js +117 -0
  28. data/lib/ledger_web/public/codemirror/lib/util/simple-hint.css +16 -0
  29. data/lib/ledger_web/public/codemirror/lib/util/simple-hint.js +66 -0
  30. data/lib/ledger_web/public/codemirror/mode/clike/clike.js +249 -0
  31. data/lib/ledger_web/public/codemirror/mode/clike/index.html +101 -0
  32. data/lib/ledger_web/public/codemirror/mode/clojure/clojure.js +207 -0
  33. data/lib/ledger_web/public/codemirror/mode/clojure/index.html +66 -0
  34. data/lib/ledger_web/public/codemirror/mode/coffeescript/LICENSE +22 -0
  35. data/lib/ledger_web/public/codemirror/mode/coffeescript/coffeescript.js +325 -0
  36. data/lib/ledger_web/public/codemirror/mode/coffeescript/index.html +721 -0
  37. data/lib/ledger_web/public/codemirror/mode/css/css.js +124 -0
  38. data/lib/ledger_web/public/codemirror/mode/css/index.html +55 -0
  39. data/lib/ledger_web/public/codemirror/mode/diff/diff.css +3 -0
  40. data/lib/ledger_web/public/codemirror/mode/diff/diff.js +13 -0
  41. data/lib/ledger_web/public/codemirror/mode/diff/index.html +99 -0
  42. data/lib/ledger_web/public/codemirror/mode/gfm/gfm.js +108 -0
  43. data/lib/ledger_web/public/codemirror/mode/gfm/index.html +47 -0
  44. data/lib/ledger_web/public/codemirror/mode/groovy/groovy.js +210 -0
  45. data/lib/ledger_web/public/codemirror/mode/groovy/index.html +71 -0
  46. data/lib/ledger_web/public/codemirror/mode/haskell/haskell.js +242 -0
  47. data/lib/ledger_web/public/codemirror/mode/haskell/index.html +60 -0
  48. data/lib/ledger_web/public/codemirror/mode/htmlembedded/htmlembedded.js +68 -0
  49. data/lib/ledger_web/public/codemirror/mode/htmlembedded/index.html +49 -0
  50. data/lib/ledger_web/public/codemirror/mode/htmlmixed/htmlmixed.js +83 -0
  51. data/lib/ledger_web/public/codemirror/mode/htmlmixed/index.html +51 -0
  52. data/lib/ledger_web/public/codemirror/mode/javascript/index.html +77 -0
  53. data/lib/ledger_web/public/codemirror/mode/javascript/javascript.js +360 -0
  54. data/lib/ledger_web/public/codemirror/mode/jinja2/index.html +37 -0
  55. data/lib/ledger_web/public/codemirror/mode/jinja2/jinja2.js +42 -0
  56. data/lib/ledger_web/public/codemirror/mode/lua/index.html +72 -0
  57. data/lib/ledger_web/public/codemirror/mode/lua/lua.js +140 -0
  58. data/lib/ledger_web/public/codemirror/mode/markdown/index.html +339 -0
  59. data/lib/ledger_web/public/codemirror/mode/markdown/markdown.js +242 -0
  60. data/lib/ledger_web/public/codemirror/mode/ntriples/index.html +32 -0
  61. data/lib/ledger_web/public/codemirror/mode/ntriples/ntriples.js +172 -0
  62. data/lib/ledger_web/public/codemirror/mode/pascal/LICENSE +7 -0
  63. data/lib/ledger_web/public/codemirror/mode/pascal/index.html +48 -0
  64. data/lib/ledger_web/public/codemirror/mode/pascal/pascal.js +138 -0
  65. data/lib/ledger_web/public/codemirror/mode/perl/LICENSE +19 -0
  66. data/lib/ledger_web/public/codemirror/mode/perl/index.html +62 -0
  67. data/lib/ledger_web/public/codemirror/mode/perl/perl.js +816 -0
  68. data/lib/ledger_web/public/codemirror/mode/php/index.html +48 -0
  69. data/lib/ledger_web/public/codemirror/mode/php/php.js +120 -0
  70. data/lib/ledger_web/public/codemirror/mode/plsql/index.html +62 -0
  71. data/lib/ledger_web/public/codemirror/mode/plsql/plsql.js +217 -0
  72. data/lib/ledger_web/public/codemirror/mode/python/LICENSE.txt +21 -0
  73. data/lib/ledger_web/public/codemirror/mode/python/index.html +122 -0
  74. data/lib/ledger_web/public/codemirror/mode/python/python.js +333 -0
  75. data/lib/ledger_web/public/codemirror/mode/r/LICENSE +24 -0
  76. data/lib/ledger_web/public/codemirror/mode/r/index.html +73 -0
  77. data/lib/ledger_web/public/codemirror/mode/r/r.js +141 -0
  78. data/lib/ledger_web/public/codemirror/mode/rpm/changes/changes.js +19 -0
  79. data/lib/ledger_web/public/codemirror/mode/rpm/changes/index.html +53 -0
  80. data/lib/ledger_web/public/codemirror/mode/rpm/spec/index.html +99 -0
  81. data/lib/ledger_web/public/codemirror/mode/rpm/spec/spec.css +5 -0
  82. data/lib/ledger_web/public/codemirror/mode/rpm/spec/spec.js +66 -0
  83. data/lib/ledger_web/public/codemirror/mode/rst/index.html +525 -0
  84. data/lib/ledger_web/public/codemirror/mode/rst/rst.js +326 -0
  85. data/lib/ledger_web/public/codemirror/mode/ruby/LICENSE +24 -0
  86. data/lib/ledger_web/public/codemirror/mode/ruby/index.html +171 -0
  87. data/lib/ledger_web/public/codemirror/mode/ruby/ruby.js +195 -0
  88. data/lib/ledger_web/public/codemirror/mode/rust/index.html +48 -0
  89. data/lib/ledger_web/public/codemirror/mode/rust/rust.js +411 -0
  90. data/lib/ledger_web/public/codemirror/mode/scheme/index.html +64 -0
  91. data/lib/ledger_web/public/codemirror/mode/scheme/scheme.js +202 -0
  92. data/lib/ledger_web/public/codemirror/mode/smalltalk/index.html +55 -0
  93. data/lib/ledger_web/public/codemirror/mode/smalltalk/smalltalk.js +139 -0
  94. data/lib/ledger_web/public/codemirror/mode/sparql/index.html +40 -0
  95. data/lib/ledger_web/public/codemirror/mode/sparql/sparql.js +143 -0
  96. data/lib/ledger_web/public/codemirror/mode/stex/index.html +95 -0
  97. data/lib/ledger_web/public/codemirror/mode/stex/stex.js +167 -0
  98. data/lib/ledger_web/public/codemirror/mode/tiddlywiki/index.html +183 -0
  99. data/lib/ledger_web/public/codemirror/mode/tiddlywiki/tiddlywiki.css +21 -0
  100. data/lib/ledger_web/public/codemirror/mode/tiddlywiki/tiddlywiki.js +374 -0
  101. data/lib/ledger_web/public/codemirror/mode/velocity/index.html +103 -0
  102. data/lib/ledger_web/public/codemirror/mode/velocity/velocity.js +146 -0
  103. data/lib/ledger_web/public/codemirror/mode/xml/index.html +44 -0
  104. data/lib/ledger_web/public/codemirror/mode/xml/xml.js +252 -0
  105. data/lib/ledger_web/public/codemirror/mode/xmlpure/index.html +59 -0
  106. data/lib/ledger_web/public/codemirror/mode/xmlpure/xmlpure.js +485 -0
  107. data/lib/ledger_web/public/codemirror/mode/yaml/index.html +67 -0
  108. data/lib/ledger_web/public/codemirror/mode/yaml/yaml.js +95 -0
  109. data/lib/ledger_web/public/codemirror/theme/cobalt.css +18 -0
  110. data/lib/ledger_web/public/codemirror/theme/eclipse.css +25 -0
  111. data/lib/ledger_web/public/codemirror/theme/elegant.css +10 -0
  112. data/lib/ledger_web/public/codemirror/theme/monokai.css +28 -0
  113. data/lib/ledger_web/public/codemirror/theme/neat.css +9 -0
  114. data/lib/ledger_web/public/codemirror/theme/night.css +21 -0
  115. data/lib/ledger_web/public/codemirror/theme/rubyblue.css +21 -0
  116. data/lib/ledger_web/public/jquery-1.7.1.min.js +4 -0
  117. data/lib/ledger_web/public/jquery.tablesorter.min.js +4 -0
  118. data/lib/ledger_web/public/ledger.css +14 -0
  119. data/lib/ledger_web/report.rb +187 -0
  120. data/lib/ledger_web/reports/savings_rate.erb +49 -0
  121. data/lib/ledger_web/version.rb +3 -0
  122. data/lib/ledger_web/views/error.erb +5 -0
  123. data/lib/ledger_web/views/help.erb +6 -0
  124. data/lib/ledger_web/views/layout.erb +44 -0
  125. data/lib/ledger_web/views/table.erb +31 -0
  126. data/lib/ledger_web/watcher.rb +37 -0
  127. data/lib/ledger_web.rb +20 -0
  128. metadata +229 -0
@@ -0,0 +1,124 @@
1
+ CodeMirror.defineMode("css", function(config) {
2
+ var indentUnit = config.indentUnit, type;
3
+ function ret(style, tp) {type = tp; return style;}
4
+
5
+ function tokenBase(stream, state) {
6
+ var ch = stream.next();
7
+ if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
8
+ else if (ch == "/" && stream.eat("*")) {
9
+ state.tokenize = tokenCComment;
10
+ return tokenCComment(stream, state);
11
+ }
12
+ else if (ch == "<" && stream.eat("!")) {
13
+ state.tokenize = tokenSGMLComment;
14
+ return tokenSGMLComment(stream, state);
15
+ }
16
+ else if (ch == "=") ret(null, "compare");
17
+ else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
18
+ else if (ch == "\"" || ch == "'") {
19
+ state.tokenize = tokenString(ch);
20
+ return state.tokenize(stream, state);
21
+ }
22
+ else if (ch == "#") {
23
+ stream.eatWhile(/[\w\\\-]/);
24
+ return ret("atom", "hash");
25
+ }
26
+ else if (ch == "!") {
27
+ stream.match(/^\s*\w*/);
28
+ return ret("keyword", "important");
29
+ }
30
+ else if (/\d/.test(ch)) {
31
+ stream.eatWhile(/[\w.%]/);
32
+ return ret("number", "unit");
33
+ }
34
+ else if (/[,.+>*\/]/.test(ch)) {
35
+ return ret(null, "select-op");
36
+ }
37
+ else if (/[;{}:\[\]]/.test(ch)) {
38
+ return ret(null, ch);
39
+ }
40
+ else {
41
+ stream.eatWhile(/[\w\\\-]/);
42
+ return ret("variable", "variable");
43
+ }
44
+ }
45
+
46
+ function tokenCComment(stream, state) {
47
+ var maybeEnd = false, ch;
48
+ while ((ch = stream.next()) != null) {
49
+ if (maybeEnd && ch == "/") {
50
+ state.tokenize = tokenBase;
51
+ break;
52
+ }
53
+ maybeEnd = (ch == "*");
54
+ }
55
+ return ret("comment", "comment");
56
+ }
57
+
58
+ function tokenSGMLComment(stream, state) {
59
+ var dashes = 0, ch;
60
+ while ((ch = stream.next()) != null) {
61
+ if (dashes >= 2 && ch == ">") {
62
+ state.tokenize = tokenBase;
63
+ break;
64
+ }
65
+ dashes = (ch == "-") ? dashes + 1 : 0;
66
+ }
67
+ return ret("comment", "comment");
68
+ }
69
+
70
+ function tokenString(quote) {
71
+ return function(stream, state) {
72
+ var escaped = false, ch;
73
+ while ((ch = stream.next()) != null) {
74
+ if (ch == quote && !escaped)
75
+ break;
76
+ escaped = !escaped && ch == "\\";
77
+ }
78
+ if (!escaped) state.tokenize = tokenBase;
79
+ return ret("string", "string");
80
+ };
81
+ }
82
+
83
+ return {
84
+ startState: function(base) {
85
+ return {tokenize: tokenBase,
86
+ baseIndent: base || 0,
87
+ stack: []};
88
+ },
89
+
90
+ token: function(stream, state) {
91
+ if (stream.eatSpace()) return null;
92
+ var style = state.tokenize(stream, state);
93
+
94
+ var context = state.stack[state.stack.length-1];
95
+ if (type == "hash" && context == "rule") style = "atom";
96
+ else if (style == "variable") {
97
+ if (context == "rule") style = "number";
98
+ else if (!context || context == "@media{") style = "tag";
99
+ }
100
+
101
+ if (context == "rule" && /^[\{\};]$/.test(type))
102
+ state.stack.pop();
103
+ if (type == "{") {
104
+ if (context == "@media") state.stack[state.stack.length-1] = "@media{";
105
+ else state.stack.push("{");
106
+ }
107
+ else if (type == "}") state.stack.pop();
108
+ else if (type == "@media") state.stack.push("@media");
109
+ else if (context == "{" && type != "comment") state.stack.push("rule");
110
+ return style;
111
+ },
112
+
113
+ indent: function(state, textAfter) {
114
+ var n = state.stack.length;
115
+ if (/^\}/.test(textAfter))
116
+ n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
117
+ return state.baseIndent + n * indentUnit;
118
+ },
119
+
120
+ electricChars: "}"
121
+ };
122
+ });
123
+
124
+ CodeMirror.defineMIME("text/css", "css");
@@ -0,0 +1,55 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>CodeMirror: CSS mode</title>
5
+ <link rel="stylesheet" href="../../lib/codemirror.css">
6
+ <script src="../../lib/codemirror.js"></script>
7
+ <script src="css.js"></script>
8
+ <style>.CodeMirror {background: #f8f8f8;}</style>
9
+ <link rel="stylesheet" href="../../doc/docs.css">
10
+ </head>
11
+ <body>
12
+ <h1>CodeMirror: CSS mode</h1>
13
+ <form><textarea id="code" name="code">
14
+ /* Some example CSS */
15
+
16
+ @import url("something.css");
17
+
18
+ body {
19
+ margin: 0;
20
+ padding: 3em 6em;
21
+ font-family: tahoma, arial, sans-serif;
22
+ color: #000;
23
+ }
24
+
25
+ #navigation a {
26
+ font-weight: bold;
27
+ text-decoration: none !important;
28
+ }
29
+
30
+ h1 {
31
+ font-size: 2.5em;
32
+ }
33
+
34
+ h2 {
35
+ font-size: 1.7em;
36
+ }
37
+
38
+ h1:before, h2:before {
39
+ content: "::";
40
+ }
41
+
42
+ code {
43
+ font-family: courier, monospace;
44
+ font-size: 80%;
45
+ color: #418A8A;
46
+ }
47
+ </textarea></form>
48
+ <script>
49
+ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
50
+ </script>
51
+
52
+ <p><strong>MIME types defined:</strong> <code>text/css</code>.</p>
53
+
54
+ </body>
55
+ </html>
@@ -0,0 +1,3 @@
1
+ span.cm-rangeinfo {color: #a0b;}
2
+ span.cm-minus {color: red;}
3
+ span.cm-plus {color: #2b2;}
@@ -0,0 +1,13 @@
1
+ CodeMirror.defineMode("diff", function() {
2
+ return {
3
+ token: function(stream) {
4
+ var ch = stream.next();
5
+ stream.skipToEnd();
6
+ if (ch == "+") return "plus";
7
+ if (ch == "-") return "minus";
8
+ if (ch == "@") return "rangeinfo";
9
+ }
10
+ };
11
+ });
12
+
13
+ CodeMirror.defineMIME("text/x-diff", "diff");
@@ -0,0 +1,99 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>CodeMirror: Diff mode</title>
5
+ <link rel="stylesheet" href="../../lib/codemirror.css">
6
+ <script src="../../lib/codemirror.js"></script>
7
+ <script src="diff.js"></script>
8
+ <link rel="stylesheet" href="diff.css">
9
+ <style>.CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}</style>
10
+ <link rel="stylesheet" href="../../doc/docs.css">
11
+ </head>
12
+ <body>
13
+ <h1>CodeMirror: Diff mode</h1>
14
+ <form><textarea id="code" name="code">
15
+ diff --git a/index.html b/index.html
16
+ index c1d9156..7764744 100644
17
+ --- a/index.html
18
+ +++ b/index.html
19
+ @@ -95,7 +95,8 @@ StringStream.prototype = {
20
+ <script>
21
+ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
22
+ lineNumbers: true,
23
+ - autoMatchBrackets: true
24
+ + autoMatchBrackets: true,
25
+ + onGutterClick: function(x){console.log(x);}
26
+ });
27
+ </script>
28
+ </body>
29
+ diff --git a/lib/codemirror.js b/lib/codemirror.js
30
+ index 04646a9..9a39cc7 100644
31
+ --- a/lib/codemirror.js
32
+ +++ b/lib/codemirror.js
33
+ @@ -399,10 +399,16 @@ var CodeMirror = (function() {
34
+ }
35
+
36
+ function onMouseDown(e) {
37
+ - var start = posFromMouse(e), last = start;
38
+ + var start = posFromMouse(e), last = start, target = e.target();
39
+ if (!start) return;
40
+ setCursor(start.line, start.ch, false);
41
+ if (e.button() != 1) return;
42
+ + if (target.parentNode == gutter) {
43
+ + if (options.onGutterClick)
44
+ + options.onGutterClick(indexOf(gutter.childNodes, target) + showingFrom);
45
+ + return;
46
+ + }
47
+ +
48
+ if (!focused) onFocus();
49
+
50
+ e.stop();
51
+ @@ -808,7 +814,7 @@ var CodeMirror = (function() {
52
+ for (var i = showingFrom; i < showingTo; ++i) {
53
+ var marker = lines[i].gutterMarker;
54
+ if (marker) html.push('<div class="' + marker.style + '">' + htmlEscape(marker.text) + '</div>');
55
+ - else html.push("<div>" + (options.lineNumbers ? i + 1 : "\u00a0") + "</div>");
56
+ + else html.push("<div>" + (options.lineNumbers ? i + options.firstLineNumber : "\u00a0") + "</div>");
57
+ }
58
+ gutter.style.display = "none"; // TODO test whether this actually helps
59
+ gutter.innerHTML = html.join("");
60
+ @@ -1371,10 +1377,8 @@ var CodeMirror = (function() {
61
+ if (option == "parser") setParser(value);
62
+ else if (option === "lineNumbers") setLineNumbers(value);
63
+ else if (option === "gutter") setGutter(value);
64
+ - else if (option === "readOnly") options.readOnly = value;
65
+ - else if (option === "indentUnit") {options.indentUnit = indentUnit = value; setParser(options.parser);}
66
+ - else if (/^(?:enterMode|tabMode|indentWithTabs|readOnly|autoMatchBrackets|undoDepth)$/.test(option)) options[option] = value;
67
+ - else throw new Error("Can't set option " + option);
68
+ + else if (option === "indentUnit") {options.indentUnit = value; setParser(options.parser);}
69
+ + else options[option] = value;
70
+ },
71
+ cursorCoords: cursorCoords,
72
+ undo: operation(undo),
73
+ @@ -1402,7 +1406,8 @@ var CodeMirror = (function() {
74
+ replaceRange: operation(replaceRange),
75
+
76
+ operation: function(f){return operation(f)();},
77
+ - refresh: function(){updateDisplay([{from: 0, to: lines.length}]);}
78
+ + refresh: function(){updateDisplay([{from: 0, to: lines.length}]);},
79
+ + getInputField: function(){return input;}
80
+ };
81
+ return instance;
82
+ }
83
+ @@ -1420,6 +1425,7 @@ var CodeMirror = (function() {
84
+ readOnly: false,
85
+ onChange: null,
86
+ onCursorActivity: null,
87
+ + onGutterClick: null,
88
+ autoMatchBrackets: false,
89
+ workTime: 200,
90
+ workDelay: 300,
91
+ </textarea></form>
92
+ <script>
93
+ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
94
+ </script>
95
+
96
+ <p><strong>MIME types defined:</strong> <code>text/x-diff</code>.</p>
97
+
98
+ </body>
99
+ </html>
@@ -0,0 +1,108 @@
1
+ CodeMirror.defineMode("gfm", function(config, parserConfig) {
2
+ var mdMode = CodeMirror.getMode(config, "markdown");
3
+ var aliases = {
4
+ html: "htmlmixed",
5
+ js: "javascript",
6
+ json: "application/json",
7
+ c: "text/x-csrc",
8
+ "c++": "text/x-c++src",
9
+ java: "text/x-java",
10
+ csharp: "text/x-csharp",
11
+ "c#": "text/x-csharp",
12
+ };
13
+
14
+ // make this lazy so that we don't need to load GFM last
15
+ var getMode = (function () {
16
+ var i, modes = {}, mimes = {}, mime;
17
+
18
+ var list = CodeMirror.listModes();
19
+ for (i = 0; i < list.length; i++) {
20
+ modes[list[i]] = list[i];
21
+ }
22
+ var mimesList = CodeMirror.listMIMEs();
23
+ for (i = 0; i < mimesList.length; i++) {
24
+ mime = mimesList[i].mime;
25
+ mimes[mime] = mimesList[i].mime;
26
+ }
27
+
28
+ for (var a in aliases) {
29
+ if (aliases[a] in modes || aliases[a] in mimes)
30
+ modes[a] = aliases[a];
31
+ }
32
+
33
+ return function (lang) {
34
+ return modes[lang] ? CodeMirror.getMode(config, modes[lang]) : null;
35
+ }
36
+ }());
37
+
38
+ function markdown(stream, state) {
39
+ // intercept fenced code blocks
40
+ if (stream.sol() && stream.match(/^```([\w+#]*)/)) {
41
+ // try switching mode
42
+ state.localMode = getMode(RegExp.$1)
43
+ if (state.localMode)
44
+ state.localState = state.localMode.startState();
45
+
46
+ state.token = local;
47
+ return 'code';
48
+ }
49
+
50
+ return mdMode.token(stream, state.mdState);
51
+ }
52
+
53
+ function local(stream, state) {
54
+ if (stream.sol() && stream.match(/^```/)) {
55
+ state.localMode = state.localState = null;
56
+ state.token = markdown;
57
+ return 'code';
58
+ }
59
+ else if (state.localMode) {
60
+ return state.localMode.token(stream, state.localState);
61
+ } else {
62
+ stream.skipToEnd();
63
+ return 'code';
64
+ }
65
+ }
66
+
67
+ // custom handleText to prevent emphasis in the middle of a word
68
+ // and add autolinking
69
+ function handleText(stream, mdState) {
70
+ var match;
71
+ if (stream.match(/^\w+:\/\/\S+/)) {
72
+ return 'linkhref';
73
+ }
74
+ if (stream.match(/^[^\[*\\<>` _][^\[*\\<>` ]*[^\[*\\<>` _]/)) {
75
+ return mdMode.getType(mdState);
76
+ }
77
+ if (match = stream.match(/^[^\[*\\<>` ]+/)) {
78
+ var word = match[0];
79
+ if (word[0] === '_' && word[word.length-1] === '_') {
80
+ stream.backUp(word.length);
81
+ return undefined;
82
+ }
83
+ return mdMode.getType(mdState);
84
+ }
85
+ if (stream.eatSpace()) {
86
+ return null;
87
+ }
88
+ }
89
+
90
+ return {
91
+ startState: function() {
92
+ var mdState = mdMode.startState();
93
+ mdState.text = handleText;
94
+ return {token: markdown, mode: "markdown", mdState: mdState,
95
+ localMode: null, localState: null};
96
+ },
97
+
98
+ copyState: function(state) {
99
+ return {token: state.token, mode: state.mode, mdState: CodeMirror.copyState(mdMode, state.mdState),
100
+ localMode: state.localMode,
101
+ localState: state.localMode ? CodeMirror.copyState(state.localMode, state.localState) : null};
102
+ },
103
+
104
+ token: function(stream, state) {
105
+ return state.token(stream, state);
106
+ }
107
+ }
108
+ });
@@ -0,0 +1,47 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>CodeMirror: GFM mode</title>
5
+ <link rel="stylesheet" href="../../lib/codemirror.css">
6
+ <script src="../../lib/codemirror.js"></script>
7
+ <script src="../xml/xml.js"></script>
8
+ <script src="../markdown/markdown.js"></script>
9
+ <script src="gfm.js"></script>
10
+ <script src="../javascript/javascript.js"></script>
11
+ <link rel="stylesheet" href="../markdown/markdown.css">
12
+ <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
13
+ <link rel="stylesheet" href="../../doc/docs.css">
14
+ </head>
15
+ <body>
16
+ <h1>CodeMirror: GFM mode</h1>
17
+
18
+ <!-- source: http://daringfireball.net/projects/markdown/basics.text -->
19
+ <form><textarea id="code" name="code">
20
+ Github Flavored Markdown
21
+ ========================
22
+
23
+ Everything from markdown plus GFM features:
24
+
25
+ ## Fenced code blocks
26
+
27
+ ```javascript
28
+ for (var i = 0; i &lt; items.length; i++) {
29
+ console.log(items[i], i); // log them
30
+ }
31
+ ```
32
+
33
+ See http://github.github.com/github-flavored-markdown/
34
+
35
+ </textarea></form>
36
+
37
+ <script>
38
+ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
39
+ mode: 'gfm',
40
+ lineNumbers: true,
41
+ matchBrackets: true,
42
+ theme: "default"
43
+ });
44
+ </script>
45
+
46
+ </body>
47
+ </html>
@@ -0,0 +1,210 @@
1
+ CodeMirror.defineMode("groovy", function(config, parserConfig) {
2
+ function words(str) {
3
+ var obj = {}, words = str.split(" ");
4
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5
+ return obj;
6
+ }
7
+ var keywords = words(
8
+ "abstract as assert boolean break byte case catch char class const continue def default " +
9
+ "do double else enum extends final finally float for goto if implements import in " +
10
+ "instanceof int interface long native new package private protected public return " +
11
+ "short static strictfp super switch synchronized threadsafe throw throws transient " +
12
+ "try void volatile while");
13
+ var blockKeywords = words("catch class do else finally for if switch try while enum interface def");
14
+ var atoms = words("null true false this");
15
+
16
+ var curPunc;
17
+ function tokenBase(stream, state) {
18
+ var ch = stream.next();
19
+ if (ch == '"' || ch == "'") {
20
+ return startString(ch, stream, state);
21
+ }
22
+ if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
23
+ curPunc = ch;
24
+ return null
25
+ }
26
+ if (/\d/.test(ch)) {
27
+ stream.eatWhile(/[\w\.]/);
28
+ if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); }
29
+ return "number";
30
+ }
31
+ if (ch == "/") {
32
+ if (stream.eat("*")) {
33
+ state.tokenize.push(tokenComment);
34
+ return tokenComment(stream, state);
35
+ }
36
+ if (stream.eat("/")) {
37
+ stream.skipToEnd();
38
+ return "comment";
39
+ }
40
+ if (expectExpression(state.lastToken)) {
41
+ return startString(ch, stream, state);
42
+ }
43
+ }
44
+ if (ch == "-" && stream.eat(">")) {
45
+ curPunc = "->";
46
+ return null;
47
+ }
48
+ if (/[+\-*&%=<>!?|\/~]/.test(ch)) {
49
+ stream.eatWhile(/[+\-*&%=<>|~]/);
50
+ return "operator";
51
+ }
52
+ stream.eatWhile(/[\w\$_]/);
53
+ if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; }
54
+ if (state.lastToken == ".") return "property";
55
+ if (stream.eat(":")) { curPunc = "proplabel"; return "property"; }
56
+ var cur = stream.current();
57
+ if (atoms.propertyIsEnumerable(cur)) { return "atom"; }
58
+ if (keywords.propertyIsEnumerable(cur)) {
59
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
60
+ return "keyword";
61
+ }
62
+ return "word";
63
+ }
64
+ tokenBase.isBase = true;
65
+
66
+ function startString(quote, stream, state) {
67
+ var tripleQuoted = false;
68
+ if (quote != "/" && stream.eat(quote)) {
69
+ if (stream.eat(quote)) tripleQuoted = true;
70
+ else return "string";
71
+ }
72
+ function t(stream, state) {
73
+ var escaped = false, next, end = !tripleQuoted;
74
+ while ((next = stream.next()) != null) {
75
+ if (next == quote && !escaped) {
76
+ if (!tripleQuoted) { break; }
77
+ if (stream.match(quote + quote)) { end = true; break; }
78
+ }
79
+ if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
80
+ state.tokenize.push(tokenBaseUntilBrace());
81
+ return "string";
82
+ }
83
+ escaped = !escaped && next == "\\";
84
+ }
85
+ if (end) state.tokenize.pop();
86
+ return "string";
87
+ }
88
+ state.tokenize.push(t);
89
+ return t(stream, state);
90
+ }
91
+
92
+ function tokenBaseUntilBrace() {
93
+ var depth = 1;
94
+ function t(stream, state) {
95
+ if (stream.peek() == "}") {
96
+ depth--;
97
+ if (depth == 0) {
98
+ state.tokenize.pop();
99
+ return state.tokenize[state.tokenize.length-1](stream, state);
100
+ }
101
+ } else if (stream.peek() == "{") {
102
+ depth++;
103
+ }
104
+ return tokenBase(stream, state);
105
+ }
106
+ t.isBase = true;
107
+ return t;
108
+ }
109
+
110
+ function tokenComment(stream, state) {
111
+ var maybeEnd = false, ch;
112
+ while (ch = stream.next()) {
113
+ if (ch == "/" && maybeEnd) {
114
+ state.tokenize.pop();
115
+ break;
116
+ }
117
+ maybeEnd = (ch == "*");
118
+ }
119
+ return "comment";
120
+ }
121
+
122
+ function expectExpression(last) {
123
+ return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
124
+ last == "newstatement" || last == "keyword" || last == "proplabel";
125
+ }
126
+
127
+ function Context(indented, column, type, align, prev) {
128
+ this.indented = indented;
129
+ this.column = column;
130
+ this.type = type;
131
+ this.align = align;
132
+ this.prev = prev;
133
+ }
134
+ function pushContext(state, col, type) {
135
+ return state.context = new Context(state.indented, col, type, null, state.context);
136
+ }
137
+ function popContext(state) {
138
+ var t = state.context.type;
139
+ if (t == ")" || t == "]" || t == "}")
140
+ state.indented = state.context.indented;
141
+ return state.context = state.context.prev;
142
+ }
143
+
144
+ // Interface
145
+
146
+ return {
147
+ startState: function(basecolumn) {
148
+ return {
149
+ tokenize: [tokenBase],
150
+ context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
151
+ indented: 0,
152
+ startOfLine: true,
153
+ lastToken: null
154
+ };
155
+ },
156
+
157
+ token: function(stream, state) {
158
+ var ctx = state.context;
159
+ if (stream.sol()) {
160
+ if (ctx.align == null) ctx.align = false;
161
+ state.indented = stream.indentation();
162
+ state.startOfLine = true;
163
+ // Automatic semicolon insertion
164
+ if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
165
+ popContext(state); ctx = state.context;
166
+ }
167
+ }
168
+ if (stream.eatSpace()) return null;
169
+ curPunc = null;
170
+ var style = state.tokenize[state.tokenize.length-1](stream, state);
171
+ if (style == "comment") return style;
172
+ if (ctx.align == null) ctx.align = true;
173
+
174
+ if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
175
+ // Handle indentation for {x -> \n ... }
176
+ else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
177
+ popContext(state);
178
+ state.context.align = false;
179
+ }
180
+ else if (curPunc == "{") pushContext(state, stream.column(), "}");
181
+ else if (curPunc == "[") pushContext(state, stream.column(), "]");
182
+ else if (curPunc == "(") pushContext(state, stream.column(), ")");
183
+ else if (curPunc == "}") {
184
+ while (ctx.type == "statement") ctx = popContext(state);
185
+ if (ctx.type == "}") ctx = popContext(state);
186
+ while (ctx.type == "statement") ctx = popContext(state);
187
+ }
188
+ else if (curPunc == ctx.type) popContext(state);
189
+ else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
190
+ pushContext(state, stream.column(), "statement");
191
+ state.startOfLine = false;
192
+ state.lastToken = curPunc || style;
193
+ return style;
194
+ },
195
+
196
+ indent: function(state, textAfter) {
197
+ if (!state.tokenize[state.tokenize.length-1].isBase) return 0;
198
+ var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
199
+ if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
200
+ var closing = firstChar == ctx.type;
201
+ if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
202
+ else if (ctx.align) return ctx.column + (closing ? 0 : 1);
203
+ else return ctx.indented + (closing ? 0 : config.indentUnit);
204
+ },
205
+
206
+ electricChars: "{}"
207
+ };
208
+ });
209
+
210
+ CodeMirror.defineMIME("text/x-groovy", "groovy");