Template change
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Thibaut Lienart
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,7 @@
|
||||||
|
[deps]
|
||||||
|
Franklin = "713c75ef-9fc9-4b05-94a9-213340da978e"
|
||||||
|
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||||
|
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
|
||||||
|
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
|
||||||
|
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
|
||||||
|
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Franklin Docs
|
||||||
|
|
||||||
|
Website for [Franklin.jl](https://github.com/tlienart/Franklin.jl).
|
||||||
|
|
||||||
|
## Dev note
|
||||||
|
|
||||||
|
No prerendering (due to tricky code environments that get destroyed by highlight.js).
|
|
@ -0,0 +1,6 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
#hideall
|
||||||
|
colors=(:pink, :lightpink, :hotpink, :deeppink, :mediumvioletred, :palevioletred, :coral, :tomato, :orangered, :darkorange, :orange, :gold, :yellow)
|
||||||
|
print("@@ccols ")
|
||||||
|
print.("\\circle{$c}" for c in colors)
|
||||||
|
println("@@")
|
|
@ -0,0 +1 @@
|
||||||
|
@@ccols \circle{pink}\circle{lightpink}\circle{hotpink}\circle{deeppink}\circle{mediumvioletred}\circle{palevioletred}\circle{coral}\circle{tomato}\circle{orangered}\circle{darkorange}\circle{orange}\circle{gold}\circle{yellow}@@
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
|
@ -0,0 +1 @@
|
||||||
|
0.65
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
|
@ -0,0 +1,19 @@
|
||||||
|
@@simple-table
|
||||||
|
Name | Number
|
||||||
|
:--- | :---
|
||||||
|
Taimur | 1525
|
||||||
|
Catherine | 5134
|
||||||
|
Maria | 4214
|
||||||
|
Arvind | 9019
|
||||||
|
Jose | 8918
|
||||||
|
Minjie | 5757
|
||||||
|
@@
|
||||||
|
~~~
|
||||||
|
<style>
|
||||||
|
.simple-table tr {
|
||||||
|
padding:0;
|
||||||
|
line-height:1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
~~~
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
|
@ -0,0 +1,77 @@
|
||||||
|
@@cards @@row
|
||||||
|
@@column
|
||||||
|
\card{Jane Doe}{CEO & Founder}{Phasellus eget enim eu lectus faucibus vestibulum}{example@example.com}
|
||||||
|
@@
|
||||||
|
|
||||||
|
@@column
|
||||||
|
\card{Mike Ross}{Art Director}{Phasellus eget enim eu lectus faucibus vestibulum}{example@example.com}
|
||||||
|
@@
|
||||||
|
|
||||||
|
@@column
|
||||||
|
\card{John Doe}{Designer}{Phasellus eget enim eu lectus faucibus vestibulum}{example@example.com}
|
||||||
|
@@
|
||||||
|
|
||||||
|
@@ @@
|
||||||
|
~~~
|
||||||
|
<style>
|
||||||
|
.column {
|
||||||
|
float:left;
|
||||||
|
width:30%;
|
||||||
|
margin-bottom:16px;
|
||||||
|
padding:0 8px;
|
||||||
|
}
|
||||||
|
@media (max-width:62rem) {
|
||||||
|
.column {
|
||||||
|
width:45%;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width:30rem){
|
||||||
|
.column {
|
||||||
|
width:95%;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card{
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.card img {
|
||||||
|
padding-left:0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
.container::after, .row::after{
|
||||||
|
content:"";
|
||||||
|
clear:both;
|
||||||
|
display:table;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
color:grey;
|
||||||
|
}
|
||||||
|
.vitae {
|
||||||
|
margin-top:0.5em;
|
||||||
|
}
|
||||||
|
.email {
|
||||||
|
font-family:courier;
|
||||||
|
margin-top:0.5em;
|
||||||
|
margin-bottom:0.5em;
|
||||||
|
}
|
||||||
|
.button{
|
||||||
|
border:none;
|
||||||
|
outline:0;
|
||||||
|
display:inline-block;
|
||||||
|
padding:8px;
|
||||||
|
color:white;
|
||||||
|
background-color:#000;
|
||||||
|
text-align:center;
|
||||||
|
cursor:pointer;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.button:hover{
|
||||||
|
background-color:#555;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
~~~
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
|
@ -0,0 +1,12 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
#hideall
|
||||||
|
using PyCall
|
||||||
|
lines = replace("""import numpy as np
|
||||||
|
np.random.seed(2)
|
||||||
|
x = np.random.randn(5)
|
||||||
|
r = np.linalg.norm(x) / len(x)
|
||||||
|
np.round(r, 2)""", r"(^|\n)([^\n]+)\n?$" => s"\1res = \2")
|
||||||
|
py"""
|
||||||
|
$$lines
|
||||||
|
"""
|
||||||
|
println(py"res")
|
|
@ -0,0 +1,19 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
#hideall
|
||||||
|
names = (:Taimur, :Catherine, :Maria, :Arvind, :Jose, :Minjie)
|
||||||
|
numbers = (1525, 5134, 4214, 9019, 8918, 5757)
|
||||||
|
println("@@simple-table")
|
||||||
|
println("Name | Number")
|
||||||
|
println(":--- | :---")
|
||||||
|
println.("$name | $number" for (name, number) in zip(names, numbers))
|
||||||
|
println("@@")
|
||||||
|
raw"""
|
||||||
|
~~~
|
||||||
|
<style>
|
||||||
|
.simple-table tr {
|
||||||
|
padding:0;
|
||||||
|
line-height:1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
~~~
|
||||||
|
""" |> println
|
|
@ -0,0 +1,82 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
#hideall
|
||||||
|
team = [
|
||||||
|
(name="Jane Doe", title="CEO & Founder", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com"),
|
||||||
|
(name="Mike Ross", title="Art Director", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com"),
|
||||||
|
(name="John Doe", title="Designer", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com")
|
||||||
|
]
|
||||||
|
|
||||||
|
"@@cards @@row" |> println
|
||||||
|
for person in team
|
||||||
|
"""
|
||||||
|
@@column
|
||||||
|
\\card{$(person.name)}{$(person.title)}{$(person.vitae)}{$(person.email)}
|
||||||
|
@@
|
||||||
|
""" |> println
|
||||||
|
end
|
||||||
|
println("@@ @@") # end of cards + row
|
||||||
|
|
||||||
|
raw"""
|
||||||
|
~~~
|
||||||
|
<style>
|
||||||
|
.column {
|
||||||
|
float:left;
|
||||||
|
width:30%;
|
||||||
|
margin-bottom:16px;
|
||||||
|
padding:0 8px;
|
||||||
|
}
|
||||||
|
@media (max-width:62rem) {
|
||||||
|
.column {
|
||||||
|
width:45%;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width:30rem){
|
||||||
|
.column {
|
||||||
|
width:95%;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card{
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.card img {
|
||||||
|
padding-left:0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
.container::after, .row::after{
|
||||||
|
content:"";
|
||||||
|
clear:both;
|
||||||
|
display:table;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
color:grey;
|
||||||
|
}
|
||||||
|
.vitae {
|
||||||
|
margin-top:0.5em;
|
||||||
|
}
|
||||||
|
.email {
|
||||||
|
font-family:courier;
|
||||||
|
margin-top:0.5em;
|
||||||
|
margin-bottom:0.5em;
|
||||||
|
}
|
||||||
|
.button{
|
||||||
|
border:none;
|
||||||
|
outline:0;
|
||||||
|
display:inline-block;
|
||||||
|
padding:8px;
|
||||||
|
color:white;
|
||||||
|
background-color:#000;
|
||||||
|
text-align:center;
|
||||||
|
cursor:pointer;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.button:hover{
|
||||||
|
background-color:#555;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
~~~
|
||||||
|
""" |> println
|
|
@ -0,0 +1,4 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
x = 5
|
||||||
|
println("hello")
|
||||||
|
x^2
|
|
@ -0,0 +1 @@
|
||||||
|
hello
|
|
@ -0,0 +1 @@
|
||||||
|
25
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
After Width: | Height: | Size: 42 KiB |
|
@ -0,0 +1,8 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
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
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
x = randn(10)
|
|
@ -0,0 +1,4 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
x = rand(10)
|
||||||
|
println(sum(x))
|
||||||
|
y = 5
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
x = randn(10)
|
||||||
|
@show x[1]
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
x = exp(im*π) + 1
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
x ≈ 0
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
abs(x) < eps()
|
|
@ -0,0 +1,11 @@
|
||||||
|
10-element Array{Float64,1}:
|
||||||
|
-0.38675115697308454
|
||||||
|
1.6354610234843316
|
||||||
|
-1.2380735722784506
|
||||||
|
-0.07027813689054306
|
||||||
|
-1.5736602463947076
|
||||||
|
0.6028777803673767
|
||||||
|
0.907469270100251
|
||||||
|
-0.0015565188581515314
|
||||||
|
0.4464988414874392
|
||||||
|
0.24990993606446546
|
|
@ -0,0 +1 @@
|
||||||
|
5.418007222107764
|
|
@ -0,0 +1 @@
|
||||||
|
5
|
|
@ -0,0 +1 @@
|
||||||
|
x[1] = 0.33964471312600475
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
|
@ -0,0 +1 @@
|
||||||
|
0.0 + 1.2246467991473532e-16im
|
|
@ -0,0 +1 @@
|
||||||
|
false
|
|
@ -0,0 +1 @@
|
||||||
|
true
|
|
@ -0,0 +1,13 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
using PlotlyJS
|
||||||
|
z = [10 10.625 12.5 15.625 20
|
||||||
|
5.625 6.25 8.125 11.25 15.625
|
||||||
|
2.5 3.125 5. 8.125 12.5
|
||||||
|
0.625 1.25 3.125 6.25 10.625
|
||||||
|
0 0.625 2.5 5.625 10]
|
||||||
|
|
||||||
|
data = contour(; z=z)
|
||||||
|
layout = Layout(; title="Basic Contour Plot")
|
||||||
|
plt = plot(data, layout)
|
||||||
|
|
||||||
|
fdplotly(json(plt)) # hide
|
|
@ -0,0 +1,10 @@
|
||||||
|
~~~
|
||||||
|
<div id="fdpdhq" style="width:600px;height:350px"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var fig = {"layout":{"margin":{"l":50,"b":50,"r":50,"t":60},"title":"Basic Contour Plot"},"data":[{"type":"contour","z":[[10.0,5.625,2.5,0.625,0.0],[10.625,6.25,3.125,1.25,0.625],[12.5,8.125,5.0,3.125,2.5],[15.625,11.25,8.125,6.25,5.625],[20.0,15.625,12.5,10.625,10.0]]}]};
|
||||||
|
CONTAINER = document.getElementById('fdpdhq');
|
||||||
|
Plotly.newPlot(CONTAINER, fig.data, fig.layout)
|
||||||
|
</script>
|
||||||
|
~~~
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 5.3 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="32px" id="Layer_1" style="enable-background:new 0 0 32 32;" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z M28,14H4c-1.104,0-2,0.896-2,2 s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2 S29.104,22,28,22z"/></svg>
|
After Width: | Height: | Size: 605 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 23"><path d="M5.1 14.8c0-.4.2-.7.5-.9-.2-.1-.4-.2-.5-.2-.5 0-.9.3-1.3.8s-.5 1.1-.5 1.8c0 1.2.5 2.2 1.4 3 .9.8 2.2 1.2 3.6 1.2 3.3 0 5.2-1.5 5.6-4.5.2-1.3.2-3 .2-5.2V4.5c0-1.6-.6-2.4-1.7-2.4-.3 0-.5 0-.7.1-.4.1-.7.1-.9.1-.3 0-.5-.1-.7-.3-.2-.3-.3-.5-.3-.8 0-.8.5-1.2 1.5-1.2h.5l1.8.2c.7.1 1.3.1 2.1.1.7 0 1.4-.1 2.2-.2l1.4-.1h.5c1 0 1.5.4 1.5 1.2 0 .7-.4 1.1-1.1 1.1-.2 0-.5 0-.9-.1-.2 0-.4-.1-.7-.1-1.1 0-1.7.8-1.7 2.4v6.3c0 3.3-.1 5.5-.4 6.6-.2 1-.7 1.9-1.5 2.7-1.6 1.8-3.8 2.7-6.5 2.7-2.3 0-4.2-.6-5.6-1.8C1.5 19.8.7 18.2.7 16.4c0-1.4.4-2.6 1.3-3.6s2-1.4 3.3-1.4c.9 0 1.7.2 2.3.7.6.5.9 1.1.9 1.9 0 .6-.2 1-.5 1.4-.4.4-.8.6-1.3.6-.4 0-.8-.1-1.1-.4-.3-.1-.5-.4-.5-.8zM35.3 21.4v-1c-1.2 1.6-2.9 2.4-5.2 2.4-2.6 0-4.4-.8-5.4-2.4-.4-.7-.7-1.5-.7-2.5v-5.6c0-3-.3-4.5-1-4.5H21.7c-.8 0-1.2-.4-1.2-1.1 0-.7.5-1 1.4-1 .2 0 .5 0 1 .1.4.1.8.1 1 .1.2 0 .5 0 1-.1.3 0 .5-.1.6-.1.7 0 1 .4 1 1.3v2.8l-.1 2.4v2.1c0 1.9.2 3.3.5 4.1.5 1.4 1.7 2.1 3.6 2.1.9 0 1.8-.2 2.5-.6.7-.4 1.2-1 1.5-1.7.4-.9.5-2.5.5-4.9v-1.8-2.1c-.1-1.1-.4-1.6-.9-1.6h-1c-.8 0-1.2-.3-1.2-1s.4-1.1 1.3-1.1c.2 0 .5 0 .9.1.4 0 .7.1.9.1.2 0 .4 0 .8-.1.4 0 .6-.1.8-.1.7 0 1 .4 1 1.1 0 .3 0 .6-.1.7-.1.8-.2 2.1-.2 3.7V18.6c.1 1.2.4 1.8.9 1.8.2 0 .4 0 .7-.1.3-.1.5-.1.7-.1.7 0 1.1.4 1.1 1.1 0 .8-.5 1.1-1.4 1.1-.2 0-.5 0-.9-.1-.6-.1-.9-.1-1-.1-.1 0-.3 0-.7.1-.3.1-.5.1-.7.1-.4-.1-.7-.4-.7-1zM45.9 4.5c0-1.7-.6-2.5-1.7-2.5-.2 0-.4 0-.7.1-.4.1-.7.1-.9.1-.7 0-1-.4-1-1.1 0-.8.5-1.2 1.5-1.2h.4l1.8.2c.7.1 1.4.1 2.1.1.6 0 1.2 0 1.9-.1l2.1-.2c.4.1 1 .1 1.6.1 2 0 3.7.3 5 .9 1.8.8 3.2 2.1 4.2 3.9 1 1.9 1.5 4 1.5 6.4 0 2.2-.4 4.1-1.2 5.8-.8 1.7-1.9 3-3.3 3.8-1.7 1-3.7 1.5-6.2 1.5-.5 0-1 0-1.5-.1l-2.3-.2h-2.3c-.7 0-1.3 0-1.8.1l-1.6.2H43c-.9 0-1.4-.4-1.4-1.2 0-.3.1-.6.3-.8.2-.2.4-.3.7-.3.2 0 .5 0 .9.1.2 0 .4.1.7.1 1.1 0 1.7-.8 1.7-2.5V4.5zm2.8-.3v13.9c0 1 .5 1.6 1.5 1.8.3.1 1.3.1 2.8.1 2.6 0 4.6-.7 5.8-2.1 1.4-1.7 2.1-4 2.1-6.8 0-2.2-.4-4.1-1.3-5.6S57.5 3.1 56 2.7c-1-.3-2.1-.4-3.5-.4-1.7 0-2.8.1-3.2.3-.4.1-.6.7-.6 1.6zM73.9 22.8c-2.3 0-4.2-.8-5.6-2.4s-2.1-3.7-2.1-6.4.7-4.8 2.1-6.4c1.4-1.6 3.3-2.4 5.6-2.4 2.4 0 4.3.8 5.7 2.3 1.4 1.6 2.1 3.7 2.1 6.4s-.7 4.8-2.1 6.5c-1.4 1.6-3.3 2.4-5.7 2.4zm.2-15.5c-1.5 0-2.8.5-3.6 1.6-.9 1.1-1.4 2.6-1.5 4.6v.4c0 2.1.4 3.7 1.3 4.9s2.1 1.8 3.7 1.8 2.9-.6 3.8-1.8 1.4-2.8 1.4-4.9c-.1-4.4-1.8-6.6-5.1-6.6zM94 11.3c0-.9.6-1.4 1.7-1.5-.2-.8-.5-1.4-1.2-1.8-.6-.4-1.4-.7-2.4-.7-1.5 0-2.7.6-3.7 1.8S87 11.9 87 13.9c0 2.1.4 3.7 1.3 4.9s2.1 1.8 3.6 1.8c1 0 1.8-.3 2.5-.8.7-.6 1.2-1.3 1.5-2.3.2-.8.4-1.2.4-1.3.2-.4.6-.7 1.1-.7.4 0 .7.1.9.4.2.2.4.6.4.9 0 .6-.2 1.2-.5 2-.4.8-.8 1.4-1.3 1.9-1.3 1.4-3 2.1-5.1 2.1-2.2 0-4.1-.8-5.4-2.4-1.4-1.6-2.1-3.7-2.1-6.2 0-2.7.7-4.9 2.1-6.6 1.4-1.6 3.3-2.5 5.7-2.5 1.8 0 3.2.5 4.4 1.4s1.8 2.2 1.8 3.7c0 .8-.2 1.5-.7 2-.5.5-1 .8-1.7.8-.6 0-1-.2-1.4-.5-.3-.3-.5-.7-.5-1.2z"/></svg>
|
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 893 B |
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 50"><path d="M9.4 36.7V26.2c0-2.1-.7-3.2-2.2-3.2-.4 0-.7 0-.9.1-.5.1-.8.2-1.1.2-.4 0-.7-.1-.9-.4-.3-.3-.4-.6-.4-1 0-1 .6-1.6 1.8-1.6h.6l3 .3c1.1.1 2.4.2 3.8.2.7 0 2.4 0 4.8-.1l5-.2c.7 0 1.4-.1 2.3-.1.4-.1.8-.1 1.3-.1 1.5 0 2.3.7 2.3 2 0 .5-.1 1.3-.2 2.4-.1 1.1-.2 1.9-.2 2.4s0 1 .1 1.7.1 1.3.1 1.9c0 1.2-.5 1.8-1.6 1.8s-1.6-.7-1.6-2c0-.4 0-1 .1-1.8s.1-1.4.1-1.8c0-1.5-.4-2.5-1.3-2.9-.9-.4-2.9-.6-6.1-.6-2.7 0-4.3.2-4.7.7-.3.4-.4 1.7-.4 4v3.2c0 .8.1 1.3.3 1.5.2.2.8.3 1.8.3h1.4c1.9 0 2.8-.7 2.8-2.1 0-.3 0-.7-.1-1.3-.1-.5-.1-1-.1-1.3 0-1.1.5-1.6 1.6-1.6 1 0 1.5.6 1.5 1.9 0 .2 0 .5-.1 1l-.4 2.3c-.1 1-.2 1.8-.2 2.3 0 1.2.2 2.7.5 4.5.1.6.2 1.2.2 1.7 0 1.1-.5 1.7-1.6 1.7-1 0-1.5-.6-1.5-1.8 0-.3 0-.7.1-1.3 0-.6.1-1 .1-1.3 0-.9-.2-1.5-.7-1.7-.3-.2-1-.3-2-.3h-1.3c-1 0-1.6.1-1.9.3-.4.3-.5.9-.5 2v5.1c0 1.3.2 2.2.5 2.7s.9.7 1.7.7H17c1.3 0 2 .5 2 1.5 0 .4-.2.7-.5 1-.3.3-.7.4-1.1.4-.5 0-1.1-.1-2-.2-1.3-.2-2.7-.3-4.3-.3-1 0-2.1.1-3.3.3l-1.5.2h-.6c-1.3 0-1.9-.5-1.9-1.6 0-.9.4-1.4 1.3-1.4.1 0 .5 0 1.1.1.3.1.6.1.9.1.8 0 1.3-.2 1.6-.7s.5-1.3.5-2.5v-6.8z" fill="#3e4fa2"/><path d="M15.1 2.8c-2.3 1.6-3 1.8-5.2 1.5-3.6-.5-4.9-.1-5.4 1.6-.3 1-.4 3.1-.3 6 0 1.6 0 2.5-.1 2.8-.1.2-.8.9-1.7 1.6-.8.6-1.7 1.3-1.8 1.5-.3.4-.3 1 .1 1 .1 0 7.1-1.3 15.4-2.9 16.5-3.2 15.8-3 15.6-3.8-.1-.4-.9-.9-1.6-.9-.3 0-1 0-1.5-.1-1.8-.1-2.7-.8-3.5-2.5-1.5-3.5-3.1-6.5-4-7.5-.3-.3-.7-.6-1-.7-1-.1-2.1.4-5 2.4z" fill="#020202"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 50"><path d="M15.1 2.8c-2.3 1.6-3 1.8-5.2 1.5-3.6-.5-4.9-.1-5.4 1.6-.3 1-.4 3.1-.3 6 0 1.6 0 2.5-.1 2.8-.1.2-.8.9-1.7 1.6-.8.6-1.7 1.3-1.8 1.5-.3.4-.3 1 .1 1 .1 0 7.1-1.3 15.4-2.9 16.5-3.2 15.8-3 15.6-3.8-.1-.4-.9-.9-1.6-.9-.3 0-1 0-1.5-.1-1.8-.1-2.7-.8-3.5-2.5-1.5-3.5-3.1-6.5-4-7.5-.3-.3-.7-.6-1-.7-1-.1-2.1.4-5 2.4z" fill="#030303"/><path d="M9.3 36.6V26.2c0-2.1-.7-3.2-2.2-3.2-.4 0-.7 0-.8.1-.5.1-.8.2-1.1.2-.4 0-.7-.1-.9-.4-.3-.3-.4-.6-.4-1 0-1 .6-1.5 1.8-1.5h.6l3 .3c1.1.1 2.4.2 3.7.2.7 0 2.3 0 4.8-.1l4.9-.2c.7 0 1.4-.1 2.3-.1.4-.1.8-.1 1.3-.1 1.5 0 2.3.7 2.3 2 0 .5-.1 1.3-.2 2.4-.1 1.1-.2 1.9-.2 2.4s0 1 .1 1.7.1 1.3.1 1.9c0 1.2-.5 1.8-1.5 1.8-1.1 0-1.6-.7-1.6-2 0-.4 0-1 .1-1.8s.1-1.4.1-1.8c0-1.5-.4-2.5-1.3-2.9-.9-.4-2.9-.6-6.1-.6-2.7 0-4.3.2-4.6.7-.3.4-.4 1.7-.4 3.9v3.2c0 .8.1 1.3.3 1.5s.8.3 1.8.3h1.4c1.9 0 2.8-.7 2.8-2.1 0-.3 0-.7-.1-1.3-.3-.7-.3-1.1-.3-1.4 0-1.1.5-1.6 1.5-1.6s1.5.6 1.5 1.9c0 .2 0 .5-.1 1l-.3 2.3c-.1 1-.2 1.8-.2 2.3 0 1.2.2 2.7.4 4.5.1.6.2 1.2.2 1.7 0 1.1-.5 1.7-1.5 1.7s-1.5-.6-1.5-1.8c0-.3 0-.7.1-1.3 0-.6.1-1 .1-1.3 0-.9-.2-1.5-.7-1.7-.3-.2-1-.3-2-.3h-1.3c-1 0-1.6.1-1.8.3-.2.2-.3.8-.3 1.9V43c0 1.3.1 2.2.4 2.7.3.5.9.7 1.7.7H17c1.3 0 2 .5 2 1.5 0 .4-.1.7-.4 1-.3.3-.7.4-1.1.4-.5 0-1.1-.1-2-.2-1.3-.2-2.7-.3-4.3-.3-1 0-2.1.1-3.3.3l-1.5.2h-.6c-1.3 0-1.9-.5-1.9-1.5 0-.9.4-1.4 1.3-1.4.1 0 .5 0 1.1.1.3.1.6.1.9.1.8 0 1.3-.2 1.6-.7.3-.5.5-1.3.5-2.5v-6.8z" fill="#3f50a2"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,37 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#3F50A2;}
|
||||||
|
.st1{fill:#030303;}
|
||||||
|
</style>
|
||||||
|
<path class="st0" d="M18.4,36.7V26.2c0-2.1-0.7-3.2-2.2-3.2c-0.4,0-0.7,0-0.9,0.1c-0.5,0.1-0.8,0.2-1.1,0.2c-0.4,0-0.7-0.1-0.9-0.4
|
||||||
|
c-0.3-0.3-0.4-0.6-0.4-1c0-1,0.6-1.6,1.8-1.6h0.6l3,0.3c1.1,0.1,2.4,0.2,3.8,0.2c0.7,0,2.4,0,4.8-0.1l5-0.2c0.7,0,1.4-0.1,2.3-0.1
|
||||||
|
c0.4-0.1,0.8-0.1,1.3-0.1c1.5,0,2.3,0.7,2.3,2c0,0.5-0.1,1.3-0.2,2.4c-0.1,1.1-0.2,1.9-0.2,2.4s0,1,0.1,1.7s0.1,1.3,0.1,1.9
|
||||||
|
c0,1.2-0.5,1.8-1.6,1.8s-1.6-0.7-1.6-2c0-0.4,0-1,0.1-1.8s0.1-1.4,0.1-1.8c0-1.5-0.4-2.5-1.3-2.9c-0.9-0.4-2.9-0.6-6.1-0.6
|
||||||
|
c-2.7,0-4.3,0.2-4.7,0.7c-0.3,0.4-0.4,1.7-0.4,4v3.2c0,0.8,0.1,1.3,0.3,1.5s0.8,0.3,1.8,0.3h1.4c1.9,0,2.8-0.7,2.8-2.1
|
||||||
|
c0-0.3,0-0.7-0.1-1.3c-0.1-0.5-0.1-1-0.1-1.3c0-1.1,0.5-1.6,1.6-1.6c1,0,1.5,0.6,1.5,1.9c0,0.2,0,0.5-0.1,1L30.8,32
|
||||||
|
c-0.1,1-0.2,1.8-0.2,2.3c0,1.2,0.2,2.7,0.5,4.5c0.1,0.6,0.2,1.2,0.2,1.7c0,1.1-0.5,1.7-1.6,1.7c-1,0-1.5-0.6-1.5-1.8
|
||||||
|
c0-0.3,0-0.7,0.1-1.3c0-0.6,0.1-1,0.1-1.3c0-0.9-0.2-1.5-0.7-1.7c-0.3-0.2-1-0.3-2-0.3h-1.3c-1,0-1.6,0.1-1.9,0.3
|
||||||
|
c-0.4,0.3-0.5,0.9-0.5,2v5.1c0,1.3,0.2,2.2,0.5,2.7c0.3,0.5,0.9,0.7,1.7,0.7H26c1.3,0,2,0.5,2,1.5c0,0.4-0.2,0.7-0.5,1
|
||||||
|
s-0.7,0.4-1.1,0.4c-0.5,0-1.1-0.1-2-0.2c-1.3-0.2-2.7-0.3-4.3-0.3c-1,0-2.1,0.1-3.3,0.3l-1.5,0.2h-0.6c-1.3,0-1.9-0.5-1.9-1.6
|
||||||
|
c0-0.9,0.4-1.4,1.3-1.4c0.1,0,0.5,0,1.1,0.1c0.3,0.1,0.6,0.1,0.9,0.1c0.8,0,1.3-0.2,1.6-0.7c0.3-0.5,0.5-1.3,0.5-2.5v-6.8L18.4,36.7
|
||||||
|
z"/>
|
||||||
|
<path class="st1" d="M24.1,2.8c-2.3,1.6-3,1.8-5.2,1.5c-3.6-0.5-4.9-0.1-5.4,1.6c-0.3,1-0.4,3.1-0.3,6c0,1.6,0,2.5-0.1,2.8
|
||||||
|
c-0.1,0.2-0.8,0.9-1.7,1.6c-0.8,0.6-1.7,1.3-1.8,1.5c-0.3,0.4-0.3,1,0.1,1c0.1,0,7.1-1.3,15.4-2.9c16.5-3.2,15.8-3,15.6-3.8
|
||||||
|
c-0.1-0.4-0.9-0.9-1.6-0.9c-0.3,0-1,0-1.5-0.1c-1.8-0.1-2.7-0.8-3.5-2.5c-1.5-3.5-3.1-6.5-4-7.5c-0.3-0.3-0.7-0.6-1-0.7
|
||||||
|
C28.1,0.3,27,0.8,24.1,2.8z"/>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><path d="M23.1 2.8c-2.3 1.6-3 1.8-5.2 1.5-3.6-.5-4.9-.1-5.4 1.6-.3 1-.4 3.1-.3 6 0 1.6 0 2.5-.1 2.8-.1.2-.8.9-1.7 1.6-.8.6-1.7 1.3-1.8 1.5-.3.4-.3 1 .1 1 .1 0 7.1-1.3 15.4-2.9 16.5-3.2 15.8-3 15.6-3.8-.1-.4-.9-.9-1.6-.9-.3 0-1 0-1.5-.1-1.8-.1-2.7-.8-3.5-2.5-1.5-3.5-3.1-6.5-4-7.5-.3-.3-.7-.6-1-.7-1-.1-2.1.4-5 2.4z" fill="#030303"/><path d="M17.3 36.6V26.2c0-2.1-.7-3.2-2.2-3.2-.4 0-.7 0-.8.1-.5.1-.8.2-1.1.2-.4 0-.7-.1-.9-.4-.3-.3-.4-.6-.4-1 0-1 .6-1.5 1.8-1.5h.6l3 .3c1.1.1 2.4.2 3.7.2.7 0 2.3 0 4.8-.1l4.9-.2c.7 0 1.4-.1 2.3-.1.4-.1.8-.1 1.3-.1 1.5 0 2.3.7 2.3 2 0 .5-.1 1.3-.2 2.4-.1 1.1-.2 1.9-.2 2.4s0 1 .1 1.7.1 1.3.1 1.9c0 1.2-.5 1.8-1.5 1.8-1.1 0-1.6-.7-1.6-2 0-.4 0-1 .1-1.8s.1-1.4.1-1.8c0-1.5-.4-2.5-1.3-2.9-.9-.4-2.9-.6-6.1-.6-2.7 0-4.3.2-4.6.7-.3.4-.4 1.7-.4 3.9v3.2c0 .8.1 1.3.3 1.5s.8.3 1.8.3h1.4c1.9 0 2.8-.7 2.8-2.1 0-.3 0-.7-.1-1.3-.3-.7-.3-1.1-.3-1.4 0-1.1.5-1.6 1.5-1.6s1.5.6 1.5 1.9c0 .2 0 .5-.1 1l-.3 2.3c-.1 1-.2 1.8-.2 2.3 0 1.2.2 2.7.4 4.5.1.6.2 1.2.2 1.7 0 1.1-.5 1.7-1.5 1.7s-1.5-.6-1.5-1.8c0-.3 0-.7.1-1.3 0-.6.1-1 .1-1.3 0-.9-.2-1.5-.7-1.7-.3-.2-1-.3-2-.3h-1.3c-1 0-1.6.1-1.8.3-.2.2-.3.8-.3 1.9V43c0 1.3.1 2.2.4 2.7.3.5.9.7 1.7.7H25c1.3 0 2 .5 2 1.5 0 .4-.1.7-.4 1-.3.3-.7.4-1.1.4-.5 0-1.1-.1-2-.2-1.3-.2-2.7-.3-4.3-.3-1 0-2.1.1-3.3.3l-1.5.2h-.6c-1.3 0-1.9-.5-1.9-1.5 0-.9.4-1.4 1.3-1.4.1 0 .5 0 1.1.1.3.1.6.1.9.1.8 0 1.3-.2 1.6-.7.3-.5.5-1.3.5-2.5v-6.8z" fill="#3f50a2"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 69 KiB |
|
@ -0,0 +1,27 @@
|
||||||
|
<!--This file was generated, do not modify it.-->
|
||||||
|
Some **really cool** maths:
|
||||||
|
|
||||||
|
$$ \exp(i\pi) + 1 \quad = \quad 0 $$
|
||||||
|
|
||||||
|
We can show this with some code:
|
||||||
|
|
||||||
|
```julia:ex1
|
||||||
|
x = exp(im*π) + 1
|
||||||
|
```
|
||||||
|
|
||||||
|
that looks close to zero but
|
||||||
|
|
||||||
|
```julia:ex2
|
||||||
|
x ≈ 0
|
||||||
|
```
|
||||||
|
|
||||||
|
however
|
||||||
|
|
||||||
|
```julia:ex3
|
||||||
|
abs(x) < eps()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Conclusion
|
||||||
|
|
||||||
|
The equation is proven thanks to our very rigorous proof.
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# This file was generated, do not modify it.
|
||||||
|
|
||||||
|
x = exp(im*π) + 1
|
||||||
|
|
||||||
|
x ≈ 0
|
||||||
|
|
||||||
|
abs(x) < eps()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
3.173
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
using LinearAlgebra, Random
|
||||||
|
Random.seed!(555)
|
||||||
|
a = randn(5)
|
||||||
|
round(norm(a), sigdigits=4)
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This file was generated, do not modify it. # hide
|
||||||
|
using PyPlot
|
||||||
|
figure()
|
||||||
|
plot([0, 1], [0, 1])
|
||||||
|
savefig(joinpath(@OUTPUT, "test.png"))
|
|
@ -0,0 +1 @@
|
||||||
|
nothing
|
After Width: | Height: | Size: 17 KiB |
|
@ -0,0 +1,747 @@
|
||||||
|
html{
|
||||||
|
font-family:sans-serif;
|
||||||
|
-ms-text-size-adjust:100%;
|
||||||
|
-webkit-text-size-adjust:100%;
|
||||||
|
font-size:15px !important;
|
||||||
|
}
|
||||||
|
@media (min-width: 31.25rem){
|
||||||
|
html{
|
||||||
|
font-size:17px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
margin:0;
|
||||||
|
position:relative;
|
||||||
|
padding-bottom:4rem;
|
||||||
|
font-family:-apple-system,"helvetica neue",helvetica,roboto,noto,"segoe ui",arial,sans-serif;
|
||||||
|
font-size:inherit;
|
||||||
|
line-height:1.5;
|
||||||
|
color:#5c5962;
|
||||||
|
background-color:#fff;
|
||||||
|
}
|
||||||
|
@media (min-width: 50rem){
|
||||||
|
body{
|
||||||
|
position:static;
|
||||||
|
padding-bottom:0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h1{
|
||||||
|
font-size:2em;
|
||||||
|
margin:0.67em 0
|
||||||
|
}
|
||||||
|
sub,sup{
|
||||||
|
font-size:75%;
|
||||||
|
line-height:0;
|
||||||
|
position:relative;
|
||||||
|
vertical-align:baseline
|
||||||
|
}
|
||||||
|
sup{
|
||||||
|
top:-0.5em
|
||||||
|
}
|
||||||
|
sub{
|
||||||
|
bottom:-0.25em
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
border:0
|
||||||
|
}
|
||||||
|
p,h1,h2,h3,h4,h5,h6,ol,ul,pre,address,blockquote,dl,div,fieldset,form,hr,noscript,table{
|
||||||
|
margin-top:0
|
||||||
|
}
|
||||||
|
h1,h2,h3,h4,h5,h6{
|
||||||
|
margin-top:1.2em;
|
||||||
|
margin-bottom:0.8em;
|
||||||
|
font-weight:500;
|
||||||
|
line-height:1.15;
|
||||||
|
color:#27262b;
|
||||||
|
}
|
||||||
|
p{
|
||||||
|
margin-bottom:1em
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
color:#0E39B0;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
pre{
|
||||||
|
overflow:auto;
|
||||||
|
margin:0;
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
}
|
||||||
|
code{
|
||||||
|
font-family:"SFMono-Regular",Menlo,Consolas,Monospace;
|
||||||
|
font-size:12px;
|
||||||
|
line-height:1.4;
|
||||||
|
padding:0.2em 0.15em;
|
||||||
|
font-weight:400;
|
||||||
|
background-color:#f5f6fa;
|
||||||
|
border:1px solid #eeebee;
|
||||||
|
border-radius:4px;
|
||||||
|
}
|
||||||
|
li:not(:last-child) {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
max-width:100%;
|
||||||
|
height:auto
|
||||||
|
}
|
||||||
|
hr{
|
||||||
|
height:1px;
|
||||||
|
padding:0;
|
||||||
|
margin:2rem 0;
|
||||||
|
background-color:#eeebee;
|
||||||
|
border:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (min-width: 50rem){
|
||||||
|
.page-wrap{
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
SIDE BAR
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
|
.side-bar{
|
||||||
|
z-index: 100;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
background-color:#f5f6fa;
|
||||||
|
}
|
||||||
|
.side-bar .header {
|
||||||
|
display: flex;
|
||||||
|
min-height: 60px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.side-bar .header .title{
|
||||||
|
padding-right:1rem;
|
||||||
|
padding-left:1rem;
|
||||||
|
flex-grow:1;
|
||||||
|
display:flex;
|
||||||
|
height:100%;
|
||||||
|
align-items:center;
|
||||||
|
padding-top:.75rem;
|
||||||
|
padding-bottom:.75rem;
|
||||||
|
color:#27262b;
|
||||||
|
font-size:18px !important;
|
||||||
|
line-height: 1.15em;
|
||||||
|
}
|
||||||
|
.show-menu {
|
||||||
|
cursor: pointer;
|
||||||
|
appearance:none;
|
||||||
|
display:flex;
|
||||||
|
height:100%;
|
||||||
|
/* line-height: 60px; */
|
||||||
|
padding:1rem;
|
||||||
|
align-items:center;
|
||||||
|
color:#0E39B0;
|
||||||
|
text-transform:uppercase;
|
||||||
|
background:transparent;
|
||||||
|
text-align:right;
|
||||||
|
padding-right: 2rem;
|
||||||
|
border:0;
|
||||||
|
width: calc(100% - 220px);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
.side-bar .menu {
|
||||||
|
width: 100%;
|
||||||
|
padding-right:1rem;
|
||||||
|
padding-left:1rem
|
||||||
|
}
|
||||||
|
.menu-list{
|
||||||
|
padding:0;
|
||||||
|
margin-top:0;
|
||||||
|
margin-bottom:0;
|
||||||
|
list-style:none
|
||||||
|
}
|
||||||
|
.menu-list-child-list{
|
||||||
|
padding-left:.75rem;
|
||||||
|
line-height: 0.9em;
|
||||||
|
list-style:none;
|
||||||
|
}
|
||||||
|
.menu-list-child-list .menu-list-link{
|
||||||
|
color:#5c5962
|
||||||
|
}
|
||||||
|
.menu-list-child-list .menu-list-item{
|
||||||
|
position:relative
|
||||||
|
}
|
||||||
|
.menu-list-child-list .menu-list-item::before{
|
||||||
|
position:absolute;
|
||||||
|
margin-top:0.3em;
|
||||||
|
margin-left:-0.8em;
|
||||||
|
color:rgba(92,89,98,0.3);
|
||||||
|
content:"- "
|
||||||
|
}
|
||||||
|
.menu-list-child-list .menu-list-item.active::before{
|
||||||
|
color:#5c5962
|
||||||
|
}
|
||||||
|
.menu-list-item{
|
||||||
|
font-size:14px !important;
|
||||||
|
margin:0
|
||||||
|
}
|
||||||
|
.menu-list-parent .menu-list-child-list{
|
||||||
|
display:none
|
||||||
|
}
|
||||||
|
.menu-list-parent.active .menu-list-child-list{
|
||||||
|
display:block
|
||||||
|
}
|
||||||
|
.menu-list-item.active a {
|
||||||
|
font-weight:600;
|
||||||
|
color:#27262b;
|
||||||
|
text-decoration:none
|
||||||
|
}
|
||||||
|
.menu-list-child-list{
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
ul.menu-list-child-list li {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-list-link{
|
||||||
|
display:block;
|
||||||
|
padding-top:.25rem;
|
||||||
|
padding-bottom:.25rem
|
||||||
|
}
|
||||||
|
/* .menu-list-link.active{
|
||||||
|
font-weight:600;
|
||||||
|
color:#27262b;
|
||||||
|
text-decoration:none
|
||||||
|
} */
|
||||||
|
|
||||||
|
.side-bar .footer {
|
||||||
|
width: 150px;
|
||||||
|
font-size: 13px;
|
||||||
|
padding-right:1rem;
|
||||||
|
padding-left:1rem;
|
||||||
|
position:absolute;
|
||||||
|
bottom:0;
|
||||||
|
left:0;
|
||||||
|
padding-top:1rem;
|
||||||
|
padding-bottom:1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Hide checkbox*/
|
||||||
|
input[type=checkbox]{display: none;}
|
||||||
|
/*Show menu when invisible checkbox is checked*/
|
||||||
|
input[type=checkbox]:checked ~ #side-menu{display: block;}
|
||||||
|
|
||||||
|
/* side bar adjustments for narrow mode (bar on top) */
|
||||||
|
@media (max-width : 49.99rem){
|
||||||
|
/* Toggle menu off */
|
||||||
|
.side-bar .menu {
|
||||||
|
display: none;
|
||||||
|
padding-left:35px;
|
||||||
|
padding-bottom:15px;}
|
||||||
|
.side-bar {
|
||||||
|
border-bottom: 1px solid #eeebee;
|
||||||
|
}
|
||||||
|
.side-bar .header {
|
||||||
|
padding-left: 15px;
|
||||||
|
width: 150px;} /* middle space */
|
||||||
|
.show-menu {display: block;}
|
||||||
|
.side-bar .footer {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* side bar adjustments for narrow mode (bar on top) */
|
||||||
|
@media (min-width: 31.25rem){
|
||||||
|
.side-bar .header .title{
|
||||||
|
font-size:24px !important
|
||||||
|
}
|
||||||
|
.menu-list-item{
|
||||||
|
font-size:16px !important
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* side bar adjustments for medium mode (bar on side) */
|
||||||
|
@media (min-width: 50rem){
|
||||||
|
.side-bar{
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
position: absolute;
|
||||||
|
width: 248px;
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
.side-bar .header{
|
||||||
|
z-index: 101;
|
||||||
|
height: 60px;
|
||||||
|
max-height: 60px;
|
||||||
|
border-bottom: 1px solid #eeebee;
|
||||||
|
padding-right:3.5rem;
|
||||||
|
padding-left:2rem;
|
||||||
|
}
|
||||||
|
.side-bar .header .title{
|
||||||
|
font-size: 35px !important;
|
||||||
|
padding-top:.5rem;
|
||||||
|
padding-bottom:.5rem
|
||||||
|
}
|
||||||
|
.show-menu {
|
||||||
|
display:none
|
||||||
|
}
|
||||||
|
.side-bar .menu{
|
||||||
|
width: 160px;
|
||||||
|
padding-right:2.5rem;
|
||||||
|
/* padding-left:0rem; */
|
||||||
|
padding-top:3rem;
|
||||||
|
padding-bottom:1rem;
|
||||||
|
overflow-y:auto;
|
||||||
|
flex:1 1 auto
|
||||||
|
}
|
||||||
|
.side-bar .footer{
|
||||||
|
padding-right:2rem;
|
||||||
|
padding-left:2rem;
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* side bar adjustments for wide mode (bar on side) */
|
||||||
|
@media (min-width: 66.5rem){
|
||||||
|
.side-bar{
|
||||||
|
width:calc((100% - 66.5rem) / 2 + 264px);
|
||||||
|
min-width:264px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
MAIN CONTENT
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
|
@media (min-width: 50rem){
|
||||||
|
.main-content-wrap{
|
||||||
|
position:absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll
|
||||||
|
}
|
||||||
|
.main-content{
|
||||||
|
position:relative;
|
||||||
|
max-width: 800px;
|
||||||
|
margin-left: 248px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 66.5rem){
|
||||||
|
.main-content {
|
||||||
|
margin-left:calc((100% - 1064px) / 2 + 264px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-header{
|
||||||
|
padding-right:1rem;
|
||||||
|
padding-left:1rem;
|
||||||
|
display:none;
|
||||||
|
/* padding-top:1rem; */
|
||||||
|
/* padding-bottom:1rem; */
|
||||||
|
background-color:#f5f6fa;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
}
|
||||||
|
@media (min-width: 50rem){
|
||||||
|
.main-header{
|
||||||
|
padding-right:2rem;
|
||||||
|
padding-left:2rem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 50rem){
|
||||||
|
.main-header{
|
||||||
|
display:flex;
|
||||||
|
justify-content:flex-end;
|
||||||
|
height: -1em;
|
||||||
|
background-color:#fff;
|
||||||
|
border-bottom:1px solid #eeebee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.main-footer{
|
||||||
|
font-size: 14px;
|
||||||
|
color: darkgray;
|
||||||
|
border-top: 1px solid #eeebee;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.franklin-content {
|
||||||
|
padding-right:1rem;
|
||||||
|
padding-left:1rem;
|
||||||
|
padding-top:1rem;
|
||||||
|
padding-bottom:1rem;
|
||||||
|
|
||||||
|
line-height:1.5
|
||||||
|
}
|
||||||
|
@media (min-width: 50rem){
|
||||||
|
.franklin-content {
|
||||||
|
padding-right:2rem;
|
||||||
|
padding-left:2rem;
|
||||||
|
padding-top:2rem;
|
||||||
|
padding-bottom:2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
JUDOC SPECIFICS
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
|
.franklin-content a{
|
||||||
|
overflow:hidden;
|
||||||
|
text-overflow:ellipsis;
|
||||||
|
white-space:nowrap
|
||||||
|
}
|
||||||
|
|
||||||
|
.franklin-content ul,ol{
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
.franklin-content li{
|
||||||
|
margin-top: 0.3em;
|
||||||
|
line-height: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.franklin-content ul,.franklin-content ol{
|
||||||
|
padding-left:1.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
.franklin-content h1:first-of-type{
|
||||||
|
margin-top:0.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
.franklin-content h1,h2,h3,h4,h5,h6{
|
||||||
|
position:relative
|
||||||
|
}
|
||||||
|
|
||||||
|
td.fndef-backref {
|
||||||
|
min-width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.franklin-content table {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
border-collapse: collapse;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 1em;}
|
||||||
|
.franklin-content tr,th,td{
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid black;}
|
||||||
|
|
||||||
|
.franklin-content table tbody tr td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.franklin-content blockquote {
|
||||||
|
background: lemonchiffon;
|
||||||
|
border-left: 7px solid #a8a8a8;
|
||||||
|
margin: 1.5em 10px;
|
||||||
|
padding: 0.5em 10px;
|
||||||
|
font-style: italic;}
|
||||||
|
|
||||||
|
.franklin-content blockquote p {
|
||||||
|
display: inline; }
|
||||||
|
|
||||||
|
.franklin-content .row {
|
||||||
|
display: block; }
|
||||||
|
|
||||||
|
.franklin-content .left {
|
||||||
|
float: left;
|
||||||
|
margin-right: 15px; }
|
||||||
|
|
||||||
|
.franklin-content .right {
|
||||||
|
float: right; }
|
||||||
|
|
||||||
|
.franklin-content .container img {
|
||||||
|
width: auto;
|
||||||
|
padding-left: 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 1em;}
|
||||||
|
|
||||||
|
|
||||||
|
.franklin-content .fndef table {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
.franklin-content .fndef tr {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.franklin-content .fndef td {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
.franklin-content .fndef td.fndef-backref {
|
||||||
|
vertical-align: top;
|
||||||
|
font-size: 80%;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
.franklin-content .fndef td.fndef-content {
|
||||||
|
font-size: 90%;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
.franklin-content .fndef tr {
|
||||||
|
border-left: 2px solid lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.franklin-content img {
|
||||||
|
width: 70%;
|
||||||
|
text-align: center;
|
||||||
|
padding-left: 10%; }
|
||||||
|
|
||||||
|
.franklin-content .img-small img {
|
||||||
|
width: 50%;
|
||||||
|
text-align: center;
|
||||||
|
padding-left: 20%; }
|
||||||
|
|
||||||
|
|
||||||
|
/* ==================================================================
|
||||||
|
KATEX
|
||||||
|
================================================================== */
|
||||||
|
|
||||||
|
body { counter-reset: eqnum; }
|
||||||
|
|
||||||
|
.katex { font-size: 1em !important; }
|
||||||
|
|
||||||
|
.katex-display .katex {
|
||||||
|
display: inline-block; } /* overwrite katex settings */
|
||||||
|
|
||||||
|
.katex-display::after {
|
||||||
|
counter-increment: eqnum;
|
||||||
|
content: "(" counter(eqnum) ")";
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
padding-right: 5px; }
|
||||||
|
|
||||||
|
/* ==================================================================
|
||||||
|
CODE & HIGHLIGHT.JS
|
||||||
|
================================================================== */
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
font-size: 80%;
|
||||||
|
line-height: 1.35em;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 1em;
|
||||||
|
padding-left:1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-meta, .hljs-metas, .hljs-metap { font-weight: bold; }
|
||||||
|
|
||||||
|
.hljs-meta { color: rgb(25, 179, 51); }
|
||||||
|
|
||||||
|
.hljs-metas { color: red; }
|
||||||
|
|
||||||
|
.hljs-metap { color: rgb(51, 131, 231); }
|
||||||
|
|
||||||
|
.hljs-string {color: #ca4418;}
|
||||||
|
.hljs-subst { color: inherit;}
|
||||||
|
|
||||||
|
.page-foot {
|
||||||
|
margin-top: 2em;
|
||||||
|
border-top: 1px solid #eeebee;
|
||||||
|
padding-top:20px;
|
||||||
|
padding-bottom:15px;
|
||||||
|
color: gray;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* code.language-plaintext {color: purple;} */
|
||||||
|
|
||||||
|
.franklin-toc ol > li > ol {list-style-type: lower-alpha;}
|
||||||
|
.franklin-toc ol > li > ol > li > ol {list-style-type: lower-roman;}
|
||||||
|
|
||||||
|
code.language-yaml .hljs-attr { color: #ca4418;}
|
||||||
|
code.language-yaml .hljs-string { color: green;}
|
||||||
|
|
||||||
|
ul.menu-list-child-list {
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.menu-list-child-list li{
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
ul.menu-list-child-list a.menu-list-link {
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* LUNR */
|
||||||
|
.result-title a {
|
||||||
|
/* font-size: 1.2em; */
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-title a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-preview {
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .search-input {
|
||||||
|
width: 250px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.resultCount {
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-query {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lunrSearchForm {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .pagination {
|
||||||
|
text-align: center;
|
||||||
|
margin: 16px 8px 16px 8px;
|
||||||
|
}
|
||||||
|
.pagination a {
|
||||||
|
color: black;
|
||||||
|
padding: 8px 16px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.pagination a.active {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.pagination a:hover:not(.active) {
|
||||||
|
background-color: #ddd;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* ================================================================== */
|
||||||
|
/* PAGE-DIVS
|
||||||
|
- .flist = lists with a checkmark
|
||||||
|
- .note = highlight the background in light yellow
|
||||||
|
*/
|
||||||
|
/* ================================================================== */
|
||||||
|
|
||||||
|
.blank {
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flist p {
|
||||||
|
display:inline;
|
||||||
|
}
|
||||||
|
.flist ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.flist a#goto {
|
||||||
|
padding-right: 10px;
|
||||||
|
margin-left: -15px;
|
||||||
|
}
|
||||||
|
.flist a#goto #arrow{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.flist a#goto:hover #check {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.flist a#goto:hover #arrow {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.tlist p {
|
||||||
|
display:inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note {
|
||||||
|
margin-top: 1.5em;
|
||||||
|
width: 95%;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:auto;
|
||||||
|
background-color: aliceblue;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.note .content {
|
||||||
|
padding: 10px;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
.note .title{
|
||||||
|
font-size: 105%;
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
padding-left: 7px;
|
||||||
|
padding-top: 2px;
|
||||||
|
color: white;
|
||||||
|
background: cornflowerblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.definition {
|
||||||
|
background-color: aliceblue;
|
||||||
|
border-left: 5px solid cornflowerblue;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.important {
|
||||||
|
background-color: lemonchiffon;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.silly-formatting {
|
||||||
|
width: 50%;
|
||||||
|
text-align: center;
|
||||||
|
color: magenta;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ccols {
|
||||||
|
margin-top:1.5em;
|
||||||
|
margin-bottom:1.5em;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:auto;
|
||||||
|
width: 60%;
|
||||||
|
text-align: center;}
|
||||||
|
.ccols svg {
|
||||||
|
width:30px;}
|
||||||
|
|
||||||
|
.lalign td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.lalign tr:first-of-type > td {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lalignb td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.lalignb tr:first-of-type > td {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.lalignb th:nth-child(1){
|
||||||
|
width:100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================================== */
|
||||||
|
/* Small additional divs */
|
||||||
|
/* ================================================================== */
|
||||||
|
|
||||||
|
.small-img {
|
||||||
|
width: 50%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
var path = require("path");
|
||||||
|
var fs = require("fs");
|
||||||
|
var lunr = require("lunr");
|
||||||
|
var cheerio = require("cheerio");
|
||||||
|
|
||||||
|
// don't modify this, it'll be modified on the fly by lunr() in Franklin
|
||||||
|
const PATH_PREPEND = "..";
|
||||||
|
|
||||||
|
const HTML_FOLDER = "../../__site";
|
||||||
|
const OUTPUT_INDEX = "lunr_index.js";
|
||||||
|
|
||||||
|
function isHtml(filename) {
|
||||||
|
lower = filename.toLowerCase();
|
||||||
|
return (lower.endsWith(".htm") || lower.endsWith(".html"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function findHtml(folder) {
|
||||||
|
if (!fs.existsSync(folder)) {
|
||||||
|
console.log("Could not find folder: ", folder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var files = fs.readdirSync(folder);
|
||||||
|
var htmls = [];
|
||||||
|
for (var i = 0; i < files.length; i++) {
|
||||||
|
var filename = path.join(folder, files[i]);
|
||||||
|
var stat = fs.lstatSync(filename);
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
if (stat == "assets" || stat == "css" || stat == "libs" ) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var recursed = findHtml(filename);
|
||||||
|
for (var j = 0; j < recursed.length; j++) {
|
||||||
|
recursed[j] = path.join(files[i], recursed[j]).replace(/\\/g, "/");
|
||||||
|
}
|
||||||
|
htmls.push.apply(htmls, recursed);
|
||||||
|
}
|
||||||
|
else if (isHtml(filename)){
|
||||||
|
htmls.push(files[i]);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return htmls;
|
||||||
|
};
|
||||||
|
|
||||||
|
function readHtml(root, file, fileId) {
|
||||||
|
var filename = path.join(root, file);
|
||||||
|
var txt = fs.readFileSync(filename).toString();
|
||||||
|
var $ = cheerio.load(txt);
|
||||||
|
var title = $("title").text();
|
||||||
|
if (typeof title == 'undefined') title = file;
|
||||||
|
var body = $("body").text()
|
||||||
|
if (typeof body == 'undefined') body = "";
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
"id": fileId,
|
||||||
|
"l": filename,
|
||||||
|
"t": title,
|
||||||
|
"b": body
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildIndex(docs) {
|
||||||
|
var idx = lunr(function () {
|
||||||
|
this.ref('id');
|
||||||
|
this.field('t'); // title
|
||||||
|
this.field('b'); // body
|
||||||
|
docs.forEach(function (doc) {
|
||||||
|
this.add(doc);
|
||||||
|
}, this);
|
||||||
|
});
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPreviews(docs) {
|
||||||
|
var result = {};
|
||||||
|
for (var i = 0; i < docs.length; i++) {
|
||||||
|
var doc = docs[i];
|
||||||
|
result[doc["id"]] = {
|
||||||
|
"t": doc["t"],
|
||||||
|
"l": doc["l"].replace(/^\.\.\/\.\.\/__site/gi, '/' + PATH_PREPEND)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
files = findHtml(HTML_FOLDER);
|
||||||
|
var docs = [];
|
||||||
|
for (var i = 0; i < files.length; i++) {
|
||||||
|
docs.push(readHtml(HTML_FOLDER, files[i], i));
|
||||||
|
}
|
||||||
|
var idx = buildIndex(docs);
|
||||||
|
var prev = buildPreviews(docs);
|
||||||
|
var js = "const LUNR_DATA = " + JSON.stringify(idx) + ";\n" +
|
||||||
|
"const PREVIEW_LOOKUP = " + JSON.stringify(prev) + ";";
|
||||||
|
fs.writeFile(OUTPUT_INDEX, js, function(err) {
|
||||||
|
if(err) {
|
||||||
|
return console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
|
@ -0,0 +1,88 @@
|
||||||
|
// This file and its minified version is adapted from https://github.com/BLE-LTER/Lunr-Index-and-Search-for-Static-Sites which is unlicensed.
|
||||||
|
//
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var LUNR_CONFIG = {
|
||||||
|
"resultsElementId": "searchResults", // Element to contain results
|
||||||
|
"countElementId": "resultCount" // Element showing number of results
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Get URL arguments
|
||||||
|
function getParameterByName(name) {
|
||||||
|
var url = window.location.href;
|
||||||
|
name = name.replace(/[\[\]]/g, "\\$&");
|
||||||
|
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
|
||||||
|
results = regex.exec(url);
|
||||||
|
if (!results) return null;
|
||||||
|
if (!results[2]) return "";
|
||||||
|
return decodeURIComponent(results[2].replace(/\+/g, " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse search results into HTML
|
||||||
|
function parseLunrResults(results) {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < results.length; i++) {
|
||||||
|
var id = results[i]["ref"];
|
||||||
|
var item = PREVIEW_LOOKUP[id]
|
||||||
|
var title = item["t"];
|
||||||
|
var preview = item["p"];
|
||||||
|
var link = item["l"].replace("__site/", "");
|
||||||
|
var result = ('<li><span class="result-title"><a href="' + link + '">'
|
||||||
|
+ title + '</a></span>');
|
||||||
|
html.push(result);
|
||||||
|
}
|
||||||
|
if (html.length) {
|
||||||
|
html.join("");
|
||||||
|
return '<ul>'+html+'</ul>'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function escapeHtml(unsafe) {
|
||||||
|
return unsafe
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function showResultCount(total) {
|
||||||
|
var element = document.getElementById(LUNR_CONFIG["countElementId"])
|
||||||
|
if (element !== null) {
|
||||||
|
element.innerHTML = total + ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function searchLunr(query) {
|
||||||
|
var idx = lunr.Index.load(LUNR_DATA);
|
||||||
|
// Write results to page
|
||||||
|
var results = idx.search(query);
|
||||||
|
var resultHtml = parseLunrResults(results);
|
||||||
|
var elementId = LUNR_CONFIG["resultsElementId"];
|
||||||
|
document.getElementById(elementId).innerHTML = resultHtml;
|
||||||
|
// Write the number of results
|
||||||
|
showResultCount(results.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// When the window loads, read query parameters and perform search
|
||||||
|
window.onload = function() {
|
||||||
|
var query = getParameterByName("q");
|
||||||
|
if (query != "" && query != null) {
|
||||||
|
document.forms.lunrSearchForm.q.value = query;
|
||||||
|
searchLunr(query);
|
||||||
|
} else {
|
||||||
|
// empty query: show 0 results (no query)
|
||||||
|
showResultCount("0 (empty query)");
|
||||||
|
}
|
||||||
|
document.getElementById("focus").focus();
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";var LUNR_CONFIG={"resultsElementId":"searchResults","countElementId":"resultCount"};function getParameterByName(name){var url=window.location.href;name=name.replace(/[\[\]]/g,"\\$&");var regex=new RegExp("[?&]"+name+"(=([^&#]*)|&|#|$)"),results=regex.exec(url);if(!results){return null}if(!results[2]){return ""}return decodeURIComponent(results[2].replace(/\+/g," "))}function parseLunrResults(results){var html=[];for(var i=0;i<results.length;i+=1){var id=results[i]["ref"];var item=PREVIEW_LOOKUP[id];var title=item["t"];var preview=item["p"];var link=item["l"].replace("__site/","");var result=('<li><span class="result-title"><a href="'+link+'">'+title+'</a></span>');html.push(result)}if(html.length){html.join("");return '<ul>'+html+'</ul>'}else{return ""}}function escapeHtml(unsafe){return unsafe.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function showResultCount(total){var element=document.getElementById(LUNR_CONFIG["countElementId"]);if(element!==null){element.innerHTML=total+"."}}function searchLunr(query){var idx=lunr.Index.load(LUNR_DATA);var results=idx.search(query);var resultHtml=parseLunrResults(results);var elementId=LUNR_CONFIG["resultsElementId"];document.getElementById(elementId).innerHTML=resultHtml;showResultCount(results.length)}window.onload=function(){var query=getParameterByName("q");if(query!=""&&query!=null){document.forms.lunrSearchForm.q.value=query;searchLunr(query)}else{showResultCount("0 (empty query)")}document.getElementById("focus").focus()};
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Some **really cool** maths:
|
||||||
|
#
|
||||||
|
# $$ \exp(i\pi) + 1 \quad = \quad 0 $$
|
||||||
|
#
|
||||||
|
# We can show this with some code:
|
||||||
|
|
||||||
|
x = exp(im*π) + 1
|
||||||
|
|
||||||
|
# that looks close to zero but
|
||||||
|
|
||||||
|
x ≈ 0
|
||||||
|
|
||||||
|
# however
|
||||||
|
|
||||||
|
abs(x) < eps()
|
||||||
|
|
||||||
|
# #### Conclusion
|
||||||
|
#
|
||||||
|
# The equation is proven thanks to our very rigorous proof.
|
|
@ -0,0 +1,417 @@
|
||||||
|
<!--
|
||||||
|
reviewed: 22/12/2019
|
||||||
|
-->
|
||||||
|
|
||||||
|
@def hascode=true
|
||||||
|
|
||||||
|
# Tricks with code evaluation
|
||||||
|
|
||||||
|
\blurb{Franklin's recursive nature coupled with code evaluation allows for neat and useful tricks.}
|
||||||
|
|
||||||
|
\lineskip
|
||||||
|
|
||||||
|
\toc
|
||||||
|
|
||||||
|
The basic idea is to exploit the fact that the output of a Julia code block evaluated by Franklin can be re-processed as Franklin Markdow when using the `\textoutput` command; this offers a wide range of possibilities best shown through a few examples (more or less in increasing degree of sophistication).
|
||||||
|
|
||||||
|
## Generating a table
|
||||||
|
|
||||||
|
### Preview
|
||||||
|
|
||||||
|
```julia:table
|
||||||
|
#hideall
|
||||||
|
names = (:Taimur, :Catherine, :Maria, :Arvind, :Jose, :Minjie)
|
||||||
|
numbers = (1525, 5134, 4214, 9019, 8918, 5757)
|
||||||
|
println("@@simple-table")
|
||||||
|
println("Name | Number")
|
||||||
|
println(":--- | :---")
|
||||||
|
println.("$name | $number" for (name, number) in zip(names, numbers))
|
||||||
|
println("@@")
|
||||||
|
raw"""
|
||||||
|
~~~
|
||||||
|
<style>
|
||||||
|
.simple-table tr {
|
||||||
|
padding:0;
|
||||||
|
line-height:1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
~~~
|
||||||
|
""" |> println
|
||||||
|
```
|
||||||
|
|
||||||
|
\textoutput{table}
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
That can be obtained with:
|
||||||
|
|
||||||
|
`````plaintext
|
||||||
|
```julia:table
|
||||||
|
#hideall
|
||||||
|
names = (:Taimur, :Catherine, :Maria, :Arvind, :Jose, :Minjie)
|
||||||
|
numbers = (1525, 5134, 4214, 9019, 8918, 5757)
|
||||||
|
println("Name | Number")
|
||||||
|
println(":--- | :---")
|
||||||
|
println.("$name | $number" for (name, number) in zip(names, numbers))
|
||||||
|
```
|
||||||
|
|
||||||
|
\textoutput{table}
|
||||||
|
`````
|
||||||
|
|
||||||
|
The code block will be executed and not shown (`#hideall`) generating a table line by line.
|
||||||
|
In practice, the code generates the markdown
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Name | Number
|
||||||
|
:--- | :---
|
||||||
|
Bob | 1525
|
||||||
|
...
|
||||||
|
Minjie | 5757
|
||||||
|
```
|
||||||
|
|
||||||
|
which is captured and reprocessed by the `\textoutput` command.
|
||||||
|
|
||||||
|
This can be used effectively when combined with reading data files etc. and of course you could do further CSS styling of the table.
|
||||||
|
|
||||||
|
## Colourful circles
|
||||||
|
|
||||||
|
The trick can be used to generate SVG code too.
|
||||||
|
|
||||||
|
### Preview
|
||||||
|
|
||||||
|
\newcommand{\circle}[1]{~~~<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 4"><circle cx="2" cy="2" r="1.5" fill="#1"/></svg>~~~}
|
||||||
|
|
||||||
|
```julia:circles
|
||||||
|
#hideall
|
||||||
|
colors=(:pink, :lightpink, :hotpink, :deeppink, :mediumvioletred, :palevioletred, :coral, :tomato, :orangered, :darkorange, :orange, :gold, :yellow)
|
||||||
|
print("@@ccols ")
|
||||||
|
print.("\\circle{$c}" for c in colors)
|
||||||
|
println("@@")
|
||||||
|
```
|
||||||
|
|
||||||
|
\textoutput{circles}
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
That can obtained with (see detailed explanations further below)
|
||||||
|
|
||||||
|
```html
|
||||||
|
\newcommand{\circle}[1]{
|
||||||
|
~~~
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 4">
|
||||||
|
<circle cx="2" cy="2" r="1.5" fill="#1"/></svg>
|
||||||
|
~~~
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
`````plaintext
|
||||||
|
```julia:circles
|
||||||
|
#hideall
|
||||||
|
colors=(:pink, :lightpink, :hotpink, :deeppink,
|
||||||
|
:mediumvioletred, :palevioletred, :coral,
|
||||||
|
:tomato, :orangered, :darkorange, :orange,
|
||||||
|
:gold, :yellow)
|
||||||
|
print("@@ccols ")
|
||||||
|
print.("\\circle{$c}" for c in colors)
|
||||||
|
println("@@")
|
||||||
|
```
|
||||||
|
\textoutput{circles}
|
||||||
|
`````
|
||||||
|
|
||||||
|
|
||||||
|
The first part defines a command `\circle` which takes one argument for the fill colour and inserts SVG code for a circle with that colour.
|
||||||
|
|
||||||
|
The second part is a Julia code block which will be evaluated but not displayed on the page (since there is a `#hideall`).
|
||||||
|
The code loops over the each colour `c` and prints `\circle{c}` so that the code block effectively generates:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
@@ccols \circle{pink}...\circle{yellow}@@
|
||||||
|
```
|
||||||
|
|
||||||
|
this output is then captured and reprocessed with the `\textoutput{snippet}` command.
|
||||||
|
|
||||||
|
The last thing to do is to style the `colors` div appropriately:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.ccols {
|
||||||
|
margin-top:1.5em;
|
||||||
|
margin-bottom:1.5em;
|
||||||
|
margin-left:auto;
|
||||||
|
margin-right:auto;
|
||||||
|
width: 60%;
|
||||||
|
text-align: center;}
|
||||||
|
.ccols svg {
|
||||||
|
width:30px;}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Team cards
|
||||||
|
|
||||||
|
You may want to have a page with responsive team cards for instance where every card would follow the same layout but the content would be different.
|
||||||
|
There are multiple ways you can do this with Franklin and a simple one below (adapted from [this tutorial](https://www.w3schools.com/howto/howto_css_team.asp)).
|
||||||
|
The advantage of doing something like this is that it can help separate the content from the layout making both arguably easier more maintainable.
|
||||||
|
|
||||||
|
### Preview
|
||||||
|
|
||||||
|
\newcommand{\card}[5]{
|
||||||
|
@@card
|
||||||
|
![#1](/assets/img/team/!#2.jpg)
|
||||||
|
@@container
|
||||||
|
~~~
|
||||||
|
<h2>#1</h2>
|
||||||
|
~~~
|
||||||
|
@@title #3 @@
|
||||||
|
@@vitae #4 @@
|
||||||
|
@@email #5 @@
|
||||||
|
~~~
|
||||||
|
<p><button class="button">Contact</button></p>
|
||||||
|
~~~
|
||||||
|
@@
|
||||||
|
@@
|
||||||
|
}
|
||||||
|
|
||||||
|
```julia:teamcards
|
||||||
|
#hideall
|
||||||
|
team = [
|
||||||
|
(name="Jane Doe", pic="beth", title="CEO & Founder", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com"),
|
||||||
|
(name="Mike Ross", pic="rick", title="Art Director", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com"),
|
||||||
|
(name="John Doe", pic="meseeks", title="Designer", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com")
|
||||||
|
]
|
||||||
|
|
||||||
|
"@@cards @@row" |> println
|
||||||
|
for person in team
|
||||||
|
"""
|
||||||
|
@@column
|
||||||
|
\\card{$(person.name)}{$(person.pic)}{$(person.title)}{$(person.vitae)}{$(person.email)}
|
||||||
|
@@
|
||||||
|
""" |> println
|
||||||
|
end
|
||||||
|
println("@@ @@") # end of cards + row
|
||||||
|
|
||||||
|
raw"""
|
||||||
|
~~~
|
||||||
|
<style>
|
||||||
|
.column {
|
||||||
|
float:left;
|
||||||
|
width:30%;
|
||||||
|
margin-bottom:16px;
|
||||||
|
padding:0 8px;
|
||||||
|
}
|
||||||
|
@media (max-width:62rem) {
|
||||||
|
.column {
|
||||||
|
width:45%;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width:30rem){
|
||||||
|
.column {
|
||||||
|
width:95%;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card{
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.card img {
|
||||||
|
padding-left:0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
.container::after, .row::after{
|
||||||
|
content:"";
|
||||||
|
clear:both;
|
||||||
|
display:table;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
color:grey;
|
||||||
|
}
|
||||||
|
.vitae {
|
||||||
|
margin-top:0.5em;
|
||||||
|
}
|
||||||
|
.email {
|
||||||
|
font-family:courier;
|
||||||
|
margin-top:0.5em;
|
||||||
|
margin-bottom:0.5em;
|
||||||
|
}
|
||||||
|
.button{
|
||||||
|
border:none;
|
||||||
|
outline:0;
|
||||||
|
display:inline-block;
|
||||||
|
padding:8px;
|
||||||
|
color:white;
|
||||||
|
background-color:#000;
|
||||||
|
text-align:center;
|
||||||
|
cursor:pointer;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.button:hover{
|
||||||
|
background-color:#555;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
~~~
|
||||||
|
""" |> println
|
||||||
|
```
|
||||||
|
|
||||||
|
\textoutput{teamcards}
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
In order to do this you could first define a `\card` command:
|
||||||
|
|
||||||
|
```html
|
||||||
|
\newcommand{\card}[5]{
|
||||||
|
@@card
|
||||||
|
![#1](/assets/img/team/!#2.jpg)
|
||||||
|
@@container
|
||||||
|
~~~
|
||||||
|
<h2>#1</h2>
|
||||||
|
~~~
|
||||||
|
@@title #3 @@
|
||||||
|
@@vitae #4 @@
|
||||||
|
@@email #5 @@
|
||||||
|
~~~
|
||||||
|
<p><button class="button">Contact</button></p>
|
||||||
|
~~~
|
||||||
|
@@
|
||||||
|
@@
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And then use it in a loop that goes over each person:
|
||||||
|
|
||||||
|
`````plaintext
|
||||||
|
```julia:teamcards
|
||||||
|
#hideall
|
||||||
|
team = [
|
||||||
|
(name="Jane Doe", pic="beth", title="CEO & Founder", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com"),
|
||||||
|
(name="Mike Ross", pic="rick", title="Art Director", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com"),
|
||||||
|
(name="John Doe", pic="meseeks", title="Designer", vitae="Phasellus eget enim eu lectus faucibus vestibulum", email="example@example.com")
|
||||||
|
]
|
||||||
|
|
||||||
|
"@@cards @@row" |> println
|
||||||
|
for person in team
|
||||||
|
"""
|
||||||
|
@@column
|
||||||
|
\\card{$(person.name)}{$(person.pic)}{$(person.title)}{$(person.vitae)}{$(person.email)}
|
||||||
|
@@
|
||||||
|
""" |> println
|
||||||
|
end
|
||||||
|
println("@@ @@") # end of cards + row
|
||||||
|
```
|
||||||
|
|
||||||
|
\textoutput{teamcards}
|
||||||
|
`````
|
||||||
|
|
||||||
|
That's about it! though of course a bit of CSS styling is needed such as:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.column {
|
||||||
|
float:left;
|
||||||
|
width:30%;
|
||||||
|
margin-bottom:16px;
|
||||||
|
padding:0 8px; }
|
||||||
|
@media (max-width:62rem) {
|
||||||
|
.column {
|
||||||
|
width:45%;
|
||||||
|
display:block; }
|
||||||
|
}
|
||||||
|
@media (max-width:30rem){
|
||||||
|
.column {
|
||||||
|
width:95%;
|
||||||
|
display:block;}
|
||||||
|
}
|
||||||
|
.card { box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); }
|
||||||
|
.card img {
|
||||||
|
padding-left:0;
|
||||||
|
width: 100%; }
|
||||||
|
.container { padding: 0 16px; }
|
||||||
|
.container::after, .row::after{
|
||||||
|
content: "";
|
||||||
|
clear: both;
|
||||||
|
display: table; }
|
||||||
|
.title { color: grey; }
|
||||||
|
.vitae { margin-top: 0.5em; }
|
||||||
|
.email {
|
||||||
|
font-family: courier;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em; }
|
||||||
|
.button{
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 8px;
|
||||||
|
color: white;
|
||||||
|
background-color: #000;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%; }
|
||||||
|
.button:hover{ background-color: #555; }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Python code blocks
|
||||||
|
|
||||||
|
Using [PyCall.jl](https://github.com/JuliaPy/PyCall.jl) you can evaluate Python code in Julia, and so you can do that in Franklin too.
|
||||||
|
The code below could definitely be improved and generalised but the point here is to show how things can work together.
|
||||||
|
You could adapt this to work with something like [RCall.jl](https://github.com/JuliaInterop/RCall.jl) as well.
|
||||||
|
|
||||||
|
\newcommand{\pycode}[2]{
|
||||||
|
```julia:!#1
|
||||||
|
#hideall
|
||||||
|
using PyCall
|
||||||
|
lines = replace("""!#2""", r"(^|\n)([^\n]+)\n?$" => s"\1res = \2")
|
||||||
|
py"""
|
||||||
|
$$lines
|
||||||
|
"""
|
||||||
|
println(py"res")
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
#2
|
||||||
|
```
|
||||||
|
\codeoutput{!#1}
|
||||||
|
}
|
||||||
|
|
||||||
|
\pycode{py1}{
|
||||||
|
import numpy as np
|
||||||
|
np.random.seed(2)
|
||||||
|
x = np.random.randn(5)
|
||||||
|
r = np.linalg.norm(x) / len(x)
|
||||||
|
np.round(r, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
We first define a `\pycode` command that takes lines of python code, adds a `res = ` before the last line, runs the lines and finally show `res`.
|
||||||
|
It also inputs the lines of code in a fenced block.
|
||||||
|
|
||||||
|
`````plaintext
|
||||||
|
\newcommand{\pycode}[2]{
|
||||||
|
```julia:!#1
|
||||||
|
#hideall
|
||||||
|
using PyCall
|
||||||
|
lines = replace("""!#2""", r"(^|\n)([^\n]+)\n?$" => s"\1res = \2")
|
||||||
|
py"""
|
||||||
|
$$lines
|
||||||
|
"""
|
||||||
|
println(py"res")
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
#2
|
||||||
|
```
|
||||||
|
\codeoutput{!#1}
|
||||||
|
}
|
||||||
|
`````
|
||||||
|
|
||||||
|
calling the command is straightforward:
|
||||||
|
|
||||||
|
`````
|
||||||
|
\pycode{py1}{
|
||||||
|
import numpy as np
|
||||||
|
np.random.seed(2)
|
||||||
|
x = np.random.randn(5)
|
||||||
|
r = np.linalg.norm(x) / len(x)
|
||||||
|
np.round(r, 2)
|
||||||
|
}
|
||||||
|
`````
|
|
@ -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,104 @@
|
||||||
|
@def hascode = true
|
||||||
|
@def showall = true
|
||||||
|
@def hasmath = true
|
||||||
|
|
||||||
|
# Work with Literate.jl
|
||||||
|
|
||||||
|
\blurb{Franklin works seamlessly with Literate to offer a convenient way to write and maintain tutorials.}
|
||||||
|
|
||||||
|
\lineskip
|
||||||
|
|
||||||
|
\toc
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
[Literate.jl](https://github.com/fredrikekre/Literate.jl) is a convenient package that allows you to write scripts in Julia and convert them to markdown pages or Jupyter notebooks.
|
||||||
|
|
||||||
|
You can combine this with Franklin with the `\literate` command which you can call in Franklin like:
|
||||||
|
|
||||||
|
```
|
||||||
|
\literate{/_literate/script.jl}
|
||||||
|
```
|
||||||
|
|
||||||
|
it does what you expect:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
* the markdown is interpreted and evaluated
|
||||||
|
* the code blocks are evaluated and their output can be shown selectively
|
||||||
|
@@
|
||||||
|
|
||||||
|
If you want the script to be shown like a notebook where the output of every code block is shown, use `@def showall = true`.
|
||||||
|
|
||||||
|
Combining Franklin with Literate offers a very convenient way to write and maintain tutorial websites (see for instance the [MLJ Tutorials](https://alan-turing-institute.github.io/MLJTutorials/)).
|
||||||
|
|
||||||
|
### File organisation
|
||||||
|
|
||||||
|
We recommend you have a folder `/_literate/` in your root folder, place your literate scripts there and call them as in the example above.
|
||||||
|
|
||||||
|
### Tricks
|
||||||
|
|
||||||
|
In the `showall = true` mode, the last line of each code block is displayed in full.
|
||||||
|
In some cases you will have to think about this a bit more than you would in your REPL and might for instance:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
* _suppress the output_, in which case you should add a `;` at the end of the line
|
||||||
|
* _only show a few elements_ (see below)
|
||||||
|
@@
|
||||||
|
|
||||||
|
For instance you might prefer:
|
||||||
|
|
||||||
|
```julia:ee0
|
||||||
|
x = randn(10)
|
||||||
|
x[1:3]
|
||||||
|
```
|
||||||
|
|
||||||
|
to just
|
||||||
|
|
||||||
|
```julia:ee1
|
||||||
|
x = randn(10)
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use `@show` or `println` to show specific things beyond the last line
|
||||||
|
|
||||||
|
```julia:ee2
|
||||||
|
x = rand(10)
|
||||||
|
println(sum(x))
|
||||||
|
y = 5
|
||||||
|
```
|
||||||
|
|
||||||
|
if the last line is a `@show` or `print` then only that is shown:
|
||||||
|
|
||||||
|
```julia:ee3
|
||||||
|
x = randn(10)
|
||||||
|
@show x[1]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
### Script
|
||||||
|
|
||||||
|
`````julia
|
||||||
|
# Some **really cool** maths:
|
||||||
|
#
|
||||||
|
# $$ \exp(i\pi) + 1 \quad = \quad 0 $$
|
||||||
|
#
|
||||||
|
# We can show this with some code:
|
||||||
|
|
||||||
|
x = exp(im*π) + 1
|
||||||
|
|
||||||
|
# that looks close to zero but
|
||||||
|
|
||||||
|
x ≈ 0
|
||||||
|
|
||||||
|
# however
|
||||||
|
|
||||||
|
abs(x) < eps()
|
||||||
|
|
||||||
|
# #### Conclusion
|
||||||
|
#
|
||||||
|
# The equation is proven thanks to our very rigorous proof.
|
||||||
|
`````
|
||||||
|
|
||||||
|
### Result
|
||||||
|
|
||||||
|
\literate{/_literate/script_ee.jl} <!--_-->
|
|
@ -0,0 +1,5 @@
|
||||||
|
using Franklin
|
||||||
|
if !(@isdefined msg)
|
||||||
|
msg = "franklin-update"
|
||||||
|
end
|
||||||
|
publish(prerender=false, final=lunr, message=msg)
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Extras
|
||||||
|
|
||||||
|
In this section of the manual, the assumption is that you already have a fairly good idea of how Franklin works so that basic explanations are skipped (refer to the rest of the manual for help).
|
||||||
|
|
||||||
|
The aim is to show how Franklin can work with other useful libraries to add functionalities to your website.
|
||||||
|
|
||||||
|
As usual, these examples are just meant to show what can be done, not the best way to do it, feel free to modify the examples at will!
|
||||||
|
Also, if you come up with other nice ways of extending Franklin, don't hesitate to make a suggestion for an example to be added here.
|
||||||
|
|
||||||
|
## List of examples
|
||||||
|
|
||||||
|
@@flist
|
||||||
|
* \goto{/extras/lunr/} Add a search functionality to your website using [`lunr.js`](https://lunrjs.com/),
|
||||||
|
* \goto{/extras/literate/} Generate auxiliary files with Literate.
|
||||||
|
* \goto{/extras/plotly/} Add interactive plots with [Plotly](https://plot.ly/javascript/).
|
||||||
|
@@
|
|
@ -0,0 +1,100 @@
|
||||||
|
@def hascode = true
|
||||||
|
|
||||||
|
# Generating auxiliary files with Literate
|
||||||
|
|
||||||
|
See also [how to interact with literate scripts](/code/literate/).
|
||||||
|
|
||||||
|
[Literate.jl](https://github.com/fredrikekre/Literate.jl) allows to pre and post-process a script in order, for instance, to generate a notebook out of a script.
|
||||||
|
This can be convenient if you want to have a tutorial be downloadable as a standalone notebook or as a scrubbed script.
|
||||||
|
|
||||||
|
This page presents one way of doing this which is used in [MLJTutorials](https://github.com/alan-turing-institute/MLJTutorials) and which might inspire your own approach.
|
||||||
|
|
||||||
|
The key ingredients are:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
1. use Literate to generate derived files,
|
||||||
|
1. use `gh-pages` to push the generated file to GitHub,
|
||||||
|
1. add this as a `final` hook to `publish`.
|
||||||
|
@@
|
||||||
|
|
||||||
|
In what follows, it is assumed you have your Literate scripts in a folder `/scripts/` and that you're using GitHub.
|
||||||
|
It shouldn't be hard to modify that to suit your own case.
|
||||||
|
|
||||||
|
|
||||||
|
## Using Literate to generate auxiliary files
|
||||||
|
|
||||||
|
Literate can manipulate scripts fairly easily, for instance to generate notebooks:
|
||||||
|
|
||||||
|
```julia
|
||||||
|
scripts = joinpath.("scripts", readdir("scripts"))
|
||||||
|
nbpath = joinpath("generated", "notebooks")
|
||||||
|
isdir(nbpath) || mkpath(nbpath)
|
||||||
|
|
||||||
|
for script in scripts
|
||||||
|
# Generate annotated notebooks
|
||||||
|
Literate.notebook(script, nbpath,
|
||||||
|
execute=false, documenter=false)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
This will go over all scripts in `/scripts/` and call `Literate.notebook` to generate a derived notebook in a `/generated/` folder (which you will want to add to your `.gitignore`).
|
||||||
|
|
||||||
|
## Push the generated files to a page branch
|
||||||
|
|
||||||
|
Start by installing `gh-pages` with `npm`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$> npm install gh-pages
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the package [NodeJS.jl](https://github.com/davidanthoff/NodeJS.jl) it is then easy to use `gh-pages` to push the generated notebooks to a folder on the `gh-pages` branch:
|
||||||
|
|
||||||
|
```julia
|
||||||
|
using NodeJS
|
||||||
|
|
||||||
|
JS_GHP = """
|
||||||
|
var ghpages = require('gh-pages');
|
||||||
|
ghpages.publish('generated/', function(err) {});
|
||||||
|
"""
|
||||||
|
|
||||||
|
run(`$(nodejs_cmd()) -e $JS_GHP`)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now these generated files are available on that branch without polluting your `master` branch.
|
||||||
|
You can see this live on the [MLJTutorials repo](https://github.com/alan-turing-institute/MLJTutorials/tree/gh-pages).
|
||||||
|
|
||||||
|
You can link to these generated notebooks with links adapted from:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
https://raw.githubusercontent.com/username/project/gh-pages/notebooks/theNotebook.ipynb
|
||||||
|
```
|
||||||
|
|
||||||
|
See [this page](https://alan-turing-institute.github.io/MLJTutorials/pub/isl/lab-2.html) for example.
|
||||||
|
|
||||||
|
## Add the whole process to `publish`
|
||||||
|
|
||||||
|
You may want to re-generate all notebooks prior to pushing updates to GitHub.
|
||||||
|
For this, use the `final` keyword of `publish` to which you can pass a function to use before publishing updates.
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
```julia
|
||||||
|
function gen_literate()
|
||||||
|
scripts = joinpath.("scripts", readdir("scripts"))
|
||||||
|
nbpath = joinpath("generated", "notebooks")
|
||||||
|
isdir(nbpath) || mkpath(nbpath)
|
||||||
|
|
||||||
|
for script in scripts
|
||||||
|
# Generate annotated notebooks
|
||||||
|
Literate.notebook(script, nbpath,
|
||||||
|
execute=false, documenter=false)
|
||||||
|
end
|
||||||
|
JS_GHP = """
|
||||||
|
var ghpages = require('gh-pages');
|
||||||
|
ghpages.publish('generated/', function(err) {});
|
||||||
|
"""
|
||||||
|
run(`$(nodejs_cmd()) -e $JS_GHP`)
|
||||||
|
end
|
||||||
|
# ... serve etc ...
|
||||||
|
# ... then finally ...
|
||||||
|
publish(final=gen_literate)
|
||||||
|
```
|
|
@ -0,0 +1,143 @@
|
||||||
|
@def hascode = true
|
||||||
|
|
||||||
|
# Add search with Lunr
|
||||||
|
|
||||||
|
\toc\skipline
|
||||||
|
|
||||||
|
[`lunr.js`](https://lunrjs.com/) is a neat little Javascript library that allows to equip your website with a search functionality fairly easily.
|
||||||
|
|
||||||
|
The steps below show a simple way of doing this matching what is done on this website.
|
||||||
|
Once it's working, you might want to adjust the `build_index.js` and/or the `lunrclient.js` to match your needs.
|
||||||
|
|
||||||
|
## Pre-requisites
|
||||||
|
|
||||||
|
### Libraries
|
||||||
|
|
||||||
|
Install `lunr` and `cheerio` (a HTML parser) with `node`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$> npm install lunr
|
||||||
|
$> npm install cheerio
|
||||||
|
```
|
||||||
|
|
||||||
|
(you might have to add `sudo` before `npm`).
|
||||||
|
|
||||||
|
### Files
|
||||||
|
|
||||||
|
Copy [this folder](https://github.com/tlienart/franklindocs/tree/master/_libs/lunr) to a `/_libs/lunr/` directory.
|
||||||
|
Discard the `lunr_index.js` which is the index of this website, you will rebuild your own of course!
|
||||||
|
|
||||||
|
The important files are `build_index.js` and `lunrclient.js` (of which a minified version is provided which you will want to re-generate if you modify the base file).
|
||||||
|
These files are adapted from [this repository](https://github.com/BLE-LTER/Lunr-Index-and-Search-for-Static-Sites) which shows how to use Lunr on a static website.
|
||||||
|
|
||||||
|
You can choose whether to serve your own copy of `lunr.min.js` (done here) or to use an online version via
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://unpkg.com/lunr/lunr.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Index builder
|
||||||
|
|
||||||
|
The file `build_index.js` does the following:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
- it goes over all files in a `HTML_FOLDER` (by default: `/__site/`),
|
||||||
|
- it builds an index `lunr_index.js` which can subsequently be queried upon the user entering search terms.
|
||||||
|
@@
|
||||||
|
|
||||||
|
By default, the index built is fairly barebone to reduce the size of the generated index. If you want fancier search, you might want to modify this a bit to add a preview of the page, boost results depending on where there are (title, keyword, ...), add stop words, etc. (Refer to the [Lunr docs](https://lunrjs.com/docs/index.html) for this as well as [the example repo](https://github.com/BLE-LTER/Lunr-Index-and-Search-for-Static-Sites) mentioned earlier or [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl/blob/master/assets/html/search.js)'s version).
|
||||||
|
|
||||||
|
\note{
|
||||||
|
Modify this file at will but be careful with the lines with `PATH_PREPEND` if your website is a project website (i.e. the root URL is something like `username.github.io/project/`). These lines help ensure that the generated links are valid. See also the section on [updating the index](#buildingupdating_the_index).
|
||||||
|
}
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
The file `lunrclient.js` (and its minified version) does the following:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
- query the index
|
||||||
|
- display the results
|
||||||
|
@@
|
||||||
|
|
||||||
|
You might want to modify the `parseLunrResults` if you want the results to be displayed differently.
|
||||||
|
|
||||||
|
\note{
|
||||||
|
If you modify this file, make sure it's called properly in the `src/_html_parts/index.html` and, eventually, [minify it](https://jscompress.com/).
|
||||||
|
}
|
||||||
|
|
||||||
|
## Adding a search box
|
||||||
|
|
||||||
|
### Adding a form in `head.html`
|
||||||
|
|
||||||
|
The search box on this website is added with the following HTML in `_layout/head.html`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<!-- first few lines ... -->
|
||||||
|
<script src="/libs/lunr/lunr.min.js"></script>
|
||||||
|
<script src="/libs/lunr/lunr_index.js"></script>
|
||||||
|
<script src="/libs/lunr/lunrclient.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<!-- ... -->
|
||||||
|
<form id="lunrSearchForm" name="lunrSearchForm">
|
||||||
|
<input class="search-input" name="q" placeholder="Enter search term" type="text">
|
||||||
|
<input type="submit" value="Search" formaction="/search/index.html">
|
||||||
|
</form>
|
||||||
|
<-- ... -->
|
||||||
|
```
|
||||||
|
|
||||||
|
You may want to style it a bit like so:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.result-title a { text-decoration: none; }
|
||||||
|
.result-title a:hover { text-decoration: underline; }
|
||||||
|
.result-preview { color: #808080; }
|
||||||
|
.resultCount { color: #808080; }
|
||||||
|
.result-query { font-weight: bold; }
|
||||||
|
#lunrSearchForm { margin-top: 1em; }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Target search page
|
||||||
|
|
||||||
|
You also need to add a `src/search.md` to display the results with the appropriate divs:
|
||||||
|
|
||||||
|
```html
|
||||||
|
@def title = "Search ⋅ YourWebsite"
|
||||||
|
|
||||||
|
## Search
|
||||||
|
|
||||||
|
Number of results found: ~~~<span id="resultCount"></span>~~~
|
||||||
|
|
||||||
|
~~~
|
||||||
|
<div id="searchResults"></div>
|
||||||
|
~~~
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that if you modify the `id` of these elements, you will need to adapt the `lunrclient` file(s) accordingly.
|
||||||
|
|
||||||
|
## Building/updating the index
|
||||||
|
|
||||||
|
Franklin exports a `lunr()` function which
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
- checks that you have the right files at the right place,
|
||||||
|
- (re)builds the index, prepending a path to links if required.
|
||||||
|
@@
|
||||||
|
|
||||||
|
If you are experimenting locally, just call `lunr()` then `serve()` and test that searching works as expected.
|
||||||
|
|
||||||
|
When you are ready to update your website you can either:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
1. (recommended) Call `publish(final=lunr)`,
|
||||||
|
1. Call `lunr()` or `lunr(prepath)` if there is a prepath and then publish your updates manually.
|
||||||
|
@@
|
||||||
|
|
||||||
|
The `publish(final=lunr)` calls the `lunr` function as a last step prior to doing a `git push`.
|
||||||
|
An advantage of using this is that Franklin will properly handle the `prepath` if there is one defined in your `config.md`.
|
||||||
|
|
||||||
|
\note{
|
||||||
|
This `final=` keyword can be used with your own functions `()->nothing` if you need to do some post-processing with the generated files before pushing.
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
@def hascode = true
|
||||||
|
@def hasplotly = true
|
||||||
|
|
||||||
|
# Work with Plotly
|
||||||
|
|
||||||
|
If you want interactive plots on some pages and are not afraid of using heavy javascript libraries, then [Plotly](https://plot.ly/javascript/) is a nice library.
|
||||||
|
The Julia wrapper [PlotlyJS.jl](https://github.com/sglyon/PlotlyJS.jl) can be used to generate Plotly plots.
|
||||||
|
|
||||||
|
## Pre-requisites
|
||||||
|
|
||||||
|
Download [`plotly.min.js`](https://cdn.plot.ly/plotly-latest.min.js) saving it to `/_libs/plotly/plotly.min.js`.
|
||||||
|
|
||||||
|
Then create a variable `hasplotly` with default value `false`: in your `config.md` write
|
||||||
|
|
||||||
|
```
|
||||||
|
@def hasplotly = false
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, in your `src/_layout/head.html` add
|
||||||
|
|
||||||
|
```html
|
||||||
|
{{if hasplotly}} <script src="/libs/plotly/plotly.min.js"></script> {{end}}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Offline-generated plot
|
||||||
|
|
||||||
|
Assuming you already have the Plotly code for some plot, displaying the result on a page with Franklin is now pretty straightforward.
|
||||||
|
Start by adding
|
||||||
|
|
||||||
|
```
|
||||||
|
@def hasplotly = true
|
||||||
|
```
|
||||||
|
|
||||||
|
so that the JS library will be loaded then somewhere appropriate add:
|
||||||
|
|
||||||
|
```html
|
||||||
|
~~~
|
||||||
|
<div id="tester" style="width:600px;height:350px;"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
TESTER = document.getElementById('tester');
|
||||||
|
Plotly.plot( TESTER, [{
|
||||||
|
x: [1, 2, 3, 4, 5],
|
||||||
|
y: [1, 2, 4, 8, 16] }], {
|
||||||
|
margin: { t: 0 } } );
|
||||||
|
</script>
|
||||||
|
~~~
|
||||||
|
```
|
||||||
|
|
||||||
|
This will give:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
<div id="tester" style="width:600px;height:350px;"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
TESTER = document.getElementById('tester');
|
||||||
|
Plotly.plot( TESTER, [{
|
||||||
|
x: [1, 2, 3, 4, 5],
|
||||||
|
y: [1, 2, 4, 8, 16] }], {
|
||||||
|
margin: { t: 0 } } );
|
||||||
|
</script>
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Live-generated plot
|
||||||
|
|
||||||
|
One step further is to use `PlotlyJS` to define a plot then pass the result to Franklin.
|
||||||
|
Start by adding `PlotlyJS` and `Random` to your environment:
|
||||||
|
|
||||||
|
```julia-repl
|
||||||
|
(myWebsite) pkg> add PlotlyJS Random
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, beyond the `@def hasplotly = true`, add the following code:
|
||||||
|
|
||||||
|
`````plaintext
|
||||||
|
```julia:ex1
|
||||||
|
using PlotlyJS
|
||||||
|
z = [10 10.625 12.5 15.625 20
|
||||||
|
5.625 6.25 8.125 11.25 15.625
|
||||||
|
2.5 3.125 5. 8.125 12.5
|
||||||
|
0.625 1.25 3.125 6.25 10.625
|
||||||
|
0 0.625 2.5 5.625 10]
|
||||||
|
|
||||||
|
data = contour(; z=z)
|
||||||
|
layout = Layout(; title="Basic Contour Plot")
|
||||||
|
plt = plot(data, layout)
|
||||||
|
|
||||||
|
fdplotly(json(plt)) # hide
|
||||||
|
```
|
||||||
|
\textoutput{ex1}
|
||||||
|
`````
|
||||||
|
|
||||||
|
**Note**: the `fdplotly` is a convenience function exported by `Franklin`; it just prints the required HTML such that a plotly object gets placed. It takes the JSON string of the plot (which you can get with `json(plt)`) and takes two optional keyword arguments:
|
||||||
|
- `id`: to specify the name of the div the plotly object is associated to, it's randomly generated by default, and,
|
||||||
|
- `style` which takes a string indicating the desired CSS for the div e.g. the default is `"width:600px;height:350px"`.
|
||||||
|
|
||||||
|
The code block above gives:
|
||||||
|
|
||||||
|
```julia:ex1
|
||||||
|
using PlotlyJS
|
||||||
|
z = [10 10.625 12.5 15.625 20
|
||||||
|
5.625 6.25 8.125 11.25 15.625
|
||||||
|
2.5 3.125 5. 8.125 12.5
|
||||||
|
0.625 1.25 3.125 6.25 10.625
|
||||||
|
0 0.625 2.5 5.625 10]
|
||||||
|
|
||||||
|
data = contour(; z=z)
|
||||||
|
layout = Layout(; title="Basic Contour Plot")
|
||||||
|
plt = plot(data, layout)
|
||||||
|
|
||||||
|
fdplotly(json(plt)) # hide
|
||||||
|
```
|
||||||
|
\textoutput{ex1}
|
|
@ -0,0 +1,133 @@
|
||||||
|
@def hascode=true
|
||||||
|
@def maxtoclevel=3
|
||||||
|
|
||||||
|
# FAQ - Technical
|
||||||
|
|
||||||
|
If you have a question that you couldn't find an answer to easily, don't hesitate to [open an issue](https://github.com/tlienart/Franklin.jl/issues/new) on GitHub, it will help me make this section more complete!
|
||||||
|
|
||||||
|
\toc
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
### Can you style footnote text?
|
||||||
|
|
||||||
|
**Reference**: [issue 243](https://github.com/tlienart/Franklin.jl/issues/243), **more on this**: [styling](/styling/classes/).
|
||||||
|
|
||||||
|
For the reference basically a footnote is inserted as
|
||||||
|
|
||||||
|
```html
|
||||||
|
<sup id="fnref:1"><a href="/menu1/#fndef:1" class="fnref">[1]</a></sup>
|
||||||
|
```
|
||||||
|
|
||||||
|
So you can style that with the class `.franklin-content sup a.fnref`.
|
||||||
|
|
||||||
|
For definitions, it's inserted as a table like:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<table class="fndef" id="fndef:blah">
|
||||||
|
<tr>
|
||||||
|
<td class="fndef-backref"><a href="/menu1/#fnref:blah">[2]</a></td>
|
||||||
|
<td class="fndef-content">this is another footnote</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
```
|
||||||
|
|
||||||
|
so you can style the back-reference via the `.franklin-content fndef td.fndef-backref` and the text of the definition via `.franklin-content fndef td.fndef-content`; for instance, consider the following base styling:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.franklin-content table.fndef {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 10px;}
|
||||||
|
.franklin-content .fndef tr, td {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
text-align: left;}
|
||||||
|
.franklin-content .fndef tr {
|
||||||
|
border-left: 2px solid lightgray;
|
||||||
|
}
|
||||||
|
.franklin-content .fndef td.fndef-backref {
|
||||||
|
vertical-align: top;
|
||||||
|
font-size: 70%;
|
||||||
|
padding-left: 5px;}
|
||||||
|
.franklin-content .fndef td.fndef-content {
|
||||||
|
font-size: 80%;
|
||||||
|
padding-left: 10px;}
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to disable numbering of math in display mode?
|
||||||
|
|
||||||
|
It is possible to specify in the CSS which Katex equations will be numbered or not by adjusting the
|
||||||
|
`.katex-display::after` class.
|
||||||
|
If you want to disable numbering in the entire site, just head to `_css/franklin.css` and remove the `.katex-display::after` block.
|
||||||
|
You can also build a simple way to disable all numbering inside a specified `@@` div
|
||||||
|
(see [div blocks](/syntax/divs-commands/#div_blocks))
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
This is numbered:
|
||||||
|
$$ 1+1 = 2 $$
|
||||||
|
|
||||||
|
This isn't:
|
||||||
|
|
||||||
|
@@no-number
|
||||||
|
$$ 2+2 = 4 $$
|
||||||
|
and
|
||||||
|
$$ 3+3 = 7-1 $$
|
||||||
|
@@
|
||||||
|
|
||||||
|
Numbered again:
|
||||||
|
$$ 7 + 1 = 8 $$
|
||||||
|
```
|
||||||
|
|
||||||
|
by adding in the CSS:
|
||||||
|
```css
|
||||||
|
.no-number .katex-display::after {
|
||||||
|
counter-increment: nothing;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And possibly [define a command](/syntax/divs-commands/#latex-like_commands) in `config.md`:\
|
||||||
|
```markdown
|
||||||
|
\newcommand{\nalign}[1]{@@no-number \begin{align}#1\end{align}@@}
|
||||||
|
```
|
||||||
|
if you feel it is more convenient to write `\nalign{3+3 = 6}`.
|
||||||
|
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
### How to use loops for templating?
|
||||||
|
|
||||||
|
**Reference**: [issue 251](https://github.com/tlienart/Franklin.jl/issues/251), **more on this**: [code tricks](/code/eval-tricks/).
|
||||||
|
|
||||||
|
Since you can show the output of any Julia code block (and interpret that output as Franklin markdown), you can use this to help with templating.
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
`````md
|
||||||
|
```julia:./ex
|
||||||
|
#hideall
|
||||||
|
for name in ("Shinzo", "Donald", "Angela", "Christine")
|
||||||
|
println("""
|
||||||
|
@@card
|
||||||
|
### $name
|
||||||
|
![]("$(lowercase(name)).jpg")
|
||||||
|
@@
|
||||||
|
""")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
\textoutput{./ex}
|
||||||
|
`````
|
||||||
|
|
||||||
|
Generates
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="card"><h3 id="shinzo"><a href="/index.html#shinzo">Shinzo</a></h3> <img src="shinzo.jpg" alt="" /></div>
|
||||||
|
<div class="card"><h3 id="donald"><a href="/index.html#donald">Donald</a></h3> <img src="donald.jpg" alt="" /></div>
|
||||||
|
<div class="card"><h3 id="angela"><a href="/index.html#angela">Angela</a></h3> <img src="angela.jpg" alt="" /></div>
|
||||||
|
<div class="card"><h3 id="christine"><a href="/index.html#christine">Christine</a></h3> <img src="christine.jpg" alt="" /></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to insert Plotly plots?
|
||||||
|
|
||||||
|
**Reference**: [issue 322](https://github.com/tlienart/Franklin.jl/issues/322).
|
||||||
|
|
||||||
|
See [this tutorial](/extras/plotly/) for a way to do this.
|
|
@ -0,0 +1,55 @@
|
||||||
|
@def hascode = true
|
||||||
|
|
||||||
|
# FAQ - Troubleshooting
|
||||||
|
|
||||||
|
This page is about some of the known errors you may encounter when using Franklin and how to deal with them.
|
||||||
|
If you encounter an error that is not mentioned here, then it's probably a bug and it would be great if you could open an issue!
|
||||||
|
|
||||||
|
\toc
|
||||||
|
|
||||||
|
## Error on interruption
|
||||||
|
|
||||||
|
You may (rarely) get an an error thrown at you when interrupting the server with `<CTRL>+C`, particularly when using Juno.
|
||||||
|
There are a couple of reasons this may happen, both unrelated to Franklin.
|
||||||
|
|
||||||
|
### Juno
|
||||||
|
|
||||||
|
Juno (very rarely) crashes if you coincidentally press `<CTRL>+C` while Juno is doing something in the background (Juno issue [#309](https://github.com/JunoLab/Juno.jl/issues/309)).
|
||||||
|
|
||||||
|
The stacktrace you will see will seem particularly obscure, for instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
InterruptException:
|
||||||
|
_string_n at string.jl:60 [inlined]
|
||||||
|
StringVector at iobuffer.jl:31 [inlined]
|
||||||
|
#IOBuffer#320(::Bool, ::Bool, ::Nothing, ::Bool, ::Int64, ::Int64, ::Type{Base.GenericIOBuffer{Array{UInt8,1}}}) at iobuffer.jl:114
|
||||||
|
(...)
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
julia> "miniERROR: InterruptException:
|
||||||
|
Stacktrace:
|
||||||
|
[1] poptaskref(::Base.InvasiveLinkedListSynchronized{Task}) at ./task.jl:564
|
||||||
|
[2] wait() at ./task.jl:591
|
||||||
|
(...)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solution**: ignore the error, kill then restart the server or, failing that, kill and restart Julia.
|
||||||
|
|
||||||
|
### Not-Juno
|
||||||
|
|
||||||
|
The [`LiveServer.jl`](https://github.com/asprionj/LiveServer.jl) package, which handles the live-serving of the files, is based upon [`HTTP.jl`](https://github.com/asprionj/LiveServer.jl).
|
||||||
|
The latter has a fairly complex codebase with a number of asynchronous tasks and is known to sometimes crash in (somewhat) mysterious ways.
|
||||||
|
|
||||||
|
If the stacktrace mentions `uv_write`, `uv_write_async`, `libuv` or something of the sorts, then this is an example of _known but mysterious way_.
|
||||||
|
|
||||||
|
Like the "Juno" case, these errors are caused when you happen to press interrupt just as the package was doing something important in the background.
|
||||||
|
This is very rare but can happen and you can safely ignore it.
|
||||||
|
|
||||||
|
**Solution**: ignore the error, kill then restart the server or, failing that, kill and restart Julia.
|
||||||
|
|
||||||
|
## IOStream error
|
||||||
|
|
||||||
|
See the comment about HTTP.jl in the [subsection above](#Not-Juno-1).
|
|
@ -0,0 +1,50 @@
|
||||||
|
@def hascode=false
|
||||||
|
|
||||||
|
<!--
|
||||||
|
reviewed: 20/12/19
|
||||||
|
-->
|
||||||
|
|
||||||
|
# FAQ - Meta
|
||||||
|
|
||||||
|
## Why bother with yet another SSG?
|
||||||
|
|
||||||
|
There is a [multitude of static site generators](https://www.staticgen.com/) out there... is this one worth your time?
|
||||||
|
|
||||||
|
I didn't start working on Franklin hoping to "beat" mature and sophisticated generators like Hugo or Jekyll.
|
||||||
|
Rather, I had been using Jacob Mattingley's much simpler [Jemdoc](http://jemdoc.jaboc.net/using.html) package in Python with Wonseok Shin's [neat extension](https://github.com/wsshin/jemdoc_mathjax) for MathJax support.
|
||||||
|
|
||||||
|
I liked that Jemdoc+Mathjax was simple to use and didn't require a lot of web-dev skills to get going.
|
||||||
|
That's how I got the idea of doing something similar in Julia, hopefully improving on the few things I didn't like such as the lack of support for live-rendering preview or the speed of page generation.
|
||||||
|
|
||||||
|
That being said, if you just want a blogging generator mostly for text and pictures, then Franklin may not be the tool for you.
|
||||||
|
If you want to host a technical blog with maths, code blocks, and would like some easy and reproducible control over elements, then Franklin could help you (feel free to [open an issue](https://github.com/tlienart/Franklin.jl/issues/new) to see if Franklin is right for you).
|
||||||
|
|
||||||
|
### Why not Pandoc?
|
||||||
|
|
||||||
|
[Pandoc](https://pandoc.org/) is a very different beast.
|
||||||
|
Franklin's aim was never to provide a full-fledged LaTeX to HTML conversion (which Pandoc does).
|
||||||
|
Rather, Franklin supports standard markdown **and** the definition of commands following a LaTeX-like syntax.
|
||||||
|
These commands can make the use of repeated elements in your website significantly easier to use and maintain.
|
||||||
|
|
||||||
|
Further, Pandoc does not deal with the generation of a full website with things like live-previews, code evaluation etc.
|
||||||
|
|
||||||
|
### Why write a markdown parser?
|
||||||
|
|
||||||
|
I suspect many computer scientists or similar types will agree that _parsing_ is an interesting topic.
|
||||||
|
Franklin provided an incentive to think hard about how to parse extended markdown efficiently and while I'd definitely not dare to say that the parser is very good, it does a decent job and I learned a lot coding it.
|
||||||
|
|
||||||
|
In particular, processing LaTeX-like commands which can be re-defined and should be resolved recursively, proved pretty interesting (and sometimes a bit tricky).
|
||||||
|
|
||||||
|
Initially Franklin was heavily reliant upon the Julia `Markdown` package (part of the `stdlib`) which can convert markdown to HTML but, over time, this changed as Franklin gained the capacity to parse a broader set of Markdown as well as extensions.
|
||||||
|
|
||||||
|
### Did you know?
|
||||||
|
|
||||||
|
Franklin was initially named "_JuDoc_" which happened to be a [fairly obscure saint](https://en.wikipedia.org/wiki/Judoc) (I definitely did not know that before registering the package). The name was meant to be close to *Jemdoc* from which the initial inspiration for this package comes and, of course, to hint at the fact that it was in Julia.
|
||||||
|
After being kindly told that the name was awkward, I received great suggestion and we ended up renaming the package Franklin to honour
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
- [Rosalind Franklin](https://en.wikipedia.org/wiki/Rosalind_Franklin), an English chemist who contributed to the discovery of the structure of DNA, and
|
||||||
|
- [Benjamin Franklin](https://en.wikipedia.org/wiki/Benjamin_Franklin), an american polymath and one of the Founding Fathers.
|
||||||
|
@@
|
||||||
|
|
||||||
|
There's also happens to be a turtle and a US president with that name but that's mostly fortuitous.
|
|
@ -0,0 +1,7 @@
|
||||||
|
@def title = "Search ⋅ Franklin"
|
||||||
|
|
||||||
|
## Search
|
||||||
|
|
||||||
|
Number of results found: ~~~<span id="resultCount"></span>~~~
|
||||||
|
|
||||||
|
~~~<div id="searchResults"></div>~~~
|
|
@ -0,0 +1,66 @@
|
||||||
|
<!--
|
||||||
|
reviewed: 22/12/19
|
||||||
|
-->
|
||||||
|
|
||||||
|
@def hascode = true
|
||||||
|
|
||||||
|
# Classes
|
||||||
|
|
||||||
|
\blurb{Use Franklin's classes or add your own.}
|
||||||
|
|
||||||
|
\lineskip
|
||||||
|
|
||||||
|
By now you know that you can add `@@divname ... @@` anywhere you want in your content in order to define an environment and style it.
|
||||||
|
Below we detail the default classes as well as some tricks that can be useful to style your content.
|
||||||
|
|
||||||
|
## Franklin's classes
|
||||||
|
|
||||||
|
@@lalignb
|
||||||
|
| Name | Function |
|
||||||
|
| ------ | ---- |
|
||||||
|
| `franklin-content` | wraps around the content of a page, so when a `mypage.md` is converted to some html, it gets inserted in the scaffolding as `<div class="franklin-content"> some html </div>` (\*)
|
||||||
|
| `franklin-toc` | wraps around the inserted table of contents
|
||||||
|
| `fnref` | wraps around a footnote reference
|
||||||
|
| `fndef` | wraps around footnote definitions
|
||||||
|
| `fndef-content` | wraps around the content of footnote definitions
|
||||||
|
| `fndef-backref` | wraps around the back-reference of a footnote definition
|
||||||
|
@@
|
||||||
|
|
||||||
|
**Notes**:\\
|
||||||
|
\smindent{(\*)} \smnote{you can change this name setting the global page variable `div_content` in your `config.md`}.\\
|
||||||
|
|
||||||
|
## Simple tricks
|
||||||
|
|
||||||
|
As soon as you're using a style more than once, it makes sense to create it as a command.
|
||||||
|
This makes it much easier to maintain and re-use.
|
||||||
|
For instance, consider the following simple examples:
|
||||||
|
|
||||||
|
```html
|
||||||
|
\newcommand{\blurb}[1]{
|
||||||
|
~~~
|
||||||
|
<span style="font-size:24px;font-weight:300;">!#1</span>
|
||||||
|
~~~
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
\newcommand{\note}[1]{@@note @@title ⚠ Note@@ @@content #1 @@ @@}
|
||||||
|
```
|
||||||
|
|
||||||
|
Further, you can pass the style as an argument:
|
||||||
|
|
||||||
|
\newcommand{\spstyle}[2]{~~~<span style="#1">#2</span>~~~}
|
||||||
|
|
||||||
|
```html
|
||||||
|
\newcommand{\spstyle}[2]{~~~<span style="#1">#2</span>~~~}
|
||||||
|
```
|
||||||
|
|
||||||
|
and for instance:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
\spstyle{font-variant:small-caps;font-size:15px;color:cornflowerblue}{formatted text}
|
||||||
|
```
|
||||||
|
|
||||||
|
gives you: \spstyle{font-variant:small-caps;font-size:15px;color:cornflowerblue}{formatted text}.
|
||||||
|
|
||||||
|
In fact, that one is pre-defined in Franklin, `\style{style}{text}` does precisely that.
|
|
@ -0,0 +1,247 @@
|
||||||
|
@def hascode = true
|
||||||
|
|
||||||
|
<!--
|
||||||
|
reviewed: 22/12/19
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Templates
|
||||||
|
|
||||||
|
\blurb{Start from one of the template or build your own.}
|
||||||
|
|
||||||
|
\lineskip
|
||||||
|
|
||||||
|
\toc
|
||||||
|
|
||||||
|
\lineskip
|
||||||
|
|
||||||
|
The pre-defined templates that are currently available in Franklin with the `newsite` function can be viewed ~~~<a href="https://tlienart.github.io/FranklinTemplates.jl/" target="_blank" rel="noopener noreferrer">here</a>~~~ (_opens in a new tab_).
|
||||||
|
|
||||||
|
## Adapting a theme to Franklin
|
||||||
|
|
||||||
|
\note{If you end up doing this, please consider making a PR to [FranklinTemplates](https://github.com/tlienart/FranklinTemplates.jl)!}
|
||||||
|
|
||||||
|
On this page, I'll take [Jemdoc's website layout](http://jemdoc.jaboc.net/) and show how it can be adapted to be a working Franklin template.
|
||||||
|
This will hopefully also show you how to adapt / modify an existing template.
|
||||||
|
|
||||||
|
Jemdoc's layout looks like this:
|
||||||
|
|
||||||
|
![](/assets/jemdoc/jemdoc1.png)
|
||||||
|
|
||||||
|
### Getting started
|
||||||
|
|
||||||
|
In order to get a blueprint for the folder etc, let's first create a Franklin site with the `basic` template:
|
||||||
|
|
||||||
|
```julia-repl
|
||||||
|
julia> newsite("jemdoc", template="basic")
|
||||||
|
```
|
||||||
|
|
||||||
|
You can serve the site in order to see the modifications directly in your browser which can be useful to fine tune the port of the layout.
|
||||||
|
|
||||||
|
We will need to provide the appropriate stylesheet in `_css/` and adjust the layout part in `_layout/`.
|
||||||
|
|
||||||
|
### Adapting the head and foot
|
||||||
|
|
||||||
|
The file `_html_parts/head.html` is the most important one you will have to adjust.
|
||||||
|
|
||||||
|
Let us first change the name of the main stylesheet `_css/basic.css` to `_css/jemdoc.css` which is more appropriate.
|
||||||
|
The reference to the stylesheet in `head.html` consequently has to be changed to mention `jemdoc.css` instead of `basic.css`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<link rel="stylesheet" href="/css/jemdoc.css">
|
||||||
|
```
|
||||||
|
|
||||||
|
The following step is fairly simple:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
1. look at the original html code,
|
||||||
|
2. copy whatever is relevant that comes before the content into `head.html`.
|
||||||
|
@@
|
||||||
|
|
||||||
|
Let's do this gradually.
|
||||||
|
The top of the original HTML can be ignored at this point so we can start modifying starting after `</head>`.
|
||||||
|
|
||||||
|
Jemdoc's body starts with a Google analytics script which I'll ignore as well.
|
||||||
|
We then have effectively one big table element.
|
||||||
|
Stripped from its content and simplified it looks like:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<table id="tlayout">
|
||||||
|
<tr valign="top">
|
||||||
|
<td id="layout-menu">
|
||||||
|
<div class="menu-category">jemdoc</div>
|
||||||
|
<div class="menu-item"><a href="/" class="current">home</a></div>
|
||||||
|
<div class="menu-category">topics</div>
|
||||||
|
<div class="menu-item"><a href="/menu1/">Menu 1</a></div>
|
||||||
|
<div class="menu-item"><a href="/menu2/">Menu 2</a></div>
|
||||||
|
<div class="menu-item"><a href="/menu3/">Menu 3</a></div>
|
||||||
|
</td>
|
||||||
|
<td id="layout-content">
|
||||||
|
<p> CONTENT HERE </p>
|
||||||
|
<div id="footer">
|
||||||
|
<div id="footer-text">
|
||||||
|
Page generated by <a href="http://jemdoc.jaboc.net/">jemdoc</a>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that I've already filled in the `href=` in the links to sub-menus.
|
||||||
|
|
||||||
|
The "`CONTENT HERE`" part is where what Franklin generates from Markdown will go.
|
||||||
|
Therefore, anything that is *after* that should go in `foot.html`; in our current case:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- ... -->
|
||||||
|
<div id="footer">
|
||||||
|
<div id="footer-text">
|
||||||
|
Page generated by <a href="http://jemdoc.jaboc.net/">jemdoc</a>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
```
|
||||||
|
|
||||||
|
That's basically it (though we still have to modify the stylesheet of course).
|
||||||
|
The `head.html` should be adapted to:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
{{if hasmath}} {{insert head_katex.html }} {{end}}
|
||||||
|
{{if hascode}} {{insert head_highlight.html }} {{end}}
|
||||||
|
<link rel="stylesheet" href="/css/franklin.css">
|
||||||
|
<link rel="stylesheet" href="/css/jemdoc.css">
|
||||||
|
<link rel="icon" href="/assets/infra/favicon.png">
|
||||||
|
{{isdef title}} <title>{{fill title}}</title> {{end}}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table id="tlayout">
|
||||||
|
<tr valign="top">
|
||||||
|
<td id="layout-menu">
|
||||||
|
<div class="menu-category">jemdoc</div>
|
||||||
|
<div class="menu-item"><a href="index.html" class="current">home</a></div>
|
||||||
|
<div class="menu-category">topics</div>
|
||||||
|
<div class="menu-item"><a href="/menu1/">Menu 1</a></div>
|
||||||
|
<div class="menu-item"><a href="/menu2/">Menu 2</a></div>
|
||||||
|
<div class="menu-item"><a href="/menu3/">Menu 3</a></div>
|
||||||
|
</td>
|
||||||
|
<td id="layout-content">
|
||||||
|
|
||||||
|
<!-- Content appended here -->
|
||||||
|
```
|
||||||
|
|
||||||
|
and the `foot.html` should be adapted to:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- CONTENT ENDS HERE -->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{{ if hasmath }}
|
||||||
|
{{ insert foot_katex.html }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if hascode }}
|
||||||
|
{{ insert foot_highlight.html }}
|
||||||
|
{{ end }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adapting the stylesheet
|
||||||
|
|
||||||
|
By now the page looks pretty bad:
|
||||||
|
|
||||||
|
![](/assets/jemdoc/jemdoc2.png)
|
||||||
|
|
||||||
|
the content is not centred in its box and overflows on the right, the menu looks ridiculous, time to do some CSS styling!
|
||||||
|
|
||||||
|
Let's start by removing everything from `_css/jemdoc.css`.
|
||||||
|
Most of what's in there was used for the styling of the top navbar which we don't have anymore (note that the styling of the content itself is in `franklin.css`, don't change that for now; note also that `jemdoc.css` is loaded *after* `franklin.css` so that you can overwrite the styles there).
|
||||||
|
|
||||||
|
Let's now just copy paste the content of the [two](http://jemdoc.jaboc.net/jemdoc.css) [original](http://jemdoc.jaboc.net/jacob.css) stylesheets into ours and hope for the best, we may have some fine-tuning to do after this.
|
||||||
|
|
||||||
|
Doing nothing else than copy pasting already helps a lot:
|
||||||
|
|
||||||
|
![](/assets/jemdoc/jemdoc3.png)
|
||||||
|
|
||||||
|
A few things should be fixed:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
1. there's too little space at the top
|
||||||
|
1. the menu is a bit too narrow and there's a bit too much space between the menu and the content
|
||||||
|
1. there's not enough space after `<pre>` blocks
|
||||||
|
@@
|
||||||
|
|
||||||
|
#### Fixing spacing
|
||||||
|
|
||||||
|
Firefox or Chrome/ium's excellent dev-tools are super helpful to fine tune stylesheets.
|
||||||
|
Here things are pretty straightforward though.
|
||||||
|
|
||||||
|
First, we need to add vertical padding above `<h1>` level title:
|
||||||
|
|
||||||
|
```css
|
||||||
|
h1 { padding-top: 2em; }
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, let's widen the menu a little
|
||||||
|
|
||||||
|
```css
|
||||||
|
td#layout-menu {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 25px;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
and let's reduce the padding on the left of the `franklin-content` element:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.franklin-content { padding-left: 5%; }
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, in the original stylesheet there is this element:
|
||||||
|
|
||||||
|
```css
|
||||||
|
pre {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
which you can just remove to have a bit more space around code blocks.
|
||||||
|
|
||||||
|
There's probably still things that could be done to improve the layout overall (and make it more responsive!) but we'll leave it at that.
|
||||||
|
|
||||||
|
![](/assets/jemdoc/jemdoc4.png)
|
||||||
|
|
||||||
|
### Adjusting other files
|
||||||
|
|
||||||
|
Here we don't need to adjust anything else but, in general, you might want to adjust the other pages:
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
* `head_highlight`, `head_katex`, `foot_highlight` and `foot_katex` are probably best left as they are, they will be appended if need be to pages (see in `head` and `foot` the `{{if hasmath}}` and `{{if hascode}}` blocks)
|
||||||
|
* `page_foot` you may want to change, it defines what goes at the bottom of the `.franklin-content` div.
|
||||||
|
@@
|
||||||
|
|
||||||
|
By default `page_foot` looks like
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="page-foot">
|
||||||
|
<div class="copyright">
|
||||||
|
© {{ fill author }}. Last modified: {{ fill fd_mtime }}. Website built with <a href="https://github.com/tlienart/Franklin.jl">Franklin.jl</a>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
It should be fairly straightforward to adapt that to your needs.
|
||||||
|
|
||||||
|
## Making a PR to the theme repo
|
||||||
|
|
||||||
|
Let's say you've built your own template and are pretty happy with the result and you'd like to share it for other users, great, thanks!
|
||||||
|
|
||||||
|
Please follow [these instructions](https://github.com/tlienart/FranklinTemplates.jl#fixingadding-a-template).
|
|
@ -0,0 +1,313 @@
|
||||||
|
|
||||||
|
<!--
|
||||||
|
reviewed: 18/4/20
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Divs and Commands
|
||||||
|
|
||||||
|
\blurb{Style your content quickly and easily with custom divs, make everything reproducible and maintainable with commands.}
|
||||||
|
|
||||||
|
\lineskip
|
||||||
|
|
||||||
|
\toc
|
||||||
|
|
||||||
|
## Div blocks
|
||||||
|
|
||||||
|
In order to locally style your content, you can use `@@divname ... @@` which will wrap the content in a `<div class="divname"> ... </div>` block which you can then style as you wish in your CSS stylesheet.
|
||||||
|
For instance, you may want to highlight some content with a light yellow background:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
Some text then
|
||||||
|
@@important
|
||||||
|
Some important content
|
||||||
|
@@
|
||||||
|
```
|
||||||
|
|
||||||
|
and then, in your CSS, you could use
|
||||||
|
|
||||||
|
```css
|
||||||
|
.important {
|
||||||
|
background-color: lemonchiffon;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
which will look like
|
||||||
|
|
||||||
|
@@important
|
||||||
|
Some important content
|
||||||
|
@@
|
||||||
|
|
||||||
|
### Nesting
|
||||||
|
|
||||||
|
Such div blocks can be nested as in standard HTML.
|
||||||
|
The distinction with inserting raw HTML div blocks with the `~~~...~~~` syntax is that the content of div blocks is processed as well (i.e.: can contain Franklin markdown):
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
@@important
|
||||||
|
Some text;
|
||||||
|
@@silly-formatting
|
||||||
|
some **silly** text with $2x+4=y$.
|
||||||
|
@@
|
||||||
|
and more text.
|
||||||
|
@@
|
||||||
|
```
|
||||||
|
|
||||||
|
@@important
|
||||||
|
Some text;
|
||||||
|
@@silly-formatting
|
||||||
|
some **silly** text with $2x+4=y$.
|
||||||
|
@@
|
||||||
|
and more text.
|
||||||
|
@@
|
||||||
|
|
||||||
|
## LaTeX-like commands
|
||||||
|
|
||||||
|
Franklin allows the definition of commands using a LaTeX-like syntax.
|
||||||
|
This can be particularly useful for repeating elements or styling inside or outside of maths environment.
|
||||||
|
|
||||||
|
To define a command, you **must** use the following syntax:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
\newcommand{\name}[...]{...}
|
||||||
|
-1- -2- -3-
|
||||||
|
```
|
||||||
|
|
||||||
|
where:
|
||||||
|
|
||||||
|
@@flist
|
||||||
|
1. the first bracket is the _command name_, starting with a backslash and _only made out of letters_ (lower or upper case),
|
||||||
|
1. the second (optional) bracket indicates the _number of arguments_, if none is set the command does not take arguments,
|
||||||
|
1. the third bracket indicates the _definition of the command_ calling `#k` to insert the $k$-th argument.
|
||||||
|
@@
|
||||||
|
|
||||||
|
As in LaTeX, command definitions can be anywhere as long as they appear before they are used.
|
||||||
|
If you want a command to be available on all your pages, put the definition in the `config.md` file.
|
||||||
|
|
||||||
|
\note{Franklin currently cannot just take the content of a `.tex` document and convert it, this may be (partially) supported in the future if it is deemed useful. Mainly it would require pre-defining all standard commands such as `\textbf`, `\section`, etc.}
|
||||||
|
|
||||||
|
### Math examples
|
||||||
|
|
||||||
|
If you end up writing a lot of equations on your site, defining commands can become rather useful:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
\newcommand{\R}{\mathbb R}
|
||||||
|
|
||||||
|
Let $f:\R\to\R$ a function...
|
||||||
|
```
|
||||||
|
|
||||||
|
\newcommand{\R}{\mathbb R}
|
||||||
|
Let $f:\R\to\R$ a function...
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
\newcommand{\scal}[1]{\left\langle #1 \right\rangle}
|
||||||
|
|
||||||
|
$$ \mathcal W_\psi[f] = \int_\R f(s)\psi(s)\mathrm{d}s = \scal{f,\psi} $$
|
||||||
|
```
|
||||||
|
|
||||||
|
\newcommand{\scal}[1]{\left\langle #1 \right\rangle}
|
||||||
|
$$ \mathcal W_\psi[f] = \int_\R f(s)\psi(s)\mathrm{d}s = \scal{f,\psi} $$
|
||||||
|
|
||||||
|
### Text examples
|
||||||
|
|
||||||
|
Commands can also be useful outside of maths environment.
|
||||||
|
For instance, you could define a command to quickly set the style of some text:
|
||||||
|
|
||||||
|
```html
|
||||||
|
\newcommand{\styletext}[2]{~~~<span style="#1">#2</span>~~~}
|
||||||
|
|
||||||
|
Here is \styletext{color:magenta;font-size:14px;}{formatted text}.
|
||||||
|
```
|
||||||
|
|
||||||
|
\newcommand{\styletext}[2]{~~~<span style="#1">#2</span>~~~}
|
||||||
|
|
||||||
|
Here is \styletext{color:magenta;font-size:14px;font-variant:small-caps;}{formatted text}.
|
||||||
|
|
||||||
|
### Nesting examples
|
||||||
|
|
||||||
|
Commands are resolved recursively which means that they can be nested and their definition can contain further Franklin markdown (again this is similar to how LaTeX works).
|
||||||
|
|
||||||
|
Consider for instance:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
\newcommand{\norm}[2]{\left\|#1\right\|_{#2}}
|
||||||
|
\newcommand{\anorm}[1]{\norm{#1}{1}}
|
||||||
|
\newcommand{\bnorm}[1]{\norm{#1}{2}}
|
||||||
|
|
||||||
|
Let $x\in\R^n$, there exists $0 < C_1 \le C_2$ such that
|
||||||
|
|
||||||
|
$$ C_1 \anorm{x} \le \bnorm{x} \le C_2\anorm{x}. $$
|
||||||
|
```
|
||||||
|
|
||||||
|
\newcommand{\norm}[2]{\left\|#1\right\|_{#2}} <!--_-->
|
||||||
|
\newcommand{\anorm}[1]{\norm{#1}{1}}
|
||||||
|
\newcommand{\bnorm}[1]{\norm{#1}{2}}
|
||||||
|
|
||||||
|
Let $x\in\R^n$, there exists $0 < C_1 \le C_2$ such that
|
||||||
|
|
||||||
|
$$ C_1 \anorm{x} \le \bnorm{x} \le C_2\anorm{x}. $$
|
||||||
|
|
||||||
|
As indicated earlier, commands can contain further Franklin markdown that is processed recursively.
|
||||||
|
For example, here is a more sophisticated example of a "definition" command such that this:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
\definition{angle between vectors}{
|
||||||
|
Let $x, y \in \R^n$ and let $\scal{\cdot, \cdot}$ denote
|
||||||
|
the usual inner product. Then, the angle $\theta$ between
|
||||||
|
$x$ and $y$ is given by
|
||||||
|
$$ \cos(\theta) = {\scal{x,y}\over \scal{x,x} \scal{y,y}}. $$
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
leads to this:
|
||||||
|
|
||||||
|
\newcommand{\definition}[2]{@@definition **Definition**: (_!#1_) #2 @@}
|
||||||
|
|
||||||
|
\definition{angle between vectors}{
|
||||||
|
Let $x, y \in \R^n$ and let $\scal{\cdot, \cdot}$ denote
|
||||||
|
the usual inner product. Then, the angle $\theta$ between $x$ and $y$ is
|
||||||
|
given by $$ \cos(\theta) = {\scal{x,y}\over \scal{x,x} \scal{y,y}}. $$
|
||||||
|
}
|
||||||
|
|
||||||
|
To do this, you would define the command:
|
||||||
|
|
||||||
|
```html
|
||||||
|
\newcommand{\definition}[2]{
|
||||||
|
@@definition
|
||||||
|
**Definition**: (_!#1_)
|
||||||
|
#2
|
||||||
|
@@
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
and specify the styling of the `definition` div in your CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.definition {
|
||||||
|
background-color: aliceblue;
|
||||||
|
border-left: 5px solid cornflowerblue;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Whitespaces
|
||||||
|
|
||||||
|
In a Franklin `newcommand`, to refer to an argument you can use `#k` or `!#k`.
|
||||||
|
There is a small difference: the first one _introduces a space_ left of the argument while the second one does not.
|
||||||
|
|
||||||
|
In general whitespaces are irrelevant and will not show up on the rendered webpage so that the usual `#k` is the recommended usage.
|
||||||
|
This helps avoid some ambiguities when resolving a chain of nested commands.
|
||||||
|
|
||||||
|
There are however cases where you do not want this because the whitespace does, in fact, show up.
|
||||||
|
In such cases use `!#k` (assuming it's not ambiguous).
|
||||||
|
|
||||||
|
Consider for instance:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
\newcommand{\pathwith}[1]{`/usr/local/bin/#1`}
|
||||||
|
\newcommand{\pathwithout}[1]{`/usr/local/bin/!#1`}
|
||||||
|
|
||||||
|
Here \pathwith{hello} is no good whereas \pathwithout{hello} is.
|
||||||
|
```
|
||||||
|
|
||||||
|
\newcommand{\pathwith}[1]{`/usr/local/bin/#1`}
|
||||||
|
\newcommand{\pathwithout}[1]{`/usr/local/bin/!#1`}
|
||||||
|
|
||||||
|
Here \pathwith{hello} is no good whereas \pathwithout{hello} is.
|
||||||
|
|
||||||
|
### Defining commands globally
|
||||||
|
|
||||||
|
If you define commands on a page, the command will be available only on that page; if you wish to define a command that is available on all pages, you should put the definition of the command in your `config.md` file.
|
||||||
|
|
||||||
|
## Hyper-references
|
||||||
|
|
||||||
|
Three types of hyper-references are supported in Franklin:
|
||||||
|
|
||||||
|
@@flist
|
||||||
|
1. for equations in display mode,
|
||||||
|
1. for references (bibliography),
|
||||||
|
1. for specific anchor points in the page.
|
||||||
|
@@
|
||||||
|
|
||||||
|
The syntax for all three is close to that of standard LaTeX.
|
||||||
|
|
||||||
|
To style the appearance of the maths or bib links in CSS, use `.franklin-content.eqref a` and `.franklin-content.bibref a` classes; for instance:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.franklin-content .eqref a {color: blue;}
|
||||||
|
.franklin-content .bibref a {color: green;}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Equations
|
||||||
|
|
||||||
|
To label an equation, just use `\label{some label}` in the math environment and, to refer to it, use `\eqref{some label}`:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
Some equation:
|
||||||
|
|
||||||
|
$$\exp(i\pi) + 1 = 0 \label{a cool equation}$$
|
||||||
|
|
||||||
|
and you can refer to it in the text: equation \eqref{a cool equation}.
|
||||||
|
```
|
||||||
|
|
||||||
|
As in LaTeX, you can refer to several equations in one shot by separating names with commas: `\eqref{some label, some other}` (that also means you cannot use commas in labels).
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
For references, you can use `\biblabel{short}{name}` to declare a reference which will appear as a clickable link `(name)` or `name` and can be referred to with `short`:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
In the text you may refer to \citep{noether15, bezanson17} while in a bibliography section you would have
|
||||||
|
|
||||||
|
* \biblabel{noether15}{Noether (1915)} **Noether**, Korper und Systeme rationaler Funktionen, 1915.
|
||||||
|
* \biblabel{bezanson17}{Bezanson et al. (2017)} **Bezanson**, **Edelman**, **Karpinski** and **Shah**, [Julia: a fresh approach to numerical computing](https://julialang.org/publications/julia-fresh-approach-BEKS.pdf), SIAM review 2017.
|
||||||
|
```
|
||||||
|
|
||||||
|
The `name` argument therefore corresponds to how the bibliography reference will appear in the text.
|
||||||
|
In the case above, the text will lead to
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
... refer to (Noether (1915), Bezanson et al. (2017)) while ...
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use either
|
||||||
|
|
||||||
|
@@tlist
|
||||||
|
* `\cite{short1, short2}` or `\citet{short3}`: which will not add parentheses around the link(s),
|
||||||
|
* `\citep{short4, short5}`: which will add parentheses around the link(s).
|
||||||
|
@@
|
||||||
|
|
||||||
|
As in LaTeX, if the reference is undefined on the page, the command will be replaced by **(??)**.
|
||||||
|
|
||||||
|
### Anchor points
|
||||||
|
|
||||||
|
You can specify anchor points on the page using `\label{name of the anchor}` anywhere on the page _outside_ of maths environment.
|
||||||
|
This will insert an anchor:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<a id="name-of-the-anchor"></a>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can subsequently link to it on the same page:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
[link to it](#name-of-the-anchor)
|
||||||
|
```
|
||||||
|
|
||||||
|
or from another page by prepending it with the path to the page, for instance:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
[link to it](/index.html#name-of-the-anchor)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note also that all section headers are anchor points for instance
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
### Some subtitle
|
||||||
|
```
|
||||||
|
|
||||||
|
can be linked to with `#some-subtitle`.
|
||||||
|
If there are multiple headers with the same name, the second and subsequent ones can be referred to with `#some-subtitle__2`, `#some-subtitle__3` etc. (note the double underscore).
|