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