mde / ejs

Embedded JavaScript templates -- http://ejs.co
Apache License 2.0
7.71k stars 846 forks source link

Using views option with include tag does not retrieve file from one of the directories #617

Closed robogeek closed 3 years ago

robogeek commented 3 years ago

I'm trying to better integrate EJS with AkashaRender and would like to use the include EJS tag. What I gathered from the options object that specifying the views attribute should cause EJS to search the named directories for the file to include.

In an AkashaRender project there are several directories from which to load templates. Those directories are available as an array of path names. The directories are searched in order, and the first one containing the requested file is used. It seemed that the views option would be the method for integrating this model into EJS.

The documentation for this option says An array of paths to use when resolving includes with relative paths. That certainly implies exactly what's needed.

But - with the implementation I made, it does not work.

Here is a test program to demonstrate the problem.

const ejs = require('ejs');

const dirs = [
    '/Volumes/Extra/akasharender/akasharender/test/partials',
    '/Volumes/Extra/akasharender/akasharender/partials'
];

const rendered = ejs.render(`
<%- include('helloworld.html') %>
`, {
    views: dirs,
    filename: 'foo.html'
});

console.log(rendered);

Then... in the directory you see:

$ ls /Volumes/Extra/akasharender/akasharender/test/partials
helloworld.html            listrender.html.ejs        strong.html.handlebars
helloworld2.html           listrender.html.handlebars strong.html.tempura
json-format.html.ejs       listrender.html.tempura    test.html.njk
json-format.html.tempura   strong.html.ejs
$ cat partials/helloworld.html 
<div id="html-partial">
<p>This is a tiny partial meant to demonstrate synchronous templates.</p>
</div>

The file specified in the include tag is in one of the directories named in the views attribute. But running this code, I get the following error:

$ node ejst.js 
/Volumes/Extra/akasharender/akasharender/node_modules/ejs/lib/ejs.js:359
  throw err;
  ^

Error: foo.html:2
    1| 
 >> 2| <%- include('helloworld.html') %>
    3| 

Could not find the include file "helloworld.html"
    at getIncludePath (/Volumes/Extra/akasharender/akasharender/node_modules/ejs/lib/ejs.js:183:13)
    at includeFile (/Volumes/Extra/akasharender/akasharender/node_modules/ejs/lib/ejs.js:309:19)
    at include (/Volumes/Extra/akasharender/akasharender/node_modules/ejs/lib/ejs.js:690:16)
    at eval (eval at compile (/Volumes/Extra/akasharender/akasharender/node_modules/ejs/lib/ejs.js:662:12), <anonymous>:12:17)
    at anonymous (/Volumes/Extra/akasharender/akasharender/node_modules/ejs/lib/ejs.js:692:17)
    at Object.exports.render (/Volumes/Extra/akasharender/akasharender/node_modules/ejs/lib/ejs.js:423:37)
    at Object.<anonymous> (/Volumes/Extra/akasharender/akasharender/test/ejst.js:9:22)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32) {
  path: ''
}

Notice that setting the "filename" option simply updated the error output. Try running the script without the "filename" option, and the only change is that the error reports the filename "ejs" rather than "foo.html".

robogeek commented 3 years ago

WHOOPSIE!!

In my sample program, I forgot to include the data argument. Changing the program to this:

const rendered = ejs.render(`
<%- include('helloworld.html') %>
`, {}, {
    views: dirs,
    filename: 'foo.html'
});

Give it correct output.