Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Includes now throwing errors #477

Closed
ghost opened this issue Nov 24, 2019 · 11 comments
Closed

Includes now throwing errors #477

ghost opened this issue Nov 24, 2019 · 11 comments

Comments

@ghost
Copy link

ghost commented Nov 24, 2019

After updating to the latest version of EJS, I am now getting errors while compiling my EJS templates.

The error message is:
SyntaxError: Unexpected token .

I believe the lines causing these issues are include lines such as the following, as when removing such lines the errors cease.
<% include ../partials/bootstrap/bootstrap_header.ejs %>
<% include ../partials/main_components/head_to_body.ejs %>

I couldn't find any changes in the changelog which would cause this. Thanks,

@ghost ghost changed the title Broken Includes Includes now throwing errors Nov 24, 2019
@Nike1016
Copy link

@ghost
Copy link
Author

ghost commented Nov 24, 2019

Huh? Link seems to be broken.

@mde
Copy link
Owner

mde commented Nov 24, 2019

It's in the current changelog: "Removed legacy preprocessor include." That usage of include is leftover from the very old v1, and was left for one major version (and for quite a long time) for backward compatibility.

We are following the semver convention of a major version bump when changing the public API. In fact, this hacky legacy feature was never actually documented in v2, but there were tests for it, so we have done a major version bump to v3. If your app depends on this feature, you can continue to install a v2.x.

Otherwise, you can convert to the modern include function call that is well documented, well supported, and will continue to exist in all future versions of EJS.

@ghost
Copy link
Author

ghost commented Nov 25, 2019

Ok, sorry for the lacking research.

For anyone else with the issue, you can change the old version of include:
<% include ../partials/bootstrap/bootstrap_header.ejs %>
to:
<%- include('../partials/bootstrap/bootstrap_header.ejs') %>

@henderea
Copy link

henderea commented Dec 4, 2019

I've been using the include directive in some EJS code I pre-compile into a single function with a gulp task, but it seems the include(...) function doesn't work the same. Is that something that will start working once the gulp task packages support EJS 3.x, or is there something else I would need to do to get those other files embedded into the overall function?

@simllll
Copy link

simllll commented Dec 5, 2019

the major difference is that include 'file.ejs' has passed all parameters as a side effect, but include('file.ejs') does not. Any idea how I can pass the whole data context to the include method to get an easy transition?

@henderea
Copy link

henderea commented Dec 5, 2019

Well, what I meant is that my gulp task gives me an output that has the include('parts/part1.ejs') method call instead of the content of the file. I'm pre-compiling the templates for use in the browser, so I can't have it pulling in other files like that. Maybe I'm just using the wrong gulp task implementation? This is the compiling part of my gulp task:

.pipe(through2.obj(function(file, enc, next) {
    try {
        var contents = file.contents.toString();
        var compiledFunction = ejs.compile(contents, {
            filename: file.path,
            client: true
        }).toString();
        file.contents = new Buffer(compiledFunction);
        file.path = replaceExt(file.path, '.js');
    } catch(err) {
        this.emit('error', new PluginError('gulp-ejs-precompiler', err));
    }
    next(null, file);
}))

It works with v2.x and the preprocessor directive, but not with v3.x and the function call. ejs is just require('ejs')

@mde
Copy link
Owner

mde commented Dec 7, 2019

@simllll By default, the local variables live in an object called locals — for when people are opting out of the use of with for execution. (The name of this object is also configurable.)

> let ejs = require('ejs');
undefined
> ejs.render('<%- JSON.stringify(locals); %>', {foo: 'FOO', bar: 'BAR'});
'{"foo":"FOO","bar":"BAR"}'
``

@simllll
Copy link

simllll commented Dec 7, 2019

Thanks, this helps already a lot to merge the object with temporary data. But is there also something that referes to the current scope variables? E.g.
ejs.render('<% var keep='blub'; var something = 'this is very old code btw'; %> <% /* access to keep and something? Or some was to see what is available in the current context */ %>', {...});
``

@henderea
Copy link

henderea commented Dec 10, 2019

@mde: is there any way with ejs 3+ to precompile include-using templates in a build process for use in the browser? I have a gulp task (listed in an earlier comment) that compiles a set of templates into a single JS file for loading into the browser and using in client-side JS to insert into the DOM with jQuery. The raw EJS templates aren't accessible to the browser in any way, but the include(...) function is left untouched (and thus non-functional) in the ejs.compile output. Right now, I am unable to upgrade to EJS 3.x because it doesn't support the include preprocessor directive that actually works in my use case.

Is there no way to separate the compiled templates from the raw EJS files when using include(...)?

As a note, I only use include for one set of templates, which is basically a multi-section report that I want to insert all together, then update specific sections without replacing the whole template and needing to re-attach all of the listeners. As a result, I need to have the child templates both separate AND as part of the parent template.

@ExE-Boss
Copy link
Collaborator

You can provide a custom include(…) function as the third parameter at runtime by compiling in client mode.

This is the default behaviour:

ejs/lib/ejs.js

Lines 647 to 656 in d8ae91d

var returnedFn = opts.client ? fn : function anonymous(data) {
var include = function (path, includeData) {
var d = utils.shallowCopy({}, data);
if (includeData) {
d = utils.shallowCopy(d, includeData);
}
return includeFile(path, opts)(d);
};
return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]);
};

dchege711 added a commit to dchege711/study_buddy that referenced this issue Oct 24, 2022
Breaking change. Solution obtained from [1].

[1]: mde/ejs#477
dchege711 added a commit to dchege711/study_buddy that referenced this issue Oct 24, 2022
* [EJS] Install ejs-lint to help investigate error messages

[1]: https://www.npmjs.com/package/ejs-lint

* [DB] Use in-memory DB during dev environment

* [EJS] Update include to match v3

Breaking change. Solution obtained from [1].

[1]: mde/ejs#477

* [EJS] Define the LOGGED_IN template var in 404 and 500 pages

Otherwise we get a fatal error. Breaking change.

* [DB] Always define exports.MONGO_URI in config.js to avoid compiler errors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants