Repository: 11ty/eleventy
Pull request #3255 (2024-04-16 19:13:23)

Cleanup for `--formats`, `templateFormats` config, and `setTemplateFormats` `addTemplateFormats` configuration API methods
Similar to #3244.

Order of precedence:
* `--formats` overrides all—ignores all other methods.
  * **Breaking change:** In 3.x `--formats=""` or `--formats=` means no formats—in 2.x these values aliased to `"*"`
* `eleventyConfig.setTemplateFormats()` (supplemented by `eleventyConfig.addTemplateFormats()`)
* `templateFormats` in return object or in `config` named export  (supplemented by `eleventyConfig.addTemplateFormats()`)


Patch:
diff --git a/cmd.cjs b/cmd.cjs
index bcc9ba43..f96ebb8c 100755
--- a/cmd.cjs
+++ b/cmd.cjs
@@ -80,6 +80,9 @@ const debug = require("debug")("Eleventy:cmd");
 			// reuse ErrorHandler instance in Eleventy
 			errorHandler = elev.errorHandler;
 
+			// Before init
+			elev.setFormats(argv.formats);
+
 			// careful, we can’t use async/await here to error properly
 			// with old node versions in `please-upgrade-node` above.
 			elev
@@ -92,7 +95,6 @@ const debug = require("debug")("Eleventy:cmd");
 
 					elev.setIgnoreInitial(argv["ignore-initial"]);
 					elev.setIncrementalBuild(argv.incremental);
