title: Highlight.js custom language definition
body: <p>I'm trying to create language definition for <strong>highlight.js</strong>.
  But it doesn't work. I've got an example.</p>
  
  <p>In this example i'm trying to create custom <em>"aaa"</em> language, which is the same as JSON. <code>registerLanguage</code> function receives same function as a default JSON highlight function (from highlight.js sources).</p>
  
  <p><code>hljs.listLanguages()</code> shows, that language is registered.</p>
  
  <p>After, i'm calling <code>hljs.highlightBlock(block)</code>.</p>
  
  <p><code>&lt;code class="aaa"&gt;</code> forces to use custom "aaa" language, and in this case <code>hljs.highlightBlock(block)</code> doesn't changes  content.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="true">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>$(document).ready(function() {
    // registering aaa language (JSON alias)
    // code from https://github.com/isagalaev/highlight.js/blob/master/src/languages/json.js
    hljs.registerLanguage("aaa", function(hljs) {
      var LITERALS = {
        literal: 'true false null'
      };
      var TYPES = [
        hljs.QUOTE_STRING_MODE,
        hljs.C_NUMBER_MODE
      ];
      var VALUE_CONTAINER = {
        className: 'value',
        end: ',',
        endsWithParent: true,
        excludeEnd: true,
        contains: TYPES,
        keywords: LITERALS
      };
      var OBJECT = {
        begin: '{',
        end: '}',
        contains: [{
          className: 'attribute',
          begin: '\\s*"',
          end: '"\\s*:\\s*',
          excludeBegin: true,
          excludeEnd: true,
          contains: [hljs.BACKSLASH_ESCAPE],
          illegal: '\\n',
          starts: VALUE_CONTAINER
        }],
        illegal: '\\S'
      };
      var ARRAY = {
        begin: '\\[',
        end: '\\]',
        contains: [hljs.inherit(VALUE_CONTAINER, {
          className: null
        })], // inherit is also a workaround for a bug that makes shared modes with endsWithParent compile only the ending of one of the parents
        illegal: '\\S'
      };
      TYPES.splice(TYPES.length, 0, OBJECT, ARRAY);
      return {
        contains: TYPES,
        keywords: LITERALS,
        illegal: '\\S'
      };
    });
    console.log(hljs.listLanguages()); // aaa in the list
    $('pre code').each(function(i, block) {
      hljs.highlightBlock(block);
    });
  });</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/tomorrow.min.css" rel="stylesheet"/&gt;
  &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"&gt;&lt;/script&gt;
  &lt;pre&gt;&lt;code class="aaa"&gt; 
  {"menu": {
    "id": "file",
    "value": "File",
    "popup": {
      "menuitem": [
        {"value": "New", "onclick": "CreateNewDoc()"},
        {"value": "Open", "onclick": "OpenDoc()"},
        {"value": "Close", "onclick": "CloseDoc()"}
      ]
    }
  }}
  &lt;/code&gt;&lt;/pre&gt;</code></pre>
  </div>
  </div>
  </p>