javascriptregexsyntax-highlightinghighlight.js

Klipper Syntax Highlighter using Highlight.JS


I'm trying to create a syntax highlighter for the Klipper 3D printer firmware. The language consists of settings elements, comments and Jinja2 template elements. In the first place, I wanted to get a simple highlighting working but I'm hitting a road block.

Highlighter Code:

hljs.registerLanguage("klipper", function (hljs) {
  const COMMENT = {
    scope: "comment",
    variants: [
      { begin: /^\s*[#;].*$/, end: /$/ }, // Standalone comments
      { begin: /(?!\s)[#|;].*/, end: /$/ }, // Inline/trailing comments
    ],
    relevance: 10,
  }

  const KEY_PART = {
    scope: "symbol",
    begin: /^[^=\s]+(?=\s*[:=])/,
    //end: /^(?!\s).+?\s?[=:](?=(?:[^\n]*$))/,
  }

  const VALUE_PART = {
    scope: "addition",
    begin: /[:=][\s*|$]/,
    //end: /\r?\n$/, // Match until the end of the line
    end: /$/, // Match until the end of the line
    excludeBegin: true, // Ensure the separator is not included
    excludeEnd: true,
  }

  const SECTION = {
    scope: "addition",
    begin: /^\s*\[/,
    end: /\]/,
    contains: [
      {
        scope: "title",
        match: /[^\]]+/,
      },
    ],
  }

  const INDENTED_BLOCK = {
    scope: "deletion",
    begin: /^\s+/,
    end: /$/,
    relevance: 10,
  }

  return {
    name: "Klipper Config",
    aliases: ["klipper", "cfg"],
    disableAutodetect: true,
    contains: [COMMENT, SECTION, KEY_PART, VALUE_PART, INDENTED_BLOCK],
  }
})

My issue is that I cannot get a regex or setting for properly matching the VALUE_PART, for example:

[idle_timeout]
gcode:
    {% if printer.pause_resume.is_paused %}

While a simple key/value pair, like step_pin: PC2, matches, the regex fails if the key is not directly followed by a value, but the statements are in an indented block below. The indented block should be formatted as INDENTED_BLOCK. See the following screenshot.

enter image description here

Basically, the VALUE_PART formatting is "bleeding into" this block, but only for the first line of such an indented block.

Fiddle with the code is here: https://jsfiddle.net/Sineos/54yz89e3/

Any pointer how to solve this would be really appreciated. Many thanks in advance.


Solution

  • The token \s also matches \r and \n and that's why it is stepping over the line break.

    Just doing:

      const VALUE_PART = {
        scope: "addition",
        begin: /[:=]/,
        end: /$/, // Match until the end of the line
        excludeBegin: true, // Ensure the separator is not included
        excludeEnd: true,
      }
    

    does the trick. Fiddle is updated.