We introduce how to implement simple html syntax highlight using Nim. We use highlight in stdlib to parse syntax. Then we use karax and htmlgen to generate Html.
import module
We need karax which constructs DSL to generate Html file and use htmlgen to generate Html strings.
First you should use command nimble install karax to install karax.
karax can be used as server side rendering and also single page application. To be simple, karax can be used to generate Html and Javascript.
import karax / [karaxdsl, vdom]
import packages/docutils/highlite
from htmlgen import span
from xmltree import escape
## code block
const code = """
import hello
type
TreeObj* = object
left*: ref TreeObj
right*: ref TreeObj
value*: char
priority*: float
Tree* = ref TreeObj
## escape `>=`
if a >= b:
echo a + b
"""
Generate HTML
karax supply text function accepting strings and verbatim function accepting raw Html strings.
We use link CSS to render keywords, comments, symbols, etc.
CSS looks like this.(highlight.css)
span.Keyword {
color: blue;
font-size: 18px;
}
span.Operator {
color: purple;
font-size: 18px;
}
span.Comment {
color: green;
font-size: 18px;
}
List Nim code as below, buildLang function uses stdlib highlight to parse syntax information and generates Html strings.
proc buildPre*(code: string): string =
let vnode = buildHtml(tdiv):
pre(class = "text"): text code
result = $vnode
proc buildVerbatimPre*(code: string, lang: string = "lang-Nim"): string =
let vnode = buildHtml(tdiv):
link(rel="stylesheet", `type`="text/css", href = "highlight.css")
pre(class = lang): verbatim code
result = $vnode
proc buildLang*(code: string): string =
var toknizr: GeneralTokenizer
initGeneralTokenizer(toknizr, code)
while true:
getNextToken(toknizr, langNim)
case toknizr.kind
of gtEof: break
of gtNone, gtWhitespace:
result.add substr(code, toknizr.start, toknizr.length +
toknizr.start - 1)
else:
result.add span(class=tokenClassToStr[toknizr.kind], escape(substr(code, toknizr.start, toknizr.length +
toknizr.start - 1)))
proc buildCode*(code: string, lang: string = "Nim"): string =
if getSourceLanguage(lang) != langNim:
return buildPre(code)
buildVerbatimPre(buildLang(code))
Let’s test our results,use openDefaultBrowser to preview.
import browsers
let file = "highlight.html"
let f = open(file, fmWrite)
f.write buildCode(code)
f.close()
openDefaultBrowser(file)
Top comments (2)
:)
Nice catch!😄