Skip to content

Commit

Permalink
Implement support for DocumenterVitepress
Browse files Browse the repository at this point in the history
Calling to_documenter now returns an object wrapping the plot data. This can be used to alter behaviour based on the documentation rendering backend.

Signed-off-by: Fabian Nawratil <[email protected]>
  • Loading branch information
fnawratil committed Jan 2, 2025
1 parent f259cb4 commit 6ba7b96
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 20 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
/Manifest.toml
/docs/Manifest.toml
/docs/build/
testdebug.jl
testdebug.jl

.vscode/
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.0] - 2025-01-02

### Added

- DocumenterVitepress extension to circumvent the limitation of raw javascript code in Vue.

### Changed

- The `to_documenter` function no longer directly returns HTML, but rather an object for which `Base.show(::MIME"text/html")` is defined.
11 changes: 7 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PlotlyDocumenter"
uuid = "9b90f1cd-2639-4507-8b17-2fbe371ceceb"
authors = ["Alberto Mengali <[email protected]>"]
version = "0.1.3"
version = "0.2.0"

[deps]
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
Expand All @@ -10,25 +10,28 @@ PackageExtensionCompat = "65ce6f38-6b18-4e1d-a461-8949797d7930"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[weakdeps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365"
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
PlotlyLight = "ca7969ec-10b3-423e-8d99-40f33abb42bf"
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
PlotlyLight = "ca7969ec-10b3-423e-8d99-40f33abb42bf"

[extensions]
DocumenterVitepressPlotsExt = ["DocumenterVitepress", "Documenter"]
PlotlyBaseExt = "PlotlyBase"
PlotlyJSExt = "PlotlyJS"
PlotlyLightExt = "PlotlyLight"

[compat]
Downloads = "1"
HypertextLiteral = "0.9"
PackageExtensionCompat = "1"
Downloads = "1"
julia = "1.6"

[extras]
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
PlotlyLight = "ca7969ec-10b3-423e-8d99-40f33abb42bf"
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
PlotlyLight = "ca7969ec-10b3-423e-8d99-40f33abb42bf"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ makedocs(;
),
pages=[
"Home" => "index.md",
"DocumenterVitepress" => "vitepress.md",
],
)

Expand Down
16 changes: 11 additions & 5 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ CurrentModule = PlotlyDocumenter

