First commit
commit
e22334952d
|
@ -0,0 +1,19 @@
|
||||||
|
A simple MD to HTML converter
|
||||||
|
|
||||||
|
## Compilation
|
||||||
|
|
||||||
|
1. `git clone https://git.kirbylife.dev/kirbylife/nim-md-to-html`
|
||||||
|
1. `cd nim-md-to-html`
|
||||||
|
1. `nimble build -d:release`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. `nim-md-to-html <path/to/file.md> </path/to/theme.css> > index.html`
|
||||||
|
|
||||||
|
The theme must be a classless CSS file.
|
||||||
|
I personally recommend [water.css](https://watercss.kognise.dev/), but on the internet there is a good variety, choose the one you like the most.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the LGPL 3.0 license.
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "kirbylife"
|
||||||
|
description = "A simple MD to HTML converter"
|
||||||
|
license = "LGPL-3.0-or-later"
|
||||||
|
srcDir = "src"
|
||||||
|
bin = @["md_to_html_embed"]
|
||||||
|
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 2.0"
|
||||||
|
requires "markdown == 0.8.7"
|
||||||
|
requires "glob == 0.11.3"
|
||||||
|
requires "regex == 0.25.0"
|
|
@ -0,0 +1,85 @@
|
||||||
|
import markdown
|
||||||
|
import glob
|
||||||
|
import regex
|
||||||
|
import std/htmlparser
|
||||||
|
import std/xmltree
|
||||||
|
import std/strtabs
|
||||||
|
import std/strutils
|
||||||
|
import std/os
|
||||||
|
import std/paths
|
||||||
|
import std/sequtils
|
||||||
|
import std/streams
|
||||||
|
import std/base64
|
||||||
|
|
||||||
|
const MAXOUTERLIMIT = 2
|
||||||
|
|
||||||
|
proc applyTheme(html: XmlNode, theme: string) =
|
||||||
|
let charset_att = {"charset": "utf-8"}.toXmlAttributes()
|
||||||
|
let charset = newXmlTree("meta", [], charset_att)
|
||||||
|
|
||||||
|
let theme_att = {"style": "text/css"}.toXmlAttributes()
|
||||||
|
let theme_content = newText(theme)
|
||||||
|
let style = newXmlTree("style", [theme_content], theme_att)
|
||||||
|
|
||||||
|
let head = newXmlTree("head", [charset, style])
|
||||||
|
|
||||||
|
html.insert(head, 0)
|
||||||
|
|
||||||
|
proc bytesToBase64(bytes: seq[byte]): string =
|
||||||
|
return " data:image/jpeg;charset=utf8;base64," & bytes.encode()
|
||||||
|
|
||||||
|
proc pathToBytes(path: string): seq[byte] =
|
||||||
|
const block_size = 4096
|
||||||
|
|
||||||
|
var
|
||||||
|
buffer: array[block_size, byte]
|
||||||
|
bytes: seq[byte]
|
||||||
|
total_bytes_readed = 0
|
||||||
|
|
||||||
|
let strm = openFileStream(path, fmRead)
|
||||||
|
|
||||||
|
while true:
|
||||||
|
let bytes_readed = strm.readData(addr(buffer), block_size)
|
||||||
|
if bytes_readed == 0:
|
||||||
|
break
|
||||||
|
bytes.add(buffer[0..<bytes_readed])
|
||||||
|
|
||||||
|
strm.close()
|
||||||
|
|
||||||
|
return bytes
|
||||||
|
|
||||||
|
proc embedImages(html: XmlNode, root: string) =
|
||||||
|
for node in html.findAll("img"):
|
||||||
|
# echo node
|
||||||
|
if node.attrs.hasKey("src"):
|
||||||
|
var src = node.attrs["src"]
|
||||||
|
if src.isEmptyOrWhitespace():
|
||||||
|
continue
|
||||||
|
if not src.startsWith("http"):
|
||||||
|
let search_param = root / "../".repeat(MAXOUTERLIMIT) / "**" / src
|
||||||
|
let possible_attempts = walkGlob(search_param).toSeq()
|
||||||
|
if possible_attempts.len() > 0:
|
||||||
|
let img_path = possible_attempts[0]
|
||||||
|
src = img_path.pathToBytes().bytesToBase64()
|
||||||
|
node.attrs["src"] = src
|
||||||
|
|
||||||
|
# let img_bytes = pathToBytes(src)
|
||||||
|
|
||||||
|
when isMainModule and declared(commandLineParams):
|
||||||
|
let
|
||||||
|
params = commandLineParams()
|
||||||
|
md_src = absolutePath(params[0])
|
||||||
|
md_root = splitFile(md_src).dir
|
||||||
|
theme_src = params[1]
|
||||||
|
|
||||||
|
let raw_md = readFile(md_src).replace(re2"!\[\[(.+)\]\]", "<img src=\"$1\">")
|
||||||
|
let raw_html = markdown(raw_md, config=initGfmConfig())
|
||||||
|
let parsed_html = parseHtml(raw_html)
|
||||||
|
|
||||||
|
let raw_theme = readFile(theme_src)
|
||||||
|
|
||||||
|
embedImages(parsed_html, md_root)
|
||||||
|
applyTheme(parsed_html, raw_theme)
|
||||||
|
|
||||||
|
echo parsed_html
|
||||||
|
|
Loading…
Reference in New Issue