diff options
author | Jean-Nicolas Veigel <art.jnveigel@gmail.com> | 2024-03-16 04:16:27 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2024-03-26 10:31:25 +0000 |
commit | b17fbfc163dfef74d66a2fceaf00f4c621462ade (patch) | |
tree | 8ce160ab0c36f8a2fb2d659fa220aaaf1ebac7da /static/js/highlight/highlight-gleam.js | |
parent | 2caba36a9adf0ee24417a09416e81610352e67f6 (diff) | |
download | tour-b17fbfc163dfef74d66a2fceaf00f4c621462ade.tar.gz tour-b17fbfc163dfef74d66a2fceaf00f4c621462ade.zip |
feat: highlight js gleam lang definition
Diffstat (limited to 'static/js/highlight/highlight-gleam.js')
-rw-r--r-- | static/js/highlight/highlight-gleam.js | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/static/js/highlight/highlight-gleam.js b/static/js/highlight/highlight-gleam.js new file mode 100644 index 0000000..47362a4 --- /dev/null +++ b/static/js/highlight/highlight-gleam.js @@ -0,0 +1,269 @@ +/** + * Registers gleam as a language + * + * Based off https://github.com/gleam-lang/website/blob/main/javascript/highlightjs-gleam.js + * Edited to work with minified hightlightjs core v11 (module) & match more of the syntax + */ + +import hljs from "./highlight.core.min.js"; +import * as regexes from "./regexes.js"; + +/** + * Copies an object to prevent prototype pollution + * @template {object} TObject - the object's structure + * @param {TObject} obj - The source object to copy + * @returns {TObject} - A shallow copy of the source object + */ +const cp = (obj) => ({ ...obj }); + + +// Define operators and keywords to highlight gleam code without spawning an editor +const GLEAM_OPERATORS = [ + "<<", ">>", "<-", "->", "|>", "<>", "..", + "<=", "<=.", ">=", ">=.", "==", "==.", "%", "%.", + "!=", "!=.", '<', "<.", ">", ">.", "&&", "||", + "+", "+.", "-", "-.", "/", "/.", "*", "*.", "=", +] +const GLEAM_KEYWORDS = [ + "as", + "assert", + "auto", + "case", + "const", + "delegate", + "derive", + "echo", + "else", + "fn", + "if", + "implement", + "import", + "let", + "macro", + "opaque", + "panic", + "pub", + "test", + "todo", + "type", + "use", +]; + +/** + * HLJS modes + * Glorified regular expressions used to target & highlight code snippets + * + * Ordered by `relevance` -> more or less translates to parsing order / priority + * https://highlightjs.readthedocs.io/en/stable/language-guide.html#relevance + * + * Their `scope` maps to 1 or more css class + * https://highlightjs.readthedocs.io/en/stable/css-classes-reference.html + */ + +// Relevance 0 + +const PUNCTUATION = { + name: "punctuation", + scope: "punctuation", + match: regexes.punctuation, + relevance: 0, +}; + +const VARIABLES = { + scope: "variable", + match: regexes.snakeCase, + relevance: 0, +}; + +/** + * TODO: fix regex to not break other selectors + */ +const FUNCTION_PARAM = { + scope: "function-param", + match: regexes.functionParam, + relevance: 0, +} + +const DISCARD_NAMES = { + scope: "attribute", + begin: regexes.discardName, + relevance: 0, +}; + +const MODULES = { + scope: "module", + match: regexes.importModule, + relevance: 0, +} + +// Relevance 1 + +const OPERATORS = { + scope: "operator", + begin: regexes.operator, + keywords: { + operator: GLEAM_OPERATORS.join(" "), + $pattern: /\b\S+\b/g, + }, + relevance: 1, +} + +const KEYWORDS = { + name: 'Gleam keywords', + scope: "keyword", + keywords: { + keyword: GLEAM_KEYWORDS.join(" "), + operator: GLEAM_OPERATORS.join(" "), + }, + relevance: 1, +}; + +// Relevance 2 + +const LITERALS = { + name: "Booleans or Nil", + scope: "literal", + match: regexes.literal, + relevance: 2, +}; + +const NUMBERS = { + name: "Number", + scope: "number", + variants: [ + { + begin: regexes.number.binary + }, + { + begin: regexes.number.octal + }, + { + begin: regexes.number.hex + }, + { + begin: regexes.number.decOrFloat + }, + { + match: regexes.number.scientific + } + ], + relevance: 2, +}; + +// Relevance 3 + +const TYPES = { + name: "Types & Aliases", + scope: "type", + match: regexes.type, + relevance: 3, +} + +// Relevance 4 + +const FUNCTION_CALL = { + name: "Function calls", + scope: "function function-name function-call", + match: regexes.functionCall, + relevance: 4, +}; + +const FUNCTION_DECLARATION = { + name: "function declaration", + scope: "function function-name", + beginKeywords: "fn", + end: regexes.endParenthesis, + returnEnd: true, + relevance: 4, +}; + +// Relevance 5 + +// Relevance 6 + +const ATTRIBUTES = { + name: "Attributes", + scope: "attribute", + match: regexes.attribute, + relevance: 6, +} + +// Relevance 7 + +const STRINGS = { + name: "Strings", + scope: "string", + variants: [{ begin: /"/, end: /"/ }], + contains: [hljs.BACKSLASH_ESCAPE], + relevance: 7, +}; + +// Relevance 8 + +const BIT_ARRAYS = { + // bit array + begin: "<<", + end: ">>", + scope: "operator", + contains: [ + { + scope: "keyword", + beginKeywords: + "binary bits bytes int float bit_string bit_array bits utf8 utf16 " + + "utf32 utf8_codepoint utf16_codepoint utf32_codepoint signed " + + "unsigned big little native unit size", + }, + cp(KEYWORDS), + cp(STRINGS), + cp(VARIABLES), + cp(DISCARD_NAMES), + cp(NUMBERS), + cp(PUNCTUATION), + ], + relevance: 8, +}; + +// Relevance 10 + +const COMMENTS = { + name: "Comments", + scope: "comment", + match: regexes.comment, + relevance: 10, +} + +/** + * Register the Gleam lang to HLJS global exported from `./highlight.core.min.js` + */ +hljs.registerLanguage("gleam", function(hljs) { + return { + name: "Gleam", + aliases: ["gleam"], + keywords: { + keyword: KEYWORDS.keywords.keyword, + operator: OPERATORS.keywords.operator, + }, + contains: [ + hljs.C_LINE_COMMENT_MODE, + cp(PUNCTUATION), + cp(MODULES), + cp(DISCARD_NAMES), + cp(OPERATORS), + cp(LITERALS), + cp(NUMBERS), + cp(TYPES), + cp(FUNCTION_DECLARATION), + cp(FUNCTION_CALL), + cp(ATTRIBUTES), + cp(STRINGS), + cp(COMMENTS), + ], + }; +}); + +/** + * Wait until other scripts & css are loaded before highlighting + */ +addEventListener("DOMContentLoaded", () => { + hljs.highlightAll(); +}) |