Mustache.js: Namen von Template-Variablen zurückgeben

Erstellt am 31. Dez. 2015  ·  12Kommentare  ·  Quelle: janl/mustache.js

Hallo! Dies ist eine ziemlich seltsame Anforderung, aber gibt es trotzdem die Möglichkeit, die Liste der Eingabevariablen als Array von Zeichenfolgen oder als Objekt zurückzugeben? Für eine Codegenerierungsfunktion in meinem Code muss ich eine Reihe von Eingaben zuordnen
ein Schnurrbart-Template-String. Die Eingabevariablen werden genau so benannt wie die Templating-Variablen und werden ihnen perfekt schattiert / zugeordnet, und weil dies automatisch erfolgen muss, daher die seltsame Anforderung. Hier ist ein Beispiel dafür, was ich meine:

Angenommen eine Funktion Mustache.getTemplateVariablesListAsObject

var pycode = <see below>
Blockly.JavaScript['math_foo'] = function(block) {
  var value_name = Blockly.JavaScript.valueToCode(block, 'NAME', Blockly.JavaScript.ORDER_ATOMIC);
// result would be something like: {value_name: value_name}
var inputList =  Mustache.getTemplateVariablesListAsObject(pycode)

  var code = Mustache.render(pycode,  inputList)
  return code;
};
def hello(foo):
  print foo
hello({{value_name}})

Ich habe mehr als eine Stunde darüber nachgedacht und kann immer noch keinen besseren Weg finden, dies zu tun. Wäre wirklich dankbar, wenn Sie alternative Methoden usw. anbieten könnten.

Hilfreichster Kommentar

Einfache Lösung, um nur die oberste Ebene zu erreichen:

Mustache.parse(template).filter(function(v) { return v[0] === 'name' || v[0] === '#' || v[0] === '&' } ).map(function(v) { return v[1]; });

Alle 12 Kommentare

Wenn ich dich richtig verstehe, willst du so etwas

var myTemplate = "{{foo}} is {{bar}}";
var variableNames = Mustache.VariableNames(myTemplate) // ['foo', 'bar']

Das setzt voraus, dass VariableNames alle Variablennamen aus der Vorlage zurückgegeben hat. Wenn Sie das möchten, könnten Sie wahrscheinlich eine Implementierung hacken, indem Sie die exponierte parse -Funktion des Moustache-Writers verwenden.

Hier ist ein Code für den Einstieg:

var results = Mustache.parse('{{foo}} is {{bar}}')
                       .filter(function(v) { return v[0] === 'name' })
                       .map(function(v) { return v[1]; });

console.log(results) // ["foo", "bar"]

Beachten Sie, dass es zwar möglich ist, eine naive Version davon zu implementieren, es jedoch keine Möglichkeit gibt, alle Tag-Namen eindeutig zu extrahieren, da Dinge wie diese:

{{# foo }}
  * {{ bar }}
{{/ foo }}

… könnte entweder {foo: {bar: 'baz'}} _oder_ {foo: true, bar: 'baz'}} bedeuten.

@bobthecow hat in diesem Fall vollkommen recht. Das Beispiel, das ich gegeben habe, würde nur alle Identifikatorknoten herausziehen, es würde auch alle Strukturen entfernen, die den Baum effektiv abflachen.

@Romanx @bobthecow Danke für deine Hilfe!

Kein Problem. Viel Glück :)

Ich hatte eine ähnliche Anfrage, musste aber den Baum durchlaufen, um alle Variablennamen zu finden. Ich dachte, ich würde die von mir verwendete Lösung teilen, wenn jemand eine Referenz benötigt.

var parseTree = Mustache.parse('{{#foo}}{{bar}}{{/foo}} {{baz}}');
var variableList = parseTree.reduce(function flattenVariablesFromParseTree(acc, v){
                    if(v[0] === 'name'){
                      return acc.concat([v]);
                    } else if (v[0] === '#') {
                      return acc.concat(v[4].reduce(flattenVariablesFromParseTree, []));
                    } else {
                      return acc;
                    }
                  }, [])
                  .map(function(v){ return v[1]; });
