Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving/resetting config file should apply new config values everywhere (including layouts) #2867

Merged
merged 4 commits into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 38 additions & 16 deletions src/Eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const ConsoleLogger = require("./Util/ConsoleLogger");
const PathPrefixer = require("./Util/PathPrefixer");
const TemplateConfig = require("./TemplateConfig");
const FileSystemSearch = require("./FileSystemSearch");

const PathNormalizer = require("./Util/PathNormalizer.js");
const simplePlural = require("./Util/Pluralize");
const checkPassthroughCopyBehavior = require("./Util/PassthroughCopyBehaviorCheck");
const debug = require("debug")("Eleventy");
Expand Down Expand Up @@ -55,6 +55,12 @@ class Eleventy {
this.eleventyConfig.setPathPrefix(this.pathPrefix);
}

/**
* @member {Object} - Options object passed to the Eleventy constructor
* @default {}
*/
this.options = options;

/* Programmatic API config */
if (options.config && typeof options.config === "function") {
// TODO use return object here?
Expand Down Expand Up @@ -728,7 +734,7 @@ Arguments:
* @method
* @param {String} changedFilePath - File that triggered a re-run (added or modified)
*/
async _addFileToWatchQueue(changedFilePath) {
async _addFileToWatchQueue(changedFilePath, isResetConfig) {
// Currently this is only for 11ty.js deps but should be extended with usesGraph
let usedByDependants = [];
if (this.watchTargets) {
Expand All @@ -738,24 +744,27 @@ Arguments:
}

// Note: this is a sync event!
eventBus.emit("eleventy.resourceModified", changedFilePath, usedByDependants);
eventBus.emit("eleventy.resourceModified", changedFilePath, usedByDependants, {
viaConfigReset: isResetConfig,
});

this.watchManager.addToPendingQueue(changedFilePath);
}

_shouldResetConfig() {
let configFilePaths = this.eleventyConfig.getLocalProjectConfigFiles();
let configFilesChanged = this.watchManager.hasQueuedFiles(configFilePaths);

if (configFilesChanged) {
return true;
shouldTriggerConfigReset(changedFiles) {
let configFilePaths = new Set(this.eleventyConfig.getLocalProjectConfigFiles());
for (let filePath of changedFiles) {
if (configFilePaths.has(filePath)) {
return true;
}
}

for (const configFilePath of configFilePaths) {
// Any dependencies of the config file changed
let configFileDependencies = this.watchTargets.getDependenciesOf(configFilePath);
let configFileDependencies = new Set(this.watchTargets.getDependenciesOf(configFilePath));

for (let dep of configFileDependencies) {
if (this.watchManager.hasQueuedFile(dep)) {
for (let filePath of changedFiles) {
if (configFileDependencies.has(filePath)) {
return true;
}
}
Expand All @@ -764,13 +773,26 @@ Arguments:
return false;
}

// Checks the build queue to see if any configuration related files have changed
_shouldResetConfig(activeQueue = []) {
if (!activeQueue.length) {
return false;
}

return this.shouldTriggerConfigReset(
activeQueue.map((path) => {
return PathNormalizer.normalizeSeperator(TemplatePath.addLeadingDotSlash(path));
})
);
}

/**
* tbd.
*
* @private
* @method
*/
async _watch() {
async _watch(isResetConfig = false) {
if (this.watchManager.isBuildRunning()) {
return;
}
Expand All @@ -785,7 +807,6 @@ Arguments:
this.watchTargets.clearRequireCacheFor(queue);

// reset and reload global configuration
let isResetConfig = this._shouldResetConfig();
if (isResetConfig) {
this.resetConfig();
}
Expand Down Expand Up @@ -1019,12 +1040,13 @@ Arguments:
let watchRun = async (path) => {
path = TemplatePath.normalize(path);
try {
this._addFileToWatchQueue(path);
let isResetConfig = this._shouldResetConfig([path]);
this._addFileToWatchQueue(path, isResetConfig);
clearTimeout(watchDelay);

await new Promise((resolve, reject) => {
watchDelay = setTimeout(async () => {
this._watch().then(resolve, reject);
this._watch(isResetConfig).then(resolve, reject);
}, this.config.watchThrottleWaitTime);
});
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion src/EleventyExtensionMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class EleventyExtensionMap {

get engineManager() {
if (!this._engineManager) {
this._engineManager = new TemplateEngineManager(this.config);
this._engineManager = new TemplateEngineManager(this.eleventyConfig);
}

return this._engineManager;
Expand Down
20 changes: 8 additions & 12 deletions src/Engines/TemplateEngine.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const debug = require("debug")("Eleventy:TemplateEngine");
class TemplateEngineConfigError extends EleventyBaseError {}

class TemplateEngine {
constructor(name, dirs, config) {
constructor(name, dirs, eleventyConfig) {
this.name = name;

if (!dirs) {
Expand All @@ -25,21 +25,17 @@ class TemplateEngine {
this.engineLib = null;
this.cacheable = false;

if (!config) {
throw new TemplateEngineConfigError("Missing `config` argument.");
if (!eleventyConfig) {
throw new TemplateEngineConfigError("Missing `eleventyConfig` argument.");
}
this._config = config;
}

set config(cfg) {
this._config = cfg;
this.eleventyConfig = eleventyConfig;
}

get config() {
if (this._config instanceof TemplateConfig) {
return this._config.getConfig();
if (this.eleventyConfig instanceof TemplateConfig) {
return this.eleventyConfig.getConfig();
}
return this._config;
throw new Error("Expecting a TemplateConfig instance.");
}

get benchmarks() {
Expand All @@ -61,7 +57,7 @@ class TemplateEngine {

get extensionMap() {
if (!this._extensionMap) {
this._extensionMap = new EleventyExtensionMap([], this.config);
this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
}
return this._extensionMap;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Template.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class Template extends TemplateContent {
return TemplateLayout.getTemplate(
layoutKey,
this.getInputDir(),
this.config,
this.eleventyConfig,
this.extensionMap
);
}
Expand Down
26 changes: 18 additions & 8 deletions src/TemplateCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ class TemplateCache {
this.cacheByInputPath = {};
}

// alias
removeAll() {
this.clear();
}

size() {
return Object.keys(this.cacheByInputPath).length;
}
Expand Down Expand Up @@ -60,29 +65,34 @@ class TemplateCache {
return this.cache[key];
}

remove(filePath) {
filePath = TemplatePath.stripLeadingDotSlash(filePath);

if (!this.cacheByInputPath[filePath]) {
remove(layoutFilePath) {
layoutFilePath = TemplatePath.stripLeadingDotSlash(layoutFilePath);
if (!this.cacheByInputPath[layoutFilePath]) {
// not a layout file
return;
}

let layoutTemplate = this.cacheByInputPath[filePath];
let layoutTemplate = this.cacheByInputPath[layoutFilePath];
layoutTemplate.resetCaches();

let keys = layoutTemplate.getCacheKeys();
for (let key of keys) {
delete this.cache[key];
}

delete this.cacheByInputPath[filePath];
delete this.cacheByInputPath[layoutFilePath];
}
}

let layoutCache = new TemplateCache();

eventBus.on("eleventy.resourceModified", (path) => {
layoutCache.remove(path);
eventBus.on("eleventy.resourceModified", (path, usedBy, metadata = {}) => {
// https://github.com/11ty/eleventy-plugin-bundle/issues/10
if (metadata.viaConfigReset) {
layoutCache.removeAll();
} else {
layoutCache.remove(path);
}
});

// singleton
Expand Down
33 changes: 20 additions & 13 deletions src/TemplateContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class TemplateContent {
if (!config) {
throw new TemplateContentConfigError("Missing `config` argument to TemplateContent");
}
this.config = config;
this.eleventyConfig = config;

this.inputPath = inputPath;

Expand Down Expand Up @@ -72,7 +72,7 @@ class TemplateContent {
/* Used by tests */
get extensionMap() {
if (!this._extensionMap) {
this._extensionMap = new EleventyExtensionMap([], this.config);
this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
}
return this._extensionMap;
}
Expand All @@ -81,26 +81,33 @@ class TemplateContent {
this._extensionMap = map;
}

set config(config) {
set eleventyConfig(config) {
this._config = config;
}

get config() {
if (this._config instanceof TemplateConfig) {
return this._config.getConfig();
this._configOptions = this._config.getConfig();
} else {
throw new TemplateContentConfigError("Tried to get an TemplateConfig but none was found.");
}
return this._config;
}

get bench() {
return this.config.benchmarkManager.get("Aggregate");
}

get eleventyConfig() {
if (this._config instanceof TemplateConfig) {
return this._config;
}
throw new TemplateContentConfigError("Tried to get an eleventyConfig but none was found.");
throw new TemplateContentConfigError("Tried to get an TemplateConfig but none was found.");
}

get config() {
if (this._config instanceof TemplateConfig && !this._configOptions) {
this._configOptions = this._config.getConfig();
}

return this._configOptions;
}

get bench() {
return this.config.benchmarkManager.get("Aggregate");
}

get engine() {
Expand All @@ -109,7 +116,7 @@ class TemplateContent {

get templateRender() {
if (!this._templateRender) {
this._templateRender = new TemplateRender(this.inputPath, this.inputDir, this.config);
this._templateRender = new TemplateRender(this.inputPath, this.inputDir, this.eleventyConfig);
this._templateRender.extensionMap = this.extensionMap;
}

Expand Down
2 changes: 1 addition & 1 deletion src/TemplateData.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class TemplateData {

get extensionMap() {
if (!this._extensionMap) {
this._extensionMap = new EleventyExtensionMap([], this.config);
this._extensionMap = new EleventyExtensionMap([], this.eleventyConfig);
}
return this._extensionMap;
}
Expand Down
20 changes: 11 additions & 9 deletions src/TemplateEngineManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ const EleventyBaseError = require("./EleventyBaseError");
class TemplateEngineManagerConfigError extends EleventyBaseError {}

class TemplateEngineManager {
constructor(config) {
if (!config) {
constructor(eleventyConfig) {
if (!eleventyConfig) {
throw new TemplateEngineManagerConfigError("Missing `config` argument.");
}
this.config = config;
this.eleventyConfig = eleventyConfig;

this.engineCache = {};
}

get config() {
return this.eleventyConfig.getConfig();
}

static isCustomEngineSimpleAlias(entry) {
let keys = Object.keys(entry);
if (keys.length > 2) {
Expand Down Expand Up @@ -74,7 +78,7 @@ class TemplateEngineManager {
}

getEngineClassByExtension(extension) {
// We include these as raw strings (and not more readable variables) so they’re parsed by the bundler.
// We include these as raw strings (and not more readable variables) so they’re parsed by the serverless bundler.
if (extension === "ejs") {
return require("./Engines/Ejs");
} else if (extension === "md") {
Expand Down Expand Up @@ -102,9 +106,7 @@ class TemplateEngineManager {

getEngine(name, dirs, extensionMap) {
if (!this.hasEngine(name)) {
throw new Error(
`Template Engine ${name} does not exist in getEngine (dirs: ${dirs})`
);
throw new Error(`Template Engine ${name} does not exist in getEngine (dirs: ${dirs})`);
}

// TODO these cached engines should be based on extensions not name, then we can remove the error in
Expand All @@ -115,7 +117,7 @@ class TemplateEngineManager {

let cls = this.getEngineClassByExtension(name);

let instance = new cls(name, dirs, this.config);
let instance = new cls(name, dirs, this.eleventyConfig);
instance.extensionMap = extensionMap;
instance.engineManager = this;

Expand All @@ -128,7 +130,7 @@ class TemplateEngineManager {
instance.constructor.name !== "CustomEngine"
) {
const CustomEngine = this.getEngineClassByExtension();
const overrideCustomEngine = new CustomEngine(name, dirs, this.config);
const overrideCustomEngine = new CustomEngine(name, dirs, this.eleventyConfig);
// Keep track of the "default" engine 11ty would normally use
// This allows the user to access the default engine in their override
overrideCustomEngine.setDefaultEngine(instance);
Expand Down