xp-forge / handlebars-templates

Handlebars templates for XP web frontends
1 stars 0 forks source link

Assets helper #6

Closed thekid closed 3 years ago

thekid commented 3 years ago

With the introduction of asset bundling (see xp-forge/frontend#17) asset names can be resolved against the assets manifest by a) passing it to the frontend globals and b) using the lookup helper as follows:

In PHP

$manifest= new AssetsManifest($this->environment->path('src/main/webapp/static/manifest.json'));
$frontend= new Frontend(
  new HandlersIn('com.example.skills.web', [$inject, 'get']),
  new Handlebars($this->environment->path('src/main/handlebars')),
  ['manifest' => $manifest] // <-- Here
) ;

Inside our templates

<link href="/static/{{lookup manifest.assets 'vendor.css'}}" rel="stylesheet">

However, if we introduce a typo (e.g. by 'vendors.css'), the link will simply resolve to "/static/" and then try to serve the directory, resulting in a 404 (see xp-forge/frontend#19). This is because how the lookup helper is defined.

The suggestion would be to fail early and introduce an asset helper which would raise an exception in these cases.

thekid commented 3 years ago

If we use the log helper as follows:

yield 'asset' => function($in, $context, $options) {
  $name= (string)$options[0];

  // We can rely on a logger being present, web.frontend.Handlebars creates one
  return $this->manifest->assets[$name] ?? key([$name => $context->engine->helper('log')(
    $in,
    $context,
    ['Missing asset in `'.(string)$in.'`, manifest contains: ', $this->manifest->assets]
  )]);
};

...we would see the following:

Development

image

Production

image

thekid commented 3 years ago

Here's how to integrate this helper, moving away from the solution above:

diff --git a/src/main/handlebars/edit.handlebars b/src/main/handlebars/edit.handlebars
index bed8d63..36fb8e4 100755
--- a/src/main/handlebars/edit.handlebars
+++ b/src/main/handlebars/edit.handlebars
@@ -90,7 +90,7 @@
     <br clear="all"/>
   {{/inline}}
   {{#*inline "script"}}
-    <script src="/static/{{lookup manifest.assets 'editor.js'}}"></script>
+    <script src="/static/{{asset 'editor.js'}}"></script>
     <script type="text/javascript">
       let _debounce = null;
       let editor;
diff --git a/src/main/php/com/example/skills/App.php b/src/main/php/com/example/skills/App.php
index 8b13f03..eb17bda 100755
--- a/src/main/php/com/example/skills/App.php
+++ b/src/main/php/com/example/skills/App.php
@@ -2,7 +2,7 @@

 use inject\{Injector, Bindings};
 use security\credentials\{Credentials, FromEnvironment, FromFile};
-use web\frontend\helpers\Dates;
+use web\frontend\helpers\{Assets, Dates};
 use web\frontend\{Frontend, HandlersIn, AssetsFrom, AssetsManifest, Handlebars};
 use web\rest\{RestApi, ResourcesIn};
 use web\session\{Sessions, InFileSystem, Cookies};
@@ -44,11 +44,11 @@ class App extends Application {
         new HandlersIn('com.example.skills.web', [$inject, 'get']),
         new Handlebars($this->environment->path('src/main/handlebars'), [
           new Dates(),
+          new Assets($manifest),
           new Translations($this->environment->path('src/main/handlebars/texts.csv')),
           new RenderMarkdown(),
           new RenderContent(),
-        ]),
-        ['manifest' => $manifest]
+        ])
       ))
     ];
   }
thekid commented 3 years ago

Released in https://github.com/xp-forge/handlebars-templates/releases/tag/v0.7.0