159 lines
3.3 KiB
Markdown
159 lines
3.3 KiB
Markdown
# Cuddly
|
|
|
|
Generate HTML and PDF from KDL structed data.
|
|
|
|
## Installation
|
|
|
|
```
|
|
git clone https://git.bksp.space/hannaeko/cuddly
|
|
cd cuddly
|
|
python -m venv env
|
|
env/bin/pip install .
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Example
|
|
|
|
Generating a PDF:
|
|
```
|
|
env/bin/cuddly --template samples/cv/cv.template.html --input samples/cv.kdl --output samples/cv.pdf
|
|
```
|
|
|
|
Generating a HTML file
|
|
|
|
```
|
|
env/bin/cuddly --template samples/cv/cv.template.html --input samples/cv.kdl --output samples/cv.html
|
|
```
|
|
|
|
### Template usage
|
|
|
|
The template language used is [Jinja](https://jinja.palletsprojects.com/en/3.0.x/), source template need to be a single HTML template file.
|
|
|
|
#### Base URL
|
|
|
|
When generating the PDF the base URL is set to the source template directory. All relative links to other resources (for example CSS and images) must be relative to that directory.
|
|
|
|
#### Accessing nodes values and attributes
|
|
|
|
Nodes are available as global variables in the template. The rendered value of a node is the first value that has been assigned to the node. This value can also be accessed using the `value` property. The list of values can be accessed using the `values` property.
|
|
|
|
```kdl
|
|
my_node "something" "other thing"
|
|
```
|
|
|
|
```jinja
|
|
{{ my_node }}
|
|
{{ my_node.value }}
|
|
{{ my_node.values | join(', ')}}
|
|
```
|
|
|
|
renders to
|
|
|
|
```
|
|
something
|
|
something
|
|
something, other thing
|
|
```
|
|
|
|
Accessing children nodes can be done using properties of the children names.
|
|
|
|
```kdl
|
|
my_node {
|
|
other_node "test"
|
|
}
|
|
```
|
|
|
|
```jinja
|
|
{{ my_node.other_node.value }}
|
|
```
|
|
renders to
|
|
|
|
```
|
|
test
|
|
```
|
|
|
|
If a node has multiple children of a same node type, then directly accessing the children properties will fail, a loop will be needed. Note that, on the other hand, looping on the children always work, even if there is only one child of the given type.
|
|
|
|
```kdl
|
|
my_node {
|
|
other_node "first"
|
|
other_node "second"
|
|
}
|
|
```
|
|
|
|
```jinja
|
|
{% for node in my_node.other_node %}
|
|
{{ node.value }}
|
|
{% endofr %}
|
|
```
|
|
|
|
renders to
|
|
|
|
```
|
|
first
|
|
second
|
|
```
|
|
|
|
Attributes of a node can be accessed through the `attributes` property:
|
|
|
|
```kdl
|
|
my_node version=42 "something"
|
|
```
|
|
|
|
```jinja
|
|
{{ my_node.attributes.version }}
|
|
```
|
|
renders to
|
|
```
|
|
42
|
|
```
|
|
|
|
#### Templating nodes
|
|
|
|
Node specific templates can be defined in the `components` element in the HTML template file. Nodes can then be rendered using those micro-templates using the `render` filter.
|
|
|
|
The context of the micro-template is the node being rendered. As such, children and properties of that node are in the global scope.
|
|
|
|
```kdl
|
|
menu "Midnight meal" price="10 €" {
|
|
dish name="Tomato soup" "Fancy tomato soup with a slice of bread"
|
|
dish name="Banana bread" "Amazing banana bread with a scoop of icecream"
|
|
}
|
|
```
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="{{ lang }}">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
</head>
|
|
<components>
|
|
<menu>
|
|
<h1>{{ value }}</h1>
|
|
<dl>
|
|
<dt>Price</dt>
|
|
<dd>{{ attributes.prices }}</dd>
|
|
</dl>
|
|
|
|
<dl>
|
|
{% for dish in dish %}
|
|
{{ dish | render }}
|
|
{% endfor %}
|
|
</dl>
|
|
</menu>
|
|
<dish>
|
|
<div>
|
|
<dt>{{ attribute.name }}</dt>
|
|
<dd>{{ value }}</dd>
|
|
</div>
|
|
</dish>
|
|
</components>
|
|
<body>
|
|
{{ menu | render }}
|
|
</body>
|
|
```
|
|
|
|
## Samples
|
|
|
|
* `samples/cv/cv.template.html`: Template to generate a CV, see `samples/cv.kdl` for the input data.
|