import gleam/string
import gleam/list
import gleam/dict.{type Dict}
import gleam/uri
import gleam/dynamic
import gleam/io
import kirala/markdown/strfmt.{str as s, text}
import kirala/markdown/parser.{
type Token, type UrlData, BlockQuote, Bold, CheckedList, CodeBlock, CodeLine,
CodeSpan, Definition, DefinitionIs, DefinitionOf, FootNote, FootNoteUrlDef, H,
HR, ImgLink, InsertedText, Italic, Line, LineIndent, ListItem, MarkedText,
Note, OrderedList, StdList, StrikeThrough, Table, Text, TokenRes,
UncheckedList, Url, UrlFootNote, UrlLink, UrlPlain, parse, pop_grapheme,
ret_string, ret_string_trim,
}
fn url_of(symbols: Dict(String, String), url: UrlData) -> String {
case url {
UrlPlain(str) -> str
UrlFootNote(id) ->
case dict.get(symbols, id) {
Ok(str) -> str
_ -> id
}
}
}
pub fn html_encode_(src: String, acc: String) -> String {
case src {
"" -> acc
_ -> {
let #(newacc, rest) = case src {
"&" <> rest -> #(acc <> "&", rest)
"<" <> rest -> #(acc <> "<", rest)
">" <> rest -> #(acc <> ">", rest)
_ -> {
let #(chr, rest) = parser.pop_grapheme(src)
#(acc <> chr, rest)
}
}
html_encode_(rest, newacc)
}
}
}
pub fn html_encode(src: String) -> String {
html_encode_(src, "")
|> ret_string
//let bits = html_encode_(bit_string.from_string(src), <<>>)
//log("~p", [bits])
//bits
//|> ret_string
}
pub fn emit_text(symbols: Dict(String, String), t: Token) -> String {
case t {
Text(text) -> html_encode(text)
Bold(t) | Italic(t) | StrikeThrough(t) | MarkedText(t) | InsertedText(t) ->
emit(symbols, t)
Line(ts) -> {
let str =
list.map(ts, fn(e) { emit(symbols, e) })
|> string.concat
case string.length(string.trim(str)) == 0 {
True -> "
"
_ -> str
}
}
Url(UrlFootNote(url)) -> url
Url(UrlPlain(url)) -> url
UrlLink(caption, url) -> {
let clen = string.length(caption) - 1
let tcaption = case string.starts_with(caption, "\\") {
True -> html_encode(string.slice(caption, 1, clen))
_ -> caption
}
tcaption
}
_ -> ""
}
}
pub fn emit(symbols: Dict(String, String), t: Token) -> String {
case t {
Text(text) -> html_encode(text)
Bold(t) -> text(["", emit(symbols, t), ""])
Italic(t) -> text(["", emit(symbols, t), ""])
StrikeThrough(t) -> text(["", emit(symbols, t), ""])
MarkedText(t) -> text(["", emit(symbols, t), ""])
InsertedText(t) -> text(["", emit(symbols, t), ""])
LineIndent(_, ts) | Line(ts) -> {
let str =
list.map(ts, fn(e) { emit(symbols, e) })
|> string.concat
case string.length(string.trim(str)) == 0 {
True -> "
"
_ -> str
}
}
H(id, level, title) ->
text([
"",
caption,
"",
])
FootNote(id, t) ->
text(["
", code, ""])
CodeBlock(syntax, filename, code) ->
case syntax {
"csv" | "tsv" ->
text([
"",
code,
"\n",
code,
"\n"), emit(symbols, t)], ..acc], ) #(BlockQuote(indent1, t1), _) -> #( t, [[ntimes(indent1, ""), emit(symbols, t)], ..acc], ) #(_, BlockQuote(indent2, t2)) -> #( t, [[ntimes(indent2, "
"), emit(symbols, t)], ..acc], ) // CodeLine #(CodeLine(t1), CodeLine(t2)) -> #(t, [[emit(symbols, t)], ..acc]) #(CodeLine(t1), _) -> #(t, [["", emit(symbols, t)], ..acc]) #(_, CodeLine(t2)) -> #(t, [["", emit(symbols, t)], ..acc]) // Definition #(_, DefinitionOf(t2)) -> #( t, [["", emit(symbols, t)], ..acc]) // _ -> #(t, [[emit(symbols, t)], ..acc]) } }) strlist |> list.reverse |> list.flatten |> string.concat } pub fn convert_bytes_outline(bytes: String) -> String { let #(tokens, symbols) = convert_(0, bytes, [], dict.new()) let filteredtokens = list.fold(tokens, [], fn(acc: List(Token), t) -> List(Token) { case t { H(id, level, title) -> [ ListItem( StdList, level, UrlLink(emit_text(symbols, title), UrlPlain(text(["#H", s(id)]))), ), ..acc ] _ -> acc } }) |> list.reverse convert_tokens_(filteredtokens, symbols) } pub fn convert_bytes_digest(bytes: String) -> String { let #(tokens, symbols) = convert_(0, bytes, [], dict.new()) let filteredtokens: List(String) = list.fold(tokens, [], fn(acc: List(List(String)), t) -> List(List(String)) { case t { H(id, level, title) -> [[emit_text(symbols, title), "
- ", emit(symbols, t2), "
"], ..acc], ) #(_, Definition(t2)) -> { let tlines = list.map(t2, fn(e) { [emit(symbols, e), "
"] }) |> list.flatten |> string.concat #(t, [[""], ..acc]) } #(Definition(t1), _) -> #(t, [["- ", tlines, "
\n"], ..acc] Line(_) -> [[emit_text(symbols, t), "
\n"], ..acc] //_ -> [emit_text(symbols, t), ..acc] _ -> acc } }) |> list.reverse |> list.flatten //convert_tokens_(filteredtokens, symbols) string.concat(filteredtokens) } // ------------------------------------------------------------------------------------------------------------------------------------