• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37773

08 May 2024 07:57AM UTC coverage: 86.275% (-0.5%) from 86.821%
#37773

push

local

web-flow
Stabilize `MulAddMul` strategically (#52439)

Co-authored-by: Ashley Milsted <ashmilsted@gmail.com>

58 of 79 new or added lines in 4 files covered. (73.42%)

1130 existing lines in 37 files now uncovered.

74527 of 86383 relevant lines covered (86.28%)

15994665.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.2
/stdlib/Markdown/src/render/html.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
include("rich.jl")
4

5
# Utils
6

7
function withtag(f, io::IO, tag, attrs...)
363✔
8
    print(io, "<$tag")
366✔
9
    for (attr, value) in attrs
366✔
10
        print(io, " ")
86✔
11
        htmlesc(io, attr)
86✔
12
        print(io, "=\"")
86✔
13
        htmlesc(io, value)
86✔
14
        print(io, "\"")
86✔
15
    end
94✔
16
    f === nothing && return print(io, " />")
366✔
17

18
    print(io, ">")
363✔
19
    f()
374✔
20
    print(io, "</$tag>")
363✔
21
end
22

23
tag(io::IO, tag, attrs...) = withtag(nothing, io, tag, attrs...)
3✔
24

25
const _htmlescape_chars = Dict('<'=>"&lt;",   '>'=>"&gt;",
26
                               '"'=>"&quot;", '&'=>"&amp;",
27
                               # ' '=>"&nbsp;",
28
                               )
29
for ch in "'`!\$%()=+{}[]"
30
    _htmlescape_chars[ch] = "&#$(Int(ch));"
31
end
32

33
function htmlesc(io::IO, s::AbstractString)
491✔
34
    # s1 = replace(s, r"&(?!(\w+|\#\d+);)" => "&amp;")
35
    for ch in s
980✔
36
        print(io, get(_htmlescape_chars, ch, ch))
3,352✔
37
    end
3,169✔
38
end
39
function htmlesc(io::IO, s::Symbol)
40
    htmlesc(io, string(s))
37✔
41
end
42
function htmlesc(io::IO, xs::Union{AbstractString,Symbol}...)
×
43
    for s in xs
×
44
        htmlesc(io, s)
×
45
    end
×
46
end
47
function htmlesc(s::Union{AbstractString,Symbol})
×
48
    sprint(htmlesc, s)
×
49
end
50

51
# Block elements
52

53
function html(io::IO, content::Vector)
151✔
54
    for md in content
151✔
55
        html(io, md)
194✔
56
        println(io)
194✔
57
    end
194✔
58
end
59

60
html(io::IO, md::MD) = html(io, md.content)
123✔
61

62
function html(io::IO, header::Header{l}) where l
33✔
63
    withtag(io, "h$l") do
33✔
64
        htmlinline(io, header.text)
33✔
65
    end
66
end
67

68
function html(io::IO, code::Code)
12✔
69
    withtag(io, :pre) do
12✔
70
        if code.language == "styled"
12✔
UNCOV
71
            code = Code("", String(styled(code.code)))
×
72
        end
73
        maybe_lang = !isempty(code.language) ? Any[:class=>"language-$(code.language)"] : []
16✔
74
        withtag(io, :code, maybe_lang...) do
12✔
75
            htmlesc(io, code.code)
12✔
76
            # TODO should print newline if this is longer than one line ?
77
        end
78
    end
79
end
80

81
function html(io::IO, md::Paragraph)
111✔
82
    withtag(io, :p) do
111✔
83
        htmlinline(io, md.content)
111✔
84
    end
85
end
86

87
function html(io::IO, md::BlockQuote)
3✔
88
    withtag(io, :blockquote) do
3✔
89
        println(io)
3✔
90
        html(io, md.content)
3✔
91
    end
92
end
93

94
function html(io::IO, f::Footnote)
4✔
95
    withtag(io, :div, :class => "footnote", :id => "footnote-$(f.id)") do
4✔
96
        withtag(io, :p, :class => "footnote-title") do
4✔
97
            print(io, f.id)
4✔
98
        end
99
        html(io, f.text)
4✔
100
    end
101
end
102

103
function html(io::IO, md::Admonition)
3✔
104
    withtag(io, :div, :class => "admonition $(md.category)") do
3✔
105
        withtag(io, :p, :class => "admonition-title") do
3✔
106
            print(io, md.title)
3✔
107
        end
108
        html(io, md.content)
3✔
109
    end
110
end
111

112
function html(io::IO, md::List)
11✔
113
    maybe_attr = md.ordered > 1 ? Any[:start => string(md.ordered)] : []
21✔
114
    withtag(io, isordered(md) ? :ol : :ul, maybe_attr...) do
11✔
115
        for item in md.items
11✔
116
            println(io)
18✔
117
            withtag(io, :li) do
18✔
118
                html(io, item)
18✔
119
            end
120
        end
18✔
121
        println(io)
11✔
122
    end
123
end
124

125
function html(io::IO, md::HorizontalRule)
1✔
126
    tag(io, :hr)
1✔
127
end
128

129
html(io::IO, x) = tohtml(io, x)
6✔
130

131
# Inline elements
132

133
function htmlinline(io::IO, content::Vector)
193✔
134
    for x in content
193✔
135
        htmlinline(io, x)
307✔
136
    end
307✔
137
end
138

139
function htmlinline(io::IO, code::Code)
26✔
140
    if code.language == "styled"
26✔
UNCOV
141
        code = Code("", String(styled(code.code)))
×
142
    end
143
    withtag(io, :code) do
26✔
144
        htmlesc(io, code.code)
26✔
145
    end
146
end
147

148
function htmlinline(io::IO, md::Union{Symbol,AbstractString})
234✔
149
    htmlesc(io, md)
251✔
150
end
151

152
function htmlinline(io::IO, md::Bold)
13✔
153
    withtag(io, :strong) do
13✔
154
        htmlinline(io, md.text)
13✔
155
    end
156
end
157

158
function htmlinline(io::IO, md::Italic)
20✔
159
    withtag(io, :em) do
20✔
160
        htmlinline(io, md.text)
20✔
161
    end
162
end
163

UNCOV
164
function htmlinline(io::IO, md::Image)
×
UNCOV
165
    tag(io, :img, :src=>md.url, :alt=>md.alt)
×
166
end
167

168

169
function htmlinline(io::IO, f::Footnote)
4✔
170
    withtag(io, :a, :href => "#footnote-$(f.id)", :class => "footnote") do
4✔
171
        print(io, "[", f.id, "]")
4✔
172
    end
173
end
174

175
function htmlinline(io::IO, link::Link)
4✔
176
    withtag(io, :a, :href=>link.url) do
4✔
177
        htmlinline(io, link.text)
4✔
178
    end
179
end
180

181
function htmlinline(io::IO, br::LineBreak)
2✔
182
    tag(io, :br)
2✔
183
end
184

185
htmlinline(io::IO, x) = tohtml(io, x)
24✔
186

187
# API
188

189
export html
190

191
"""
192
    html([io::IO], md)
193

194
Output the contents of the Markdown object `md` in HTML format, either
195
writing to an (optional) `io` stream or returning a string.
196

197
One can alternatively use `show(io, "text/html", md)` or `repr("text/html", md)`, which
198
differ in that they wrap the output in a `<div class="markdown"> ... </div>` element.
199

200
# Examples
201
```jldoctest
202
julia> html(md"hello _world_")
203
"<p>hello <em>world</em></p>\\n"
204
```
205
"""
206
html(md) = sprint(html, md)
76✔
207

208
function show(io::IO, ::MIME"text/html", md::MD)
1✔
209
    withtag(io, :div, :class=>"markdown") do
1✔
210
        html(io, md)
1✔
211
    end
212
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc