Custom styles
Flower comes with a number of built-in styles, but it is also possible to create new styles that match your particular use case. Custom styles can only be used with the build command and not with view.
Creating a custom style involves making templates and using configuration files to set the layout and structure of the documentation generated from the datapackage.json file.
In this guide, you will walk through how to create a custom style that generates one Markdown file for the Data Package as a whole and separate Markdown files for each data resource. To demonstrate this custom style, you will use the following Data Package about a (fake) study on flowers and their growing conditions.
At the end of this page and after completing all the steps, your file structure will look like the below:
flora/
├── datapackage.json
├── .flower.toml
└── templates/
├── sections.toml
├── package.qmd.jinja
├── contributors.qmd.jinja
└── resource.qmd.jinja
└── docs/
├── index.qmd
└── resources/
├── species_catalog.qmd
└── growth_records.qmdThe first step is to set up the files within the templates/ folder.
Creating the templates
You can define a custom layout for your metadata (or part of your metadata) using a Jinja2 template. In this template, you write out the structure of your desired output in your target language (e.g., HTML, markdown, yaml, etc.), using placeholder values for the metadata elements that will come from your datapackage.json.
In this guide, you will create template files containing the Data Package’s general metadata, the contributor metadata, and metadata for each resource contained in the Data Package. To start, create a new directory for the templates and give it a descriptive name:
flora/
├── datapackage.json
└── templates/You can store your templates wherever it makes sense for your project; in this example, call the template folder templates/ and put it inside the root of the Data Package folder. Inside the template folder, create three files, one for each type of metadata listed above.
package.qmd.jinjafor the general metadata.contributors.qmd.jinjafor the contributor metadata.resource.qmd.jinjafor each resource’s metadata.
The .qmd.jinja extension indicates that the file is a jinja template that will create a qmd file. If you wanted to create an html file instead, the extension would be .html.jinja.
Next, set your desired layout for the generated documentation in each template. Since Flower uses Jinja2 as its templating engine, you need to use Jinja syntax when accessing values from the Data Package metadata.
package.qmd.jinja
Start with the package.qmd.jinja template. Define the layout for package properties by writing a template that looks like:
templates/package.qmd.jinja
---
title: "{{ package.title or package.name }}"
subtitle: "Version: {{ package.version }}"
date: "{{ package.created }}"
---
{{ package.description }}Here, Jinja syntax is used to access properties on the metadata object passed to the template as package. Double curly brackets {{...}} are used to output the value of a variable or expression. In this example, {{ package.title or package.name }} sets the title of the generated document to the title property of the package metadata, or to the name property if title is not available. You can use any name for the metadata object passed to the template (e.g., root or data_package instead of package); this variable name will be defined in the sections.toml configuration file.
Jinja also provides built-in filters and functions for processing values, as well as control flow statements such as conditionals and loops. Below, you will extend package.qmd.jinja to include a list of keywords that describe the Data Package. An if statement is used to check if the keywords property exists in the package metadata. If it does, it will output a line with the keywords joined by commas using the built-in Jinja join filter. You can learn more about advanced Jinja features in the Jinja documentation.
templates/package.qmd.jinja
---
title: "{{ package.title or package.name }}"
subtitle: "Version: {{ package.version }}"
date: "{{ package.created }}"
---
{{ package.description }}
{% if package.keywords %}
**Keywords:** {{ package.keywords | join(", ") }}
{% endif %}contributors.qmd.jinja
In the contributors.qmd.jinja template, you will define the layout for the contributors (using the variable name contributors). You could include the contributors in the package.qmd.jinja template, but, to show how to split content across templates, you will create a separate template.
templates/contributors.qmd.jinja
## Contributors
{%- if contributors %}
{% for contributor in contributors %}
### {{ contributor.title }}
{%- if contributor.organization %}
**Organization:** {{ contributor.organization }}
{% endif %}
{% if contributor.email -%}
**Email:** <{{ contributor.email }}>
{%- endif %}
{% endfor %}
{% else %}
No contributors listed.
{% endif %}resource.qmd.jinja
A Data Package can contain multiple data resources, and you may want to display the metadata of each resource in a separate file with the same layout. To do this, you can create a template that defines the layout for a single resource and then use the sections.toml configuration file to indicate that this template should be applied to each resource in the Data Package. In the template, the variable name resource is used to refer to the metadata of any single resource that will be rendered with the template.
templates/resource.qmd.jinja
---
title: "{{ resource.title or resource.name }}"
---
{{ resource.description }}
## Overview
- **Name:** `{ resource.name }`
{% if resource.path %}
- **Path:** `{ resource.path }`
{% endif %}
{%- if resource.schema and resource.schema.fields %}
- **Number of fields:** {{ resource.schema.fields | length }}
{% else %}
- **Number of fields:** 0
{% endif %}The template variable can reference any property or collection of properties in the datapackage.json that is possible to select using JSON path notation. This JSON path will be defined in the sections.toml configuration file.
Creating the configuration files
Main configuration file
The main configuration file is used to set the template and output folders for the documentation. Flower can read the main configuration from the .flower.toml or the pyproject.toml file in the root of your Data Package. In this guide, you will use .flower.toml.
Create a .flower.toml file in the root of your Data Package and add the following settings:
.flower.toml
# Point Flower to the folder containing your templates
template-dir = "templates/"
# Specify where the output files should be generated
output-dir = "docs/"The style field in the main configuration file is for specifying a built-in style and should not be used when creating a custom style. If you want to use a built-in style, leave template-dir unset and set style to the name of your chosen built-in style.
sections.toml configuration file
The sections.toml file is used to define how many output files will be created and which metadata will be displayed in each file. Documentation is split into two section types: one and many.
oneis for one output file (e.g., an index file).manyis for a group of similar output files (e.g., a file for each resource).
The sections.toml file must be stored in the template folder.
Adding [[one]] section(s)
Create a sections.toml file in the templates/ folder. Inside, add a [[one]] for each output file you want to create. For this guide, create just one [[one]] to save an index.qmd:
templates/sections.toml
# One output file at docs/index.qmd
[[one]]
output-path = "index.qmd"Each [[one]] section contains one or more content items, with each content item corresponding to a specific part of the metadata (e.g., the contributors). A content item links this specific part of the metadata to the template that will be used to render it. In the rendered output, content items in the same section will be combined into the same output file in the order they are defined.
This section will output the index.qmd file, which would be considered the “landing page” for the Data Package documentation. In this case, add a content for the general Data Package properties (like title and description) and a content for the contributors.
Add one or more contents to each [[one]] section, you need to include these fields:
jsonpath: The JSON path to the metadata that will be sent to the template. The JSON path should be expressed using JSON path syntax.template-path: The path to the Jinja template file for this content item, relative to the template folder.jinja-variable: The variable name that will be used in the template to reference the selected metadata.
Update the sections.toml file to include the content items for the [[one]] section:
templates/sections.toml
[[one]]
output-path = "index.qmd"
[[one.contents]]
# Select the whole metadata object
jsonpath = "$"
# Render the selected metadata with this template
template-path = "package.qmd.jinja"
# Reference the selected metadata in the template with this
# variable name
jinja-variable = "package"
# The contents of this section will be appended to the contents
# of the previous section inside the `docs/index.qmd` file.
[[one.contents]]
jsonpath = "$.contributors"
template-path = "contributors.qmd.jinja"
jinja-variable = "contributors"You can do the same thing to add more [[one]] sections if you want to create more output files that contain different metadata. Or you can keep adding content items to the same [[one]] section.
Adding [[many]] section(s)
When you want to create a group of similar output files (e.g., one file for each resource), you can use the [[many]] section type. Here you’ll create a [[many]] section to save a file for each resource in the resources/ folder. The [[many]] section works similarly to [[one]] except you can only have one content type (either "resources" or "fields") that is used in place of jsonpath, with the other Content attributes being included within the [[many]] section.
To create one file for each resource using the resource.qmd.jinja template, you add the following [[many]] section to the sections.toml file:
templates/sections.toml
[[many]]
output-path = "resources/"
content = "resources"
template-path = "resource.qmd.jinja"
jinja-variable = "resource"This will place the created files in the resources/ folder inside the output directory (docs/ in this example). Each created file will be named using the name metadata of the resource (e.g., species_catalog.qmd and growth_records.qmd).
You can either set a folder or a file in the output-path of [[many]]. If you use a file path, you need to include the {} placeholder for the file name. In the case above, it would be resources/{resource-name}.qmd. See the design documentation on Many for more details.
Running the build command
To generate the documentation, run the build command in the Terminal from the root of your Data Package:
Terminal
seedcase-flower buildThis will read the configuration files (.flower.toml and sections.toml), populate the templates (in the templates/ folder) with metadata from datapackage.json, and output the generated documentation files to the specified output directory (docs/ in this example).
Your file structure should now look like:
flora/
├── datapackage.json
├── .flower.toml
└── templates/
├── sections.toml
├── package.qmd.jinja
├── contributors.qmd.jinja
└── resource.qmd.jinja
└── docs/
├── index.qmd
└── resources/
├── species_catalog.qmd
└── growth_records.qmd