From 4695060907f2921d19415c713bfa57bb69ee79cc Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sun, 14 Apr 2024 13:40:24 +0200 Subject: [PATCH] Code and doc formatting, changelog, mark as experimental. --- CHANGELOG.md | 10 ++++- docs/src/outputformats.md | 88 +++++++++++++++++++++++++++------------ src/Literate.jl | 35 +++++++++++----- 3 files changed, 95 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88d8b02..0ef8031 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ 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.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - +## [Unreleased] +### Added + - Literate can now output [Quarto](https://quarto.org/) notebooks (markdown documents with + the `.qmd` file extension) by passing `flavor = Literate.QuartoFlavor()` to + `Literate.markdown`. This feature is marked as experimental since it has not been widely + tested and the Quarto-specific syntax may change before Literate version 3 depending on + what the community wants or needs. ([#199][github-199], [#200][github-200]) ## [2.16.1] - 2024-01-04 ### Fixed @@ -276,6 +282,8 @@ https://discourse.julialang.org/t/ann-literate-jl/10651 for release announcement [github-194]: https://github.com/fredrikekre/Literate.jl/pull/194 [github-195]: https://github.com/fredrikekre/Literate.jl/pull/195 [github-197]: https://github.com/fredrikekre/Literate.jl/issues/197 +[github-199]: https://github.com/fredrikekre/Literate.jl/issues/199 +[github-200]: https://github.com/fredrikekre/Literate.jl/pull/200 [github-204]: https://github.com/fredrikekre/Literate.jl/issues/204 [github-205]: https://github.com/fredrikekre/Literate.jl/pull/205 [github-219]: https://github.com/fredrikekre/Literate.jl/pull/219 diff --git a/docs/src/outputformats.md b/docs/src/outputformats.md index d3c3e4d..8333a3b 100644 --- a/docs/src/outputformats.md +++ b/docs/src/outputformats.md @@ -86,34 +86,70 @@ Literate can output markdown in different flavors. The flavor is specified using [CommonMark](https://commonmark.org/) specification. - `flavor = Literate.FranklinFlavor()`: this outputs markdown meant to be used as input to [Franklin.jl](https://franklinjl.org/). - - `flavor = Literate.QuartoFlavor()` : this outputs markdown file (with file extension ".qmd") meant to be used with [Quarto CLI](https://quarto.org). + - `flavor = Literate.QuartoFlavor()`: this outputs markdown file (with file extension + `.qmd`) meant to be used with [Quarto CLI](https://quarto.org). + +#### Quarto flavor + +!!! warning "Experimental feature" + Quarto markdown output is marked as and experimental feature since it has not been + widely tested. Quarto-specific syntax may change before Literate version 3 depending on + what the community wants and/or needs. If you use this flavor non-interactively (such as + automatically building documentation) it is recommended to pin Literate to a good known + version. + +[Quarto](https://quarto.org/) is an open-source scientific and technical publishing system, +which can extend the range of output formats from your Literate.jl-formatted scripts. +Literate.jl will produce a `.qmd` file, which can be used as input to Quarto CLI to produce +a variety of output formats, including HTML, PDF, Word and RevealJS slides. + +##### Literate + Quarto syntax tips + +- `# `(hashtag followed by a space) at the beginning of a line will be stripped and anything + that follows will rendered as a markdown, e.g., `# # Header level 1` in your script will + be rendered as `# Header level 1` in your .qmd file (ie, it will show as a header). Use + this for adding the YAML header at the top or any Markdown blocks in the Quarto guide. +- `##|`(two hashtags followed by a pipe) at the beginning of a line will strip the first + hashtag and interpret the remainder of the line as part of the code block. This is useful + to provide Quarto commands in computation blocks, e.g., `##! echo: false` would be + rendered as `#| echo: false` and would tell Quarto not to "echo" the outputs of the + execution (see [Guide: Executions + options](https://quarto.org/docs/computations/execution-options.html) for more commands). +- Make sure to always provide the YAML header and specify IJulia kernel when executing the + file by Quarto, e.g., + ``` + # --- + # title: "My Report" + # jupyter: julia-1.9 + # --- + ``` + Notice how all lines are escaped with a `# ` so Literate.jl knows to strip the hashtags + and render it as markdown (see [Authoring + Tutorial](https://quarto.org/docs/get-started/authoring/vscode.html#multiple-formats) for + more examples) +- If any markdown components (e.g. headers) are not rendering correctly in your Quarto + outputs, make sure they are surrounded by empty lines (e.g., add an empty line before and + after the header) to help Quarto parse them correctly + +##### Configuring Quarto for Julia code execution -#### Quarto Flavor Tips & Tricks - -[Quarto](https://quarto.org/) is a new and exciting open-source scientific and technical publishing system, which can extend the range of output formats from your Literate.jl-formatted scripts. -Literate.jl will produce a `.qmd` file, which can be used as input to Quarto CLI to produce a variety of output formats, including HTML, PDF, Word and RevealJS slides. - -Syntax tips: -- `# `(hashtag followed by a space) at the beginning of a line will be stripped and anything that follows will rendered as a markdown, e.g., `# # Header level 1` in your script will be rendered as `# Header level 1` in your .qmd file (ie, it will show as a header). Use this for adding the YAML header at the top or any Markdown blocks in the Quarto guide. -- `##|`(two hashtags followed by a pipe) at the beginning of a line will strip the first hashtag and interpret the remainder of the line as part of the code block. This is useful to provide Quarto commands in computation blocks, e.g., `##! echo: false` would be rendered as `#| echo: false` and would tell Quarto not to "echo" the outputs of the execution (see [Guide: Executions options](https://quarto.org/docs/computations/execution-options.html) for more commands). -- Make sure to always provide the YAML header and specify IJulia kernel when executing the file by Quarto, e.g., -``` -# --- -# title: "My Report" -# jupyter: julia-1.9 -# --- -``` - Notice how all lines are escaped with a `# ` so Literate.jl knows to strip the hashtags and render it as markdown (see [Authoring Tutorial](https://quarto.org/docs/get-started/authoring/vscode.html#multiple-formats) for more examples) -- If any markdown components (eg, headers) are not rendering correctly in your Quarto outputs, make sure they are surrounded by empty lines (e.g., add an empty line before and after the header) to help Quarto parse them correctly - -Steps to install: - Install [Quarto CLI](https://quarto.org/docs/getting-started/installation.html) -- Run `quarto check` to ensure all is installed correctly (you will need Python, Jupyter, and IJulia kernel, see [Getting Started](https://quarto.org/docs/get-started/computations/vscode.html)) - -Steps to create reports: -- Make sure you have the right header specifying which IJulia kernel to use (e.g. `jupyter: julia-1.9`), otherwise Quarto will use the default Python kernel -- Convert your Literate.jl script to a `.qmd` file, e.g. `literate("my_script.jl", flavor = Literate.QuartoFlavor())` -- Run Quarto CLI to produce your desired output format, e.g. `quarto render my_script.qmd --to html` +- Run `quarto check` to ensure all is installed correctly (you will need Python, Jupyter, + and IJulia kernel, see [Getting + Started](https://quarto.org/docs/get-started/computations/vscode.html)) + +##### Steps to create reports + +- Make sure you have the right header specifying which IJulia kernel to use (e.g. `jupyter: + julia-1.9`), otherwise Quarto will use the default Python kernel. +- Convert your Literate.jl script to a `.qmd` file, e.g. + ```julia + Literate.markdown("my_script.jl", flavor = Literate.QuartoFlavor()) + ``` +- Run Quarto CLI to produce your desired output format, e.g. + ```bash + quarto render my_script.qmd --to html + ``` ## [**4.2.** Notebook output](@id Notebook-output) diff --git a/src/Literate.jl b/src/Literate.jl index 586db95..55a064f 100644 --- a/src/Literate.jl +++ b/src/Literate.jl @@ -1,5 +1,5 @@ """ -# Literate + Literate Julia package for Literate Programming. See https://fredrikekre.github.io/Literate.jl/ for documentation. @@ -289,15 +289,23 @@ function edit_commit(inputfile, user_config) return fallback_edit_commit end -# Default to DefaultFlavor() setting -pick_codefence(flavor::AbstractFlavor, execute::Bool, name::AbstractString)=pick_codefence(DefaultFlavor(), execute,name) -pick_codefence(flavor::DefaultFlavor, execute::Bool, name::AbstractString)=("````julia" => "````") -pick_codefence(flavor::DocumenterFlavor,execute::Bool, name::AbstractString)=(execute ? - pick_codefence(DefaultFlavor(), execute,name) : ("````@example $(name)" => "````") -) -pick_codefence(flavor::QuartoFlavor, execute::Bool, name::AbstractString)=(execute ? - error("QuartoFlavor does not support argument execute=true!") : ("```{julia}" => "```") -) +# All flavors default to the DefaultFlavor() setting +function pick_codefence(::AbstractFlavor, execute::Bool, name::AbstractString) + return pick_codefence(DefaultFlavor(), execute, name) +end +function pick_codefence(::DefaultFlavor, execute::Bool, name::AbstractString) + return "````julia" => "````" +end +function pick_codefence(::DocumenterFlavor, execute::Bool, name::AbstractString) + if execute + return pick_codefence(DefaultFlavor(), execute, name) + else + return "````@example $(name)" => "````" + end +end +function pick_codefence(::QuartoFlavor, execute::Bool, name::AbstractString) + return "```{julia}" => "```" +end function create_configuration(inputfile; user_config, user_kwargs, type=nothing) # Combine user config with user kwargs @@ -335,7 +343,7 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing) cfg["codefence"] = pick_codefence( get(user_config, "flavor", cfg["flavor"]), get(user_config, "execute", cfg["execute"]), - get(user_config, "name", replace(cfg["name"], r"\s" => "_")) + get(user_config, "name", replace(cfg["name"], r"\s" => "_")), ) cfg["image_formats"] = _DEFAULT_IMAGE_FORMATS cfg["edit_commit"] = edit_commit(inputfile, user_config) @@ -448,6 +456,11 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) config = create_configuration(inputfile; user_config=user_config, user_kwargs=user_kwargs, type=type) + # Quarto output does not support execute = true + if config["flavor"] isa QuartoFlavor && config["execute"] + throw(ArgumentError("QuartoFlavor does not support `execute = true`.")) + end + # normalize paths inputfile = normpath(inputfile) isfile(inputfile) || throw(ArgumentError("cannot find inputfile `$(inputfile)`"))