Mustache.js: Devolver nombres de variables de plantilla

Creado en 31 dic. 2015  ·  12Comentarios  ·  Fuente: janl/mustache.js

¡Hola! Esta es una solicitud bastante extraña, pero ¿hay alguna forma de devolver la lista de variables de entrada como una matriz de cadenas o como un objeto? Para una función de generación de código en mi código, necesito mapear una serie de entradas en
una cadena con plantilla de bigote. Las variables de entrada se nombran exactamente igual que las variables de plantilla y las sombrearán/asignarán perfectamente y porque esto debe hacerse automáticamente, de ahí la extraña solicitud. He aquí un ejemplo de lo que quiero decir:

Asumiendo una función 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}})

He estado pensando en esto durante más de una hora y todavía no puedo encontrar una mejor manera de hacerlo. Estaría muy agradecido si puede ofrecer algunos métodos alternativos, etc.

Comentario más útil

Solución simple para obtener solo el nivel superior:

Moustache.parse(plantilla).filtro(función(v) { return v[0] === 'nombre' || v[0] === '#' || v[0] === '&' } ).mapa(función(v) { devuelve v[1]; });

Todos 12 comentarios

Si te entiendo bien quieres algo como esto

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

Eso suponiendo que VariableNames fue y devolvió todos los nombres de variables de la plantilla. Si eso es lo que desea, probablemente podría hackear una implementación utilizando la función parse expuesta en el escritor de bigotes.

Aquí hay un código para que comiences:

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"]

Tenga en cuenta que si bien es posible implementar una versión ingenua de esto, no hay forma de extraer sin ambigüedades todos los nombres de las etiquetas, porque cosas como esta:

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

… podría significar {foo: {bar: 'baz'}} _o_ {foo: true, bar: 'baz'}} .

@bobthecow tiene toda la razón en esta circunstancia. El ejemplo que di solo sacaría todos los nodos identificadores, también eliminaría toda la estructura aplanando efectivamente el árbol.

@Romanx @bobthecow ¡ gracias por tu ayuda!

No hay problema. Buena suerte :)

Tuve una solicitud similar, pero necesitaba atravesar el árbol para encontrar todos los nombres de variables. Pensé en compartir la solución que utilicé si alguien necesita una referencia.

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 , ¿esto también sufre el problema de la ambigüedad?

Sí. Es inherente a la especificación del idioma.

El problema de la ambigüedad es interesante, los documentos mencionan que intentaría encontrar el valor en este contexto y luego buscaría en el contexto del padre si no se encuentran valores. Un poco de investigación me llevó a esto:

{{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

El ejemplo es muy artificial y se utilizan muchos trucos para ser conciso, pero debería mostrar lo difícil que me resulta reinventar la rueda. Salud

@Immortalin ¿Puede elaborar / proporcionar una mejor definición del problema? ¿Qué sucede con las propiedades anidadas en los objetos? ¿Puede proporcionar una entrada y salida más completa?

@dasilvacontin el proyecto que requiere esta función está actualmente en pausa, así que voy a cerrar esto por el momento

Solución simple para obtener solo el nivel superior:

Moustache.parse(plantilla).filtro(función(v) { return v[0] === 'nombre' || v[0] === '#' || v[0] === '&' } ).mapa(función(v) { devuelve v[1]; });

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

amper5and picture amper5and  ·  5Comentarios

zekth picture zekth  ·  18Comentarios

mbrodala picture mbrodala  ·  16Comentarios

rlightner picture rlightner  ·  7Comentarios

barbalex picture barbalex  ·  5Comentarios