Skip to content

Commit

Permalink
Fix to allow #3433 to use custom compile functions with preprocessors
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Sep 18, 2024
1 parent e221e19 commit 36c2e52
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 12 deletions.
65 changes: 55 additions & 10 deletions src/Engines/Custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,49 @@ class CustomEngine extends TemplateEngine {
this._defaultEngine = defaultEngine;
}

async getInstanceFromInputPath(inputPath) {
if (
"getInstanceFromInputPath" in this.entry &&
typeof this.entry.getInstanceFromInputPath === "function"
) {
// returns Promise
return this.entry.getInstanceFromInputPath(inputPath);
}

// aliased upstream type
if (
this._defaultEngine &&
"getInstanceFromInputPath" in this._defaultEngine &&
typeof this._defaultEngine.getInstanceFromInputPath === "function"
) {
// returns Promise
return this._defaultEngine.getInstanceFromInputPath(inputPath);
}

return false;
}

/**
* Whether to use the module loader directly
*
* @override
*/
useJavaScriptImport() {
if ("useJavaScriptImport" in this.entry) {
return this.entry.useJavaScriptImport;
}

if (
this._defaultEngine &&
"useJavaScriptImport" in this._defaultEngine &&
typeof this._defaultEngine.useJavaScriptImport === "function"
) {
return this._defaultEngine.useJavaScriptImport();
}

return false;
}

/**
* @override
*/
Expand Down Expand Up @@ -110,15 +153,6 @@ class CustomEngine extends TemplateEngine {
return data;
}

// if getData is not false or a function then `getInstanceFromInputPath` must exist
if (!("getInstanceFromInputPath" in this.entry)) {
return Promise.reject(
new Error(
`getInstanceFromInputPath callback missing from ${this.name} template engine plugin.`,
),
);
}

