Skip to content

Commit bac224b

Browse files
authored
Copy new state-based export from PlutoSliderServer (#1063)
* Copy new state-based export from PlutoSliderServer * asdf
1 parent 7feb905 commit bac224b

File tree

7 files changed

+96
-156
lines changed

7 files changed

+96
-156
lines changed

frontend/common/OfflineHTMLExport.js

Lines changed: 0 additions & 95 deletions
This file was deleted.

frontend/components/Editor.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,20 +1001,19 @@ patch: ${JSON.stringify(
10011001
const status = this.cached_status ?? statusmap(this.state)
10021002
const statusval = first_true_key(status)
10031003

1004-
const notebook_export_url =
1004+
const export_url = (u) =>
10051005
this.state.binder_session_url == null
1006-
? `./notebookfile?id=${this.state.notebook.notebook_id}`
1007-
: `${this.state.binder_session_url}notebookfile?id=${this.state.notebook.notebook_id}&token=${this.state.binder_session_token}`
1006+
? `./${u}?id=${this.state.notebook.notebook_id}`
1007+
: `${this.state.binder_session_url}${u}?id=${this.state.notebook.notebook_id}&token=${this.state.binder_session_token}`
10081008

10091009
return html`
10101010
<${PlutoContext.Provider} value=${this.actions}>
10111011
<${PlutoBondsContext.Provider} value=${this.state.notebook.bonds}>
10121012
<${Scroller} active=${this.state.scroller} />
10131013
<header className=${export_menu_open ? "show_export" : ""}>
10141014
<${ExportBanner}
1015-
pluto_version=${this.client?.version_info?.pluto}
1016-
notebook=${this.state.notebook}
1017-
notebook_export_url=${notebook_export_url}
1015+
notebookfile_url=${export_url("notebookfile")}
1016+
notebookexport_url=${export_url("notebookexport")}
10181017
open=${export_menu_open}
10191018
onClose=${() => this.setState({ export_menu_open: false })}
10201019
/>
@@ -1039,7 +1038,7 @@ patch: ${JSON.stringify(
10391038
<div class="flex_grow_1"></div>
10401039
${
10411040
this.state.binder_phase === BinderPhase.ready
1042-
? html`<pluto-filepicker><a href=${notebook_export_url} target="_blank">Save notebook...</a></pluto-filepicker>`
1041+
? html`<pluto-filepicker><a href=${export_url("notebookfile")} target="_blank">Save notebook...</a></pluto-filepicker>`
10431042
: html`<${FilePicker}
10441043
client=${this.client}
10451044
value=${notebook.in_temp_dir ? "" : notebook.path}

frontend/components/ExportBanner.js

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { html } from "../imports/Preact.js"
22

3-
import { offline_html } from "../common/OfflineHTMLExport.js"
4-
53
const Circle = ({ fill }) => html`
64
<svg
75
width="48"
@@ -23,61 +21,20 @@ const Triangle = ({ fill }) => html`
2321
</svg>
2422
`
2523

26-
export const ExportBanner = ({ notebook, pluto_version, onClose, notebook_export_url }) => {
27-
// @ts-ignore
28-
let is_chrome = window.chrome == null
29-
24+
export const ExportBanner = ({ onClose, notebookfile_url, notebookexport_url }) => {
3025
return html`
3126
<aside id="export">
3227
<div id="container">
3328
<div class="export_title">export</div>
34-
<a href=${notebook_export_url} target="_blank" class="export_card">
29+
<a href=${notebookfile_url} target="_blank" class="export_card" download>
3530
<header><${Triangle} fill="#a270ba" /> Notebook file</header>
3631
<section>Download a copy of the <b>.jl</b> script.</section>
3732
</a>
38-
<a
39-
href="#"
40-
class="export_card"
41-
onClick=${(e) => {
42-
offline_html({
43-
pluto_version: pluto_version,
44-
head: document.head,
45-
body: document.body,
46-
}).then((html) => {
47-
if (html != null) {
48-
const fake_anchor = document.createElement("a")
49-
fake_anchor.setAttribute("download", `${notebook.shortpath}.html`)
50-
fake_anchor.setAttribute(
51-
"href",
52-
URL.createObjectURL(
53-
new Blob([html], {
54-
type: "text/html",
55-
})
56-
)
57-
)
58-
document.body.appendChild(fake_anchor)
59-
setTimeout(() => {
60-
fake_anchor.click()
61-
document.body.removeChild(fake_anchor)
62-
}, 100)
63-
}
64-
})
65-
}}
66-
>
33+
<a href=${notebookexport_url} target="_blank" class="export_card" download>
6734
<header><${Circle} fill="#E86F51" /> Static HTML</header>
6835
<section>An <b>.html</b> file for your web page, or to share online.</section>
6936
</a>
70-
<a
71-
href="#"
72-
class="export_card"
73-
style=${!is_chrome ? "opacity: .7;" : ""}
74-
onClick=${() => {
75-
if (!is_chrome) {
76-
alert("PDF generation works best on Google Chome.\n\n(We're working on it!)")
77-
}
78-
window.print()
79-
}}
80-
>
37+
<a href="#" class="export_card" onClick=${() => window.print()}>
8138
<header><${Circle} fill="#3D6117" /> Static PDF</header>
8239
<section>A static <b>.pdf</b> file for print or email.</section>
8340
</a>

sample/Interactivity.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
### A Pluto.jl notebook ###
2-
# v0.12.11
2+
# v0.14.0
33

44
using Markdown
55
using InteractiveUtils
@@ -94,7 +94,7 @@ Try drawing a rectangle in the canvas below 👇 and notice that the `area` vari
9494
9595
<script>
9696
// 🐸 `currentScript` is the current script tag - we use it to select elements 🐸 //
97-
const canvas = currentScript.closest('pluto-output').querySelector("canvas")
97+
const canvas = currentScript.parentElement.querySelector("canvas")
9898
const ctx = canvas.getContext("2d")
9999
100100
var startX = 80

src/Pluto.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ project_relative_path(xs...) = normpath(joinpath(dirname(dirname(pathof(Pluto)))
1313

1414
import Pkg
1515

16+
include_dependency("../Project.toml")
1617
const PLUTO_VERSION = VersionNumber(Pkg.TOML.parsefile(project_relative_path("Project.toml"))["version"])
1718
const PLUTO_VERSION_STR = 'v' * string(PLUTO_VERSION)
1819
const JULIA_VERSION_STR = 'v' * string(VERSION)
1920

2021
include("./notebook/PathHelpers.jl")
22+
include("./notebook/Export.jl")
2123
include("./Configuration.jl")
2224

2325
include("./evaluation/Tokens.jl")

src/notebook/Export.jl

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Pkg
2+
using Base64
3+
4+
function generate_html(;
5+
version=nothing, pluto_cdn_root=nothing,
6+
notebookfile_js="undefined", statefile_js="undefined",
7+
slider_server_url_js="undefined", binder_url_js="undefined",
8+
disable_ui=true
9+
)::String
10+
11+
original = read(project_relative_path("frontend", "editor.html"), String)
12+
13+
cdn_root = if pluto_cdn_root === nothing
14+
if version isa Nothing
15+
version = PLUTO_VERSION
16+
end
17+
"https://cdn.jsdelivr.net/gh/fonsp/Pluto.jl@$(string(version))/frontend/"
18+
else
19+
pluto_cdn_root
20+
end
21+
22+
@info "Using CDN for Pluto assets:" cdn_root
23+
24+
cdnified = replace(
25+
replace(original,
26+
"href=\"./" => "href=\"$(cdn_root)"),
27+
"src=\"./" => "src=\"$(cdn_root)")
28+
29+
result = replace(cdnified,
30+
"<!-- [automatically generated launch parameters can be inserted here] -->" =>
31+
"""
32+
<script data-pluto-file="launch-parameters">
33+
window.pluto_notebookfile = $(notebookfile_js)
34+
window.pluto_disable_ui = $(disable_ui ? "true" : "false")
35+
window.pluto_statefile = $(statefile_js)
36+
window.pluto_slider_server_url = $(slider_server_url_js)
37+
window.pluto_binder_url = $(binder_url_js)
38+
</script>
39+
<!-- [automatically generated launch parameters can be inserted here] -->
40+
"""
41+
)
42+
43+
return result
44+
end
45+
46+
47+
function generate_html(notebook; kwargs...)
48+
state = notebook_to_js(notebook)
49+
50+
statefile_js = let
51+
statefile64 = base64encode() do io
52+
pack(io, state)
53+
end
54+
55+
"\"data:;base64,$(statefile64)\""
56+
end
57+
58+
generate_html(; statefile_js=statefile_js, kwargs...)
59+
end

src/webserver/Static.jl

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,18 @@ function http_router_for(session::ServerSession)
200200
HTTP.@register(router, "GET", "/sample/*", serve_sample)
201201
HTTP.@register(router, "POST", "/sample/*", serve_sample)
202202

203+
notebook_from_uri(request) = let
204+
uri = HTTP.URI(request.target)
205+
query = HTTP.queryparams(uri)
206+
id = UUID(query["id"])
207+
session.notebooks[id]
208+
end
203209
serve_notebookfile = with_authentication(;
204210
required=security.require_secret_for_access ||
205211
security.require_secret_for_open_links
206212
) do request::HTTP.Request
207213
try
208-
uri = HTTP.URI(request.target)
209-
query = HTTP.queryparams(uri)
210-
id = UUID(query["id"])
211-
notebook = session.notebooks[id]
212-
214+
notebook = notebook_from_uri(request)
213215
response = HTTP.Response(200, sprint(save_notebook, notebook))
214216
push!(response.headers, "Content-Type" => "text/plain; charset=utf-8")
215217
push!(response.headers, "Content-Disposition" => "inline; filename=\"$(basename(notebook.path))\"")
@@ -219,6 +221,22 @@ function http_router_for(session::ServerSession)
219221
end
220222
end
221223
HTTP.@register(router, "GET", "/notebookfile", serve_notebookfile)
224+
225+
serve_notebookexport = with_authentication(;
226+
required=security.require_secret_for_access ||
227+
security.require_secret_for_open_links
228+
) do request::HTTP.Request
229+
try
230+
notebook = notebook_from_uri(request)
231+
response = HTTP.Response(200, generate_html(notebook))
232+
push!(response.headers, "Content-Type" => "text/html; charset=utf-8")
233+
push!(response.headers, "Content-Disposition" => "inline; filename=\"$(basename(notebook.path)).html\"")
234+
response
235+
catch e
236+
return error_response(400, "Bad query", "Please <a href='https://github.com/fonsp/Pluto.jl/issues'>report this error</a>!", sprint(showerror, e, stacktrace(catch_backtrace())))
237+
end
238+
end
239+
HTTP.@register(router, "GET", "/notebookexport", serve_notebookexport)
222240

223241
function serve_asset(request::HTTP.Request)
224242
uri = HTTP.URI(request.target)

0 commit comments

Comments
 (0)