twig.js
twig.js copied to clipboard
In the PHP version, you can include templates from multiple locations
It would be nice to be able to pass an array of locations for the path option.
+1
+1
+1
+1
+1
+1
if I understood you are talking about namespaces, it is now working at the last version: https://github.com/justjohn/twig.js/blob/master/CHANGELOG.md
and I added a example on how to implement on the wiki
Namespaces are a great addition, but I am talking about cascading locations.
In php, you can specify an array of folders where to look for templates.
Twig will loop through the locations until it finds the template.
If I define my path as [folder-a, folder-b], Twig looks for template.twig first in folder-a and if it doesn't exist, it will cascade to look if it exists in folder-b.
in Express 4 we'd hope to set it up like
app.set('views', ['path/to/files/', 'path/to/other/files'] ;
But when you do this, Twigjs doesn't see this as an array of 2 items. It tries to look in:
'path/to/files/,path/to/other/files'
Appears that the relativePath
function assumes template.base to be a string, and not an array (which it is when multiple paths are defined in express.
I took a little stab at a fix, but it might require more of a rewrite than I'm able to do in order to support array paths.
Namespaces are a great addition, but I am talking about cascading locations.
In php, you can specify an array of folders where to look for templates.
Twig will loop through the locations until it finds the template.
Actually, they are the same thing. In the PHP Twig, there is a default "main" namespace. When you add paths to search for templates, you are adding paths to the main namespace. Here's the relevant docs: http://twig.sensiolabs.org/doc/api.html#built-in-loaders
There are 2 incompatibilities with Twig.js here.
- Twig.js does not have a main namespace.
- Namespaces can only have a single path. But namespaces should have an ordered array of paths.
Right now we are required to pass namespaces every time we call Twig.twig() which is kind of a pain, but manageable. However, if Twig.js adds a main namespace, it is going to have to manage a global registry for namespaces which means a user should be able to register their custom namespace once with Twig.js and not have to provide it every time it calls Twig.twig().
Here's more Twig docs. http://symfony.com/doc/current/cookbook/templating/namespaced_paths.html#multiple-paths-per-namespace
With Symfony, Twig.js' namespaces are configured by a YML file:
# app/config/config.yml
twig:
# ...
paths:
"%kernel.root_dir%/../vendor/acme/themes/theme1": theme
"%kernel.root_dir%/../vendor/acme/themes/theme2": theme
"%kernel.root_dir%/../vendor/acme/themes/common": theme
In Twig without Symfony, you have to add namespace from within a loader. And then use that loader when creating the global Twig environment
$twig = new Twig_Environment($loader);
Or inserting it into the global twig with:
$twig->addLoader($loader);
Many Symfony-based apps use "services" to configure a Twig_Loader_Chain that includes several different loader types. So if you want custom namespaces, you register your custom loader with the services and it pushes it onto the loader chain stack. When a template is requested, Twig goes through each loader in the Twig_Loader_Chain stack and tries to find a match. Since your @mypath/template.twig
will only match a namespace in your custom loader, your custom loader will be used to resolve any custom namespaces.
I just did this with a Drupal module, which is why I'm familiar with this API. http://drupal.org/project/components
TLDR;
Yes, its a pain in the ass to add namespaces with multiple paths in Twig for PHP. So how do we add it to Twig.js?
Twig.js has an equivalent to Twig_Loader_Chain in that Twig.exports.twig()
goes through a long if/then/else checking for which loader to use.
I'd rather not have to implement a custom loader that was essentially a fork of the fs
loader just so I can add custom namespaces.
Ideally, we would be able to configure Twig.js' fs
or ajax
loader by adding paths to the default namespace or adding custom namespaces. PHP Twig loaders have these methods for adding paths and namespaces: setPaths(), addPath(), and prependPath(). e.g. $loader->addPath('/etc');
adds a path to the main namespace and $loader->addPath('/etc', 'mynamespace');
adds that path to a custom namespace. If you want multiple paths in your namespace, you call addPath()
or prependPath()
multiple times. FYI, setPaths()
only adds paths to the main namespace, you can't specify custom namespaces. https://github.com/twigphp/Twig/blob/f0a4fa678465491947554f6687c5fca5e482f8ec/lib/Twig/Loader/Filesystem.php
However, in Twig.js, we aren't resolving namespaces inside loaders, we are doing it in twig.path.js
, so our separation is already a little muddy.
The twig.path.js
module is in charge of replacing namespaces with paths for fs
and it completely ignores the concept of namespaces for the ajax loader. Wouldn't ajax users want a nice conversion of @mysite/template.twig
into http://mysite/myfolder/template.twig
? To be clear, I don't think multiple URLs would make sense, but a single path per namespace would be mighty handy.
Still TLDR;
So we have 2 options:
- Export
Twig.Templates.loaders
, so users can useTwig.loaders.fs.addPath()
,Twig.loaders.fs.setPaths()
,Twig.loaders.ajax.addPath()
, etc. That meansTwig.path.parsePath()
would just be calling the loader'sfindTemplate()
method to get the correct path. - Add methods to
Twig.path
that resolves namespaces for any loader. That means you can't have a single namespace that resolves to different paths; e.g. "myStuff" resolving to a URL forajax
and to a file system path forfs
. Users can useTwig.path.setPaths()
,Twig.path.addPath()
, andTwig.path.prependPath()
.
Option 2 is shorter for the user (and easier to implement), but option 1 is closer to what Twig PHP does.
I'm happy to do the PR for option 1.
Sorry for the long comment. Thoughts?
I'll counter your long comment with a short one :)
We go for whatever solution gets us closer to parity with Twig PHP. Adding sugar to said solution could be done in an additional module.
I'll see if I can get a PR for this done this week. @micahgodbolt and I are both at the same conference this week.
Any movement on this? It's been months and there doesn't appear to be a solution or an open PR
Bump :wave: Would love this too!
any updates ?