Skip to content

Conversation

@thekid
Copy link
Member

@thekid thekid commented Oct 14, 2023

This pull request adds support for organizing templates into namespaces. For example, an application could use a library providing the layout namespace.

Example

The application uses the TemplatesFrom class instead of directly passing the file path to the Handlebars class:

use web\frontend\{Frontend, AssetsFrom, HandlersIn, Handlebars, TemplatesFrom};
use web\Application;

class App extends Application {

  /** Returns routing for this web application */
  public function routes() {
    return [
      '/static' => new AssetsFrom($this->environment->path('src/main/webapp')),
      '/'       => new Frontend(
        new HandlersIn('com.example.app.web'),
        new Handlebars(new TemplatesFrom(
          $this->environment->path('src/main/handlebars'),
          ['layout' => $this->environment->path('vendor/example/layout-lib/src/main/handlebars')]
        ))
      )
    ];
  }
}

The default.handlebars template in the layout library:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>{{> title}} - Application</title>
</head>
<body>
  <main>
    {{> main}}
  </main>
</body>
</html>

The home.handlebars templates references this via the namespace:name notation:

{{#> layout:default}}
  {{#*inline "title"}}Home{{/inline}}
  {{#*inline "main"}}
    <h1>Welcome</h1>
  {{/inline}}
{{/layout:default}}

@thekid thekid added the enhancement New feature or request label Oct 14, 2023
@thekid
Copy link
Member Author

thekid commented Oct 14, 2023

Is there a way we can remove the hardcoded vendor path in the following?

['layout' => $this->environment->path('vendor/example/layout-lib/src/main/handlebars')]

Maybe something like new InModule('example/layout-lib') which would use the module API, or new InLibrary('example/layout-lib', 'src/main/handlebars') which would Composer's class loader?

@thekid
Copy link
Member Author

thekid commented Oct 14, 2023

If a library wants to use another library, it would need to know the namespace under which this other library was imported into the application. For example:

new TemplatesFrom($this->environment->path('src/main/handlebars'), [
  'layout' => $this->environment->path('vendor/example/layout-lib/src/main/handlebars'),
  'common' => $this->environment->path('vendor/example/common-lib/src/main/handlebars'),
]);

Is there a way we can make this work without relying on documentation stating something along the lines of this library expects the common-lib to be namespaced as common?


First idea: by using the unique vendor/library name in PHP:

new TemplatesFrom($this->environment->path('src/main/handlebars'), [
  'example/layout-lib' => $this->environment->path('vendor/example/layout-lib/src/main/handlebars'),
  'example/common-lib' => $this->environment->path('vendor/example/common-lib/src/main/handlebars'),
]);

// Or maybe even shorter, see question above about removing hardcoded "vendor" path...
new TemplatesFrom($this->environment->path('src/main/handlebars'), [
  new Library('example/layout-lib'),
  new Library('example/common-lib'),
]);

...and inside Handlebars:

{{#> example/layout-lib:default}}
  {{#*inline "title"}}Home{{/inline}}
  {{#*inline "main"}}
    <h1>Welcome</h1>
  {{/inline}}
{{/example/layout-lib:default}}

...potentially including a namespace helper to shorten the names, e.g.:

{{namespace layout="example/layout-lib"}}

{{#> layout:default}}
  {{#*inline "title"}}Home{{/inline}}
  {{#*inline "main"}}
    <h1>Welcome</h1>
  {{/inline}}
{{/layout:default}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants