Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Heptazhou committed Oct 25, 2024
1 parent feff787 commit 862f57b
Show file tree
Hide file tree
Showing 16 changed files with 223 additions and 122 deletions.
59 changes: 59 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: CI
on:
pull_request:
branches:
- "master"
push:
branches:
- "master"
tags:
- "*"
defaults:
run:
shell: bash
env:
JULIA_NUM_THREADS: auto
jobs:
test:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
os:
- windows-latest
- ubuntu-latest
- macos-latest
julia-version:
- "min"
- "lts"
- "1"
- "pre"
- "nightly"
exclude:
- os: windows-latest
julia-version: "min"
- os: macos-latest
julia-version: "min"
include:
- os: ubuntu-latest
julia-prefix: xvfb-run
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: julia-actions/setup-julia@v2
with:
show-versioninfo: true
version: ${{ matrix.julia-version }}
- uses: julia-actions/julia-buildpkg@v1
with:
ignore-no-cache: true
localregistry: https://github.com/0h7z/0hjl.git
- uses: julia-actions/julia-runtest@v1
with:
prefix: ${{ matrix.julia-prefix }}
- uses: heptazhou/julia-codecov@v1
- uses: codecov/[email protected]
with:
file: lcov.info
16 changes: 9 additions & 7 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
uuid = "90851b43-1319-4523-8ba0-be51ac244080"
authors = ["Heptazhou <zhou at 0h7z dot com>"]
version = "1.40.8"

[deps]
Expand All @@ -12,12 +12,13 @@ FFMPEG = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
JLFzf = "1019f520-868f-41f5-a6de-eb00f4b6a39c"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
JSON5 = "275fdaeb-5887-4102-8704-6b08b28f797b"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043"
Expand Down Expand Up @@ -66,18 +67,19 @@ Gaston = "1"
HDF5 = "0.16 - 0.17"
InspectDR = "0.5"
JLFzf = "0.1"
JSON = "0.21, 1"
JSON5 = "0.21.1"
LaTeXStrings = "1"
Latexify = "0.14 - 0.16"
Measures = "0.3"
NaNMath = "0.3, 1"
OrderedCollections = "1.5"
PGFPlots = "3"
PGFPlotsX = "1"
PlotThemes = "2, 3"
PlotUtils = "1"
PlotlyBase = "0.7 - 0.8"
PlotlyJS = "0.18"
PlotlyKaleido = "1,2"
PlotlyKaleido = "1, 2"
PrecompileTools = "1"
PyPlot = "2"
PythonPlot = "1"
Expand All @@ -94,7 +96,7 @@ UnicodeFun = "0.4"
UnicodePlots = "3.4"
UnitfulLatexify = "1"
Unzip = "0.1 - 0.2"
julia = "1.6"
julia = "1.7"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Expand Down Expand Up @@ -131,4 +133,4 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92"

[targets]
test = ["Aqua", "Colors", "Distributions", "FileIO", "FilePathsBase", "FreeType", "Gaston", "GeometryBasics", "Gtk", "ImageMagick", "Images", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "PlotlyBase", "PyPlot", "PythonPlot", "PlotlyKaleido", "HDF5", "RDatasets", "SentinelArrays", "StableRNGs", "StaticArrays", "StatsPlots", "Test", "TestImages", "UnicodePlots", "Unitful", "VisualRegressionTests"]
test = ["Aqua", "Colors", "Distributions", "FileIO", "FilePathsBase", "FreeType", "Gaston", "GeometryBasics", "Gtk", "ImageMagick", "Images", "LibGit2", "OffsetArrays", "PGFPlotsX", "PlotlyJS", "PlotlyBase", "PythonPlot", "PlotlyKaleido", "HDF5", "RDatasets", "SentinelArrays", "StableRNGs", "StaticArrays", "Test", "TestImages", "UnicodePlots", "Unitful", "VisualRegressionTests"]
7 changes: 6 additions & 1 deletion src/Plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@max_m
@eval Base.Experimental.@max_methods 1
end

