JSFiddle - React, Tailwind, and code Playground
by Sineos
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Klipper Config Syntax Highlighting</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="./dev_test.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
<script>
document.addEventListener('DOMContentLoaded', (event) => {
hljs.highlightAll();
});
</script>
</head>
<body>
<h1>Klipper Config Example</h1>
<pre><code class="language-klipper">
[idle_timeout]
gcode:
{% if printer.pause_resume.is_paused %}
M104 S0 ;ooo
G1 X0
{% else %}
[stepper_x] # iii
step_pin: 10 ; kkk
; bla
step_pin: PC2
[board_pins] ; kkk
aliases:
EXP1_5=PE12, EXP1_6=PE13, # hhh
EXP1_5=PE12, EXP1_6=PE13, ; jjj
</code></pre>
</body>
</html>
JavaScript
hljs.registerLanguage("klipper", function (hljs) {
const COMMENT = {
scope: "comment",
variants: [
{ begin: /^\s*[#;].*$/, end: /$/ }, // Standalone comments
{ begin: /[#;].*/, end: /$/ }, // Inline/trailing comments
],
relevance: 10,
};
const KEY_PART = {
scope: "symbol",
begin: /^[^=\s][^:=]*/, // More flexible key matching
end: /(?=\s*[:=])/,
};
const VALUE_PART = {
scope: "addition",
begin: /[:=]/,
end: /$/,
excludeBegin: true,
excludeEnd: true,
contains: [
COMMENT,
hljs.inherit(hljs.NUMBER_MODE, { scope: "number" }),
hljs.QUOTE_STRING_MODE
],
};
const SECTION = {
scope: "punctuation",
begin: /^\s*\[/,
end: /\]/,
contains: [
{
scope: "section",
match: /[^\]]+/,
},
],
};
const JINJA_BLOCK = {
scope: "name",
begin: /(?:^{%|{%|{{|{#)/, // All Jinja delimiters
end: /(?:%}|%}|}}|#})/,
contains: [
{
scope: "built_in",
match: /\b(if|elif|else|for|endfor|while|endwhile|set|in|params|not|and|trim|round)\b/,
},
hljs.QUOTE_STRING_MODE,
hljs.inherit(hljs.NUMBER_MODE, { scope: "number" }),
],
};
const GCODE_COMMAND = {
scope: "deletion",
match: /\b([GMT]\d+(?:\.\d+)?|D[0-9.]+|I[-0-9.]+|J[-0-9.]+|K[-0-9.]+)\b/,
contains: [
{
scope: "addition",
match: /\b[XZYEFSPQRIJK]\d*\.?\d*\b/,
},
],
};
const INDENTED_BLOCK = {
scope: "deletion",
begin: /^\s+/,
end: /$/,
contains: [
COMMENT,
hljs.inherit(hljs.NUMBER_MODE, { scope: "number" }),
hljs.QUOTE_STRING_MODE,
GCODE_COMMAND,
JINJA_BLOCK, // Allow Jinja in indented blocks
],
relevance: 10,
};
return {
name: "Klipper Config",
aliases: ["klipper", "cfg"],
disableAutodetect: true,
contains: [
COMMENT,
SECTION,
KEY_PART,
VALUE_PART,
JINJA_BLOCK,
...