LoginSignup
0
0

More than 1 year has passed since last update.

【Tips】Typescript+Mustache.jsでリカーシブなテンプレートを作成する方法

Posted at

はじめに

Mustache.jsは便利だが、リカーシブなテンプレートを作成したい場合にはクセがあり分かりにくい。
やり方をググってもなかなか出てこないので、やり方をメモっておく。

Mustacheテンプレート

コードは以下のように作っておく。
> attributeの部分が、Partialsという部品呼び出しの記法だ。これ自体は、メインのテンプレートファイルが大きくなりすぎる場合に部品を切り出すための記法であるが、これを応用することでリカーシブに呼ぶことができる。

main.mustache
{{#attributes}}
{{> attribute}}
{{/attributes}}
attribute.mustache
{{attributeName}}
{{#attributeValue}}
  {{> attribute}}
{{/attributeValue}}

Typescriptのサンプル① 短項目の場合

上記の機能を呼び出すタイプスクリプトは以下のように書ける。

index.ts
import * as Mustache from 'mustache';
import { readFileSync } from 'fs';

const path = require('path');

type templateDataAttribute = {
  attributeName: string;
  attributeValue: null | (string | templateDataAttribute)[];
}

type templateData = {
  attributes: templateDataAttribute[];
}

const main = () => {
  const template: string = readFileSync(path.join(__dirname, 'mustache/main.mustache'), 'utf-8');
  const partial: string = readFileSync(path.join(__dirname, 'mustache/attribute.mustache'), 'utf-8');

  {
    const templateData: templateData = {
      attributes: [{
        attributeName: 'hoge',
        attributeValue: null,
      }],
    };

    console.log('--- case 1 ---');
    console.log(Mustache.render(template, templateData, { attribute: partial }));
  }
};

main();

上記を実行すると、以下のような出力が得られる。

--- case 1 ---
hoge

nullで終端することで、attribute.mustache側の{{#attributeValue}}が呼ばれなくなるという仕組みだ。

Typescriptのサンプル① 1階層ネストでのリカーシブコール

上記のindex.tsのmain()関数に以下のコードを書き加える。

index.ts
// 前略
  {
    const templateData: templateData = {
      attributes: [{
        attributeName: 'hoge',
        attributeValue: [{
          attributeName: 'hige',
          attributeValue: null,
        }],
      }],
    };

    console.log('--- case 2 ---');
    console.log(Mustache.render(template, templateData, { attribute: partial }));
  }
// 以下略

上記を実行すると、以下のような出力が得られる。

--- case 2 ---
hoge
  hige

ここまでくれば、あとはお手の物だろう。

Typescriptのサンプル③ 2階層ネストでのリカーシブコール

上記のindex.tsのmain()関数に以下のコードを書き加える。

index.ts
// 前略
  {
    const templateData: templateData = {
      attributes: [{
        attributeName: 'hoge',
        attributeValue: [{
          attributeName: 'hige',
          attributeValue: [{
            attributeName: 'hage',
            attributeValue: null,
          }],
        }],
      }],
    };

    console.log('--- case 3 ---');
    console.log(Mustache.render(template, templateData, { attribute: partial }));
  }
// 以下略

上記を実行すると、以下のような出力が得られる。

--- case 3 ---
hoge
  hige
    hage

バッチリ2段階のネストもいける!
ループや条件分岐も組み合わせることで、複雑な構造もMustacheのみで書けそうだ!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0