using OrderedCollections: OrderedDict
using Dates, Printf, Statistics, Base64, LinearAlgebra, SparseArrays, Random, TOML
using PrecompileTools, Reexport, RelocatableFolders
using Base.Meta
@reexport using LaTeXStrings
@reexport using RecipesBase
@reexport using PlotThemes
@reexport using PlotUtils
Expand Down Expand Up @@ -42,7 +44,7 @@ import Downloads
import Showoff
import Unzip
import JLFzf
import JSON
import JSON5: JSON

#! format: off
export
Expand All @@ -54,6 +56,7 @@ export
wrap,
theme,

Plot,
plot,
plot!,
attr!,
Expand Down Expand Up @@ -82,6 +85,8 @@ export
inline,
closeall,

GRBackend,
PlotlyBackend,
backend,
backends,
backend_name,
Expand Down
2 changes: 1 addition & 1 deletion src/backends.jl
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ function _initialize_backend(pkg::PlotlyBackend)
_runtime_init(pkg)
catch err
if err isa ArgumentError
@warn "Failed to load integration with PlotlyBase & PlotlyKaleido." exception =
@debug "Failed to load integration with PlotlyBase & PlotlyKaleido." exception =
(err, catch_backtrace())
else
rethrow(err)
Expand Down
15 changes: 12 additions & 3 deletions src/backends/gr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ end

gr_inqtext(x, y, s) = gr_inqtext(x, y, string(s))
gr_inqtext(x, y, s::AbstractString) =
if (occursin('\\', s) || occursin("10^{", s)) &&
if (occursin('\\', s) || occursin(r"(?:2|e|10)\^\{", s)) &&
match(r".*\$[^\$]+?\$.*", String(s)) === nothing
GR.inqtextext(x, y, s)
else
Expand All @@ -259,7 +259,7 @@ gr_inqtext(x, y, s::AbstractString) =

gr_text(x, y, s) = gr_text(x, y, string(s))
gr_text(x, y, s::AbstractString) =
if (occursin('\\', s) || occursin("10^{", s)) &&
if (occursin('\\', s) || occursin(r"(?:2|e|10)\^\{", s)) &&
match(r".*\$[^\$]+?\$.*", String(s)) === nothing
GR.textext(x, y, s)
else
Expand Down Expand Up @@ -2086,7 +2086,16 @@ for (mime, fmt) in (
gr_display(plt, dpi_factor)
end
GR.emergencyclosegks()
write(io, read(filepath, String))
let str = read(filepath, String)
if $fmt == "svg"
rex = r"^\t*\K {2}"m
while contains(str, rex)
str = replace(str, rex => "\t")
end
str = replace(str, r"[^\n]\K(</svg>)\s*$"s => s"\n\1\n")
end
write(io, str)
end
rm(filepath)
end
end
Expand Down
85 changes: 8 additions & 77 deletions src/backends/plotly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ end

plotly_font(font::Font, color = font.color) = KW(
:family => font.family,
:size => round(Int, 1.4font.pointsize),
:size => round(Int, 1.5font.pointsize),
:color => rgba_string(color),
)

Expand Down Expand Up @@ -191,13 +191,16 @@ function plotly_polaraxis(sp::Subplot, axis::Axis)
ax
end

function plotly_layout(plt::Plot)
function plotly_layout(plt::Plot; responsive::Bool = true, _...)
plotattributes_out = KW()

w, h = plt[:size]
plotattributes_out[:width], plotattributes_out[:height] = w, h
if !responsive
plotattributes_out[:width], plotattributes_out[:height] = w, h
end
plotattributes_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
plotattributes_out[:margin] = KW(:l => 0, :b => 20, :r => 0, :t => 20)
plotattributes_out[:hoverlabel] = KW(:namelength => -1)

plotattributes_out[:annotations] = KW[]

Expand Down Expand Up @@ -1050,79 +1053,7 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt), 4)

# ----------------------------------------------------------------

html_head(plt::Plot{PlotlyBackend}) = plotly_html_head(plt)
html_body(plt::Plot{PlotlyBackend}) = plotly_html_body(plt)

plotly_url() =
if _use_local_dependencies[]
_plotly_data_url()
else
"https://cdn.plot.ly/$_plotly_min_js_filename"
end

function plotly_html_head(plt::Plot)
plotly = plotly_url()

include_mathjax = get(plt[:extra_plot_kwargs], :include_mathjax, "")

mathjax_file = if include_mathjax != "cdn"
"file://" * include_mathjax
else
"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML"
end

mathjax_head = if isempty(include_mathjax)
""
else
"<script src=\"$mathjax_file\"></script>\n\t\t"
end

if isijulia()
mathjax_head
else
"$mathjax_head<script src=$(repr(plotly))></script>"
end
end

function plotly_html_body(plt, style = nothing)
if style === nothing
w, h = plt[:size]
style = "width:$(w)px;height:$(h)px;"
end

requirejs_prefix = requirejs_suffix = ""
if isijulia()
# require.js adds .js automatically
plotly_no_ext = plotly_url() |> splitext |> first

requirejs_prefix = """
requirejs.config({
paths: {
plotly: '$(plotly_no_ext)'
}
});
require(['plotly'], function (Plotly) {
"""
requirejs_suffix = "});"
end

uuid = UUIDs.uuid4()
html = """
<div id=\"$(uuid)\" style=\"$(style)\"></div>
<script>
$(requirejs_prefix)
$(js_body(plt, uuid))
$(requirejs_suffix)
</script>
"""
html
end

js_body(plt::Plot, uuid) =
"Plotly.newPlot('$(uuid)', $(plotly_series_json(plt)), $(plotly_layout_json(plt)));"

plotly_show_js(io::IO, plot::Plot) =
JSON.print(io, Dict(:data => plotly_series(plot), :layout => plotly_layout(plot)))
include("plotly_html.jl")

# ----------------------------------------------------------------

Expand All @@ -1131,6 +1062,6 @@ Base.showable(::MIME"application/prs.juno.plotpane+html", plt::Plot{PlotlyBacken
_show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend}) =
plotly_show_js(io, plot)

_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend}) = write(io, embeddable_html(plt))
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend}) = write(io, standalone_html(plt))

_display(plt::Plot{PlotlyBackend}) = standalone_html_window(plt)
70 changes: 70 additions & 0 deletions src/backends/plotly_html.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copyright (C) 2024 Heptazhou <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

html_head(plt::Plot{PlotlyBackend}; kw...) = plotly_html_head(plt; kw...)
html_body(plt::Plot{PlotlyBackend}; kw...) = plotly_html_body(plt; kw...)

# https://github.com/plotly/plotly.js/blob/master/src/plot_api/plot_config.js
function plotly_config(plt::Plot; responsive::Bool = true, _...)
KW([:responsive => responsive, :showTips => false])
end

function plotly_html_head(plt::Plot; _...)
# https://cdnjs.com/libraries/mathjax
# https://cdnjs.com/libraries/plotly.js
mathjax = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg-full.min.js"
plotly_js = "https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.35.0/plotly.min.js"

script(src::String) = """\t<script src="$src"></script>\n"""
script(mathjax) * script(plotly_js)
end

function plotly_html_body(plt::Plot; kw...)
id = uuid4()
"""
<main>
<div id="$id"></div>
</main>
<!-- beautify ignore:start -->
<script>
/* beautify ignore:start */
$(js_body(plt, id; kw...) |> strip)
/* beautify ignore:end */
</script>
<!-- beautify ignore:end -->
"""
end

function js_body(plt::Plot, id::Base.UUID; kw...)
f = sort! OrderedDict
s = JSON.json(["$id",
plotly_series(plt) .|> f,
plotly_layout(plt; kw...) |> f,
plotly_config(plt; kw...) |> f,
], 4)
"""
Plotly.newPlot(
$(strip(("[\t\n]"), s))
)
"""
end

plotly_show_js(io::IO, plot::Plot) =
JSON.print(io, OrderedDict(
:data => plotly_series(plot),
:layout => plotly_layout(plot),
:config => plotly_config(plot),
))

Loading

0 comments on commit 862f57b

Please sign in to comment.