diff --git a/examples/subsession_integration.jl b/examples/subsession_integration.jl
new file mode 100644
index 00000000..4268ef96
--- /dev/null
+++ b/examples/subsession_integration.jl
@@ -0,0 +1,63 @@
+using HTTP
+using Bonito: App, Styles, Observable
+using Bonito.DOM
+using Random
+using Colors
+using Base.Threads: @spawn
+using Dates: Dates
+
+
+function html(app; kwargs...)
+ io = IOBuffer()
+ show_html(io, app; kwargs...)
+ take!(io)
+end
+
+function main()
+ # start a blocking server
+ session_root_storage = Dict()
+ rng = Random.default_rng()
+ HTTP.listen() do http::HTTP.Stream
+ HTTP.setstatus(http, 200)
+ HTTP.startwrite(http)
+ req_uri = HTTP.URI(http.message.target)
+ if req_uri.path == "/fragment"
+ params = HTTP.queryparams(req_uri)
+ sid = params["sid"]
+ session = session_root_storage[params["sid"]]
+ color = rand(RGB{Float64})
+ css = Styles(
+ "background-color" => color,
+ )
+ app = App() do
+ date_obs::Observable{String} = Observable("unset")
+ @async begin
+ while true
+ date_obs[] = string(Dates.now())
+ sleep(1)
+ end
+ end
+ DOM.div(map(date -> "date: $(date); sid: $(sid)", date_obs), style=css)
+ end
+ app_html = html(app; parent=session)
+ write(http, app_html)
+ else
+ root_app = App(_ -> DOM.div(""))
+ app_html = html(root_app)
+ session = root_app.session[]
+ session_root_storage[session.id] = session
+ write(http, "
")
+ write(http, "")
+ write(http, "fragment insertion
")
+ write(http, "")
+ write(http, "")
+ write(http, app_html)
+ write(http, "
")
+ write(http, "")
+ end
+ end
+end
+
+if abspath(PROGRAM_FILE) == @__FILE__
+ main()
+end
diff --git a/src/Bonito.jl b/src/Bonito.jl
index 61ce2803..5d9fdf2f 100644
--- a/src/Bonito.jl
+++ b/src/Bonito.jl
@@ -70,7 +70,7 @@ include("interactive.jl")
# Core functionality
export Page, Session, App, DOM, SVG, @js_str, ES6Module, Asset, CSS
export Slider, Button, TextField, NumberInput, Checkbox, RangeSlider, CodeEditor
-export browser_display, configure_server!, Server, html, route!, online_url, use_electron_display
+export browser_display, configure_server!, Server, show_html, html, route!, online_url, use_electron_display
export Observable, on, onany, bind_global
export linkjs, evaljs, evaljs_value, onjs
export NoServer, AssetFolder, HTTPAssetServer, DocumenterAssets
diff --git a/src/display.jl b/src/display.jl
index 642bd73c..6a3287d3 100644
--- a/src/display.jl
+++ b/src/display.jl
@@ -59,12 +59,11 @@ end
get_io_context(io::IO) = nothing
get_io_context(io::IOContext) = io
-function Base.show(io::IO, ::Union{MIME"text/html", MIME"application/prs.juno.plotpane+html"}, app::App)
+function show_html(io::IO, app::App; parent=CURRENT_SESSION[])
ctx = get_io_context(io)
session = nothing
- if !isnothing(CURRENT_SESSION[])
+ if !isnothing(parent)
# We render in a subsession
- parent = CURRENT_SESSION[]
sub = Session(parent; title=app.title)
sub.io_context[] = ctx
dom = session_dom(sub, app)
@@ -93,6 +92,10 @@ function Base.show(io::IO, ::Union{MIME"text/html", MIME"application/prs.juno.pl
return sub
end
+function Base.show(io::IO, ::Union{MIME"text/html", MIME"application/prs.juno.plotpane+html"}, app::App)
+ show_html(io, app)
+end
+
function print_as_page(io::IO, dom::Node)
println(io, "")
# use Hyperscript directly to avoid the additional Bonito attributes