-					elev.setFormats(argv.formats);
 
 					try {
 						if (argv.serve) {
diff --git a/src/Data/TemplateData.js b/src/Data/TemplateData.js
index d35f3cba..9a1d5790 100644
--- a/src/Data/TemplateData.js
+++ b/src/Data/TemplateData.js
@@ -1,4 +1,5 @@
 import path from "node:path";
+import semver from "semver";
 
 import lodash from "@11ty/lodash-custom";
 import { TemplatePath, isPlainObject } from "@11ty/eleventy-utils";
@@ -10,15 +11,12 @@ import TemplateGlob from "../TemplateGlob.js";
 import EleventyExtensionMap from "../EleventyExtensionMap.js";
 import EleventyBaseError from "../Errors/EleventyBaseError.js";
 import TemplateDataInitialGlobalData from "./TemplateDataInitialGlobalData.js";
-import { getEleventyPackageJson } from "../Util/ImportJsonSync.js";
-import {
-	EleventyImport,
-	EleventyLoadContent,
-	normalizeFilePathInEleventyPackage,
-} from "../Util/Require.js";
+import { getEleventyPackageJson, getWorkingProjectPackageJson } from "../Util/ImportJsonSync.js";
+import { EleventyImport, EleventyLoadContent } from "../Util/Require.js";
 import { DeepFreeze } from "../Util/DeepFreeze.js";
 
 const { set: lodashSet, get: lodashGet } = lodash;
+
 const debugWarn = debugUtil("Eleventy:Warnings");
 const debug = debugUtil("Eleventy:TemplateData");
 const debugDev = debugUtil("Dev:Eleventy:TemplateData");
@@ -85,7 +83,8 @@ class TemplateData {
 
 	get extensionMap() {
 		if (!this._extensionMap) {
-			this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
+			this._extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+			this._extensionMap.setFormats([]);
 		}
 		return this._extensionMap;
 	}
@@ -108,16 +107,24 @@ class TemplateData {
 	}
 
 	getRawImports() {
+		if (!this.config.keys.package) {
+			debug(
+				"Opted-out of package.json assignment for global data with falsy value for `keys.package` configuration.",
+			);
+			return this.rawImports;
+		} else if (Object.keys(this.rawImports).length > 0) {
+			return this.rawImports;
+		}
+
 		try {
-			let pkgJson = getEleventyPackageJson();
+			let pkgJson = getWorkingProjectPackageJson();
 			this.rawImports[this.config.keys.package] = pkgJson;
 
 			if (this.config.freezeReservedData) {
 				DeepFreeze(this.rawImports);
 			}
 		} catch (e) {
-			let pkgPath = normalizeFilePathInEleventyPackage("package.json");
-			debug("Could not find and/or require package.json for data preprocessing at %o", pkgPath);
+			debug("Could not find or require package.json import for global data.");
 		}
 
 		return this.rawImports;
@@ -311,6 +318,15 @@ class TemplateData {
 			this.configApiGlobalData = new Promise(async (resolve) => {
 				let globalData = await this.initialGlobalData.getData();
 
+				if (!("eleventy" in globalData)) {
+					globalData.eleventy = {};
+				}
+
+				// #2293 for meta[name=generator]
+				const pkg = getEleventyPackageJson();
+				globalData.eleventy.version = semver.coerce(pkg.version).toString();
+				globalData.eleventy.generator = `Eleventy v${globalData.eleventy.version}`;
+
 				if (this.environmentVariables) {
 					if (!("env" in globalData.eleventy)) {
 						globalData.eleventy.env = {};
diff --git a/src/Data/TemplateDataInitialGlobalData.js b/src/Data/TemplateDataInitialGlobalData.js
index fc83a5c2..ffd5029f 100644
--- a/src/Data/TemplateDataInitialGlobalData.js
+++ b/src/Data/TemplateDataInitialGlobalData.js
@@ -1,11 +1,8 @@
-import semver from "semver";
 import lodash from "@11ty/lodash-custom";
 
 import EleventyBaseError from "../Errors/EleventyBaseError.js";
-import { getEleventyPackageJson } from "../Util/ImportJsonSync.js";
 
 const { set: lodashSet } = lodash;
-const pkg = getEleventyPackageJson();
 
 class TemplateDataConfigError extends EleventyBaseError {}
 
@@ -35,13 +32,6 @@ class TemplateDataInitialGlobalData {
 			}
 		}
 
-		if (!("eleventy" in globalData)) {
-			globalData.eleventy = {};
-		}
-		// #2293 for meta[name=generator]
-		globalData.eleventy.version = semver.coerce(pkg.version).toString();
-		globalData.eleventy.generator = `Eleventy v${globalData.eleventy.version}`;
-
 		return globalData;
 	}
 }
diff --git a/src/Eleventy.js b/src/Eleventy.js
index 671bf065..88de12af 100644
--- a/src/Eleventy.js
+++ b/src/Eleventy.js
@@ -26,6 +26,7 @@ import RenderPlugin, * as RenderPluginExtras from "./Plugins/RenderPlugin.js";
 import I18nPlugin, * as I18nPluginExtras from "./Plugins/I18nPlugin.js";
 import HtmlBasePlugin, * as HtmlBasePluginExtras from "./Plugins/HtmlBasePlugin.js";
 import { TransformPlugin as InputPathToUrlTransformPlugin } from "./Plugins/InputPathToUrl.js";
+import ProjectTemplateFormats from "./Util/ProjectTemplateFormats.js";
 
 const pkg = getEleventyPackageJson();
 const debug = debugUtil("Eleventy");
@@ -42,8 +43,9 @@ const debug = debugUtil("Eleventy");
  * @returns {module:11ty/eleventy/Eleventy~Eleventy}
  */
 class Eleventy {
-	#directories; /* ProjectDirectories instance */
 	#projectPackageJson; /* userspace package.json file contents */
+	#directories; /* ProjectDirectories instance */
+	#templateFormats; /* ProjectTemplateFormats instance */
 
 	constructor(input, output, options = {}, eleventyConfig = null) {
 		/** @member {String} - Holds the path to the input (might be a file or folder) */
@@ -97,12 +99,6 @@ class Eleventy {
 		 */
 		this.needsInit = true;
 
-		/**
-		 * @member {Array<String>} - Subset of template types.
-		 * @default null
-		 */
-		this.formatsOverride = null;
-
 		/**
 		 * @member {Boolean} - Is this an incremental build? (only operates on a subset of input files)
 		 * @default false
@@ -139,6 +135,7 @@ class Eleventy {
 		this.eleventyConfig.setProjectUsingEsm(this.isEsm);
 		this.eleventyConfig.setLogger(this.logger);
 		this.eleventyConfig.setDirectories(this.directories);
+		this.eleventyConfig.setTemplateFormats(this.templateFormats);
 
 		if (this.pathPrefix || this.pathPrefix === "") {
 			this.eleventyConfig.setPathPrefix(this.pathPrefix);
@@ -423,8 +420,10 @@ class Eleventy {
 			await this.config.events.emit("eleventy.env", this.env);
 		}
 
-		let formats = this.formatsOverride || this.config.templateFormats;
-		this.extensionMap = new EleventyExtensionMap(formats, this.eleventyConfig);
+		let formats = this.templateFormats.getTemplateFormats();
+
+		this.extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+		this.extensionMap.setFormats(formats);
 		await this.config.events.emit("eleventy.extensionmap", this.extensionMap);
 
 		// eleventyServe is always available, even when not in --serve mode
@@ -617,6 +616,15 @@ Verbose Output: ${this.verboseMode}`;
 		this.eleventyConfig.verbose = isVerbose;
 	}
 
+	get templateFormats() {
+		if (!this.#templateFormats) {
+			let tf = new ProjectTemplateFormats();
+			this.#templateFormats = tf;
+		}
+
+		return this.#templateFormats;
+	}
+
 	/**
 	 * Updates the template formats of Eleventy.
 	 *
@@ -624,9 +632,7 @@ Verbose Output: ${this.verboseMode}`;
 	 * @param {String} formats - The new template formats.
 	 */
 	setFormats(formats) {
-		if (formats && formats !== "*") {
-			this.formatsOverride = formats.split(",");
-		}
+		this.templateFormats.setViaCommandLine(formats);
 	}
 
 	/**
diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js
index 1d744b0d..3f1bbedd 100644
--- a/src/EleventyExtensionMap.js
+++ b/src/EleventyExtensionMap.js
@@ -6,17 +6,16 @@ import EleventyBaseError from "./Errors/EleventyBaseError.js";
 class EleventyExtensionMapConfigError extends EleventyBaseError {}
 
 class EleventyExtensionMap {
-	constructor(formatKeys, config) {
+	constructor(config) {
 		this.config = config;
 
-		this.formatKeys = formatKeys;
-
-		this.setFormats(formatKeys);
-
 		this._spiderJsDepsCache = {};
 	}
 
 	setFormats(formatKeys = []) {
+		// raw
+		this.formatKeys = formatKeys;
+
 		this.unfilteredFormatKeys = formatKeys.map(function (key) {
 			return key.trim().toLowerCase();
 		});
@@ -251,6 +250,10 @@ class EleventyExtensionMap {
 		return this._extensionToKeyMap;
 	}
 
+	getAllTemplateKeys() {
+		return Object.keys(this.extensionToKeyMap);
+	}
+
 	getReadableFileExtensions() {
 		return Object.keys(this.extensionToKeyMap).join(" ");
 	}
diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js
index e9bd853c..fea45bb4 100644
--- a/src/EleventyFiles.js
+++ b/src/EleventyFiles.js
@@ -130,7 +130,8 @@ class EleventyFiles {
 	get extensionMap() {
 		// for tests
 		if (!this._extensionMap) {
-			this._extensionMap = new EleventyExtensionMap(this.formats, this.eleventyConfig);
+			this._extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+			this._extensionMap.setFormats(this.formats);
 			this._extensionMap.config = this.eleventyConfig;
 		}
 		return this._extensionMap;
diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js
index 15f6999a..b3c7e33c 100644
--- a/src/Engines/TemplateEngine.js
+++ b/src/Engines/TemplateEngine.js
@@ -55,7 +55,8 @@ class TemplateEngine {
 
 	get extensionMap() {
 		if (!this._extensionMap) {
-			this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
+			this._extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+			this._extensionMap.setFormats([]);
 		}
 		return this._extensionMap;
 	}
diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js
index c16050ff..98e130df 100644
--- a/src/TemplateConfig.js
+++ b/src/TemplateConfig.js
@@ -9,8 +9,8 @@ import UserConfig from "./UserConfig.js";
 import GlobalDependencyMap from "./GlobalDependencyMap.js";
 import ExistsCache from "./Util/ExistsCache.js";
 import merge from "./Util/Merge.js";
-import unique from "./Util/Unique.js";
 import eventBus from "./EventBus.js";
+import ProjectTemplateFormats from "./Util/ProjectTemplateFormats.js";
 
 const debug = debugUtil("Eleventy:TemplateConfig");
 const debugDev = debugUtil("Dev:Eleventy:TemplateConfig");
@@ -50,6 +50,8 @@ class EleventyPluginError extends EleventyBaseError {}
  * @param {String} projectConfigPath - Path to local project config.
  */
 class TemplateConfig {
+	#templateFormats;
+
 	constructor(customRootConfig, projectConfigPath) {
 		this.userConfig = new UserConfig();
 
@@ -101,6 +103,18 @@ class TemplateConfig {
 		this.userConfig.directories = directories.getUserspaceInstance();
 	}
 
+	/* Setter for TemplateFormats instance */
+	setTemplateFormats(templateFormats) {
+		this.#templateFormats = templateFormats;
+	}
+
+	get templateFormats() {
+		if (!this.#templateFormats) {
+			this.#templateFormats = new ProjectTemplateFormats();
+		}
+		return this.#templateFormats;
+	}
+
 	/* Backwards compat */
 	get inputDir() {
 		return this.directories.input;
@@ -335,8 +349,6 @@ class TemplateConfig {
 					this.directories.setViaConfigObject(exportedConfigObject.dir);
 				}
 
-				// TODO (config) sync `exportedConfigObject` to the rest of `userConfig` (e.g. templateFormats)
-
 				if (typeof configDefaultReturn === "function") {
 					localConfig = await configDefaultReturn(this.userConfig);
 				} else {
@@ -399,20 +411,28 @@ class TemplateConfig {
 			}
 		}
 
-		// Template Formats:
-		// 1. Root Config (usually defaultConfig.js)
-		// 2. Local Config return object (project .eleventy.js)
-		// 3.
-		let templateFormats = this.rootConfig.templateFormats || [];
-		if (localConfig && localConfig.templateFormats) {
-			templateFormats = localConfig.templateFormats;
-			delete localConfig.templateFormats;
+		// `templateFormats` is an override via `setTemplateFormats`
+		if (this.userConfig && this.userConfig.templateFormats) {
+			this.templateFormats.setViaConfig(this.userConfig.templateFormats);
+		} else if (localConfig?.templateFormats || this.rootConfig?.templateFormats) {
+			// Local project config or defaultConfig.js
+			this.templateFormats.setViaConfig(
+				localConfig.templateFormats || this.rootConfig?.templateFormats,
+			);
+		}
+
+		// `templateFormatsAdded` is additive via `addTemplateFormats`
+		if (this.userConfig && this.userConfig.templateFormatsAdded) {
+			this.templateFormats.addViaConfig(this.userConfig.templateFormatsAdded);
 		}
 
 		let mergedConfig = merge({}, this.rootConfig, localConfig);
 
 		// Setup a few properties for plugins:
 
+		// Set frozen templateFormats
+		mergedConfig.templateFormats = Object.freeze(this.templateFormats.getTemplateFormats());
+
 		// Setup pathPrefix set via command line for plugin consumption
 		if (this.overrides.pathPrefix) {
 			mergedConfig.pathPrefix = this.overrides.pathPrefix;
@@ -433,9 +453,6 @@ class TemplateConfig {
 		// But BEFORE the rest of the config options are merged
 		// this way we can pass directories and other template information to plugins
 
-		// Temporarily restore templateFormats
-		mergedConfig.templateFormats = templateFormats;
-
 		await this.userConfig.events.emit("eleventy.beforeConfig", this.userConfig);
 
 		let benchmarkManager = this.userConfig.benchmarkManager.get("Aggregate");
@@ -444,30 +461,17 @@ class TemplateConfig {
 		await this.processPlugins(mergedConfig);
 		pluginsBench.after();
 
-		delete mergedConfig.templateFormats;
-
 		let eleventyConfigApiMergingObject = this.userConfig.getMergingConfigObject();
 
-		// `templateFormats` is an override via `setTemplateFormats`
-		// `templateFormatsAdded` is additive via `addTemplateFormats`
-		if (eleventyConfigApiMergingObject && eleventyConfigApiMergingObject.templateFormats) {
-			templateFormats = eleventyConfigApiMergingObject.templateFormats;
-			delete eleventyConfigApiMergingObject.templateFormats;
+		if ("templateFormats" in eleventyConfigApiMergingObject) {
+			throw new Error(
+				"Internal error: templateFormats should not return from `getMergingConfigObject`",
+			);
 		}
 
-		let templateFormatsAdded = eleventyConfigApiMergingObject.templateFormatsAdded || [];
-		delete eleventyConfigApiMergingObject.templateFormatsAdded;
-
-		templateFormats = unique([...templateFormats, ...templateFormatsAdded]);
-
-		merge(mergedConfig, eleventyConfigApiMergingObject);
-
-		// Apply overrides, currently only pathPrefix uses this I think!
+		// Overrides are only used by pathPrefix
 		debug("Configuration overrides: %o", this.overrides);
-		merge(mergedConfig, this.overrides);
-
-		// Restore templateFormats
-		mergedConfig.templateFormats = templateFormats;
+		merge(mergedConfig, eleventyConfigApiMergingObject, this.overrides);
 
 		debug("Current configuration: %o", mergedConfig);
 
diff --git a/src/TemplateContent.js b/src/TemplateContent.js
index c935d277..f8eabd8e 100644
--- a/src/TemplateContent.js
+++ b/src/TemplateContent.js
@@ -81,7 +81,8 @@ class TemplateContent {
 	/* Used by tests */
 	get extensionMap() {
 		if (!this._extensionMap) {
-			this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
+			this._extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+			this._extensionMap.setFormats([]);
 		}
 		return this._extensionMap;
 	}
diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js
index dbf29ed8..664da514 100644
--- a/src/TemplatePassthroughManager.js
+++ b/src/TemplatePassthroughManager.js
@@ -37,7 +37,8 @@ class TemplatePassthroughManager {
 
 	get extensionMap() {
 		if (!this._extensionMap) {
-			this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
+			this._extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+			this._extensionMap.setFormats([]);
 		}
 		return this._extensionMap;
 	}
diff --git a/src/TemplateRender.js b/src/TemplateRender.js
index 9e4c5a3f..c6567991 100644
--- a/src/TemplateRender.js
+++ b/src/TemplateRender.js
@@ -61,7 +61,8 @@ class TemplateRender {
 
 	get extensionMap() {
 		if (!this._extensionMap) {
-			this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
+			this._extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+			this._extensionMap.setFormats([]);
 		}
 		return this._extensionMap;
 	}
diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js
index 06ea9fdc..81d5ccfb 100755
--- a/src/TemplateWriter.js
+++ b/src/TemplateWriter.js
@@ -106,7 +106,8 @@ class TemplateWriter {
 
 	get extensionMap() {
 		if (!this._extensionMap) {
-			this._extensionMap = new EleventyExtensionMap(this.templateFormats, this.eleventyConfig);
+			this._extensionMap = new EleventyExtensionMap(this.eleventyConfig);
+			this._extensionMap.setFormats(this.templateFormats);
 		}
 		return this._extensionMap;
 	}
diff --git a/src/UserConfig.js b/src/UserConfig.js
index fa68e6e9..dedc9a23 100644
--- a/src/UserConfig.js
+++ b/src/UserConfig.js
@@ -48,6 +48,7 @@ class UserConfig {
 		this.collections = {};
 		this.precompiledCollections = {};
 		this.templateFormats = undefined;
+		this.templateFormatsAdded = [];
 
 		this.liquidOptions = {};
 		this.liquidTags = {};
@@ -489,38 +490,17 @@ class UserConfig {
 		return this;
 	}
 
-	_normalizeTemplateFormats(templateFormats, existingValues) {
-		// setTemplateFormats(null) should return null
-		if (templateFormats === null || templateFormats === undefined) {
-			return null;
-		}
-
-		let set = new Set();
-		if (Array.isArray(templateFormats)) {
-			set = new Set(templateFormats.map((format) => format.trim()));
-		} else if (typeof templateFormats === "string") {
-			for (let format of templateFormats.split(",")) {
-				set.add(format.trim());
-			}
-		}
-
-		for (let format of existingValues || []) {
-			set.add(format);
-		}
-
-		return Array.from(set);
+	_normalizeTemplateFormats() {
+		throw new Error("The internal _normalizeTemplateFormats() method was removed in Eleventy 3.0");
 	}
 
 	setTemplateFormats(templateFormats) {
-		this.templateFormats = this._normalizeTemplateFormats(templateFormats);
+		this.templateFormats = templateFormats;
 	}
 
 	// additive, usually for plugins
 	addTemplateFormats(templateFormats) {
-		this.templateFormatsAdded = this._normalizeTemplateFormats(
-			templateFormats,
-			this.templateFormatsAdded,
-		);
+		this.templateFormatsAdded.push(templateFormats);
 	}
 
 	setLibrary(engineName, libraryInstance) {
@@ -927,8 +907,6 @@ class UserConfig {
 
 	getMergingConfigObject() {
 		let obj = {
-			templateFormats: this.templateFormats,
-			templateFormatsAdded: this.templateFormatsAdded,
 			// filters removed in 1.0 (use addTransform instead)
 			transforms: this.transforms,
 			linters: this.linters,
diff --git a/src/Util/ProjectTemplateFormats.js b/src/Util/ProjectTemplateFormats.js
new file mode 100644
index 00000000..69243de6
--- /dev/null
+++ b/src/Util/ProjectTemplateFormats.js
@@ -0,0 +1,130 @@
+import debugUtil from "debug";
+const debug = debugUtil("Eleventy:Util:ProjectTemplateFormats");
+
+class ProjectTemplateFormats {
+	#useAll = {};
+	#raw = {};
+
+	#allFormats = [];
+	#values = {}; // Set objects
+
+	static union(...sets) {
+		let s = new Set();
+
+		for (let set of sets) {
+			if (!set || typeof set[Symbol.iterator] !== "function") {
+				continue;
+			}
+			for (let v of set) {
+				s.add(v);
+			}
+		}
+
+		return s;
+	}
+
+	#normalize(formats) {
+		if (Array.isArray(formats)) {
+			return formats.map((entry) => entry.trim());
+		}
+
+		if (typeof formats !== "string") {
+			throw new Error(
+				`Invalid formats (expect String, Array) passed to ProjectTemplateFormats->normalize: ${formats}`,
+			);
+		}
+
+		let final = new Set();
+		for (let format of formats.split(",")) {
+			format = format.trim();
+			if (format && format !== "*") {
+				final.add(format);
+			}
+		}
+
+		return final;
+	}
+
+	#isUseAll(rawFormats) {
+		if (rawFormats === "") {
+			return false;
+		}
+
+		if (typeof rawFormats === "string") {
+			rawFormats = rawFormats.split(",");
+		}
+
+		if (Array.isArray(rawFormats)) {
+			return rawFormats.find((entry) => entry === "*") !== undefined;
+		}
+
+		return false;
+	}
+
+	// 3.x Breaking: "" now means no formats. In 2.x and prior it meant "*"
+	setViaCommandLine(formats) {
+		if (formats === undefined) {
+			return;
+		}
+
+		this.#useAll.cli = this.#isUseAll(formats);
+		this.#raw.cli = formats;
+		this.#values.cli = this.#normalize(formats);
+	}
+
+	// 3.x Breaking: "" now means no formats—in 2.x and prior it meant "*"
+	// 3.x Adds support for comma separated string—in 2.x this required an Array
+	setViaConfig(formats) {
+		if (formats === undefined) {
+			return;
+		}
+
+		// "*" is supported
+		this.#useAll.config = this.#isUseAll(formats);
+		this.#raw.config = formats;
+		this.#values.config = this.#normalize(formats);
+	}
+
+	addViaConfig(formats) {
+		if (!formats) {
+			return;
+		}
+
+		if (this.#isUseAll(formats)) {
+			throw new Error(
+				`\`addTemplateFormats("*")\` is not supported for project template syntaxes.`,
+			);
+		}
+
+		// "*" not supported here
+		this.#raw.configAdd = formats;
+		this.#values.configAdd = this.#normalize(formats);
+	}
+
+	getAllTemplateFormats() {
+		return Array.from(ProjectTemplateFormats.union(this.#values.config, this.#values.configAdd));
+	}
+
+	getTemplateFormats() {
+		if (this.#useAll.cli) {
+			let v = this.getAllTemplateFormats();
+			debug("Using CLI --formats='*': %o", v);
+			return v;
+		}
+
+		if (this.#raw.cli !== undefined) {
+			let v = Array.from(this.#values.cli);
+			debug("Using CLI --formats: %o", v);
+			return v;
+		}
+
+		let v = this.getAllTemplateFormats();
+		debug(
+			"Using configuration `templateFormats`, `setTemplateFormats()`, `addTemplateFormats()`: %o",
+			v,
+		);
+		return v;
+	}
+}
+
+export default ProjectTemplateFormats;
diff --git a/src/defaultConfig.js b/src/defaultConfig.js
index 00213459..9234d3a6 100644
--- a/src/defaultConfig.js
+++ b/src/defaultConfig.js
@@ -31,7 +31,7 @@ import { HtmlTransformer } from "./Util/HtmlTransformer.js";
  * @property {string} [htmlOutputSuffix='-o']
  * @property {string} [jsDataFileSuffix='.11tydata'] - File suffix for jsData files.
  * @property {Object} keys
- * @property {string} [keys.package='pkg']
+ * @property {string} [keys.package='pkg'] - Global data property for package.json data
  * @property {string} [keys.layout='layout']
  * @property {string} [keys.permalink='permalink']
  * @property {string} [keys.permalinkRoot='permalinkBypassOutputDir']
@@ -118,7 +118,8 @@ export default function (config) {
 		dataFileDirBaseNameOverride: false,
 
 		keys: {
-			package: "pkg",
+			// TODO breaking: use `false` by default
+			package: "pkg", // supports `false`
 			layout: "layout",
 			permalink: "permalink",
 			permalinkRoot: "permalinkBypassOutputDir",


Test patch:
diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js
index a040ec66..6abb8a5a 100644
--- a/test/EleventyExtensionMapTest.js
+++ b/test/EleventyExtensionMapTest.js
@@ -6,7 +6,8 @@ async function getExtensionMap(formats, config = new TemplateConfig()) {
   if (config) {
     await config.init();
   }
-  let map = new EleventyExtensionMap(formats, config);
+  let map = new EleventyExtensionMap(config);
+  map.setFormats(formats);
   return map;
 }
 
diff --git a/test/EleventyTest.js b/test/EleventyTest.js
index 77fdc40a..d14ca60f 100644
--- a/test/EleventyTest.js
+++ b/test/EleventyTest.js
@@ -1066,6 +1066,37 @@ pkg:
   });
 });
 
+test("Eleventy setting pkg data is okay when keys.package is false", async (t) => {
+  let elev = new Eleventy("./test/stubs-virtual/", undefined, {
+    config: eleventyConfig => {
+      eleventyConfig.addTemplate("index.html", `---
+pkg:
+  myOwn: OVERRIDE
+---
+{{ pkg.myOwn }}`);
+    }
+  });
+  elev.disableLogger();
+
+  await elev.initializeConfig({
+    keys: {
+      package: false
+    }
+  });
+
+  // Remap successful
+  t.is(elev.eleventyConfig.config.keys.package, false);
+
+  let [result] = await elev.toJSON();
+  t.deepEqual(result, {
+    content: "OVERRIDE",
+    inputPath: "./test/stubs-virtual/index.html",
+    outputPath: "./_site/index.html",
+    rawInput: "{{ pkg.myOwn }}",
+    url: "/"
+  });
+});
+
 test("Eleventy setting reserved data throws error (pkg remapped to parkour)", async (t) => {
   let elev = new Eleventy("./test/stubs-virtual/", undefined, {
     config: eleventyConfig => {
diff --git a/test/ProjectTemplateFormatsTest.js b/test/ProjectTemplateFormatsTest.js
new file mode 100644
index 00000000..c42973c5
--- /dev/null
+++ b/test/ProjectTemplateFormatsTest.js
@@ -0,0 +1,196 @@
+import test from "ava";
+import ProjectTemplateFormats from "../src/Util/ProjectTemplateFormats.js";
+
+function getTestInstance() {
+  let tf = new ProjectTemplateFormats();
+  return tf;
+}
+
+test("Empty formats", t => {
+  let tf = new ProjectTemplateFormats();
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+test("Return all eligible on no config or CLI", t => {
+  let tf = getTestInstance();
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+
+// CLI
+test("CLI", t => {
+  let tf = getTestInstance();
+  tf.setViaCommandLine("md,html");
+
+  t.deepEqual(tf.getTemplateFormats(), ["md", "html"]);
+});
+
+test("CLI empty", t => {
+  let tf = getTestInstance();
+  tf.setViaCommandLine("");
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+test("CLI *", t => {
+  let tf = getTestInstance();
+  tf.setViaCommandLine("*");
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+
+// Config Set
+test("Config", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("md,html");
+
+  t.deepEqual(tf.getTemplateFormats(), ["md", "html"]);
+});
+
+test("Config empty", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("");
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+test("Config *", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("*");
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+
+// Config Add
+test("Config Add", t => {
+  let tf = getTestInstance();
+  // add without set unions all with new
+  tf.addViaConfig("md,html");
+
+  t.deepEqual(tf.getTemplateFormats(), ["md", "html"]);
+});
+
+test("Config Add (not yet known)", t => {
+  let tf = getTestInstance();
+  // add without set unions all with new
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), ["vue"]);
+});
+
+test("Config Add empty", t => {
+  let tf = getTestInstance();
+  tf.addViaConfig("");
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+test("Config Add *", t => {
+  let tf = getTestInstance();
+  t.throws(() => {
+    tf.addViaConfig("*");
+  }, {
+    message: '`addTemplateFormats("*")` is not supported for project template syntaxes.'
+  });
+});
+
+test("Config Add Multiple", t => {
+  let tf = getTestInstance();
+// While this does support multiple addTemplateFormat calls from config, they are collected and addViaConfig is only called once.
+  // add without set unions all with new
+  tf.addViaConfig("vue");
+  tf.addViaConfig("pug");
+  tf.addViaConfig("zbbbbb");
+
+  t.deepEqual(tf.getTemplateFormats(), ["zbbbbb"]);
+});
+
+
+// CLI and Config (CLI wins every time)
+test("CLI + Config", t => {
+  let tf = getTestInstance();
+  tf.setViaCommandLine("md,html");
+  tf.setViaConfig("liquid");
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), ["md", "html"]);
+});
+
+test("CLI + Config empty", t => {
+  let tf = getTestInstance();
+  tf.setViaCommandLine("");
+  tf.setViaConfig("liquid");
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+test("CLI + Config *", t => {
+  let tf = getTestInstance();
+  tf.setViaCommandLine("*");
+  tf.setViaConfig("liquid");
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), ["liquid", "vue"]);
+});
+
+
+// Config set and add
+test("Config set/add", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("liquid");
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), ["liquid", "vue"]);
+});
+
+test("Config set/add set undefined", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig(undefined);
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), ["vue"]);
+});
+
+test("Config set/add add undefined", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("vue");
+  tf.addViaConfig(undefined);
+
+  t.deepEqual(tf.getTemplateFormats(), ["vue"]);
+});
+
+test("Config set/add set empty", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("");
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), ["vue"]);
+});
+
+test("Config set/add add empty", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("vue");
+  tf.addViaConfig("");
+
+  t.deepEqual(tf.getTemplateFormats(), ["vue"]);
+});
+
+test("Config set/add both empty", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("");
+  tf.addViaConfig("");
+
+  t.deepEqual(tf.getTemplateFormats(), []);
+});
+
+test("Config set *, add", t => {
+  let tf = getTestInstance();
+  tf.setViaConfig("*");
+  tf.addViaConfig("vue");
+
+  t.deepEqual(tf.getTemplateFormats(), ["vue"]);
+});
diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js
index aa9ea076..96ca2704 100644
--- a/test/TemplateConfigTest.js
+++ b/test/TemplateConfigTest.js
@@ -282,7 +282,7 @@ test("setTemplateFormats(null)", async (t) => {
   await templateCfg.init();
 
   let cfg = templateCfg.getConfig();
-  t.deepEqual(cfg.templateFormats.sort(), ["md", "njk"]);
+  t.deepEqual([...cfg.templateFormats].sort(), ["md", "njk"]);
 });
 
 test("setTemplateFormats(undefined)", async (t) => {
@@ -292,7 +292,7 @@ test("setTemplateFormats(undefined)", async (t) => {
   await templateCfg.init();
 
   let cfg = templateCfg.getConfig();
-  t.deepEqual(cfg.templateFormats.sort(), ["md", "njk"]);
+  t.deepEqual([...cfg.templateFormats].sort(), ["md", "njk"]);
 });
 
 test("multiple setTemplateFormats calls", async (t) => {
diff --git a/test/TemplateFileSlugTest.js b/test/TemplateFileSlugTest.js
index 154c08ea..1ce9e865 100644
--- a/test/TemplateFileSlugTest.js
+++ b/test/TemplateFileSlugTest.js
@@ -12,7 +12,8 @@ async function getNewSlugInstance(path, inputDir) {
     }
   });
 
-  let extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  let extensionMap = new EleventyExtensionMap(eleventyConfig);
+  extensionMap.setFormats([]);
   let fs = new TemplateFileSlug(path, extensionMap, eleventyConfig);
   return fs;
 }
diff --git a/test/TemplateLayoutPathResolverTest.js b/test/TemplateLayoutPathResolverTest.js
index 2df43287..8b5c18f4 100644
--- a/test/TemplateLayoutPathResolverTest.js
+++ b/test/TemplateLayoutPathResolverTest.js
@@ -15,7 +15,8 @@ async function getResolverInstance(path, inputDir, { eleventyConfig, map } = {})
   }
 
   if (!map) {
-    map = new EleventyExtensionMap(["liquid", "md", "njk", "html", "11ty.js"], eleventyConfig);
+    map = new EleventyExtensionMap(eleventyConfig);
+    map.setFormats(["liquid", "md", "njk", "html", "11ty.js"]);
   }
 
   return new TemplateLayoutPathResolver(path, map, eleventyConfig);
diff --git a/test/TemplateLayoutTest.js b/test/TemplateLayoutTest.js
index d798a276..7af3b387 100644
--- a/test/TemplateLayoutTest.js
+++ b/test/TemplateLayoutTest.js
@@ -14,7 +14,8 @@ async function getTemplateLayoutInstance(key, inputDir, map) {
 	});
 
   if (!map) {
-    map = new EleventyExtensionMap(["liquid", "md", "njk", "html", "11ty.js"], eleventyConfig);
+    map = new EleventyExtensionMap(eleventyConfig);
+    map.setFormats(["liquid", "md", "njk", "html", "11ty.js"]);
   }
   let layout = new TemplateLayout(key, map, eleventyConfig);
   return layout;
diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js
index 92e7b002..d418c250 100644
--- a/test/TemplateRenderCustomTest.js
+++ b/test/TemplateRenderCustomTest.js
@@ -17,7 +17,8 @@ async function getNewTemplateRender(name, inputDir, eleventyConfig, extensionMap
   }
 
   if (!extensionMap) {
-    extensionMap = new EleventyExtensionMap([], eleventyConfig);
+    extensionMap = new EleventyExtensionMap(eleventyConfig);
+    extensionMap.setFormats([]);
   }
 
   let tr = new TemplateRender(name, eleventyConfig);
@@ -318,7 +319,8 @@ test.skip("Breaking Change (3.0): Two simple aliases to JavaScript Render", asyn
     }
   );
 
-  let map = new EleventyExtensionMap([], eleventyConfig); // reuse this
+  let map = new EleventyExtensionMap(eleventyConfig); // reuse this
+  map.setFormats([]);
 
   let tr = await getNewTemplateRender("./test/stubs/string.11ty.custom", null, eleventyConfig, map);
   let fn = await tr.getCompiledTemplate();
@@ -347,7 +349,8 @@ test("Double override (not aliases) throws an error", async (t) => {
     }
   );
 
-  let map = new EleventyExtensionMap([], eleventyConfig); // reuse this
+  let map = new EleventyExtensionMap(eleventyConfig); // reuse this
+  map.setFormats([]);
 
   await t.throwsAsync(
     async () => {
diff --git a/test/TemplateRenderHTMLTest.js b/test/TemplateRenderHTMLTest.js
index b3ddd3a8..8079344a 100644
--- a/test/TemplateRenderHTMLTest.js
+++ b/test/TemplateRenderHTMLTest.js
@@ -12,7 +12,8 @@ async function getNewTemplateRender(name, inputDir) {
 	});
 
   let tr = new TemplateRender(name, eleventyConfig);
-  tr.extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  tr.extensionMap = new EleventyExtensionMap(eleventyConfig);
+  tr.extensionMap.setFormats([]);
   await tr.init();
   return tr;
 }
diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js
index 7737f803..8dcfdef1 100644
--- a/test/TemplateRenderJavaScriptTest.js
+++ b/test/TemplateRenderJavaScriptTest.js
@@ -13,7 +13,8 @@ async function getNewTemplateRender(name, inputDir, extendedConfig) {
 	}, null, extendedConfig);
 
   let tr = new TemplateRender(name, eleventyConfig);
-  tr.extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  tr.extensionMap = new EleventyExtensionMap(eleventyConfig);
+  tr.extensionMap.setFormats([]);
   await tr.init();
 
   return tr;
diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js
index 94a802f3..7e847e1e 100644
--- a/test/TemplateRenderLiquidTest.js
+++ b/test/TemplateRenderLiquidTest.js
@@ -14,7 +14,8 @@ async function getNewTemplateRender(name, inputDir, userConfig = {}) {
 	}, null, userConfig);
 
   let tr = new TemplateRender(name, eleventyConfig);
-  tr.extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  tr.extensionMap = new EleventyExtensionMap(eleventyConfig);
+  tr.extensionMap.setFormats([]);
   await tr.init();
   return tr;
 }
diff --git a/test/TemplateRenderMarkdownPluginTest.js b/test/TemplateRenderMarkdownPluginTest.js
index 356b8666..57bd88a0 100644
--- a/test/TemplateRenderMarkdownPluginTest.js
+++ b/test/TemplateRenderMarkdownPluginTest.js
@@ -10,7 +10,8 @@ async function getNewTemplateRender(name, inputDir) {
   let eleventyConfig = await getTemplateConfigInstance();
 
   let tr = new TemplateRender(name, eleventyConfig);
-  tr.extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  tr.extensionMap = new EleventyExtensionMap(eleventyConfig);
+  tr.extensionMap.setFormats([]);
   await tr.init();
   return tr;
 }
diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js
index c1bb7ce9..ff25e933 100644
--- a/test/TemplateRenderMarkdownTest.js
+++ b/test/TemplateRenderMarkdownTest.js
@@ -21,7 +21,8 @@ async function getNewTemplateRender(name, inputDir, eleventyConfig) {
   }
 
   let tr = new TemplateRender(name, eleventyConfig);
-  tr.extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  tr.extensionMap = new EleventyExtensionMap(eleventyConfig);
+  tr.extensionMap.setFormats([]);
   await tr.init();
   return tr;
 }
diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js
index 8e662337..7fcfc430 100644
--- a/test/TemplateRenderNunjucksTest.js
+++ b/test/TemplateRenderNunjucksTest.js
@@ -17,7 +17,8 @@ async function getNewTemplateRender(name, inputDir, eleventyConfig) {
   }
 
   let tr = new TemplateRender(name, eleventyConfig);
-  tr.extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  tr.extensionMap = new EleventyExtensionMap(eleventyConfig);
+  tr.extensionMap.setFormats([]);
   await tr.init();
   return tr;
 }
diff --git a/test/TemplateRenderTest.js b/test/TemplateRenderTest.js
index d2de6564..203dbaf5 100644
--- a/test/TemplateRenderTest.js
+++ b/test/TemplateRenderTest.js
@@ -13,7 +13,8 @@ async function getNewTemplateRender(name, inputDir) {
   });
 
   let tr = new TemplateRender(name, eleventyConfig);
-  tr.extensionMap = new EleventyExtensionMap([], eleventyConfig);
+  tr.extensionMap = new EleventyExtensionMap(eleventyConfig);
+  tr.extensionMap.setFormats([]);
   await tr.init();
   return tr;
 }
diff --git a/test/TemplateTest.js b/test/TemplateTest.js
index 3d077d26..f632bf65 100644
--- a/test/TemplateTest.js
+++ b/test/TemplateTest.js
@@ -1655,7 +1655,8 @@ test("Engine Singletons", async (t) => {
     }
   });
 
-  let map = new EleventyExtensionMap(["njk"], eleventyConfig);
+  let map = new EleventyExtensionMap(eleventyConfig);
+  map.setFormats(["njk"]);
   let tmpl1 = await getNewTemplate(
     "./test/stubs/engine-singletons/first.njk",
     "./test/stubs/engine-singletons/",
@@ -1738,7 +1739,8 @@ test("Add Extension via Configuration (txt file)", async (t) => {
     });
   });
 
-  let map = new EleventyExtensionMap([], eleventyConfig);
+  let map = new EleventyExtensionMap(eleventyConfig);
+  map.setFormats([]);
   let tmpl = await getNewTemplate(
     "./test/stubs/default.txt",
     "./test/stubs/",
diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js
index c80ab6e4..fd9ea63a 100644
--- a/test/TemplateWriterTest.js
+++ b/test/TemplateWriterTest.js
@@ -629,7 +629,8 @@ test.skip("Markdown with alias", async (t) => {
     }
   });
 
-  let map = new EleventyExtensionMap(["md"], eleventyConfig);
+  let map = new EleventyExtensionMap(eleventyConfig);
+  map.setFormats(["md"]);
   map.config = {
     templateExtensionAliases: {
       markdown: "md",
@@ -675,7 +676,8 @@ test.skip("JavaScript with alias", async (t) => {
     }
   });
 
-  let map = new EleventyExtensionMap(["11ty.js"], eleventyConfig);
+  let map = new EleventyExtensionMap(eleventyConfig);
+  map.setFormats(["11ty.js"]);
   map.config = {
     templateExtensionAliases: {
       js: "11ty.js",
diff --git a/test/UserConfigTest.js b/test/UserConfigTest.js
index 2a870b02..971f3df5 100644
--- a/test/UserConfigTest.js
+++ b/test/UserConfigTest.js
@@ -4,29 +4,29 @@ import UserConfig from "../src/UserConfig.js";
 test("Template Formats", (t) => {
   let userCfg = new UserConfig();
 
-  t.falsy(userCfg.getMergingConfigObject().templateFormats);
+  t.falsy(userCfg.templateFormats);
 
   userCfg.setTemplateFormats("njk,liquid");
-  t.deepEqual(userCfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]);
+  t.deepEqual(userCfg.templateFormats, "njk,liquid");
 
   // setting multiple times takes the last one
   userCfg.setTemplateFormats("njk,liquid,pug");
   userCfg.setTemplateFormats("njk,liquid");
-  t.deepEqual(userCfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]);
+  t.deepEqual(userCfg.templateFormats, "njk,liquid");
 });
 
 test("Template Formats (Arrays)", (t) => {
   let userCfg = new UserConfig();
 
-  t.falsy(userCfg.getMergingConfigObject().templateFormats);
+  t.falsy(userCfg.templateFormats);
 
   userCfg.setTemplateFormats(["njk", "liquid"]);
-  t.deepEqual(userCfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]);
+  t.deepEqual(userCfg.templateFormats, ["njk", "liquid"]);
 
   // setting multiple times takes the last one
   userCfg.setTemplateFormats(["njk", "liquid", "pug"]);
   userCfg.setTemplateFormats(["njk", "liquid"]);
-  t.deepEqual(userCfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]);
+  t.deepEqual(userCfg.templateFormats, ["njk", "liquid"]);
 });
 
 // more in TemplateConfigTest.js
@@ -144,7 +144,7 @@ test("Set manual Pass-through File Copy (glob patterns)", (t) => {
 test("Set Template Formats (string)", (t) => {
   let userCfg = new UserConfig();
   userCfg.setTemplateFormats("njk, liquid");
-  t.deepEqual(userCfg.templateFormats, ["njk", "liquid"]);
+  t.deepEqual(userCfg.templateFormats, "njk, liquid");
 });
 
 test("Set Template Formats (array)", (t) => {
@@ -156,13 +156,13 @@ test("Set Template Formats (array)", (t) => {
 test("Set Template Formats (js passthrough copy)", (t) => {
   let userCfg = new UserConfig();
   userCfg.setTemplateFormats("njk, liquid, js");
-  t.deepEqual(userCfg.templateFormats, ["njk", "liquid", "js"]);
+  t.deepEqual(userCfg.templateFormats, "njk, liquid, js");
 });
 
 test("Set Template Formats (11ty.js)", (t) => {
   let userCfg = new UserConfig();
   userCfg.setTemplateFormats("njk, liquid, 11ty.js");
-  t.deepEqual(userCfg.templateFormats, ["njk", "liquid", "11ty.js"]);
+  t.deepEqual(userCfg.templateFormats, "njk, liquid, 11ty.js");
 });
 
 test("Add Template Formats", (t) => {
diff --git a/test/_getNewTemplateForTests.js b/test/_getNewTemplateForTests.js
index c7abaecc..e9820354 100644
--- a/test/_getNewTemplateForTests.js
+++ b/test/_getNewTemplateForTests.js
@@ -22,7 +22,8 @@ export default async function getNewTemplate(
   }
 
   if (!map) {
-    map = new EleventyExtensionMap(["liquid", "md", "njk", "html", "11ty.js"], eleventyConfig);
+    map = new EleventyExtensionMap(eleventyConfig);
+    map.setFormats(["liquid", "md", "njk", "html", "11ty.js"])
   }
   if (templateData) {
     templateData.setFileSystemSearch(new FileSystemSearch());