source: node_modules/highlight.js/lib/languages/ruby.js@ 65b6638

main
Last change on this file since 65b6638 was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 8.6 KB
Line 
1/**
2 * @param {string} value
3 * @returns {RegExp}
4 * */
5
6/**
7 * @param {RegExp | string } re
8 * @returns {string}
9 */
10function source(re) {
11 if (!re) return null;
12 if (typeof re === "string") return re;
13
14 return re.source;
15}
16
17/**
18 * @param {RegExp | string } re
19 * @returns {string}
20 */
21function lookahead(re) {
22 return concat('(?=', re, ')');
23}
24
25/**
26 * @param {...(RegExp | string) } args
27 * @returns {string}
28 */
29function concat(...args) {
30 const joined = args.map((x) => source(x)).join("");
31 return joined;
32}
33
34/*
35Language: Ruby
36Description: Ruby is a dynamic, open source programming language with a focus on simplicity and productivity.
37Website: https://www.ruby-lang.org/
38Author: Anton Kovalyov <anton@kovalyov.net>
39Contributors: Peter Leonov <gojpeg@yandex.ru>, Vasily Polovnyov <vast@whiteants.net>, Loren Segal <lsegal@soen.ca>, Pascal Hurni <phi@ruby-reactive.org>, Cedric Sohrauer <sohrauer@googlemail.com>
40Category: common
41*/
42
43function ruby(hljs) {
44 const RUBY_METHOD_RE = '([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)';
45 const RUBY_KEYWORDS = {
46 keyword:
47 'and then defined module in return redo if BEGIN retry end for self when ' +
48 'next until do begin unless END rescue else break undef not super class case ' +
49 'require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor ' +
50 '__FILE__',
51 built_in: 'proc lambda',
52 literal:
53 'true false nil'
54 };
55 const YARDOCTAG = {
56 className: 'doctag',
57 begin: '@[A-Za-z]+'
58 };
59 const IRB_OBJECT = {
60 begin: '#<',
61 end: '>'
62 };
63 const COMMENT_MODES = [
64 hljs.COMMENT(
65 '#',
66 '$',
67 {
68 contains: [ YARDOCTAG ]
69 }
70 ),
71 hljs.COMMENT(
72 '^=begin',
73 '^=end',
74 {
75 contains: [ YARDOCTAG ],
76 relevance: 10
77 }
78 ),
79 hljs.COMMENT('^__END__', '\\n$')
80 ];
81 const SUBST = {
82 className: 'subst',
83 begin: /#\{/,
84 end: /\}/,
85 keywords: RUBY_KEYWORDS
86 };
87 const STRING = {
88 className: 'string',
89 contains: [
90 hljs.BACKSLASH_ESCAPE,
91 SUBST
92 ],
93 variants: [
94 {
95 begin: /'/,
96 end: /'/
97 },
98 {
99 begin: /"/,
100 end: /"/
101 },
102 {
103 begin: /`/,
104 end: /`/
105 },
106 {
107 begin: /%[qQwWx]?\(/,
108 end: /\)/
109 },
110 {
111 begin: /%[qQwWx]?\[/,
112 end: /\]/
113 },
114 {
115 begin: /%[qQwWx]?\{/,
116 end: /\}/
117 },
118 {
119 begin: /%[qQwWx]?</,
120 end: />/
121 },
122 {
123 begin: /%[qQwWx]?\//,
124 end: /\//
125 },
126 {
127 begin: /%[qQwWx]?%/,
128 end: /%/
129 },
130 {
131 begin: /%[qQwWx]?-/,
132 end: /-/
133 },
134 {
135 begin: /%[qQwWx]?\|/,
136 end: /\|/
137 },
138 // in the following expressions, \B in the beginning suppresses recognition of ?-sequences
139 // where ? is the last character of a preceding identifier, as in: `func?4`
140 {
141 begin: /\B\?(\\\d{1,3})/
142 },
143 {
144 begin: /\B\?(\\x[A-Fa-f0-9]{1,2})/
145 },
146 {
147 begin: /\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/
148 },
149 {
150 begin: /\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/
151 },
152 {
153 begin: /\B\?\\(c|C-)[\x20-\x7e]/
154 },
155 {
156 begin: /\B\?\\?\S/
157 },
158 { // heredocs
159 begin: /<<[-~]?'?(\w+)\n(?:[^\n]*\n)*?\s*\1\b/,
160 returnBegin: true,
161 contains: [
162 {
163 begin: /<<[-~]?'?/
164 },
165 hljs.END_SAME_AS_BEGIN({
166 begin: /(\w+)/,
167 end: /(\w+)/,
168 contains: [
169 hljs.BACKSLASH_ESCAPE,
170 SUBST
171 ]
172 })
173 ]
174 }
175 ]
176 };
177
178 // Ruby syntax is underdocumented, but this grammar seems to be accurate
179 // as of version 2.7.2 (confirmed with (irb and `Ripper.sexp(...)`)
180 // https://docs.ruby-lang.org/en/2.7.0/doc/syntax/literals_rdoc.html#label-Numbers
181 const decimal = '[1-9](_?[0-9])*|0';
182 const digits = '[0-9](_?[0-9])*';
183 const NUMBER = {
184 className: 'number',
185 relevance: 0,
186 variants: [
187 // decimal integer/float, optionally exponential or rational, optionally imaginary
188 {
189 begin: `\\b(${decimal})(\\.(${digits}))?([eE][+-]?(${digits})|r)?i?\\b`
190 },
191
192 // explicit decimal/binary/octal/hexadecimal integer,
193 // optionally rational and/or imaginary
194 {
195 begin: "\\b0[dD][0-9](_?[0-9])*r?i?\\b"
196 },
197 {
198 begin: "\\b0[bB][0-1](_?[0-1])*r?i?\\b"
199 },
200 {
201 begin: "\\b0[oO][0-7](_?[0-7])*r?i?\\b"
202 },
203 {
204 begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"
205 },
206
207 // 0-prefixed implicit octal integer, optionally rational and/or imaginary
208 {
209 begin: "\\b0(_?[0-7])+r?i?\\b"
210 }
211 ]
212 };
213
214 const PARAMS = {
215 className: 'params',
216 begin: '\\(',
217 end: '\\)',
218 endsParent: true,
219 keywords: RUBY_KEYWORDS
220 };
221
222 const RUBY_DEFAULT_CONTAINS = [
223 STRING,
224 {
225 className: 'class',
226 beginKeywords: 'class module',
227 end: '$|;',
228 illegal: /=/,
229 contains: [
230 hljs.inherit(hljs.TITLE_MODE, {
231 begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|!)?'
232 }),
233 {
234 begin: '<\\s*',
235 contains: [
236 {
237 begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE,
238 // we already get points for <, we don't need poitns
239 // for the name also
240 relevance: 0
241 }
242 ]
243 }
244 ].concat(COMMENT_MODES)
245 },
246 {
247 className: 'function',
248 // def method_name(
249 // def method_name;
250 // def method_name (end of line)
251 begin: concat(/def\s+/, lookahead(RUBY_METHOD_RE + "\\s*(\\(|;|$)")),
252 relevance: 0, // relevance comes from kewords
253 keywords: "def",
254 end: '$|;',
255 contains: [
256 hljs.inherit(hljs.TITLE_MODE, {
257 begin: RUBY_METHOD_RE
258 }),
259 PARAMS
260 ].concat(COMMENT_MODES)
261 },
262 {
263 // swallow namespace qualifiers before symbols
264 begin: hljs.IDENT_RE + '::'
265 },
266 {
267 className: 'symbol',
268 begin: hljs.UNDERSCORE_IDENT_RE + '(!|\\?)?:',
269 relevance: 0
270 },
271 {
272 className: 'symbol',
273 begin: ':(?!\\s)',
274 contains: [
275 STRING,
276 {
277 begin: RUBY_METHOD_RE
278 }
279 ],
280 relevance: 0
281 },
282 NUMBER,
283 {
284 // negative-look forward attemps to prevent false matches like:
285 // @ident@ or $ident$ that might indicate this is not ruby at all
286 className: "variable",
287 begin: '(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])' + `(?![A-Za-z])(?![@$?'])`
288 },
289 {
290 className: 'params',
291 begin: /\|/,
292 end: /\|/,
293 relevance: 0, // this could be a lot of things (in other languages) other than params
294 keywords: RUBY_KEYWORDS
295 },
296 { // regexp container
297 begin: '(' + hljs.RE_STARTERS_RE + '|unless)\\s*',
298 keywords: 'unless',
299 contains: [
300 {
301 className: 'regexp',
302 contains: [
303 hljs.BACKSLASH_ESCAPE,
304 SUBST
305 ],
306 illegal: /\n/,
307 variants: [
308 {
309 begin: '/',
310 end: '/[a-z]*'
311 },
312 {
313 begin: /%r\{/,
314 end: /\}[a-z]*/
315 },
316 {
317 begin: '%r\\(',
318 end: '\\)[a-z]*'
319 },
320 {
321 begin: '%r!',
322 end: '![a-z]*'
323 },
324 {
325 begin: '%r\\[',
326 end: '\\][a-z]*'
327 }
328 ]
329 }
330 ].concat(IRB_OBJECT, COMMENT_MODES),
331 relevance: 0
332 }
333 ].concat(IRB_OBJECT, COMMENT_MODES);
334
335 SUBST.contains = RUBY_DEFAULT_CONTAINS;
336 PARAMS.contains = RUBY_DEFAULT_CONTAINS;
337
338 // >>
339 // ?>
340 const SIMPLE_PROMPT = "[>?]>";
341 // irb(main):001:0>
342 const DEFAULT_PROMPT = "[\\w#]+\\(\\w+\\):\\d+:\\d+>";
343 const RVM_PROMPT = "(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>";
344
345 const IRB_DEFAULT = [
346 {
347 begin: /^\s*=>/,
348 starts: {
349 end: '$',
350 contains: RUBY_DEFAULT_CONTAINS
351 }
352 },
353 {
354 className: 'meta',
355 begin: '^(' + SIMPLE_PROMPT + "|" + DEFAULT_PROMPT + '|' + RVM_PROMPT + ')(?=[ ])',
356 starts: {
357 end: '$',
358 contains: RUBY_DEFAULT_CONTAINS
359 }
360 }
361 ];
362
363 COMMENT_MODES.unshift(IRB_OBJECT);
364
365 return {
366 name: 'Ruby',
367 aliases: [
368 'rb',
369 'gemspec',
370 'podspec',
371 'thor',
372 'irb'
373 ],
374 keywords: RUBY_KEYWORDS,
375 illegal: /\/\*/,
376 contains: [
377 hljs.SHEBANG({
378 binary: "ruby"
379 })
380 ]
381 .concat(IRB_DEFAULT)
382 .concat(COMMENT_MODES)
383 .concat(RUBY_DEFAULT_CONTAINS)
384 };
385}
386
387module.exports = ruby;
Note: See TracBrowser for help on using the repository browser.