Changes to the whole template
This commit is contained in:
parent
01304f599e
commit
416c0f5fb4
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
|
@ -0,0 +1,383 @@
|
|||
@def hascode = true
|
||||
|
||||
# Inserting and evaluating code
|
||||
|
||||
\blurb{Franklin makes it easy to insert code and the result of running the code; Julia code can be evaluated on the fly.}
|
||||
|
||||
\lineskip
|
||||
|
||||
\toc
|
||||
|
||||
## Overview
|
||||
|
||||
### Inserting code
|
||||
|
||||
As per Common Mark specifications, you have multiple ways of inserting code:
|
||||
|
||||
* **inline code**: you can use single backticks (\`) or double backticks (\`\`) (if the code contains single ticks) like so:
|
||||
|
||||
`````plaintext
|
||||
This is some `inline code` or ``inline ` code with a tick``.
|
||||
`````
|
||||
|
||||
* **code blocks**: it is recommended to use triple backticks (\`\`\`) optionally followed by a language name for highlighting like so:
|
||||
|
||||
`````
|
||||
This is some julia code:
|
||||
```julia
|
||||
a = 2
|
||||
@show a
|
||||
```
|
||||
`````
|
||||
|
||||
* **code blocks 2**: you can also use indented code blocks (lines starting with four spaces or a tab) but _fenced code blocks should be preferred_ and you now have to opt-in to use them by setting `@def indented_code = true`
|
||||
|
||||
`````
|
||||
This is some code:
|
||||
|
||||
a = 2
|
||||
@show a
|
||||
`````
|
||||
|
||||
**Note**: when either using indented code blocks or using fenced code blocks with no language name, then the code language for highlighting can be specified with the local page variable `lang` i.e. `@def lang = "julia"` (which is the default) or `@def lang = ""` if you don't want the code to be highlighted.
|
||||
|
||||
### Evaluating code
|
||||
|
||||
When presenting code in a post, it's often convenient to have a way to check the code works and the output shown corresponds to the code.
|
||||
In Franklin there are two approaches that help you for this:
|
||||
|
||||
@@tlist
|
||||
1. For Julia code, a **live-evaluation** of code blocks is supported,
|
||||
1. For all languages, you can run the script separately and use Franklin to insert the code file and/or the output generated by the code.
|
||||
@@
|
||||
|
||||
## Live evaluation (Julia)
|
||||
|
||||
Julia code blocks can be evaluated on the fly and their output either displayed as code or re-interpreted as Markdown.
|
||||
|
||||
\note{
|
||||
**Evaluation time**: when a code block is created or modified and the page is saved, it will trigger a page build that will _wait_ for the evaluation of the code block to complete. So if your code block takes a long time to execute, the page will not be updated before that's done.
|
||||
That being said, if you don't modify the code block, it will only be executed **once** as the output is saved to file.
|
||||
}
|
||||
|
||||
Code blocks that _should not_ be evaluated should be added as per standard markdown, so for instance:
|
||||
|
||||
`````
|
||||
```julia
|
||||
a = 10
|
||||
```
|
||||
`````
|
||||
|
||||
Code blocks that _should_ be evaluated should be added with `julia:path/to/script` where `path/to/script` indicates _where_ the script corresponding to the code block will be saved (**note**: the given path _must_ be in UNIX format even if you're on Windows)
|
||||
|
||||
`````
|
||||
```julia:./code/ex1
|
||||
a = 10
|
||||
@show a
|
||||
```
|
||||
`````
|
||||
|
||||
What this will do is:
|
||||
|
||||
@@tlist
|
||||
1. write the code to the file `/assets/[subpath]/code/ex1.jl`
|
||||
1. run the code and capture its output (`STDOUT`) and write it to `/assets/[subpath]/code/output/ex1.out`
|
||||
@@
|
||||
|
||||
The `[subpath]` here is the _exact same sub-path structure_ than to the page where the code block is inserted.
|
||||
To clarify, let's say you wrote the above code-block in
|
||||
|
||||
```
|
||||
/folder1/page1.md
|
||||
```
|
||||
|
||||
then with the syntax above, the script will be saved in
|
||||
|
||||
```
|
||||
/__site/assets/folder1/code/ex1.jl
|
||||
```
|
||||
|
||||
### More on paths
|
||||
|
||||
There are three ways you can specify where the script corresponding to a code-block should be saved.
|
||||
|
||||
@@tlist
|
||||
1. _relative to the page_: `./[p]/script` is as above, it will write the code block to `/assets/[subpath]/p/script.jl` where `subpath` corresponds to the sub-path of the page where the code block is inserted (path below `/src/`)
|
||||
1. _relative to the assets dir_: `p/script` will write the code block to `/assets/p/script.jl`
|
||||
1. _full path_: `/p/script` will write the code block to `/p/script.jl`
|
||||
@@
|
||||
|
||||
**Note**: when code blocks are evaluated, their output (`STDOUT`) is captured and saved at `[path]/output/script.out` where `[path]` is what precedes `script.jl` in the cases above.
|
||||
|
||||
### Inserting the output
|
||||
|
||||
Let's say you've added the following code block:
|
||||
|
||||
`````
|
||||
```julia:./code_pg1/ex1
|
||||
using LinearAlgebra
|
||||
a = [1, 2, 3]
|
||||
@show dot(a, a)
|
||||
```
|
||||
`````
|
||||
|
||||
In order to show the raw output (whatever was captured in STDOUT) as a code block, write
|
||||
|
||||
```
|
||||
\output{./code_pg1/ex1}
|
||||
```
|
||||
|
||||
which in the present example will introduce exactly the following HTML
|
||||
|
||||
```html
|
||||
<pre><code class="language-julia">dot(a, a) = 14</code></pre>
|
||||
```
|
||||
|
||||
and will look like
|
||||
|
||||
```
|
||||
dot(a, a) = 14
|
||||
```
|
||||
|
||||
If you now change the vector `a` in the code block, the page will be re-compiled with the code-block re-evaluated and the new output will be shown.
|
||||
|
||||
If you would like the output to be re-interpeted by Franklin as text, you can use `\textoutput` instead.
|
||||
Here's an example:
|
||||
|
||||
`````
|
||||
```julia:./code_pg1/ex2
|
||||
using Statistics
|
||||
temps = (15, 15, 14, 16, 18, 19, 20, 12, 10, 24)
|
||||
println("The _average_ temperature is **$(mean(temps))°C**.")
|
||||
```
|
||||
\textoutput{./code_pg1/ex2}
|
||||
`````
|
||||
|
||||
That code block and the `\textoutput` command will appear as:
|
||||
|
||||
```julia
|
||||
using Statistics
|
||||
temps = (15, 15, 14, 16, 18, 19, 20, 12, 10, 24)
|
||||
println("The _average_ temperature is **$(mean(temps))°C**.")
|
||||
```
|
||||
|
||||
The _average_ temperature is **16.3°C**.
|
||||
|
||||
Finally if you want to show your code "notebook-style", i.e. both STDOUT and the result of the last line, use `\show`:
|
||||
|
||||
`````
|
||||
```julia:ex_show
|
||||
x = 5
|
||||
println("hello")
|
||||
x^2
|
||||
```
|
||||
\show{ex_show}
|
||||
`````
|
||||
|
||||
resulting in:
|
||||
|
||||
```julia:ex_show
|
||||
x = 5
|
||||
println("hello")
|
||||
x^2
|
||||
```
|
||||
\show{ex_show}
|
||||
|
||||
|
||||
### Hiding lines
|
||||
|
||||
Sometimes you may want to run some lines but hide them from the presentation, for this just use `# hide` at the end of the line (`hide` is not case sensitive so `# HiDe` would be fine too):
|
||||
|
||||
`````
|
||||
```julia:./code_pg1/ex1
|
||||
using LinearAlgebra # hide
|
||||
a = [1, 2, 3]
|
||||
@show dot(a, a)
|
||||
```
|
||||
`````
|
||||
|
||||
You could also hide the entire code block if you only care about the output, for this put a `# hideall` on any line:
|
||||
|
||||
`````
|
||||
```julia:./code_pg1/ex2
|
||||
#hideall
|
||||
using Statistics
|
||||
temps = (15, 15, 14, 16, 18, 19, 20, 12, 10, 24)
|
||||
println("The _average_ temperature is **$(mean(temps))°C**.")
|
||||
```
|
||||
\textoutput{./code_pg1/ex2}
|
||||
`````
|
||||
|
||||
Which will appear as just:
|
||||
|
||||
The _average_ temperature is **16.3°C**.
|
||||
|
||||
### Project.toml
|
||||
|
||||
It can be convenient to set up your website as you would a Julia environment: _activating_ it and _adding_ the packages that you will use in code blocks.
|
||||
In order to do this, just activate the environment as you would otherwise, this will generate a `Project.toml` which will subsequently be used by Franklin without you having to worry about it.
|
||||
|
||||
For instance, let's say that you want to use `PyCall` in some code blocks, then before starting the Franklin server do
|
||||
|
||||
```julia-repl
|
||||
(1.x) pkg> activate .
|
||||
(myWebsite) pkg> add PyCall
|
||||
```
|
||||
|
||||
once that's done, if you now start the server, Franklin will write
|
||||
|
||||
```julia-repl
|
||||
julia> serve()
|
||||
Activating environment at `~/Desktop/myWebsite/Project.toml`
|
||||
```
|
||||
|
||||
In other words, whenever you start the server, Franklin will now activate the environment with that `Project.toml`.
|
||||
This is particularly useful if you intend to write a tutorial website (for a live example of this, see the [MLJ Tutorials](https://alan-turing-institute.github.io/MLJTutorials/)).
|
||||
|
||||
### Plots
|
||||
|
||||
Using the machinery introduced above, you can also evaluate code that generates a plot which you can then include on the page.
|
||||
In the example below, `PyPlot` is used but you could do something similar with other frameworks.
|
||||
|
||||
Assuming you've added `PyPlot` to your environment, this markdown
|
||||
|
||||
`````markdown
|
||||
```julia:pyplot1
|
||||
using PyPlot
|
||||
figure(figsize=(8, 6))
|
||||
x = range(-2, 2, length=500)
|
||||
for α in 1:5
|
||||
plot(x, sinc.(α .* x))
|
||||
end
|
||||
savefig(joinpath(@OUTPUT, "sinc.svg")) # hide
|
||||
```
|
||||
|
||||
\fig{sinc}
|
||||
`````
|
||||
|
||||
will give:
|
||||
|
||||
```julia:pyplot1
|
||||
using PyPlot
|
||||
figure(figsize=(8, 6))
|
||||
x = range(-2, 2, length=500)
|
||||
for α in 1:5
|
||||
plot(x, sinc.(α .* x))
|
||||
end
|
||||
savefig(joinpath(@OUTPUT, "sinc.svg")) # hide
|
||||
```
|
||||
|
||||
\fig{sinc}
|
||||
|
||||
**Note**: observe that here everything is done with relative paths, `pyplot1` is placed in the `/assets/` folder relatively to the path of the current page and the `\fig` since it's given a path that doesn't start with `/` or `./` will also look in that folder to try to find a figure which starts with the name `sinc`. See also [more about paths](#more_on_paths).
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
A few things can go wrong when attempting to use and evaluate code blocks.
|
||||
The first thing to do if no output is shown or an error appears is to make sure that:
|
||||
|
||||
@@tlist
|
||||
1. if the code uses packages, these packages are available in the local environment,
|
||||
1. the code "just works" in the REPL.
|
||||
@@
|
||||
|
||||
If this is the case and you still have issues, then you may want to force re-evaluation of the code on the page.
|
||||
In such a case, try adding `@def reeval = true` on the page which will cause **all** code blocks on the page to be completely re-evaluated and their output re-generated.
|
||||
Assuming that helped, you will then want to remove that line as otherwise that page will be fully re-evaluated _every single time the page is modified_ which will cause an unnecessary overhead.
|
||||
|
||||
**Important note**: unless you explicitly use `@def reeval = true`, code blocks are evaluated *only* if:
|
||||
@@tlist
|
||||
- an earlier code block has been evaluated (in which case, since their results may depend on it, all subsequent blocks are re-evaluated),
|
||||
- the content of the code block has changed.
|
||||
@@
|
||||
An example where this can be a bit tricky is if your code block calls a function on a file, for instance `read(file, String)`; if the underlying *file* is changed, the code block will **not** be re-evaluated (since the code doesn't change), so in such cases you will want to use a `@def reeval = true`.
|
||||
|
||||
## Offline evaluation (any language)
|
||||
|
||||
The philosophy here is:
|
||||
|
||||
@@tlist
|
||||
* keep your code snippets in appropriate subfolders of `/assets/` where they can be run and their output can be saved, this can be compared to a `test/` folder in a Julia package,
|
||||
* run some or all of the snippets (before running Franklin),
|
||||
* use `\input{...}{...}` in your markdown (see below) and when the website is updated, it will plug-in the most recent parts that have been generated.
|
||||
@@
|
||||
|
||||
That way, if you modify the code, everything will be updated on the website too while ensuring that the code actually runs and generates the output you're displaying.
|
||||
|
||||
Again, the script files can contain `# hide` at the end of lines you do not want to show (`#` to be replaced by whatever symbol indicates comments in that language).
|
||||
|
||||
The `generate_results.jl` file should run the scripts and redirect outputs to the `assets/[path]/output` directory.
|
||||
You can use something like the script below (if you generate an example website with `newsite`, it's already in there) though you can of course modify it as you wish.
|
||||
|
||||
```julia
|
||||
dir = @__DIR__
|
||||
"""
|
||||
genplain(s)
|
||||
|
||||
Small helper function to run some code and redirect the output (stdout) to a file.
|
||||
"""
|
||||
function genplain(s::String)
|
||||
open(joinpath(dir, "output", "$(splitext(s)[1]).out"), "w") do outf
|
||||
redirect_stdout(outf) do
|
||||
include(joinpath(dir, s))
|
||||
end
|
||||
end
|
||||
end
|
||||
# run `script1.jl` and redirect what it prints to `output/script1.out`
|
||||
genplain("script1.jl")
|
||||
# run `script2.jl` which has a savefig(joinpath(@__DIR__, "output", "script2.png"))
|
||||
include("script2.jl")
|
||||
```
|
||||
|
||||
The function `genplain("scriptname.jl")` just redirects the output of the script to `output/scriptname.out`.
|
||||
So for instance if you have in `assets/scripts/script1.jl`
|
||||
|
||||
```julia
|
||||
print("hello")
|
||||
```
|
||||
|
||||
Then `genplain("script1.jl")` will generate `/assets/scripts/output/script1.out` with content
|
||||
|
||||
```julia
|
||||
hello
|
||||
```
|
||||
|
||||
\note{You could have scripts in any language here (`R`, `Python`, ...) as long as the folder structure is the same.}
|
||||
|
||||
### Inserting code
|
||||
|
||||
In order to insert the code of a script and have it highlighted you can use
|
||||
|
||||
```
|
||||
\input{julia}{scripts/script1.jl}
|
||||
```
|
||||
|
||||
This will insert the content of the file `/assets/scripts/script1.jl` (see also the section earlier on paths) into a block that will be highlighted as julia code.
|
||||
|
||||
### Plain-text output
|
||||
|
||||
In order to insert the plain-text output of a script, you can use
|
||||
|
||||
```
|
||||
\output{scripts/script1.jl}
|
||||
```
|
||||
|
||||
This will insert the content of the file `/assets/scripts/script1.out` into a non-highlighted code-block.
|
||||
|
||||
### Plot output
|
||||
|
||||
In order to insert a plot generated by a script, you can use `\fig` as indicated earlier or
|
||||
|
||||
```
|
||||
\input{plot}{scripts/script1.jl}
|
||||
```
|
||||
|
||||
or `\input{plot:id}{scripts/script1.jl}`. This will look for an image file with root name `/assets/scripts/script1.ext` where `ext` is `gif, png, jp(e)g, svg`.
|
||||
If you use `plot:id` then it will look for an image file with root name `/assets/scripts/script1id.ext`.
|
||||
|
||||
The `plot:id` option is useful if you have a script that generates several plots for instance.
|
||||
|
||||
### Slicing up
|
||||
|
||||
The structure in the `generate_results.jl` effectively means that all your code is run as one big script.
|
||||
This also means that if you want to slice some of your code in several parts and show intermediate outputs (e.g. plots), you can just do that by having a `script_1_p1.jl`, `script_1_p2.jl` etc. and then just use `\input` multiple times.
|
|
@ -0,0 +1,197 @@
|
|||
<!--
|
||||
reviewed: 18/4/20
|
||||
-->
|
||||
|
||||
# Working with Franklin
|
||||
|
||||
\blurb{Set things up in minutes and focus on writing great content.}
|
||||
|
||||
\lineskip
|
||||
|
||||
\toc
|
||||
|
||||
## Creating your website
|
||||
|
||||
To get started, the easiest is to use the `newsite` function to generate a website folder which you can then modify to your heart's content.
|
||||
The command takes one mandatory argument: the _name_ of the folder (which can be `"."` if you want to set things up in your current directory).
|
||||
You can optionally specify a template:
|
||||
|
||||
```julia-repl
|
||||
julia> newsite("TestWebsite"; template="vela")
|
||||
✓ Website folder generated at "TestWebsite" (now the current directory).
|
||||
→ Use serve() from Franklin to see the website in your browser.
|
||||
```
|
||||
|
||||
There are a number of [simple templates](https://tlienart.github.io/FranklinTemplates.jl/) you can choose from and tweak.
|
||||
|
||||
\note{The templates are meant to be used as _starting points_ and will likely require some fixes to match what you want. Your help to make them better is very welcome.}
|
||||
|
||||
Once you have created a new website folder, you can start the live-rendering of your website with
|
||||
|
||||
```julia-repl
|
||||
julia> serve()
|
||||
→ Initial full pass...
|
||||
→ Starting the server...
|
||||
✓ LiveServer listening on http://localhost:8000/ ...
|
||||
(use CTRL+C to shut down)
|
||||
```
|
||||
|
||||
and navigate in a browser to the corresponding address to preview the website.
|
||||
|
||||
### Folder structure
|
||||
|
||||
The initial call to `newsite` generates a folder with the following structure:
|
||||
|
||||
```plaintext
|
||||
.
|
||||
├── _assets/
|
||||
├── _layout/
|
||||
├── _libs/
|
||||
├── config.md
|
||||
└── index.md
|
||||
```
|
||||
|
||||
After running `serve` the first time, an additional folder is generated: `__site` which will contain your full generated website.
|
||||
Among these folders:
|
||||
|
||||
@@tlist
|
||||
* the files in the top folder such as `index.md` are the source files for the generated pages, you must have an `index.md` or `index.html` at the top level but can then use whatever folder structure you want (see further),
|
||||
* you should **not** modify the content of `__site` as it's *generated* and any changes you do in there may be silently over-written whenever you modify files elsewhere,
|
||||
* the folders `_assets/`, `_libs/`, `_layout` and `_css` contain *auxiliary files* supporting your site:
|
||||
* `_assets/` will contain images, code snippets, etc.,
|
||||
* `_css/` will contain the style sheets,
|
||||
* `_libs/` will contain javascript libraries,
|
||||
* `_layout/` will contain bits of HTML scaffolding for the generated pages,
|
||||
@@
|
||||
|
||||
### Top folder
|
||||
|
||||
In this folder,
|
||||
|
||||
@@tlist
|
||||
* `index.md` will generate the site's landing page,
|
||||
* `pages/page1.md` would correspond to pages on your website (you can have whatever subfolder structure you want in here),
|
||||
* `config.md` allows to specify variables that help steer the page generation, you can also use it to declare global variables or definitions that can then be used on all pages.
|
||||
@@
|
||||
|
||||
\note{You can also write pages in plain HTML. For instance you may want to write an `index.html` file instead of generating it via the `index.md`. You will still need to put it at the exact same place and let Franklin copy the files appropriately.}
|
||||
|
||||
Note that Franklin generates a folder structure in `__site` which allows to have URLs like `[website]/page1/`. The following rules are applied:
|
||||
|
||||
* the filename is `[path/]index.md` or `[path/]index.html`, it will be copied over "as is" to `__site/[path/]index.html`,
|
||||
* the filename is `[path/]somepage.md` or `[path/]somepage.html`, it will be copied to `__site/[path/]somepage/index.html`.
|
||||
|
||||
So for instance if we ignore auxiliary files and you have
|
||||
|
||||
```
|
||||
.
|
||||
├── index.md
|
||||
├── folder
|
||||
│ └── subpage.md
|
||||
└── page.md
|
||||
```
|
||||
|
||||
it will lead to
|
||||
|
||||
```
|
||||
__site
|
||||
├── index.html
|
||||
├── folder
|
||||
│ └── subpage
|
||||
│ └── index.html
|
||||
└── page
|
||||
└── index.html
|
||||
```
|
||||
|
||||
which allows to have the following URLs:
|
||||
|
||||
@@tlist
|
||||
* `[website]/`
|
||||
* `[website]/page/`
|
||||
* `[website]/folder/subpage/`
|
||||
@@
|
||||
|
||||
### Reserved names
|
||||
|
||||
To avoid name clashes, refrain from using the following paths where `/` indicates the topdir (website folder):
|
||||
|
||||
@@tlist
|
||||
* `/css/` or `/css.md`
|
||||
* `/layout/` or `/layout.md`
|
||||
* `/literate/` or `/literate.md`
|
||||
@@
|
||||
|
||||
Also bear in mind that Franklin will ignore `README.md`, `LICENSE.md`, `Manifest.toml` and `Project.toml`.
|
||||
|
||||
### Editing and testing your website
|
||||
|
||||
The `serve` function can be used to launch a server which will track and render modifications.
|
||||
There are a few useful options you can use beyond the barebone `serve()`, do `?serve` in your REPL for all options, we list a few noteworthy one below:
|
||||
|
||||
@@tlist
|
||||
* `clear=false`, whether to erases `__site` and starts from a blank slate,
|
||||
* `single=false`, whether to do a single build pass generating all pages and not start the server.
|
||||
* `prerender=false`, whether to prerender code blocks and maths (see the [optimisation step](#optimisation_step))
|
||||
* `verb=false`, whether to show information about which page is being processed etc,
|
||||
* `silent=false`, whether to suppress any informative messages that could otherwise appear in your console when editing your site, this goes one step further than `verb=false` as it also applies for code evaluation,
|
||||
* `eval_all=false`, whether to re-evaluate all code blocks on all pages.
|
||||
@@
|
||||
|
||||
## Post-processing
|
||||
|
||||
### Verify links
|
||||
|
||||
Before deploying you may want to verify that links on your website lead somewhere, to do so use the `verify_links()`.
|
||||
It will take a few second to verify all links on every generated pages but can be quite helpful to identify dead links or links with typos:
|
||||
|
||||
```julia-repl
|
||||
julia> verify_links()
|
||||
Verifying links... [you seem online ✓]
|
||||
- internal link issue on page index.md: /menu3/.
|
||||
```
|
||||
|
||||
then after fixing and re-generating pages:
|
||||
|
||||
```julia-repl
|
||||
julia> verify_links()
|
||||
All internal and external links verified ✓.
|
||||
```
|
||||
|
||||
### Pre-rendering and compression
|
||||
|
||||
The `optimize` function can
|
||||
|
||||
@@tlist
|
||||
* pre-render KaTeX and highlight.js code to HTML so that the pages don't have to load these javascript libraries,
|
||||
* minify all generated HTML and CSS.
|
||||
@@
|
||||
See `?optimize` for options.
|
||||
|
||||
Those two steps may lead to faster loading pages.
|
||||
Note that in order to run them, you will need a couple of external dependencies as mentioned in the [installation section](/index.html#installing_optional_extras).
|
||||
|
||||
The `optimize` function is called by default in the `publish` function which can be used to help deploy your website.
|
||||
|
||||
### Publish
|
||||
|
||||
\note{If you use GitHub or GitLab with a deployment action on those platforms, you do not need to use `publish`, you can just push your changes and let the relevant action do the rest on the platform. See the section on [deployment](/workflow/deploy/).}
|
||||
|
||||
Once you have synched your local folder with a remote repository (see [deployment instructions](/workflow/deploy/)), the `publish` function can be called to deploy your website; it essentially:
|
||||
|
||||
@@tlist
|
||||
- applies an optional optimisation step (see previous point),
|
||||
- does a `git add -A; git commit -am "franklin-update"; git push`.
|
||||
@@
|
||||
|
||||
See `?publish` for more information.
|
||||
|
||||
In any case, before deploying, if you're working on a _project website_ i.e. a website whose root URL will look like `username.gitlab.io/project/` then you should add the following line in your `config.md` file:
|
||||
|
||||
```markdown
|
||||
@def prepath = "project"
|
||||
```
|
||||
|
||||
the `publish` function will then ensure that all links are fixed before deploying your website.
|
||||
|
||||
Note also that the `publish` function accepts a `final=` keyword to which you can pass any function `() -> nothing` to do some final post-processing before pushing updates online.
|
||||
For instance, you can use `final=lunr` where `lunr` is a function exported by Franklin which generates a Lunr search index (see [this tutorial](/extras/lunr/) for more details).
|
Loading…
Reference in New Issue