diff --git a/src/ElectronDisplay.jl b/src/ElectronDisplay.jl index f5d4fce..7a0d827 100644 --- a/src/ElectronDisplay.jl +++ b/src/ElectronDisplay.jl @@ -10,6 +10,7 @@ Base.@kwdef mutable struct ElectronDisplayConfig showable = electron_showable single_window::Bool = false focus::Bool = true + max_json_bytes::Int = 2^20 end """ @@ -22,11 +23,13 @@ setconfig( showable = config.showable, single_window::Bool = config.single_window, focus::Bool = config.focus, + max_json_bytes::Int = config.max_json_bytes, ) = ElectronDisplayConfig( showable = showable, single_window = single_window, focus = focus, + max_json_bytes = max_json_bytes, ) struct ElectronDisplayType <: Base.AbstractDisplay @@ -57,6 +60,11 @@ Configuration for ElectronDisplay. * `focus::Bool = true`: Focus the Electron window on `display` if `true` (default). + +* `max_json_bytes::Int = $(ElectronDisplayConfig().max_json_bytes)`: + Maximum size in bytes for which JSON representation is used. Otherwise, + convert visualization locally in a binary form before sending it to the + Electron display. Currently only Vega and Vega-Lite support this. """ const CONFIG = ElectronDisplayConfig() diff --git a/src/vega.jl b/src/vega.jl index 7fcb68f..78f25c5 100644 --- a/src/vega.jl +++ b/src/vega.jl @@ -4,8 +4,22 @@ Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vega.v3+ Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vega.v4+json")}) = true Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vega.v5+json")}) = true +function _maybe_fallback_to(mime, d, x, payload) + if sizeof(payload) > d.config.max_json_bytes + @warn string( + "The size of JSON representation (", sizeof(payload), ")", + " exceeds `max_json_bytes = ", d.config.max_json_bytes, "`.", + " Falling back to $mime." + ) + return display(d, mime, x) + end + return nothing +end + function _display_vegalite(d, major_version_vegalite, major_version_vega, x) payload = stringmime(MIME("application/vnd.vegalite.v$major_version_vegalite+json"), x) + ans = _maybe_fallback_to(MIME"image/png"(), d, x, payload) + ans === nothing || return ans html_page = """ @@ -49,6 +63,8 @@ end function _display_vega(d, major_version, x) payload = stringmime(MIME("application/vnd.vega.v$major_version+json"), x) + ans = _maybe_fallback_to(MIME"image/png"(), d, x, payload) + ans === nothing || return ans html_page = """ diff --git a/test/construct_vega_specs.jl b/test/construct_vega_specs.jl index b6ee531..26dc831 100644 --- a/test/construct_vega_specs.jl +++ b/test/construct_vega_specs.jl @@ -318,3 +318,20 @@ vg5 = DummyDisplayable{MIME"application/vnd.vega.v5+json"}(""" ] } """) + +# based on https://github.com/mathiasbynens/small +dummy_png_bytes = UInt8[ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, + 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, + 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0x63, 0x00, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x01, +] + +struct DummyVegaLitePNGHybrid end +Base.show(io::IO, ::MIME"application/vnd.vegalite.v3+json", ::DummyVegaLitePNGHybrid) = + print(io, vl3) +Base.show(io::IO, ::MIME"image/png", ::DummyVegaLitePNGHybrid) = + write(io, dummy_png_bytes) + +vl3png = DummyVegaLitePNGHybrid() diff --git a/test/runtests.jl b/test/runtests.jl index 83605e5..604a47b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -40,6 +40,11 @@ eldt = ElectronDisplay.ElectronDisplayType() @test electrondisplay(vg4) isa Electron.Window @test electrondisplay(vg5) isa Electron.Window +@test_logs( + (:warn, r"The size of JSON representation.*exceeds.*max_json_bytes"), + electrondisplay(vl3png; max_json_bytes=-1)::Electron.Window +) + mdo = DummyDisplayable{MIME"text/markdown"}("""foo""") @test electrondisplay(mdo) isa Electron.Window