Terrific Twig
, (*1)
Extension to embrace the Terrific frontend methodology in Twig., (*2)
Adds a custom component
tag to Twig which mimics the Nitro handlebars helper., (*3)
Installation
Using composer:, (*4)
```shell script
$ composer require namics/terrific-twig, (*5)
## Requirements
The following versions of PHP are currently supported.
* 8.0
* 8.1
## Setup
Step 1: Implement `TemplateInformationProvider`
```php
class TemplateInformationProvider implements TemplateInformationProviderInterface
{
public function getPaths() {
/* List of path where Terrific Components can be found, e.g.
@code
[
'/var/www/example.com/frontend/src/atoms',
'/var/www/example.com/frontend/src/molecules',
'/var/www/example.com/frontend/src/organisms'
]
@endcode */
return [];
}
}
Step 2: Implement ContextProviderInterface
, (*6)
class ContextProvider implements ContextProviderInterface
{
public function compile(\Twig\Compiler $compiler, \Twig\Node\Node $component, \Twig\Node\Node $dataVariant, $only) {
// ...
}
}
Step 3: Add TerrificLoader
, (*7)
$loader = ...;
$chain = new \Twig\Loader\ChainLoader([$loader, new TerrificLoader(new TemplateInformationProvider)]);
$twig = new \Twig\Environment($chain);
Step 4: Add TerrificExtension
, (*8)
$twig = new \Twig\Environment($chain);
$twig->addExtension(new TerrificExtension(new ContextProvider));
Step 5: Profit!, (*9)
Usage
{# Includes the component, data object is merged with the context #}
{% component 'Example' { title: 'Inject an Object' } %}
{# Includes the component, data object is injected as a child context #}
{% component 'Example' { title: 'Inject an Object' } only %}
{# Includes the component, object variable data is merged with the context #}
{% set fooComponentData = { title: 'Inject an Object' } %}
{% component 'Example' fooComponentData %}
{# Includes the component with name contained by string variable, data object is merged with the context #}
{% set fooComponentName = 'Example' %}
{% component fooComponentName { title: 'Inject an Object' } %}
{# Includes the component with name contained by string variable, object variable data is merged with the context #}
{% set fooComponentName = 'Example' %}
{% set fooComponentData = { title: 'Inject an Object' } %}
{% component fooComponentName fooComponentData %}
Documentation
Extension
The extension provides terrific extensions to Twig. Currently, the extension provides the ComponentTokenParser
., (*10)
Token Parser
The token parser contains the parsing step for the component tag. It tokenizes the stream to different nodes (component
, data
) and an attribute (only
)., (*11)
The functionality is based on the fantastic Twig_TokenParser_Include
., (*12)
Node
The Node compiles the tokenized tag to PHP. To see some of the output, check the ComponentTest
., (*13)
Loader
The TerrificLoader
loads templates contained inside the given paths. An implementation of TemplateLocatorInterface
provides the paths where the loader should search for templates. Recursively loads any directories contained inside the given directories., (*14)
An implementation of TemplateInformationProviderInterface
should return a list of paths where templates live. These should be in the form of ['frontend/components/atoms', 'frontend/components/molecules', 'frontend/components/organisms']
. The component directory will be provided by the TerrificLoader
(Example/example.[ext]
)., (*15)
Context Provider
This is the tricky part. An implementation of ContextProviderInterface
decides which data will be made available to Twig templates.
TODO: More on that., (*16)
ConfigReader
Reads nitro's config.json
and parses essential information such as the component paths and file extension., (*17)
Tests
Tests can be run by using the following command:
shell script
composer run-scrip tests
, (*18)
CI
This project uses GitHub actions., (*19)
Run locally
- Install nektos/act.
- Open terminal, go to project directory.
- Run
act -P ubuntu-latest=shivammathur/node:latest
as described here.
Credits
This project is partially sponsored by Namics., (*20)