diff options
Diffstat (limited to 'js/codemirror/mode/rst/rst.js')
-rw-r--r-- | js/codemirror/mode/rst/rst.js | 333 |
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 @@ | |||
1 | CodeMirror.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)) { | ||