| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- /**
- * @param {string} value
- * @returns {RegExp}
- * */
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function source(re) {
- if (!re) return null;
- if (typeof re === "string") return re;
- return re.source;
- }
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function lookahead(re) {
- return concat('(?=', re, ')');
- }
- /**
- * @param {...(RegExp | string) } args
- * @returns {string}
- */
- function concat(...args) {
- const joined = args.map((x) => source(x)).join("");
- return joined;
- }
- /*
- Language: Ruby
- Description: Ruby is a dynamic, open source programming language with a focus on simplicity and productivity.
- Website: https://www.ruby-lang.org/
- Author: Anton Kovalyov <anton@kovalyov.net>
- Contributors: 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>
- Category: common
- */
- function ruby(hljs) {
- var RUBY_METHOD_RE = '([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)';
- var RUBY_KEYWORDS = {
- keyword:
- 'and then defined module in return redo if BEGIN retry end for self when ' +
- 'next until do begin unless END rescue else break undef not super class case ' +
- 'require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor ' +
- '__FILE__',
- built_in: 'proc lambda',
- literal:
- 'true false nil'
- };
- var YARDOCTAG = {
- className: 'doctag',
- begin: '@[A-Za-z]+'
- };
- var IRB_OBJECT = {
- begin: '#<', end: '>'
- };
- var COMMENT_MODES = [
- hljs.COMMENT(
- '#',
- '$',
- {
- contains: [YARDOCTAG]
- }
- ),
- hljs.COMMENT(
- '^=begin',
- '^=end',
- {
- contains: [YARDOCTAG],
- relevance: 10
- }
- ),
- hljs.COMMENT('^__END__', '\\n$')
- ];
- var SUBST = {
- className: 'subst',
- begin: /#\{/, end: /\}/,
- keywords: RUBY_KEYWORDS
- };
- var STRING = {
- className: 'string',
- contains: [hljs.BACKSLASH_ESCAPE, SUBST],
- variants: [
- {begin: /'/, end: /'/},
- {begin: /"/, end: /"/},
- {begin: /`/, end: /`/},
- {begin: /%[qQwWx]?\(/, end: /\)/},
- {begin: /%[qQwWx]?\[/, end: /\]/},
- {begin: /%[qQwWx]?\{/, end: /\}/},
- {begin: /%[qQwWx]?</, end: />/},
- {begin: /%[qQwWx]?\//, end: /\//},
- {begin: /%[qQwWx]?%/, end: /%/},
- {begin: /%[qQwWx]?-/, end: /-/},
- {begin: /%[qQwWx]?\|/, end: /\|/},
- {
- // \B in the beginning suppresses recognition of ?-sequences where ?
- // is the last character of a preceding identifier, as in: `func?4`
- begin: /\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/
- },
- { // heredocs
- begin: /<<[-~]?'?(\w+)\n(?:[^\n]*\n)*?\s*\1\b/,
- returnBegin: true,
- contains: [
- { begin: /<<[-~]?'?/ },
- hljs.END_SAME_AS_BEGIN({
- begin: /(\w+)/, end: /(\w+)/,
- contains: [hljs.BACKSLASH_ESCAPE, SUBST],
- })
- ]
- }
- ]
- };
- // Ruby syntax is underdocumented, but this grammar seems to be accurate
- // as of version 2.7.2 (confirmed with (irb and `Ripper.sexp(...)`)
- // https://docs.ruby-lang.org/en/2.7.0/doc/syntax/literals_rdoc.html#label-Numbers
- var decimal = '[1-9](_?[0-9])*|0';
- var digits = '[0-9](_?[0-9])*';
- var NUMBER = {
- className: 'number', relevance: 0,
- variants: [
- // decimal integer/float, optionally exponential or rational, optionally imaginary
- { begin: `\\b(${decimal})(\\.(${digits}))?([eE][+-]?(${digits})|r)?i?\\b` },
- // explicit decimal/binary/octal/hexadecimal integer,
- // optionally rational and/or imaginary
- { begin: "\\b0[dD][0-9](_?[0-9])*r?i?\\b" },
- { begin: "\\b0[bB][0-1](_?[0-1])*r?i?\\b" },
- { begin: "\\b0[oO][0-7](_?[0-7])*r?i?\\b" },
- { begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b" },
- // 0-prefixed implicit octal integer, optionally rational and/or imaginary
- { begin: "\\b0(_?[0-7])+r?i?\\b" },
- ]
- };
- var PARAMS = {
- className: 'params',
- begin: '\\(', end: '\\)', endsParent: true,
- keywords: RUBY_KEYWORDS
- };
- var RUBY_DEFAULT_CONTAINS = [
- STRING,
- {
- className: 'class',
- beginKeywords: 'class module', end: '$|;',
- illegal: /=/,
- contains: [
- hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|!)?'}),
- {
- begin: '<\\s*',
- contains: [{
- begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE
- }]
- }
- ].concat(COMMENT_MODES)
- },
- {
- className: 'function',
- // def method_name(
- // def method_name;
- // def method_name (end of line)
- begin: concat(/def\s*/, lookahead(RUBY_METHOD_RE + "\\s*(\\(|;|$)")),
- keywords: "def",
- end: '$|;',
- contains: [
- hljs.inherit(hljs.TITLE_MODE, {begin: RUBY_METHOD_RE}),
- PARAMS
- ].concat(COMMENT_MODES)
- },
- {
- // swallow namespace qualifiers before symbols
- begin: hljs.IDENT_RE + '::'
- },
- {
- className: 'symbol',
- begin: hljs.UNDERSCORE_IDENT_RE + '(!|\\?)?:',
- relevance: 0
- },
- {
- className: 'symbol',
- begin: ':(?!\\s)',
- contains: [STRING, {begin: RUBY_METHOD_RE}],
- relevance: 0
- },
- NUMBER,
- {
- // negative-look forward attemps to prevent false matches like:
- // @ident@ or $ident$ that might indicate this is not ruby at all
- className: "variable",
- begin: '(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])' + `(?![A-Za-z])(?![@$?'])`
- },
- {
- className: 'params',
- begin: /\|/,
- end: /\|/,
- relevance:0, // this could be a lot of things (in other languages) other than params
- keywords: RUBY_KEYWORDS
- },
- { // regexp container
- begin: '(' + hljs.RE_STARTERS_RE + '|unless)\\s*',
- keywords: 'unless',
- contains: [
- {
- className: 'regexp',
- contains: [hljs.BACKSLASH_ESCAPE, SUBST],
- illegal: /\n/,
- variants: [
- {begin: '/', end: '/[a-z]*'},
- {begin: /%r\{/, end: /\}[a-z]*/},
- {begin: '%r\\(', end: '\\)[a-z]*'},
- {begin: '%r!', end: '![a-z]*'},
- {begin: '%r\\[', end: '\\][a-z]*'}
- ]
- }
- ].concat(IRB_OBJECT, COMMENT_MODES),
- relevance: 0
- }
- ].concat(IRB_OBJECT, COMMENT_MODES);
- SUBST.contains = RUBY_DEFAULT_CONTAINS;
- PARAMS.contains = RUBY_DEFAULT_CONTAINS;
- // >>
- // ?>
- var SIMPLE_PROMPT = "[>?]>";
- // irb(main):001:0>
- var DEFAULT_PROMPT = "[\\w#]+\\(\\w+\\):\\d+:\\d+>";
- var RVM_PROMPT = "(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>";
- var IRB_DEFAULT = [
- {
- begin: /^\s*=>/,
- starts: {
- end: '$', contains: RUBY_DEFAULT_CONTAINS
- }
- },
- {
- className: 'meta',
- begin: '^('+SIMPLE_PROMPT+"|"+DEFAULT_PROMPT+'|'+RVM_PROMPT+')(?=[ ])',
- starts: {
- end: '$', contains: RUBY_DEFAULT_CONTAINS
- }
- }
- ];
- COMMENT_MODES.unshift(IRB_OBJECT);
- return {
- name: 'Ruby',
- aliases: ['rb', 'gemspec', 'podspec', 'thor', 'irb'],
- keywords: RUBY_KEYWORDS,
- illegal: /\/\*/,
- contains: [
- hljs.SHEBANG({binary:"ruby"}),
- ]
- .concat(IRB_DEFAULT)
- .concat(COMMENT_MODES)
- .concat(RUBY_DEFAULT_CONTAINS)
- };
- }
- module.exports = ruby;
|