Mustacheテンプレートはテンプレート拡張を行うことができますか?

私は口ひげには新しいです。

多くのテンプレート言語( Django / Jinja など)では、「親」テンプレートを拡張できます。

base.html

<html><head></head>
    <body>
    {% block content %}{% endblock %}
    </body>
</html>

frontpage.html

{% extends "base.html" %}
{% block content %}

Foobar!

{% endblock %}

レンダリングされたfrontpage.html

<html><head></head>
    <body>
    

Foobar!

</body> </html>

I'm aware of Mustache's partials (e.g., {{>content}}), but those seem to be just includes.

Mustacheのテンプレート拡張機能はありますか?または、それに失敗しても、インクルードを効果的にテンプレート拡張に変換するデザインパターンが少なくともあります。

51

8 答え

私は最近、マコのバックグラウンドから来た以外は、同じボートで自分自身を見つけました。

口ひげはテンプレートの拡張/継承を許可していませんが、あなたが知っているいくつかのオプションがあります。

  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.

59
追加された
PHPでインクルードする方法と部分的に似ていますか?
追加された 著者 Alvaro,
{{{body}}}
追加された 著者 Chris W.,
はい、残念ながらあなたは正しいですが、私のために#4を除外します。私は答えを更新しました。
追加された 著者 Walden,
最終的に、再利用可能なサブテンプレートを作成し、テンプレートローディングコード(つまり#5)に継承を実装することは、より柔軟で、より安全です。テンプレート継承の問題は、外部テンプレートを記述するときに、子テンプレートに必要なもの(または必須ではないもの)を決して理解できないことです。これは、外側のテンプレート内の特定の子ページ(ただし別の子ページには不要)に必要なJS/CSSを含むことがあります。テンプレートの継承を使用するときにこの問題を回避する唯一の方法は、JS/CSS要件を変数として渡すことです。
追加された 著者 Walden,
口ひげの Twitterのバージョンは、テンプレート継承を参照してください。
追加された 著者 Walden,
(@Waldenおそらく、あなたのリストにNo。0またはNo。6を追加してHoogianに言及するべきでしょうか?とにかくコメントを追加してくれてありがとう:-))
追加された 著者 KajMagnus,

私はここでMustacheの仕様にこれを提案しました:

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

現在、mustache.java、hogan.js、phly_mustacheはテンプレートの継承をサポートしています。

12
追加された
ただし、Hogan.jsについては、ドキュメントからは分かりませんが、 github.com /twitter/hogan.js/issues/70
追加された 著者 Paul D. Waite,
GRMustacheも同様です。
追加された 著者 Gwendal Roué,

口ひげはテンプレート拡張をしません。

テンプレート拡張を本当にしたいのであれば、言語/フレームワークの選択肢として、この機能で構築されたライブラリの目的を使用することができます。


FYI, I'm using Node.js/Express, so I will probably end up using https://github.com/fat/stache

3
追加された
W Stashは維持されておらず、hogan.js(推奨置換)は拡張を実装していないようです。
追加された 著者 mikemaccana,
TwitterのHoogianは継承をサポートしているようだ。最近のコミットを参照してください: Hogan 3.テンプレート継承を追加...
追加された 著者 KajMagnus,

口ひげのPHPでは、テンプレートの継承はバージョン2.7.0以降でサポートされています。

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

Mustache/Engine.phpファイルから現在のバージョンを把握し、以下を含む行を検索することができます:

class Mustache_Engine
{
    const VERSION        = '2.8.0';
    ...
3
追加された

HTMLを含む変数を使用できます。 {{{variable}}} のような「トリプルヒゲ」は、エスケープされていないHTMLを返します。テンプレートの拡張機能とまったく同じではありませんが、 frontpage-content.html をレンダリングし、その出力を content 変数に入れて baseに渡します。 html ]をクリックします。

(この名前パターンがファイル名の管理に役立つことを期待して、 frontpage.html ファイル名に content を追加しました)。

3
追加された

私はPythonでこれを使って遊んでいます(私はMakoの作成者です)。動的なコンテキストで、セクションをキャプチャすることは正しいことをしているように見えますが、これをさらにテストする必要があります。

Basically we are using lambdas, where a "<" prefix indicates "inherit from this template" (similar to the syntax discussed at https://github.com/mustache/spec/issues/38) and a "$" prefix indicates "this is an inherited section".

import pystache

class NameSpace(object):
    def __init__(self, renderer, vars_={}):
        self.renderer = renderer
        self._content = {}
        self.vars = vars_

    def add_content(self, name, value):
        self._content[name] = value

    def __getattr__(self, key):
        if key in self.vars:
            # regular symbol in the vars dictionary
            return self.vars[key]
        elif key.startswith("<"):
            # an "inherit from this template" directive
            name = key[1:]
            return inheritor(self, name)
        elif key.startswith("$"):
            # a "here's a replaceable section" directive
            name = key[1:]
            if name in self._content:
                # if we have this section collected, return the rendered
                # version
                return sub_renderer(self, name)
            else:
                # else render it here and collect it
                return collector(self, name)
        else:
            # unknown key.
            raise AttributeError(key)

def sub_renderer(namespace, key):
    def go():
        def render(nested):
            return namespace._content[key]
        return render
    return go


def collector(namespace, key):
    def go():
        def render(nested):
            content = namespace.renderer.render(nested, namespace)
            namespace.add_content(key, content)
            return content
        return render
    return go


def inheritor(namespace, name):
    def go():
        def render(nested):
            namespace.renderer.render(nested, namespace)
            return namespace.renderer.render_name(name, namespace)
        return render
    return go

ここにいくつかのテンプレートがあります。 base.mustache:

<html>

{{#$header}}
    default header
{{/$header}}

{{#$body}}
    default body
{{/$body}}

{{#$footer}}
    default footer, using {{local key}}
{{/$footer}}


</html>

hello.mustache:

{{#

and then to play with three levels deep, subhello.mustache:

{{#

このようにhello.mustacheをレンダリングする:

renderer = pystache.Renderer(search_dirs=["./templates/"])

print renderer.render_name("hello",
                    NameSpace(renderer, {"local key": "some local key"}))

出力:

<html>

    new header

    new body, with some local key

    default footer, using some local key


</html>

Rendering subhello.mustache:

print renderer.render_name("subhello",
                    NameSpace(renderer, {"local key": "some local key"}))

出力:

<html>

    new header

    new body, with some local key

    im some new footer


</html>

私はちょうど20分でこれを書いた、そして私はハンドルバーを使用したことがある。過去にはちょっと過去と痛い。今では "口ひげ"のアイデアはまだ深いものではない。しかし、これは動作するようですか?

1
追加された

あなたがサーバーサイドのコードに満足しているなら、 NunはMustacheのようなテンプレートシステムであり、テンプレートオーバーライド '機能 - djangoをモデルにしています。しかし、それは動作しますが、それはもはやその著者によって維持されていません。

0
追加された

node.jsでは、 express-handlebars または hogan-express を使ってひな形テンプレートをレイアウトすることはできますが、テンプレート自体にレイアウトを設定することはできませんレイアウトはアプリコードに登録されます。

0
追加された
JavaScript - 日本のコミュニティ
JavaScript - 日本のコミュニティ
2 参加者の

日本人コミュニティのjavascript