highlight-ts
Version:
Highlight.JS in TypeScript (and ES6).
170 lines (159 loc) • 4.75 kB
text/typescript
/*
Language: CoffeeScript
Author: Dmytrii Nagirniak <dnagir@gmail.com>
Contributors: Oleg Efimov <efimovov@gmail.com>, Cédric Néhémie <cedric.nehemie@gmail.com>
Description: CoffeeScript is a programming language that transcompiles to JavaScript. For info about language see http://coffeescript.org/
Category: common, scripting
*/
import { KeywordsDef, SyntaxDef, LanguageDef } from '../types';
import {
BINARY_NUMBER_MODE,
C_NUMBER_MODE,
BACKSLASH_ESCAPE,
HASH_COMMENT_MODE,
TITLE_MODE,
COMMENT
} from '../common';
const KEYWORDS: KeywordsDef = {
keyword:
// JS keywords
'in if for while finally new do return else break catch instanceof throw try this ' +
'switch continue typeof delete debugger super yield import export from as default await ' +
// Coffee keywords
'then unless until loop of by when and or is isnt not',
literal:
// JS literals
'true false null undefined ' +
// Coffee literals
'yes no on off',
built_in:
'npm require console print module global window document'
};
const JS_IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
const SUBST: SyntaxDef = {
className: 'subst',
begin: /#\{/, end: /}/,
keywords: KEYWORDS
};
const EXPRESSIONS = [
BINARY_NUMBER_MODE,
{ ...C_NUMBER_MODE, starts: { end: '(\\s*/)?', relevance: 0 } }, // a number tries to eat the following slash to prevent treating it as a regexp
{
className: 'string',
variants: [
{
begin: /'''/, end: /'''/,
contains: [BACKSLASH_ESCAPE]
},
{
begin: /'/, end: /'/,
contains: [BACKSLASH_ESCAPE]
},
{
begin: /"""/, end: /"""/,
contains: [BACKSLASH_ESCAPE, SUBST]
},
{
begin: /"/, end: /"/,
contains: [BACKSLASH_ESCAPE, SUBST]
}
]
},
{
className: 'regexp',
variants: [
{
begin: '///', end: '///',
contains: [SUBST, HASH_COMMENT_MODE]
},
{
begin: '//[gim]*',
relevance: 0
},
{
// regex can't start with space to parse x / 2 / 3 as two divisions
// regex can't start with *, and it supports an "illegal" in the main mode
begin: /\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/
}
]
},
{
begin: '@' + JS_IDENT_RE // relevance booster
},
{
subLanguage: 'javascript',
excludeBegin: true, excludeEnd: true,
variants: [
{
begin: '```', end: '```',
},
{
begin: '`', end: '`',
}
]
}
];
SUBST.contains = EXPRESSIONS;
const TITLE = { ...TITLE_MODE, begin: JS_IDENT_RE };
const PARAMS_RE = '(\\(.*\\))?\\s*\\B[-=]>';
const PARAMS: SyntaxDef = {
className: 'params',
begin: '\\([^\\(]', returnBegin: true,
/* We need another contained nameless mode to not have every nested
pair of parens to be called "params" */
contains: [{
begin: /\(/, end: /\)/,
keywords: KEYWORDS,
contains: ['self', ...EXPRESSIONS]
}]
};
export const CoffeeScript: LanguageDef = {
name: 'coffeescript',
aliases: ['coffee', 'cson', 'iced'],
keywords: KEYWORDS,
illegal: /\/\*/,
contains: [
...EXPRESSIONS,
COMMENT('###', '###'),
HASH_COMMENT_MODE,
{
className: 'function',
begin: '^\\s*' + JS_IDENT_RE + '\\s*=\\s*' + PARAMS_RE, end: '[-=]>',
returnBegin: true,
contains: [TITLE, PARAMS]
},
{
// anonymous function start
begin: /[:\(,=]\s*/,
relevance: 0,
contains: [
{
className: 'function',
begin: PARAMS_RE, end: '[-=]>',
returnBegin: true,
contains: [PARAMS]
}
]
},
{
className: 'class',
beginKeywords: 'class',
end: '$',
illegal: /[:="\[\]]/,
contains: [
{
beginKeywords: 'extends',
endsWithParent: true,
illegal: /[:="\[\]]/,
contains: [TITLE]
},
TITLE
]
},
{
begin: JS_IDENT_RE + ':', end: ':',
returnBegin: true, returnEnd: true,
relevance: 0
}
]
};