Skip to content

Commit 838467d

Browse files
committed
Fixes #1645
1 parent 82307ef commit 838467d

2 files changed

Lines changed: 94 additions & 0 deletions

File tree

src/Engines/JavaScript.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ export default class JavaScript extends TemplateEngine {
7070

7171
return new mod();
7272
} else {
73+
// JavaScript lol
74+
if (mod.toString().trimStart().startsWith("class ")) {
75+
// we already know that mod.prototype.data and mod.prototype.render do not exist (per above)
76+
// now we look for instance properties for `data` or `render`, issue #1645
77+
let modInstance = new mod();
78+
if (Object.hasOwn(modInstance, "data") || Object.hasOwn(modInstance, "render")) {
79+
if (!Object.hasOwn(modInstance, "render")) {
80+
mod.prototype.render = noop;
81+
}
82+
83+
if (!Object.hasOwn(modInstance, "data") && !mod.data && originalModData) {
84+
mod.prototype.data = originalModData;
85+
}
86+
87+
return modInstance;
88+
} else {
89+
throw new Error(
90+
"Invalid class signature for an 11ty.js template: needs a render or data instance property.",
91+
);
92+
}
93+
}
94+
7395
return {
7496
...(originalModData ? { data: originalModData } : undefined),
7597
render: mod,

test/EleventyVirtualTemplatesTest.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,75 @@ test("11ty.js Virtual Templates (function), issue #3347", async (t) => {
221221
// TODO support rawInput on 11ty.js?
222222
// t.deepEqual(results[0].rawInput, templateDefinition);
223223
});
224+
225+
226+
test("11ty.js class templates with invalid signature, issue #1645", async (t) => {
227+
let elev = new Eleventy("./test/stubs-virtual-nowrite", "./test/stubs-virtual-nowrite/_site", {
228+
config: function (eleventyConfig) {
229+
eleventyConfig.addTemplate("virtual.11ty.js", class {});
230+
}
231+
});
232+
elev.disableLogger();
233+
234+
await t.throwsAsync(elev.toJSON(), {
235+
message: `Invalid class signature for an 11ty.js template: needs a render or data instance property.`
236+
});
237+
});
238+
239+
test("11ty.js class templates with instance properties (data), issue #1645", async (t) => {
240+
let elev = new Eleventy("./test/stubs-virtual-nowrite", "./test/stubs-virtual-nowrite/_site", {
241+
config: function (eleventyConfig) {
242+
eleventyConfig.addTemplate("virtual.11ty.js", class { data() { return {} } });
243+
}
244+
});
245+
246+
let results = await elev.toJSON();
247+
248+
t.deepEqual(results.length, 1);
249+
t.deepEqual(results[0].content.trim(), ``);
250+
});
251+
252+
test("11ty.js class templates with instance properties (render), issue #1645", async (t) => {
253+
let elev = new Eleventy("./test/stubs-virtual-nowrite", "./test/stubs-virtual-nowrite/_site", {
254+
config: function (eleventyConfig) {
255+
eleventyConfig.addTemplate("virtual.11ty.js", class { render() { return "Hello!" } });
256+
}
257+
});
258+
259+
let results = await elev.toJSON();
260+
261+
t.deepEqual(results.length, 1);
262+
t.deepEqual(results[0].content.trim(), `Hello!`);
263+
});
264+
265+
test("11ty.js class templates with instance properties (data and render), issue #1645", async (t) => {
266+
let elev = new Eleventy("./test/stubs-virtual-nowrite", "./test/stubs-virtual-nowrite/_site", {
267+
config: function (eleventyConfig) {
268+
eleventyConfig.addTemplate("virtual.11ty.js", class {
269+
data() { return { key: "world" }; }
270+
render(data) { return `Hello ${data.key}!` }
271+
});
272+
}
273+
});
274+
275+
let results = await elev.toJSON();
276+
277+
t.deepEqual(results.length, 1);
278+
t.deepEqual(results[0].content.trim(), `Hello world!`);
279+
});
280+
281+
test("11ty.js class templates with instance properties (data and render arrows), issue #1645", async (t) => {
282+
let elev = new Eleventy("./test/stubs-virtual-nowrite", "./test/stubs-virtual-nowrite/_site", {
283+
config: function (eleventyConfig) {
284+
eleventyConfig.addTemplate("virtual.11ty.js", class {
285+
data = () => { return { key: "world" }; }
286+
render = (data) => { return `Hello ${data.key}!` }
287+
});
288+
}
289+
});
290+
291+
let results = await elev.toJSON();
292+
293+
t.deepEqual(results.length, 1);
294+
t.deepEqual(results[0].content.trim(), `Hello world!`);
295+
});

0 commit comments

Comments
 (0)