diff options
Diffstat (limited to 'node_modules/highlight.js/lib/languages/less.js')
-rw-r--r-- | node_modules/highlight.js/lib/languages/less.js | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/node_modules/highlight.js/lib/languages/less.js b/node_modules/highlight.js/lib/languages/less.js new file mode 100644 index 000000000..29d77471d --- /dev/null +++ b/node_modules/highlight.js/lib/languages/less.js @@ -0,0 +1,139 @@ +module.exports = function(hljs) { + var IDENT_RE = '[\\w-]+'; // yes, Less identifiers may begin with a digit + var INTERP_IDENT_RE = '(' + IDENT_RE + '|@{' + IDENT_RE + '})'; + + /* Generic Modes */ + + var RULES = [], VALUE = []; // forward def. for recursive modes + + var STRING_MODE = function(c) { return { + // Less strings are not multiline (also include '~' for more consistent coloring of "escaped" strings) + className: 'string', begin: '~?' + c + '.*?' + c + };}; + + var IDENT_MODE = function(name, begin, relevance) { return { + className: name, begin: begin, relevance: relevance + };}; + + var PARENS_MODE = { + // used only to properly balance nested parens inside mixin call, def. arg list + begin: '\\(', end: '\\)', contains: VALUE, relevance: 0 + }; + + // generic Less highlighter (used almost everywhere except selectors): + VALUE.push( + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE, + STRING_MODE("'"), + STRING_MODE('"'), + hljs.CSS_NUMBER_MODE, // fixme: it does not include dot for numbers like .5em :( + { + begin: '(url|data-uri)\\(', + starts: {className: 'string', end: '[\\)\\n]', excludeEnd: true} + }, + IDENT_MODE('number', '#[0-9A-Fa-f]+\\b'), + PARENS_MODE, + IDENT_MODE('variable', '@@?' + IDENT_RE, 10), + IDENT_MODE('variable', '@{' + IDENT_RE + '}'), + IDENT_MODE('built_in', '~?`[^`]*?`'), // inline javascript (or whatever host language) *multiline* string + { // @media features (it’s here to not duplicate things in AT_RULE_MODE with extra PARENS_MODE overriding): + className: 'attribute', begin: IDENT_RE + '\\s*:', end: ':', returnBegin: true, excludeEnd: true + }, + { + className: 'meta', + begin: '!important' + } + ); + + var VALUE_WITH_RULESETS = VALUE.concat({ + begin: '{', end: '}', contains: RULES + }); + + var MIXIN_GUARD_MODE = { + beginKeywords: 'when', endsWithParent: true, + contains: [{beginKeywords: 'and not'}].concat(VALUE) // using this form to override VALUE’s 'function' match + }; + + /* Rule-Level Modes */ + + var RULE_MODE = { + begin: INTERP_IDENT_RE + '\\s*:', returnBegin: true, end: '[;}]', + relevance: 0, + contains: [ + { + className: 'attribute', + begin: INTERP_IDENT_RE, end: ':', excludeEnd: true, + starts: { + endsWithParent: true, illegal: '[<=$]', + relevance: 0, + contains: VALUE + } + } + ] + }; + + var AT_RULE_MODE = { + className: 'keyword', + begin: '@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b', + starts: {end: '[;{}]', returnEnd: true, contains: VALUE, relevance: 0} + }; + + // variable definitions and calls + var VAR_RULE_MODE = { + className: 'variable', + variants: [ + // using more strict pattern for higher relevance to increase chances of Less detection. + // this is *the only* Less specific statement used in most of the sources, so... + // (we’ll still often loose to the css-parser unless there's '//' comment, + // simply because 1 variable just can't beat 99 properties :) + {begin: '@' + IDENT_RE + '\\s*:', relevance: 15}, + {begin: '@' + IDENT_RE} + ], + starts: {end: '[;}]', returnEnd: true, contains: VALUE_WITH_RULESETS} + }; + + var SELECTOR_MODE = { + // first parse unambiguous selectors (i.e. those not starting with tag) + // then fall into the scary lookahead-discriminator variant. + // this mode also handles mixin definitions and calls + variants: [{ + begin: '[\\.#:&\\[>]', end: '[;{}]' // mixin calls end with ';' + }, { + begin: INTERP_IDENT_RE, end: '{' + }], + returnBegin: true, + returnEnd: true, + illegal: '[<=\'$"]', + relevance: 0, + contains: [ + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE, + MIXIN_GUARD_MODE, + IDENT_MODE('keyword', 'all\\b'), + IDENT_MODE('variable', '@{' + IDENT_RE + '}'), // otherwise it’s identified as tag + IDENT_MODE('selector-tag', INTERP_IDENT_RE + '%?', 0), // '%' for more consistent coloring of @keyframes "tags" + IDENT_MODE('selector-id', '#' + INTERP_IDENT_RE), + IDENT_MODE('selector-class', '\\.' + INTERP_IDENT_RE, 0), + IDENT_MODE('selector-tag', '&', 0), + {className: 'selector-attr', begin: '\\[', end: '\\]'}, + {className: 'selector-pseudo', begin: /:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/}, + {begin: '\\(', end: '\\)', contains: VALUE_WITH_RULESETS}, // argument list of parametric mixins + {begin: '!important'} // eat !important after mixin call or it will be colored as tag + ] + }; + + RULES.push( + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE, + AT_RULE_MODE, + VAR_RULE_MODE, + RULE_MODE, + SELECTOR_MODE + ); + + return { + case_insensitive: true, + illegal: '[=>\'/<($"]', + contains: RULES + }; +};
\ No newline at end of file |