1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
# This file is a part of Julia. License is MIT: http://julialang.org/license
include("rich.jl")
# 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{l}(io::IO, header::Header{l})
withtag(io, "h$l") do
htmlinline(io, header.text)
end
end
function html(io::IO, code::Code)
withtag(io, :pre) do
maybe_lang = 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, md::List)
withtag(io, md.ordered ? :ol : :ul) do
for item in md.items
println(io)
withtag(io, :li) do
htmlinline(io, item)
end
end
println(io)
end
end
function html(io::IO, md::HorizontalRule)
tag(io, :hr)
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, 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, 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
export html
html(md) = sprint(html, md)
function writemime(io::IO, ::MIME"text/html", md::MD)
withtag(io, :div, :class=>"markdown") do
html(io, md)
end
end
|