module.exports = class {
data = {
title: 'hi',
};
render(data) {
return `
<p>${data.title}</p>
`;
}
};
Class properties are a relatively new JS feature, but are supported in recent-ish versions of Node.
I would expect the above to render <p>hi</p>, but it isn't picking up the data.
I did have a quick glance at this before my internet went out 😱 and here’s the offending code:
https://github.com/11ty/eleventy/blob/master/src/Engines/JavaScript.js#L33
Ohhh interesting. I didn't realise it worked this way.
One gotcha with how it works, is the instance that creates the data isn't the same as the instance that receives the render() call. It means that data & render would be pointing to the same instance variable and get different results.
It might be more consistent to support:
exports.data = {…};
exports.render = function(data) {
// …
};
Which would work nicely with esm:
export const data = {…};
export function render(data) {
// …
};
Alright I think this is important so I did most of the work for this and checked it into branch 622.
https://github.com/11ty/eleventy/compare/issue-622?expand=1
It still needs a few tests and docs but it’s shaping up here.
This needs more tests but it’s a good start at adding support for public class fields, one class instance for data and render, as well as multiple exports as described here https://github.com/11ty/eleventy/issues/622#issuecomment-514681826
Also adds travis tests for Node 12 (required for public class fields)
Class fields support: https://node.green/#ESNEXT-candidate--stage-3--instance-class-fields
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Field_declarations
Oh wow, that was quick! Looks good from scanning it.
I think there's some opportunity to simplify stuff. RIght now, getInstanceFromInputPath is handling cases where the input is a constructor, but instead it could be the point where the input is normalised to { data?, render }.
Something like:
function getInstanceFromInputPath(inputPath) {
if (this.instances[inputPath]) {
return this.instances[inputPath];
}
const mod = this._getRequire(inputPath);
let inst;
if (typeof mod === 'string' || mod instanceof Buffer || mod.then) {
inst = { render: () => mod };
} else if (typeof mod === 'function') {
if ('data' in mod.prototype || 'render' in mod.prototype) {
inst = new mod();
} else {
inst = { render: mod };
}
} else if ('data' in mod || 'render' in mod) {
inst = mod;
}
this.instances[inputPath] = inst;
return inst;
}
Ah, right on—thanks! I added that code. Looking _pretty_ nice right now.