PlutoStaticHTML
Convert Pluto notebooks to pure HTML (without Javascript). This allows Pluto notebooks to be embedded in Documenter, Franklin and (optionally) to be styled manually via CSS. Also, it is possible to hide code blocks making it easy to show Julia generated output without showing code. Typically, converting Pluto notebooks to HTML is useful for things like
- tutorials (a ready-to-use template can be found at https://rikhuijzer.github.io/JuliaTutorialsTemplate/)
- blogs
- documentation
For a quick preview, this package is used for the tutorials at TuringGLM.jl. Also, I'm using this package for my own blog, for example: https://huijzer.xyz/posts/frequentist-bayesian-coin-flipping/.
API overview
The most important method is build_notebooks
(API).
build_notebooks
ensures that the original notebook will not be changed.
In general, the idea is to
- Create a bunch of Pluto notebooks.
- Get the name of the directory
dir
which contains your Pluto notebooks. - Choose one or more appropriate
output_format
s depending on how the output will be used. The output format can behtml_output
,documenter_output
,franklin_output
orpdf_output
. - Pass the paths to
build_notebooks
which, depending onoutput_format
, writes HTML or Markdown outputs to files. - Read the output from the files and show them on a website via either your own logic or Documenter or Franklin.
Note that this is a very nice development workflow because developing in Pluto notebooks is easy and allows for quick debugging. Also, Pluto has a lot of conversions built-in. This package will take the converted outputs, such as plots or tables, from Pluto which ensures that what you see in Pluto is what you see in the HTML output.
As an extension of Pluto, this package provides # hide
and # hideall
comments like Franklin and Documenter. A # hideall
somewhere in a Pluto code block will hide the code (but not the output). A # hide
behind a line in a code block will hide the line. Also, by default, this package hides all Markdown code blocks since readers are probably only interested in reading the output of the Markdown code block. This and more options can be tuned via OutputOptions
.
See below for more specific instructions on
Documenter.jl
The output_format=documenter_output
is used at various places which can all serve as an example:
- "docs/make.jl" in this repository.
- TuringGLM.jl; for example output see the linear regression tutorial.
- Resample.jl; for example output see the SMOTE tutorial.
- GraphNeuralNetworks.jl tutorials, see for example Hand-On Graph Neural Networks.
Avoid calling the conversion from inside a Documenter.jl code block. For some reason, that is likely to freeze or hang; probably due to stdout
being flooded with information. Instead generate Markdown files via docs/make.jl
and point to these files in pages
.
Franklin.jl
For output_format=franklin_output
examples, see
- The template at https://rikhuijzer.github.io/JuliaTutorialsTemplate/.
- My blog. For example, a post on random forests.
Specifically, use the following KaTeX options:
const options = {
delimiters: [
{left: "$$", right: "$$", display: true},
{left: "\\begin{equation}", right: "\\end{equation}", display: true},
{left: "\\begin{align}", right: "\\end{align}", display: true},
{left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
{left: "\\begin{gather}", right: "\\end{gather}", display: true},
{left: "\\(", right: "\\)", display: false},
{left: "\\[", right: "\\]", display: true}
]
};
document.addEventListener('DOMContentLoaded', function() {
renderMathInElement(document.body, options);
});
Note that $x$
will not be interpreted as inline math by this KaTeX configuration. This is to avoid conflicts with using the dollar symbol to represent the dollar (currency). Instead, PlutoStaticHTML.jl
automatically converts inline math from $x$
to \($x\)
. With above KaTeX settings, Franklin.jl
will interpret this as inline math. By default, Documenter.jl
will also automatically interpret this as inline math.
Parallel build
To speed up the build, this package defines build_notebooks
. This function evaluates the notebooks in parallel by default. Also, it can use Caching to speed up the build even more.
To use it, pass a dir
to write HTML files for all notebook files (the files are recognized by the ".jl" extension and that the file starts with ### A Pluto.jl notebook ###
):
julia> using PlutoStaticHTML: build_notebooks
julia> dir = joinpath("posts", "notebooks");
julia> bopts = BuildOptions(dir);
julia> build_notebooks(bopts);
[...]
To run only specific notebooks, specify the files
:
julia> files = ["notebook1.jl", "notebook2.jl"];
julia> build_notebooks(bopts, files)
[...]
In CI, be sure to call this before using Franklin serve
or optimize
.
For more options, such as append_build_context
to add Julia and packages version information, you can pass OutputOptions
:
julia> oopts = OutputOptions(; append_build_context=true);
julia> build_notebooks(bopts, files, oopts)
[...]
See build_notebooks
for more information.
Caching
Using caching can greatly speed up running times by avoiding to re-evaluate notebooks. Caching can be enabled by passing previous_dir
via BuildOptions
. This previous_dir
should point to a location where HTML or Markdown files are from the previous build. Then, build_notebooks
will, for each input file file.jl
, check:
- Whether
joinpath(previous_dir, "file.html")
exists - Whether the SHA checksum of the current
$file.jl
matches the checksum of the previous$file.jl
. When assuming that Pluto's built-in package manager is used to manage packages, this check ensures that the packages of the previous run match the packages of the current run. - Whether the Julia version of the previous run matches the Julia version of the current run.
Caching assumes that notebooks are deterministic, that is, the notebook will produce the same output from the same input.
The previous_dir
provides a lot of flexibility. For example, it is possible to point towards a Git directory with the HTML or Markdown output files from last time. Alternatively, for output_format=html_output
it is possible to download the web pages where the notebooks are shown and put these web pages in a directory. This works by extracting the state from the previous run from the output.
LaTeX equations
Pluto uses MathJax by default, so make sure to setup MathJax in Franklin or Documenter. For Franklin, see https://rikhuijzer.github.io/JuliaTutorialsTemplate/. For Documenter, see docs/make.jl
in this repository.
API
PlutoStaticHTML.build_notebooks
— Functionbuild_notebooks(
bopts::BuildOptions,
[files,]
oopts::OutputOptions=OutputOptions();
session=ServerSession()
)
Build Pluto notebook files
in dir
. Here, files
is optional. When not passing files
, then all Pluto notebooks in dir
will be built.
Example
julia> dir = joinpath(homedir(), "my_project", "notebooks");
julia> bopts = BuildOptions(dir);
julia> oopts = OutputOptions(; append_build_context=true);
julia> files = ["pi.jl", "math.jl"];
julia> build_notebooks(bopts, files, oopts);
PlutoStaticHTML.BuildOptions
— TypeBuildOptions(
dir::AbstractString;
write_files::Bool=true,
previous_dir::Union{Nothing,AbstractString}=nothing,
output_format::Union{OutputFormat,Vector{OutputFormat}}=html_output,
add_documenter_css::Bool=true,
use_distributed::Bool=true,
compiler_options::Union{Nothing,CompilerOptions}=nothing,
max_concurrent_runs::Int=4
)
Arguments:
dir
: Directory in which the Pluto notebooks are stored.write_files
: Write files tojoinpath(dir, "$file.html")
.previous_dir::Union{Nothing,AbstractString}=Nothing
: Use the output from the previous run as a cache to speed up running time. To use the cache, specify a directoryprevious_dir::AbstractString
which contains HTML or Markdown files from a previous run. Specifically, files are expected to be atjoinpath(previous_dir, "$file.html")
. The output from the previous run may be embedded in a larger HTML or Markdown file. This package will extract the original output from the full file contents. By default, caching is disabled.output_format
: What file to write the output to. By default this ishtml_output::OutputFormat
meaning that the output of the HTML method is pure HTML. To generate Franklin, Documenter or PDF files, use respectivelyfranklin_output
,documenter_output
orpdf_output
. WhenBuildOptions.write_files == true
andoutput_format == franklin_output
oroutput_format == documenter_output
, the output file has a ".md" extension instead of ".html". WhenBuildOptions.write_files == true
andoutput_format == pdf_output
, two output files are created with ".tex" and ".pdf" extensions.add_documenter_css
whether to add a CSS style to the HTML whendocumenter_output=true
.use_distributed
: Whether to build the notebooks in different processes. By default, this is enabled just like in Pluto and the notebooks are build in parallel. The benefit of different processes is that things are more independent of each other. Unfortunately, the drawback is that compilation has to happen for each process. By setting this option tofalse
, all notebooks are built sequentially in the same process which avoids recompilation. This is likely quicker in situations where there are few threads available such as GitHub Runners depending on the notebook contents. Beware thatuse_distributed=false
will not work with Pluto's built-in package manager.compiler_options
:Pluto.Configuration.CompilerOptions
to be passed to Pluto. This can, for example, be useful to pass custom system images fromPackageCompiler.jl
.max_concurrent_runs
: Maximum number of notebooks to evaluate concurrently whenuse_distributed=true
. Note that each notebook starts in a different process and can start multiple threads, so don't set this number too high or the CPU might be busy switching tasks and not do any productive work.
PlutoStaticHTML.OutputOptions
— TypeOutputOptions(;
code_class::AbstractString="language-julia",
output_pre_class::AbstractString="code-output documenter-example-output",
hide_code::Bool=false,
hide_md_code::Bool=true,
hide_md_def_code::Bool=true,
add_state::Bool=true,
append_build_context::Bool=false,
show_output_above_code::Bool=false,
replace_code_tabs::Bool=true,
convert_admonitions::Bool=true
)
Arguments:
code_class
: HTML class for code. This is used by CSS and/or the syntax highlighter.output_pre_class
: HTML class for<pre>
.output_class
: HTML class for output. This is used by CSS and/or the syntax highlighter.hide_code
: Whether to omit all code blocks. Can be useful when readers are not interested in code at all.hide_md_code
: Whether to omit all Markdown code blocks.hide_md_def_code
: Whether to omit Franklin Markdown definition code blocks (blocks surrounded by +++).add_state
: Whether to add a comment in HTML with the state of the input notebook. This state can be used for caching. Specifically, this state stores a checksum of the input notebook and the Julia version.append_build_context
: Whether to append build context. When set totrue
, this adds information about the dependencies and Julia version. This is not executed via Pluto.jl's evaluation to avoid having to add extra dependencies to existing notebooks. Instead, this reads the manifest from the notebook file.show_output_above_code
: Whether to show the output from the code above the code. Pluto.jl shows the output above the code by default; this package shows the output below the code by default. To show the output above the code, setshow_output_above_code=true
.replace_code_tabs
: Replace tabs at the start of lines inside code blocks with spaces. This avoids inconsistent appearance of code blocks on web pages.convert_admonitions
: Convert admonitions such as!!! note This is a note.
from Pluto's HTML to Documenter's HTML. When this is enabled, thedocumenter_output
has proper styling by default.