106 votes

En Mustache templating, y a-t-il un moyen élégant d'exprimer une liste séparée par des virgules sans la virgule finale ?

Je suis en train d'utiliser la bibliothèque de modèles Mustache et j'essaie de générer une liste séparée par des virgules sans virgule finale, par exemple

rouge, vert, bleu

Créer une liste avec la virgule finale est simple, étant donné la structure

{
  "items": [
    {"name": "rouge"},
    {"name": "vert"},
    {"name": "bleu"}
  ]
}

et le modèle

{{#items}}{{name}}, {{/items}}

ceci se traduira par

rouge, vert, bleu,

Cependant, je ne vois pas de moyen élégant d'exprimer le cas sans la virgule finale. Je peux toujours générer la liste dans le code avant de la passer dans le modèle, mais je me demandais si la bibliothèque offre une approche alternative, comme vous permettre de détecter s'il s'agit du dernier élément dans une liste dans le modèle.

0voto

王子1986 Points 89

Si vous utilisez Java, vous pouvez utiliser ce qui suit :

https://github.com/spullara/mustache.java/blob/master/compiler/src/test/java/com/github/mustachejava/util/DecoratedCollectionTest.java

MustacheFactory mf = new DefaultMustacheFactory();
Mustache test = mf.compile(new StringReader("{{#test}}{{#first}}[{{/first}}{{^first}}, {{/first}}\"{{value}}\"{{#last}}]{{/last}}{{/test}}"), "test");
StringWriter sw = new StringWriter();
test.execute(sw, new Object() {
    Collection test = new DecoratedCollection(Arrays.asList("one", "two", "three"));
}).flush();
System.out.println(sw.toString());

0voto

LostMekkaSoft Points 83

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())
            })

0voto

tmdoit Points 39

Je utilise des fonctions personnalisées pour cela, dans mon cas lorsque je travaille avec des requêtes SQL dynamiques.

    $(document).ready(function () {
    var output = $("#output");    
    var template = $("#test1").html();
    var idx = 0;
    var rows_count = 0;
    var data = {};

    data.columns = ["name", "lastname", "email"];
    data.rows  = [
      ["John", "Wick", "john.wick@hotmail.com"],
      ["Donald", "Duck", "donald.duck@ducks.com"],
      ["Anonymous", "Anonymous","jack.kowalski@gmail.com"]
    ];

    data.rows_lines = function() {
      let rows = this.rows;
      let rows_new = [];
      for (let i = 0; i < rows.length; i++) {
        let row = rows[i].map(function(v) {
            return `'${v}'`
        })
        rows_new.push([row.join(",")]);
      }
      rows_count = rows_new.length;
      return rows_new
    }

    data.last = function() {
        return idx++ === rows_count-1; // omit comma for last record
    }

    var html = Mustache.render(template, data);
    output.append(html);

});

Mustache example: Generate SQL query (last item support - omit comma for last insert)

    INSERT INTO Customers({{{columns}}})<br/>
    VALUES<br/>
      {{#rows_lines}}
         ({{{.}}}){{^last}},{{/last}}<br/>
      {{/rows_lines}}

https://jsfiddle.net/tmdoit/4p5duw70/8/

0voto

Peter Krauss Points 1888

La solution @LostMekkaSoft a du sens, mais lambda pose problème pour les tâches simples (fonctions d'aide):

Peut-être qu'une solution est une fonction d'aide complexe qui "injecte" ce genre de lambdas standard dans l'entrée, par une configuration d'entrée supplémentaire... Une autre solution est d'élire un ensemble de "fonctions standard" et de le construire en tant que bibliothèque de fonctions d'aide standard Mustache pour chaque langue.

Mustache a besoin d'une bibliothèque d'aides standard

Supposons une bibliothèque de fonctions d'aide Mustache ms_*. Exemple de la définition de ms_items_setLast(). Pour implémenter, la solution la plus votée ici (en 2021) est la solution de @Clyde sur StackOverflow; donc, la généralisant pour n'importe quel langage :

Pour Javascript :

function ms_items_setLast(x,label='') {
   if (label=='' || label === undefined)
     x[ x.length - 1 ].last = true
   else
     x[label][ x[label].length - 1 ].last = true
   return x
}
// model = ms_items_setLast(model,'items');

Pour Python :

def ms_items_setLast(x,label=''):
   if label=='':
      x[ len(x) - 1 ]['last'] = True
   else:
      x[label][ len(x[label]) - 1 ]['last'] = True

l'utiliser dans le terminal :

model = {
"items": [
    {"name": "red"},
    {"name": "green"},
    {"name": "blue"}
  ]
}
items= [
    {"name": "red"},
    {"name": "green"},
    {"name": "blue"}
]
ms_items_setLast(model,'items')
ms_items_setLast(items)
model
items

donne comme résultats

>>> model
{'items': [{'name': 'red'}, {'name': 'green'}, {'name': 'blue', 'last': True}]}
>>> items
[{'name': 'red'}, {'name': 'green'}, {'name': 'blue', 'last': True}]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X