//variableList: ["bar", "baz"]

@nicluo leidet dies auch unter dem Mehrdeutigkeitsproblem?

Ja. Es ist in der Sprachspezifikation enthalten.

Das Mehrdeutigkeitsproblem ist interessant, die Dokumentation erwähnt, dass es versuchen würde, den Wert in diesem Kontext zu finden und dann den Kontext des übergeordneten Elements zu durchsuchen, wenn keine Werte gefunden werden. Eine kleine Recherche hat mich dazu gebracht:

{{bar}} 
{{#foo}}
  {{bar}} 
  {{#foo}}
    {{bar}} 
    {{#baz}}
      {{no}} 
      {{yes}}
    {{/baz}}
  {{/foo}}
{{/foo}}

var renderString = '{{bar}} {{#foo}}{{bar}} {{#foo}}{{bar}} {{#baz}}{{no}} {{yes}}{{/baz}}{{/foo}}{{/foo}}';
var renderContext = new Mustache.Context({
  bar: 'bar',
  baz: {
    no: 'no'
  },
  foo: {
    bar: 'y',
    foo: {
      bar: 'z',
      yes: 'yes'
    }
  }});

var parseTree = Mustache.parse(renderString);
var variableRefList = [];
var variableNameList = parseTree.reduce(function flattenVariablesFromParseTree(acc, v){
                    // Skip non-name or non-# tags
                    if(v[0] !== 'name' && v[0] !== '#'){
                      return acc;
                    }

                    var paths = [v[1]].concat(this.parents.slice(0).map(function(e){
                      return [e, v[1]].join('.');
                    }));

                    // Pops available context until a value is found
                    var path;
                    while(path = paths.pop()){
                      if(renderContext.lookup(path)){
                        //push to advanced list
                        variableRefList.push(path);
                        contextFound = true;
                        break;
                      }
                    }

                    if(v[0] === 'name'){
                      return acc.concat([v]);
                    } else if (v[0] === '#')  {
                      if(typeof renderContext.lookup(path) === 'object'){
                        this.parents = this.parents.concat([path]);
                      }

                      return acc.concat(v[4].reduce(
                        flattenVariablesFromParseTree.bind({
                          parents: this.parents
                        }), []));
                    }
                  }.bind({parents: []}), [])
                  .map(function(v){ return v[1]; });

//variableNameList: ["bar", "bar", "bar", "no", "yes"]
//variableRefList: ["bar", "foo", "foo.bar", "foo.foo", "foo.foo.bar", "baz", "baz.no", "foo.foo.yes"]
//Mustache.render(renderString, renderContext): bar y z no yes

Das Beispiel ist sehr erfunden, und es gibt viele Tricks, um knapp zu bleiben, aber es sollte zeigen, wie schwierig ich es finde, das Rad neu zu erfinden. Prost

@Immortalin Können Sie das Problem näher erläutern / besser definieren? Was passiert mit Eigenschaften, die in Objekten verschachtelt sind? Können Sie eine vollständigere Eingabe und Ausgabe bereitstellen?

@dasilvacontin Das Projekt, das diese Funktion erfordert, befindet sich derzeit in einer Pause, daher werde ich es vorerst schließen

Einfache Lösung, um nur die oberste Ebene zu erreichen:

Mustache.parse(template).filter(function(v) { return v[0] === 'name' || v[0] === '#' || v[0] === '&' } ).map(function(v) { return v[1]; });

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

kuldeepdhaka picture kuldeepdhaka  ·  9Kommentare

SmasherHell picture SmasherHell  ·  18Kommentare

barbalex picture barbalex  ·  5Kommentare

mbrodala picture mbrodala  ·  16Kommentare

MatthijsZw picture MatthijsZw  ·  18Kommentare