Initial commit: initial implementation.
This commit is contained in:
129
src/pco_chordspkg/html.nim
Normal file
129
src/pco_chordspkg/html.nim
Normal file
@@ -0,0 +1,129 @@
|
||||
import std/logging, std/os, std/strutils
|
||||
import zero_functional
|
||||
|
||||
import ./ast
|
||||
|
||||
const DEFAULT_STYLESHEET* = """
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html { font-family: sans-serif; }
|
||||
|
||||
h2 { font-size: 1.25em; }
|
||||
|
||||
section { margin-top: 1em; }
|
||||
|
||||
h3 {
|
||||
font-size: 1.125rem;
|
||||
margin-bottom: 0.5em;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.line {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
|
||||
margin-left: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.word {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.word.space-after { margin-right: 0.5em; }
|
||||
|
||||
.chord {
|
||||
font-weight: 600;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
body { margin: 1em; }
|
||||
}
|
||||
</style>
|
||||
"""
|
||||
|
||||
proc toHtml(node: ChordChartNode, indent: string): string =
|
||||
result = ""
|
||||
case node.kind
|
||||
of ccnkSection:
|
||||
result &= indent & "<section>\p" &
|
||||
indent & " " & "<h3>" & node.sectionName & "</h3>\p"
|
||||
|
||||
result &= join(
|
||||
node.sectionContents --> map(it.toHtml(indent & " ")),
|
||||
"\p")
|
||||
|
||||
result &= indent & "</section>"
|
||||
|
||||
of ccnkLine:
|
||||
result &= indent & "<div class=line>\p"
|
||||
result &= join(node.line --> map(it.toHtml(indent & " ")), "")
|
||||
result &= indent & "</div>"
|
||||
|
||||
of ccnkWord:
|
||||
result &= "<span class='word"
|
||||
#if node.spaceBefore: result&=" space-before"
|
||||
if node.spaceAfter: result&=" space-after"
|
||||
result &= "'>"
|
||||
|
||||
if node.chord.len > 0:
|
||||
result &= "<span class=chord>" & node.chord & "</span>"
|
||||
|
||||
result &= "<span class=lyric>"
|
||||
if node.word.len > 0: result &= node.word
|
||||
else: result &= " "
|
||||
result &= "</span>"
|
||||
|
||||
result &= "</span>"
|
||||
|
||||
of ccnkNote:
|
||||
result &= indent & "<div class=note>" & node.note & "</div>"
|
||||
|
||||
of ccnkColBreak: discard #FIXME
|
||||
of ccnkPageBreak: discard #FIXME
|
||||
of ccnkTransposeKey: discard #FIXME
|
||||
of ccnkRedefineKey: discard #FIXME
|
||||
|
||||
proc toHtml*(
|
||||
cc: ChordChart,
|
||||
stylesheets = @[DEFAULT_STYLESHEET],
|
||||
scripts: seq[string] = @[]): string =
|
||||
|
||||
result = """<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>""" & cc.metadata.title & "</title>\p"
|
||||
|
||||
for ss in stylesheets:
|
||||
if ss.startsWith("<style>"): result &= ss
|
||||
elif fileExists(ss): result &= "<style>\p" & readFile(ss) & "\p</style>"
|
||||
else: warn "cannot read stylesheet file '" & ss & "'"
|
||||
|
||||
for sc in scripts:
|
||||
if sc.startsWith("<script"): result &= sc
|
||||
elif fileExists(sc): result &= "<script>\p" & readFile(sc) & "\p</script>"
|
||||
else: warn "cannot read script file '" & sc & "'"
|
||||
|
||||
result &= " </head>\p <body>"
|
||||
|
||||
var indent = " "
|
||||
#
|
||||
# Title
|
||||
result &= indent & "<h1>" & cc.metadata.title & "</h1>\p"
|
||||
|
||||
result &= indent & "<h2>Key: " & $cc.metadata.key
|
||||
if cc.metadata.contains("bpm"): result &= " " & cc.metadata["bpm"] & "bpm"
|
||||
result &= "</h2>\p"
|
||||
|
||||
result &= join(cc.nodes --> map(it.toHtml(indent & " ")), "\p")
|
||||
|
||||
result &= " </body>\p</html>"
|
||||
Reference in New Issue
Block a user