Created
February 8, 2023 15:16
-
-
Save thatrandomperson5/fcc59ac4814a601d2d00ac18f5e3eb6d to your computer and use it in GitHub Desktop.
Adapted Highlighter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Adapted from https://github.com/pietroppeter/nimib/blob/2e0c2223cef10423fc43fc3be9626890a6bb4779/src/nimib/highlight.nim | |
import std/[strutils, dom] | |
import packages/docutils/highlite | |
func nimNormalize(s: string): string = | |
# Copied from strutils.normalize (same except for branch i == 0) | |
# Normalizes a Nim identifier to all lowercase: | |
# - All letters except the first one are lower-cased | |
# - Underscores are ignored | |
result = newString(s.len) | |
var j = 0 | |
for i in 0 .. len(s) - 1: | |
# First char is case-sensitive | |
if i == 0: | |
result[j] = s[i] | |
inc j | |
# Lowercase all upper-case chars | |
elif s[i] in {'A'..'Z'}: | |
result[j] = chr(ord(s[i]) + (ord('a') - ord('A'))) | |
inc j | |
# Ignore underscores | |
elif s[i] != '_': | |
result[j] = s[i] | |
inc j | |
# Trim the string if it's shorter than the original | |
if j != s.len: setLen(result, j) | |
# Constants below are taken from highlight.js and saem/vscode-nim | |
const builtin = [ | |
"int", "int8", "int16", "int32", "int64", | |
"uint", "uint8", "uint16", "uint32", "uint64", | |
"float", "float32", "float64", | |
"bool", "char", "string", "cstring", "pointer", | |
"expr", "stmt", "untyped", "typed", "void", "auto", | |
"any", "range", "openArray", "varargs", "seq", "set", | |
"clong", "culong", "cchar", "cschar", "cshort", "cint", "csize", | |
"clonglong", "cfloat", "cdouble", "clongdouble", "cuchar", "cushort", | |
"cuint", "culonglong", "cstringArray", "array" | |
] | |
const literal = [ | |
"stdin", "stdout", "stderr", "result", "true", | |
"false", "Inf", "NegInf", "NaN", "nil" | |
] | |
const commonFuncs = [ | |
"new", "await", "assert", "echo", "defined", "declared", | |
"newException", "countup", "countdown", "high", "low" | |
] | |
func tokClass(str: string, kind: TokenClass): string = | |
let norm = nimNormalize(str) | |
case norm | |
of builtin: "hljs-built_in" | |
of literal: "hljs-literal" | |
of commonFuncs: "hljs-keyword" | |
else: | |
case kind | |
of gtKeyword: "hljs-keyword" | |
of gtComment, gtLongComment: "hljs-comment" | |
of gtStringLit, gtLongStringLit, gtCharLit, gtRawData: "hljs-string" | |
# All number types | |
of gtDecNumber..gtFloatNumber: "hljs-number" | |
of gtRegularExpression: "hljs-regexp" | |
of gtEscapeSequence, gtDirective: "hljs-meta" | |
of gtIdentifier: | |
# Most types are PascalCase (start with an upper-case letter) | |
if norm.len > 0 and norm[0] in {'A'..'Z'}: "hljs-type" | |
else: "" | |
else: "" | |
proc highlightNim*(code: string, root: Element) = | |
var g: GeneralTokenizer | |
g.initGeneralTokenizer(code) | |
while true: | |
g.getNextToken(langNim) | |
# Get the string for the current identifier | |
var istr = substr(code, g.start, g.length + g.start - 1) | |
case g.kind | |
of gtEof: break | |
else: | |
# Get Highlight.js-compatible token class | |
let cls = tokClass(istr, g.kind) | |
var s = document.createElement("span") | |
s.appendChild(document.createTextNode(istr)) | |
if cls != "": | |
s.class = cls | |
root.appendChild(s) | |
g.deinitGeneralTokenizer() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment