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.
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]; });
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]; });