Skip to content

Commit

Permalink
* Allow render function to return undefined to skip the file write.
Browse files Browse the repository at this point in the history
* `compileOptions: permalink: false` now aliases to `compileOptions: permalink: () => false`. Use `compileOptions: permalink: "raw"` to skip permalink compilation altogether
  • Loading branch information
zachleat committed Dec 27, 2021
1 parent 35eeb94 commit 1ea3a90
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 13 deletions.
8 changes: 7 additions & 1 deletion src/Engines/Custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,15 @@ class CustomEngine extends TemplateEngine {
permalinkNeedsCompilation(str) {
if (this.entry.compileOptions && "permalink" in this.entry.compileOptions) {
let p = this.entry.compileOptions.permalink;
if (p === false || p === "raw") {
if (p === "raw") {
return false;
}

// permalink: false is aliased to permalink: () => false
if (p === false) {
return () => false;
}

return this.entry.compileOptions.permalink;
}

Expand Down
33 changes: 23 additions & 10 deletions src/Template.js
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ class Template extends TemplateContent {
return ret;
}

// Used only by tests
async renderContent(str, data, bypassMarkdown) {
return super.render(str, data, bypassMarkdown);
}
Expand Down Expand Up @@ -678,11 +679,18 @@ class Template extends TemplateContent {
date: data.page.date,
outputPath: data.page.outputPath,
url: data.page.url,
checkTemplateContent: true,
set templateContent(content) {
if (content === undefined) {
this.checkTemplateContent = false;
}
this._templateContent = content;
},
get templateContent() {
if (this._templateContent === undefined) {
if (
this.checkTemplateContent &&
this._templateContent === undefined
) {
if (this.template.behavior.isRenderable()) {
// should at least warn here
throw new TemplateContentPrematureUseError(
Expand Down Expand Up @@ -728,11 +736,18 @@ class Template extends TemplateContent {
pageNumber: pageNumber,
outputPath: pageData.page.outputPath,
url: pageData.page.url,
checkTemplateContent: true,
set templateContent(content) {
if (content === undefined) {
this.checkTemplateContent = false;
}
this._templateContent = content;
},
get templateContent() {
if (this._templateContent === undefined) {
if (
this.checkTemplateContent &&
this._templateContent === undefined
) {
if (this.template.behavior.isRenderable()) {
throw new TemplateContentPrematureUseError(
`Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})`
Expand Down Expand Up @@ -803,13 +818,9 @@ class Template extends TemplateContent {
await mkdir(templateOutputDir, { recursive: true });
}

if (Buffer.isBuffer(finalContent)) {
finalContent = finalContent.toString();
}

if (typeof finalContent !== "string") {
if (!Buffer.isBuffer(finalContent) && typeof finalContent !== "string") {
throw new Error(
`The return value from the render function for the ${this.engine.name} template was not a string. Received ${finalContent}`
`The return value from the render function for the ${this.engine.name} template was not a String or Buffer. Received ${finalContent}`
);
}

Expand Down Expand Up @@ -854,7 +865,6 @@ class Template extends TemplateContent {
return Promise.all(
mapEntry._pages.map(async (page) => {
let content;

// Note that behavior.render is overridden when using json or ndjson output
if (mapEntry.template.behavior.isRenderable()) {
// this reuses page.templateContent, it doesn’t render it
Expand Down Expand Up @@ -907,7 +917,10 @@ class Template extends TemplateContent {
return;
}

return this._write(page.outputPath, content);
// compile returned undefined
if (content !== undefined) {
return this._write(page.outputPath, content);
}
})
);
}
Expand Down
1 change: 1 addition & 0 deletions src/TemplateContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ class TemplateContent {
// No string compilation:
// ({ compileOptions: { permalink: "raw" }})
// These mean `permalink: false`, which is no file system writing:
// ({ compileOptions: { permalink: false }})
// ({ compileOptions: { permalink: () => false }})
// ({ compileOptions: { permalink: () => (() = > false) }})
if (permalinkCompilation === false) {
Expand Down
5 changes: 4 additions & 1 deletion src/TemplateMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,10 @@ class TemplateMap {
// This check skips precompiled collections
if (entry) {
let index = item.pageNumber || 0;
item.templateContent = entry._pages[index]._templateContent;
let content = entry._pages[index]._templateContent;
if (content !== undefined) {
item.templateContent = content;
}
}
}
}
Expand Down
69 changes: 68 additions & 1 deletion test/TemplateTest-CompileOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ test("Custom extension (.txt) with custom permalink compile function", async (t)
});
});

test("Custom extension with and opt-out of permalink compilation", async (t) => {
test("Custom extension with and compileOptions.permalink = false", async (t) => {
let eleventyConfig = new TemplateConfig();
eleventyConfig.userConfig.extensionMap.add({
extension: "txt",
Expand All @@ -73,6 +73,41 @@ test("Custom extension with and opt-out of permalink compilation", async (t) =>
eleventyConfig
);

let data = await tmpl.getData();
t.is(await tmpl.render(data), "Sample content");
t.deepEqual(await tmpl.getOutputLocations(data), {
href: false,
path: false,
rawPath: false,
});
});

test("Custom extension with and opt-out of permalink compilation", async (t) => {
let eleventyConfig = new TemplateConfig();
eleventyConfig.userConfig.extensionMap.add({
extension: "txt",
key: "txt",
compileOptions: {
permalink: "raw",
},
compile: function (str, inputPath) {
// plaintext
return function (data) {
return str;
};
},
});

let dataObj = new TemplateData("./test/stubs/", eleventyConfig);
let tmpl = getNewTemplate(
"./test/stubs/custom-extension.txt",
"./test/stubs/",
"dist",
dataObj,
null,
eleventyConfig
);

let data = await tmpl.getData();
t.is(await tmpl.render(data), "Sample content");
t.deepEqual(await tmpl.getOutputLocations(data), {
Expand Down Expand Up @@ -206,3 +241,35 @@ test("Custom extension (.txt) with custom permalink compile function that return
rawPath: false,
});
});

test("Custom extension (.txt) that returns undefined from compile", async (t) => {
let eleventyConfig = new TemplateConfig();
eleventyConfig.userConfig.extensionMap.add({
extension: "txt",
key: "txt",
compile: function (str, inputPath) {
t.is(str, "Sample content");
return function (data) {
return undefined;
};
},
});

let dataObj = new TemplateData("./test/stubs/", eleventyConfig);
let tmpl = getNewTemplate(
"./test/stubs/custom-extension-no-permalink.txt",
"./test/stubs/",
"dist",
dataObj,
null,
eleventyConfig
);

let data = await tmpl.getData();
t.is(await tmpl.render(data), undefined);
let pages = await tmpl.getTemplates(data);
for (let page of pages) {
page.templateContent = undefined;
t.is(page.templateContent, undefined); // shouldn’t throw an error
}
});

0 comments on commit 1ea3a90

Please sign in to comment.