-
-
Notifications
You must be signed in to change notification settings - Fork 423
Add custom MIME types to display_dict. #755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
0451835
a708a62
30a462c
883fe82
c1fc7e3
e735ac4
3511bd5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,54 +5,111 @@ | |
| import Base.Libc: flush_cstdio | ||
| import Pkg | ||
|
|
||
| const text_plain = MIME("text/plain") | ||
| const image_svg = MIME("image/svg+xml") | ||
| const image_png = MIME("image/png") | ||
| const image_jpeg = MIME("image/jpeg") | ||
| const text_markdown = MIME("text/markdown") | ||
| const text_html = MIME("text/html") | ||
| const text_latex = MIME("text/latex") # Jupyter expects this | ||
| const text_latex2 = MIME("application/x-latex") # but this is more standard? | ||
| const application_vnd_vega_v3 = MIME("application/vnd.vega.v3+json") | ||
| const application_vnd_vegalite_v2 = MIME("application/vnd.vegalite.v2+json") | ||
| const application_vnd_dataresource = MIME("application/vnd.dataresource+json") | ||
| Base.showable(a::Vector{MIME}, x) = any(m -> showable(m, x), a) | ||
|
|
||
| """ | ||
| A vector of MIME types (or vectors of MIME types) that IJulia will try to | ||
| render. IJulia will try to render every MIME type specified in the first level | ||
| of the vector. If a vector of MIME types is specified, IJulia will include only | ||
| the first MIME type that is renderable (this allows for the expression of | ||
| priority and exclusion of redundant data). | ||
| For example, since "text/plain" is specified as a first-child of the array, | ||
| IJulia will always try to include a "text/plain" representation of anything that | ||
| is displayed. Since markdown and latex are specified within a sub-vector, IJulia | ||
| will always try to render "text/markdown", and will only try to render | ||
| "text/latex" if markdown isn't possible. | ||
| """ | ||
| const ijulia_mime_types = Vector{Union{MIME, Vector{MIME}}}([ | ||
| MIME("text/plain"), | ||
| MIME("image/svg+xml"), | ||
| MIME("image/png"), | ||
| MIME("image/jpeg"), | ||
|
||
| MIME("text/html"), | ||
| [ | ||
twavv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| MIME("text/markdown"), | ||
| MIME("text/latex"), # Jupyter expects this | ||
| MIME("application/x-latex"), # but this is more standard? | ||
| ], | ||
| ]) | ||
|
|
||
| """ | ||
| MIME types that when rendered (via stringmime) return JSON data. See | ||
| `ijulia_mime_types` for a description of how MIME types are selected. | ||
| This is necessary to embed the JSON as is in the displaydata bundle (rather than | ||
| as stringify'd JSON). | ||
| """ | ||
| const ijulia_jsonmime_types = Vector{Union{MIME, Vector{MIME}}}([ | ||
| [MIME("application/vnd.vegalite.v2+json"), MIME("application/vnd.vega.v3+json")], | ||
twavv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ]) | ||
|
|
||
| register_ijulia_mime(x::Union{MIME, Vector{MIME}}) = push!(ijulia_mime_types, x) | ||
|
||
| register_ijulia_jsonmime(x::Union{MIME, Vector{MIME}}) = push!(ijulia_jsonmime_types, x) | ||
|
|
||
| include("magics.jl") | ||
|
|
||
| # return a String=>Any dictionary to attach as metadata | ||
| # in Jupyter display_data and pyout messages | ||
| metadata(x) = Dict() | ||
|
|
||
| # return a String=>String dictionary of mimetype=>data | ||
| # for passing to Jupyter display_data and execute_result messages. | ||
| function display_dict(x) | ||
| data = Dict{String,Any}("text/plain" => limitstringmime(text_plain, x)) | ||
| if showable(application_vnd_vegalite_v2, x) | ||
| data[string(application_vnd_vegalite_v2)] = JSON.JSONText(limitstringmime(application_vnd_vegalite_v2, x)) | ||
| elseif showable(application_vnd_vega_v3, x) # don't send vega if we have vega-lite | ||
| data[string(application_vnd_vega_v3)] = JSON.JSONText(limitstringmime(application_vnd_vega_v3, x)) | ||
| end | ||
| if showable(application_vnd_dataresource, x) | ||
| data[string(application_vnd_dataresource)] = JSON.JSONText(limitstringmime(application_vnd_dataresource, x)) | ||
| """ | ||
| Generate the preferred MIME representation of x. | ||
| Returns a tuple with the selected MIME type and the representation of the data | ||
| using that MIME type. | ||
| """ | ||
| function display_mimestring(mime_array::Vector{MIME}, x) | ||
| for m in mime_array | ||
| if showable(mime_array, x) | ||
| return display_mimestring(m, x) | ||
| end | ||
| end | ||
| if showable(image_svg, x) | ||
| data[string(image_svg)] = limitstringmime(image_svg, x) | ||
| error("No displayable MIME types in mime array.") | ||
| end | ||
|
|
||
| display_mimestring(m::MIME, x) = (m, limitstringmime(m, x)) | ||
|
|
||
| """ | ||
| Generate the preferred json-MIME representation of x. | ||
| Returns a tuple with the selected MIME type and the representation of the data | ||
| using that MIME type (as a `JSONText`). | ||
| """ | ||
| function display_mimejson(mime_array::Vector{MIME}, x) | ||
| for m in mime_array | ||
| if showable(mime_array, x) | ||
| return display_mimejson(m, x) | ||
| end | ||
| end | ||
| if showable(image_png, x) | ||
| data[string(image_png)] = limitstringmime(image_png, x) | ||
| elseif showable(image_jpeg, x) # don't send jpeg if we have png | ||
| data[string(image_jpeg)] = limitstringmime(image_jpeg, x) | ||
| error("No displayable MIME types in mime array.") | ||
| end | ||
|
|
||
| display_mimejson(m::MIME, x) = (m, JSON.JSONText(limitstringmime(m, x))) | ||
|
|
||
| """ | ||
| Generate a dictionary of `mime_type => data` pairs for all registered MIME | ||
| types. This is the format that Jupyter expects in display_data and | ||
| execute_result messages. | ||
| """ | ||
| function display_dict(x) | ||
| data = Dict{String, Union{String, JSONText}}() | ||
| for m in ijulia_mime_types | ||
| if showable(m, x) | ||
| mime, mime_repr = display_mimestring(m, x) | ||
| data[string(mime)] = mime_repr | ||
| end | ||
| end | ||
| if showable(text_markdown, x) | ||
| data[string(text_markdown)] = limitstringmime(text_markdown, x) | ||
| elseif showable(text_html, x) | ||
| data[string(text_html)] = limitstringmime(text_html, x) | ||
| elseif showable(text_latex, x) | ||
| data[string(text_latex)] = limitstringmime(text_latex, x) | ||
| elseif showable(text_latex2, x) | ||
| data[string(text_latex)] = limitstringmime(text_latex2, x) | ||
|
|
||
| for m in ijulia_jsonmime_types | ||
| if showable(m, x) | ||
| mime, mime_repr = display_mimejson(m, x) | ||
| data[string(mime)] = mime_repr | ||
| end | ||
| end | ||
|
|
||
| return data | ||
|
|
||
| end | ||
|
|
||
| # queue of objects to display at end of cell execution | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,45 @@ | ||
| using Test | ||
| using Base64, JSON | ||
|
|
||
| import IJulia | ||
| import IJulia: helpmode, error_content, docdict | ||
|
|
||
| content = error_content(UndefVarError(:a)) | ||
| @test "UndefVarError" == content["ename"] | ||
|
|
||
| @test haskey(docdict("import"), "text/plain") | ||
| @test haskey(docdict("sum"), "text/plain") | ||
|
|
||
| struct FriendlyData | ||
| name::AbstractString | ||
| end | ||
|
|
||
| @testset "Custom MIME types" begin | ||
| friend = FriendlyData("world") | ||
|
|
||
| FRIENDLY_MIME_TYPE = MIME"application/vnd.ijulia.friendly-text" | ||
| FRIENDLY_MIME = FRIENDLY_MIME_TYPE() | ||
| Base.Multimedia.istextmime(::FRIENDLY_MIME_TYPE) = true | ||
| Base.show(io, ::FRIENDLY_MIME_TYPE, x::FriendlyData) = write(io, "Hello, $(x.name)!") | ||
| IJulia.register_ijulia_mime(FRIENDLY_MIME) | ||
|
|
||
| BINARY_MIME_TYPE = MIME"application/vnd.ijulia.friendly-binary" | ||
| BINARY_MIME = BINARY_MIME_TYPE() | ||
| Base.Multimedia.istextmime(::BINARY_MIME_TYPE) = false | ||
| Base.show(io, ::BINARY_MIME_TYPE, x::FriendlyData) = write(io, "Hello, $(x.name)!") | ||
| IJulia.register_ijulia_mime(BINARY_MIME) | ||
|
|
||
| JSON_MIME_TYPE = MIME"application/vnd.ijulia.friendly-json" | ||
| JSON_MIME = JSON_MIME_TYPE() | ||
| Base.Multimedia.istextmime(::JSON_MIME_TYPE) = true | ||
| Base.show(io, ::JSON_MIME_TYPE, x::FriendlyData) = write(io, JSON.json(Dict("name" => x.name))) | ||
| IJulia.register_ijulia_jsonmime(JSON_MIME) | ||
|
|
||
| # We stringify then re-parse the dict so that JSONText's are parsed as | ||
| # actual JSON objects and we can index into them. | ||
| data = JSON.parse(JSON.json(IJulia.display_dict(friend))) | ||
| @test data[string(FRIENDLY_MIME)] == "Hello, world!" | ||
| @test data[string(BINARY_MIME)] == base64encode("Hello, world!") | ||
| @test data[string(JSON_MIME)]["name"] == "world" | ||
|
|
||
| end |
Uh oh!
There was an error while loading. Please reload this page.