let keys = new Set();
if (this.entry.getData === true) {
keys.add("data");
Expand All @@ -131,7 +165,18 @@ class CustomEngine extends TemplateEngine {
let dataBench = this.benchmarks.aggregate.get(`Engine (${this.name}) Get Data From File`);
dataBench.before();

let inst = await this.entry.getInstanceFromInputPath(inputPath);
let inst = await this.getInstanceFromInputPath(inputPath);

if (inst === false) {
dataBench.after();

return Promise.reject(
new Error(
`\`getInstanceFromInputPath\` callback missing from '${this.name}' template engine plugin. It is required when \`getData\` is in use. You can set \`getData: false\` to opt-out of this.`,
),
);
}

// override keys set at the plugin level in the individual template
if (inst.eleventyDataKey) {
keys = new Set(inst.eleventyDataKey);
Expand Down
147 changes: 147 additions & 0 deletions test/EleventyTest-Preprocessors.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,36 @@ test("#188: Content preprocessing (wildcard)", async (t) => {
t.is(results[0].content, `Hello Before`);
});


test("addPreprocessor with 11ty.js, Issue #3433", async (t) => {
t.plan(5);

let elev = new Eleventy("./test/stubs-virtual/", undefined, {
config: eleventyConfig => {
eleventyConfig.addPreprocessor("testing", "11ty.js", (data, content) => {
t.is( typeof content.render, "function" );
t.is(content.render(), "Hello!");

return {
render: function() {
return "naw";
}
};
});

eleventyConfig.addTemplate("template.11ty.js", function render() {
return "Hello!"
});
}
});

let results = await elev.toJSON();
t.is(results.length, 1);
t.is(results[0].url, `/template/`);
t.is(results[0].content.trim(), `naw`);
});


test("addPreprocessor and addExtension, Issue #3433", async (t) => {
t.plan(5);

Expand Down Expand Up @@ -134,3 +164,120 @@ test("addPreprocessor and addExtension, Issue #3433", async (t) => {
t.is(results[0].url, `/template/`);
t.is(results[0].content.trim(), `naw`);
});

test("addPreprocessor and addExtension with custom `compile` (defaultRenderer), Issue #3433", async (t) => {
t.plan(5);

let elev = new Eleventy("./test/stubs-virtual/", undefined, {
config: eleventyConfig => {
eleventyConfig.addTemplateFormats("11ty.test");
eleventyConfig.addExtension("11ty.test", {
key: "11ty.js",
compile: function() {
return this.defaultRenderer;
}
});

eleventyConfig.addPreprocessor("testing", "11ty.test", (data, content) => {
t.is( typeof content.render, "function" );
t.is(content.render(), "Hello!");

return {
render: function() {
return "naw";
}
};
});

eleventyConfig.addTemplate("template.11ty.test", function render() {
return "Hello!"
});
}
});

let results = await elev.toJSON();
t.is(results.length, 1);
t.is(results[0].url, `/template/`);
t.is(results[0].content.trim(), `naw`);
});

test("addPreprocessor and addExtension with custom `compile` (re-use render function directly), Issue #3433", async (t) => {
t.plan(5);

let elev = new Eleventy("./test/stubs-virtual/", undefined, {
config: eleventyConfig => {
eleventyConfig.addTemplateFormats("11ty.test");
eleventyConfig.addExtension("11ty.test", {
key: "11ty.js",
compile: function(content) {
return function() {
return content.render();
}
}
});

eleventyConfig.addPreprocessor("testing", "11ty.test", (data, content) => {
t.is( typeof content.render, "function" );
t.is(content.render(), "Hello!");

return {
render: function() {
return "naw";
}
};
});

eleventyConfig.addTemplate("template.11ty.test", function render() {
return "Hello!"
});
}
});

let results = await elev.toJSON();
t.is(results.length, 1);
t.is(results[0].url, `/template/`);
t.is(results[0].content.trim(), `naw`);
});

test("addPreprocessor and addExtension with custom `compile` (new render function), Issue #3433", async (t) => {
t.plan(7);

let elev = new Eleventy("./test/stubs-virtual/", undefined, {
config: eleventyConfig => {
eleventyConfig.addTemplateFormats("11ty.test");
eleventyConfig.addExtension("11ty.test", {
key: "11ty.js",
compile: function(content) {
// check preprocessor override
t.is( typeof content.render, "function" );
t.is(content.render(), "Preprocessor override");

return function() {
return "Compiled content";
}
}
});

eleventyConfig.addPreprocessor("testing", "11ty.test", (data, content) => {
// check template content directly
t.is( typeof content.render, "function" );
t.is(content.render(), "Original template content");

return {
render: function() {
return "Preprocessor override";
}
};
});

eleventyConfig.addTemplate("template.11ty.test", function render() {
return "Original template content"
});
}
});

let results = await elev.toJSON();
t.is(results.length, 1);
t.is(results[0].url, `/template/`);
t.is(results[0].content.trim(), `Compiled content`);
});
4 changes: 2 additions & 2 deletions test/TemplateTest-CustomExtensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ test("Using getData: true without getInstanceFromInputPath should error", async
await t.throwsAsync(async () => {
await tmpl.getData();
}, {
message: "getInstanceFromInputPath callback missing from txt template engine plugin."
message: "`getInstanceFromInputPath` callback missing from \'txt\' template engine plugin. It is required when `getData` is in use. You can set `getData: false` to opt-out of this."
});
});

Expand Down Expand Up @@ -111,7 +111,7 @@ test("Using getData: [] without getInstanceFromInputPath should error", async (t
await t.throwsAsync(async () => {
await tmpl.getData();
}, {
message: "getInstanceFromInputPath callback missing from txt template engine plugin."
message: "`getInstanceFromInputPath` callback missing from \'txt\' template engine plugin. It is required when `getData` is in use. You can set `getData: false` to opt-out of this."
});
});

Expand Down

0 comments on commit 36c2e52

Please sign in to comment.