From f061d8488eb10211a5f0bf206dbcf08a4f05429c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 1 Jun 2021 23:20:33 -0500 Subject: [PATCH] Fixes #1754 --- src/Template.js | 46 ++++++++---------- src/TemplateBehavior.js | 33 +++++++++++++ src/TemplateMap.js | 54 ++++++++++----------- src/TemplatePermalink.js | 22 --------- test/TemplateTest.js | 54 ++++++++++++++++++--- test/stubs/permalink-false-computed/test.md | 6 +++ 6 files changed, 132 insertions(+), 83 deletions(-) create mode 100644 src/TemplateBehavior.js create mode 100644 test/stubs/permalink-false-computed/test.md diff --git a/src/Template.js b/src/Template.js index 966348d5d..162240a06 100755 --- a/src/Template.js +++ b/src/Template.js @@ -2,7 +2,6 @@ const fs = require("fs-extra"); const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); -const lodashGet = require("lodash/get"); const { DateTime } = require("luxon"); const TemplateData = require("./TemplateData"); @@ -16,6 +15,7 @@ const Pagination = require("./Plugins/Pagination"); const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); const TemplateContentUnrenderedTemplateError = require("./Errors/TemplateContentUnrenderedTemplateError"); const ConsoleLogger = require("./Util/ConsoleLogger"); +const TemplateBehavior = require("./TemplateBehavior"); const debug = require("debug")("Eleventy:Template"); const debugDev = require("debug")("Dev:Eleventy:Template"); @@ -62,6 +62,9 @@ class Template extends TemplateContent { this.filePathStem = this.fileSlug.getFullPathWithoutExtension(); this.outputFormat = "fs"; + + this.behavior = new TemplateBehavior(); + this.behavior.setOutputFormat(this.outputFormat); } get logger() { @@ -79,6 +82,7 @@ class Template extends TemplateContent { setOutputFormat(to) { this.outputFormat = to; + this.behavior.setOutputFormat(to); } setIsVerbose(isVerbose) { @@ -142,6 +146,9 @@ class Template extends TemplateContent { permalinkValue, this.extraOutputSubdirectory ); + + this.behavior.setFromPermalink(perm); + return perm; } @@ -153,9 +160,8 @@ class Template extends TemplateContent { let permalink = data[this.config.keys.permalink]; let permalinkValue; - // v1.0 added support for `permalink: true` - // `permalink: true` is a more accurate alias for `permalink: false` behavior: - // render but no file system write, e.g. use in collections only) + // `permalink: false` means render but no file system write, e.g. use in collections only) + // `permalink: true` throws an error if (typeof permalink === "boolean") { debugDev("Using boolean permalink %o", permalink); permalinkValue = permalink; @@ -573,20 +579,12 @@ class Template extends TemplateContent { await this.computedData.processRemainingData(data); } - async getTemplates(data, behavior) { - if (!behavior) { - behavior = { - read: true, - render: true, - write: true, - }; - } - + async getTemplates(data) { // no pagination on permalink.serverless for local builds let hasPagination = Pagination.hasPagination(data); - let isServerlessRenderOnBuild = !behavior.render; + let isServerlessRenderOnBuild = !this.behavior.isRenderable(); let isServerlessRenderOnServerless = - behavior.render === "override" && + this.behavior.isRenderForced() && hasPagination && "serverless" in data.pagination; @@ -624,7 +622,7 @@ class Template extends TemplateContent { }, get templateContent() { if (this._templateContent === undefined) { - if (behavior.render) { + if (this.template.behavior.isRenderable()) { // should at least warn here throw new TemplateContentPrematureUseError( `Tried to use templateContent too early (${this.inputPath})` @@ -672,7 +670,7 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if (behavior.render) { + if (this.template.behavior.isRenderable()) { if (this._templateContent === undefined) { throw new TemplateContentPrematureUseError( `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` @@ -723,7 +721,8 @@ class Template extends TemplateContent { }; } - let engineList = this.templateRender.getReadableEnginesListDifferingFromFileExtension(); + let engineList = + this.templateRender.getReadableEnginesListDifferingFromFileExtension(); this.logger.log( `${lang.start} ${outputPath} from ${this.inputPath}${ engineList ? ` (${engineList})` : "" @@ -769,7 +768,7 @@ class Template extends TemplateContent { let content; // Note that behavior.render is overridden when using json or ndjson output - if (mapEntry.behavior.render) { + if (mapEntry.template.behavior.isRenderable()) { // this reuses page.templateContent, it doesn’t render it content = await this.renderPageEntry(mapEntry, page); } @@ -791,7 +790,7 @@ class Template extends TemplateContent { return obj; } - if (!mapEntry.behavior.render) { + if (!mapEntry.template.behavior.isRenderable()) { debug( "Template not written %o from %o (via permalink.behavior).", page.outputPath, @@ -800,7 +799,7 @@ class Template extends TemplateContent { return; } - if (!mapEntry.behavior.write) { + if (!mapEntry.template.behavior.isWriteable()) { debug( "Template not written %o from %o (via permalink: false, permalink.build: false, or a permalink object without a build property).", page.outputPath, @@ -926,17 +925,12 @@ class Template extends TemplateContent { // Important reminder: This is where the template data is first generated via TemplateMap let data = dataOverride || (await this.getData()); - let rawPermalinkValue = data[this.config.keys.permalink]; - let link = this._getRawPermalinkInstance(rawPermalinkValue); - - let behavior = link.getBehavior(this.outputFormat); let entries = []; // does not return outputPath or url, we don’t want to render permalinks yet entries.push({ template: this, inputPath: this.inputPath, data, - behavior, }); return entries; } diff --git a/src/TemplateBehavior.js b/src/TemplateBehavior.js new file mode 100644 index 000000000..9767f1e0e --- /dev/null +++ b/src/TemplateBehavior.js @@ -0,0 +1,33 @@ +class TemplateBehavior { + constructor() { + this.render = true; + this.write = true; + this.outputFormat = null; + } + + isRenderable() { + return this.render || this.isRenderForced(); + } + + setOutputFormat(format) { + this.outputFormat = format; + } + + isRenderForced() { + return this.outputFormat === "json" || this.outputFormat === "ndjson"; + } + + isWriteable() { + return this.write; + } + + isIncludedInCollections() { + return this.isRenderable(); + } + + setFromPermalink(templatePermalink) { + this.render = templatePermalink._isRendered; + this.write = templatePermalink._writeToFileSystem; + } +} +module.exports = TemplateBehavior; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 9eadf9f89..90777117f 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -123,7 +123,7 @@ class TemplateMap { if ( !entry.data.eleventyExcludeFromCollections && - entry.behavior.includeInCollections + entry.template.behavior.isIncludedInCollections() ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -177,7 +177,7 @@ class TemplateMap { if ( !entry.data.eleventyExcludeFromCollections && - entry.behavior.includeInCollections + entry.template.behavior.isIncludedInCollections() ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -221,7 +221,7 @@ class TemplateMap { if ( !entry.data.eleventyExcludeFromCollections && - entry.behavior.includeInCollections + entry.template.behavior.isIncludedInCollections() ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -253,7 +253,7 @@ class TemplateMap { if ( !entry.data.eleventyExcludeFromCollections && - entry.behavior.includeInCollections + entry.template.behavior.isIncludedInCollections() ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -297,33 +297,29 @@ class TemplateMap { } else { // is a template entry let map = this.getMapEntryForInputPath(depEntry); - if (!map.behavior.read) { - map._pages = []; - } else { - map._pages = await map.template.getTemplates(map.data, map.behavior); + map._pages = await map.template.getTemplates(map.data); - let counter = 0; - for (let page of map._pages) { - // Copy outputPath to map entry - if (!map.outputPath) { - map.outputPath = page.outputPath; - } + let counter = 0; + for (let page of map._pages) { + // Copy outputPath to map entry + if (!map.outputPath) { + map.outputPath = page.outputPath; + } + if ( + counter === 0 || + (map.data.pagination && + map.data.pagination.addAllPagesToCollections) + ) { if ( - counter === 0 || - (map.data.pagination && - map.data.pagination.addAllPagesToCollections) + !map.data.eleventyExcludeFromCollections && + map.template.behavior.isIncludedInCollections() ) { - if ( - !map.data.eleventyExcludeFromCollections && - map.behavior.includeInCollections - ) { - // TODO do we need .template in collection entries? - this.collection.add(page); - } + // TODO do we need .template in collection entries? + this.collection.add(page); } - counter++; } + counter++; } } } @@ -343,10 +339,12 @@ class TemplateMap { let delayedDependencyMap = this.getDelayedMappedDependencies(); await this.initDependencyMap(delayedDependencyMap); - let firstPaginatedDepMap = this.getPaginatedOverCollectionsMappedDependencies(); + let firstPaginatedDepMap = + this.getPaginatedOverCollectionsMappedDependencies(); await this.initDependencyMap(firstPaginatedDepMap); - let secondPaginatedDepMap = this.getPaginatedOverAllCollectionMappedDependencies(); + let secondPaginatedDepMap = + this.getPaginatedOverAllCollectionMappedDependencies(); await this.initDependencyMap(secondPaginatedDepMap); await this.resolveRemainingComputedData(); @@ -444,7 +442,7 @@ class TemplateMap { if (!map._pages) { throw new Error(`Content pages not found for ${map.inputPath}`); } - if (!map.behavior.render) { + if (!map.template.behavior.isRenderable()) { continue; } try { diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 896a92409..539b100e4 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -8,7 +8,6 @@ class TemplatePermalink { constructor(link, extraSubdir) { let isLinkAnObject = isPlainObject(link); - this._isIgnoredTemplate = false; this._isRendered = true; this._writeToFileSystem = true; @@ -54,10 +53,6 @@ class TemplatePermalink { } else if (link.behavior === "read") { this._writeToFileSystem = false; this._isRendered = false; - } else if (link.behavior === "skip") { - this._writeToFileSystem = false; - this._isRendered = false; - this._isIgnoredTemplate = true; } } @@ -128,23 +123,6 @@ class TemplatePermalink { return normalize(uri); } - getBehavior(outputFormat = "fs") { - let obj = { - read: !this._isIgnoredTemplate, - render: this._isRendered, - write: this._writeToFileSystem, - }; - - // override render behavior for --json or --ndjson - if (outputFormat !== "fs") { - obj.render = "override"; - } - - obj.includeInCollections = obj.read && obj.render; - - return obj; - } - static _hasDuplicateFolder(dir, base) { let folders = dir.split("/"); if (!folders[folders.length - 1]) { diff --git a/test/TemplateTest.js b/test/TemplateTest.js index ff64a8d29..484c6247a 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -38,12 +38,13 @@ async function getTemplateMapEntriesWithContent(template, data) { ); } -async function write(tmpl, data) { - let mapEntries = await getTemplateMapEntriesWithContent(tmpl, data); +async function writeMapEntries(mapEntries) { let promises = []; for (let entry of mapEntries) { - if (entry.behavior.writeable) { - promises.push(tmpl._write(entry.outputPath, entry.templateContent)); + if (entry.template.behavior.isWriteable()) { + promises.push( + entry.template._write(entry.outputPath, entry.templateContent) + ); } } return Promise.all(promises); @@ -1382,10 +1383,15 @@ test("permalink: false", async (t) => { ); let data = await tmpl.getData(); - t.is(await tmpl.getOutputLink(data), false); - t.is(await tmpl.getOutputHref(data), false); - await write(tmpl, data); + let mapEntries = await getTemplateMapEntriesWithContent(tmpl, data); + for (let entry of mapEntries) { + t.is(entry.template.behavior.isWriteable(), false); + t.is(entry.data.page.url, false); + t.is(entry.data.page.outputPath, false); + } + + await writeMapEntries(mapEntries); // Input file exists (sanity check for paths) t.is(fs.existsSync("./test/stubs/permalink-false/"), true); @@ -1400,6 +1406,40 @@ test("permalink: false", async (t) => { ); }); +test("permalink: false inside of eleventyComputed, Issue #1754", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-false-computed/test.md", + "./test/stubs/", + "./test/stubs/_site" + ); + + let data = await tmpl.getData(); + let mapEntries = await getTemplateMapEntriesWithContent(tmpl, data); + for (let entry of mapEntries) { + t.is(entry.template.behavior.isWriteable(), false); + t.is(entry.data.page.url, false); + t.is(entry.data.page.outputPath, false); + } + await writeMapEntries(mapEntries); + + // Input file exists (sanity check for paths) + t.is(fs.existsSync("./test/stubs/permalink-false-computed/"), true); + t.is(fs.existsSync("./test/stubs/permalink-false-computed/test.md"), true); + + // Output does not exist + t.is(fs.existsSync("./test/stubs/_site/permalink-false-computed/"), false); + t.is( + fs.existsSync("./test/stubs/_site/permalink-false-computed/test/"), + false + ); + t.is( + fs.existsSync( + "./test/stubs/_site/permalink-false-computed/test/index.html" + ), + false + ); +}); + test("permalink: true", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-true/permalink-true.md", diff --git a/test/stubs/permalink-false-computed/test.md b/test/stubs/permalink-false-computed/test.md new file mode 100644 index 000000000..c9c548212 --- /dev/null +++ b/test/stubs/permalink-false-computed/test.md @@ -0,0 +1,6 @@ +--- +eleventyComputed: + permalink: false +--- + +This shouldn’t write