From 8e4428ed87c8bcacc5b7511b84669a74e465fae9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 30 Jul 2024 13:14:02 -0500 Subject: [PATCH] Fixes #3389 --- src/Data/TemplateDataInitialGlobalData.js | 1 + src/UserConfig.js | 14 ++- test/EleventyAddGlobalDataTest.js | 118 ++++++++++++++++++++++ test/EleventyTest.js | 47 --------- 4 files changed, 131 insertions(+), 49 deletions(-) create mode 100644 test/EleventyAddGlobalDataTest.js diff --git a/src/Data/TemplateDataInitialGlobalData.js b/src/Data/TemplateDataInitialGlobalData.js index ffd5029fb..7e2a7ee2e 100644 --- a/src/Data/TemplateDataInitialGlobalData.js +++ b/src/Data/TemplateDataInitialGlobalData.js @@ -24,6 +24,7 @@ class TemplateDataInitialGlobalData { for (let key of keys) { let returnValue = this.config.globalData[key]; + // This section is problematic when used with eleventyComputed #3389 if (typeof returnValue === "function") { returnValue = await returnValue(); } diff --git a/src/UserConfig.js b/src/UserConfig.js index 3d146e911..b5d3070ee 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -4,7 +4,7 @@ import yaml from "js-yaml"; import matter from "gray-matter"; import debugUtil from "debug"; -import { DeepCopy, TemplatePath } from "@11ty/eleventy-utils"; +import { DeepCopy, TemplatePath, isPlainObject } from "@11ty/eleventy-utils"; import HtmlBasePlugin from "./Plugins/HtmlBasePlugin.js"; import RenderPlugin from "./Plugins/RenderPlugin.js"; @@ -1073,9 +1073,19 @@ class UserConfig { } } + // 3.0.0-alpha.18 started merging conflicts here (when possible), issue #3389 addGlobalData(name, data) { name = this.getNamespacedName(name); - this.globalData[name] = data; + if (this.globalData[name]) { + if (isPlainObject(this.globalData[name]) && isPlainObject(data)) { + DeepCopy(this.globalData[name], data); + } else { + debug("Warning: overwriting a previous value set with addGlobalData(%o)", name); + this.globalData[name] = data; + } + } else { + this.globalData[name] = data; + } return this; } diff --git a/test/EleventyAddGlobalDataTest.js b/test/EleventyAddGlobalDataTest.js new file mode 100644 index 000000000..9181dfd74 --- /dev/null +++ b/test/EleventyAddGlobalDataTest.js @@ -0,0 +1,118 @@ +import test from "ava"; +import Eleventy from "../src/Eleventy.js"; + +test("Eleventy addGlobalData should run once", async (t) => { + let count = 0; + let elev = new Eleventy("./test/stubs-addglobaldata/", "./test/stubs-addglobaldata/_site", { + config: function (eleventyConfig) { + eleventyConfig.addGlobalData("count", () => { + count++; + return count; + }); + }, + }); + + let results = await elev.toJSON(); + t.is(count, 1); +}); + +test("Eleventy addGlobalData shouldn’t run if no input templates match!", async (t) => { + let count = 0; + let elev = new Eleventy( + "./test/stubs-addglobaldata-noop/", + "./test/stubs-addglobaldata-noop/_site", + { + config: function (eleventyConfig) { + eleventyConfig.addGlobalData("count", () => { + count++; + return count; + }); + }, + } + ); + + let results = await elev.toJSON(); + t.is(count, 0); +}); + +test("Eleventy addGlobalData can feed layouts to populate data cascade with layout data, issue #1245", async (t) => { + let elev = new Eleventy("./test/stubs-2145/", "./test/stubs-2145/_site", { + config: function (eleventyConfig) { + eleventyConfig.addGlobalData("layout", () => "layout.njk"); + eleventyConfig.dataFilterSelectors.add("LayoutData"); + }, + }); + + let [result] = await elev.toJSON(); + t.deepEqual(result.data, { LayoutData: 123 }); + t.is(result.content.trim(), "FromLayoutlayout.njk"); +}); + +test("Eleventy addGlobalData merge data #3389", async (t) => { + let elev = new Eleventy("./test/stubs-virtual/", undefined, { + config: function (eleventyConfig) { + eleventyConfig.addGlobalData("eleventyComputed", { + testing(data) { + return `testing:${data.page.url}`; + } + }); + + eleventyConfig.addGlobalData("eleventyComputed", { + other(data) { + return `other:${data.page.url}`; + } + }); + + eleventyConfig.addTemplate("computed.njk", "{{ testing }}|{{ other }}", {}) + }, + }); + + let results = await elev.toJSON(); + t.is(results.length, 1); + t.is(results[0].content, "testing:/computed/|other:/computed/"); +}); + +test("Eleventy addGlobalData merge data #3389 lodash set", async (t) => { + let elev = new Eleventy("./test/stubs-virtual/", undefined, { + config: function (eleventyConfig) { + eleventyConfig.addGlobalData("eleventyComputed.testing", () => { + return (data) => { + return `testing:${data.page.url}`; + } + }); + + eleventyConfig.addGlobalData("eleventyComputed.other", () => { + return (data) => { + return `other:${data.page.url}`; + } + }); + + eleventyConfig.addTemplate("computed.njk", "{{ testing }}|{{ other }}", {}) + }, + }); + + let results = await elev.toJSON(); + t.is(results.length, 1); + t.is(results[0].content, "testing:/computed/|other:/computed/"); +}); + +test.skip("Eleventy addGlobalData merge data #3389 no nested function", async (t) => { + let elev = new Eleventy("./test/stubs-virtual/", undefined, { + config: function (eleventyConfig) { + eleventyConfig.addGlobalData("eleventyComputed.testing", (data) => { + return `testing:${data.page.url}`; + }); + + eleventyConfig.addGlobalData("eleventyComputed.other", (data) => { + return `other:${data.page.url}`; + }); + + eleventyConfig.addTemplate("computed.njk", "{{ testing }}|{{ other }}", {}) + }, + }); + + let results = await elev.toJSON(); + t.is(results.length, 1); + t.is(results[0].content, "testing:/computed/|other:/computed/"); +}); + diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 0610a45a3..6fec34aac 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -460,53 +460,6 @@ test("Can Eleventy run two executeBuilds in parallel?", async (t) => { ); }); -test("Eleventy addGlobalData should run once", async (t) => { - let count = 0; - let elev = new Eleventy("./test/stubs-addglobaldata/", "./test/stubs-addglobaldata/_site", { - config: function (eleventyConfig) { - eleventyConfig.addGlobalData("count", () => { - count++; - return count; - }); - }, - }); - - let results = await elev.toJSON(); - t.is(count, 1); -}); - -test("Eleventy addGlobalData shouldn’t run if no input templates match!", async (t) => { - let count = 0; - let elev = new Eleventy( - "./test/stubs-addglobaldata-noop/", - "./test/stubs-addglobaldata-noop/_site", - { - config: function (eleventyConfig) { - eleventyConfig.addGlobalData("count", () => { - count++; - return count; - }); - }, - } - ); - - let results = await elev.toJSON(); - t.is(count, 0); -}); - -test("Eleventy addGlobalData can feed layouts to populate data cascade with layout data, issue #1245", async (t) => { - let elev = new Eleventy("./test/stubs-2145/", "./test/stubs-2145/_site", { - config: function (eleventyConfig) { - eleventyConfig.addGlobalData("layout", () => "layout.njk"); - eleventyConfig.dataFilterSelectors.add("LayoutData"); - }, - }); - - let [result] = await elev.toJSON(); - t.deepEqual(result.data, { LayoutData: 123 }); - t.is(result.content.trim(), "FromLayoutlayout.njk"); -}); - test("Unicode in front matter `tags`, issue #670", async (t) => { let elev = new Eleventy("./test/stubs-670/", "./test/stubs-670/_site");