diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index e52f51c23..b4ea6471c 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -19,6 +19,7 @@ class Liquid extends TemplateEngine { constructor(name, eleventyConfig) { super(name, eleventyConfig); + this.globalsReference = this.config.globalData; this.liquidOptions = this.config.liquidOptions || {}; this.setLibrary(this.config.libraryOverrides.liquid); @@ -50,11 +51,30 @@ class Liquid extends TemplateEngine { }; let options = Object.assign(defaults, this.liquidOptions || {}); + + this.mergeGlobalData(); + options.globals = this.globalsReference; // debug("Liquid constructor options: %o", options); return options; } + mergeGlobalData() { + for (let name in this.config.liquidOptions.globals) { + if (name in this.config.globalData) continue; + this.config.globalData[name] = this.config.liquidOptions.globals[name]; + } + } + + /** + * Liquid needs to receive globals in order for {% render %} to have access to them + * + * @override + **/ + needsGlobals() { + return true; + } + static wrapFilter(fn) { return function (...args) { if (this.context && "get" in this.context) { @@ -111,6 +131,16 @@ class Liquid extends TemplateEngine { this.liquidLib.registerTag(name, tagObj); } + addGlobals(globals) { + for (let [name, value] of Object.entries(globals)) { + this.addGlobal(name, value); + } + } + + addGlobal(name, value) { + this.globalsReference[name] = value; + } + addAllShortcodes(shortcodes) { for (let name in shortcodes) { this.addShortcode(name, shortcodes[name]); diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 15f6999ac..14e5c9c52 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -115,6 +115,10 @@ class TemplateEngine { return true; } + needsGlobals() { + return false; + } + getExtraDataFromFile() { return {}; } diff --git a/src/Template.js b/src/Template.js index c45661420..2ce02d009 100755 --- a/src/Template.js +++ b/src/Template.js @@ -356,6 +356,14 @@ class Template extends TemplateContent { debugDev("%o getData mergedData", this.inputPath); this._dataCache = mergedData; + if (this.templateRender.engine.needsGlobals()) { + if (typeof this.templateRender.engine.addGlobals != "function") { + throw new Error( + "Internal error: the engine's `.needsGlobals()` method returned `true`, but it does not have an `.addGlobals()` method", + ); + } + this.templateRender.engine.addGlobals(globalData); + } return mergedData; } diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 94a802f39..e324ce93b 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -6,12 +6,12 @@ import EleventyExtensionMap from "../src/EleventyExtensionMap.js"; import { getTemplateConfigInstance } from "./_testHelpers.js"; -async function getNewTemplateRender(name, inputDir, userConfig = {}) { +async function getNewTemplateRender(name, inputDir, userConfig = {}, configCallback) { let eleventyConfig = await getTemplateConfigInstance({ dir: { input: inputDir } - }, null, userConfig); + }, null, userConfig, configCallback); let tr = new TemplateRender(name, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); @@ -1039,3 +1039,21 @@ test("Liquid Parse for Symbols", async (t) => { t.deepEqual(engine.parseForSymbols("{{ collections.mine | test }}>"), ["collections.mine"]); }); + +test("Issue 1541: global data in rendered templates passed through liquidOptions", async (t) => { + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + globals: {globalVariable: "Hello world"} + }, + }); + let fn = await tr.getCompiledTemplate(`

{% render "globals" %}

`); + t.is(await fn(), "

Hello world

"); +}); + +test("Issue 1541: global data in rendered templates passed through addGlobalData", async (t) => { + let tr = await getNewTemplateRender("liquid", "./test/stubs/", null, eleventyConfig => { + eleventyConfig.userConfig.addGlobalData('globalVariable', 'Hello world'); + }); + let fn = await tr.getCompiledTemplate(`

{% render "globals" %}

`); + t.is(await fn(), "

Hello world

"); +}); diff --git a/test/_testHelpers.js b/test/_testHelpers.js index ae8be4b0d..a7bfcf38c 100644 --- a/test/_testHelpers.js +++ b/test/_testHelpers.js @@ -2,7 +2,7 @@ import { isPlainObject } from "@11ty/eleventy-utils"; import TemplateConfig from "../src/TemplateConfig.js"; import ProjectDirectories from "../src/Util/ProjectDirectories.js"; -async function getTemplateConfigInstance(configObj, dirs, configObjOverride = undefined) { +async function getTemplateConfigInstance(configObj, dirs, configObjOverride = undefined, configCallback = undefined) { let eleventyConfig; if(configObj instanceof TemplateConfig) { eleventyConfig = configObj; @@ -25,6 +25,8 @@ async function getTemplateConfigInstance(configObj, dirs, configObjOverride = un eleventyConfig.setDirectories(dirs); + configCallback?.(eleventyConfig); + await eleventyConfig.init(configObjOverride || configObj); // overrides return eleventyConfig; diff --git a/test/stubs/_includes/globals.liquid b/test/stubs/_includes/globals.liquid new file mode 100644 index 000000000..c8a583032 --- /dev/null +++ b/test/stubs/_includes/globals.liquid @@ -0,0 +1 @@ +{{ globalVariable }} \ No newline at end of file