| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 | /*Language: LessAuthor:   Max Mikhailov <[email protected]>Category: css*/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  };}
 |