Description
Is it possible to do something similar to eval(compile(\
...`))` but with a template tag function?
For example, instead of
const div = <div {...props} />;
we could write
const div = s`<div {...${props}} />`;
(or similar) and both would compile to
const div = (() => {
var __ = document.createElement("div");
Surplus.spread(__, props);
return __;
})();
Note how in the example I left the ...
in the string, as I imagine Surplus needs to detect things like spread and function call parens to make it work properly. F.e.
const div = <div className={className()}/>;
becomes
const div = s`<div className={${className}()}/>`;
and notice the ()
is in the string.
But maybe the ${}
syntax is too complicated in some cases? F.e. imagine writing this example as a template string:
const view = // declarative main view
<div>
<h2>Minimalist ToDos in Surplus</h2>
<input type="text" fn={data(newTitle)}/>
<a onClick={addTodo}> + </a>
{todos.map(todo => // insert todo views
<div>
<input type="checkbox" fn={data(todo.done)}/>
<input type="text" fn={data(todo.title)}/>
<a onClick={() => todos.remove(todo)}>×</a>
</div>
)}
</div>;
What's nice about template strings is that various editors now have support for syntax highlighting inside template strings, so if we could at least change
eval(compile(`...`))
to
eval(compile`...`) // without parens on the compile call
then we'd have support for syntax highlight. compile
could still take a single string, just like in the codepen examples, and docs would tell us not to use ${}
interpolation.
Another posibility could be to remove eval, and let us pass parameters in, maybe something like this:
const view = s`
<div>
<h2>Minimalist ToDos in Surplus</h2>
<input type="text" fn={data(newTitle)}/>
<a onClick={addTodo}> + </a>
{todos.map(todo => // insert todo views
<div>
<input type="checkbox" fn={data(todo.done)}/>
<input type="text" fn={data(todo.title)}/>
<a onClick={() => todos.remove(todo)}>×</a>
</div>
)}
</div>
${ { data, newTitle, addTodo, todos } }
`;
Notice it is taking advantage of object shorthand to make props that match the names of identifiers inside the string. Eval could then be used internally. Notice I didn't pass in todo
, as the compiler be able to infer this from the map callback arg, plus on the outside I don't have a reference to any single todo.
Maybe
eval(s`...`)
is the simplest way to do it, a tag function that expects us not to use ${}
interpolation.
Activity