Skip to content

Commit 71ff605

Browse files
committed
Refactor MIME rendering to make it extensible!
1 parent 0dbc6a3 commit 71ff605

File tree

1 file changed

+138
-91
lines changed

1 file changed

+138
-91
lines changed

src/writer.jl

Lines changed: 138 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -387,104 +387,151 @@ function render(io::IO, mime::MIME"text/plain", node::Documenter.MarkdownAST.Nod
387387
end
388388

389389
# Select the "best" rendering MIME for markdown output!
390+
391+
"""
392+
mime_priority(mime::MIME)::Float64
393+
394+
This function returns a priority for a given MIME type, which
395+
is used to select the best MIME type for rendering a given
396+
element.
397+
"""
398+
function mime_priority end
399+
mime_priority(::MIME"text/markdown") = 1.0
400+
mime_priority(::MIME"text/html") = 2.0
401+
mime_priority(::MIME"image/svg+xml") = 3.0
402+
mime_priority(::MIME"image/png") = 4.0
403+
mime_priority(::MIME"image/webp") = 5.0
404+
mime_priority(::MIME"image/jpeg") = 6.0
405+
mime_priority(::MIME"image/png+lightdark") = 7.0
406+
mime_priority(::MIME"image/jpeg+lightdark") = 8.0
407+
mime_priority(::MIME"image/svg+xml+lightdark") = 9.0
408+
mime_priority(::MIME"image/gif") = 10.0
409+
mime_priority(::MIME"video/mp4") = 11.0
410+
mime_priority(::MIME"text/plain") = 12.0
411+
mime_priority(::MIME) = Inf
412+
413+
function render_mime(io::IO, mime::MIME, node, element, page, doc; kwargs...)
414+
@warn("DocumenterVitepress: Unknown MIME type $mime provided and no alternatives given. Ignoring render!")
415+
end
416+
417+
function render_mime(io::IO, mime::MIME"text/markdown", node, element, page, doc; kwargs...)
418+
println(io, element)
419+
end
420+
421+
function render_mime(io::IO, mime::MIME"text/html", node, element, page, doc; kwargs...)
422+
println(io, element)
423+
end
424+
425+
function render_mime(io::IO, mime::MIME"image/svg+xml", node, element, page, doc; kwargs...)
426+
# NOTE: It seems that we can't simply save the SVG images as a file and include them
427+
# as browsers seem to need to have the xmlns attribute set in the <svg> tag if you
428+
# want to include it with <img>. However, setting that attribute is up to the code
429+
# creating the SVG image.
430+
image_text = d[MIME"image/svg+xml"()]
431+
# Additionally, Vitepress complains about the XML version and encoding string below,
432+
# so we just remove this bad hombre!
433+
bad_hombre_string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" |> lowercase
434+
location = findfirst(bad_hombre_string, lowercase(image_text))
435+
if !isnothing(location)
436+
image_text = replace(image_text, image_text[location] => "")
437+
end
438+
println(io, image_text)
439+
end
440+
441+
function render_mime(io::IO, mime::MIME"image/png", node, element, page, doc; kwargs...)
442+
filename = String(rand('a':'z', 7))
443+
write(joinpath(dirname(page.build), md_output_path, "$(filename).png"),
444+
base64decode(element))
445+
println(io, "![]($(filename).png)")
446+
end
447+
448+
function render_mime(io::IO, mime::MIME"image/webp", node, element, page, doc; kwargs...)
449+
filename = String(rand('a':'z', 7))
450+
write(joinpath(dirname(page.build), md_output_path, "$(filename).webp"),
451+
base64decode(element))
452+
println(io, "![]($(filename).webp)")
453+
end
454+
455+
function render_mime(io::IO, mime::MIME"image/jpeg", node, element, page, doc; kwargs...)
456+
filename = String(rand('a':'z', 7))
457+
write(joinpath(dirname(page.build), md_output_path, "$(filename).jpeg"),
458+
base64decode(element))
459+
println(io, "![]($(filename).jpeg)")
460+
end
461+
462+
function render_mime(io::IO, mime::MIME"image/png+lightdark", node, element, page, doc; kwargs...)
463+
fig_light, fig_dark, backend = element
464+
filename = String(rand('a':'z', 7))
465+
write(joinpath(dirname(page.build), md_output_path, "$(filename)_light.png"), fig_light)
466+
write(joinpath(dirname(page.build), md_output_path, "$(filename)_dark.png"), fig_dark)
467+
println(io,
468+
"""
469+
![]($(filename)_light.png){.light-only}
470+
![]($(filename)_dark.png){.dark-only}
471+
"""
472+
)
473+
end
474+
475+
function render_mime(io::IO, mime::MIME"image/jpeg+lightdark", node, element, page, doc; kwargs...)
476+
fig_light, fig_dark, backend = element
477+
filename = String(rand('a':'z', 7))
478+
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_light.jpeg"), fig_light)
479+
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_dark.jpeg"), fig_dark)
480+
println(io,
481+
"""
482+
![]($(filename)_light.jpeg){.light-only}
483+
![]($(filename)_dark.jpeg){.dark-only}
484+
"""
485+
)
486+
end
487+
488+
function render_mime(io::IO, mime::MIME"image/svg+xml+lightdark", node, element, page, doc; kwargs...)
489+
fig_light, fig_dark, backend = element
490+
filename = String(rand('a':'z', 7))
491+
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_light.svg"), fig_light)
492+
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_dark.svg"), fig_dark)
493+
println(io,
494+
"""
495+
<img src = "$(filename)_light.svg" style=".light-only"></img>
496+
<img src = "$(filename)_dark.svg" style=".dark-only"></img>
497+
"""
498+
)
499+
end
500+
501+
function render_mime(io::IO, mime::MIME"image/gif", node, element, page, doc; kwargs...)
502+
filename = String(rand('a':'z', 7))
503+
write(joinpath(dirname(page.build), md_output_path, "$(filename).gif"),
504+
base64decode(element))
505+
println(io, "![]($(filename).gif)")
506+
end
507+
508+
function render_mime(io::IO, mime::MIME"video/mp4", node, element, page, doc; kwargs...)
509+
filename = String(rand('a':'z', 7))
510+
write(joinpath(dirname(page.build), md_output_path, "$(filename).mp4"),
511+
base64decode(element))
512+
println(io, "<video src='$filename.mp4' controls='controls' autoplay='autoplay'></video>")
513+
end
514+
515+
function render_mime(io::IO, mime::MIME"text/plain", node, element, page, doc; kwargs...)
516+
return render(io, mime, node, Markdown.Code(element), page, doc; kwargs...)
517+
end
518+
390519
function render(io::IO, mime::MIME"text/plain", node::Documenter.MarkdownAST.Node, d::Dict{MIME, Any}, page, doc; kwargs...)
391520

392521
settings_ind = findfirst(x -> x isa MarkdownVitepress, doc.user.format)
393522
settings = doc.user.format[settings_ind]
394523
md_output_path = settings.md_output_path
395524

396-
filename = String(rand('a':'z', 7))
397-
if haskey(d, MIME"text/markdown"())
398-
println(io, d[MIME"text/markdown"()])
399-
elseif haskey(d, MIME"text/html"())
400-
println(io, d[MIME"text/html"()])
401-
elseif haskey(d, MIME"image/svg+xml"())
402-
# NOTE: It seems that we can't simply save the SVG images as a file and include them
403-
# as browsers seem to need to have the xmlns attribute set in the <svg> tag if you
404-
# want to include it with <img>. However, setting that attribute is up to the code
405-
# creating the SVG image.
406-
image_text = d[MIME"image/svg+xml"()]
407-
# Additionally, Vitepress complains about the XML version and encoding string below,
408-
# so we just remove this bad hombre!
409-
bad_hombre_string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" |> lowercase
410-
location = findfirst(bad_hombre_string, lowercase(image_text))
411-
if !isnothing(location)
412-
image_text = replace(image_text, image_text[location] => "")
413-
end
414-
println(io, image_text)
415-
elseif haskey(d, MIME"image/png"())
416-
write(joinpath(dirname(page.build), md_output_path, "$(filename).png"),
417-
base64decode(d[MIME"image/png"()]))
418-
println(io,
419-
"""
420-
![]($(filename).png)
421-
""")
422-
elseif haskey(d, MIME"image/webp"())
423-
write(joinpath(dirname(page.build), md_output_path, "$(filename).webp"),
424-
base64decode(d[MIME"image/webp"()]))
425-
println(io,
426-
"""
427-
![]($(filename).webp)
428-
""")
429-
elseif haskey(d, MIME"image/jpeg"())
430-
write(joinpath(dirname(page.build), md_output_path, "$(filename).jpeg"),
431-
base64decode(d[MIME"image/jpeg"()]))
432-
println(io,
433-
"""
434-
![]($(filename).jpeg)
435-
""")
436-
elseif haskey(d, MIME"image/png+lightdark"())
437-
fig_light, fig_dark, backend = d[MIME"image/png+lightdark"()]
438-
write(joinpath(dirname(page.build), md_output_path, "$(filename)_light.png"), fig_light)
439-
write(joinpath(dirname(page.build), md_output_path, "$(filename)_dark.png"), fig_dark)
440-
println(io,
441-
"""
442-
![]($(filename)_light.png){.light-only}
443-
![]($(filename)_dark.png){.dark-only}
444-
"""
445-
)
446-
elseif haskey(d, MIME"image/jpeg+lightdark"())
447-
fig_light, fig_dark, backend = d[MIME"image/jpeg+lightdark"()]
448-
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_light.jpeg"), fig_light)
449-
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_dark.jpeg"), fig_dark)
450-
println(io,
451-
"""
452-
![]($(filename)_light.jpeg){.light-only}
453-
![]($(filename)_dark.jpeg){.dark-only}
454-
"""
455-
)
456-
elseif haskey(d, MIME"image/svg+xml+lightdark"())
457-
fig_light, fig_dark, backend = d[MIME"image/svg+lightdark"()]
458-
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_light.svg"), fig_light)
459-
Main.Makie.save(joinpath(dirname(page.build), md_output_path, "$(filename)_dark.svg"), fig_dark)
460-
println(io,
461-
"""
462-
<img src = "$(filename)_light.svg" style=".light-only"></img>
463-
<img src = "$(filename)_dark.svg" style=".dark-only"></img>
464-
"""
465-
)
466-
elseif haskey(d, MIME"image/gif"())
467-
write(joinpath(dirname(page.build), md_output_path, "$(filename).gif"),
468-
base64decode(d[MIME"image/gif"()]))
469-
println(io,
470-
"""
471-
![]($(filename).gif)
472-
""")
473-
elseif haskey(d, MIME"video/mp4"())
474-
write(joinpath(dirname(page.build), md_output_path, "$(filename).gif"),
475-
base64decode(d[MIME"image/gif"()]))
476-
println(io,
477-
"""
478-
<video src="$filename.mp4" controls="controls" autoplay="autoplay"></video>)
479-
""")
480-
elseif haskey(d, MIME"text/plain"())
481-
text = d[MIME"text/plain"()]
482-
out = repr(MIME"text/plain"(), ANSIColoredPrinters.PlainTextPrinter(IOBuffer(text)))
483-
render(io, mime, node, Markdown.Code(out), page, doc; kwargs...)
484-
else
485-
error("this should never happen.")
525+
available_mimes = keys(d)
526+
if isempty(available_mimes)
527+
return nothing
486528
end
487-
return nothing
529+
# Sort the available mimes by priority
530+
sorted_mimes = sort(collect(available_mimes), by = mime_priority)
531+
# Select the best MIME type for rendering
532+
best_mime = sorted_mimes[1]
533+
# Render the best MIME type
534+
render_mime(io, best_mime, node, d[best_mime], page, doc; kwargs...)
488535
end
489536

490537
## Basic Nodes. AKA: any other content that hasn't been handled yet.

0 commit comments

Comments
 (0)