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!😄