ExampleJuggler.ExampleJugglerModule
ExampleJuggler

ci Aqua QA

ExampleJuggler.jl

This package also could be called "DocumenterAndTestExampleHandler.jl". It helps to maintain comprehensive complete (i.e. ready to download and run) code examples in Documenter.jl documentation.

Code examples could be in plain Julia scripts, Julia scripts containing modules or pluto notebooks and serve three purposes:

Maintaining a list of examples leads to considerable boilerplate ("example juggling" - that is why the name ...) in test/runtest.jl and docs/make.jl. This package helps to hide this boilerplate behind its API.

Breaking changes

  • v2.0.0: Moved all direct and indirect dependencies on Pluto into extensions. Correspondingly, one needs to explicitely import Pluto, PlutoStaticHTML or PlutoSliderServer. They are not anymore direct dependencies of ExampleJuggler.

CI Tests

With this package, test/runtests.jl can look as follows(please see test/runtests.jl of this package for a more comprehensive setting):

using Test
using ExampleJuggler
import Pluto

ExampleJuggler.verbose!(true)

example_dir = joinpath(@__DIR__, "..", "examples")

modules = ["ExampleModule.jl"]
notebooks = ["PlutoTemplate.jl", "ExamplePluto.jl"]
scripts = ["testscript.jl", "PlutoTemplate.jl", "ExamplePluto.jl"]

# This needs `import Pluto`
@testset "pluto notebooks" begin
    @testplutonotebooks(example_dir, notebooks)
end

@testset "module examples" begin
    @testmodules(example_dir, modules, a=2)
end

# This tests Pluto notebooks as scripts and doesn't need Pluto
@testset "scripts + notebooks" begin
    @testscripts(example_dir, scripts)
end

Documenter build

With this package, docs/make.jl can look as follows (please see docs/make.jl of this package for a more comprehensive setting):

using Documenter, ExampleJuggler, CairoMakie
import PlutoStaticHTML

DocMeta.setdocmeta!(ExampleJuggler, :DocTestSetup, :(using ExampleJuggler); recursive = true)

example_dir = joinpath(@__DIR__, "..", "examples")

modules = ["ExampleModule.jl"]
    
notebooks = ["PlutoTemplate.jl"
                 "Example with Graphics" => "ExamplePluto.jl"]

cleanexamples()

module_examples = @docmodules(example_dir, example_modules, Plotter=CairoMakie)

# This needs to load PlutoStaticHTML
html_examples = @docplutonotebooks(example_dir, notebooks)

makedocs(; sitename = "ExampleJuggler.jl",
           modules = [ExampleJuggler],
           format = Documenter.HTML(; size_threshold_ignore = last.(html_examples),
                                      mathengine = MathJax3()),
             authors = "J. Fuhrmann",
             repo = "https://github.com/j-fu/ExampleJuggler.jl",
             pages = [
                 "api.md",
                 "Modules" => module_examples,
                 "Notebooks" => html_examples,
             ])


cleanexamples()

deploydocs(; repo = "github.com/j-fu/ExampleJuggler.jl.git", devbranch = "main")

end

In particular, graphics generation for module and script examples is supported.

ExampleJuggler.docmodulesMethod
     docmodules(example_dir, example_modules; kwargs...)

Generate markdown files for use with documenter from list of Julia code examples in example_dir via Literate.jl in form of modules.

Keyword arguments:

  • use_module_titles: use titles from module input files

See ExampleModule.jl for an example.

ExampleJuggler.docplutonotebooksMethod
docplutonotebooks(example_dir, notebooks, kwargs...)

Parameters:

  • notebooks: vector of pathnames or pairs of pathnames and strings pointing to notebooks to be tested.

Keyword arguments:

  • pluto_project: if not nothing, this is passed via ENV["PLUTO_PROJECT"] to the notebooks with the possibility to activate it. By default it has the value of Base.active_project() which in practice is the environment runtests.jl is running in. As a consequence, if this default is kept, it is necessary to have all package dependencies of the notebooks in the package environment.
  • iframe: boolean (default: false).
    • If true, html files are produced from the notebooks via PlutoSliderServer.jl, similar to Pluto's html export. For documenter, a markdown page is created which contains statements to show the notebook html in an iframe. The advantage of this method is that active javascript content is shown. The disadvantage is weak integration into documenter. Prerequisite is import PlutoSliderServer in docs/make.jl.
    • If false, Documenter markdown files are ceated via PlutoStaticHTML.jl. These integrate well with Documenter, but are (as of now) unable to show active javascript content. Graphics is best prepared with CairoMakie. Prerequisite is import PlutoStaticHTML in docs/make.jl.
  • distributed: Use parallel evaluation when iframe==false
  • source_prefix: Path prefix to the notebooks on github (for generating download links) Default: "https://github.com/j-fu/ExampleJuggler.jl/blob/main/examples".
  • iframe_height: Height of the iframe generated. Default: "500px".

Return value: Vector of pairs of pathnames and strings pointing to generated markdown files for use in Documenter.makedocs()

ExampleJuggler.example_md_dirMethod
 example_md_dir(subdir)

Return full path to the subdirectory of docs/src where the markdown files should be placed which later will be scanned by Documenter. Creates the directory if it doesn't already exist.

ExampleJuggler.mock_xMethod
mock_x(; n, f)

Generate n-Vector X and return X, f.(X) for some function f;

ExampleJuggler.mock_xtMethod
mock_xt(; n, m, f)
    Generate n-Vector `X`, m-Vector `T` and return `X,T,[f(x,t) for x ∈ X, t∈T]` for some function f;
ExampleJuggler.testplutonotebooksMethod
 testplutonotebooks(example_dir, notebooks; kwargs...)

Test pluto notebooks as notebooks in a pluto session which means that the notebook code is run in an extra process. Implemented in an extension triggered by using Pluto.

The method tracks Test.@test statements in notebook cells via testing errors of failed cells. The method does not invoke eventual runteststs() methods in the notebooks.

Parameters:

  • example_dir: subdirectory with examples
  • notebooks: vector of pathnames of notebooks to be tested.

Keyword arguments:

  • pluto_project: if not nothing, this is passed via ENV["PLUTO_PROJECT"] to the notebooks with the possibility to activate it. By default it has the value of Base.active_project() which in practice is the environment runtests.jl is running in. As a consequence, if this default is kept, it is necessary to have all package dependencies of the notebooks in the package environment.
ExampleJuggler.@docmodulesMacro
@docmodules(example_dir, modules, kwargs...)

Generate markdown files and plots for use with documenter from list of Julia modules. Wrapper macro for docmodules.

ExampleJuggler.@docscriptsMacro
@docscripts(example_dir, modules, kwargs...)

Generate markdown files and plots for use with documenter from list of Julia modules. Wrapper macro for docmodules.

ExampleJuggler.@plotmoduleMacro
@plotmodule(modules, kwargs...)

Include module into context of calling module and execute generateplots(;kwargs...) if it exists.

ExampleJuggler.@testmoduleMacro
@testmodule

Include script defining a module in the context of the calling module and call the runtests method if it is defined in this module, passing kwargs....

ExampleJuggler.@testscriptMacro
testscript(script)

Wrap script (or Pluto notebook seen as script) into a custom module and evaluate it in the context of the calling module. If the script contains a function runtests, call it. It is assumed that the script uses Test.@test to test correctness.