Je sais que c'est une vieille question, mais je voulais quand même ajouter une réponse qui propose une autre approche.
Réponse principale
Mustache prend en charge les lambdas, (voir la documentation), donc on peut l'écrire de cette manière :
Modèle :
{{#removeTrailingComma}}{{#items}}{{name}}, {{/items}}{{/removeTrailingComma}}
Hash :
{
"items": [
{"name": "red"},
{"name": "green"},
{"name": "blue"}
]
"removeTrailingComma": function() {
return function(text, render) {
var original = render(text);
return original.substring(0, original.length - 2);
}
}
}
Sortie :
red, green, blue
Commentaire
Personnellement, j'aime bien cette approche par rapport aux autres, car selon moi, le modèle ne devrait spécifier que ce qui est rendu et pas comment c'est rendu. Techniquement, la lambda fait partie du modèle, mais l'intention est bien plus claire.
J'utilise cette approche pour écrire mes propres générateurs OpenApi. Là, Mustache est enveloppé par Java, mais la fonctionnalité est à peu près la même. Voici à quoi ressemblent la création de lambdas pour moi : (en Kotlin)
override fun addMustacheLambdas(): ImmutableMap.Builder =
super.addMustacheLambdas()
.put("lowerCase", Mustache.Lambda { fragment, writer ->
writer.write(fragment.execute().toLowerCase())
})
.put("removeLastComma", Mustache.Lambda { fragment, writer ->
writer.write(fragment.execute().removeSuffix(","))
})
.put("printContext", Mustache.Lambda { fragment, writer ->
val context = fragment.context()
println(context) // très utile pour le débogage si vous n'êtes pas l'auteur du modèle
writer.write(fragment.execute())
})