First commit

main
kirbylife 2024-05-11 01:19:08 -06:00
commit e22334952d
3 changed files with 120 additions and 0 deletions

19
README.md 100644
View File

@ -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.

View File

@ -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"

View File

@ -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