mindoc/static/editor.md/lib/highlight/languages/crystal.js

182 lines
5.4 KiB
Go

/*
Language: Crystal
Author: TSUYUSATO Kitsune <make.just.on@gmail.com>
*/
function(hljs) {
var NUM_SUFFIX = '(_[uif](8|16|32|64))?';
var CRYSTAL_IDENT_RE = '[a-zA-Z_]\\w*[!?=]?';
var RE_STARTER = '!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|' +
'>>|>|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
var CRYSTAL_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\][=?]?';
var CRYSTAL_KEYWORDS = {
keyword:
'abstract alias as asm begin break case class def do else elsif end ensure enum extend for fun if ifdef ' +
'include instance_sizeof is_a? lib macro module next of out pointerof private protected rescue responds_to? ' +
'return require self sizeof struct super then type typeof union unless until when while with yield ' +
'__DIR__ __FILE__ __LINE__',
literal: 'false nil true'
};
var SUBST = {
className: 'subst',
begin: '#{', end: '}',
keywords: CRYSTAL_KEYWORDS
};
var EXPANSION = {
className: 'template-variable',
variants: [
{begin: '\\{\\{', end: '\\}\\}'},
{begin: '\\{%', end: '%\\}'}
],
keywords: CRYSTAL_KEYWORDS
};
function recursiveParen(begin, end) {
var
contains = [{begin: begin, end: end}];
contains[0].contains = contains;
return contains;
}
var STRING = {
className: 'string',
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
variants: [
{begin: /'/, end: /'/},
{begin: /"/, end: /"/},
{begin: /`/, end: /`/},
{begin: '%w?\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
{begin: '%w?\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
{begin: '%w?{', end: '}', contains: recursiveParen('{', '}')},
{begin: '%w?<', end: '>', contains: recursiveParen('<', '>')},
{begin: '%w?/', end: '/'},
{begin: '%w?%', end: '%'},
{begin: '%w?-', end: '-'},
{begin: '%w?\\|', end: '\\|'},
],
relevance: 0,
};
var REGEXP = {
begin: '(' + RE_STARTER + ')\\s*',
contains: [
{
className: 'regexp',
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
variants: [
{begin: '//[a-z]*', relevance: 0},
{begin: '/', end: '/[a-z]*'},
{begin: '%r\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
{begin: '%r\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
{begin: '%r{', end: '}', contains: recursiveParen('{', '}')},
{begin: '%r<', end: '>', contains: recursiveParen('<', '>')},
{begin: '%r/', end: '/'},
{begin: '%r%', end: '%'},
{begin: '%r-', end: '-'},
{begin: '%r\\|', end: '\\|'},
]
}
],
relevance: 0
};
var REGEXP2 = {
className: 'regexp',
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
variants: [
{begin: '%r\\(', end: '\\)', contains: recursiveParen('\\(', '\\)')},
{begin: '%r\\[', end: '\\]', contains: recursiveParen('\\[', '\\]')},
{begin: '%r{', end: '}', contains: recursiveParen('{', '}')},
{begin: '%r<', end: '>', contains: recursiveParen('<', '>')},
{begin: '%r/', end: '/'},
{begin: '%r%', end: '%'},
{begin: '%r-', end: '-'},
{begin: '%r\\|', end: '\\|'},
],
relevance: 0
};
var ATTRIBUTE = {
className: 'meta',
begin: '@\\[', end: '\\]',
contains: [
hljs.inherit(hljs.QUOTE_STRING_MODE, {className: 'meta-string'})
]
};
var CRYSTAL_DEFAULT_CONTAINS = [
EXPANSION,
STRING,
REGEXP,
REGEXP2,
ATTRIBUTE,
hljs.HASH_COMMENT_MODE,
{
className: 'class',
beginKeywords: 'class module struct', end: '$|;',
illegal: /=/,
contains: [
hljs.HASH_COMMENT_MODE,
hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?'}),
{begin: '<'} // relevance booster for inheritance
]
},
{
className: 'class',
beginKeywords: 'lib enum union', end: '$|;',
illegal: /=/,
contains: [
hljs.HASH_COMMENT_MODE,
hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?'}),
],
relevance: 10
},
{
className: 'function',
beginKeywords: 'def', end: /\B\b/,
contains: [
hljs.inherit(hljs.TITLE_MODE, {
begin: CRYSTAL_METHOD_RE,
endsParent: true
})
]
},
{
className: 'function',
beginKeywords: 'fun macro', end: /\B\b/,
contains: [
hljs.inherit(hljs.TITLE_MODE, {
begin: CRYSTAL_METHOD_RE,
endsParent: true
})
],
relevance: 5
},
{
className: 'symbol',
begin: hljs.UNDERSCORE_IDENT_RE + '(\\!|\\?)?:',
relevance: 0
},
{
className: 'symbol',
begin: ':',
contains: [STRING, {begin: CRYSTAL_METHOD_RE}],
relevance: 0
},
{
className: 'number',
variants: [
{ begin: '\\b0b([01_]*[01])' + NUM_SUFFIX },
{ begin: '\\b0o([0-7_]*[0-7])' + NUM_SUFFIX },
{ begin: '\\b0x([A-Fa-f0-9_]*[A-Fa-f0-9])' + NUM_SUFFIX },
{ begin: '\\b(([0-9][0-9_]*[0-9]|[0-9])(\\.[0-9_]*[0-9])?([eE][+-]?[0-9_]*[0-9])?)' + NUM_SUFFIX}
],
relevance: 0
}
];
SUBST.contains = CRYSTAL_DEFAULT_CONTAINS;
EXPANSION.contains = CRYSTAL_DEFAULT_CONTAINS.slice(1); // without EXPANSION
return {
aliases: ['cr'],
lexemes: CRYSTAL_IDENT_RE,
keywords: CRYSTAL_KEYWORDS,
contains: CRYSTAL_DEFAULT_CONTAINS
};
}