Mustache.js: Retornando nomes de variáveis ​​de modelo

Criado em 31 dez. 2015  ·  12Comentários  ·  Fonte: janl/mustache.js

Oi! Esta é uma solicitação bastante estranha, mas existe alguma maneira de retornar a lista de variáveis ​​de entrada como uma matriz de string ou como um objeto? Para uma função de geração de código no meu código, preciso mapear uma série de entradas em
uma string com molde de bigode. As variáveis ​​de entrada são nomeadas exatamente da mesma forma que as variáveis ​​de modelagem e serão mapeadas/sombradas para elas perfeitamente e porque isso precisa ser feito automaticamente, daí a solicitação estranha. Aqui está um exemplo do que quero dizer:

Assumindo uma função 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}})

Eu estive pensando sobre isso por mais de uma hora e ainda não consigo encontrar uma maneira melhor de fazer isso. Ficaria muito grato se você pudesse oferecer alguns métodos alternativos etc.

Comentários muito úteis

Solução simples para obter apenas o nível superior:

Bigode.parse(template).filter(function(v) { return v[0] === 'nome' || v[0] === '#' || v[0] === '&' } ).map(função(v) { return v[1]; });

Todos 12 comentários

Se eu estou entendendo você corretamente, você quer algo assim

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

Isso assumindo que VariableNames foi e retornou todos os nomes de variáveis ​​do template. Se é isso que você quer, você provavelmente poderia hackear uma implementação usando a função exposta parse no escritor bigode.

Aqui está algum código para você começar:

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

Observe que, embora seja possível implementar uma versão ingênua disso, não há como extrair inequivocamente todos os nomes de tags, porque coisas assim:

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

… pode significar {foo: {bar: 'baz'}} _ou_ {foo: true, bar: 'baz'}} .

@bobthecow está totalmente certo nesta circunstância. O exemplo que dei apenas retiraria todos os nós identificadores, também removeria toda a estrutura efetivamente achatando a árvore.

@Romanx @bobthecow obrigado pela ajuda!

Sem problemas. Boa sorte :)

Eu tive uma solicitação semelhante, mas precisava percorrer a árvore para encontrar todos os nomes de variáveis. Pensei em compartilhar a solução que usei se alguém precisar de uma referência.

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 isso também sofre com o problema da ambiguidade?

Sim. É inerente à especificação do idioma.

O problema da ambiguidade é interessante, os documentos mencionam que tentaria encontrar o valor neste contexto e depois pesquisar o contexto do pai se nenhum valor fosse encontrado. Um pouco de investigação me levou a isso:

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

O exemplo é muito artificial, e há muitos truques usados ​​para se manter conciso, mas deve mostrar como é difícil reinventar a roda. Saúde

@Immortalin Você pode elaborar/fornecer uma definição melhor do problema? O que acontece com propriedades aninhadas em objetos? Você pode fornecer uma entrada e saída mais completa?

@dasilvacontin o projeto que requer esse recurso está atualmente em hiato, então vou fechar isso por enquanto

Solução simples para obter apenas o nível superior:

Bigode.parse(template).filter(function(v) { return v[0] === 'nome' || v[0] === '#' || v[0] === '&' } ).map(função(v) { return v[1]; });

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

MatthijsZw picture MatthijsZw  ·  18Comentários

amper5and picture amper5and  ·  5Comentários

funston picture funston  ·  7Comentários

zekth picture zekth  ·  18Comentários

connor11528 picture connor11528  ·  3Comentários