emaphp / underscore-template-loader

A Underscore and Lodash template loader for Webpack
MIT License
104 stars 24 forks source link

Cannot use variables for attributes in include or require macros #28

Open jamesehly opened 6 years ago

jamesehly commented 6 years ago

It would be cool if we could use variables with the require and include macros, but it looks like they can only accept string, number, boolean and objects at the moment. For instance, doing this:

@include(htmlWebpackPlugin.options.filename)

results in...

ERROR in   Error: Child compilation failed:
  Module not found: Error: Can't resolve './NaN' in 'C:\static\outkit-docs\src\templates\docs':
  Error: Can't resolve './NaN' in 'C:\static\outkit-docs\src\templates\docs'

Does anyone know of a workaround for this?

idudinov commented 5 years ago

+1, the other possible desired use case is something like that – just use something JS evaluate-able :

@require('./header.html', {
    someValue: 2 + 3,
    title: (originalTitle && originalTitle.trim()) || 'no title',
})

This could allow to have more dynamic and complex templating, and generate more static htmls instead of having it in runtime.

idudinov commented 5 years ago

OK, I've investigated the sources a bit, and have found out that object literal (used as second @require argument) is processed by JSON.parse and then by JSON.stringify inside the loader, so should be evaluated somehow before @require is parsed. But as for now, it doesn't seem feasible to me to swap the order of parsing steps or add additional one. So I have no idea how that feature can be implemented.

idudinov commented 5 years ago

A workaround came to me suddenly :) Tricky a bit, and uses portions of the loader's source code as example, but here it is:

<%
    const title = 'Some ' + 'title';
    const headFileName = htmlWebpackPlugin.options.headFileName || 'head.ejs';

    function objExtend(args, obj) {
        args = Array.prototype.slice.call(args);
        args[0] = Object.assign(obj, args[0]);
        return args;
    };
%>

<%= require(`./structure/${headFileName}`).apply(null, objExtend(arguments, { title })) %>