Transform a JSON grammar into a syntax-highlight mode for Highlight.js
JavaScript HTML Other
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
build v.4.2.1 Dec 11, 2016
editor-grammar @ 3ad07d6 v.4.2.1 Dec 11, 2016
src v.4.1.0 (changes) Nov 27, 2016
test v.4.1.0 (changes) Nov 27, 2016
.gitmodules v.3.1.0 (tentative) Mar 30, 2016 markdown github fix Mar 1, 2018
beeld.config v.4.2.1 Dec 11, 2016
build-min.bat v.3.1.0 (tentative) Mar 30, 2016
update.bat v.3.1.0 (tentative) Mar 30, 2016


Transform a JSON grammar into a syntax-highlight mode for Highlight.js

Highlightjs Grammar

A simple and light-weight (~ 44kB minified, ~ 15kB zipped) Highlight.js add-on

to generate highlightjs-compatible modes from a grammar specification in JSON format.

See also: codemirror-grammar, ace-grammar, prism-grammar, syntaxhighlighter-grammar

Note: The invariant codebase for all the *-grammar add-ons resides at editor-grammar repository (used as a git submodule)


Build your own syntax-highlight mode on the fly


see Modularity and Future Directions

  • enable grammar add-on to pre-compile a grammar specification directly into mode source code, so it can be used without the add-on as standalone mode [TODO, maybe]


  • A Grammar can extend other Grammars (so arbitrary variations and dialects can be handled more easily)
  • Grammar includes: Style Model , Lex Model and Syntax Model (optional), plus a couple of settings (see examples)
  • Grammar specification can be minimal, defaults will be used (see example grammars)
  • Grammar.Syntax Model can enable highlight in a more context-specific way, plus detect possible syntax errors
  • Grammar.Syntax Model can contain recursive references
  • Grammar.Syntax Model can be (fully) specificed using PEG-like notation or BNF-like notation (NEW feature)
  • Grammar.Syntax Model implements positive / negative lookahead tokens (analogous to PEG and-/not- predicates) (NEW feature)
  • Grammar.Syntax Model can include external (sub-)grammars so that new multiplexed / mixed grammars are created easily and intuitively (see test examples) (NEW feature)
  • Grammar can define action tokens to perform complex context-specific parsing functionality, including associated tag matching and duplicate identifiers (see for example xml.grammar example) (NEW feature)
  • Generated highlighters are optimized for speed and size
  • Can generate a syntax-highlighter from a grammar interactively and on-the-fly ( see example, )
  • see also Modularity and Future Directions

How to use:

An example for XML:

// 1. a partial xml grammar in simple JSON format
var xml_grammar = {
// prefix ID for regular expressions, represented as strings, used in the grammar
"RegExpID"                          : "RE::",

// Style model
"Style"                             : {
     "declaration"                  : "section"
    ,"doctype"                      : "template-tag"
    ,"meta"                         : "meta"
    ,"comment"                      : "comment"
    ,"cdata"                        : "literal"
    ,"atom"                         : "literal"
    ,"tag"                          : "meta"
    ,"attribute"                    : "built_in"
    ,"string"                       : "string"
    ,"number"                       : "number"


// Lexical model
"Lex"                               : {
     "comment:comment"              : ["<!--", "-->"]
    ,"declaration:block"            : ["<?xml", "?>"]
    ,"doctype:block"                : ["RE::/<!doctype\\b/i", ">"]
    ,"meta:block"                   : ["RE::/<\\?[_a-zA-Z][\\w\\._\\-]*/", "?>"]
    ,"cdata:block"                  : ["<![CDATA[", "]]>"]
    ,"open_tag"                     : "RE::/<([_a-zA-Z][_a-zA-Z0-9\\-]*)/"
    ,"close_tag"                    : "RE::/<\\/([_a-zA-Z][_a-zA-Z0-9\\-]*)>/"
    ,"attribute"                    : "RE::/[_a-zA-Z][_a-zA-Z0-9\\-]*/"
    ,"string:line-block"            : [["\""], ["'"]]
    ,"number"                       : ["RE::/[0-9]\\d*/", "RE::/#[0-9a-fA-F]+/"]
    ,"atom"                         : ["RE::/&#x[a-fA-F\\d]+;/", "RE::/&#[\\d]+;/", "RE::/&[a-zA-Z][a-zA-Z0-9]*;/"]
    ,"text"                         : "RE::/[^<&]+/"
    // actions
    ,"tag_ctx:action"               : {"context":true}
    ,"\\tag_ctx:action"             : {"context":false}
    ,"unique_id:action"             : {"unique":["xml", "$1"],"msg":"Duplicate id value \"$0\""}
    ,"unique_att:action"            : {"unique":["tag", "$0"],"msg":"Duplicate attribute \"$0\"","in-context":true}
    ,"tag_opened:action"            : {"push":"<$1>","ci":true}
    ,"tag_closed:action"            : {"pop":"<$1>","ci":true,"msg":"Tags \"$0\" and \"$1\" do not match"}
    ,"tag_autoclosed:action"        : {"pop":null}
    ,"out_of_place:error"           : "\"$2$3\" can only be at the beginning of XML document"
// Syntax model (optional)
"Syntax"                            : {
     "tag_att"                      : "'id'.attribute unique_att '=' string unique_id | attribute unique_att '=' (string | number)"
    ,"start_tag"                    : "open_tag.tag tag_ctx tag_opened tag_att* ('>'.tag | '/>'.tag tag_autoclosed) \\tag_ctx"
    ,"end_tag"                      : "close_tag.tag tag_closed"
    ,"xml"                          : "(^^1 declaration? doctype?) (declaration.error out_of_place | doctype.error out_of_place | comment | meta | cdata | start_tag | end_tag | atom | text)*"
// what to parse and in what order
"Parser"                            : [ ["xml"] ]


// 2. parse the grammar into a Highlight.js-compatible mode
var xml_mode = HighlightJSGrammar.getMode( xml_grammar );

// 3. use it with Highlight.js
hljs.registerLanguage( "xml", xml_mode );
hljs.highlightBlock( document.getElementById("code") );



Other Examples: