Kiss me on GitHub
Highlight.js Grammar
Build your own syntax-highlight grammar for Highlight.js
Highlight.js v.
0
, HighlightJSGrammar v.
0
Sample Code to be highlighted (see output below):
// this is part of the HighlightJSGrammar code itself function get_mode( grammar, hljs ) { var HighlightJSMode = function HighlightJSMode( hljs ) { var tokens = null, token = null, mode, matchToken = { lastIndex : 0, exec : function( str ) { var m = null; if ( token ) { m = [token.token]; m.index = 0; this.lastIndex = m[0].length; } return m; } }, getToken = { lastIndex : 0, exec : function( str ) { var m = null; if ( token && !token.ret ) { m = [token.token]; m.index = 0; this.lastIndex = m[0].length; // returned, reset it token.ret = 1; } return m; } }, parseToken = { _str : null, lastIndex : 0, exec : function( str ) { var m = null, self = this; if ( str !== self._str ) { self._str = str; self.lastIndex = self.lastIndex || 0; tokens = HighlightJSMode.$parser.parse(str, TOKENS|ERRORS|FLAT).tokens; token = tokens.shift( ); token.ret = 0; mode.parent = mode; if ( null === token.type ) { // unstyled mode.keywords = null; } else { // token.type is the syntax-highlight style mode.keywords = { }; mode.keywords[token.token] = [token.type, 1]; } m = [token.token]; m.index = self.lastIndex; self.lastIndex += m[0].length; } else if ( tokens && tokens.length ) { self.lastIndex = self.lastIndex || 0; token = tokens.shift( ); token.ret = 0; mode.parent = mode; if ( null === token.type ) { // unstyled mode.keywords = null; } else { // token.type is the syntax-highlight style mode.keywords = { }; mode.keywords[token.token] = [token.type, 1]; } m = [token.token]; m.index = self.lastIndex; self.lastIndex += m[0].length; } else { self._str = null; self.lastIndex = 0; tokens = null; token = null; mode.parent = null; mode.keywords = null; } return m; } } ; mode = { // this is supposed to be an already compiled mode compiled: true, aliases: HighlightJSMode.aliases || null, case_insensitive: false, relevance: 0, contains: [], parent: null, keywords: null, className: null, // a hack for hljs to introduce grammar token parsing beginRe: matchToken, endRe: matchToken, lexemesRe: getToken, terminators: parseToken }; return mode; }; HighlightJSMode.$id = uuid("highlightjs_grammar_mode"); HighlightJSMode.$parser = new HighlightJSGrammar.Parser( parse_grammar( grammar ) ); HighlightJSMode.dispose = function( ) { if ( HighlightJSMode.$parser ) HighlightJSMode.$parser.dispose( ); HighlightJSMode.$parser = null; }; HighlightJSMode.aliases = null; return HighlightJSMode; }
Grammar (JSON format):
// a partial javascript grammar in simple JSON format { // prefix ID for regular expressions used in the grammar "RegExpID" : "RE::", // Style model "Style" : { "comment" : "comment" ,"atom" : "literal" ,"keyword" : "section" ,"this" : "section" ,"builtin" : "built_in" ,"identifier" : "meta" ,"property" : "variable" ,"number" : "number" ,"string" : "string" ,"regex" : "regexp" }, // Lexical model "Lex" : { "comment" : {"type":"comment","tokens":[ // line comment // start, end delims (null matches end-of-line) [ "//", null ], // block comments // start, end delims [ "/*", "*/" ] ]} ,"identifier" : "RE::/[_A-Za-z$][_A-Za-z0-9$]*/" ,"this" : "RE::/this\\b/" ,"property" : "RE::/[_A-Za-z$][_A-Za-z0-9$]*/" ,"number" : [ // floats "RE::/\\d*\\.\\d+(e[\\+\\-]?\\d+)?/", "RE::/\\d+\\.\\d*/", "RE::/\\.\\d+/", // integers // hex "RE::/0x[0-9a-fA-F]+L?/", // binary "RE::/0b[01]+L?/", // octal "RE::/0o[0-7]+L?/", // decimal "RE::/[1-9]\\d*(e[\\+\\-]?\\d+)?L?/", // just zero "RE::/0(?![\\dx])/" ] ,"string" : {"type":"escaped-block","escape":"\\","tokens": // start, end of string (can be the matched regex group ie. 1 ) [ "RE::/(['\"])/", 1 ] } ,"regex" : {"type":"escaped-block","escape":"\\","tokens": // javascript literal regular expressions can be parsed similar to strings [ "/", "RE::#/[gimy]{0,4}#" ] } ,"operator" : {"tokens":[ "+", "-", "++", "--", "%", ">>", "<<", ">>>", "*", "/", "^", "|", "&", "!", "~", ">", "<", "<=", ">=", "!=", "!==", "=", "==", "===", "+=", "-=", "%=", ">>=", ">>>=", "<<=", "*=", "/=", "|=", "&=" ]} ,"delimiter" : {"tokens":[ "(", ")", "[", "]", "{", "}", ",", "=", ";", "?", ":", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "++", "--", ">>=", "<<=" ]} ,"atom" : {"autocomplete":true,"tokens":[ "true", "false", "null", "undefined", "NaN", "Infinity" ]} ,"keyword" : {"autocomplete":true,"tokens":[ "if", "while", "with", "else", "do", "try", "finally", "return", "break", "continue", "new", "delete", "throw", "var", "const", "let", "function", "catch", "void", "for", "switch", "case", "default", "class", "import", "yield", "in", "typeof", "instanceof" ]} ,"builtin" : {"autocomplete":true,"tokens":[ "Object", "Function", "Array", "String", "Date", "Number", "RegExp", "Math", "Exception", "setTimeout", "setInterval", "parseInt", "parseFloat", "isFinite", "isNan", "alert", "prompt", "console", "window", "global", "this" ]} }, // Syntax model (optional) "Syntax" : { "dot_property" : {"sequence":[".", "property"]} ,"js" : "comment | number | string | regex | keyword | operator | atom | (('}' | ')' | this | builtin | identifier | dot_property) dot_property*)" }, // what to parse and in what order "Parser" : [ ["js"] ] }
Output: