| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 | /** * @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: RubyDescription: 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) {  const RUBY_METHOD_RE = '([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)';  const 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'  };  const YARDOCTAG = {    className: 'doctag',    begin: '@[A-Za-z]+'  };  const IRB_OBJECT = {    begin: '#<',    end: '>'  };  const COMMENT_MODES = [    hljs.COMMENT(      '#',      '$',      {        contains: [ YARDOCTAG ]      }    ),    hljs.COMMENT(      '^=begin',      '^=end',      {        contains: [ YARDOCTAG ],        relevance: 10      }    ),    hljs.COMMENT('^__END__', '\\n$')  ];  const SUBST = {    className: 'subst',    begin: /#\{/,    end: /\}/,    keywords: RUBY_KEYWORDS  };  const 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: /\|/      },      // in the following expressions, \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})/      },      {        begin: /\B\?(\\x[A-Fa-f0-9]{1,2})/      },      {        begin: /\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/      },      {        begin: /\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/      },      {        begin: /\B\?\\(c|C-)[\x20-\x7e]/      },      {        begin: /\B\?\\?\S/      },      { // 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  const decimal = '[1-9](_?[0-9])*|0';  const digits = '[0-9](_?[0-9])*';  const 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"      }    ]  };  const PARAMS = {    className: 'params',    begin: '\\(',    end: '\\)',    endsParent: true,    keywords: RUBY_KEYWORDS  };  const 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,              // we already get points for <, we don't need poitns              // for the name also              relevance: 0            }          ]        }      ].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*(\\(|;|$)")),      relevance: 0, // relevance comes from kewords      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;  // >>  // ?>  const SIMPLE_PROMPT = "[>?]>";  // irb(main):001:0>  const DEFAULT_PROMPT = "[\\w#]+\\(\\w+\\):\\d+:\\d+>";  const RVM_PROMPT = "(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>";  const 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;
 |