## Nunjucks

The templating language used for rendering the HTML is called Nunjucks. It is
very similar to other templating languages like Twig, but is instead JavaScript
based. It allows the use of conditional statements, loops, variables, includes,
extends, ...

Make sure to check out the
[Nunjucks documentation](https://mozilla.github.io/nunjucks/api.html) to get a
better understanding of awesomeness.

## Structure

The Nunjucks is by default placed within the `src/styleguide`. This folder can
be changed through the configuration of the project.

More information about the config and how to change the source folder can be
found in the config section of the getting started manual.

Now then, let's start talking about the structure. This is very important! So
try not to fall asleep.

The structure is fixed and is not customizable. This is done because the Express
server looks at the structure and based on the folder structure creates the
component-library. An example of a folder structure looks like this:

* **level 0**: The source folder that contains basically everything
* **level 1**: A category in the styleguide, for example when seperating into
different projects. This can happen when 2 projects in the same brand use the
same component but looks completely different. This can be anything you want.
But by default, we need at least one, is called general.
* **level 2**: A type or name you give to a group of components. This can be
anything you want, it just needs to encapsulate the type of components you place
within. **Important to know** is that there are 2 names that are fixed:
**fundamentals** and **pages**, but they can be changed within the configuration
of the project.
* **level 3**: The name you give to the component. This can be anything as well
but should be a folder because it needs different types of files to render the
component and their documentation correctly. The only exceptions are the
fundamentals and pages folder.

* **styleguide** - (*level 0*)
	* **general** - (*level 1*)
		* **fundamentals** - (*level 2*)
			* colors - (*level 3*)
			* typography - (*level 3*)
		* **building-blocks** - (*level 2*)
			* button - (*level 3*)
			* input - (*level 3*)
			* tag - (*level 3*)
		* **components** - (*level 2*)
			* collapse - (*level 3*)
			* header - (*level 3*)
			* footer - (*level 3*)
		* **layouts** - (*level 2*)
			* container - (*level 3*)
			* section - (*level 3*)
			* form - (*level 3*)
		* **pages** - (*level 2*)
			* home - (*level 3*)
			* about - (*level 3*)
			* contact - (*level 3*)
	* **marketing** - (*level 1*)
		* **building-blocks** - (*level 2*)
			* button - (*level 3*)
			* input - (*level 3*)
		* **components** - (*level 2*)
			* header - (*level 3*)
		* **pages** - (*level 2*)
			* home - (*level 3*)
	* **tools** - (*level 1*)
		* ...

## Fundamentals

At the moment the brandplatform only supports two types of fundamentals:

* Colors
* Typography

If you want to implement these settings you must create, in comparison to
components, two files with an object in there with the same name mentioned
above:

### Colors

Place a variable called **config** in there, which is an object containing
different keys. Each key is the category to which the colors belong too. Then
you can add 2 types of colors:

* a **string** with the color value in there (preferable #HEX)
* an **object** with with 2 keys:
	* **style**: inline styling used to change the way the preview of the color
	looks. This is done to make sure you can see white blocks on a white
	background.
	* **value**: a string with the color value

```html
{% set config = {
	primary: [
		"#0365F4"
	],
	text: [
		"#000000",
		{
			style: "background-color: #FFFFFF; border: 1px solid #E9EAEB;",
			value: "#FFFFFF"
		},
		"#767676"
	]
} %}
```

### Typography

Place **two objects** to visualise the font-families and the different
text-styles:

* **families**: An array that contains objects with each two keys
	* **name**: The name you want to give the font
	* **style**: The inline styling that will be used to change the preview of
	the font-family

	```html
	{% set families = [
		{
			name: "Helvetica bold",
			style: "font-family: 'Helvetica'; font-weight: 700;"
		},
		{
			name: "Helvetica regular",
			style: "font-family: 'Helvetica'; font-weight: 400;"
		}
	] %}
	```

* **styles**: An object that contains a key which represents the type of tag
you want to add the style to. Each of these objects can contain any amount of
keys and values. But the important thing is that these keys represents
CSS-properties with their values. This is done so that the correct style is
applied to the tag

	```html
	{% set styles = {
		h1: {
			"font-family": "Helvetica",
			"fontSize": "40px",
			"line-height": "50px",
			"font-weight": "700"
		},
		h2: {
			"font-family": "Helvetica",
			"font-size": "40px",
			"line-height": "50px",
			"font-weight": "700"
		}
	} %}
	```

## Building-blocks, components, ...

These folders are variable and unlike the fundamentals they do not contain any
fixed values. You can add as many folders as you want or name them any way you
want. The name will be used and rendered in the sidebar and can be used to
generate components within those folders.

Each component can have different variations. These are different ways the
component can be shown or presented. These can contain differentiations in
modifiers or DOM. By default thre is already one variation called **default**.

The information about generating components can be found within the commands
section of the getting started manual.

For example, if you run this command a component **header** will be generated
in the **components** folder of the category **general**.
`npm run generate -- --category=general --components=header`

When generating or adding a component it will first generate a folder. This
folder is called **header**, which is the name of the component passed in the
command. In this folder different files are generated, lets take the header
example, where the [name] is replaced by header.

### _[name]-default.njk

The files within a component that have an **_** (underscore) in front of them
are used as variations of a component. The title, in this case, **default** is
used as the title of the variation. This means that you can replace **default**
by anything you want if you want to name your variation differently.

These variations consists out of imports and variables which will be used by the
page to render the variation based on the contents of the variables. The name of
these variables cannot be changed:

* **params**: This contains any sort of parameters necessary to influence the
variation, like a config for that variation specifically.

	```html
	{% set params = {
		styleVendors: [],
		scriptVendors: [],
		order: 1,
		scope: ""
	} %}
	```

	* **styleVendors**: This is an array of the different style vendors that
	should be loaded in the `<head>` of the page
	* **scriptVendors**: This is an array of the different script vendors that
	should be loaded right before closing the `</body>`
	* **order**: A number used to order the variations, the higher the number
	the lower it is rendered in the list. The lower the number the higher it is
	rendered.
	* **scope**: An extra class you can pass to the preview of the variation to
	change the visual representation within the brandplatform. This is slicing
	that should only be part of the brandplatform, not of the components.

* **info**: Optional information about the variation. This should be written in
markdown.
* **preview**: This is the component that we will see rendered within the
preview window. This should simply be an execution of the macro within the
[name]-macros.njk file, which is imported on top of the page. Here you can pass
parameters to fill up the content of the component.
* **code**: This is used to give a code-sample of the component. This is
optional and if not used, the code from the preview variable is used to render
the code sample. This should simply be an execution of the macro within the
[name]-macros.njk file, which is imported on top of the page. Here you can pass
parameters to fill up the content of the component.

By default a variation looks like this:

```html
{# ========================================================================== #}
{# :: Imports #}
{# ========================================================================== #}
{% import "general/components/header/header-macros.njk" as header %}

{# ========================================================================== #}
{# :: Settings #}
{# ========================================================================== #}
{% set params = {
	isFullWidth: false,
	styleVendors: [],
	scriptVendors: [],
	order: 1,
	scope: ""
} %}

{# ========================================================================== #}
{# :: Info #}
{# ========================================================================== #}
{# {% set info %}

{% endset %} #}

{# ========================================================================== #}
{# :: Preview #}
{# ========================================================================== #}
{% set preview %}

	{{header.default("", {})}}

{% endset %}

{# ========================================================================== #}
{# :: Code #}
{# ========================================================================== #}
{# {% set code %}

{% endset %} #}
```

### [name]-macros.njk

The macros file of the component is used to contain the markup. This is the only
file that should contain code to structure the component. This file is a
collection of macro's, which in Nunjucks are functions, that contain markup.
Once the function is called, the markup is rendered where the function call is
happening.

The macro file can have imports of other components that are used to render the
component correctly. By default the macro file should look like this:

```html
{# ========================================================================== #}
{# :: Imports #}
{# ========================================================================== #}

{# ========================================================================== #}
{# :: Default #}
{# ========================================================================== #}
{% macro default(classes, data) %}

{% endmacro %}
```

As you can see above, these macro's are able to get parameters. We find that it
is a good pattern to only pass two parameters to these macros:

* **classes**: a string that is a list of classes that will be placed on the
root of the structure within the macro

	```html
	{% macro default(classes, data) %}
		<header class="o-header {{classes}}">
		</header>
	{% endmacro %}
	```

* **data**: an object that has all the different keys used to fill up the
content of the component. Even if there is just one key, this must stay an
object for consistency. These keys are placed within the DOM to render for
example copy.

	```html
	{% macro default(classes, data) %}
		<header class="o-header {{classes}}">
			<h1 class="o-header__title">{{data.title}}</h1>

			{% if data.text %}
				<p class="o-header__text">{{data.text}}</p>
			{% endif %}
		</header>
	{% endmacro %}
	```

### [name]-page.njk

The file used as the entry point of the component. This is a nunjucks file that
mainly contains variables which can hold markdown. These are passed to the page
rendering everything underneath and are rendered as markdown. The name of these
variables cannot be changed:

* **info**: Small block used to give an explanation to what a component is, what
it does or what it contains. This is rendered on top of the page underneath the
title and above the variations of the component.
* **modifiers**: This variable is meant to hold a list of modifier-classes with
their respective explanation. When adding markdown to this variable you must
maintain the correct structure:

	```md
	* o-header--inverted
		A header that is inverted in colors where...
	* o-header--light
		A header in which the background color is...
	```

* **states**: This variable is meant to hold a list of state-classes with their
respective explanation. When adding markdown to this variable you must maintain
the correct structure:

	```md
	* is-open
		The headers state changes in which the navigation...
	* is-disabled
		The header is completely disabled, not being able to click...
	```

* **javascript**: This variable is meant to hold a list of javascript-classes
with their respective explanation. When adding markdown to this variable you
must maintain the correct structure:

	```md
	* js-hamburger
		The JavaScript is enabled on this component, making sure...
	* js-outline-text
		The Javascript is enabled on this component, rendering...
	```

### [name]-usage.njk

A markdown file where you can write down how to use this component, like do's
or dont's. This file is optional. Keep in mind, you have to write Markdown in
this file.

## Pages

Pages contain the different views or interfaces that are build up with
components and building-blocks defined in the previous chapters. There are two
ways to structure the pages within the folder structure and these cannot be
combined:

* **Using files**: Directly place files in the pages folder, each file
represents a page. A structure could look like this:

	* **pages**
		* home
		* about
		* contact

* **Using folders**: Directly place folders in the pages folder, each folder
represents a group of pages and each file within that folder is a page. A
structure could look like this:

	* **pages**
		* **general**
			* home
			* about
		* **booking**
			* step 1
			* step 2
			* step 3
		* **detail**
			* article
			* booking

**IMPORTANT TO KNOW** is that pages have their very own logic and structure. The
way this structure is build is a combination of folders starting with **_** to
make sure they are ignored by the express server and the pages structure as
files or folders mentioned above. By default the folder structure there looks
something like this (but more folders or files can be added):

* **pages**
	* **_base**
		* default.njk
		* foot.njk
		* head.njk
	* **_partials**
		* home
			* hero.njk
			* ...
    	* ...
	* home.njk
	* ...

### _base

Contains all the starter templates of each page which are extendable and gives
you the ability to define Nunjucks Placeholders to put the content of every page
in.

#### default.njk

The default page should look very small and should only contain logic for
reusability purposes in every other page.

```html
<!DOCTYPE html>
<html lang="en">

	{% include "general/pages/_base/head.njk" %}

	<body class="{{pageParams.bodyClass}}">

		{{header.default()}}

		<main>
			{% block content %}
			{% endblock %}
		</main>

		{{footer.default(pageParams.footerClass)}}

		{% include "general/pages/_base/foot.njk" %}

	</body>

</html>
```

#### foot.njk

The foot.njk file is mainly used to load everything necessary before the closing
of the `</body>`. These are for example mainly scripts or script vendors.

#### head.njk

The head.njk file is mainly used to define the `<meta>` tags and other SEO
related tags. The `<link>` to load in the CSS and their vendors should also
be present.

### _partials

The partials can be seen as parts of a page that are loaded in one after another
to form a page. These should only contain markup, imports and execution of
macro's. Each macro or loaded component should receive their data from these
files. We do this to seperate the partials content and logic from each other and
get a clear view of what belongs together.

A standard partial structure always has the name of the page the partials belong
to as a parent folder in which the files are placed in:

* **_partials**
	* **home**
		* hero.njk
		* article.njk
		* cta.njk
		* ...
	* **about**
		* intro.njk
		* content.njk
		* ...

### home.njk, about.njk, contact.njk, ...

The page should make use of the files defined in the _base folder to load in the
page template and fill in the placeholders to render everything in the correct
place on the page. The content block for example should only consist out of
includes of partials which have their own logic.

```html
{# ========================================================================== #}
{# :: Inheritance #}
{# ========================================================================== #}
{% extends "general/pages/_base/default.njk" %}

{# ========================================================================== #}
{# :: Settings #}
{# ========================================================================== #}
{% set pageParams = {
	bodyClass: "",
	styleVendors: [],
	scriptVendors: []
} %}

{# ========================================================================== #}
{# :: Imports #}
{# ========================================================================== #}

{# ========================================================================== #}
{# :: Content #}
{# ========================================================================== #}
{% block content %}

	{% include "general/pages/_partials/home/intro.njk" %}

{% endblock %}
```
