Can Mustache Templates do template extension?

后端 未结 9 509
醉话见心
醉话见心 2021-01-30 06:39

I\'m new to Mustache.

Many templating languages (e.g., Django / Jinja) will let you extend a \"parent\" template like so...

ba

相关标签:
9条回答
  • 2021-01-30 06:59

    I've proposed this to the specification for Mustache here:

    https://github.com/mustache/spec/issues/38

    Currently mustache.java, hogan.js and phly_mustache support template inheritance.

    0 讨论(0)
  • 2021-01-30 07:01

    You could use variables containing HTML. A "triple mustache" like {{{variable}}} will return unescaped HTML. It's not exactly the same as template extensions, but you could render frontpage-content.html and then put its output in a content variable that gets passed to base.html.

    (I added -content to the frontpage.html filename with the expectation that such a naming pattern will help keep the filenames manageable.)

    0 讨论(0)
  • 2021-01-30 07:02

    I recently found myself in the same boat, except I came from a mako background.

    Mustache does not allow for template extension/inheritance but there are a few options available to you that I know of.

    1. You could use partials:

      {{>header}}
          Hello {{name}}
      {{>footer}}
      
    2. You could inject template pre-processing functions into the context for each template that needs to inherit from some other page:

      {{#extendBase}}      
          Hello {{name}}
      {{/extendBase}} 
      

      Hash:

      {
         "name": "Walden",
         "extendBase": function() {
             return function(text) {
                 return "<html><head></head>" + render(text) + "</body></html>"
             }
         }
      }
      
    3. Prepend and append the desired HTML to the relevant pages in your controller.

    4. Have a layout template ala:

      {{>header}}
          {{{body}}}
      {{>footer}}
      

      And render the body in your controller, passing that to the layout template as a variable named body.

    5. Implement template inheritance, pre-mustache, in your code that loads templates.

    I wouldn't, however, use the triple mustache because I don't want unescaped HTML to be appearing anywhere, it's just too risky in my opinion.

    If someone else has a better solution to this problem I'd love to hear it as well, since I haven't yet taken the plunge in any one of these directions.

    0 讨论(0)
  • 2021-01-30 07:05

    I wrote a short code to enable extend and create layouts. .

    If you don't want to copy/paste the header/footer, or maybe an menu bar that is repeated in all admin sub sections, each time you render a page/view, you just need to use the function: build of the followed class, that you can use as utils module

    class MustacheLayout {
      constructor() {
        if (!MustacheLayout.instance) {
          MustacheLayout.instance = this;
        }
        return MustacheLayout.instance;
      }
    
      async build(...layers) {
        let previousLayer = '';
        let combinedLayout = '';
        for (const layer of layers) {
          const { name: layerName } = layer;
          let { data: layerData } = layer;
          if (!layerData) layerData = {};
          layerData.child = previousLayer;
          combinedLayout = await this.renderHtml(layerName, layerData);
          previousLayer = combinedLayout;
        }
        return combinedLayout;
      }
    
      renderHtml(viewName, data) {
        return new Promise((resolve, reject) => {
          this.app.render(viewName, data, (error, html) => {
            if (error) reject(error);
            resolve(html);
          });
        });
      }
    
      setExpressApp(expressApp) {
        this.app = expressApp;
      }
    }
    
    module.exports = new MustacheLayout();
    
    • In your server.js/index file of express app, add the app instance to our class.
    //import the class const mustacheLayout = require('') //
    const app = express();;
    mustacheLayout.setExpressApp(app);
    

    Controller

    Put all the layer in the build function as parameters,

    warning: - you need to respect order, from the smallest layout to the biggest (base.html) - data properties should be named as in the view

    const layout = require('mustache-layout');
    
    router.get('/edit', async (_, res) => {
        const user = 'admin'
        const html = await layout.build(
            { name: 'admin/edition/editor.view.html', data: { user } },
            { name:'layout/base.view.html' }
        )
        return res.send(html);
    });
    

    View

    warning You need to use the keyword child in layout view pages. don't forget triple braces {{{ }}}

    Use your passed data here

    <!-- ditor.view.html -->
    <div> {{ user }} </div>
    
    <!-- base.view.html -->
    <!DOCTYPE html>
    <html lang="en">
    <body>
        {{ > layout/header.view }}
        <div class="main">
            <div class="layout-content">
                {{{ child }}}
            </div>
        </div>
        {{ > layout/footer.view }}
    </body>
    </html>
    

    If you need the package version of this code check mustache-layout-s

    0 讨论(0)
  • 2021-01-30 07:09

    In node.js you can use express-handlebars or hogan-express to have layouts inna mustache templates, but the way they do things is different, in none of them you set the layout at the template itself, layouts are registered in your app code.

    0 讨论(0)
  • 2021-01-30 07:11

    In mustache php, template inheritance is supported since version 2.7.0.

    https://github.com/bobthecow/mustache.php/wiki/BLOCKS-pragma

    You can figure out your current version from the file Mustache/Engine.php and search for the line containing:

    class Mustache_Engine
    {
        const VERSION        = '2.8.0';
        ...
    
    0 讨论(0)
提交回复
热议问题