### ----------------------------------------------------
### -- Raku::Pod::Render
### -- Licenses: Artistic-2.0
### -- Authors: Richard Hainsworth
### -- File: PodTemplates.md
### ----------------------------------------------------
# Templates needed for a Processed Pod.
>
## Table of Contents
[Template Engine Autodetection](#template-engine-autodetection)  
[Minimum Set](#minimum-set)  
[Test-Templates](#test-templates)  
[Verification utility](#verification-utility)  
[Usage](#usage)  
[Data structures accepted by templates](#data-structures-accepted-by-templates)  
[Structure specification syntax](#structure-specification-syntax)  
[Examples](#examples)  
[Parameters of required templates](#parameters-of-required-templates)  
[Notes](#notes)  
[Custom block parameters](#custom-block-parameters)  
[Notes](#notes)  
[HTML2](#html2)  
[Notes](#notes)  

----
This describes the template set for the ProcessedPod renderer, the templating engines that can be used, the Test-Template functions, and the test-templates verification utility.

The templating part of Raku-Pod-Render is separated into a Templating module `RenderPod::Templating`. It is written to allow for other templating engines to be added. Currently the following Engines are available in this distribution:

*  Mustache

*  Raku Closure (a templating system designed for Raku-Pod-Render)

*  Cro Templates

# Template Engine Autodetection
Templates are written to be interpretted by a templating engine. The Templating module in this distribution has been written to allow for other engines to be added. It is best to look at the module to see how this is done.

The first minimum set of templates is loaded and an autodetect function determines which engine to use. Subsequent templates added by plugins must use the same template engine.

The template engine is determined in two ways:

*  The hash (normally loaded from a file) containing the minimum set of templates may contain the key `_templater`, which must have a String value that is the name of the class implementing the Templating Engine. For the default engines, these are

> **Mustache**  
MustacheTemplater

> **Raku Closure**  
RakuClosureTemplater

> **Cro Templates**  
CroTemplater

# Minimum Set
The minimum set of templates is `block-code comment declarator defn dlist-end dlist-start escaped footnotes format-b format-c format-i format-k format-l format-n format-p format-r format-t format-u format-x glossary heading item list meta unknown-name output para pod raw source-wrap table toc`.

Almost all of these templates expect a [parameter to be rendered](Parameters of required templates.md). The test functions will check the templates for the parameters to be returned.

# Test-Templates
These subs are intended for use in a TAP context. They can be applied as follows

```
use Test;
use RenderPod::Test-Templates;
%templates = EVALFILE "templates/basic-templates.raku";
templates-present %templates, 'basic file contains minimum set of templates';
```
> **multi sub templates-present( Hash %templates, Str $description = 'minimum templates present' )**  
Short for 'are all minimum templates present in the hash'. Takes a hash, whose keys are template names. Checks the key-names contains all of the required templates.

> **multi sub templates-match( Hash %templates, Str $description = 'minimum templates match the specification' )**  
Checks whether the required templates render all parameters. Fails if any parameters are not rendered. If a parameter should not appear, render it as a comment or invisible element, so that it is in the output for it to match the specification, but not be seen when finally rendered. If there are more templates in the hash than are in the specifications, they are ignored.

> **multi sub extra-templates-match( Hash %templates, Hash %specifications, Str $description = 'extra templates match')**  
Check that templates in %templates match the specifications in %specifications. True if the templates match, AND all the templates in %templates are specified in %specifications.

# Verification utility
The `test-templates` utility helps to verify whether all the parameters specified for a template are in fact rendered by the template.

A template developer may decide not to render a parameter provided by ProcessedPod to the template. The verification tool will flag this with a warning.

If the minimum set of templates is not provided, the renderer will throw an error.

## Usage
This testing tool has the structure of the minimum template set coded into it. It is called as

```
test-templates --extra='filename-of-custom-template-structure.raku' --verbosity=2 'filename-of-templates.raku'
```
*  **--extra (optional, default: `Any` )**

This is a **Raku** compilable program that returns a `Hash` with the structure of the key, more below.

*  **--verbosity (optional, default: 0 )**

An integer that produces more information for higher values:

	*  = 0 returns 0 if no errors, or list templates with errors

	*  = 1 0 + parameters sent, sub-keys not returned

	*  = 2 1 + sub-keys found in error templates

	*  = 3 2 + full response for error templates

	*  = 4 all templates with sub-key returns

	*  = 5 5 + full response for all templates

*  **'filename-of-templates.raku' (mandatory, string)**

A **Raku** compilable program that returns a `Hash` contains all the minimum templates as keys pointing subroutines.

If the minimum set of templates is not provided in **filename-of-templates.raku**, a `MissingTemplates` exception will be thrown.

Since all the templates are provided to all the templates, it is recommended to use sub-templates within the minimum set to simplify the code.

## Data structures accepted by templates
All templates, whether Mustache or RakuClosure, expect PodRender to present them with parameters with one of the following data structures


 | level | allowable Type | element Type |
|:----:|:----:|:----:|
 | top | Str | n/a |
 | top | Hash | Str |
 |  |  | Bool |
 |  |  | Hash |
 |  |  | Array |
 | ! top | Str | n/a |
 | ! top | Bool | n/a |
 | ! top | Hash | Str |
 |  |  | Bool |
 |  |  | Hash |
 |  |  | Array |
 | ! top | Array | Str |
 | ! top | Array | Hash |

This specification allows for `test-templates` to create create random data for template and to test whether it is returned.

However, the developer has to provide information about what each template is expecting.

## Structure specification syntax
As can be seen from the table in [Data structures accepted by templates](Data structures accepted by templates.md), a parameter value, whether directly expected from a key, or as part of an Array or Hash, may be either 'Bool' or 'Str'. These are given as `Str` values, eg.

```
'title' => 'Str',
'heading' => { :text('Str'), :level('Str'), :is-header('Bool') }
```
A `Hash` element is specified as a `Hash`, using `{ ... } ` as shown above, and an `Array` is specified using `[ ... ] `, eg.

```
'table' => { :rows( [ 'Str', ] ) }
```
# Examples
Examples of a set of RakuClosureTemplates can be found in the `resources` directory of the distribution, as

*  `closure-temp.raku` is an array of templates, including a custom `image` template. The templates are designed for `Pod::To::HTML2`.

*  `extra-test.raku` is a hash with the template structure for the `image` template.

# Parameters of required templates
Each block has a default template and provides parameters to the default template. It is possible to over-ride the default template of a block by associating it with `:template<xxxx>` metadata. In this case, the same parameters are provided to the over-ridden template.

It is possible to provide a custom block to ProcessedPod, the parameters are shown below.

HTML2 has some extra templates, shown below.

>Required templates and their normal parameters

 | Key | Parameter | Sub-param | Type | Description |
|:----:|:----:|:----:|:----:|:----:|
 | escaped |  |  |  | Should be a special case |
 |  | contents |  | String | String |
 | raw |  |  |  | Should be a special case |
 |  | contents |  | String | normally should return the contents unchanged |
 | block-code |  |  |  | template for code |
 |  | contents |  | String | A code body |
 | comment |  |  |  |  |
 |  | contents |  | String | will be made into a comment |
 | declarator |  |  |  | renders documentation on a sub or variable |
 |  | target |  | String | 'target' is used in the glossary to point to the content, like a TOC for a header |
 |  | code |  | String | the line of code that is being documented |
 |  | contents |  | String | the documentation |
 | dlist-start |  |  | String | the tag or code that starts a declaration list |
 | defn |  |  |  | renders and element of a definition list |
 |  | term |  | String | the term part of a definition |
 |  | contents |  | String | the definition body |
 | dlist-end |  |  | String | the end tag of a definition list |
 | format-b |  |  |  | bold |
 |  | contents |  | String |  |
 | format-c |  |  |  | inline code |
 |  | contents |  | String |  |
 | format-i |  |  |  | italic |
 |  | contents |  | String |  |
 | format-k |  |  |  | keyboard |
 |  | contents |  | String |  |
 | format-r |  |  |  | replace |
 |  | contents |  | String |  |
 | format-t |  |  |  | terminal |
 |  | contents |  | String |  |
 | format-u |  |  |  | underline |
 |  | contents |  | String |  |
 | para |  |  |  | The template for a normal paragraph |
 |  | contents |  | String | text in para block |
 | format-l |  |  |  | renders a link to somewhere else |
 |  | internal |  | Boolean | true if target is within document |
 |  | external |  | Boolean | true if target is not in local area, eg., an internet url |
 |  | target |  | String | The url of the link |
 |  | local |  | String | url is local to system (perhaps with implied file extension) |
 |  | contents |  | String | The text associated with the link, which should be read (may be empty) |
 | format-n |  |  |  | render the footnote for the text |
 |  | retTarget |  | String | The anchor name the footnote will target |
 |  | fnTarget |  | String | The target for the footnote text |
 |  | fnNumber |  | String | The footnote number as allocated by the renderer |
 | format-p |  |  |  | Renders arbitrary text at some url. |
 |  | contents |  | String | The text at the link indicated by P |
 |  | html |  | Boolean | if True, then contents is in HTML format |
 | format-x |  |  |  |  |
 |  | target |  | String | Anchor name the glossary item will target |
 |  | text |  | String | The text to be included (the text to be included in the glossary is in the glossary structure) |
 |  | header |  | Boolean | True if the glossary item is also a header |
 | heading |  |  |  | Renders a heading in the text |
 |  | level |  | String | The level of the heading |
 |  | target |  | String | The anchor which TOC will target |
 |  | top |  | String | Top of document target |
 |  | text |  | String | Text of the header |
 | item |  |  |  | Renders to a string an item block |
 |  | contents |  | String | contents of block |
 | list |  |  |  | renders a lest of items, |
 |  | items |  | Array | Of strings already rendered with the "item" template |
 | unknown-name |  |  |  | A named block is included in the TOC, but is not known to ProcessedPod |
 |  | level |  | String | level of the header implied by the block = 1 |
 |  | target |  | String | The target in the text body to which the TOC entry points |
 |  | top |  | String | The top of the document for the Header to point to |
 |  | name |  | String | The Name of the block |
 |  | contents |  | String | The contents of the block |
 | output |  |  |  | Output block contents |
 |  | contents |  | String |  |
 | pod |  |  |  |  |
 |  | name |  | String | Like "unknown-name" |
 |  | contents |  | String | as "unknown-name" |
 |  | tail |  | String | any remaining list at end of pod not triggered by next pod statement |
 | table |  |  |  | renders table with hash of keys |
 |  | caption |  | String | possibly empty caption |
 |  | headers |  | Array | of hash with key 'cells' |
 |  |  | cells | Array | Of string elements, that are the headers |
 |  | rows |  | Array | Of cells for the table body |
 |  |  | cells | Array | Of strings |
 | source-wrap |  |  |  | Turns all content to a string for a file |
 |  | name |  | String | Name of file |
 |  | title |  | String | Title for top of file / header |
 |  | subtitle |  | String | Subtitle string (if any) |
 |  | title-target |  | String | target name in text (may be same as top target) |
 |  | metadata |  | String | rendered metadata string |
 |  | lang |  | String | The language of the document (default 'en') |
 |  | toc |  | String | rendered TOC string |
 |  | glossary |  | String | rendered glossary string |
 |  | body |  | String | rendered body string |
 |  | footnotes |  | String | rendered footnotes string |
 |  | renderedtime |  | String | rendered time |
 |  | path |  | String | path to source file |
 |  | page-config |  | Hash | user data given in first pod statement |
 | footnotes |  |  |  | renders the notes structure to a string |
 |  | notes |  | Array | Of hash with the following keys |
 |  |  | fnTarget | String | target in the footnote area |
 |  |  | text | String | text for the footnote |
 |  |  | retTarget | String | name for the anchor that the footnote will target |
 |  |  | fnNumber | String | The footnote number as allocated by the renderer |
 | glossary |  |  |  | renders the glossary structure to string |
 |  | glossary |  | Array | Of hash with keys |
 |  |  | text | String | text to be displayed in glossary (aka index) |
 |  |  | refs | Array | Of hash with keys |
 |  |  | (refs) target | String | target in text of one ref |
 |  |  | (refs) place | String | description of place in text of one ref (most recent header) |
 | toc |  |  |  | Renders the TOC structure to a string |
 |  | toc |  | Array | Of hash with keys: |
 |  |  | level | String | level of relevant header |
 |  |  | target | String | target in text where header is |
 |  |  | counter | String | formatted counter corresponding to level |
 |  |  | text | String | text of the header |
 | meta |  |  |  | renders the meta structure to a string that is then called metadata |
 |  | meta |  | Array | Of hash |
 |  |  | name | String | Name of meta data, eg. AUTHOR |
 |  |  | value | String | Value of key |

## Notes
If a block is accompanied by metadata in the Rakudoc document, then that data is also passed to the template.

## Custom block parameters
When a custom block name is provided to an instance of ProcessedPod, a default template with the same name, but in lower-case, must also be supplied. These are the parameters provided to the custom's default template (which can be over-ridden as explained above).

>Custom Templates, MyBlock and formatcode-F

 | Key | Parameter | Sub-param | Type | Description |
|:----:|:----:|:----:|:----:|:----:|
 | myblock |  |  |  | The name block is included in the TOC, unless overridden |
 |  | level |  | String | level of the header implied by the block, unless overridden |
 |  | target |  | String | The target in the text body to which the TOC entry points |
 |  | top |  | String | The top of the document for the Header to point to |
 |  | name |  | String | The Name of the block |
 |  | contents |  | String | The processed contents of the block |
 |  | raw-contents |  | String | Unprocessed contents of the block |
 |  | myblock | custom structure | Hash | Data provided by plugin |
 | format-f |  |  |  | A custom format code |
 |  | contents |  | String | contents |
 |  | meta |  | String / Array | contents after the straight line |

### Notes
For a custom block, using 'MyBlock' as an example:

The difference between `contents` and `raw-contents` is that the string in `contents` has been processed by ProcessedPod as if it was a `para` and so if the contents contains embedded Rakudoc blocks, they will be rendered as well.

`raw-contents` processes the contents with context Raw. This renders PodBlocks as text and does not escape contents.

The parameter `myblock` is provided if data has been provided to the instance of ProcessedPod by the plugin that created the custom block and templates. Normally it is the same name as the Block name, but this can be over-ridden using the `:namespace<xxx>` metadata.

The structure of `myblock` is determined by the plugin.

If a custom block is associated with the metadata key `:headlevel(integer)`, then `level` is given the value of `integer`.

If `integer` is 0, then the contents of the block are not included in the Table of Contents.

For a custom format code, using format code `F` as an example:

A Formatting Code in Rakudoc has the form F<contents|metadata> . See documentation about L<> as an example. The template is given this data.

## HTML2
>Helper templates in Pod::To::HTML2

 | Key | Parameter | Calls | Called-by | Description |
|:----:|:----:|:----:|:----:|:----:|
 | camelia-img |  |  | head-block | Returns a reference to C<camelia-svg> |
 | css |  |  | head-block | Returns a reference to C<rakudoc-styling.css> |
 | favicon |  |  | head-block | Returns a reference to C<favicon.ico> |
 | title |  |  | head-block | Helper template to format title for text (title also used in header-block) |
 |  | title |  |  |  |
 |  | title-target |  |  |  |
 | subtitle |  |  | source-wrap | Helper template to format title for text |
 |  | subtitle |  |  |  |
 | head-block |  |  | source-wrap | Forms the text for the 'head' section |
 |  | title |  |  |  |
 |  | metadata |  |  |  |
 |  | css | css-text |  | if 'css' is empty, it calls css-text |
 |  | head |  |  |  |
 |  |  | favicon |  |  |
 | header |  |  | source-wrap | renders the header section for the body |
 |  |  | title |  |  |
 |  |  | camelia-img |  |  |
 | footer |  |  | source-wrap | renders the footer section for the body |
 |  | path |  |  | path to the source file |
 |  | renderedtime |  |  | time the source was rendered |

### Notes


*  All blocks pass any extra config parameters to the template, eg., 'class', as well but if a developer passes configuration data to a block, she will be able to use it in the template.

*  The template does not need to render a parameter, but the template verification tool will issue a warning if it does not.

*  required templates are called by the Renderer, but it is cleaner to break the template into sections. The templates for Pod::To::HTML2 do this, with footer, header and head-block templates, all of which are called by file-wrap. This structure is shown in the table above.





----
Rendered from PodTemplates at 2022-10-28T16:55:01Z


