aboutsummaryrefslogtreecommitdiff
path: root/js/codemirror/mode/rst/rst.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/codemirror/mode/rst/rst.js')
-rw-r--r--js/codemirror/mode/rst/rst.js333
1 files changed, 333 insertions, 0 deletions
diff --git a/js/codemirror/mode/rst/rst.js b/js/codemirror/mode/rst/rst.js
new file mode 100644
index 00000000..eecc5bea
--- /dev/null
+++ b/js/codemirror/mode/rst/rst.js
@@ -0,0 +1,333 @@
1CodeMirror.defineMode('rst', function(config, options) {
2 function setState(state, fn, ctx) {
3 state.fn = fn;
4 setCtx(state, ctx);
5 }
6
7 function setCtx(state, ctx) {
8 state.ctx = ctx || {};
9 }
10
11 function setNormal(state, ch) {
12 if (ch && (typeof ch !== 'string')) {
13 var str = ch.current();
14 ch = str[str.length-1];
15 }
16
17 setState(state, normal, {back: ch});
18 }
19
20 function hasMode(mode) {
21 if (mode) {
22 var modes = CodeMirror.listModes();
23
24 for (var i in modes) {
25 if (modes[i] == mode) {
26 return true;
27 }
28 }
29 }
30
31 return false;
32 }
33
34 function getMode(mode) {
35 if (hasMode(mode)) {
36 return CodeMirror.getMode(config, mode);
37 } else {
38 return null;
39 }
40 }
41
42 var verbatimMode = getMode(options.verbatim);
43 var pythonMode = getMode('python');
44
45 var reSection = /^[!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]/;
46 var reDirective = /^\s*\w([-:.\w]*\w)?::(\s|$)/;
47 var reHyperlink = /^\s*_[\w-]+:(\s|$)/;
48 var reFootnote = /^\s*\[(\d+|#)\](\s|$)/;
49 var reCitation = /^\s*\[[A-Za-z][\w-]*\](\s|$)/;
50 var reFootnoteRef = /^\[(\d+|#)\]_/;
51 var reCitationRef = /^\[[A-Za-z][\w-]*\]_/;
52 var reDirectiveMarker = /^\.\.(\s|$)/;
53 var reVerbatimMarker = /^::\s*$/;
54 var rePreInline = /^[-\s"([{</:]/;
55 var rePostInline = /^[-\s`'")\]}>/:.,;!?\\_]/;
56 var reEnumeratedList = /^\s*((\d+|[A-Za-z#])[.)]|\((\d+|[A-Z-a-z#])\))\s/;
57 var reBulletedList = /^\s*[-\+\*]\s/;
58 var reExamples = /^\s+(>>>|In \[\d+\]:)\s/;
59
60 function normal(stream, state) {
61 var ch, sol, i;
62
63 if (stream.eat(/\\/)) {
64 ch = stream.next();
65 setNormal(state, ch);
66 return null;
67 }
68
69 sol = stream.sol();
70
71 if (sol && (ch = stream.eat(reSection))) {
72 for (i = 0; stream.eat(ch); i++);
73
74 if (i >= 3 && stream.match(/^\s*$/)) {
75 setNormal(state, null);
76 return 'section';
77 } else {
78 stream.backUp(i + 1);
79 }
80 }
81
82 if (sol && stream.match(reDirectiveMarker)) {
83 if (!stream.eol()) {
84 setState(state, directive);
85 }
86
87 return 'directive-marker';
88 }
89
90 if (stream.match(reVerbatimMarker)) {
91 if (!verbatimMode) {
92 setState(state, verbatim);
93 } else {
94 var mode = verbatimMode;
95
96 setState(state, verbatim, {
97 mode: mode,
98 local: mode.startState()
99 });
100 }
101
102 return 'verbatim-marker';
103 }
104
105 if (sol && stream.match(reExamples, false)) {
106 if (!pythonMode) {
107 setState(state, verbatim);
108 return 'verbatim-marker';
109 } else {
110 var mode = pythonMode;
111
112 setState(state, verbatim, {
113 mode: mode,
114 local: mode.startState()
115 });
116
117 return null;
118 }
119 }
120
121 if (sol && (stream.match(reEnumeratedList) ||
122 stream.match(reBulletedList))) {
123 setNormal(state, stream);
124 return 'list';
125 }
126
127 function testBackward(re) {
128 return sol || !state.ctx.back || re.test(state.ctx.back);
129 }
130
131 function testForward(re) {
132 return stream.eol() || stream.match(re, false);
133 }
134
135 function testInline(re) {
136 return stream.match(re) && testBackward(/\W/) && testForward(/\W/);
137 }
138
139 if (testInline(reFootnoteRef)) {
140 setNormal(state, stream);
141 return 'footnote';
142 }
143
144 if (testInline(reCitationRef)) {
145 setNormal(state, stream);
146 return 'citation';
147 }
148
149 ch = stream.next();
150
151 if (testBackward(rePreInline)) {
152 if ((ch === ':' || ch === '|') && stream.eat(/\S/)) {
153 var token;
154
155 if (ch === ':') {
156 token = 'role';
157 } else {
158 token = 'replacement';
159 }
160
161 setState(state, inline, {
162 ch: ch,
163 wide: false,
164 prev: null,
165 token: token
166 });
167
168 return token;
169 }
170
171 if (ch === '*' || ch === '`') {
172 var orig = ch,
173 wide = false;
174
175 ch = stream.next();
176
177 if (ch == orig) {
178 wide = true;
179 ch = stream.next();
180 }
181
182 if (ch && !/\s/.test(ch)) {
183 var token;
184
185 if (orig === '*') {
186 token = wide ? 'strong' : 'emphasis';
187 } else {
188 token = wide ? 'inline' : 'interpreted';
189 }
190
191 setState(state, inline, {
192 ch: orig, // inline() has to know what to search for
193 wide: wide, // are we looking for `ch` or `chch`
194 prev: null, // terminator must not be preceeded with whitespace
195 token: token // I don't want to recompute this all the time
196 });
197
198 return token;
199 }
200 }
201 }
202
203 setNormal(state, ch);
204 return null;
205 }
206
207 function inline(stream, state) {
208 var ch = stream.next(),
209 token = state.ctx.token;
210
211 function finish(ch) {
212 state.ctx.prev = ch;
213 return token;
214 }
215
216 if (ch != state.ctx.ch) {
217 return finish(ch);
218 }
219
220 if (/\s/.test(state.ctx.prev)) {
221 return finish(ch);
222 }
223
224 if (state.ctx.wide) {
225 ch = stream.next();
226
227 if (ch != state.ctx.ch) {
228 return finish(ch);
229 }
230 }
231
232 if (!stream.eol() && !rePostInline.test(stream.peek())) {
233 if (state.ctx.wide) {
234 stream.backUp(1);
235 }
236
237 return finish(ch);
238 }
239
240 setState(state, normal);
241 setNormal(state, ch);
242
243 return token;
244 }
245
246 function directive(stream, state) {
247 var token = null;
248
249 if (stream.match(reDirective)) {