# How to get a markdown repr of an object? (MIME type fallbacks)

**URL:** <https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242>\
**Category:** General Usage\
**Tags:** question, markdown\
**Created:** [April 17, 2019, 2:53pm UTC](https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242 "2019-04-17T14:53:05Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [April 17, 2019, 2:53pm UTC](https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242/1 "2019-04-17T14:53:05Z")

</div>

`repr` takes a mimetype arguement.  
Sometimes, it is evan used.  
e.g.

```julia
julia> repr("text/html",Docs.html"<b>foo</b>")
"<b>foo</b>"

julia> repr("text/markdown", "foo")
"foo"

```

Mostly though it is not:

```julia
julia> repr("text/markdown", 1)
ERROR: MethodError: no method matching show(::Base.GenericIOBuffer{Array{UInt8,1}}, ::MIME{Symbol("text/markdown")}, ::Int64)
Closest candidates are:
  show(::IO, ::MIME{Symbol("text/plain")}, ::Any) at sysimg.jl:194
  show(::IO, ::MIME{Symbol("text/markdown")}, ::Markdown.MD) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/Markdown/src/render/plain.jl:140
  show(::IO, ::MIME{Symbol("text/csv")}, ::Any) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/DelimitedFiles/src/DelimitedFiles.jl:828
  ...
Stacktrace:
 [1] __binrepr(::MIME{Symbol("text/markdown")}, ::Int64, ::Nothing) at ./multimedia.jl:127
 [2] _textrepr(::MIME{Symbol("text/markdown")}, ::Int64, ::Nothing) at ./multimedia.jl:119
 [3] #repr#1(::Nothing, ::Function, ::MIME{Symbol("text/markdown")}, ::Int64) at ./multimedia.jl:115
 [4] (::getfield(Base, Symbol("#kw##repr")))(::NamedTuple{(:context,),Tuple{Nothing}}, ::typeof(repr), ::MIME{Symbol("text/markdown")}, ::Int64) at ./none:0
 [5] #repr#2(::Nothing, ::Function, ::String, ::Int64) at ./multimedia.jl:116
 [6] repr(::String, ::Int64) at ./multimedia.jl:116
 [7] top-level scope at none:0

```

Which makes sense when there is no canonical markdown representation of the thing.  
However, markdown is a pretty flexible format.  
So I would like to fallback, first to HTML, then to plain text,  
then to just _what ever `repr(x)` returns_.

Is there any better way than doing exception handling?

```julia
"""
    markdown_repr(x)

Returns the most suitable method for displaying `x` in a markdown document.
"""
function markdown_repr(x)
    for mime_type in ("text/markdown", "text/html", "text/plain")
        try
            return repr(mime_type, x)
        catch err
            err isa MethodError || rethrow(err)
        end
    end
    return repr(x)
end

```

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [April 17, 2019, 3:04pm UTC](https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242/2 "2019-04-17T15:04:44Z")

</div>

I believe `showable` is meant for cases like this, but it is not perfect since it just checks that the method exist for the given argument and mime type. It will for example fail when someone defines a fallback like

```julia
function Base.show(io::IO, ::MIME, x::MyType)
    error("MyType does not support this MIME type")
end

```

see e.g. [https://github.com/JuliaLang/IJulia.jl/issues/835](https://github.com/JuliaLang/IJulia.jl/issues/835).

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [April 17, 2019, 4:34pm UTC](https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242/3 "2019-04-17T16:34:56Z")

</div>

if `showable` is good enough for IJulia  
(which indeed it does seem to be [https://github.com/JuliaLang/IJulia.jl/blob/master/src/display.jl#L4](https://github.com/JuliaLang/IJulia.jl/blob/master/src/display.jl#L4))  
then it is good enough for me.

IJulia also wraps the whole thing in a `try-catch`  
Which seems reasonable.  
But at least `showable` lets us not try to do things only to get `MethodErrors.`

```julia
"""
    markdown_repr(x)

Returns the most suitable method for displaying `x` in a markdown document.
"""
function markdown_repr(x)
    for mime_type in ("text/markdown", "text/html", "text/plain")
        try
            if showable(mime_type, x)
                repr(mime_type, x)
            end
        catch
            @debug "It said it was showable, but it lied" mime_type x exception=err
            
            # we blindly catch everything, because who knows what evil
            # people are doing in their misimplemented `repr` functions
        end
    end
    return repr(x)
end

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 17, 2019, 4:45pm UTC](https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242/4 "2019-04-17T16:45:04Z")

</div>

> [@oxinabox](#):
>
> IJulia also wraps the whole thing in a `try-catch`  
> Which seems reasonable.

That’s to handle objects with buggy `show` functions, where you’d still like to see text/plain output if nothing else. You can omit this if you’re not handling arbitrary user interactions and don’t mind throwing an exception if there are bugs.

Types that define `show` via generic `::MIME` handlers should also override `showable` to indicate what types they can actually handle. For example, PyCall does this because whether a [rich representation](https://ipython.readthedocs.io/en/stable/config/integrating.html#rich-display) exists for a given Python object can only be determined at runtime.

---

<div class="post-metadata">

**Author:** ![shashikdm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shashikdm/32/8103_2.png) [@shashikdm](https://discourse.julialang.org/u/shashikdm)\
**Post date:** [April 22, 2019, 2:42pm UTC](https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242/5 "2019-04-22T14:42:00Z")

</div>

```julia
showable("text/markdown", "Hello **World**")

```

returns `false`  
It should return true since

```julia
repr("text/markdown", "Hello **World**")

```

returns “Hello \*\*World\*\*” and does not cause any error  
Is this a bug or am I doing something wrong?

---

<div class="post-metadata">

**Author:** ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)\
**Post date:** [April 22, 2019, 3:14pm UTC](https://discourse.julialang.org/t/how-to-get-a-markdown-repr-of-an-object-mime-type-fallbacks/23242/6 "2019-04-22T15:14:20Z")

</div>

`showable` tells you whether your object can be `show`n, not `repr`esented:

```julia
julia> showable("text/markdown", "Hello **World**")
false

julia> show(stdout, "text/markdown", "Hello **World**")
ERROR: MethodError: no method matching show(::Base.TTY, ::MIME{Symbol("text/markdown")}, ::String)
Closest candidates are:
  show(::IO, ::MIME{Symbol("text/plain")}, ::Any) at sysimg.jl:194
  show(::IO, ::MIME{Symbol("text/markdown")}, ::Markdown.MD) at C:\cygwin\home\Administrator\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.0\Markdown\src\render\plain.jl:140
  show(::IO, ::MIME{Symbol("text/csv")}, ::Any) at C:\cygwin\home\Administrator\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.0\DelimitedFiles\src\DelimitedFiles.jl:828
  ...
Stacktrace:
 [1] show(::Base.TTY, ::String, ::String) at .\multimedia.jl:79
 [2] top-level scope at none:0

julia> showable("text/markdown", Markdown.parse("Hello **World**"))
true

julia> show(stdout, "text/markdown", Markdown.parse("Hello **World**"))
Hello **World**

```
