Skip to content

template tag function? #74

Open
Open
@trusktr

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)}>&times;</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)}>&times;</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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions