-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7ff2773
commit bfffd56
Showing
10 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import JuliaFormatter | ||
|
||
cd(dirname(@__DIR__)) do | ||
formatted_paths = String[] | ||
unformatted_paths = String[] | ||
subdirs = ["src", "test", ".ci"] | ||
for subdir in subdirs | ||
for (root, dirs, files) in walkdir(subdir) | ||
for file in files | ||
fullpath = joinpath(root, file) | ||
fullpath_lowercase = lowercase(fullpath) | ||
if endswith(fullpath_lowercase, ".jl") && | ||
!contains(fullpath_lowercase, "vendor") | ||
is_formatted = JuliaFormatter.format(fullpath) | ||
if is_formatted | ||
push!(formatted_paths, fullpath) | ||
else | ||
push!(unformatted_paths, fullpath) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
n = length(formatted_paths) + length(unformatted_paths) | ||
println("Processed $(n) files.") | ||
println("Formatted correctly: $(length(formatted_paths))") | ||
println("Not formatted correctly: $(length(unformatted_paths))") | ||
if !isempty(unformatted_paths) | ||
println("The following files are not formatted correctly:") | ||
[println(x) for x in unformatted_paths] | ||
throw(ErrorException("Some files are not formatted correctly")) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name: Documentation | ||
|
||
on: | ||
merge_group: | ||
pull_request: | ||
push: | ||
branches: | ||
- main | ||
tags: | ||
- '*' | ||
workflow_dispatch: | ||
concurrency: | ||
# Skip intermediate builds: all builds except for builds on the `master` branch | ||
# Cancel intermediate builds: only pull request builds | ||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/main' || github.run_number }} | ||
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} | ||
|
||
jobs: | ||
build: | ||
permissions: | ||
contents: write | ||
statuses: write | ||
pages: write # to deploy to Pages | ||
id-token: write # to verify the deployment originates from an appropriate source | ||
pull-requests: write | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 | ||
- uses: julia-actions/setup-julia@5c9647d97b78a5debe5164e9eec09d653d29bd71 # v2.6.1 | ||
with: | ||
version: '1' | ||
- uses: julia-actions/cache@2b1bf4d8a138668ac719ea7ca149b53ed8d8401e # v2.0.7 | ||
- name: Install dependencies | ||
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' | ||
- name: Build and deploy | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
run: julia --project=docs/ --color=yes docs/make.jl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: "Enforce changelog" | ||
on: | ||
pull_request: | ||
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled] | ||
|
||
jobs: | ||
changelog: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
- uses: julia-actions/setup-julia@5c9647d97b78a5debe5164e9eec09d653d29bd71 # v2.6.1 | ||
with: | ||
version: '1' | ||
- uses: dangoslen/changelog-enforcer@204e7d3ef26579f4cd0fd759c57032656fdf23c7 # v3.6.1 | ||
with: | ||
changeLogPath: 'CHANGELOG.md' | ||
skipLabels: 'skip-changelog' | ||
- run: julia --project=.ci -e 'using Pkg; Pkg.instantiate()' | ||
- run: julia --project=.ci .ci/changelog.jl | ||
- run: git diff --exit-code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: TagBot | ||
on: | ||
issue_comment: | ||
types: | ||
- created | ||
workflow_dispatch: | ||
inputs: | ||
lookback: | ||
default: "3" | ||
permissions: | ||
actions: read | ||
checks: read | ||
contents: write | ||
deployments: read | ||
issues: read | ||
discussions: read | ||
packages: read | ||
pages: read | ||
pull-requests: read | ||
repository-projects: read | ||
security-events: read | ||
statuses: read | ||
jobs: | ||
TagBot: | ||
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: JuliaRegistries/TagBot@v1 | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
# Edit the following line to reflect the actual name of the GitHub Secret containing your private key | ||
ssh: ${{ secrets.DOCUMENTER_KEY }} | ||
# ssh: ${{ secrets.NAME_OF_MY_SSH_PRIVATE_KEY_SECRET }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ LocalPreferences.toml | |
*.jls | ||
*.ipynb | ||
.cache | ||
docs/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
# QuartoTools.jl | ||
|
||
Helper functions and other utilities for use in `.qmd` notebooks. | ||
|
||
[](https://pumasai.github.io/QuartoTools.jl/stable/) | ||
[](https://pumasai.github.io/QuartoTools.jl/dev/) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[deps] | ||
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" | ||
QuartoTools = "5fded309-f5a0-485a-9129-b3749510da85" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
using Documenter | ||
using QuartoTools | ||
|
||
makedocs(sitename = "QuartoTools", format = Documenter.HTML(), modules = [QuartoTools]) | ||
|
||
deploydocs(repo = "github.com/PumasAI/QuartoTools.jl.git", push_preview = true) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
# QuartoTools.jl | ||
|
||
*Utilities for working with Quarto notebooks in Julia* | ||
|
||
This package provides several utilities that can be used in conjuction with | ||
Quarto notebooks when using the `engine: julia` setting, which executes your | ||
notebook code with | ||
[QuartoNotebookRunner.jl](https://github.com/PumasAI/QuartoNotebookRunner.jl). | ||
|
||
## "Expandables" | ||
|
||
`QuartoNotebookRunner.jl` has a special feature called cell expansion. It | ||
allows you to have a single code cell that outputs what looks like multiple | ||
code cells and their outputs to Quarto. | ||
|
||
*What can you use this feature for?* | ||
|
||
Quarto has many advanced options which allow you to create richer output, for | ||
example [tabsets](https://quarto.org/docs/interactive/layout.html#tabset-panel) | ||
which can group several separate sections of a quarto notebook into selectable | ||
tabs. These features are controlled with markdown annotations, for example, a | ||
tabset follows this structure: | ||
|
||
````qmd | ||
::: {.panel-tabset} | ||
|
||
## Tab 1 | ||
|
||
Content of tab 1 | ||
|
||
## Tab 2 | ||
|
||
Content of tab 2 | ||
|
||
... possibly more tabs ... | ||
|
||
::: | ||
```` | ||
|
||
As you can see, the tabset begins and ends with a pandoc `:::` div fence and | ||
consists of sections demarcated by markdown headings. This mechanism has two | ||
drawbacks for the user: | ||
|
||
- It can be tricky to get the syntax right, especially with multiple nested `:::` fences that need to be closed correctly. (This also applies when you generate markdown programmatically by printing out snippets in loops and using the `output: asis` cell option.) | ||
- It is static. Each tab has to be written into the source markdown explicitly, so you cannot easily create a tabset with a dynamic number of tabs. For example, a tabset with one plot per tab where the number of plots depends on runtime information and therefore is not known in advance. | ||
|
||
Cell expansion can solve both of these problems. It relies on a function called | ||
`QuartoNotebookWorker.expand`, which is defined within the notebook worker | ||
process for every notebook that you execute. | ||
|
||
When a notebook cell returns a Julia value from a cell, such that it is | ||
displayed but Quarto, the `expand` function will first be called on that value. | ||
By default this returns `nothing` and so we just display the original value. | ||
But if an `expand` method is defined for that type, then it should return a | ||
`Vector{QuartoNotebookWorker.Cell}` object which is then evaluated as if they | ||
were real cells. This feature is recursive, so `Cell`s can themselves return | ||
more vectors of `Cell`s. | ||
|
||
Thus we can use these cells to build the structures Quarto expects | ||
programmatically, instead of having to hardcode them into the notebook. | ||
|
||
For example, a tabset with plots could be generated by expanding into: | ||
|
||
- a cell with markdown output `::: {.panel-tabset}` | ||
- a cell with markdown output `## Tab 1` | ||
- a cell with a plot output, for example a `Makie.Figure` | ||
- more headings and plots | ||
- a cell with markdown output `:::` | ||
|
||
!!! note | ||
|
||
Cell expansion is not code generation. We do not generate and evaluate | ||
arbitrary code. Instead, we create objects describing code cells together with | ||
their outputs which is easier to reason about and more composable. | ||
|
||
Each `QuartoNotebookWorker.Cell` has three fields: | ||
|
||
- `thunk` stores a function which returns the fake cell's output value when run. This value is treated as any other code cell output value, so it may be of any type that the display system can handle, and it may even be expandable itself (allowing for recursive expansion). | ||
- `code` may hold a string which will be rendered as the code of the fake cell (this code is not run). | ||
- `options` is a dictionary of quarto cell options, for example `"echo" => false` to hide the source code section. | ||
|
||
`QuartoTools` defines a set of helper objects that can serve as building blocks | ||
that can be composed further. For example, a [`Tabset`](@ref QuartoTools.Tabset) | ||
may contain multiple [`Div`](@ref QuartoTools.Div)s, each describing a | ||
two-column layout which is populated with two plots. | ||
|
||
## Caching | ||
|
||
`QuartoTools` provides a caching mechanism that can be used to save the results | ||
of expensive function calls in your notebook cells. Once loaded into a notebook | ||
via a cell containing `import QuartoTools` you can annotate any subsequent cell | ||
with the `julia.cache.enabled` key as follows: | ||
|
||
````qmd | ||
--- | ||
engine: julia | ||
--- | ||
|
||
```{julia} | ||
import QuartoTools | ||
``` | ||
|
||
```{julia} | ||
#| julia: | ||
#| cache: | ||
#| enabled: true | ||
result = expensive_func(arg) | ||
``` | ||
```` | ||
|
||
The first time that `expensive_func` is called with any specific `arg` value | ||
the result will be saved to disk using [Serialization](@ref). Subsequent calls | ||
with the same `arg` value will return the cached result rather than re-running | ||
`expensive_func`. This can be useful for long-running computations that slow | ||
down the rendering of your notebook. | ||
|
||
Avoid using the feature on cells that only take a few seconds that run, since | ||
the overhead of saving and loading cached results can be larger than the time | ||
saved. If you have a particularly complex cell that contains some fast calls | ||
and some slow ones, try to factor them out into separate cells and only run the | ||
caching on the slow ones. | ||
|
||
The cache for each notebook is stored alongside it in a folder called `.cache`. | ||
Removing this folder will clear the cache for the notebook. Do not commit the | ||
contents of this folder to version control. | ||
|
||
## Serialization | ||
|
||
When working with serialized data in Quarto notebooks users must use the | ||
[`QuartoTools.serialize`](@ref) and [`QuartoTools.deserialize`](@ref) functions | ||
provided by the `QuartoTools` package rather than the `Serialization` package. | ||
This is due to the differences in the behaviour of code evaluation between the | ||
Julia REPL and that of Quarto. These two functions are drop-in replacements for | ||
those provided by `Serialization` and fall back on the implementation provided | ||
by it when not run in a Quarto notebook. This means that simply replacing | ||
`using Serialization` with `using QuartoTools` should be sufficient to allow | ||
for transparent serialization and deserialization between notebooks, batch | ||
scripts, and the REPL. | ||
|
||
Note that if both `QuartoTools` and `Serialization` are imported with `using` | ||
in the same session then the functions `serialize` and `deserialize` will need | ||
to be prefixed with their package name due to the name collisions between the | ||
two packages. Typically users should only need to import `QuartoTools`. | ||
|
||
## Docstrings | ||
|
||
```@autodocs | ||
Modules = [QuartoTools] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
default: | ||
just -l | ||
|
||
changelog: | ||
julia --project=.ci .ci/changelog.jl | ||
|
||
docs: | ||
julia --project=docs docs/make.jl | ||
|
||
format: | ||
julia --project=.ci .ci/format.jl |