Documentation for [PlotlyDocumenter](https://github.com/disberd/PlotlyDocumenter.jl).

```@index
```
This package provides a function `to_documenter` that returns a wrapped plot object. This object will be rendered interactively by Documenter.
If you are using DocumenterVitepress, see [here](vitepress.md) for more information.

!!! note
To prevent `to_documenter` from showing up in the documentation, add `#hide` to the end of the line.
See [Documenter.jl](https://documenter.juliadocs.org/stable/man/syntax/#reference-at-example) for more information.

## API
```@autodocs
Modules = [PlotlyDocumenter]
```

## PlotlyBase
## Examples
### PlotlyBase
```@example
using PlotlyDocumenter
using PlotlyBase
Expand All @@ -22,7 +28,7 @@ p = Plot(scatter(;y = rand(5)))
to_documenter(p)
```

## PlotlyJS
### PlotlyJS
```@example
using PlotlyDocumenter
using PlotlyJS
Expand All @@ -31,7 +37,7 @@ p = plot(scatter(;y = rand(5)), Layout(height = 700))
to_documenter(p)
```

## PlotlyLight
### PlotlyLight
```@example
using PlotlyDocumenter
using PlotlyLight
Expand Down
30 changes: 30 additions & 0 deletions docs/src/vitepress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Usage with DocumenterVitepress

PlotlyDocumenter provides an extension to work with DocumenterVitepress. As raw javascript code cannot be executed in Vue, an alternate approach is required.
For this reason, when using DocumenterVitepress, the custom plot object will be rendered as the `<VuePlotly/>` component from the [vue3-plotly-ts](https://github.com/boscoh/vue3-plotly-ts) package.

!!! warning
The keyword arguments for `to_documenter` are ignored when using DocumenterVitepress.

To make this work, first install the `vue3-plotly-ts` package in your project:

```bash
npm install vue3-plotly-ts
```

Then, add the `VuePlotly` component to your `.vitepress/theme/index.ts` file:

```typescript
import VuePlotly from "vue3-plotly-ts"

export default {
...
enhanceApp({ app, router, siteData }) {
...
app.component('VuePlotly', VuePlotly);
...
}
} satisfies Theme
```
In your `make.jl`, make sure you call `using PlotlyDocumenter` before `makedocs`.

24 changes: 24 additions & 0 deletions ext/DocumenterVitepressPlotsExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module DocumenterVitepressPlotsExt

using Documenter
using DocumenterVitepress
using HypertextLiteral
using PlotlyDocumenter

DocumenterVitepress.mime_priority(::MIME"text/vnd.plotlydocumenter.plot") = 2.5;
DocumenterVitepress.render_mime(io::IO, mime::MIME"text/vnd.plotlydocumenter.plot", node, element, page, doc; kwargs...) = println(io, element)

function Documenter.display_dict(x::PlotlyDocumenterPlot; context = nothing)
base_dict = invoke(Documenter.display_dict, Tuple{Any}, x; context)
rendered = @htl("""
<VuePlotly
:data="$(x.data)"
:layout="$(x.layout)"
:config="$(x.config)"
/>
""")
base_dict[MIME"text/vnd.plotlydocumenter.plot"()] = repr(MIME"text/html"(), rendered, context = context)
return base_dict
end

end
2 changes: 1 addition & 1 deletion ext/PlotlyBaseExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ module PlotlyBaseExt
data = json(p.data)
layout = json(p.layout)
config = json(p.config)
return PlotlyDocumenter._to_documenter(;kwargs..., data, layout, config)
return PlotlyDocumenterPlot(data, layout, config, kwargs...)
end
end
2 changes: 1 addition & 1 deletion ext/PlotlyLightExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ module PlotlyLightExt
data = JSON3.write(p.data)
layout = JSON3.write(merge(settings.layout, p.layout))
config = JSON3.write(merge(settings.config, p.config))
return PlotlyDocumenter._to_documenter(;kwargs..., data, layout, config)
return PlotlyDocumenterPlot(data, layout, config, kwargs...)
end
end
43 changes: 38 additions & 5 deletions src/PlotlyDocumenter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ using Random
using Downloads: download

export to_documenter
export PlotlyDocumenterPlot

"""
PlotlyDocumenterPlot
A wrapper type for Plotly plot data that enables flexible rendering in different contexts.
The plot data is stored as strings containing the JSON representation of the plot's data, layout and config.
The `options` field contains rendering options that control how the plot is displayed. For the default
`text/html` MIME output, see [`to_documenter`](@ref) for more information.
"""
struct PlotlyDocumenterPlot
data::AbstractString
layout::AbstractString
config::AbstractString
options::Dict{Symbol,Any}

function PlotlyDocumenterPlot(data, layout, config, kwargs...)
options = Dict{Symbol,Any}(kwargs...)
return new(data, layout, config, options)
end
end


# Taken from PlotlyLight
get_semver(x) = VersionNumber(match(r"v(\d+)\.(\d+)\.(\d+)", x).match[2:end])
Expand All @@ -16,6 +40,7 @@ function latest_plotlyjs_version()
get_semver(read(file, String))
end


const DEFAULT_VERSION = v"2.24.2"
const PLOTLY_VERSION = Ref(DEFAULT_VERSION)

Expand All @@ -25,15 +50,22 @@ Change the plotly version that is used by default to render Plotly plots using [
"""
change_default_plotly_version(v) = PLOTLY_VERSION[] = VersionNumber(string(v))

function _to_documenter(;data, layout, config, version = PLOTLY_VERSION[], id = randstring(10), classes = [], style = (;))
function Base.show(io::IO, ::MIME"text/html", x::PlotlyDocumenterPlot)
js = HypertextLiteral.JavaScript

version = get(x.options, :version, PLOTLY_VERSION[])
id = get(x.options, :id, randstring(10))
classes = get(x.options, :classes, [])
style = get(x.options, :style, (;))

v = js(string(version))
plot_obj = (;
data = js(data),
layout = js(layout),
config = js(config),
data = js(x.data),
layout = js(x.layout),
config = js(x.config),
)
return @htl("""

rendered = @htl("""
<div id=$id class=$classes style=$style></div>
<script type="module">
import Plotly from "https://esm.sh/plotly.js-dist-min@$v"
Expand All @@ -48,6 +80,7 @@ function _to_documenter(;data, layout, config, version = PLOTLY_VERSION[], id =
PLOT.style.height = plot_obj.layout.height ? "" : "100%"
</script>
""")
Base.show(io, MIME"text/html"(), rendered)
end

# Define the function name. Methods are added in the extension packages
Expand Down
4 changes: 1 addition & 3 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import PlotlyJS

@testset "PlotlyDocumenter.jl" begin
function to_str(o)
io = IOBuffer()
show(io, o)
String(take!(io))
repr(MIME"text/html"(), o)
end


Expand Down

0 comments on commit 6ba7b96

Please sign in to comment.