Caltech Library logo

The Basics

mkpage uses Pandoc’s template engine to render content. This template is documented on the Pandoc.

Basic element

A templated data element is wrapped in a dollar sign, opening curly bracket, the data name, and closing curly bracket. A template that says “Hello” followed by a value named “world” would look something like this

    Hello ${world}

We can use the template to say Hello to “Georgina”

    echo 'Hello ${world}' > hello-world.tmpl
    mkpage "world=text:Georgina" hello-world.tmpl

Running these two command should result in output like

    Hello Georgina

The line with the echo is just creating our template and saving it as the file “hello-world.tmpl”. In the template the only special part is ${world}. “world” is a variable will be replaced by something we define. In the line with mkpage we define the value for “world” as plain text. Note we don’t need to prefix “world” in the command line. The ‘text:’ before the variable name to indicate the type of object, in this case plain text. The line tells the template to replace ${world} with the text value “Georgina”. The last part of the command instructs mkpage to use our hello-world.tmpl template.

If we did not include world=… with the mkpage command using the hello-world.tmpl template mkpage would return output like

    Hello

If we included other key/value pairs not mentioned in the template they would be silently ignored.

If we made a typo in hello-world.tmpl then we would see an error message from the pandoc template engine. NOTE: “5 PandocTemplateError” is the one that tells you you have a template error.

Try the following to get a feel for how key/value pairs work with mkpage. The first two will render but display Hello. The first example fails because no value is provided and the second fails because the value provided doesn’t match what is in the template (notice the typo “wrold” vs. “world”). the next one will display an error because text: wasn’t included on the value side of the key/value pair. By default mkpage assumes the value is refering to a file and in this case can’t find the file Georgina in your current directory. The last two will display Hello Georgina should display since the value for “world” is provided. The last one just ignores “Name=text:Fred” because “Name” isn’t found in the template.

    mkpage hello-world.tmpl
    mkpage "wrold=text:Georgina" hello-world.tmpl
    mkpage "world=Georgina" hello-world.tmpl
    mkpage "world=text:Georgina" "name=text:Fred" hello-world.tmpl
    mkpage "world=text:Georgina" hello-world.tmpl

Conditional elements

Pandoc templates have conditional elements. ${if()} … ${endif} and ${for()} … ${endfor} are simimlar. The “if” will display the contents if the variable passing to the “if” function is non-empty. If the object is an array it will concatenate the elements together, if it is a map then it will display true. The “for” function is similar but iterates over the elements provided and those elements can be accessed with an alias of ${it}. See the Pandoc Manual for details.

   ${if(title)}Title: ${title}${endif}

or using “for”

    By ${for(authors)}${it}$sep$, ${endfor}

Let’s create a template file with both these statements called title-demo.tmpl and run the mkpage command.

    echo '${if(title)}Title: ${title}${endif}' > title-demo.tmpl
    echo 'By ${for(authors)}${it}$sep$ and ${endif}' >> title-demo.tmpl 
    mkpage 'title=text:This is a title demo' \
           'authors=json:[ 'Jane', 'Carol' ]' \
           title-demo.tmpl

The output should look like

    Title: This is a title demo
    By Jane and Carol

In the first line with the if we use “title” as the variable, just like “world” in our first example. The second line uses a for to iterate over authors names and insert an “and” between them. What happens if you run this command?

    mkpage title-demo.tmpl

This produces two lines of output that look something . The reason we don’t see something like

    By

We see the “By” because it is outside the for loop, but we don’t see a title because “Title:” is inside the if block.

Template and sub templates

Pandoc provides for a simple mechanism to include sub templates. If the same directory as your main template any template can be included as its own function. This is easier to see in practice than to describe.

Create two templates, “header.tmpl” and “footer.tmpl”.

This would be the header.

   <header>${if(title)}<h1>${title}</h1>${endif}</header>

This would be for the footer.

    <footer>By ${for(authors)}${it}$sep$, ${endfor}</footer>

Now create a third temaplte called “main.tmpl”

   ${header()}
   <section>
   This is the title: ${title}
   <p>
   Authors are: ${authors[, ]}
   </section>
   ${footer()}

Now run our mkpage command providing our “title” and “authors” values and the template named “main.tmpl”.

    mkpage 'title=text:This is a big template project' \
           'authors=text:Me, Myself and I' \
           main.tmpl

This output should look like

    <header><h1>Hi there</h1></header><section>
    This is the title: Hi there
    <p>
    Authors are: Me, Myself and I
    </section>
    <footer>

In this case “header.tmpl” and “footer.tmpl” are found because they are in the same directory as “main.tmpl”.

Content formats and data sources

mkpage understands several content formats

It also supports three data sources

Content type is evaluated, transformed (if necessary), and sent to the Pandoc template engine.

    This is a plain text string: "${string}"

    Below is a an included file:
    ${file}
    
    Finally below is data from a URL:
    ${url}
    ${end}

Create a text file named hello.md.

    # this is a file

    Hello World!

Type the following

    mkpage "string=text:Hello World" "file=hello.md" \
      "url=https://raw.githubusercontent.com/caltechlibrary/mkpage/master/nav.md" \
      data-source-demo.tmpl

What do you see?

A note about Markdown dialect

mkpage uses Pandoc as its markdown (markup) and template (output) engine.

The markdown processor is invoked for values with the “markdown:” hint prefix, files ending in “.md” extension or URL content with the content type returned as “text/markdown” (i.e. content with a type of “text/plain” does not use the markdown process and is treated as plain text).