guppy
guppy copied to clipboard
Importing 'text' with 'text' format
Hi there,
I've been trying to find a solution to allow Guppy to import the following text:
"((text(abc def) * squareroot(((x * y) * z))) * text(more text))"
rendering using:
Guppy.Doc.render(<the above text>, <my element ID>, 'text');
which should render something like:
At the moment it seems to be getting hung up in the AST.to_xml
method because it tries to evaluate the text itself as a function name, which of course fails. I was thinking of adding a text
handler to the functions
object as:
functions['text'] = function(args) {
return (new window.DOMParser).parseFromString("<f type='text'><b p='latex'>\\text{" + args[0] + "}</b></f>", "text/xml")
}
then add a text_eval
method to unwrap the text itself:
text_eval: function(ast) {
// As far as I can tell, the AST first value is either `var`
if (ast[0] == 'var') {
return ast[1][0];
// Or it is a multiply AST tree
} else if (ast[0] == '*') {
var args = [];
for (var i = 0; i < ast[1].length; i++) {
args.push(AST.text_eval(ast[1][i]));
}
return n.join(' ');
}
}
and the AST.eval
method would be modified as such:
for(var i = 0; i < ast[1].length; i++){
if(Object.prototype.toString.call(ast[1][i]) === '[object Array]'){
if (ast[0] === 'text'){
args.push(AST.text_eval(ast[1][i]));
} else {
args.push(AST.eval(ast[1][i], functions, ast));
}
}
else{
args.push(ast[1][i]);
}
}
This seems to work as expected:
(or close enough - minus some padding around the text), but just wanted to get your thoughts on the issue. Happy to put the above changes into a PR if it would make understanding the issue a bit easier?
I guess some
tags around the args[0]
in the text
functions handler would 'fix' the spacing issue, but not sure that's a great solution. Also, the args[0]
isn't escaped so typing XML tags into the text breaks things. I didn't see any escaping with the other function handlers? Would it be safer to create the tags then set the inner text to the args[0]
value and let the DOM parser handle the escaping?
Hmm. An excellent point. It feels like this should be handled by the parser, since otherwise text_eval
has to be sure that forever into the future it remains able to undo whatever mess the parser made of the argument to text()
. I have a working experiment with minimal modifications to parser.js (and similarly a functions["text"]
implementation). I'll push after a little more testing, as I think this has turned up some large amount of dead code in the parser.
I think in the end I'm likely going to switch export/import format to XML. As well as the import issues described above, there is clearly no way that the importer can handle things like round brackets, and it doesn't behave particularly nicely with 'math like' characters (periods, exclamations, numbers, etc).
It might just be safer to just be fairly explicit regarding text within math, to say that exporting and importing in the text
format isn't/poorly supported??
Only 'real' option in my mind would be to add character escaping to the text contents when exporting? (well.. in reality it would only need to be the closing round bracket that would need to be escaped). If that were the case, the parser could be simplified to capture the entire text in one block? Thus also negating the need for any text eval code as the entire string would already be 'contained'.