Franklin supports two types of special functions:lx_*
andhfun_*
functions. At a high level,lx_*
functions can be used to hijack Franklin's parsing of Markdown whereashfun_*
functions can be used to generate and plug custom HTML.
These functions are to be defined in theutils.jl
file which lies at the same level as theconfig.md
file and complements it. Theymust be named withlx_
orhfun_
followed by a name; for instance:lx_foo
,hfun_bar_baz
are accepted. These functions are defined in plain Julia and can themselves call other functions that would be defined in theutils.jl
file or elsewhere.
Note: often, it is enough to use~~~...~~~
blocks or definenewcommand
s (or both) rather than usehfun_*
andlx_*
; but sometimes it can be very convenient to have a way to just generate things with your own code. For instance, to locally use custom styling of text, Franklin comes with the following command:
\newcommand{\style}[2]{~~~<span style="!#1">!#2</span>~~~}
which allows you to do something like\style{color:red}{hello}
:hello. No need for ahfun_*
orlx_*
function here...
hfun_*
)Ahfun_*
function is a simple way to generate custom and plug custom HTML somewhere.
A parameter-free HTML functionhfun_foo
will have a definition inutils.jl
like
function hfun_foo() # some code here which defines "generated_html" # as a String containing valid HTML return generated_htmlend
this can be called with{{foo}}
either in one of the files inlayout/
or in any of your markdown files.
hfun_foo
⟶foo
. Make sure that the name does not clash with one of thebase HTML function (fill
,insert
, ...) or one of the local or global variables.Working example: here's an example where the function would list the last 3 files in a folder and display them as a list; you can see also see a similar full example used on the JuliaLang websitehere.
function hfun_recentblogposts() list = readdir("blog") filter!(f -> endswith(f, ".md"), list) dates = [stat(joinpath("blog", f)).mtime for f in list] perm = sortperm(dates, rev=true) idxs = perm[1:min(3, length(perm))] io = IOBuffer() write(io, "<ul>") for (k, i) in enumerate(idxs) fi = "/blog/" * splitext(list[i])[1] * "/" write(io, """<li><a href="$fi">Post $k</a></li>\n""") end write(io, "</ul>") return String(take!(io))end
that function can then be called as{{recentblogposts}}
.
You can also have parameters withhfun_*
functions which will allow you to write:
{{fname arg1 arg2}}
the parameters are passed as avector of strings i.e.: in the case above, the function will receive["arg1", "arg2"]
and these strings will need to be further processed by the function.
The procedure is otherwise the same as at the previous point, you just need to define the function like this:
function hfun_bar(params) # params is a Vector{String}, do what you need to # with the individual strings then form some HTML return generated_htmlend
Note that all functions defined inutils.jl
can calllocvar(name)
andglobvar(name)
to retrieve the value associated with a local or global page variable by its name; for instancelocvar("author")
. You may optionally pass adefault
argument that will be returned instead ofnothing
if the variable does not exist, eglocvar(name; default="Not named")
.
lx_*
)Alx_*
function is a way to bypass Franklin's parsing and generate Markdown which will bereprocessed by Franklin (though you can always avoid that by generating HTML directly after wrapping it in~~~
).
This is a more advanced command and you should probably double-check before making use of it as, usually, there will be a simpler way of achieving what you want. Also if you intend to use it, you will want to check outFranklinUtils which provides helper functions for it.
It's harder to come up with meaningful examples as most simple examples will be achievable another way so here we proceed with a dumb example (and will show why it's dumb later).
Let's imagine you want to bypass the way Franklin deals with headers, that you would like to be able to write
\h2{id="foo" title="Bar"}
in order to get
<h2 id="foo">Bar</h2>
You can do this via alx_*
function:
function lx_h2(com, _) # the signature must look like this # leave this first line, it extracts the content of the brace content = Franklin.content(com.braces[1]) # dumb way to recover stuff m = match(r"id\s*=\s*\"(.*?)\"\s*title\s*=\s*\"(.*?)\"", content) id, title = m.captures[1:2] return """~~~<h2 id="$id">$title</h2>~~~"""end
lx_foo
⟶foo
. Make sure that the name does not clash with one of the pre-defined commands (label
,style
, ...).In this case, it would have been simpler to just define this as a simple newcommand:
\newcommand{\h2}[2]{~~~<h2 id="!#1">#2</h2>~~~}
which you would have called\h2{foo}{Bar}
.