mirror of https://github.com/mpastell/Weave.jl
Add markdown2html writer, remove Documenter depency
parent
88d8665e03
commit
b2b143c22e
1
REQUIRE
1
REQUIRE
|
@ -4,6 +4,5 @@ FileIO
|
||||||
JSON
|
JSON
|
||||||
Highlights
|
Highlights
|
||||||
Mustache
|
Mustache
|
||||||
Documenter
|
|
||||||
YAML
|
YAML
|
||||||
Compat 0.25.0
|
Compat 0.25.0
|
||||||
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
module Markdown2HTML
|
||||||
|
# Markdown to HTML writer, Modified from Julia Base.Markdown html writer
|
||||||
|
using Base.Markdown: MD, Header, Code, Paragraph, BlockQuote, Footnote,
|
||||||
|
Admonition, List, HorizontalRule, Bold, Italic, Image, Link, LineBreak,
|
||||||
|
LaTeX
|
||||||
|
|
||||||
|
|
||||||
|
function tohtml(io::IO, m::MIME"text/html", x)
|
||||||
|
show(io, m, x)
|
||||||
|
end
|
||||||
|
|
||||||
|
function tohtml(io::IO, m::MIME"text/plain", x)
|
||||||
|
htmlesc(io, sprint(show, m, x))
|
||||||
|
end
|
||||||
|
|
||||||
|
function tohtml(io::IO, m::MIME"image/png", img)
|
||||||
|
print(io, """<img src="data:image/png;base64,""")
|
||||||
|
print(io, stringmime(m, img))
|
||||||
|
print(io, "\" />")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tohtml(m::MIME"image/svg+xml", img)
|
||||||
|
show(io, m, img)
|
||||||
|
end
|
||||||
|
|
||||||
|
# AbstractDisplay infrastructure
|
||||||
|
|
||||||
|
function bestmime(val)
|
||||||
|
for mime in ("text/html", "image/svg+xml", "image/png", "text/plain")
|
||||||
|
mimewritable(mime, val) && return MIME(Symbol(mime))
|
||||||
|
end
|
||||||
|
error("Cannot render $val to Markdown.")
|
||||||
|
end
|
||||||
|
|
||||||
|
tohtml(io::IO, x) = tohtml(io, bestmime(x), x)
|
||||||
|
|
||||||
|
|
||||||
|
# Utils
|
||||||
|
|
||||||
|
function withtag(f, io::IO, tag, attrs...)
|
||||||
|
print(io, "<$tag")
|
||||||
|
for (attr, value) in attrs
|
||||||
|
print(io, " ")
|
||||||
|
htmlesc(io, attr)
|
||||||
|
print(io, "=\"")
|
||||||
|
htmlesc(io, value)
|
||||||
|
print(io, "\"")
|
||||||
|
end
|
||||||
|
f === nothing && return print(io, " />")
|
||||||
|
|
||||||
|
print(io, ">")
|
||||||
|
f()
|
||||||
|
print(io, "</$tag>")
|
||||||
|
end
|
||||||
|
|
||||||
|
tag(io::IO, tag, attrs...) = withtag(nothing, io, tag, attrs...)
|
||||||
|
|
||||||
|
const _htmlescape_chars = Dict('<'=>"<", '>'=>">",
|
||||||
|
'"'=>""", '&'=>"&",
|
||||||
|
# ' '=>" ",
|
||||||
|
)
|
||||||
|
for ch in "'`!\$%()=+{}[]"
|
||||||
|
_htmlescape_chars[ch] = "&#$(Int(ch));"
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlesc(io::IO, s::AbstractString)
|
||||||
|
# s1 = replace(s, r"&(?!(\w+|\#\d+);)" => "&")
|
||||||
|
for ch in s
|
||||||
|
print(io, get(_htmlescape_chars, ch, ch))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function htmlesc(io::IO, s::Symbol)
|
||||||
|
htmlesc(io, string(s))
|
||||||
|
end
|
||||||
|
function htmlesc(io::IO, xs::Union{AbstractString,Symbol}...)
|
||||||
|
for s in xs
|
||||||
|
htmlesc(io, s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function htmlesc(s::Union{AbstractString,Symbol})
|
||||||
|
sprint(htmlesc, s)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Block elements
|
||||||
|
|
||||||
|
function html(io::IO, content::Vector)
|
||||||
|
for md in content
|
||||||
|
html(io, md)
|
||||||
|
println(io)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
html(io::IO, md::MD) = html(io, md.content)
|
||||||
|
|
||||||
|
function html(io::IO, header::Header{l}) where l
|
||||||
|
withtag(io, "h$l") do
|
||||||
|
htmlinline(io, header.text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, code::Code)
|
||||||
|
withtag(io, :pre) do
|
||||||
|
maybe_lang = !isempty(code.language) ? Any[:class=>"language-$(code.language)"] : []
|
||||||
|
withtag(io, :code, maybe_lang...) do
|
||||||
|
htmlesc(io, code.code)
|
||||||
|
# TODO should print newline if this is longer than one line ?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, md::Paragraph)
|
||||||
|
withtag(io, :p) do
|
||||||
|
htmlinline(io, md.content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, md::BlockQuote)
|
||||||
|
withtag(io, :blockquote) do
|
||||||
|
println(io)
|
||||||
|
html(io, md.content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, f::Footnote)
|
||||||
|
withtag(io, :div, :class => "footnote", :id => "footnote-$(f.id)") do
|
||||||
|
withtag(io, :p, :class => "footnote-title") do
|
||||||
|
print(io, f.id)
|
||||||
|
end
|
||||||
|
html(io, f.text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, md::Admonition)
|
||||||
|
withtag(io, :div, :class => "admonition $(md.category)") do
|
||||||
|
withtag(io, :p, :class => "admonition-title") do
|
||||||
|
print(io, md.title)
|
||||||
|
end
|
||||||
|
html(io, md.content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, md::List)
|
||||||
|
maybe_attr = md.ordered > 1 ? Any[:start => string(md.ordered)] : []
|
||||||
|
withtag(io, isordered(md) ? :ol : :ul, maybe_attr...) do
|
||||||
|
for item in md.items
|
||||||
|
println(io)
|
||||||
|
withtag(io, :li) do
|
||||||
|
html(io, item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
println(io)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, md::HorizontalRule)
|
||||||
|
tag(io, :hr)
|
||||||
|
end
|
||||||
|
|
||||||
|
function html(io::IO, tex::LaTeX)
|
||||||
|
withtag(io, :p, :class => "math") do
|
||||||
|
write(io, string("\\[", tex.formula, "\\]"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
html(io::IO, x) = tohtml(io, x)
|
||||||
|
|
||||||
|
# Inline elements
|
||||||
|
|
||||||
|
function htmlinline(io::IO, content::Vector)
|
||||||
|
for x in content
|
||||||
|
htmlinline(io, x)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, code::Code)
|
||||||
|
withtag(io, :code) do
|
||||||
|
htmlesc(io, code.code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, tex::LaTeX)
|
||||||
|
withtag(io, :span, :class => "math") do
|
||||||
|
write(io, string("\$", tex.formula, "\$"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, md::Union{Symbol,AbstractString})
|
||||||
|
htmlesc(io, md)
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, md::Bold)
|
||||||
|
withtag(io, :strong) do
|
||||||
|
htmlinline(io, md.text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, md::Italic)
|
||||||
|
withtag(io, :em) do
|
||||||
|
htmlinline(io, md.text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, md::Image)
|
||||||
|
tag(io, :img, :src=>md.url, :alt=>md.alt)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function htmlinline(io::IO, f::Footnote)
|
||||||
|
withtag(io, :a, :href => "#footnote-$(f.id)", :class => "footnote") do
|
||||||
|
print(io, "[", f.id, "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, link::Link)
|
||||||
|
withtag(io, :a, :href=>link.url) do
|
||||||
|
htmlinline(io, link.text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function htmlinline(io::IO, br::LineBreak)
|
||||||
|
tag(io, :br)
|
||||||
|
end
|
||||||
|
|
||||||
|
htmlinline(io::IO, x) = tohtml(io, x)
|
||||||
|
|
||||||
|
# API
|
||||||
|
|
||||||
|
html(md) = sprint(html, md)
|
||||||
|
|
||||||
|
function show(io::IO, ::MIME"text/html", md::MD)
|
||||||
|
withtag(io, :div, :class=>"markdown") do
|
||||||
|
html(io, md)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
|
@ -1,4 +1,5 @@
|
||||||
import Mustache, Highlights, Documenter
|
import Mustache, Highlights
|
||||||
|
import .Markdown2HTML
|
||||||
using Compat
|
using Compat
|
||||||
|
|
||||||
function format(doc::WeaveDoc)
|
function format(doc::WeaveDoc)
|
||||||
|
@ -132,7 +133,8 @@ function format_chunk(chunk::DocChunk, formatdict, docformat::JMarkdown2HTML)
|
||||||
#invokelatest seems to be needed here
|
#invokelatest seems to be needed here
|
||||||
#to fix "invalid age range" on 0.6 #21653
|
#to fix "invalid age range" on 0.6 #21653
|
||||||
m = Compat.invokelatest(Base.Markdown.parse, text)
|
m = Compat.invokelatest(Base.Markdown.parse, text)
|
||||||
return string(Documenter.Writers.HTMLWriter.mdconvert(m))
|
|
||||||
|
return string(Markdown2HTML.html(m))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ f = Weave.format_chunk(dchunk, pformat.formatdict, pformat)
|
||||||
@test f == content
|
@test f == content
|
||||||
|
|
||||||
docformat = Weave.formats["md2html"]
|
docformat = Weave.formats["md2html"]
|
||||||
f_check = "<div><h1>Test chunk</h1><p>Test rendering <span>\$\alpha\$</span></p></div>"
|
f_check = "<h1>Test chunk</h1>\n<p>Test rendering <span class=\"math\">\$\alpha\$</span></p>\n"
|
||||||
f = Weave.format_chunk(dchunk, docformat.formatdict, docformat)
|
f = Weave.format_chunk(dchunk, docformat.formatdict, docformat)
|
||||||
@test f_check == f
|
@test f_check == f
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue