From 01665c2c2f2d23f8c3ec3c1785ae4d67b70ff7df Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 3 Jul 2019 08:09:10 -0500 Subject: [PATCH 001/746] Convert to class --- src/TemplateWriter.js | 338 +++++++++++++++++++++--------------------- 1 file changed, 169 insertions(+), 169 deletions(-) diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index f5eb75c89..f12357495 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -13,203 +13,203 @@ const debugDev = require("debug")("Dev:Eleventy:TemplateWriter"); class TemplateWriterWriteError extends EleventyBaseError {} -function TemplateWriter( - inputPath, - outputDir, - templateFormats, // TODO remove this, see `.getFileManager()` first - templateData, - isPassthroughAll -) { - this.config = config.getConfig(); - this.input = inputPath; - this.inputDir = TemplatePath.getDir(inputPath); - this.outputDir = outputDir; - this.templateFormats = templateFormats; - this.templateData = templateData; - this.isVerbose = true; - this.isDryRun = false; - this.writeCount = 0; - - // TODO can we get rid of this? It’s only used for tests in getFileManager() - this.passthroughAll = isPassthroughAll; -} +class TemplateWriter { + constructor( + inputPath, + outputDir, + templateFormats, // TODO remove this, see `.getFileManager()` first + templateData, + isPassthroughAll + ) { + this.config = config.getConfig(); + this.input = inputPath; + this.inputDir = TemplatePath.getDir(inputPath); + this.outputDir = outputDir; + this.templateFormats = templateFormats; + this.templateData = templateData; + this.isVerbose = true; + this.isDryRun = false; + this.writeCount = 0; + + // TODO can we get rid of this? It’s only used for tests in getFileManager() + this.passthroughAll = isPassthroughAll; + } -/* For testing */ -TemplateWriter.prototype.overrideConfig = function(config) { - this.config = config; -}; - -TemplateWriter.prototype.restart = function() { - this.writeCount = 0; - debugDev("Resetting counts to 0"); -}; - -TemplateWriter.prototype.setEleventyFiles = function(eleventyFiles) { - this.eleventyFiles = eleventyFiles; -}; - -TemplateWriter.prototype.getFileManager = function() { - // usually Eleventy.js will setEleventyFiles with the EleventyFiles manager - if (!this.eleventyFiles) { - // if not, we can create one (used only by tests) - this.eleventyFiles = new EleventyFiles( - this.input, - this.outputDir, - this.templateFormats, - this.passthroughAll - ); - this.eleventyFiles.init(); + /* For testing */ + overrideConfig(config) { + this.config = config; } - return this.eleventyFiles; -}; - -TemplateWriter.prototype._getAllPaths = async function() { - return await this.getFileManager().getFiles(); -}; - -TemplateWriter.prototype._createTemplate = function(path) { - let tmpl = new Template( - path, - this.inputDir, - this.outputDir, - this.templateData - ); - - tmpl.setIsVerbose(this.isVerbose); - tmpl.setDryRun(this.isDryRun); - - /* - * Sample filter: arg str, return pretty HTML string - * function(str) { - * return pretty(str, { ocd: true }); - * } - */ - for (let transformName in this.config.filters) { - let transform = this.config.filters[transformName]; - if (typeof transform === "function") { - tmpl.addTransform(transform); - } + restart() { + this.writeCount = 0; + debugDev("Resetting counts to 0"); + } + + setEleventyFiles(eleventyFiles) { + this.eleventyFiles = eleventyFiles; } - for (let linterName in this.config.linters) { - let linter = this.config.linters[linterName]; - if (typeof linter === "function") { - tmpl.addLinter(linter); + getFileManager() { + // usually Eleventy.js will setEleventyFiles with the EleventyFiles manager + if (!this.eleventyFiles) { + // if not, we can create one (used only by tests) + this.eleventyFiles = new EleventyFiles( + this.input, + this.outputDir, + this.templateFormats, + this.passthroughAll + ); + this.eleventyFiles.init(); } + + return this.eleventyFiles; } - return tmpl; -}; + async _getAllPaths() { + return await this.getFileManager().getFiles(); + } -TemplateWriter.prototype._addToTemplateMap = async function(paths) { - let promises = []; - for (let path of paths) { - if (TemplateRender.hasEngine(path)) { - promises.push( - this.templateMap.add(this._createTemplate(path)).then(() => { - debug(`${path} added to map.`); - }) - ); + _createTemplate(path) { + let tmpl = new Template( + path, + this.inputDir, + this.outputDir, + this.templateData + ); + + tmpl.setIsVerbose(this.isVerbose); + tmpl.setDryRun(this.isDryRun); + + /* + * Sample filter: arg str, return pretty HTML string + * function(str) { + * return pretty(str, { ocd: true }); + * } + */ + for (let transformName in this.config.filters) { + let transform = this.config.filters[transformName]; + if (typeof transform === "function") { + tmpl.addTransform(transform); + } + } + + for (let linterName in this.config.linters) { + let linter = this.config.linters[linterName]; + if (typeof linter === "function") { + tmpl.addLinter(linter); + } } + + return tmpl; } - return Promise.all(promises); -}; + async _addToTemplateMap(paths) { + let promises = []; + for (let path of paths) { + if (TemplateRender.hasEngine(path)) { + promises.push( + this.templateMap.add(this._createTemplate(path)).then(() => { + debug(`${path} added to map.`); + }) + ); + } + } -TemplateWriter.prototype._createTemplateMap = async function(paths) { - this.templateMap = new TemplateMap(); + return Promise.all(promises); + } + + async _createTemplateMap(paths) { + this.templateMap = new TemplateMap(); - await this._addToTemplateMap(paths); - await this.templateMap.cache(); + await this._addToTemplateMap(paths); + await this.templateMap.cache(); - debugDev("TemplateMap cache complete."); - return this.templateMap; -}; + debugDev("TemplateMap cache complete."); + return this.templateMap; + } -TemplateWriter.prototype._writeTemplate = async function(mapEntry) { - let tmpl = mapEntry.template; - // we don’t re-use the map templateContent because it doesn’t include layouts - return tmpl.writeMapEntry(mapEntry).then(() => { - this.writeCount += tmpl.getWriteCount(); - }); -}; + async _writeTemplate(mapEntry) { + let tmpl = mapEntry.template; + // we don’t re-use the map templateContent because it doesn’t include layouts + return tmpl.writeMapEntry(mapEntry).then(() => { + this.writeCount += tmpl.getWriteCount(); + }); + } -TemplateWriter.prototype.write = async function() { - let promises = []; - let paths = await this._getAllPaths(); - debug("Found: %o", paths); + async write() { + let promises = []; + let paths = await this._getAllPaths(); + debug("Found: %o", paths); - promises.push( - this.getFileManager() - .getPassthroughManager() - .copyAll(paths) - .catch(e => { - EleventyErrorHandler.warn(e, "Error with passthrough copy"); - }) - ); - - // TODO optimize await here - await this._createTemplateMap(paths); - debug("Template map created."); - - let mapEntry; - let usedTemplateContentTooEarlyMap = []; - for (mapEntry of this.templateMap.getMap()) { promises.push( - this._writeTemplate(mapEntry).catch(function(e) { - // Premature templateContent in layout render, this also happens in - // TemplateMap.populateContentDataInMap for non-layout content - if (EleventyErrorUtil.isPrematureTemplateContentError(e)) { - usedTemplateContentTooEarlyMap.push(mapEntry); - } else { + this.getFileManager() + .getPassthroughManager() + .copyAll(paths) + .catch(e => { + EleventyErrorHandler.warn(e, "Error with passthrough copy"); + }) + ); + + // TODO optimize await here + await this._createTemplateMap(paths); + debug("Template map created."); + + let mapEntry; + let usedTemplateContentTooEarlyMap = []; + for (mapEntry of this.templateMap.getMap()) { + promises.push( + this._writeTemplate(mapEntry).catch(function(e) { + // Premature templateContent in layout render, this also happens in + // TemplateMap.populateContentDataInMap for non-layout content + if (EleventyErrorUtil.isPrematureTemplateContentError(e)) { + usedTemplateContentTooEarlyMap.push(mapEntry); + } else { + throw new TemplateWriterWriteError( + `Having trouble writing template: ${mapEntry.outputPath}`, + e + ); + } + }) + ); + } + + for (mapEntry of usedTemplateContentTooEarlyMap) { + promises.push( + this._writeTemplate(mapEntry).catch(function(e) { throw new TemplateWriterWriteError( - `Having trouble writing template: ${mapEntry.outputPath}`, + `Having trouble writing template (second pass): ${mapEntry.outputPath}`, e ); - } - }) - ); - } + }) + ); + } - for (mapEntry of usedTemplateContentTooEarlyMap) { - promises.push( - this._writeTemplate(mapEntry).catch(function(e) { - throw new TemplateWriterWriteError( - `Having trouble writing template (second pass): ${ - mapEntry.outputPath - }`, - e - ); - }) - ); + return Promise.all(promises).catch(e => { + EleventyErrorHandler.error(e, "Error writing templates"); + }); } - return Promise.all(promises).catch(e => { - EleventyErrorHandler.error(e, "Error writing templates"); - }); -}; - -TemplateWriter.prototype.setVerboseOutput = function(isVerbose) { - this.isVerbose = isVerbose; -}; + setVerboseOutput(isVerbose) { + this.isVerbose = isVerbose; + } -TemplateWriter.prototype.setDryRun = function(isDryRun) { - this.isDryRun = !!isDryRun; + setDryRun(isDryRun) { + this.isDryRun = !!isDryRun; - this.getFileManager() - .getPassthroughManager() - .setDryRun(this.isDryRun); -}; + this.getFileManager() + .getPassthroughManager() + .setDryRun(this.isDryRun); + } -TemplateWriter.prototype.getCopyCount = function() { - return this.getFileManager() - .getPassthroughManager() - .getCopyCount(); -}; + getCopyCount() { + return this.getFileManager() + .getPassthroughManager() + .getCopyCount(); + } -TemplateWriter.prototype.getWriteCount = function() { - return this.writeCount; -}; + getWriteCount() { + return this.writeCount; + } +} module.exports = TemplateWriter; From 831df5f9a76d0c3d7b0034ab0ee7223494cd5fe3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 4 Jul 2019 21:01:31 -0500 Subject: [PATCH 002/746] Removes a bunch of static usage to get ready for #117 --- src/Eleventy.js | 6 ++ src/EleventyExtensionMap.js | 57 +++++---------- src/EleventyFiles.js | 33 +++++---- src/Template.js | 13 +--- src/TemplateContent.js | 12 +++- src/TemplateData.js | 29 +++++--- src/TemplatePassthroughManager.js | 16 ++++- src/TemplateRender.js | 31 ++++---- src/TemplateWriter.js | 18 ++++- src/UserConfig.js | 6 -- test/EleventyExtensionMapTest.js | 114 +++++++++++++++--------------- test/EleventyFilesTest.js | 30 ++------ test/TemplateRenderTest.js | 18 +---- test/TemplateWriterTest.js | 92 ------------------------ 14 files changed, 182 insertions(+), 293 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index ad3e92a78..0ae23b422 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -1,6 +1,7 @@ const TemplatePath = require("./TemplatePath"); const TemplateData = require("./TemplateData"); const TemplateWriter = require("./TemplateWriter"); +const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyErrorHandler = require("./EleventyErrorHandler"); const EleventyServe = require("./EleventyServe"); const EleventyWatchTargets = require("./EleventyWatchTargets"); @@ -140,15 +141,19 @@ class Eleventy { async init() { let formats = this.formatsOverride || this.config.templateFormats; + this.extensionMap = new EleventyExtensionMap(formats); + this.eleventyFiles = new EleventyFiles( this.input, this.outputDir, formats, this.isPassthroughAll ); + this.eleventyFiles.extensionMap = this.extensionMap; this.eleventyFiles.init(); this.templateData = new TemplateData(this.inputDir); + this.templateData.extensionMap = this.extensionMap; this.eleventyFiles.setTemplateData(this.templateData); this.writer = new TemplateWriter( @@ -159,6 +164,7 @@ class Eleventy { this.isPassthroughAll ); + this.writer.extensionMap = this.extensionMap; this.writer.setEleventyFiles(this.eleventyFiles); // TODO maybe isVerbose -> console.log? diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 5b2940c81..4af4ad953 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -2,7 +2,11 @@ const TemplatePath = require("./TemplatePath"); const config = require("./Config"); class EleventyExtensionMap { - constructor(formatKeys = []) { + constructor(formatKeys) { + this.setFormats(formatKeys); + } + + setFormats(formatKeys = []) { this.unfilteredFormatKeys = formatKeys.map(function(key) { return key.trim().toLowerCase(); }); @@ -71,8 +75,8 @@ class EleventyExtensionMap { } hasExtension(key) { - for (var extension in EleventyExtensionMap.keyMap) { - if (EleventyExtensionMap.keyMap[extension] === key) { + for (var extension in this.keyMap) { + if (this.keyMap[extension] === key) { return true; } } @@ -89,17 +93,15 @@ class EleventyExtensionMap { return extensions; } - getKey(pathOrKey) { - return EleventyExtensionMap._getKey(pathOrKey, this.keyMap); - } - static getKey(pathOrKey) { - return EleventyExtensionMap._getKey(pathOrKey, EleventyExtensionMap.keyMap); + hasEngine(pathOrKey) { + return !!this.getKey(pathOrKey); } - static _getKey(pathOrKey, map) { - pathOrKey = pathOrKey.toLowerCase(); - for (var extension in map) { - let key = map[extension]; + getKey(pathOrKey) { + pathOrKey = (pathOrKey || "").toLowerCase(); + + for (var extension in this.keyMap) { + let key = this.keyMap[extension]; if (pathOrKey === extension) { return key; } else if (pathOrKey.endsWith("." + extension)) { @@ -109,16 +111,7 @@ class EleventyExtensionMap { } removeTemplateExtension(path) { - return EleventyExtensionMap._removeTemplateExtension(path, this.keyMap); - } - static removeTemplateExtension(path) { - return EleventyExtensionMap._removeTemplateExtension( - path, - EleventyExtensionMap.keyMap - ); - } - static _removeTemplateExtension(path, map) { - for (var extension in map) { + for (var extension in this.keyMap) { if (path === extension || path.endsWith("." + extension)) { return path.substr(0, path.length - 1 - extension.length); } @@ -127,19 +120,7 @@ class EleventyExtensionMap { } get keyMap() { - return EleventyExtensionMap._getKeyMap( - this.config.templateExtensionAliases || {} - ); - } - static get keyMap() { - return EleventyExtensionMap._getKeyMap( - config.getConfig().templateExtensionAliases || {} - ); - } - - // file extension => key - static _getKeyMap(aliases) { - let fileExtensionToKeyMap = { + return { ejs: "ejs", md: "md", jstl: "jstl", @@ -152,12 +133,6 @@ class EleventyExtensionMap { liquid: "liquid", "11ty.js": "11ty.js" }; - - for (let extension in aliases) { - fileExtensionToKeyMap[extension] = aliases[extension]; - } - - return fileExtensionToKeyMap; } } diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index cd09eca7b..54999e61d 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -23,7 +23,6 @@ class EleventyFiles { this.passthroughAll = !!passthroughAll; this.formats = formats; - this.extensionMap = new EleventyExtensionMap(formats); } initConfig() { @@ -42,7 +41,7 @@ class EleventyFiles { init() { this.initFormatsGlobs(); - this.setPassthroughManager(); + this.initPassthroughManager(); this.setupGlobs(); } @@ -56,15 +55,22 @@ class EleventyFiles { this.config = config; this.initConfig(); } - /* For testing */ - _setExtensionMap(map) { - this.extensionMap = map; - } /* Set command root for local project paths */ _setLocalPathRoot(dir) { this.localPathRoot = dir; } + set extensionMap(extensionMap) { + this._extensionMap = extensionMap; + } + + get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap(this.formats); + } + return this._extensionMap; + } + setPassthroughAll(passthroughAll) { this.passthroughAll = !!passthroughAll; } @@ -80,17 +86,20 @@ class EleventyFiles { } } + initPassthroughManager() { + let mgr = new TemplatePassthroughManager(); + mgr.setInputDir(this.inputDir); + mgr.setOutputDir(this.outputDir); + mgr.extensionMap = this.extensionMap; + this.passthroughManager = mgr; + } + getPassthroughManager() { return this.passthroughManager; } setPassthroughManager(mgr) { - if (!mgr) { - mgr = new TemplatePassthroughManager(); - mgr.setInputDir(this.inputDir); - mgr.setOutputDir(this.outputDir); - } - + mgr.extensionMap = this.extensionMap; this.passthroughManager = mgr; } diff --git a/src/Template.js b/src/Template.js index a50400196..6e49c4927 100644 --- a/src/Template.js +++ b/src/Template.js @@ -4,7 +4,6 @@ const normalize = require("normalize-path"); const lodashIsObject = require("lodash/isObject"); const { DateTime } = require("luxon"); -const EleventyExtensionMap = require("./EleventyExtensionMap"); const TemplateData = require("./TemplateData"); const TemplateContent = require("./TemplateContent"); const TemplatePath = require("./TemplatePath"); @@ -71,9 +70,7 @@ class Template extends TemplateContent { } get baseFile() { - return (this._extensionMap || EleventyExtensionMap).removeTemplateExtension( - this.parsed.base - ); + return this.extensionMap.removeTemplateExtension(this.parsed.base); } get htmlIOException() { @@ -450,9 +447,7 @@ class Template extends TemplateContent { get templateContent() { if (!this._templateContent) { throw new TemplateContentPrematureUseError( - `Tried to use templateContent too early (${ - this.inputPath - } page ${this.pageNumber})` + `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` ); } return this._templateContent; @@ -609,9 +604,7 @@ class Template extends TemplateContent { let date = DateTime.fromISO(data.date, { zone: "utc" }); if (!date.isValid) { throw new Error( - `date front matter value (${data.date}) is invalid for ${ - this.inputPath - }` + `date front matter value (${data.date}) is invalid for ${this.inputPath}` ); } debug( diff --git a/src/TemplateContent.js b/src/TemplateContent.js index d44665b0b..9dc96f87e 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -3,6 +3,7 @@ const normalize = require("normalize-path"); const matter = require("gray-matter"); const lodashSet = require("lodash/set"); +const EleventyExtensionMap = require("./EleventyExtensionMap"); const TemplateData = require("./TemplateData"); const TemplateRender = require("./TemplateRender"); const EleventyBaseError = require("./EleventyBaseError"); @@ -26,7 +27,14 @@ class TemplateContent { } /* Used by tests */ - _setExtensionMap(map) { + get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap(); + } + return this._extensionMap; + } + + set extensionMap(map) { this._extensionMap = map; } @@ -51,7 +59,7 @@ class TemplateContent { this._templateRender = new TemplateRender( this.inputPath, this.inputDir, - this._extensionMap + this.extensionMap ); } diff --git a/src/TemplateData.js b/src/TemplateData.js index a3df667ef..69d013070 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -29,6 +29,18 @@ class TemplateData { this.globalData = null; } + // for tests + get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap(); + } + return this._extensionMap; + } + + set extensionMap(map) { + this._extensionMap = map; + } + /* Used by tests */ _setConfig(config) { this.config = config; @@ -161,11 +173,7 @@ class TemplateData { // TODO maybe merge these two? (if both valid objects) if (dataFileConflicts[folders]) { debugWarn( - `Warning: the key for a global data file (${ - files[j] - }) will overwrite data from an already existing global data file (${ - dataFileConflicts[folders] - })` + `Warning: the key for a global data file (${files[j]}) will overwrite data from an already existing global data file (${dataFileConflicts[folders]})` ); } dataFileConflicts[folders] = files[j]; @@ -290,7 +298,7 @@ class TemplateData { debugDev("parsed.dir: %o", parsed.dir); if (parsed.dir) { - let fileNameNoExt = EleventyExtensionMap.removeTemplateExtension( + let fileNameNoExt = this.extensionMap.removeTemplateExtension( parsed.base ); let filePathNoExt = parsed.dir + "/" + fileNameNoExt; @@ -338,12 +346,11 @@ class TemplateData { } static cleanupData(data) { - if ("tags" in data){ - if (typeof data.tags === "string"){ + if ("tags" in data) { + if (typeof data.tags === "string") { data.tags = data.tags ? [data.tags] : []; - } - else if (data.tags === null){ - data.tags = [] + } else if (data.tags === null) { + data.tags = []; } } diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index bd053dbc7..09a39e95a 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -1,13 +1,14 @@ const config = require("./Config"); +const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); const TemplatePassthrough = require("./TemplatePassthrough"); -const TemplateRender = require("./TemplateRender"); const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthroughManager"); class TemplatePassthroughManagerCopyError extends EleventyBaseError {} class TemplatePassthroughManager { + // TODO bunch of unused args here constructor(inputDir, outputDir, isDryRun) { this.config = config.getConfig(); @@ -23,6 +24,17 @@ class TemplatePassthroughManager { this.config = configOverride || {}; } + set extensionMap(extensionMap) { + this._extensionMap = extensionMap; + } + + get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap(); + } + return this._extensionMap; + } + setOutputDir(outputDir) { this.outputDir = outputDir; } @@ -65,7 +77,7 @@ class TemplatePassthroughManager { let matches = []; for (let path of paths) { - if (!TemplateRender.hasEngine(path)) { + if (!this.extensionMap.hasEngine(path)) { matches.push(path); } } diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 0c1b4436b..7f5035524 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -45,8 +45,19 @@ class TemplateRender { } } + set extensionMap(extensionMap) { + this._extensionMap = extensionMap; + } + + get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap(); + } + return this._extensionMap; + } + init(engineNameOrPath) { - this.engineName = this.cleanupEngineName(engineNameOrPath); + this.engineName = this.extensionMap.getKey(engineNameOrPath); if (!this.engineName) { throw new TemplateRenderUnknownEngineError( `Unknown engine for ${engineNameOrPath}` @@ -56,24 +67,6 @@ class TemplateRender { this.engine.initRequireCache(this.path); } - cleanupEngineName(tmplPath) { - return TemplateRender._cleanupEngineName( - tmplPath, - this.extensionMap || EleventyExtensionMap - ); - } - static cleanupEngineName(tmplPath) { - return TemplateRender._cleanupEngineName(tmplPath, EleventyExtensionMap); - } - static _cleanupEngineName(tmplPath, extensionMapRef) { - return extensionMapRef.getKey(tmplPath); - } - - static hasEngine(tmplPath) { - let name = TemplateRender.cleanupEngineName(tmplPath); - return TemplateEngine.hasEngine(name); - } - static parseEngineOverrides(engineName) { let overlappingEngineWarningCount = 0; let engines = []; diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index f12357495..01a3a34c1 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -3,6 +3,7 @@ const TemplatePath = require("./TemplatePath"); const TemplateMap = require("./TemplateMap"); const TemplateRender = require("./TemplateRender"); const EleventyFiles = require("./EleventyFiles"); +const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyErrorHandler = require("./EleventyErrorHandler"); const EleventyErrorUtil = require("./EleventyErrorUtil"); @@ -49,6 +50,19 @@ class TemplateWriter { this.eleventyFiles = eleventyFiles; } + set extensionMap(extensionMap) { + this._extensionMap = extensionMap; + } + + get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap( + this.config.templateFormats + ); + } + return this._extensionMap; + } + getFileManager() { // usually Eleventy.js will setEleventyFiles with the EleventyFiles manager if (!this.eleventyFiles) { @@ -77,6 +91,8 @@ class TemplateWriter { this.templateData ); + tmpl.extensionMap = this.extensionMap; + tmpl.setIsVerbose(this.isVerbose); tmpl.setDryRun(this.isDryRun); @@ -106,7 +122,7 @@ class TemplateWriter { async _addToTemplateMap(paths) { let promises = []; for (let path of paths) { - if (TemplateRender.hasEngine(path)) { + if (this.extensionMap.hasEngine(path)) { promises.push( this.templateMap.add(this._createTemplate(path)).then(() => { debug(`${path} added to map.`); diff --git a/src/UserConfig.js b/src/UserConfig.js index 679d5da06..9aa08ed90 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -51,7 +51,6 @@ class UserConfig { this.dataDeepMerge = false; this.experiments = new Set(); // this.userExtensionMap = {}; - // this.templateExtensionAliases = {}; this.watchJavaScriptDependencies = true; this.browserSyncConfig = {}; } @@ -481,10 +480,6 @@ class UserConfig { this.dataDeepMerge = !!deepMerge; } - // addTemplateExtensionAlias(targetKey, extension) { - // this.templateExtensionAliases[extension] = targetKey; - // } - setWatchJavaScriptDependencies(watchEnabled) { this.watchJavaScriptDependencies = !!watchEnabled; } @@ -526,7 +521,6 @@ class UserConfig { useGitIgnore: this.useGitIgnore, dataDeepMerge: this.dataDeepMerge, experiments: this.experiments, - // templateExtensionAliases: this.templateExtensionAliases, watchJavaScriptDependencies: this.watchJavaScriptDependencies, browserSyncConfig: this.browserSyncConfig, frontMatterParsingOptions: this.frontMatterParsingOptions diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index 4a3b1607c..90465ad1c 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -77,67 +77,69 @@ test("fileList with dir in path and dir", t => { }); test("removeTemplateExtension", t => { - t.is( - EleventyExtensionMap.removeTemplateExtension("component.njk"), - "component" - ); - t.is( - EleventyExtensionMap.removeTemplateExtension("component.11ty.js"), - "component" - ); - - t.is(EleventyExtensionMap.removeTemplateExtension(""), ""); - t.is(EleventyExtensionMap.removeTemplateExtension("component"), "component"); - t.is( - EleventyExtensionMap.removeTemplateExtension("component.js"), - "component.js" - ); -}); - -test("getKey", t => { - t.is(EleventyExtensionMap.getKey("component.njk"), "njk"); - t.is(EleventyExtensionMap.getKey("component.11ty.js"), "11ty.js"); - t.is(EleventyExtensionMap.getKey("11ty.js"), "11ty.js"); - t.is(EleventyExtensionMap.getKey(".11ty.js"), "11ty.js"); + let map = new EleventyExtensionMap(["njk", "11ty.js"]); + t.is(map.removeTemplateExtension("component.njk"), "component"); + t.is(map.removeTemplateExtension("component.11ty.js"), "component"); + + t.is(map.removeTemplateExtension(""), ""); + t.is(map.removeTemplateExtension("component"), "component"); + t.is(map.removeTemplateExtension("component.js"), "component.js"); +}); + +test("hasEngine", t => { + let map = new EleventyExtensionMap([ + "liquid", + "njk", + "11ty.js", + "ejs", + "pug" + ]); + t.true(map.hasEngine("default.ejs")); + t.is(map.getKey("default.ejs"), "ejs"); + t.falsy(map.getKey()); + t.is(map.getKey("EjS"), "ejs"); + t.true(map.hasEngine("EjS")); + t.true(map.hasEngine("ejs")); + t.falsy(map.getKey("sldkjfkldsj")); + t.false(map.hasEngine("sldkjfkldsj")); - t.is(EleventyExtensionMap.getKey("sample.md"), "md"); + t.is(map.getKey("11ty.js"), "11ty.js"); + t.true(map.hasEngine("11ty.js")); - t.is(EleventyExtensionMap.getKey(""), undefined); - t.is(EleventyExtensionMap.getKey("js"), undefined); - t.is(EleventyExtensionMap.getKey("component"), undefined); - t.is(EleventyExtensionMap.getKey("component.js"), undefined); + t.is(map.getKey("md"), "md"); + t.true(map.hasEngine("md")); }); -test("Extension aliasing (one format key)", t => { - let map = new EleventyExtensionMap(["md"]); - map.config = { - templateExtensionAliases: { - markdown: "md", - nunjucks: "njk" // N/A to current format list - } - }; - t.deepEqual(map.getExtensionsFromKey("md"), ["md", "markdown"]); - t.deepEqual(map.getExtensionsFromKey("njk"), ["njk", "nunjucks"]); +test("hasEngine no formats passed in", t => { + let map = new EleventyExtensionMap([]); + t.true(map.hasEngine("default.ejs")); + t.is(map.getKey("default.ejs"), "ejs"); + t.falsy(map.getKey()); + t.is(map.getKey("EjS"), "ejs"); + t.true(map.hasEngine("EjS")); + t.true(map.hasEngine("ejs")); + t.falsy(map.getKey("sldkjfkldsj")); + t.false(map.hasEngine("sldkjfkldsj")); + + // should return keys for engines that exist but are not filtered + t.is(map.getKey("11ty.js"), "11ty.js"); + t.true(map.hasEngine("11ty.js")); - // should filter out N/A aliases - t.deepEqual(map.getGlobs("."), ["./**/*.md", "./**/*.markdown"]); + t.is(map.getKey("md"), "md"); + t.true(map.hasEngine("md")); }); -test("Extension aliasing (two format keys)", t => { - let map = new EleventyExtensionMap(["md", "njk"]); - map.config = { - templateExtensionAliases: { - markdown: "md", - nunjucks: "njk" - } - }; - t.deepEqual(map.getExtensionsFromKey("md"), ["md", "markdown"]); - t.deepEqual(map.getExtensionsFromKey("njk"), ["njk", "nunjucks"]); - - t.deepEqual(map.getGlobs("."), [ - "./**/*.md", - "./**/*.markdown", - "./**/*.njk", - "./**/*.nunjucks" - ]); +test("getKey", t => { + let map = new EleventyExtensionMap(["njk", "11ty.js", "md"]); + t.is(map.getKey("component.njk"), "njk"); + t.is(map.getKey("component.11ty.js"), "11ty.js"); + t.is(map.getKey("11ty.js"), "11ty.js"); + t.is(map.getKey(".11ty.js"), "11ty.js"); + + t.is(map.getKey("sample.md"), "md"); + + t.is(map.getKey(""), undefined); + t.is(map.getKey("js"), undefined); + t.is(map.getKey("component"), undefined); + t.is(map.getKey("component.js"), undefined); }); diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index fa6ab47f4..2227240f9 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -54,8 +54,8 @@ test("getFiles (with js, treated as passthrough copy)", async t => { "./test/stubs/writeTestJS/test.11ty.js" ].sort() ); - t.false(TemplateRender.hasEngine("./test/stubs/writeTestJS/sample.js")); - t.true(TemplateRender.hasEngine("./test/stubs/writeTestJS/test.11ty.js")); + t.false(evf.extensionMap.hasEngine("./test/stubs/writeTestJS/sample.js")); + t.true(evf.extensionMap.hasEngine("./test/stubs/writeTestJS/test.11ty.js")); }); test("getFiles (with case insensitivity)", async t => { @@ -73,8 +73,8 @@ test("getFiles (with case insensitivity)", async t => { "./test/stubs/writeTestJS/test.11ty.js" ].sort() ); - t.false(TemplateRender.hasEngine("./test/stubs/writeTestJS/sample.js")); - t.true(TemplateRender.hasEngine("./test/stubs/writeTestJS/test.11ty.js")); + t.false(evf.extensionMap.hasEngine("./test/stubs/writeTestJS/sample.js")); + t.true(evf.extensionMap.hasEngine("./test/stubs/writeTestJS/test.11ty.js")); }); test("Mutually exclusive Input and Output dirs", async t => { @@ -566,25 +566,3 @@ test("Glob Watcher Files with passthroughAll", async t => { t.is((await evf.getFileGlobs())[0], "./test/stubs/**"); }); - -test("File extension aliasing", async t => { - let map = new EleventyExtensionMap(["md"]); - map.config = { - templateExtensionAliases: { - markdown: "md" - } - }; - - let evf = new EleventyFiles( - "./test/stubs/writeTestMarkdown", - "./test/stubs/_writeTestMarkdownSite", - ["md"] - ); - evf._setExtensionMap(map); - evf.init(); - - t.deepEqual(await evf.getFiles(), [ - "./test/stubs/writeTestMarkdown/sample.md", - "./test/stubs/writeTestMarkdown/sample2.markdown" - ]); -}); diff --git a/test/TemplateRenderTest.js b/test/TemplateRenderTest.js index 16317d8dd..04502293c 100644 --- a/test/TemplateRenderTest.js +++ b/test/TemplateRenderTest.js @@ -1,22 +1,10 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; -import path from "path"; test("Basic", t => { - // Path is unnecessary but supported - t.is(TemplateRender.cleanupEngineName("default.ejs"), "ejs"); - t.true(TemplateRender.hasEngine("default.ejs")); - t.is(new TemplateRender("default.ejs").getEngineName(), "ejs"); - - // Better - t.is(TemplateRender.cleanupEngineName("ejs"), "ejs"); - t.is(TemplateRender.cleanupEngineName("EjS"), "ejs"); - t.true(TemplateRender.hasEngine("EjS")); - t.true(TemplateRender.hasEngine("ejs")); - t.is(new TemplateRender("ejs").getEngineName(), "ejs"); - - t.falsy(TemplateRender.cleanupEngineName("sldkjfkldsj")); - t.false(TemplateRender.hasEngine("sldkjfkldsj")); + t.throws(() => { + new TemplateRender("sldkjfkldsj"); + }); }); test("Includes Dir", async t => { diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 0f26cde46..054295385 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -525,95 +525,3 @@ test("Write Test 11ty.js", async t => { "./test/stubs/_writeTestJSSite/test/index.html" ); }); - -test.skip("Markdown with alias", async t => { - let map = new EleventyExtensionMap(["md"]); - map.config = { - templateExtensionAliases: { - markdown: "md" - } - }; - - let evf = new EleventyFiles( - "./test/stubs/writeTestMarkdown", - "./test/stubs/_writeTestMarkdownSite", - ["md"] - ); - evf._setExtensionMap(map); - evf.init(); - - let files = await fastglob.async(evf.getFileGlobs()); - t.deepEqual(evf.getRawFiles(), [ - "./test/stubs/writeTestMarkdown/**/*.md", - "./test/stubs/writeTestMarkdown/**/*.markdown" - ]); - t.true(files.indexOf("./test/stubs/writeTestMarkdown/sample.md") > -1); - t.true(files.indexOf("./test/stubs/writeTestMarkdown/sample2.markdown") > -1); - - let tw = new TemplateWriter( - "./test/stubs/writeTestMarkdown", - "./test/stubs/_writeTestMarkdownSite" - ); - tw.setEleventyFiles(evf); - - let tmpl = tw._createTemplate(files[0]); - tmpl._setExtensionMap(map); - t.is( - await tmpl.getOutputPath(), - "./test/stubs/_writeTestMarkdownSite/sample/index.html" - ); - - let tmpl2 = tw._createTemplate(files[1]); - tmpl2._setExtensionMap(map); - t.is( - await tmpl2.getOutputPath(), - "./test/stubs/_writeTestMarkdownSite/sample2/index.html" - ); -}); - -test.skip("JavaScript with alias", async t => { - let map = new EleventyExtensionMap(["11ty.js"]); - map.config = { - templateExtensionAliases: { - js: "11ty.js" - } - }; - - let evf = new EleventyFiles( - "./test/stubs/writeTestJS", - "./test/stubs/_writeTestJSSite", - ["11ty.js"] - ); - evf._setExtensionMap(map); - evf.init(); - - let files = await fastglob.async(evf.getFileGlobs()); - t.deepEqual(evf.getRawFiles(), [ - "./test/stubs/writeTestJS/**/*.11ty.js", - "./test/stubs/writeTestJS/**/*.js" - ]); - t.deepEqual(files, [ - "./test/stubs/writeTestJS/sample.js", - "./test/stubs/writeTestJS/test.11ty.js" - ]); - - let tw = new TemplateWriter( - "./test/stubs/writeTestJS", - "./test/stubs/_writeTestJSSite" - ); - tw.setEleventyFiles(evf); - - let tmpl = tw._createTemplate(files[0]); - tmpl._setExtensionMap(map); - t.is( - await tmpl.getOutputPath(), - "./test/stubs/_writeTestJSSite/sample/index.html" - ); - - let tmpl2 = tw._createTemplate(files[1]); - tmpl2._setExtensionMap(map); - t.is( - await tmpl2.getOutputPath(), - "./test/stubs/_writeTestJSSite/test/index.html" - ); -}); From 59c6aabba905731dbe6e57eb902d337dc7f62f32 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 4 Jul 2019 22:36:39 -0500 Subject: [PATCH 003/746] More static removal --- src/Engines/Html.js | 2 +- src/Engines/Markdown.js | 2 +- src/Engines/TemplateEngine.js | 39 +++++++----------------------- src/TemplateEngineManager.js | 40 +++++++++++++++++++++++++++++++ src/TemplateRender.js | 7 +++++- test/TemplateEngineManagerTest.js | 32 +++++++++++++++++++++++++ test/TemplateEngineTest.js | 21 ---------------- 7 files changed, 88 insertions(+), 55 deletions(-) create mode 100644 src/TemplateEngineManager.js create mode 100644 test/TemplateEngineManagerTest.js diff --git a/src/Engines/Html.js b/src/Engines/Html.js index 8815076df..2e50f4fdd 100644 --- a/src/Engines/Html.js +++ b/src/Engines/Html.js @@ -3,7 +3,7 @@ const TemplateEngine = require("./TemplateEngine"); class Html extends TemplateEngine { async compile(str, inputPath, preTemplateEngine) { if (preTemplateEngine) { - let engine = TemplateEngine.getEngine( + let engine = this.engineManager.getEngine( preTemplateEngine, super.getIncludesDir() ); diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index f064c5f21..d142ee147 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -52,7 +52,7 @@ class Markdown extends TemplateEngine { let engine; if (typeof preTemplateEngine === "string") { - engine = TemplateEngine.getEngine( + engine = this.engineManager.getEngine( preTemplateEngine, super.getIncludesDir() ); diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 5a7549487..1dbf22540 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -28,6 +28,14 @@ class TemplateEngine { this._config = config; } + get engineManager() { + return this._engineManager; + } + + set engineManager(manager) { + this._engineManager = manager; + } + getName() { return this.name; } @@ -110,37 +118,6 @@ class TemplateEngine { initRequireCache(inputPath) { // do nothing } - - static get templateKeyMapToClassName() { - return { - ejs: "Ejs", - md: "Markdown", - jstl: "JavaScriptTemplateLiteral", - html: "Html", - hbs: "Handlebars", - mustache: "Mustache", - haml: "Haml", - pug: "Pug", - njk: "Nunjucks", - liquid: "Liquid", - "11ty.js": "JavaScript" - }; - } - - static hasEngine(name) { - return name in TemplateEngine.templateKeyMapToClassName; - } - - static getEngine(name, includesDir) { - if (!this.hasEngine(name)) { - throw new Error( - `Template Engine ${name} does not exist in getEngine (includes dir: ${includesDir})` - ); - } - - const cls = require("./" + TemplateEngine.templateKeyMapToClassName[name]); - return new cls(name, includesDir); - } } module.exports = TemplateEngine; diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js new file mode 100644 index 000000000..c461dca3e --- /dev/null +++ b/src/TemplateEngineManager.js @@ -0,0 +1,40 @@ +class TemplateEngineManager { + constructor() {} + + getClassNameFromTemplateKey(key) { + let keys = { + ejs: "Ejs", + md: "Markdown", + jstl: "JavaScriptTemplateLiteral", + html: "Html", + hbs: "Handlebars", + mustache: "Mustache", + haml: "Haml", + pug: "Pug", + njk: "Nunjucks", + liquid: "Liquid", + "11ty.js": "JavaScript" + }; + + return keys[key]; + } + + hasEngine(name) { + return !!this.getClassNameFromTemplateKey(name); + } + + getEngine(name, includesDir) { + if (!this.hasEngine(name)) { + throw new Error( + `Template Engine ${name} does not exist in getEngine (includes dir: ${includesDir})` + ); + } + + const cls = require("./Engines/" + this.getClassNameFromTemplateKey(name)); + let instance = new cls(name, includesDir); + instance.engineManager = this; + return instance; + } +} + +module.exports = TemplateEngineManager; diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 7f5035524..79c6686a2 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -1,5 +1,6 @@ const TemplatePath = require("./TemplatePath"); const TemplateEngine = require("./Engines/TemplateEngine"); +const TemplateEngineManager = require("./TemplateEngineManager"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const config = require("./Config"); @@ -63,7 +64,11 @@ class TemplateRender { `Unknown engine for ${engineNameOrPath}` ); } - this.engine = TemplateEngine.getEngine(this.engineName, this.includesDir); + this.engineManager = new TemplateEngineManager(); + this.engine = this.engineManager.getEngine( + this.engineName, + this.includesDir + ); this.engine.initRequireCache(this.path); } diff --git a/test/TemplateEngineManagerTest.js b/test/TemplateEngineManagerTest.js new file mode 100644 index 000000000..a42974152 --- /dev/null +++ b/test/TemplateEngineManagerTest.js @@ -0,0 +1,32 @@ +import test from "ava"; +import TemplateEngineManager from "../src/TemplateEngineManager"; + +test("Unsupported engine", async t => { + t.throws(() => { + let tem = new TemplateEngineManager(); + tem.getEngine("doesnotexist"); + }); +}); + +test("Supported engine", async t => { + let tem = new TemplateEngineManager(); + t.truthy(tem.hasEngine("ejs")); +}); + +test("Handlebars Helpers", async t => { + let tem = new TemplateEngineManager(); + let engine = tem.getEngine("hbs"); + engine.addHelpers({ + uppercase: function(name) { + return name.toUpperCase(); + } + }); + + let fn = await engine.compile("

{{uppercase author}}

"); + t.is(await fn({ author: "zach" }), "

ZACH

"); +}); + +test("getEngineLib", async t => { + let tem = new TemplateEngineManager(); + t.truthy(tem.getEngine("md").getEngineLib()); +}); diff --git a/test/TemplateEngineTest.js b/test/TemplateEngineTest.js index 090820275..b3e43dbfc 100644 --- a/test/TemplateEngineTest.js +++ b/test/TemplateEngineTest.js @@ -3,29 +3,8 @@ import TemplateEngine from "../src/Engines/TemplateEngine"; test("Unsupported engine", async t => { t.is(new TemplateEngine("doesnotexist").getName(), "doesnotexist"); - - t.throws(() => { - TemplateEngine.getEngine("doesnotexist"); - }); }); test("Supported engine", async t => { t.is(new TemplateEngine("ejs").getName(), "ejs"); - t.truthy(TemplateEngine.hasEngine("ejs")); -}); - -test("Handlebars Helpers", async t => { - let engine = TemplateEngine.getEngine("hbs"); - engine.addHelpers({ - uppercase: function(name) { - return name.toUpperCase(); - } - }); - - let fn = await engine.compile("

{{uppercase author}}

"); - t.is(await fn({ author: "zach" }), "

ZACH

"); -}); - -test("getEngineLib", async t => { - t.truthy(TemplateEngine.getEngine("md").getEngineLib()); }); From 6a9da7bb53161634d76ec302a97ee54d8aacee0b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Jul 2019 12:19:40 -0500 Subject: [PATCH 004/746] Also adds case sensitivity to the file names in the test for #517 --- src/EleventyFiles.js | 7 ++++++- test/EleventyFilesTest.js | 20 +++++++++++++------ .../stubs/writeTestJS-casesensitive/sample.Js | 1 + .../writeTestJS-casesensitive/test.11Ty.js | 1 + 4 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 test/stubs/writeTestJS-casesensitive/sample.Js create mode 100644 test/stubs/writeTestJS-casesensitive/test.11Ty.js diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 54999e61d..c8b2c4b7d 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -278,7 +278,12 @@ class EleventyFiles { debug("Searching for: %o", globs); let paths = TemplatePath.addLeadingDotSlashArray( - await fastglob.async(globs, { nocase: true, onlyFiles: true }) + await fastglob.async(globs, { + // nocase: true (case insensitive match) was the old property but was from node-glob, not fastglob + caseSensitiveMatch: false, + onlyFiles: true, + dot: true + }) ); this.pathCache = paths; return paths; diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 2227240f9..5e811d321 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -60,8 +60,8 @@ test("getFiles (with js, treated as passthrough copy)", async t => { test("getFiles (with case insensitivity)", async t => { let evf = new EleventyFiles( - "./test/stubs/writeTestJS", - "./test/stubs/_writeTestJSSite", + "./test/stubs/writeTestJS-casesensitive", + "./test/stubs/_writeTestJSCaseSensitiveSite", ["JS"] ); evf.init(); @@ -69,12 +69,20 @@ test("getFiles (with case insensitivity)", async t => { t.deepEqual( (await evf.getFiles()).sort(), [ - "./test/stubs/writeTestJS/sample.js", - "./test/stubs/writeTestJS/test.11ty.js" + "./test/stubs/writeTestJS-casesensitive/sample.Js", + "./test/stubs/writeTestJS-casesensitive/test.11Ty.js" ].sort() ); - t.false(evf.extensionMap.hasEngine("./test/stubs/writeTestJS/sample.js")); - t.true(evf.extensionMap.hasEngine("./test/stubs/writeTestJS/test.11ty.js")); + t.false( + evf.extensionMap.hasEngine( + "./test/stubs/writeTestJS-casesensitive/sample.Js" + ) + ); + t.true( + evf.extensionMap.hasEngine( + "./test/stubs/writeTestJS-casesensitive/test.11Ty.js" + ) + ); }); test("Mutually exclusive Input and Output dirs", async t => { diff --git a/test/stubs/writeTestJS-casesensitive/sample.Js b/test/stubs/writeTestJS-casesensitive/sample.Js new file mode 100644 index 000000000..e9aa24752 --- /dev/null +++ b/test/stubs/writeTestJS-casesensitive/sample.Js @@ -0,0 +1 @@ +module.exports = "

Zach

"; diff --git a/test/stubs/writeTestJS-casesensitive/test.11Ty.js b/test/stubs/writeTestJS-casesensitive/test.11Ty.js new file mode 100644 index 000000000..e9aa24752 --- /dev/null +++ b/test/stubs/writeTestJS-casesensitive/test.11Ty.js @@ -0,0 +1 @@ +module.exports = "

Zach

"; From 6eabbc235fde1201f8c3eb8bc6832c3eacbf7dfd Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Jul 2019 15:53:37 -0500 Subject: [PATCH 005/746] Bunch more refactoring to get ready for #117 --- src/EleventyExtensionMap.js | 37 ++++++----- src/EleventyFiles.js | 101 +++++++++++++++++++------------ src/TemplateWriter.js | 39 ++++++------ test/EleventyExtensionMapTest.js | 2 +- test/EleventyFilesTest.js | 32 +++++----- test/TemplateWriterTest.js | 14 +++-- 6 files changed, 127 insertions(+), 98 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 4af4ad953..a5d4498c4 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -3,6 +3,7 @@ const config = require("./Config"); class EleventyExtensionMap { constructor(formatKeys) { + this.config = config.getConfig(); this.setFormats(formatKeys); } @@ -11,17 +12,17 @@ class EleventyExtensionMap { return key.trim().toLowerCase(); }); - this.formatKeys = this.unfilteredFormatKeys.filter(key => + this.validTemplateLanguageKeys = this.unfilteredFormatKeys.filter(key => this.hasExtension(key) ); - this.prunedFormatKeys = this.unfilteredFormatKeys.filter( + this.passthroughCopyKeys = this.unfilteredFormatKeys.filter( key => !this.hasExtension(key) ); } get config() { - return this.configOverride || config.getConfig(); + return this.configOverride || this.config.getConfig(); } set config(cfg) { this.configOverride = cfg; @@ -34,7 +35,7 @@ class EleventyExtensionMap { } let files = []; - this.formatKeys.forEach( + this.validTemplateLanguageKeys.forEach( function(key) { this.getExtensionsFromKey(key).forEach(function(extension) { files.push((dir ? dir + "/" : "") + path + "." + extension); @@ -45,8 +46,12 @@ class EleventyExtensionMap { return files; } - getPrunedGlobs(inputDir) { - return this._getGlobs(this.prunedFormatKeys, inputDir); + getPassthroughCopyGlobs(inputDir) { + return this._getGlobs(this.passthroughCopyKeys, inputDir); + } + + getValidGlobs(inputDir) { + return this._getGlobs(this.validTemplateLanguageKeys, inputDir); } getGlobs(inputDir) { @@ -54,7 +59,7 @@ class EleventyExtensionMap { return this._getGlobs(this.unfilteredFormatKeys, inputDir); } - return this._getGlobs(this.formatKeys, inputDir); + return this._getGlobs(this.validTemplateLanguageKeys, inputDir); } _getGlobs(formatKeys, inputDir) { @@ -75,8 +80,8 @@ class EleventyExtensionMap { } hasExtension(key) { - for (var extension in this.keyMap) { - if (this.keyMap[extension] === key) { + for (var extension in this.extensionToKeyMap) { + if (this.extensionToKeyMap[extension] === key) { return true; } } @@ -85,8 +90,8 @@ class EleventyExtensionMap { getExtensionsFromKey(key) { let extensions = []; - for (var extension in this.keyMap) { - if (this.keyMap[extension] === key) { + for (var extension in this.extensionToKeyMap) { + if (this.extensionToKeyMap[extension] === key) { extensions.push(extension); } } @@ -100,8 +105,8 @@ class EleventyExtensionMap { getKey(pathOrKey) { pathOrKey = (pathOrKey || "").toLowerCase(); - for (var extension in this.keyMap) { - let key = this.keyMap[extension]; + for (var extension in this.extensionToKeyMap) { + let key = this.extensionToKeyMap[extension]; if (pathOrKey === extension) { return key; } else if (pathOrKey.endsWith("." + extension)) { @@ -111,7 +116,7 @@ class EleventyExtensionMap { } removeTemplateExtension(path) { - for (var extension in this.keyMap) { + for (var extension in this.extensionToKeyMap) { if (path === extension || path.endsWith("." + extension)) { return path.substr(0, path.length - 1 - extension.length); } @@ -119,7 +124,9 @@ class EleventyExtensionMap { return path; } - get keyMap() { + // keys are file extensions + // values are template language keys + get extensionToKeyMap() { return { ejs: "ejs", md: "md", diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index c8b2c4b7d..030a76ce0 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -40,11 +40,32 @@ class EleventyFiles { } init() { - this.initFormatsGlobs(); + // Input was a directory + if (this.input === this.inputDir) { + this.templateGlobs = this.extensionMap.getGlobs(this.inputDir); + } else { + this.templateGlobs = TemplateGlob.map([this.input]); + } + this.initPassthroughManager(); this.setupGlobs(); } + get validTemplateAndPassthroughCopyGlobs() { + if (!this._validTemplateAndPassthroughCopyGlobs) { + let globs; + if (this.input === this.inputDir) { + globs = this.extensionMap.getValidGlobs(this.inputDir); + } else { + globs = this.templateGlobs; + } + this._validTemplateAndPassthroughCopyGlobs = globs.concat( + this._getPassthroughPaths() + ); + } + return this._validTemplateAndPassthroughCopyGlobs; + } + restart() { this.passthroughManager.reset(); this.setupGlobs(); @@ -65,6 +86,7 @@ class EleventyFiles { } get extensionMap() { + // for tests if (!this._extensionMap) { this._extensionMap = new EleventyExtensionMap(this.formats); } @@ -75,17 +97,6 @@ class EleventyFiles { this.passthroughAll = !!passthroughAll; } - initFormatsGlobs() { - // Input was a directory - if (this.input === this.inputDir) { - this.templateGlobs = TemplateGlob.map( - this.extensionMap.getGlobs(this.inputDir) - ); - } else { - this.templateGlobs = TemplateGlob.map([this.input]); - } - } - initPassthroughManager() { let mgr = new TemplatePassthroughManager(); mgr.setInputDir(this.inputDir); @@ -122,18 +133,20 @@ class EleventyFiles { } setupGlobs() { - this.ignores = this.getIgnores(); + this.fileIgnores = this.getIgnores(); if (this.passthroughAll) { - this.watchedGlobs = TemplateGlob.map([ + this.templateGlobsWithIgnoresFromFiles = TemplateGlob.map([ TemplateGlob.normalizePath(this.input, "/**") - ]).concat(this.ignores); + ]).concat(this.fileIgnores); } else { - this.watchedGlobs = this.templateGlobs.concat(this.ignores); + this.templateGlobsWithIgnoresFromFiles = this.templateGlobs.concat( + this.fileIgnores + ); } - this.templateGlobsWithIgnores = this.watchedGlobs.concat( - this.getTemplateIgnores() + this.templateGlobsWithAllIgnores = this.templateGlobsWithIgnoresFromFiles.concat( + this._getIncludesAndDataDirIgnores() ); } @@ -261,11 +274,11 @@ class EleventyFiles { return this.layoutsDir; } - getFileGlobs() { - return this.templateGlobsWithIgnores; + _testGetFileGlobs() { + return this.templateGlobsWithAllIgnores; } - getRawFiles() { + _testGetRawFiles() { return this.templateGlobs; } @@ -274,13 +287,12 @@ class EleventyFiles { } async getFiles() { - let globs = this.getFileGlobs(); - - debug("Searching for: %o", globs); + debug("Searching for: %o", this.templateGlobsWithAllIgnores); let paths = TemplatePath.addLeadingDotSlashArray( - await fastglob.async(globs, { - // nocase: true (case insensitive match) was the old property but was from node-glob, not fastglob - caseSensitiveMatch: false, + await fastglob.async(this.templateGlobsWithAllIgnores, { + // even though the fast-glob docs say to use `caseSensitiveMatch: false` + // it doesn’t work and `nocase: true` from node-glob does so ¯\_(ツ)_/¯ + nocase: true, onlyFiles: true, dot: true }) @@ -289,18 +301,21 @@ class EleventyFiles { return paths; } + /* For `eleventy --watch` */ getGlobWatcherFiles() { // TODO is it better to tie the includes and data to specific file extensions or keep the **? - return this.templateGlobs - .concat(this.getIncludesAndDataDirs()) - .concat(this.getPassthroughPaths()); + return this.validTemplateAndPassthroughCopyGlobs.concat( + this._getIncludesAndDataDirs() + ); } + /* For `eleventy --watch` */ async getGlobWatcherTemplateDataFiles() { let templateData = this.getTemplateData(); return await templateData.getTemplateDataFileGlob(); } + /* For `eleventy --watch` */ // TODO this isn’t great but reduces complexity avoiding using TemplateData:getLocalDataPaths for each template in the cache async getWatcherTemplateJavaScriptDataFiles() { let globs = await this.getTemplateData().getTemplateJavaScriptDataFileGlob(); @@ -309,22 +324,28 @@ class EleventyFiles { ); } + /* Ignored by `eleventy --watch` */ getGlobWatcherIgnores() { // convert to format without ! since they are passed in as a separate argument to glob watcher - return this.ignores.map(ignore => + return this.fileIgnores.map(ignore => TemplatePath.stripLeadingDotSlash(ignore.substr(1)) ); } - getPassthroughPaths() { - let paths = []; - paths = paths.concat(this.passthroughManager.getConfigPathGlobs()); - // These are already added in the root templateGlobs - // paths = paths.concat(this.extensionMap.getPrunedGlobs(this.inputDir)); - return paths; + _getPassthroughPaths() { + let paths = new Set(); + // stuff added in addPassthroughCopy() + for (let path of this.passthroughManager.getConfigPathGlobs()) { + paths.add(path); + } + // non-template language extensions + for (let path of this.extensionMap.getPassthroughCopyGlobs(this.inputDir)) { + paths.add(path); + } + return Array.from(paths); } - getIncludesAndDataDirs() { + _getIncludesAndDataDirs() { let files = []; // we want this to fail on "" because we don’t want to ignore the // entire input directory when using "" @@ -346,8 +367,8 @@ class EleventyFiles { return files; } - getTemplateIgnores() { - return this.getIncludesAndDataDirs().map(function(dir) { + _getIncludesAndDataDirIgnores() { + return this._getIncludesAndDataDirs().map(function(dir) { return "!" + dir; }); } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 01a3a34c1..05fc477eb 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -1,7 +1,6 @@ const Template = require("./Template"); const TemplatePath = require("./TemplatePath"); const TemplateMap = require("./TemplateMap"); -const TemplateRender = require("./TemplateRender"); const EleventyFiles = require("./EleventyFiles"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); @@ -18,7 +17,7 @@ class TemplateWriter { constructor( inputPath, outputDir, - templateFormats, // TODO remove this, see `.getFileManager()` first + templateFormats, // TODO remove this, see `get eleventyFiles` first templateData, isPassthroughAll ) { @@ -32,7 +31,7 @@ class TemplateWriter { this.isDryRun = false; this.writeCount = 0; - // TODO can we get rid of this? It’s only used for tests in getFileManager() + // TODO can we get rid of this? It’s only used for tests in `get eleventyFiles`` this.passthroughAll = isPassthroughAll; } @@ -46,10 +45,6 @@ class TemplateWriter { debugDev("Resetting counts to 0"); } - setEleventyFiles(eleventyFiles) { - this.eleventyFiles = eleventyFiles; - } - set extensionMap(extensionMap) { this._extensionMap = extensionMap; } @@ -63,24 +58,32 @@ class TemplateWriter { return this._extensionMap; } - getFileManager() { + setEleventyFiles(eleventyFiles) { + this.eleventyFiles = eleventyFiles; + } + + set eleventyFiles(eleventyFiles) { + this._eleventyFiles = eleventyFiles; + } + + get eleventyFiles() { // usually Eleventy.js will setEleventyFiles with the EleventyFiles manager - if (!this.eleventyFiles) { + if (!this._eleventyFiles) { // if not, we can create one (used only by tests) - this.eleventyFiles = new EleventyFiles( + this._eleventyFiles = new EleventyFiles( this.input, this.outputDir, this.templateFormats, this.passthroughAll ); - this.eleventyFiles.init(); + this._eleventyFiles.init(); } - return this.eleventyFiles; + return this._eleventyFiles; } async _getAllPaths() { - return await this.getFileManager().getFiles(); + return await this.eleventyFiles.getFiles(); } _createTemplate(path) { @@ -158,7 +161,7 @@ class TemplateWriter { debug("Found: %o", paths); promises.push( - this.getFileManager() + this.eleventyFiles .getPassthroughManager() .copyAll(paths) .catch(e => { @@ -212,15 +215,11 @@ class TemplateWriter { setDryRun(isDryRun) { this.isDryRun = !!isDryRun; - this.getFileManager() - .getPassthroughManager() - .setDryRun(this.isDryRun); + this.eleventyFiles.getPassthroughManager().setDryRun(this.isDryRun); } getCopyCount() { - return this.getFileManager() - .getPassthroughManager() - .getCopyCount(); + return this.eleventyFiles.getPassthroughManager().getCopyCount(); } getWriteCount() { diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index 90465ad1c..318dd60ed 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -39,7 +39,7 @@ test("Keys are mapped to lower case", t => { test("Pruned globs", t => { let map = new EleventyExtensionMap(["pug", "njk", "png"]); - t.deepEqual(map.getPrunedGlobs("."), ["./**/*.png"]); + t.deepEqual(map.getPassthroughCopyGlobs("."), ["./**/*.png"]); }); test("Empty path for fileList", t => { diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 5e811d321..9902e9163 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -2,8 +2,6 @@ import test from "ava"; import fastglob from "fast-glob"; import EleventyFiles from "../src/EleventyFiles"; import TemplatePath from "../src/TemplatePath"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; -import TemplateRender from "../src/TemplateRender"; import TemplatePassthroughManager from "../src/TemplatePassthroughManager"; test("getFiles", async t => { @@ -93,8 +91,8 @@ test("Mutually exclusive Input and Output dirs", async t => { ); evf.init(); - let files = await fastglob.async(evf.getFileGlobs()); - t.is(evf.getRawFiles().length, 2); + let files = await fastglob.async(evf._testGetFileGlobs()); + t.is(evf._testGetRawFiles().length, 2); t.true(files.length > 0); t.is(files[0], "./test/stubs/writeTest/test.md"); }); @@ -106,8 +104,8 @@ test("Single File Input (deep path)", async t => { ]); evf.init(); - let files = await fastglob.async(evf.getFileGlobs()); - t.is(evf.getRawFiles().length, 1); + let files = await fastglob.async(evf._testGetFileGlobs()); + t.is(evf._testGetRawFiles().length, 1); t.is(files.length, 1); t.is(files[0], "./test/stubs/index.html"); }); @@ -116,9 +114,9 @@ test("Single File Input (shallow path)", async t => { let evf = new EleventyFiles("README.md", "./test/stubs/_site", ["md"]); evf.init(); - let globs = evf.getFileGlobs().filter(path => path !== "!./README.md"); + let globs = evf._testGetFileGlobs().filter(path => path !== "!./README.md"); let files = await fastglob.async(globs); - t.is(evf.getRawFiles().length, 1); + t.is(evf._testGetRawFiles().length, 1); t.is(files.length, 1); t.is(files[0], "./README.md"); }); @@ -131,7 +129,7 @@ test("Glob Input", async t => { ); evf.init(); - let globs = evf.getFileGlobs(); + let globs = evf._testGetFileGlobs(); let files = await fastglob.async(globs); t.is(files.length, 2); t.is(files[0], "./test/stubs/glob-pages/about.md"); @@ -179,7 +177,7 @@ test(".eleventyignore files", async t => { let ignoredFiles = await fastglob.async("test/stubs/ignoredFolder/*.md"); t.is(ignoredFiles.length, 1); - let files = await fastglob.async(evf.getFileGlobs()); + let files = await fastglob.async(evf._testGetFileGlobs()); t.true(files.length > 0); t.is( @@ -405,7 +403,7 @@ test("Include and Data Dirs", t => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); - t.deepEqual(evf.getIncludesAndDataDirs(), [ + t.deepEqual(evf._getIncludesAndDataDirs(), [ "./test/stubs/_includes/**", "./test/stubs/_data/**" ]); @@ -415,7 +413,7 @@ test("Ignore Include and Data Dirs", t => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); - t.deepEqual(evf.getTemplateIgnores(), [ + t.deepEqual(evf._getIncludesAndDataDirIgnores(), [ "!./test/stubs/_includes/**", "!./test/stubs/_data/**" ]); @@ -435,7 +433,7 @@ test("Input to 'src' and empty includes dir (issue #403)", t => { }); evf.init(); - t.deepEqual(evf.getFileGlobs(), [ + t.deepEqual(evf._testGetFileGlobs(), [ "./src/**/*.md", "./src/**/*.liquid", "./src/**/*.html", @@ -503,7 +501,7 @@ test("Issue #403: all .eleventyignores should be relative paths not absolute pat }); evf.init(); - let globs = await evf.getFileGlobs(); + let globs = await evf._testGetFileGlobs(); t.is( globs.filter(glob => { return glob.indexOf(TemplatePath.absolutePath()) > -1; @@ -552,9 +550,9 @@ test("Glob Watcher Files with Config Passthroughs (one template format)", async t.deepEqual(evf.getGlobWatcherFiles(), [ "./test/stubs/**/*.njk", + "./test/stubs/img/**", "./test/stubs/_includes/**", - "./test/stubs/_data/**", - "./test/stubs/img/**" + "./test/stubs/_data/**" ]); }); @@ -572,5 +570,5 @@ test("Glob Watcher Files with passthroughAll", async t => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", [], true); evf.init(); - t.is((await evf.getFileGlobs())[0], "./test/stubs/**"); + t.is((await evf._testGetFileGlobs())[0], "./test/stubs/**"); }); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 054295385..c89086be1 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -23,8 +23,8 @@ test("Output is a subdir of input", async t => { ); evf.init(); - let files = await fastglob.async(evf.getFileGlobs()); - t.is(evf.getRawFiles().length, 2); + let files = await fastglob.async(evf._testGetFileGlobs()); + t.is(evf._testGetRawFiles().length, 2); t.true(files.length > 0); let tmpl = tw._createTemplate(files[0]); @@ -366,7 +366,9 @@ Layout 1 dog` test("Glob Watcher Files with Passthroughs", t => { let tw = new TemplateWriter("test/stubs", "test/stubs/_site", ["njk", "png"]); - t.deepEqual(tw.getFileManager().getPassthroughPaths(), []); + t.deepEqual(tw.eleventyFiles._getPassthroughPaths(), [ + "./test/stubs/**/*.png" + ]); }); test("Pagination and TemplateContent", async t => { @@ -515,8 +517,10 @@ test("Write Test 11ty.js", async t => { ); evf.init(); - let files = await fastglob.async(evf.getFileGlobs()); - t.deepEqual(evf.getRawFiles(), ["./test/stubs/writeTestJS/**/*.11ty.js"]); + let files = await fastglob.async(evf._testGetFileGlobs()); + t.deepEqual(evf._testGetRawFiles(), [ + "./test/stubs/writeTestJS/**/*.11ty.js" + ]); t.deepEqual(files, ["./test/stubs/writeTestJS/test.11ty.js"]); let tmpl = tw._createTemplate(files[0]); From fbc0d31546be48cf2fc5af0d7a533a0682e36d2f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 11 Jul 2019 21:46:25 -0500 Subject: [PATCH 006/746] =?UTF-8?q?Getting=20there!=20All=20the=20static?= =?UTF-8?q?=20gone,=20the=20tests=20are=20lookin=E2=80=99=20good?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EleventyExtensionMap.js | 46 +++++--- src/EleventyFiles.js | 1 + src/Engines/Custom.js | 26 +++++ src/Engines/Ejs.js | 1 - src/TemplateContent.js | 8 +- src/TemplateData.js | 8 +- src/TemplateEngineManager.js | 53 ++++++--- src/TemplatePassthroughManager.js | 1 + src/TemplateRender.js | 70 ++++++++---- src/TemplateWriter.js | 5 +- src/UserConfig.js | 17 ++- test/TemplateEngineManagerTest.js | 22 ++++ test/TemplateRenderCustomTest.js | 57 +++++++++ test/TemplateRenderEJSTest.js | 36 +++--- test/TemplateRenderHTMLTest.js | 21 ++-- test/TemplateRenderHamlTest.js | 13 ++- test/TemplateRenderHandlebarsTest.js | 64 ++++++----- test/TemplateRenderJSTLTest.js | 17 ++- test/TemplateRenderJavaScriptTest.js | 49 ++++---- test/TemplateRenderLiquidTest.js | 165 ++++++++++++++++----------- test/TemplateRenderMarkdownTest.js | 57 +++++---- test/TemplateRenderMustacheTest.js | 27 +++-- test/TemplateRenderNunjucksTest.js | 77 +++++++------ test/TemplateRenderPugTest.js | 39 ++++--- test/TemplateRenderTest.js | 16 ++- test/TemplateTest.js | 2 +- 26 files changed, 596 insertions(+), 302 deletions(-) create mode 100644 src/Engines/Custom.js create mode 100644 test/TemplateRenderCustomTest.js diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index a5d4498c4..d298d6ae4 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -3,7 +3,8 @@ const config = require("./Config"); class EleventyExtensionMap { constructor(formatKeys) { - this.config = config.getConfig(); + this.formatKeys = formatKeys; + this.setFormats(formatKeys); } @@ -22,10 +23,13 @@ class EleventyExtensionMap { } get config() { - return this.configOverride || this.config.getConfig(); + if (!this._config) { + this._config = config.getConfig(); + } + return this._config; } set config(cfg) { - this.configOverride = cfg; + this._config = cfg; } /* Used for layout path resolution */ @@ -127,19 +131,29 @@ class EleventyExtensionMap { // keys are file extensions // values are template language keys get extensionToKeyMap() { - return { - ejs: "ejs", - md: "md", - jstl: "jstl", - html: "html", - hbs: "hbs", - mustache: "mustache", - haml: "haml", - pug: "pug", - njk: "njk", - liquid: "liquid", - "11ty.js": "11ty.js" - }; + if (!this._extensionToKeyMap) { + this._extensionToKeyMap = { + ejs: "ejs", + md: "md", + jstl: "jstl", + html: "html", + hbs: "hbs", + mustache: "mustache", + haml: "haml", + pug: "pug", + njk: "njk", + liquid: "liquid", + "11ty.js": "11ty.js" + }; + + if ("extensionMap" in this.config) { + for (let entry of this.config.extensionMap) { + this._extensionToKeyMap[entry.extension] = entry.key; + } + } + } + + return this._extensionToKeyMap; } } diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 030a76ce0..532c8ddbc 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -89,6 +89,7 @@ class EleventyFiles { // for tests if (!this._extensionMap) { this._extensionMap = new EleventyExtensionMap(this.formats); + this._extensionMap.config = this.config; } return this._extensionMap; } diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js new file mode 100644 index 000000000..d9d412e5f --- /dev/null +++ b/src/Engines/Custom.js @@ -0,0 +1,26 @@ +const TemplateEngine = require("./TemplateEngine"); + +class CustomEngine extends TemplateEngine { + constructor(name, includesDir) { + super(name, includesDir); + } + + get compileFunction() { + for (let entry of this.config.extensionMap) { + if (entry.key.toLowerCase() === this.name.toLowerCase()) { + return entry.compile; + } + } + + throw Error( + `Could not find a custom extension for ${this.name}. Did you add it to your config file?` + ); + } + + async compile(str, inputPath) { + // TODO generalize this (look at JavaScript.js) + return this.compileFunction(str, inputPath); + } +} + +module.exports = CustomEngine; diff --git a/src/Engines/Ejs.js b/src/Engines/Ejs.js index 98ca1ebbf..7c1e235f8 100644 --- a/src/Engines/Ejs.js +++ b/src/Engines/Ejs.js @@ -1,6 +1,5 @@ const ejsLib = require("ejs"); const TemplateEngine = require("./TemplateEngine"); -const config = require("../Config"); class Ejs extends TemplateEngine { constructor(name, includesDir) { diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 9dc96f87e..00118951d 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -30,6 +30,7 @@ class TemplateContent { get extensionMap() { if (!this._extensionMap) { this._extensionMap = new EleventyExtensionMap(); + this._extensionMap.config = this.config; } return this._extensionMap; } @@ -56,11 +57,8 @@ class TemplateContent { get templateRender() { if (!this._templateRender) { - this._templateRender = new TemplateRender( - this.inputPath, - this.inputDir, - this.extensionMap - ); + this._templateRender = new TemplateRender(this.inputPath, this.inputDir); + this._templateRender.extensionMap = this.extensionMap; } return this._templateRender; diff --git a/src/TemplateData.js b/src/TemplateData.js index 69d013070..63ce53906 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -33,6 +33,7 @@ class TemplateData { get extensionMap() { if (!this._extensionMap) { this._extensionMap = new EleventyExtensionMap(); + this._extensionMap.config = this.config; } return this._extensionMap; } @@ -268,9 +269,10 @@ class TemplateData { ); } } else { - let fn = await new TemplateRender(engineName).getCompiledTemplate( - rawInput - ); + let tr = new TemplateRender(engineName, this.inputDir); + tr.extensionMap = this.extensionMap; + + let fn = await tr.getCompiledTemplate(rawInput); try { // pass in rawImports, don’t pass in global data, that’s what we’re parsing diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index c461dca3e..a482efbda 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -1,20 +1,46 @@ +const config = require("./Config"); + class TemplateEngineManager { constructor() {} + get config() { + if (!this._config) { + this._config = config.getConfig(); + } + return this._config; + } + + set config(cfg) { + this._config = cfg; + } + + get keyToClassNameMap() { + if (!this._keyToClassNameMap) { + this._keyToClassNameMap = { + ejs: "Ejs", + md: "Markdown", + jstl: "JavaScriptTemplateLiteral", + html: "Html", + hbs: "Handlebars", + mustache: "Mustache", + haml: "Haml", + pug: "Pug", + njk: "Nunjucks", + liquid: "Liquid", + "11ty.js": "JavaScript" + }; + + if ("extensionMap" in this.config) { + for (let entry of this.config.extensionMap) { + this._keyToClassNameMap[entry.key] = "Custom"; + } + } + } + return this._keyToClassNameMap; + } + getClassNameFromTemplateKey(key) { - let keys = { - ejs: "Ejs", - md: "Markdown", - jstl: "JavaScriptTemplateLiteral", - html: "Html", - hbs: "Handlebars", - mustache: "Mustache", - haml: "Haml", - pug: "Pug", - njk: "Nunjucks", - liquid: "Liquid", - "11ty.js": "JavaScript" - }; + let keys = this.keyToClassNameMap; return keys[key]; } @@ -32,6 +58,7 @@ class TemplateEngineManager { const cls = require("./Engines/" + this.getClassNameFromTemplateKey(name)); let instance = new cls(name, includesDir); + instance.config = this.config; instance.engineManager = this; return instance; } diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 09a39e95a..d4ccba9f4 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -31,6 +31,7 @@ class TemplatePassthroughManager { get extensionMap() { if (!this._extensionMap) { this._extensionMap = new EleventyExtensionMap(); + this._extensionMap.config = this.config; } return this._extensionMap; } diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 79c6686a2..0994f7fce 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -1,5 +1,4 @@ const TemplatePath = require("./TemplatePath"); -const TemplateEngine = require("./Engines/TemplateEngine"); const TemplateEngineManager = require("./TemplateEngineManager"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyExtensionMap = require("./EleventyExtensionMap"); @@ -10,25 +9,21 @@ class TemplateRenderUnknownEngineError extends EleventyBaseError {} // works with full path names or short engine name class TemplateRender { - constructor(tmplPath, inputDir, extensionMap) { + constructor(tmplPath, inputDir) { if (!tmplPath) { throw new Error( `TemplateRender requires a tmplPath argument, instead of ${tmplPath}` ); } - this.path = tmplPath; - this.extensionMap = extensionMap; + this.engineNameOrPath = tmplPath; + this.inputDir = inputDir; // optional this.includesDir = this._normalizeIncludesDir(inputDir); this.parseMarkdownWith = this.config.markdownTemplateEngine; this.parseHtmlWith = this.config.htmlTemplateEngine; - - this.init(tmplPath); - - this.useMarkdown = this.engineName === "md"; } get config() { @@ -40,10 +35,6 @@ class TemplateRender { set config(config) { this._config = config; - - if (this.engine) { - this.engine.config = config; - } } set extensionMap(extensionMap) { @@ -51,25 +42,52 @@ class TemplateRender { } get extensionMap() { - if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(); - } return this._extensionMap; } init(engineNameOrPath) { - this.engineName = this.extensionMap.getKey(engineNameOrPath); - if (!this.engineName) { + this.extensionMap.config = this.config; + this._engineName = this.extensionMap.getKey(engineNameOrPath); + if (!this._engineName) { throw new TemplateRenderUnknownEngineError( `Unknown engine for ${engineNameOrPath}` ); } - this.engineManager = new TemplateEngineManager(); - this.engine = this.engineManager.getEngine( - this.engineName, + + this._engineManager = new TemplateEngineManager(); + this._engineManager.config = this.config; + + this._engine = this._engineManager.getEngine( + this._engineName, this.includesDir ); - this.engine.initRequireCache(this.path); + this._engine.config = this.config; + this._engine.initRequireCache(engineNameOrPath); + + if (this.useMarkdown === undefined) { + this.setUseMarkdown(this._engineName === "md"); + } + } + + get engineName() { + if (!this._engineName) { + this.init(this.engineNameOrPath); + } + return this._engineName; + } + + get engine() { + if (!this._engine) { + this.init(this.engineNameOrPath); + } + return this._engine; + } + + get engineManager() { + if (!this._engineManager) { + this.init(this.engineNameOrPath); + } + return this._engineManager; } static parseEngineOverrides(engineName) { @@ -189,14 +207,18 @@ class TemplateRender { if (this.engineName === "md") { return this.engine.compile( str, - this.path, + this.engineNameOrPath, this.parseMarkdownWith, !this.useMarkdown ); } else if (this.engineName === "html") { - return this.engine.compile(str, this.path, this.parseHtmlWith); + return this.engine.compile( + str, + this.engineNameOrPath, + this.parseHtmlWith + ); } else { - return this.engine.compile(str, this.path); + return this.engine.compile(str, this.engineNameOrPath); } } } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 05fc477eb..6dc4ca484 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -51,9 +51,8 @@ class TemplateWriter { get extensionMap() { if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap( - this.config.templateFormats - ); + this._extensionMap = new EleventyExtensionMap(this.templateFormats); + this._extensionMap.config = this.config; } return this._extensionMap; } diff --git a/src/UserConfig.js b/src/UserConfig.js index 9aa08ed90..02cbb999d 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -50,7 +50,7 @@ class UserConfig { this.useGitIgnore = true; this.dataDeepMerge = false; this.experiments = new Set(); - // this.userExtensionMap = {}; + this.extensionMap = new Set(); this.watchJavaScriptDependencies = true; this.browserSyncConfig = {}; } @@ -492,6 +492,14 @@ class UserConfig { this.frontMatterParsingOptions = options; } + addExtension(fileExtension, userClass) { + this.extensionMap.add({ + key: fileExtension, + extension: fileExtension, + compile: userClass + }); + } + getMergingConfigObject() { return { templateFormats: this.templateFormats, @@ -523,13 +531,10 @@ class UserConfig { experiments: this.experiments, watchJavaScriptDependencies: this.watchJavaScriptDependencies, browserSyncConfig: this.browserSyncConfig, - frontMatterParsingOptions: this.frontMatterParsingOptions + frontMatterParsingOptions: this.frontMatterParsingOptions, + extensionMap: this.extensionMap }; } - - // addExtension(fileExtension, userClass) { - // this.userExtensionMap[ fileExtension ] = userClass; - // } } module.exports = UserConfig; diff --git a/test/TemplateEngineManagerTest.js b/test/TemplateEngineManagerTest.js index a42974152..a7dc35437 100644 --- a/test/TemplateEngineManagerTest.js +++ b/test/TemplateEngineManagerTest.js @@ -1,5 +1,7 @@ import test from "ava"; import TemplateEngineManager from "../src/TemplateEngineManager"; +import templateConfig from "../src/Config"; +const config = templateConfig.getConfig(); test("Unsupported engine", async t => { t.throws(() => { @@ -13,6 +15,26 @@ test("Supported engine", async t => { t.truthy(tem.hasEngine("ejs")); }); +test("Supported custom engine", async t => { + let tem = new TemplateEngineManager(); + tem.config = Object.assign({}, config); + tem.config.extensionMap.add({ + extension: "txt", + key: "txt", + compile: function(str, inputPath) { + // plaintext + return function(data) { + return str; + }; + } + }); + + t.truthy(tem.hasEngine("txt")); + let engine = tem.getEngine("txt"); + let fn = await engine.compile("

This is plaintext

"); + t.is(await fn({ author: "zach" }), "

This is plaintext

"); +}); + test("Handlebars Helpers", async t => { let tem = new TemplateEngineManager(); let engine = tem.getEngine("hbs"); diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js new file mode 100644 index 000000000..ca55973e9 --- /dev/null +++ b/test/TemplateRenderCustomTest.js @@ -0,0 +1,57 @@ +import test from "ava"; +import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; +import templateConfig from "../src/Config"; +import Vue from "vue"; +const renderer = require("vue-server-renderer").createRenderer(); + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} + +test("Custom plaintext Render", async t => { + let tr = getNewTemplateRender("txt"); + + const config = templateConfig.getConfig(); + tr.config = Object.assign({}, config); + tr.config.extensionMap.add({ + extension: "txt", + key: "txt", + compile: function(str, inputPath) { + // plaintext + return function(data) { + return str; + }; + } + }); + + let fn = await tr.getCompiledTemplate("

Paragraph

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

Paragraph

"); + t.is(await fn({}), "

Paragraph

"); +}); + +test("Custom Vue Render", async t => { + let tr = getNewTemplateRender("vue"); + + const config = templateConfig.getConfig(); + tr.config = Object.assign({}, config); + tr.config.extensionMap.add({ + extension: "vue", + key: "vue", + compile: function(str, inputPath) { + return async function(data) { + const app = new Vue({ + template: str, + data: data + }); + + return renderer.renderToString(app); + }; + } + }); + + let fn = await tr.getCompiledTemplate(`

Paragraph

`); + t.is(await fn({ test: "Hello" }), `

Hello

`); +}); diff --git a/test/TemplateRenderEJSTest.js b/test/TemplateRenderEJSTest.js index 236b2cd65..928cd4db2 100644 --- a/test/TemplateRenderEJSTest.js +++ b/test/TemplateRenderEJSTest.js @@ -1,14 +1,24 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // EJS test("EJS", t => { - t.is(new TemplateRender("ejs").getEngineName(), "ejs"); - t.is(new TemplateRender("./test/stubs/filename.ejs").getEngineName(), "ejs"); + t.is(getNewTemplateRender("ejs").getEngineName(), "ejs"); + t.is( + getNewTemplateRender("./test/stubs/filename.ejs").getEngineName(), + "ejs" + ); }); test("EJS Render", async t => { - let fn = await new TemplateRender("ejs").getCompiledTemplate( + let fn = await getNewTemplateRender("ejs").getCompiledTemplate( "

<%= name %>

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); @@ -16,7 +26,7 @@ test("EJS Render", async t => { test("EJS Render Absolute Include, Preprocessor Directive", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", "./test/stubs/" ).getCompiledTemplate("

<% include /included %>

"); @@ -25,7 +35,7 @@ test("EJS Render Absolute Include, Preprocessor Directive", async t => { test("EJS Render Absolute Include, Fxn no Data", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", "./test/stubs/" ).getCompiledTemplate("

<%- include('/included') %>

"); @@ -34,7 +44,7 @@ test("EJS Render Absolute Include, Fxn no Data", async t => { test("EJS Render Absolute Include, Fxn with Data", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", "./test/stubs/" ).getCompiledTemplate( @@ -45,7 +55,7 @@ test("EJS Render Absolute Include, Fxn with Data", async t => { test("EJS Render Relative Include (no leading dot-slash for current dir), Preprocessor Directive", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/dir/filename.ejs", "./test/stubs/" ).getCompiledTemplate("

<% include included %>

"); @@ -54,7 +64,7 @@ test("EJS Render Relative Include (no leading dot-slash for current dir), Prepro test("EJS Render Relative Include Current dir to Subdir, Preprocessor Directive", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/filename.ejs", "./test/stubs/" ).getCompiledTemplate("

<% include ./dir/included %>

"); @@ -63,7 +73,7 @@ test("EJS Render Relative Include Current dir to Subdir, Preprocessor Directive" test("EJS Render Relative Include Parent dir to Subdir, Preprocessor Directive", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/dir/filename.ejs", "./test/stubs/" ).getCompiledTemplate("

<% include ../dir/included %>

"); @@ -72,7 +82,7 @@ test("EJS Render Relative Include Parent dir to Subdir, Preprocessor Directive", test("EJS Render Relative Include, Fxn no Data", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", "./test/stubs/" ).getCompiledTemplate("

<%- include('_includes/included', {}) %>

"); @@ -81,7 +91,7 @@ test("EJS Render Relative Include, Fxn no Data", async t => { test("EJS Render Relative Include current dir to subdir, Fxn no Data", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/filename.ejs", "./test/stubs/" ).getCompiledTemplate("

<%- include('./dir/included', {}) %>

"); @@ -90,7 +100,7 @@ test("EJS Render Relative Include current dir to subdir, Fxn no Data", async t = test("EJS Render Relative Include, Fxn with Data", async t => { // includes require a full filename passed in - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", "./test/stubs/" ).getCompiledTemplate( @@ -100,7 +110,7 @@ test("EJS Render Relative Include, Fxn with Data", async t => { }); test("EJS Render: with Library Override", async t => { - let tr = new TemplateRender("ejs"); + let tr = getNewTemplateRender("ejs"); let lib = require("ejs"); tr.engine.setLibrary(lib); diff --git a/test/TemplateRenderHTMLTest.js b/test/TemplateRenderHTMLTest.js index ac735db20..7069a178d 100644 --- a/test/TemplateRenderHTMLTest.js +++ b/test/TemplateRenderHTMLTest.js @@ -1,13 +1,20 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // HTML test("HTML", t => { - t.is(new TemplateRender("html").getEngineName(), "html"); + t.is(getNewTemplateRender("html").getEngineName(), "html"); }); test("HTML Render", async t => { - let fn = await new TemplateRender("html").getCompiledTemplate( + let fn = await getNewTemplateRender("html").getCompiledTemplate( "

Paragraph

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

Paragraph

"); @@ -15,35 +22,35 @@ test("HTML Render", async t => { }); test("HTML Render: Parses HTML using liquid engine (default, with data)", async t => { - let fn = await new TemplateRender("html").getCompiledTemplate( + let fn = await getNewTemplateRender("html").getCompiledTemplate( "

{{title}}

" ); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); test("HTML Render: Parses HTML using ejs engine", async t => { - let tr = new TemplateRender("html"); + let tr = getNewTemplateRender("html"); tr.setHtmlEngine("ejs"); let fn = await tr.getCompiledTemplate("

<%=title %>

"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); test("HTML Render: Set HTML engine to false, don’t parse", async t => { - let tr = new TemplateRender("html"); + let tr = getNewTemplateRender("html"); tr.setHtmlEngine(false); let fn = await tr.getCompiledTemplate("

{{title}}

"); t.is((await fn()).trim(), "

{{title}}

"); }); test("HTML Render: Pass in an override (ejs)", async t => { - let tr = new TemplateRender("html"); + let tr = getNewTemplateRender("html"); tr.setHtmlEngine("ejs"); let fn = await tr.getCompiledTemplate("

<%= title %>

"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); test("HTML Render: Pass in an override (liquid)", async t => { - let tr = new TemplateRender("html"); + let tr = getNewTemplateRender("html"); tr.setHtmlEngine("liquid"); let fn = await tr.getCompiledTemplate("

{{title}}

"); diff --git a/test/TemplateRenderHamlTest.js b/test/TemplateRenderHamlTest.js index 309026c99..189bc0787 100644 --- a/test/TemplateRenderHamlTest.js +++ b/test/TemplateRenderHamlTest.js @@ -1,18 +1,25 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // Haml test("Haml", t => { - t.is(new TemplateRender("haml").getEngineName(), "haml"); + t.is(getNewTemplateRender("haml").getEngineName(), "haml"); }); test("Haml Render", async t => { - let fn = await new TemplateRender("haml").getCompiledTemplate("%p= name"); + let fn = await getNewTemplateRender("haml").getCompiledTemplate("%p= name"); t.is((await fn({ name: "Zach" })).trim(), "

Zach

"); }); test("Haml Render: with Library Override", async t => { - let tr = new TemplateRender("haml"); + let tr = getNewTemplateRender("haml"); let lib = require("hamljs"); tr.engine.setLibrary(lib); diff --git a/test/TemplateRenderHandlebarsTest.js b/test/TemplateRenderHandlebarsTest.js index 261b468e6..b9d44bca4 100644 --- a/test/TemplateRenderHandlebarsTest.js +++ b/test/TemplateRenderHandlebarsTest.js @@ -1,48 +1,56 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // Handlebars test("Handlebars", t => { - t.is(new TemplateRender("hbs").getEngineName(), "hbs"); + t.is(getNewTemplateRender("hbs").getEngineName(), "hbs"); }); test("Handlebars Render", async t => { - let fn = await new TemplateRender("hbs").getCompiledTemplate( + let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{name}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); test("Handlebars Render Unescaped Output (no HTML)", async t => { - let fn = await new TemplateRender("hbs").getCompiledTemplate( + let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{{name}}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); test("Handlebars Render Escaped Output", async t => { - let fn = await new TemplateRender("hbs").getCompiledTemplate( + let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{name}}

" ); t.is(await fn({ name: "Zach" }), "

<b>Zach</b>

"); }); test("Handlebars Render Unescaped Output (HTML)", async t => { - let fn = await new TemplateRender("hbs").getCompiledTemplate( + let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{{name}}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); test("Handlebars Render Partial", async t => { - let fn = await new TemplateRender("hbs", "./test/stubs/").getCompiledTemplate( - "

{{> included}}

" - ); + let fn = await getNewTemplateRender( + "hbs", + "./test/stubs/" + ).getCompiledTemplate("

{{> included}}

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

This is an include.

"); }); test.skip("Handlebars Render Partial (Relative)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.hbs", "./test/stubs/" ).getCompiledTemplate("

{{> ./included}}

"); @@ -52,21 +60,23 @@ test.skip("Handlebars Render Partial (Relative)", async t => { }); test("Handlebars Render Partial (Subdirectory)", async t => { - let fn = await new TemplateRender("hbs", "./test/stubs/").getCompiledTemplate( - "

{{> subfolder/included}}

" - ); + let fn = await getNewTemplateRender( + "hbs", + "./test/stubs/" + ).getCompiledTemplate("

{{> subfolder/included}}

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

This is an include.

"); }); test("Handlebars Render Partial with variable", async t => { - let fn = await new TemplateRender("hbs", "./test/stubs/").getCompiledTemplate( - "

{{> includedvar}}

" - ); + let fn = await getNewTemplateRender( + "hbs", + "./test/stubs/" + ).getCompiledTemplate("

{{> includedvar}}

"); t.is(await fn({ name: "Zach" }), "

This is a Zach.

"); }); test("Handlebars Render: with Library Override", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); let lib = require("handlebars"); tr.engine.setLibrary(lib); @@ -76,7 +86,7 @@ test("Handlebars Render: with Library Override", async t => { }); test("Handlebars Render Helper", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ helpername: function() { return "Zach"; @@ -90,7 +100,7 @@ test("Handlebars Render Helper", async t => { }); test("Handlebars Render Helper (uses argument)", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ helpername2: function(name) { return "Zach"; @@ -104,7 +114,7 @@ test("Handlebars Render Helper (uses argument)", async t => { }); test("Handlebars Render Shortcode", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodename: function(name) { return name.toUpperCase(); @@ -118,7 +128,7 @@ test("Handlebars Render Shortcode", async t => { }); test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodenamehtml: function(name) { return `${name.toUpperCase()}`; @@ -132,7 +142,7 @@ test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { }); test("Handlebars Render Shortcode (Multiple args)", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodename2: function(name, name2) { return name.toUpperCase() + name2.toUpperCase(); @@ -149,7 +159,7 @@ test("Handlebars Render Shortcode (Multiple args)", async t => { }); test("Handlebars Render Paired Shortcode", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ shortcodename3: function(content, name, options) { return (content + name).toUpperCase(); @@ -163,7 +173,7 @@ test("Handlebars Render Paired Shortcode", async t => { }); test("Handlebars Render Paired Shortcode (HTML)", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ shortcodename3html: function(content, name, options) { return `${(content + name).toUpperCase()}`; @@ -180,7 +190,7 @@ test("Handlebars Render Paired Shortcode (HTML)", async t => { }); test("Handlebars Render Paired Shortcode (Spaces)", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ shortcodename4: function(content, name, options) { return (content + name).toUpperCase(); @@ -194,7 +204,7 @@ test("Handlebars Render Paired Shortcode (Spaces)", async t => { }); test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodechild: function(txt, options) { return txt; @@ -217,7 +227,7 @@ test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async }); test("Handlebars Render Raw Output (Issue #436)", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ "raw-helper": function(options) { return options.fn(); @@ -231,7 +241,7 @@ test("Handlebars Render Raw Output (Issue #436)", async t => { }); test("Handlebars Render Raw Output (Issue #436 with if statement)", async t => { - let tr = new TemplateRender("hbs"); + let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ "raw-helper": function(options) { return options.fn(); diff --git a/test/TemplateRenderJSTLTest.js b/test/TemplateRenderJSTLTest.js index 4027ce09d..3ce85f821 100644 --- a/test/TemplateRenderJSTLTest.js +++ b/test/TemplateRenderJSTLTest.js @@ -1,14 +1,21 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // ES6 test("ES6 Template Literal", t => { - t.is(new TemplateRender("jstl").getEngineName(), "jstl"); + t.is(getNewTemplateRender("jstl").getEngineName(), "jstl"); }); test("ES6 Template Literal Render (Backticks)", async t => { // pass in a string here, we don’t want to compile the template in the test :O - let fn = await new TemplateRender("jstl").getCompiledTemplate( + let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "`

${name.toUpperCase()}

`" ); t.is(await fn({ name: "Tim" }), "

TIM

"); @@ -16,7 +23,7 @@ test("ES6 Template Literal Render (Backticks)", async t => { test("ES6 Template Literal Render (No backticks)", async t => { // pass in a string here, we don’t want to compile the template in the test :O - let fn = await new TemplateRender("jstl").getCompiledTemplate( + let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "

${name.toUpperCase()}

" ); t.is(await fn({ name: "Tim" }), "

TIM

"); @@ -24,7 +31,7 @@ test("ES6 Template Literal Render (No backticks)", async t => { test("ES6 Template Literal with newlines", async t => { // pass in a string here, we don’t want to compile the template in the test :O - let fn = await new TemplateRender("jstl").getCompiledTemplate( + let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "Test\n\nMarkdown Syntax ${name}\n" ); t.is(await fn({ name: "Tim" }), "Test\n\nMarkdown Syntax Tim\n"); @@ -32,7 +39,7 @@ test("ES6 Template Literal with newlines", async t => { test("ES6 Template Literal with markdown", async t => { // pass in a string here, we don’t want to compile the template in the test :O - let fn = await new TemplateRender("jstl").getCompiledTemplate( + let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "Test\n```\nMarkdown Syntax ${name}\n```" ); diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 80e78a690..ce334d60f 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -1,37 +1,44 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} test("JS", t => { - t.is(new TemplateRender("11ty.js").getEngineName(), "11ty.js"); + t.is(getNewTemplateRender("11ty.js").getEngineName(), "11ty.js"); t.is( - new TemplateRender("./test/stubs/filename.11ty.js").getEngineName(), + getNewTemplateRender("./test/stubs/filename.11ty.js").getEngineName(), "11ty.js" ); }); test("JS Render a string (no data)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/string.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Bill" }), "

Zach

"); }); test("JS Render a promise (no data)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/promise.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Bill" }), "

Zach

"); }); test("JS Render a buffer (no data)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/buffer.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Bill" }), "

tést

"); }); test("JS Render a function", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/function.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Zach" }), "

Zach

"); @@ -39,7 +46,7 @@ test("JS Render a function", async t => { }); test("JS Render a function (arrow syntax)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/function-arrow.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Zach" }), "

Zach

"); @@ -47,7 +54,7 @@ test("JS Render a function (arrow syntax)", async t => { }); test("JS Render a function, returns a Buffer", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/function-buffer.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "tést" }), "

tést

"); @@ -56,7 +63,7 @@ test("JS Render a function, returns a Buffer", async t => { }); test("JS Render a function (Markdown)", async t => { - let tr = new TemplateRender("./test/stubs/function-markdown.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/function-markdown.11ty.js"); tr.setEngineOverride("11ty.js,md"); let fn = await tr.getCompiledTemplate(); t.is((await fn({ name: "Zach" })).trim(), "

Zach

"); @@ -64,7 +71,7 @@ test("JS Render a function (Markdown)", async t => { }); test("JS Render a function (Collections)", async t => { - let tr = new TemplateRender("./test/stubs/use-collection.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/use-collection.11ty.js"); let fn = await tr.getCompiledTemplate(); t.is( (await fn({ @@ -88,7 +95,7 @@ test("JS Render a function (Collections)", async t => { }); test("JS Render an async function", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/function-async.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Zach" }), "

Zach

"); @@ -96,7 +103,7 @@ test("JS Render an async function", async t => { }); test("JS Render with a Class", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/class.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Zach" }), "

ZachBillTed

"); @@ -104,7 +111,7 @@ test("JS Render with a Class", async t => { }); test("JS Render with a Class, returns a buffer", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/class-buffer.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Zách" }), "

ZáchBillTed

"); @@ -113,7 +120,7 @@ test("JS Render with a Class, returns a buffer", async t => { }); test("JS Render with a Class, async render", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/class-async.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Zach" }), "

Zach

"); @@ -121,7 +128,7 @@ test("JS Render with a Class, async render", async t => { }); test("JS Render using Vue", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/vue.11ty.js" ).getCompiledTemplate(); t.is( @@ -135,7 +142,7 @@ test("JS Render using Vue", async t => { }); test("JS Render using Vue (with a layout)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/vue-layout.11ty.js" ).getCompiledTemplate(); t.is( @@ -147,7 +154,7 @@ test("JS Render using Vue (with a layout)", async t => { }); test("JS Render using ViperHTML", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/viperhtml.11ty.js" ).getCompiledTemplate(); t.is( @@ -160,7 +167,7 @@ test("JS Render using ViperHTML", async t => { }); test("JS Render with a function", async t => { - let tr = new TemplateRender("./test/stubs/function-filter.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/function-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { @@ -175,7 +182,7 @@ test("JS Render with a function", async t => { }); test("JS Render with a function prototype", async t => { - let tr = new TemplateRender("./test/stubs/function-prototype.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/function-prototype.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { @@ -190,7 +197,7 @@ test("JS Render with a function prototype", async t => { }); test("JS Class Render with a function", async t => { - let tr = new TemplateRender("./test/stubs/class-filter.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/class-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { @@ -205,7 +212,7 @@ test("JS Class Render with a function", async t => { }); test("JS Class Async Render with a function", async t => { - let tr = new TemplateRender("./test/stubs/class-async-filter.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/class-async-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 61561c710..953e524d5 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1,22 +1,32 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // Liquid test("Liquid", t => { - t.is(new TemplateRender("liquid").getEngineName(), "liquid"); + t.is(getNewTemplateRender("liquid").getEngineName(), "liquid"); }); test("Liquid Render (with Helper)", async t => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{name | capitalize}}

" ); t.is(await fn({ name: "tim" }), "

Tim

"); }); test("Liquid Render Include", async t => { - t.is(new TemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid"); + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate("

{% include included %}

"); @@ -24,9 +34,12 @@ test("Liquid Render Include", async t => { }); test("Liquid Render Relative Include", async t => { - t.is(new TemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid"); + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate("

{% include ./included %}

"); @@ -34,7 +47,7 @@ test("Liquid Render Relative Include", async t => { }); test("Liquid Render Relative (current dir) Include", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/relative-liquid/does_not_exist_and_thats_ok.liquid", "./test/stubs/" ).getCompiledTemplate("

{% include ./dir/included %}

"); @@ -42,7 +55,7 @@ test("Liquid Render Relative (current dir) Include", async t => { }); test("Liquid Render Relative (parent dir) Include", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/relative-liquid/dir/does_not_exist_and_thats_ok.liquid", "./test/stubs/" ).getCompiledTemplate("

{% include ../dir/included %}

"); @@ -50,7 +63,7 @@ test("Liquid Render Relative (parent dir) Include", async t => { }); test.skip("Liquid Render Relative (relative include should ignore _includes dir) Include", async t => { - let tr = new TemplateRender( + let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", "./test/stubs/" ); @@ -63,9 +76,12 @@ test.skip("Liquid Render Relative (relative include should ignore _includes dir) }); test("Liquid Render Include with Liquid Suffix", async t => { - t.is(new TemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid"); + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate("

{% include included.liquid %}

"); @@ -73,9 +89,12 @@ test("Liquid Render Include with Liquid Suffix", async t => { }); test("Liquid Render Include with HTML Suffix", async t => { - t.is(new TemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid"); + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate("

{% include included.html %}

"); @@ -83,9 +102,12 @@ test("Liquid Render Include with HTML Suffix", async t => { }); test("Liquid Render Include with HTML Suffix and Data Pass in", async t => { - t.is(new TemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid"); + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate( @@ -95,7 +117,7 @@ test("Liquid Render Include with HTML Suffix and Data Pass in", async t => { }); test("Liquid Custom Filter", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addFilter("prefixWithZach", function(val) { return "Zach" + val; }); @@ -104,7 +126,7 @@ test("Liquid Custom Filter", async t => { }); test("Liquid Custom Tag prefixWithZach", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addTag("prefixWithZach", function(liquidEngine) { return { parse: function(tagToken, remainTokens) { @@ -124,7 +146,7 @@ test("Liquid Custom Tag prefixWithZach", async t => { }); test("Liquid Custom Tag postfixWithZach", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addTag("postfixWithZach", function(liquidEngine) { return { parse: function(tagToken, remainTokens) { @@ -144,7 +166,7 @@ test("Liquid Custom Tag postfixWithZach", async t => { }); test("Liquid Custom Tag Unquoted String", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addTag("testUnquotedStringTag", function(liquidEngine) { return { parse: function(tagToken, remainTokens) { @@ -166,14 +188,14 @@ test("Liquid Custom Tag Unquoted String", async t => { }); test("Liquid addTag errors", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); t.throws(() => { tr.engine.addTag("badSecondArgument", {}); }); }); test("Liquid addTags", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addCustomTags({ postfixWithZach: function(liquidEngine) { return { @@ -195,7 +217,7 @@ test("Liquid addTags", async t => { }); test("Liquid Shortcode", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { return str + "Zach"; }); @@ -207,7 +229,7 @@ test("Liquid Shortcode", async t => { }); test("Liquid Shortcode Safe Output", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { return `${str}`; }); @@ -219,7 +241,7 @@ test("Liquid Shortcode Safe Output", async t => { }); test("Liquid Paired Shortcode", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { return str + content + "Zach"; }); @@ -234,7 +256,7 @@ test("Liquid Paired Shortcode", async t => { }); test("Liquid Render Include Subfolder", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include subfolder/included.liquid %}

`); @@ -242,7 +264,7 @@ test("Liquid Render Include Subfolder", async t => { }); test("Liquid Render Include Subfolder HTML", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include subfolder/included.html %}

`); @@ -250,7 +272,7 @@ test("Liquid Render Include Subfolder HTML", async t => { }); test("Liquid Render Include Subfolder No file extension", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include subfolder/included %}

`); @@ -261,7 +283,7 @@ test("Liquid Render Include Subfolder No file extension", async t => { // Resolution: we’re going to leave this skipped as LiquidJS will require dynamicPartials // to be on for quoted includes! test.skip("Liquid Render Include Subfolder Single quotes", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include 'subfolder/included.liquid' %}

`); @@ -269,7 +291,7 @@ test.skip("Liquid Render Include Subfolder Single quotes", async t => { }); test.skip("Liquid Render Include Subfolder Double quotes", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include "subfolder/included.liquid" %}

`); @@ -277,7 +299,7 @@ test.skip("Liquid Render Include Subfolder Double quotes", async t => { }); test.skip("Liquid Render Include Subfolder Single quotes HTML", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include 'subfolder/included.html' %}

`); @@ -285,7 +307,7 @@ test.skip("Liquid Render Include Subfolder Single quotes HTML", async t => { }); test.skip("Liquid Render Include Subfolder Double quotes HTML", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include "subfolder/included.html" %}

`); @@ -293,7 +315,7 @@ test.skip("Liquid Render Include Subfolder Double quotes HTML", async t => { }); test.skip("Liquid Render Include Subfolder Single quotes No file extension", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include 'subfolder/included' %}

`); @@ -301,7 +323,7 @@ test.skip("Liquid Render Include Subfolder Single quotes No file extension", asy }); test.skip("Liquid Render Include Subfolder Double quotes No file extension", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include "subfolder/included" %}

`); @@ -310,7 +332,7 @@ test.skip("Liquid Render Include Subfolder Double quotes No file extension", asy /* End skipped tests */ test("Liquid Options Overrides", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let options = tr.engine.getLiquidOptions(); @@ -318,7 +340,7 @@ test("Liquid Options Overrides", async t => { }); test("Liquid Render Include Subfolder Single quotes no extension dynamicPartials true", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -328,7 +350,7 @@ test("Liquid Render Include Subfolder Single quotes no extension dynamicPartials }); test("Liquid Render Include Subfolder Single quotes (relative include current dir) dynamicPartials true", async t => { - let tr = new TemplateRender( + let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", "./test/stubs/" ); @@ -341,7 +363,7 @@ test("Liquid Render Include Subfolder Single quotes (relative include current di }); test("Liquid Render Include Subfolder Single quotes (relative include parent dir) dynamicPartials true", async t => { - let tr = new TemplateRender( + let tr = getNewTemplateRender( "./test/stubs/subfolder/does_not_exist_and_thats_ok.liquid", "./test/stubs/" ); @@ -354,7 +376,7 @@ test("Liquid Render Include Subfolder Single quotes (relative include parent dir }); test("Liquid Render Include Subfolder Double quotes no extension dynamicPartials true", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -364,7 +386,7 @@ test("Liquid Render Include Subfolder Double quotes no extension dynamicPartials }); test("Liquid Render Include Subfolder Single quotes dynamicPartials true", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -374,7 +396,7 @@ test("Liquid Render Include Subfolder Single quotes dynamicPartials true", async }); test("Liquid Render Include Subfolder Double quotes dynamicPartials true", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -384,7 +406,7 @@ test("Liquid Render Include Subfolder Double quotes dynamicPartials true", async }); test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -394,7 +416,7 @@ test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true", }); test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -404,7 +426,7 @@ test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true", }); test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true, data passed in", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -414,7 +436,7 @@ test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true, d }); test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true, data passed in", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); let fn = await tr.getCompiledTemplate( @@ -424,7 +446,7 @@ test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true, d }); test("Liquid Render: with Library Override", async t => { - let tr = new TemplateRender("liquid"); + let tr = getNewTemplateRender("liquid"); let lib = require("liquidjs")(); tr.engine.setLibrary(lib); @@ -434,7 +456,7 @@ test("Liquid Render: with Library Override", async t => { }); test("Liquid Paired Shortcode with Tag Inside", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { return str + content + "Zach"; }); @@ -449,7 +471,7 @@ test("Liquid Paired Shortcode with Tag Inside", async t => { }); test("Liquid Nested Paired Shortcode", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { return str + content + "Zach"; }); @@ -464,7 +486,7 @@ test("Liquid Nested Paired Shortcode", async t => { }); test("Liquid Shortcode Multiple Args", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str, str2) { return str + str2 + "Zach"; }); @@ -479,9 +501,12 @@ test("Liquid Shortcode Multiple Args", async t => { }); test.skip("Liquid Include Scope Leak", async t => { - t.is(new TemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid"); + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate("

{% include scopeleak %}{{ test }}

"); @@ -490,7 +515,7 @@ test.skip("Liquid Include Scope Leak", async t => { // TODO this will change in 1.0 test("Liquid Missing Filter Issue #183 (no strict_filters)", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); try { await tr.render("{{ 'test' | prefixWithZach }}", {}); @@ -501,7 +526,7 @@ test("Liquid Missing Filter Issue #183 (no strict_filters)", async t => { }); test("Liquid Missing Filter Issue #183", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ strict_filters: true }); try { @@ -513,7 +538,7 @@ test("Liquid Missing Filter Issue #183", async t => { }); test("Issue 258: Liquid Render Date", async t => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{ myDate }}

" ); let dateStr = await fn({ myDate: new Date(Date.UTC(2016, 0, 1, 0, 0, 0)) }); @@ -523,7 +548,7 @@ test("Issue 258: Liquid Render Date", async t => { }); test("Issue 347: Liquid addTags with space in argument", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addCustomTags({ issue347CustomTag: function(liquidEngine) { return { @@ -547,7 +572,7 @@ test("Issue 347: Liquid addTags with space in argument", async t => { }); test("Issue 347: Liquid Shortcode, string argument", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347", function(str) { return str + "Zach"; }); @@ -559,7 +584,7 @@ test("Issue 347: Liquid Shortcode, string argument", async t => { }); test("Issue 347: Liquid Shortcode string argument with space, double quotes", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347b", function(str) { return str + "Zach"; }); @@ -573,7 +598,7 @@ test("Issue 347: Liquid Shortcode string argument with space, double quotes", as }); test("Issue 347: Liquid Shortcode string argument with space, single quotes", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347", function(str) { return str + "Zach"; }); @@ -585,7 +610,7 @@ test("Issue 347: Liquid Shortcode string argument with space, single quotes", as }); test("Issue 347: Liquid Shortcode string argument with space, combination of quotes", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347", function(str, str2) { return str + str2 + "Zach"; }); @@ -599,7 +624,7 @@ test("Issue 347: Liquid Shortcode string argument with space, combination of quo }); test("Issue 347: Liquid Shortcode multiple arguments, comma separated", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347", function(str, str2) { return str + str2 + "Zach"; }); @@ -613,7 +638,7 @@ test("Issue 347: Liquid Shortcode multiple arguments, comma separated", async t }); test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is an integer", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347", function(str, str2) { return str + str2 + "Zach"; }); @@ -625,7 +650,7 @@ test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is an }); test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is a float", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347", function(str, str2) { return str + str2 + "Zach"; }); @@ -637,7 +662,7 @@ test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is a }); test("Issue 347: Liquid Shortcode boolean argument", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue347", function(bool) { return bool ? "Zach" : "Not Zach"; }); @@ -653,7 +678,7 @@ test("Issue 347: Liquid Shortcode boolean argument", async t => { }); test("Issue 347: Liquid Paired Shortcode with Spaces", async t => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function( content, str1, @@ -673,8 +698,20 @@ test("Issue 347: Liquid Paired Shortcode with Spaces", async t => { }); test("Liquid Render with dash variable Issue #567", async t => { - let tr = new TemplateRender("liquid"); + let tr = getNewTemplateRender("liquid"); let fn = await tr.getCompiledTemplate("

{{ my-global-name }}

"); t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); + +test("Issue 600: Liquid Shortcode, Variable with key argument", async t => { + let tr = getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.addShortcode("issue600", function(url) { + return url; + }); + + t.is( + await tr.render("{% issue600 page.url %}", { name: "alkdsjfkslja" }), + "testZach" + ); +}); diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js index cca7dbbe6..585e9a537 100644 --- a/test/TemplateRenderMarkdownTest.js +++ b/test/TemplateRenderMarkdownTest.js @@ -1,48 +1,55 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; import md from "markdown-it"; import mdEmoji from "markdown-it-emoji"; import UserConfig from "../src/UserConfig"; import eleventySyntaxHighlightPlugin from "@11ty/eleventy-plugin-syntaxhighlight"; +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} + // Markdown test("Markdown", t => { - t.is(new TemplateRender("md").getEngineName(), "md"); + t.is(getNewTemplateRender("md").getEngineName(), "md"); }); test("Markdown Render: Parses base markdown, no data", async t => { - let fn = await new TemplateRender("md").getCompiledTemplate("# My Title"); + let fn = await getNewTemplateRender("md").getCompiledTemplate("# My Title"); t.is((await fn()).trim(), "

My Title

"); }); test("Markdown Render: Markdown should work with HTML too", async t => { - let fn = await new TemplateRender("md").getCompiledTemplate( + let fn = await getNewTemplateRender("md").getCompiledTemplate( "

My Title

" ); t.is((await fn()).trim(), "

My Title

"); }); test("Markdown Render: Parses markdown using liquid engine (default, with data)", async t => { - let fn = await new TemplateRender("md").getCompiledTemplate("# {{title}}"); + let fn = await getNewTemplateRender("md").getCompiledTemplate("# {{title}}"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); test("Markdown Render: Parses markdown using ejs engine", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); tr.setMarkdownEngine("ejs"); let fn = await tr.getCompiledTemplate("<%=title %>"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); test("Markdown Render: Ignore markdown, use only preprocess engine (useful for variable resolution in permalinks)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); tr.setUseMarkdown(false); let fn = await tr.getCompiledTemplate("{{title}}"); t.is((await fn({ title: "My Title" })).trim(), "My Title"); }); test("Markdown Render: Skip markdown and preprocess engine (issue #466)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); tr.setMarkdownEngine(false); tr.setUseMarkdown(false); let fn = await tr.getCompiledTemplate("404.html"); @@ -50,14 +57,14 @@ test("Markdown Render: Skip markdown and preprocess engine (issue #466)", async }); test("Markdown Render: Set markdown engine to false, don’t parse", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); tr.setMarkdownEngine(false); let fn = await tr.getCompiledTemplate("# {{title}}"); t.is((await fn()).trim(), "

{{title}}

"); }); test("Markdown Render: Set markdown engine to false, don’t parse (test with HTML input)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); tr.setMarkdownEngine(false); let fn = await tr.getCompiledTemplate("

{{title}}

"); @@ -65,14 +72,14 @@ test("Markdown Render: Set markdown engine to false, don’t parse (test with HT }); test("Markdown Render: Pass in engine override (ejs)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); tr.setMarkdownEngine("ejs"); let fn = await tr.getCompiledTemplate("# <%= title %>"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); test("Markdown Render: Pass in an override (liquid)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); tr.setMarkdownEngine("liquid"); let fn = await tr.getCompiledTemplate("# {{title}}"); @@ -80,17 +87,17 @@ test("Markdown Render: Pass in an override (liquid)", async t => { }); test("Markdown Render: Strikethrough", async t => { - let fn = await new TemplateRender("md").getCompiledTemplate("~~No~~"); + let fn = await getNewTemplateRender("md").getCompiledTemplate("~~No~~"); t.is((await fn()).trim(), "

No

"); }); test("Markdown Render: Strikethrough in a Header", async t => { - let fn = await new TemplateRender("md").getCompiledTemplate("# ~~No~~"); + let fn = await getNewTemplateRender("md").getCompiledTemplate("# ~~No~~"); t.is((await fn()).trim(), "

No

"); }); test("Markdown Render: with Library Override", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let mdLib = md(); tr.engine.setLibrary(mdLib); @@ -101,7 +108,7 @@ test("Markdown Render: with Library Override", async t => { }); test("Markdown Render: with Library Override and a Plugin", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let mdLib = md().use(mdEmoji); tr.engine.setLibrary(mdLib); @@ -112,7 +119,7 @@ test("Markdown Render: with Library Override and a Plugin", async t => { }); test("Markdown Render: use a custom highlighter", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let mdLib = md(); mdLib.set({ @@ -129,7 +136,7 @@ This is some code. }); test("Markdown Render: use prism highlighter (no language)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -153,7 +160,7 @@ This is some code. }); test("Markdown Render: use prism highlighter", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -176,7 +183,7 @@ var key = "value"; }); test("Markdown Render: use prism highlighter (no space before language)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -199,7 +206,7 @@ var key = "value"; }); test("Markdown Render: use prism highlighter, line highlighting", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -222,7 +229,7 @@ var key = "value"; }); test("Markdown Render: use prism highlighter, line highlighting with fallback `text` language.", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -245,7 +252,7 @@ var key = "value"; }); test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Liquid"); let liquidEngine = new cls("liquid", tr.getIncludesDir()); @@ -267,7 +274,7 @@ test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", }); test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Nunjucks"); let nunjucksEngine = new cls("njk", tr.getIncludesDir()); @@ -289,7 +296,7 @@ test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)" }); test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue #536)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Liquid"); let liquidEngine = new cls("liquid", tr.getIncludesDir()); @@ -311,7 +318,7 @@ test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue # }); test("Markdown Render: use Markdown inside of a Nunjucks paired shortcode (Issue #536)", async t => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Nunjucks"); let nunjucksEngine = new cls("njk", tr.getIncludesDir()); diff --git a/test/TemplateRenderMustacheTest.js b/test/TemplateRenderMustacheTest.js index 802bdd0f5..a9f872506 100644 --- a/test/TemplateRenderMustacheTest.js +++ b/test/TemplateRenderMustacheTest.js @@ -1,20 +1,27 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // Mustache test("Mustache", async t => { - t.is(new TemplateRender("mustache").getEngineName(), "mustache"); + t.is(getNewTemplateRender("mustache").getEngineName(), "mustache"); }); test("Mustache Render", async t => { - let fn = await new TemplateRender("mustache").getCompiledTemplate( + let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{name}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); test("Mustache Render Partial (raw text content)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "mustache", "./test/stubs/" ).getCompiledTemplate("

{{> included}}

"); @@ -22,7 +29,7 @@ test("Mustache Render Partial (raw text content)", async t => { }); test.skip("Mustache Render Partial (relative path, raw text content)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.mustache", "./test/stubs/" ).getCompiledTemplate("

{{> ./includedrelative}}

"); @@ -30,7 +37,7 @@ test.skip("Mustache Render Partial (relative path, raw text content)", async t = }); test("Mustache Render Partial (uses a variable in content)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "mustache", "./test/stubs/" ).getCompiledTemplate("

{{> includedvar}}

"); @@ -38,7 +45,7 @@ test("Mustache Render Partial (uses a variable in content)", async t => { }); test("Mustache Render Partial (Subdirectory)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "mustache", "./test/stubs/" ).getCompiledTemplate("

{{> subfolder/included}}

"); @@ -46,7 +53,7 @@ test("Mustache Render Partial (Subdirectory)", async t => { }); test("Mustache Render: with Library Override", async t => { - let tr = new TemplateRender("mustache"); + let tr = getNewTemplateRender("mustache"); let lib = require("mustache"); tr.engine.setLibrary(lib); @@ -56,14 +63,14 @@ test("Mustache Render: with Library Override", async t => { }); test("Mustache Render Unescaped Output (no HTML)", async t => { - let fn = await new TemplateRender("mustache").getCompiledTemplate( + let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{{name}}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); test("Mustache Render Escaped Output", async t => { - let fn = await new TemplateRender("mustache").getCompiledTemplate( + let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{name}}

" ); t.is( @@ -73,7 +80,7 @@ test("Mustache Render Escaped Output", async t => { }); test("Mustache Render Unescaped Output (HTML)", async t => { - let fn = await new TemplateRender("mustache").getCompiledTemplate( + let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{{name}}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index d55a02edb..10468b4c2 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -1,27 +1,34 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // Nunjucks test("Nunjucks", t => { - t.is(new TemplateRender("njk").getEngineName(), "njk"); + t.is(getNewTemplateRender("njk").getEngineName(), "njk"); }); test("Nunjucks Render", async t => { - let fn = await new TemplateRender("njk").getCompiledTemplate( + let fn = await getNewTemplateRender("njk").getCompiledTemplate( "

{{ name }}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); test("Nunjucks Render Extends", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "{% extends 'base.njk' %}{% block content %}This is a child.{% endblock %}" ); t.is(await fn(), "

This is a child.

"); }); test("Nunjucks Render Relative Extends", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "test/stubs" ).getCompiledTemplate( @@ -31,28 +38,28 @@ test("Nunjucks Render Relative Extends", async t => { }); test("Nunjucks Render Include", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'included.njk' %}

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

This is an include.

"); }); test("Nunjucks Render Include (different extension)", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'included.nunj' %}

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

Nunjabusiness

"); }); test("Nunjucks Render Include (different extension, subdir)", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'subfolder/included.nunj' %}

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

Nunjabusiness2

"); }); test("Nunjucks Render Relative Include Issue #190", async t => { - let tr = new TemplateRender( + let tr = getNewTemplateRender( "./test/stubs/njk-relative/does_not_exist_and_thats_ok.njk", "./test/stubs" ); @@ -63,7 +70,7 @@ test("Nunjucks Render Relative Include Issue #190", async t => { }); test("Nunjucks Render Relative Include (using ..) Issue #190", async t => { - let tr = new TemplateRender( + let tr = getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs" ); @@ -74,7 +81,7 @@ test("Nunjucks Render Relative Include (using ..) Issue #190", async t => { }); test("Nunjucks Render Relative Include (using current dir) Issue #190", async t => { - let tr = new TemplateRender( + let tr = getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs" ); @@ -91,7 +98,7 @@ test("Nunjucks Render Relative Include (using current dir) Issue #190", async t }); test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes and in current dir) Issue #190", async t => { - let tr = new TemplateRender( + let tr = getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs" ); @@ -103,7 +110,7 @@ test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes t.is(await fn(), "

This is an include.

"); // This fails, a leading dot is required for a relative include - // let tr2 = new TemplateRender("./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs"); + // let tr2 = getNewTemplateRender("./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs"); // let fn2 = await tr.getCompiledTemplate( // "

{% include 'unique-include-123.njk' %}

" // ); @@ -111,7 +118,7 @@ test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes }); test("Nunjucks Render Include a JS file (Issue 398)", async t => { - let tr = new TemplateRender("njk", "test/stubs"); + let tr = getNewTemplateRender("njk", "test/stubs"); let engine = tr.engine; engine.addFilters({ jsmin: function(str) { @@ -125,35 +132,35 @@ test("Nunjucks Render Include a JS file (Issue 398)", async t => { }); test("Nunjucks Render Include Subfolder", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'subfolder/included.html' %}

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

This is an include.

"); }); test("Nunjucks Render Include Double Quotes", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( `

{% include "included.njk" %}

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

This is an include.

"); }); test("Nunjucks Render Include Subfolder Double Quotes", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( `

{% include "subfolder/included.html" %}

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

This is an include.

"); }); test("Nunjucks Render Imports", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "{% import 'imports.njk' as forms %}
{{ forms.label('Name') }}
" ); t.is(await fn(), "
"); }); test("Nunjucks Render Relative Imports", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "test/stubs" ).getCompiledTemplate( @@ -163,19 +170,19 @@ test("Nunjucks Render Relative Imports", async t => { }); test("Nunjucks Render Imports From", async t => { - let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( + let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "{% from 'imports.njk' import label %}
{{ label('Name') }}
" ); t.is(await fn(), "
"); }); test("Nunjucks getEngineLib", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); t.truthy(tr.engine.getEngineLib()); }); test("Nunjucks Render: with Library Override", async t => { - let tr = new TemplateRender("njk"); + let tr = getNewTemplateRender("njk"); let lib = require("nunjucks"); let env = new lib.Environment( @@ -188,7 +195,7 @@ test("Nunjucks Render: with Library Override", async t => { }); test("Nunjucks Render with getGlobals Issue #567", async t => { - let tr = new TemplateRender("njk"); + let tr = getNewTemplateRender("njk"); let env = tr.engine.getEngineLib(); env.addGlobal("getGlobals", function() { return this.getVariables(); @@ -201,7 +208,7 @@ test("Nunjucks Render with getGlobals Issue #567", async t => { }); test("Nunjucks Render with getVarByName Filter Issue #567", async t => { - let tr = new TemplateRender("njk"); + let tr = getNewTemplateRender("njk"); let env = tr.engine.getEngineLib(); env.addFilter("getVarByName", function(varName) { return this.getVariables()[varName]; @@ -214,7 +221,7 @@ test("Nunjucks Render with getVarByName Filter Issue #567", async t => { }); test("Nunjucks Shortcode without args", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function() { return "Zach"; }); @@ -223,7 +230,7 @@ test("Nunjucks Shortcode without args", async t => { }); test("Nunjucks Shortcode", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { return str + "Zach"; }); @@ -235,7 +242,7 @@ test("Nunjucks Shortcode", async t => { }); test("Nunjucks Shortcode Safe Output", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { return `${str}`; }); @@ -247,7 +254,7 @@ test("Nunjucks Shortcode Safe Output", async t => { }); test("Nunjucks Paired Shortcode", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { return str + content + "Zach"; }); @@ -262,7 +269,7 @@ test("Nunjucks Paired Shortcode", async t => { }); test("Nunjucks Paired Shortcode without args", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content) { return content + "Zach"; }); @@ -274,7 +281,7 @@ test("Nunjucks Paired Shortcode without args", async t => { }); test("Nunjucks Paired Shortcode with Tag Inside", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { return str + content + "Zach"; }); @@ -289,7 +296,7 @@ test("Nunjucks Paired Shortcode with Tag Inside", async t => { }); test("Nunjucks Nested Paired Shortcode", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { return str + content + "Zach"; }); @@ -304,7 +311,7 @@ test("Nunjucks Nested Paired Shortcode", async t => { }); test("Nunjucks Shortcode Multiple Args", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str, str2) { return str + str2 + "Zach"; }); @@ -319,7 +326,7 @@ test("Nunjucks Shortcode Multiple Args", async t => { }); test("Nunjucks Shortcode Named Args", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { return arg.arg1 + arg.arg2 + "Zach"; }); @@ -334,7 +341,7 @@ test("Nunjucks Shortcode Named Args", async t => { }); test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { return arg.arg1 + arg.arg2 + "Zach"; }); @@ -349,7 +356,7 @@ test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { }); test("Nunjucks Shortcode Named Args (JS notation)", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { return arg.arg1 + arg.arg2 + "Zach"; }); @@ -364,7 +371,7 @@ test("Nunjucks Shortcode Named Args (JS notation)", async t => { }); test("Nunjucks Test if statements on arrays (Issue #524)", async t => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); t.is( await tr.render("{% if 'first' in tags %}Success.{% endif %}", { diff --git a/test/TemplateRenderPugTest.js b/test/TemplateRenderPugTest.js index 5ec9e87ec..5d83675c1 100644 --- a/test/TemplateRenderPugTest.js +++ b/test/TemplateRenderPugTest.js @@ -1,32 +1,39 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} // Pug test("Pug", t => { - t.is(new TemplateRender("pug").getEngineName(), "pug"); + t.is(getNewTemplateRender("pug").getEngineName(), "pug"); }); test("Pug Render", async t => { - let fn = await new TemplateRender("pug").getCompiledTemplate("p= name"); + let fn = await getNewTemplateRender("pug").getCompiledTemplate("p= name"); t.is(await fn({ name: "Zach" }), "

Zach

"); }); test("Pug Render Include (Absolute)", async t => { - let fn = await new TemplateRender("pug", "./test/stubs/") + let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`p include /included.pug`); t.is(await fn({ name: "Zach" }), "

This is an include.

"); }); test("Pug Render Include with Data", async t => { - let fn = await new TemplateRender("pug", "./test/stubs/") + let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`p include /includedvar.pug`); t.is(await fn({ name: "Zach" }), "

This is Zach.

"); }); test("Pug Render Include with Data, inline var overrides data", async t => { - let fn = await new TemplateRender("pug", "./test/stubs/") + let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(` - var name = "Bill"; p @@ -35,7 +42,7 @@ p }); test("Pug Render Extends (Layouts)", async t => { - let fn = await new TemplateRender("pug", "./test/stubs/") + let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`extends /layout.pug block content h1= name`); @@ -43,7 +50,7 @@ block content }); test("Pug Render Extends (Relative, Layouts)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.pug", "./test/stubs/" ).getCompiledTemplate(`extends ./layout-relative.pug @@ -53,14 +60,14 @@ block content }); test("Pug Render Include (Relative)", async t => { - let fn = await new TemplateRender("pug", "./test/stubs/") + let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`p include _includes/included.pug`); t.is(await fn({ name: "Zach" }), "

This is an include.

"); }); test("Pug Render Include (Relative, again)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.pug", "./test/stubs/" ).getCompiledTemplate(`p @@ -72,7 +79,7 @@ test("Pug Render Include (Relative, again)", async t => { }); test("Pug Render Include (Relative, dot slash)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.pug", "./test/stubs/" ).getCompiledTemplate(`p @@ -84,7 +91,7 @@ test("Pug Render Include (Relative, dot slash)", async t => { }); test("Pug Render Include (Relative, dot dot slash)", async t => { - let fn = await new TemplateRender( + let fn = await getNewTemplateRender( "./test/stubs/dir/does_not_exist_and_thats_ok.pug", "./test/stubs/" ).getCompiledTemplate(`p @@ -96,7 +103,7 @@ test("Pug Render Include (Relative, dot dot slash)", async t => { }); test("Pug Options Overrides", async t => { - let tr = new TemplateRender("pug", "./test/stubs/"); + let tr = getNewTemplateRender("pug", "./test/stubs/"); tr.engine.setPugOptions({ testoption: "testoverride" }); let options = tr.engine.getPugOptions(); @@ -104,12 +111,12 @@ test("Pug Options Overrides", async t => { }); test("Pug getEngineLib", async t => { - let tr = new TemplateRender("pug", "./test/stubs/"); + let tr = getNewTemplateRender("pug", "./test/stubs/"); t.truthy(tr.engine.getEngineLib()); }); test("Pug Render: with Library Override", async t => { - let tr = new TemplateRender("pug"); + let tr = getNewTemplateRender("pug"); let lib = require("pug"); tr.engine.setLibrary(lib); @@ -119,7 +126,7 @@ test("Pug Render: with Library Override", async t => { }); test("Pug Filter", async t => { - let tr = new TemplateRender("pug", "./test/stubs/"); + let tr = getNewTemplateRender("pug", "./test/stubs/"); tr.engine.setPugOptions({ filters: { makeUppercase: function(text, options) { @@ -136,7 +143,7 @@ test("Pug Filter", async t => { }); test("Pug Render with Function", async t => { - let fn = await new TemplateRender("pug").getCompiledTemplate("p= name()"); + let fn = await getNewTemplateRender("pug").getCompiledTemplate("p= name()"); t.is( await fn({ name: function() { diff --git a/test/TemplateRenderTest.js b/test/TemplateRenderTest.js index 04502293c..8b4957cf8 100644 --- a/test/TemplateRenderTest.js +++ b/test/TemplateRenderTest.js @@ -1,28 +1,36 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewTemplateRender(name, inputDir) { + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap(); + return tr; +} test("Basic", t => { t.throws(() => { - new TemplateRender("sldkjfkldsj"); + let tr = getNewTemplateRender("sldkjfkldsj"); + tr.init("sldkjfkldsj"); }); }); test("Includes Dir", async t => { t.is( - new TemplateRender("ejs", "./test/stubs").getIncludesDir(), + getNewTemplateRender("ejs", "./test/stubs").getIncludesDir(), "test/stubs/_includes" ); }); test("Invalid override", async t => { - let tr = new TemplateRender("ejs", "./test/stubs"); + let tr = getNewTemplateRender("ejs", "./test/stubs"); t.throws(() => { tr.setEngineOverride("lslkdjf"); }); }); test("Valid Override", async t => { - let tr = new TemplateRender("ejs", "./test/stubs"); + let tr = getNewTemplateRender("ejs", "./test/stubs"); tr.setEngineOverride("njk"); t.is(tr.getEngineName(), "njk"); t.truthy(tr.isEngine("njk")); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index c1d4c7366..1d0c12230 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -5,9 +5,9 @@ import TemplateData from "../src/TemplateData"; import Template from "../src/Template"; import EleventyErrorUtil from "../src/EleventyErrorUtil"; import TemplateContentPrematureUseError from "../src/Errors/TemplateContentPrematureUseError"; -import templateConfig from "../src/Config"; import normalizeNewLines from "./Util/normalizeNewLines"; +import templateConfig from "../src/Config"; const config = templateConfig.getConfig(); function cleanHtml(str) { From b0a717079a17afb9e087ada1980501e587377819 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 11 Jul 2019 22:17:25 -0500 Subject: [PATCH 007/746] Option to use a different default file extension for a template type. --- src/Engines/TemplateEngine.js | 4 ++++ src/Template.js | 3 ++- src/TemplatePermalink.js | 30 +++++++++++++++++++++++------- src/TemplateRender.js | 1 - test/TemplatePermalinkTest.js | 9 +++++++++ 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 1dbf22540..5950237c8 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -118,6 +118,10 @@ class TemplateEngine { initRequireCache(inputPath) { // do nothing } + + get defaultTemplateFileExtension() { + return "html"; + } } module.exports = TemplateEngine; diff --git a/src/Template.js b/src/Template.js index 6e49c4927..731460bc6 100644 --- a/src/Template.js +++ b/src/Template.js @@ -119,7 +119,8 @@ class Template extends TemplateContent { this.getTemplateSubfolder(), this.baseFile, this.extraOutputSubdirectory, - this.htmlIOException ? this.config.htmlOutputSuffix : "" + this.htmlIOException ? this.config.htmlOutputSuffix : "", + this.engine.defaultTemplateFileExtension ); } diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 13f55657a..59433e16d 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -43,14 +43,30 @@ TemplatePermalink._hasDuplicateFolder = function(dir, base) { return folders[folders.length - 1] === base; }; -TemplatePermalink.generate = function(dir, filenameNoExt, extraSubdir, suffix) { +TemplatePermalink.generate = function( + dir, + filenameNoExt, + extraSubdir, + suffix, + fileExtension = "html" +) { let hasDupeFolder = TemplatePermalink._hasDuplicateFolder(dir, filenameNoExt); - let path = - (dir ? dir + "/" : "") + - (filenameNoExt !== "index" && !hasDupeFolder ? filenameNoExt + "/" : "") + - "index" + - (suffix || "") + - ".html"; + let path; + if (fileExtension === "html") { + path = + (dir ? dir + "/" : "") + + (filenameNoExt !== "index" && !hasDupeFolder ? filenameNoExt + "/" : "") + + "index" + + (suffix || "") + + ".html"; + } else { + path = + (dir ? dir + "/" : "") + + filenameNoExt + + (suffix || "") + + "." + + fileExtension; + } return new TemplatePermalink(path, extraSubdir); }; diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 0994f7fce..be4ded189 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -1,7 +1,6 @@ const TemplatePath = require("./TemplatePath"); const TemplateEngineManager = require("./TemplateEngineManager"); const EleventyBaseError = require("./EleventyBaseError"); -const EleventyExtensionMap = require("./EleventyExtensionMap"); const config = require("./Config"); // const debug = require("debug")("Eleventy:TemplateRender"); diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index d2acc5c97..b53275094 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -99,6 +99,15 @@ test("Permalink generate with suffix", t => { t.is(gen(".", "test", "1/", "-o").toHref(), "/test/1/index-o.html"); }); +test("Permalink generate with new extension", t => { + let gen = TemplatePermalink.generate; + + t.is(gen(".", "test", null, null, "css").toString(), "test.css"); + t.is(gen(".", "test", null, null, "css").toHref(), "/test.css"); + t.is(gen(".", "test", "1/", null, "css").toString(), "1/test.css"); + t.is(gen(".", "test", "1/", null, "css").toHref(), "/1/test.css"); +}); + test("Permalink generate with subfolders", t => { let gen = TemplatePermalink.generate; From 5bdc077d4f190b3f491f42e82033fba027d30560 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 11 Jul 2019 22:18:05 -0500 Subject: [PATCH 008/746] Adds sass test and filter option for addExtension --- package.json | 1 + src/EleventyFiles.js | 11 ++++++++ src/Engines/Custom.js | 12 +++++++++ src/UserConfig.js | 16 +++++++----- test/TemplateRenderCustomTest.js | 43 ++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 3d6c86cf3..e2550a69e 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "ava": "^2.1.0", "lint-staged": "^8.2.1", "markdown-it-emoji": "^1.4.0", + "node-sass": "^4.12.0", "nyc": "^14.1.1", "pre-commit": "^1.2.2", "pre-push": "^0.1.1", diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 532c8ddbc..77858c0de 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -298,6 +298,17 @@ class EleventyFiles { dot: true }) ); + + let extensions = this.config.extensionMap; + paths = paths.filter(function(path) { + for (let entry of extensions) { + if (path.endsWith(entry.extension) && entry.filter) { + return entry.filter(path); + } + } + return true; + }); + this.pathCache = paths; return paths; } diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index d9d412e5f..2ea5db556 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -21,6 +21,18 @@ class CustomEngine extends TemplateEngine { // TODO generalize this (look at JavaScript.js) return this.compileFunction(str, inputPath); } + + get defaultTemplateFileExtension() { + for (let entry of this.config.extensionMap) { + if (entry.key.toLowerCase() === this.name.toLowerCase()) { + return entry.outputFileExtension; + } + } + + throw Error( + `Could not find a custom extension for ${this.name}. Did you add it to your config file?` + ); + } } module.exports = CustomEngine; diff --git a/src/UserConfig.js b/src/UserConfig.js index 02cbb999d..7444aa46c 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -492,12 +492,16 @@ class UserConfig { this.frontMatterParsingOptions = options; } - addExtension(fileExtension, userClass) { - this.extensionMap.add({ - key: fileExtension, - extension: fileExtension, - compile: userClass - }); + addExtension(fileExtension, options = {}) { + this.extensionMap.add( + Object.assign( + { + key: fileExtension, + extension: fileExtension + }, + options + ) + ); } getMergingConfigObject() { diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index ca55973e9..a829d99b5 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -55,3 +55,46 @@ test("Custom Vue Render", async t => { let fn = await tr.getCompiledTemplate(`

Paragraph

`); t.is(await fn({ test: "Hello" }), `

Hello

`); }); + +test("Custom Sass Render", async t => { + const sass = require("node-sass"); + let tr = getNewTemplateRender("sass"); + + const config = templateConfig.getConfig(); + tr.config = Object.assign({}, config); + tr.config.extensionMap.add({ + extension: "sass", + key: "sass", + compile: function(str, inputPath) { + // TODO declare data variables as SASS variables? + return async function(data) { + return new Promise(function(resolve, reject) { + sass.render( + { + data: str, + includePaths: [tr.inputDir, tr.includesDir], + style: "expanded", + // TODO + // sourcemap: "file", + outFile: "test_this_is_to_not_write_a_file.css" + }, + function(error, result) { + if (error) { + reject(error); + } else { + resolve(result.css.toString("utf8")); + } + } + ); + }); + }; + } + }); + + let fn = await tr.getCompiledTemplate(`$color: blue; p { color: $color; }`); + t.is( + (await fn({})).trim(), + `p { + color: blue; }` + ); +}); From 1113025ed5175a832e47fcceb96a77b83ba12574 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Jul 2019 08:00:00 -0500 Subject: [PATCH 009/746] Fix tests --- src/EleventyFiles.js | 18 ++++++++++-------- src/Engines/Custom.js | 16 ++++++++++------ test/TemplateRenderLiquidTest.js | 3 ++- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 77858c0de..67aefcd68 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -299,15 +299,17 @@ class EleventyFiles { }) ); - let extensions = this.config.extensionMap; - paths = paths.filter(function(path) { - for (let entry of extensions) { - if (path.endsWith(entry.extension) && entry.filter) { - return entry.filter(path); + if ("extensionMap" in this.config) { + let extensions = this.config.extensionMap; + paths = paths.filter(function(path) { + for (let entry of extensions) { + if (path.endsWith(entry.extension) && entry.filter) { + return entry.filter(path); + } } - } - return true; - }); + return true; + }); + } this.pathCache = paths; return paths; diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 2ea5db556..4c3c665dc 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -6,9 +6,11 @@ class CustomEngine extends TemplateEngine { } get compileFunction() { - for (let entry of this.config.extensionMap) { - if (entry.key.toLowerCase() === this.name.toLowerCase()) { - return entry.compile; + if ("extensionMap" in this.config) { + for (let entry of this.config.extensionMap) { + if (entry.key.toLowerCase() === this.name.toLowerCase()) { + return entry.compile; + } } } @@ -23,9 +25,11 @@ class CustomEngine extends TemplateEngine { } get defaultTemplateFileExtension() { - for (let entry of this.config.extensionMap) { - if (entry.key.toLowerCase() === this.name.toLowerCase()) { - return entry.outputFileExtension; + if ("extensionMap" in this.config) { + for (let entry of this.config.extensionMap) { + if (entry.key.toLowerCase() === this.name.toLowerCase()) { + return entry.outputFileExtension; + } } } diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 953e524d5..0afaa57a2 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -704,7 +704,8 @@ test("Liquid Render with dash variable Issue #567", async t => { t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); -test("Issue 600: Liquid Shortcode, Variable with key argument", async t => { +// Work is Ongoing +test.skip("Issue 600: Liquid Shortcode, Variable with key argument", async t => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue600", function(url) { return url; From 09e5046f07c01057f34348a21c313d190c2eb12e Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Sun, 28 Jul 2019 23:25:36 +0300 Subject: [PATCH 010/746] Implementation of custom data files. Main changes are in TemplateData. User config uses new Map() to store pairs (extension, parser) where parser is a function receiving file contents in string and returning data object. Later declared parsers have priority over first ones. --- src/TemplateData.js | 189 +++++++++++++++++++++++++++++++++----------- src/UserConfig.js | 10 ++- 2 files changed, 152 insertions(+), 47 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 06912f8f5..008925a5a 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -110,10 +110,19 @@ class TemplateData { async getTemplateDataFileGlob() { let dir = await this.getInputDir(); - return TemplatePath.addLeadingDotSlashArray([ + let paths = [ `${dir}/**/*.json`, // covers .11tydata.json too `${dir}/**/*${this.config.jsDataFileSuffix}.js` - ]); + ]; + + if (this.hasUserDataExtensions()) { + let userPaths = this.getUserDataExtensions().map( + extension => `${dir}/**/*.${extension}` // covers .11tydata.{extension} too + ); + paths = userPaths.concat(paths); + } + + return TemplatePath.addLeadingDotSlashArray(paths); } async getTemplateJavaScriptDataFileGlob() { @@ -125,7 +134,15 @@ class TemplateData { async getGlobalDataGlob() { let dir = await this.getInputDir(); - return [this._getGlobalDataGlobByExtension(dir, "(json|js)")]; + let userExtensions = ""; + // creating glob string for user extensions + if (this.hasUserDataExtensions()) { + userExtensions = this.getUserDataExtensions().join("|") + "|"; + } + + return [ + this._getGlobalDataGlobByExtension(dir, "(" + userExtensions + "json|js)") + ]; } getWatchPathCache() { @@ -156,6 +173,7 @@ class TemplateData { let files = TemplatePath.addLeadingDotSlashArray( await this.getGlobalDataFiles() ); + let dataFileConflicts = {}; for (let j = 0, k = files.length; j < k; j++) { @@ -217,7 +235,31 @@ class TemplateData { return localData; } - async _getLocalJsonString(path) { + getUserDataExtensions() { + if (!this.config.dataExtensions) { + return []; + } + + // returning extensions in reverse order to create proper extension order + // later added formats will override first ones + return Array.from(this.config.dataExtensions.keys()).reverse(); + } + + getUserDataParser(extension) { + return this.config.dataExtensions.get(extension); + } + + isUserDataExtension(extension) { + return ( + this.config.dataExtensions && this.config.dataExtensions.has(extension) + ); + } + + hasUserDataExtensions() { + return this.config.dataExtensions && this.config.dataExtensions.size > 0; + } + + async _loadFileContents(path) { let rawInput; try { rawInput = await fs.readFile(path, "utf-8"); @@ -227,56 +269,78 @@ class TemplateData { return rawInput; } + async _parseDataFile(path, rawImports, ignoreProcessing, parser) { + let rawInput = await this._loadFileContents(path); + let engineName = this.dataTemplateEngine; + + if (!rawInput) { + return {}; + } + + if (ignoreProcessing || engineName === false) { + try { + return parser(rawInput); + } catch (e) { + throw new TemplateDataParseError( + `Having trouble parsing data file ${path}`, + e + ); + } + } else { + let fn = await new TemplateRender(engineName).getCompiledTemplate( + rawInput + ); + + try { + // pass in rawImports, don’t pass in global data, that’s what we’re parsing + let raw = await fn(rawImports); + return parser(raw); + } catch (e) { + throw new TemplateDataParseError( + `Having trouble parsing data file ${path}`, + e + ); + } + } + } + async getDataValue(path, rawImports, ignoreProcessing) { - if (ignoreProcessing || TemplatePath.getExtension(path) === "js") { - let localPath = TemplatePath.absolutePath(path); - if (await fs.pathExists(localPath)) { - let dataBench = bench.get(`\`${path}\``); - dataBench.before(); - delete require.cache[localPath]; - let returnValue = require(localPath); - if (typeof returnValue === "function") { - returnValue = await returnValue(); - } + let extension = TemplatePath.getExtension(path); - dataBench.after(); - return returnValue; - } else { + if ((ignoreProcessing && extension === "json") || extension === "js") { + let localPath = TemplatePath.absolutePath(path); + if (!(await fs.pathExists(localPath))) { return {}; } - } else { - let rawInput = await this._getLocalJsonString(path); - let engineName = this.dataTemplateEngine; - - if (rawInput) { - if (ignoreProcessing || engineName === false) { - try { - return JSON.parse(rawInput); - } catch (e) { - throw new TemplateDataParseError( - `Having trouble parsing data file ${path}`, - e - ); - } - } else { - let fn = await new TemplateRender(engineName).getCompiledTemplate( - rawInput - ); - try { - // pass in rawImports, don’t pass in global data, that’s what we’re parsing - return JSON.parse(await fn(rawImports)); - } catch (e) { - throw new TemplateDataParseError( - `Having trouble parsing data file ${path}`, - e - ); - } - } + let dataBench = bench.get(`\`${path}\``); + dataBench.before(); + delete require.cache[localPath]; + + let returnValue = require(localPath); + if (typeof returnValue === "function") { + returnValue = await returnValue(); } + + dataBench.after(); + return returnValue; + } else if (this.isUserDataExtension(extension)) { + var parser = this.getUserDataParser(extension); + return this._parseDataFile(path, rawImports, ignoreProcessing, parser); + } else { + return this._parseDataFile( + path, + rawImports, + ignoreProcessing, + JSON.parse + ); } + } - return {}; + _pushExtensionsToPaths(paths, curpath, extensions) { + for (let extension of extensions) { + paths.push(curpath + "." + extension); + } } async getLocalDataPaths(templatePath) { @@ -285,19 +349,34 @@ class TemplateData { let inputDir = TemplatePath.addLeadingDotSlash( TemplatePath.normalize(this.inputDir) ); + debugDev("getLocalDataPaths(%o)", templatePath); debugDev("parsed.dir: %o", parsed.dir); + let userExtensions = this.getUserDataExtensions(); + if (parsed.dir) { let fileNameNoExt = EleventyExtensionMap.removeTemplateExtension( parsed.base ); + let filePathNoExt = parsed.dir + "/" + fileNameNoExt; let dataSuffix = this.config.jsDataFileSuffix; debug("Using %o to find data files.", dataSuffix); + + // data suffix paths.push(filePathNoExt + dataSuffix + ".js"); paths.push(filePathNoExt + dataSuffix + ".json"); + // inject user extensions + this._pushExtensionsToPaths( + paths, + filePathNoExt + dataSuffix, + userExtensions + ); + + // top level paths.push(filePathNoExt + ".json"); + this._pushExtensionsToPaths(paths, filePathNoExt, userExtensions); let allDirs = TemplatePath.getAllDirs(parsed.dir); debugDev("allDirs: %o", allDirs); @@ -306,15 +385,33 @@ class TemplateData { let dirPathNoExt = dir + "/" + lastDir; if (!inputDir) { + // data suffix paths.push(dirPathNoExt + dataSuffix + ".js"); paths.push(dirPathNoExt + dataSuffix + ".json"); + this._pushExtensionsToPaths( + paths, + dirPathNoExt + dataSuffix, + userExtensions + ); + + // top level paths.push(dirPathNoExt + ".json"); + this._pushExtensionsToPaths(paths, dirPathNoExt, userExtensions); } else { debugDev("dirStr: %o; inputDir: %o", dir, inputDir); if (dir.indexOf(inputDir) === 0 && dir !== inputDir) { + // data suffix paths.push(dirPathNoExt + dataSuffix + ".js"); paths.push(dirPathNoExt + dataSuffix + ".json"); + this._pushExtensionsToPaths( + paths, + dirPathNoExt + dataSuffix, + userExtensions + ); + + // top level paths.push(dirPathNoExt + ".json"); + this._pushExtensionsToPaths(paths, dirPathNoExt, userExtensions); } } } diff --git a/src/UserConfig.js b/src/UserConfig.js index bf97e89b5..05b029a34 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -54,6 +54,9 @@ class UserConfig { // this.templateExtensionAliases = {}; this.watchJavaScriptDependencies = true; this.browserSyncConfig = {}; + + // using Map to preserve insertion order + this.dataExtensions = new Map(); } versionCheck(expected) { @@ -537,13 +540,18 @@ class UserConfig { // templateExtensionAliases: this.templateExtensionAliases, watchJavaScriptDependencies: this.watchJavaScriptDependencies, browserSyncConfig: this.browserSyncConfig, - frontMatterParsingOptions: this.frontMatterParsingOptions + frontMatterParsingOptions: this.frontMatterParsingOptions, + dataExtensions: this.dataExtensions }; } // addExtension(fileExtension, userClass) { // this.userExtensionMap[ fileExtension ] = userClass; // } + + addDataExtension(formatExtension, formatParser) { + this.dataExtensions.set(formatExtension, formatParser); + } } module.exports = UserConfig; From a948bc852791b869ba58320b76f8f648e3304483 Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Sun, 28 Jul 2019 23:29:32 +0300 Subject: [PATCH 011/746] Tests for user data hooks. Tests are placed in separate file. All test data are in test/stubs-630/. Tests are focused on loading local and global custom data (yaml and nosj) and checking format priority order. From top to bottom it must be js-json-nosj-yaml, in the case where nosj declared after yaml (nosj is a simple JSON file) js-yaml added to devDependencies --- package.json | 5 +- test/UserDataExtensionsTest.js | 92 +++++++++++++++++++ test/stubs-630/_data/globalData0.js | 3 + test/stubs-630/_data/globalData1.json | 4 + test/stubs-630/_data/globalData2.yaml | 2 + test/stubs-630/_data/globalData3.nosj | 4 + .../_data/subdir/globalDataSubdir.yaml | 1 + .../component-yaml/component.11tydata.js | 3 + .../component-yaml/component.11tydata.json | 3 + .../component-yaml/component.11tydata.nosj | 3 + .../component-yaml/component.11tydata.yaml | 5 + test/stubs-630/component-yaml/component.json | 5 + test/stubs-630/component-yaml/component.njk | 1 + test/stubs-630/component-yaml/component.yaml | 5 + 14 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 test/UserDataExtensionsTest.js create mode 100644 test/stubs-630/_data/globalData0.js create mode 100644 test/stubs-630/_data/globalData1.json create mode 100644 test/stubs-630/_data/globalData2.yaml create mode 100644 test/stubs-630/_data/globalData3.nosj create mode 100644 test/stubs-630/_data/subdir/globalDataSubdir.yaml create mode 100644 test/stubs-630/component-yaml/component.11tydata.js create mode 100644 test/stubs-630/component-yaml/component.11tydata.json create mode 100644 test/stubs-630/component-yaml/component.11tydata.nosj create mode 100644 test/stubs-630/component-yaml/component.11tydata.yaml create mode 100644 test/stubs-630/component-yaml/component.json create mode 100644 test/stubs-630/component-yaml/component.njk create mode 100644 test/stubs-630/component-yaml/component.yaml diff --git a/package.json b/package.json index 4e5dd1357..63a36cc6f 100755 --- a/package.json +++ b/package.json @@ -78,7 +78,8 @@ "toml": "^3.0.0", "viperhtml": "^2.17.0", "vue": "^2.6.10", - "vue-server-renderer": "^2.6.10" + "vue-server-renderer": "^2.6.10", + "js-yaml": "^3.13.1" }, "dependencies": { "browser-sync": "^2.26.7", @@ -116,4 +117,4 @@ }, "pre-commit": "lint-staged", "pre-push": "test" -} \ No newline at end of file +} diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js new file mode 100644 index 000000000..fa5cc1e62 --- /dev/null +++ b/test/UserDataExtensionsTest.js @@ -0,0 +1,92 @@ +import test from "ava"; +import TemplateData from "../src/TemplateData"; +let yaml = require("js-yaml"); + +function injectDataExtensions(dataObj) { + dataObj.config.dataExtensions = new Map([ + ["yaml", s => yaml.safeLoad(s)], + ["nosj", JSON.parse] + ]); +} + +test("Local data", async t => { + let dataObj = new TemplateData("./test/stubs-630/"); + injectDataExtensions(dataObj); + + let data = await dataObj.getData(); + + // YAML GLOBAL DATA + t.is(data.globalData2.datakey1, "datavalue2"); + t.is(data.globalData2.datakey2, "@11ty/eleventy--yaml"); + + // NOSJ (JSON) GLOBAL DATA + t.is(data.globalData3.datakey1, "datavalue3"); + t.is(data.globalData3.datakey2, "@11ty/eleventy--nosj"); + + let withLocalData = await dataObj.getLocalData( + "./test/stubs-630/component-yaml/component.njk" + ); + // console.log("localdata", withLocalData); + + t.is(withLocalData.yamlKey1, "yaml1"); + t.is(withLocalData.yamlKey2, "yaml2"); + t.is(withLocalData.yamlKey3, "yaml3"); + t.is(withLocalData.nosjKey1, "nosj1"); + t.is(withLocalData.jsonKey1, "json1"); + t.is(withLocalData.jsonKey2, "json2"); + t.is(withLocalData.jsKey1, "js1"); +}); + +test("Local files", async t => { + let dataObj = new TemplateData("./test/stubs-630/"); + injectDataExtensions(dataObj); + let files = await dataObj.getLocalDataPaths( + "./test/stubs-630/component-yaml/component.njk" + ); + t.deepEqual(files, [ + "./test/stubs-630/component-yaml/component-yaml.yaml", + "./test/stubs-630/component-yaml/component-yaml.nosj", + "./test/stubs-630/component-yaml/component-yaml.json", + "./test/stubs-630/component-yaml/component-yaml.11tydata.yaml", + "./test/stubs-630/component-yaml/component-yaml.11tydata.nosj", + "./test/stubs-630/component-yaml/component-yaml.11tydata.json", + "./test/stubs-630/component-yaml/component-yaml.11tydata.js", + "./test/stubs-630/component-yaml/component.yaml", + "./test/stubs-630/component-yaml/component.nosj", + "./test/stubs-630/component-yaml/component.json", + "./test/stubs-630/component-yaml/component.11tydata.yaml", + "./test/stubs-630/component-yaml/component.11tydata.nosj", + "./test/stubs-630/component-yaml/component.11tydata.json", + "./test/stubs-630/component-yaml/component.11tydata.js" + ]); +}); + +test("Global data", async t => { + let dataObj = new TemplateData("./test/stubs-630/"); + + injectDataExtensions(dataObj); + + t.deepEqual(await dataObj.getGlobalDataGlob(), [ + "./test/stubs-630/_data/**/*.(nosj|yaml|json|js)" + ]); + + let dataFilePaths = await dataObj.getGlobalDataFiles(); + let data = await dataObj.getData(); + + // JS GLOBAL DATA + t.is(data.globalData0.datakey1, "datavalue0"); + + // JSON GLOBAL DATA + t.is(data.globalData1.datakey1, "datavalue1"); + t.is(data.globalData1.datakey2, "@11ty/eleventy--json"); + + // YAML GLOBAL DATA + t.is(data.globalData2.datakey1, "datavalue2"); + t.is(data.globalData2.datakey2, "@11ty/eleventy--yaml"); + + // NOSJ (JSON) GLOBAL DATA + t.is(data.globalData3.datakey1, "datavalue3"); + t.is(data.globalData3.datakey2, "@11ty/eleventy--nosj"); + + t.is(data.subdir.globalDataSubdir.keyyaml, "yaml"); +}); diff --git a/test/stubs-630/_data/globalData0.js b/test/stubs-630/_data/globalData0.js new file mode 100644 index 000000000..4f79aca51 --- /dev/null +++ b/test/stubs-630/_data/globalData0.js @@ -0,0 +1,3 @@ +module.exports = { + datakey1: "datavalue0" +}; diff --git a/test/stubs-630/_data/globalData1.json b/test/stubs-630/_data/globalData1.json new file mode 100644 index 000000000..5f02feff3 --- /dev/null +++ b/test/stubs-630/_data/globalData1.json @@ -0,0 +1,4 @@ +{ + "datakey1": "datavalue1", + "datakey2": "{{pkg.name}}--json" +} diff --git a/test/stubs-630/_data/globalData2.yaml b/test/stubs-630/_data/globalData2.yaml new file mode 100644 index 000000000..9a852bfa8 --- /dev/null +++ b/test/stubs-630/_data/globalData2.yaml @@ -0,0 +1,2 @@ +datakey1: datavalue2 +datakey2: "{{pkg.name}}--yaml" diff --git a/test/stubs-630/_data/globalData3.nosj b/test/stubs-630/_data/globalData3.nosj new file mode 100644 index 000000000..3f01a07ea --- /dev/null +++ b/test/stubs-630/_data/globalData3.nosj @@ -0,0 +1,4 @@ +{ + "datakey1": "datavalue3", + "datakey2": "{{pkg.name}}--nosj" +} diff --git a/test/stubs-630/_data/subdir/globalDataSubdir.yaml b/test/stubs-630/_data/subdir/globalDataSubdir.yaml new file mode 100644 index 000000000..7e610b578 --- /dev/null +++ b/test/stubs-630/_data/subdir/globalDataSubdir.yaml @@ -0,0 +1 @@ +keyyaml: "yaml" diff --git a/test/stubs-630/component-yaml/component.11tydata.js b/test/stubs-630/component-yaml/component.11tydata.js new file mode 100644 index 000000000..f8e5b9878 --- /dev/null +++ b/test/stubs-630/component-yaml/component.11tydata.js @@ -0,0 +1,3 @@ +module.exports = { + jsKey1: "js1" +}; diff --git a/test/stubs-630/component-yaml/component.11tydata.json b/test/stubs-630/component-yaml/component.11tydata.json new file mode 100644 index 000000000..0af98b490 --- /dev/null +++ b/test/stubs-630/component-yaml/component.11tydata.json @@ -0,0 +1,3 @@ +{ + "jsonKey1": "json1" +} diff --git a/test/stubs-630/component-yaml/component.11tydata.nosj b/test/stubs-630/component-yaml/component.11tydata.nosj new file mode 100644 index 000000000..76bc8b93e --- /dev/null +++ b/test/stubs-630/component-yaml/component.11tydata.nosj @@ -0,0 +1,3 @@ +{ + "nosjKey1": "nosj1" +} diff --git a/test/stubs-630/component-yaml/component.11tydata.yaml b/test/stubs-630/component-yaml/component.11tydata.yaml new file mode 100644 index 000000000..b61c3866f --- /dev/null +++ b/test/stubs-630/component-yaml/component.11tydata.yaml @@ -0,0 +1,5 @@ +yamlKey2: "yaml2" +yamlKey3: "yaml3" +jsonKey1: "overriden" +jsKey1: "overriden" +nosjKey1: "overriden" diff --git a/test/stubs-630/component-yaml/component.json b/test/stubs-630/component-yaml/component.json new file mode 100644 index 000000000..21e49a8ce --- /dev/null +++ b/test/stubs-630/component-yaml/component.json @@ -0,0 +1,5 @@ +{ + "jsonKey2": "json2", + "jsKey1": "overriden", + "yamlKey3": "overriden" +} diff --git a/test/stubs-630/component-yaml/component.njk b/test/stubs-630/component-yaml/component.njk new file mode 100644 index 000000000..4772f7452 --- /dev/null +++ b/test/stubs-630/component-yaml/component.njk @@ -0,0 +1 @@ +{{localkeyOverride}} \ No newline at end of file diff --git a/test/stubs-630/component-yaml/component.yaml b/test/stubs-630/component-yaml/component.yaml new file mode 100644 index 000000000..f65aadd9d --- /dev/null +++ b/test/stubs-630/component-yaml/component.yaml @@ -0,0 +1,5 @@ +yamlKey1: "yaml1" +yamlKey2: "overriden" +jsonKey1: "overriden" +jsonKey2: "overriden" +jsKey1: "overriden" From 66144f159f4fd91fa0685c6dffb544d0b427b680 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 Aug 2019 08:30:23 +1000 Subject: [PATCH 012/746] Add custom watch target option to config --- src/Eleventy.js | 1 + src/TemplateConfig.js | 1 - src/UserConfig.js | 10 +- test/TemplateConfigTest.js | 22 +- yarn.lock | 6888 ++++++++++++++++++++++++++++++++++++ 5 files changed, 6912 insertions(+), 10 deletions(-) create mode 100644 yarn.lock diff --git a/src/Eleventy.js b/src/Eleventy.js index ad3e92a78..7a6495d1b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -27,6 +27,7 @@ class Eleventy { this.rawOutput = output; this.watchTargets = new EleventyWatchTargets(); + this.watchTargets.add(this.config.additionalWatchTargets); this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; } diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index b605df888..0e77f73b6 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -3,7 +3,6 @@ const chalk = require("chalk"); const lodashMerge = require("lodash/merge"); const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); -const dependencyTree = require("dependency-tree"); const eleventyConfig = require("./EleventyConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); diff --git a/src/UserConfig.js b/src/UserConfig.js index c65e2dd53..2fb82a565 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -53,15 +53,14 @@ class UserConfig { // this.userExtensionMap = {}; // this.templateExtensionAliases = {}; this.watchJavaScriptDependencies = true; + this.additionalWatchTargets = []; this.browserSyncConfig = {}; } versionCheck(expected) { if (!semver.satisfies(pkg.version, expected)) { throw new UserConfigError( - `This project requires the eleventy version to match '${expected}' but found ${ - pkg.version - }. Use \`npm update @11ty/eleventy -g\` to upgrade the eleventy global or \`npm update @11ty/eleventy --save\` to upgrade your local project version.` + `This project requires the eleventy version to match '${expected}' but found ${pkg.version}. Use \`npm update @11ty/eleventy -g\` to upgrade the eleventy global or \`npm update @11ty/eleventy --save\` to upgrade your local project version.` ); } } @@ -495,6 +494,10 @@ class UserConfig { // this.templateExtensionAliases[extension] = targetKey; // } + addWatchTarget(additionalWatchTargets) { + this.additionalWatchTargets.push(additionalWatchTargets); + } + setWatchJavaScriptDependencies(watchEnabled) { this.watchJavaScriptDependencies = !!watchEnabled; } @@ -534,6 +537,7 @@ class UserConfig { experiments: this.experiments, // templateExtensionAliases: this.templateExtensionAliases, watchJavaScriptDependencies: this.watchJavaScriptDependencies, + additionalWatchTargets: this.additionalWatchTargets, browserSyncConfig: this.browserSyncConfig }; } diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index f7231d86c..488ff9ea4 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -312,10 +312,20 @@ test("libraryOverrides", t => { }); test("Properly throws error on missing module #182", t => { - t.throws(function() { - new TemplateConfig( - require("../config.js"), - "./test/stubs/broken-config.js" - ); - }); + let templateCfg = new TemplateConfig( + require("../config.js"), + "./test/stubs/config.js" + ); +}); + +test(".addWatchTarget adds a watch target", t => { + eleventyConfig.reset(); + eleventyConfig.addWatchTarget("/testdirectory/"); + + let templateCfg = new TemplateConfig( + require("../config.js"), + "./test/stubs/config.js" + ); + let cfg = templateCfg.getConfig(); + t.deepEqual(cfg.additionalWatchTargets, ["/testdirectory/"]); }); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..9e4983929 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,6888 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@11ty/eleventy-plugin-syntaxhighlight@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@11ty/eleventy-plugin-syntaxhighlight/-/eleventy-plugin-syntaxhighlight-2.0.3.tgz#49193015d1bf561926ebd93c14800d83de27d752" + integrity sha512-tPoNaEawOG1kkOYAvr4fwKaMOXRhNueOH7z5aepA0vjfnGCagUlSbUipvjCcUUOf+nQgfJYW2rwR2g97Vv8/rg== + dependencies: + prismjs "^1.15.0" + +"@ava/babel-plugin-throws-helper@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-3.0.0.tgz#2c933ec22da0c4ce1fc5369f2b95452c70420586" + integrity sha512-mN9UolOs4WX09QkheU1ELkVy2WPnwonlO3XMdN8JF8fQqRVgVTR21xDbvEOUsbwz6Zwjq7ji9yzyjuXqDPalxg== + +"@ava/babel-preset-stage-4@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-3.0.0.tgz#32c46b22b640d1ba0c6e38ae4abd58efab965558" + integrity sha512-uI5UBx++UsckkfnbF0HH6jvTIvM4r/Kxt1ROO2YXKu5H15sScAtxUIAHiUVbPIw24zPqz/PlF3xxlIDuyFzlQw== + dependencies: + "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-transform-dotall-regex" "^7.4.3" + "@babel/plugin-transform-modules-commonjs" "^7.4.3" + +"@ava/babel-preset-transform-test-files@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-5.0.0.tgz#e06fc762069511e597531cc1120e22216aac6981" + integrity sha512-rqgyQwkT0+j2JzYP51dOv80u33rzAvjBtXRzUON+7+6u26mjoudRXci2+1s18rat8r4uOlZfbzm114YS6pwmYw== + dependencies: + "@ava/babel-plugin-throws-helper" "^3.0.0" + babel-plugin-espower "^3.0.1" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/core@^7.5.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" + integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.5.5" + "@babel/helpers" "^7.5.5" + "@babel/parser" "^7.5.5" + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.5.5" + "@babel/types" "^7.5.5" + convert-source-map "^1.1.0" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.0.0", "@babel/generator@^7.4.0", "@babel/generator@^7.5.0", "@babel/generator@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" + integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== + dependencies: + "@babel/types" "^7.5.5" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + trim-right "^1.0.1" + +"@babel/helper-annotate-as-pure@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" + integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-function-name@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" + integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== + dependencies: + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-get-function-arity@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" + integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-module-imports@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" + integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-module-transforms@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" + integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/template" "^7.4.4" + "@babel/types" "^7.5.5" + lodash "^4.17.13" + +"@babel/helper-plugin-utils@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" + integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== + +"@babel/helper-regex@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" + integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-wrap-function" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-simple-access@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" + integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== + dependencies: + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-split-export-declaration@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" + integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== + dependencies: + "@babel/types" "^7.4.4" + +"@babel/helper-wrap-function@^7.1.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" + integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.2.0" + +"@babel/helpers@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" + integrity sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g== + dependencies: + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.5.5" + "@babel/types" "^7.5.5" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.0.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" + integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== + +"@babel/plugin-proposal-async-generator-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" + integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" + integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" + integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" + integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-dotall-regex@^7.4.3": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" + integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" + +"@babel/plugin-transform-modules-commonjs@^7.4.3": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74" + integrity sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ== + dependencies: + "@babel/helper-module-transforms" "^7.4.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/runtime@^7.0.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" + integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" + integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.4.4" + "@babel/types" "^7.4.4" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" + integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.5.5" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.5.5" + "@babel/types" "^7.5.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" + integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@concordance/react@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@concordance/react/-/react-2.0.0.tgz#aef913f27474c53731f4fd79cc2f54897de90fde" + integrity sha512-huLSkUuM2/P+U0uy2WwlKuixMsTODD8p4JVQBI4VKeopkiN0C7M3N9XYVawb4M+4spN5RrO/eLhk7KoQX6nsfA== + dependencies: + arrify "^1.0.1" + +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.scandir@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" + integrity sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg== + dependencies: + "@nodelib/fs.stat" "2.0.1" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.1", "@nodelib/fs.stat@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz#814f71b1167390cfcb6a6b3d9cdeb0951a192c14" + integrity sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw== + +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + +"@nodelib/fs.walk@^1.2.1": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz#6a6450c5e17012abd81450eb74949a4d970d2807" + integrity sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ== + dependencies: + "@nodelib/fs.scandir" "2.1.1" + fastq "^1.6.0" + +"@samverschueren/stream-to-observable@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" + integrity sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg== + dependencies: + any-observable "^0.3.0" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@types/babel-types@*", "@types/babel-types@^7.0.0": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.7.tgz#667eb1640e8039436028055737d2b9986ee336e3" + integrity sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ== + +"@types/babylon@^6.16.2": + version "6.16.5" + resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.5.tgz#1c5641db69eb8cdf378edd25b4be7754beeb48b4" + integrity sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w== + dependencies: + "@types/babel-types" "*" + +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*": + version "12.6.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.9.tgz#ffeee23afdc19ab16e979338e7b536fdebbbaeaf" + integrity sha512-+YB9FtyxXGyD54p8rXwWaN1EWEyar5L58GlGWgtH2I9rGmLGBQcw63+0jw+ujqVavNuO47S1ByAjm9zdHMnskw== + +a-sync-waterfall@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" + integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +accepts@~1.3.4: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-globals@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" + integrity sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8= + dependencies: + acorn "^4.0.4" + +acorn@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= + +acorn@^4.0.4, acorn@~4.0.2: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= + +after@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" + integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + +ansi-escapes@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.2.1.tgz#4dccdb846c3eee10f6d64dea66273eab90c37228" + integrity sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q== + dependencies: + type-fest "^0.5.2" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.0.0.tgz#f6b84e8fc97ea7add7a53b7530ef28f3fde0e048" + integrity sha512-8zjUtFJ3db/QoPXuuEMloS2AUf79/yeyttJ7Abr3hteopJu9HK8vsgGviGUMq+zyA6cZZO6gAyZoMTF6TgaEjA== + dependencies: + color-convert "^2.0.0" + +ansi-styles@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" + integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg= + +any-observable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" + integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.0.3.tgz#2fb624fe0e84bccab00afee3d0006ed310f22f09" + integrity sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +app-module-path@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= + +append-transform@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" + integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== + dependencies: + default-require-extensions "^2.0.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= + +array-differ@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1" + integrity sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w== + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + +array-union@^1.0.1, array-union@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-uniq@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-2.1.0.tgz#46603d5e28e79bfd02b046fcc1d77c6820bd8e98" + integrity sha512-bdHxtev7FN6+MXI1YFW0Q8mQ8dTJc2S8AMfju+ZR77pbg2yAdVyDlwkaUI7Har0LyOMRFPHrJ9lYdyjZZswdlQ== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arraybuffer.slice@~0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" + integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== + +arrify@^1.0.0, arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + +asap@^2.0.3, asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +ast-module-types@^2.3.1, ast-module-types@^2.3.2, ast-module-types@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-2.5.0.tgz#44b8bcd51684329a77f2af6b2587df9ea6b4d5ff" + integrity sha512-dP6vhvatex3Q+OThhvcyGRvHn4noQBg1b8lCNKUAFL05up80hr2pAExveU3YQNDGMhfNPhQit/vzIkkvBPbSXw== + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-each-series@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/async-each-series/-/async-each-series-0.1.1.tgz#7617c1917401fd8ca4a28aadce3dbae98afeb432" + integrity sha1-dhfBkXQB/Yykooqtzj266Yr+tDI= + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + +async@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +ava@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ava/-/ava-2.2.0.tgz#5a7d799c2c8cc5926f95d2b76bdfe6081fe9a4f8" + integrity sha512-lROj3eQ8L4ZjfiN5P8UGekEQLfKmseGMtat6pUOHgJLEb2K1kT0ZpR/IlWwuytjvwO6nZpzpD+QsTW/XiayIgg== + dependencies: + "@ava/babel-preset-stage-4" "^3.0.0" + "@ava/babel-preset-transform-test-files" "^5.0.0" + "@babel/core" "^7.5.0" + "@babel/generator" "^7.5.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@concordance/react" "^2.0.0" + ansi-escapes "^4.2.0" + ansi-styles "^4.0.0" + arr-flatten "^1.1.0" + array-union "^2.1.0" + array-uniq "^2.1.0" + arrify "^2.0.1" + bluebird "^3.5.5" + chalk "^2.4.2" + chokidar "^3.0.2" + chunkd "^1.0.0" + ci-parallel-vars "^1.0.0" + clean-stack "^2.1.0" + clean-yaml-object "^0.1.0" + cli-cursor "^3.1.0" + cli-truncate "^2.0.0" + code-excerpt "^2.1.1" + common-path-prefix "^1.0.0" + concordance "^4.0.0" + convert-source-map "^1.6.0" + currently-unhandled "^0.4.1" + debug "^4.1.1" + del "^4.1.1" + dot-prop "^5.1.0" + emittery "^0.4.1" + empower-core "^1.2.0" + equal-length "^1.0.0" + escape-string-regexp "^2.0.0" + esm "^3.2.25" + figures "^3.0.0" + find-up "^4.1.0" + get-port "^5.0.0" + globby "^10.0.1" + ignore-by-default "^1.0.0" + import-local "^3.0.1" + indent-string "^4.0.0" + is-ci "^2.0.0" + is-error "^2.2.2" + is-observable "^2.0.0" + is-plain-object "^3.0.0" + is-promise "^2.1.0" + lodash "^4.17.11" + loud-rejection "^2.1.0" + make-dir "^3.0.0" + matcher "^2.0.0" + md5-hex "^3.0.0" + meow "^5.0.0" + micromatch "^4.0.2" + ms "^2.1.2" + observable-to-promise "^1.0.0" + ora "^3.4.0" + package-hash "^4.0.0" + pkg-conf "^3.1.0" + plur "^3.1.1" + pretty-ms "^5.0.0" + require-precompiled "^0.1.0" + resolve-cwd "^3.0.0" + slash "^3.0.0" + source-map-support "^0.5.12" + stack-utils "^1.0.2" + strip-ansi "^5.2.0" + strip-bom-buf "^2.0.0" + supertap "^1.0.0" + supports-color "^7.0.0" + trim-off-newlines "^1.0.1" + trim-right "^1.0.1" + unique-temp-dir "^1.0.0" + update-notifier "^3.0.1" + write-file-atomic "^3.0.0" + +axios@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" + integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== + dependencies: + follow-redirects "1.5.10" + is-buffer "^2.0.2" + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" + integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-espower@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-espower/-/babel-plugin-espower-3.0.1.tgz#180db17126f88e754105b8b5216d21e520a6bd4e" + integrity sha512-Ms49U7VIAtQ/TtcqRbD6UBmJBUCSxiC3+zPc+eGqxKUIFO1lTshyEDRUjhoAbd2rWfwYf3cZ62oXozrd8W6J0A== + dependencies: + "@babel/generator" "^7.0.0" + "@babel/parser" "^7.0.0" + call-matcher "^1.0.0" + core-js "^2.0.0" + espower-location-detector "^1.0.0" + espurify "^1.6.0" + estraverse "^4.1.1" + +babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backo2@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-arraybuffer@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" + integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= + +base64id@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" + integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + +better-assert@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" + integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= + dependencies: + callsite "1.0.0" + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + +blob@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" + integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== + +bluebird@^3.5.5: + version "3.5.5" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" + integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== + +blueimp-md5@^2.10.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.11.0.tgz#eff55d30fe3daddd7e801072e2c4483e5fcfc87c" + integrity sha512-xvA4mdnIevstCvNKTRLMOKi7L76U/X/CTs9Yz+PLWmWAC/7SuYi5Xv2J7bAhJnE2+LcLv+x4+0vusvKgM9LnZQ== + +boxen@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" + integrity sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^2.4.2" + cli-boxes "^2.2.0" + string-width "^3.0.0" + term-size "^1.2.0" + type-fest "^0.3.0" + widest-line "^2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1, braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-sync-client@^2.26.6: + version "2.26.6" + resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.26.6.tgz#e5201d3ace8aee88af17656b7b0c0620b6f8e4ab" + integrity sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw== + dependencies: + etag "1.8.1" + fresh "0.5.2" + mitt "^1.1.3" + rxjs "^5.5.6" + +browser-sync-ui@^2.26.4: + version "2.26.4" + resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz#3772f13c6b93f2d7d333f4be0ca1ec02aae97dba" + integrity sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA== + dependencies: + async-each-series "0.1.1" + connect-history-api-fallback "^1" + immutable "^3" + server-destroy "1.0.1" + socket.io-client "^2.0.4" + stream-throttle "^0.1.3" + +browser-sync@^2.26.7: + version "2.26.7" + resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.26.7.tgz#120287716eb405651a76cc74fe851c31350557f9" + integrity sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w== + dependencies: + browser-sync-client "^2.26.6" + browser-sync-ui "^2.26.4" + bs-recipes "1.3.4" + bs-snippet-injector "^2.0.1" + chokidar "^2.0.4" + connect "3.6.6" + connect-history-api-fallback "^1" + dev-ip "^1.0.1" + easy-extender "^2.3.4" + eazy-logger "^3" + etag "^1.8.1" + fresh "^0.5.2" + fs-extra "3.0.1" + http-proxy "1.15.2" + immutable "^3" + localtunnel "1.9.2" + micromatch "^3.1.10" + opn "5.3.0" + portscanner "2.1.1" + qs "6.2.3" + raw-body "^2.3.2" + resp-modifier "6.0.2" + rx "4.1.0" + send "0.16.2" + serve-index "1.9.1" + serve-static "1.13.2" + server-destroy "1.0.1" + socket.io "2.1.1" + ua-parser-js "0.7.17" + yargs "6.4.0" + +bs-recipes@1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/bs-recipes/-/bs-recipes-1.3.4.tgz#0d2d4d48a718c8c044769fdc4f89592dc8b69585" + integrity sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU= + +bs-snippet-injector@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz#61b5393f11f52559ed120693100343b6edb04dd5" + integrity sha1-YbU5PxH1JVntEgaTEANDtu2wTdU= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +caching-transform@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70" + integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w== + dependencies: + hasha "^3.0.0" + make-dir "^2.0.0" + package-hash "^3.0.0" + write-file-atomic "^2.4.2" + +call-matcher@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/call-matcher/-/call-matcher-1.1.0.tgz#23b2c1bc7a8394c8be28609d77ddbd5786680432" + integrity sha512-IoQLeNwwf9KTNbtSA7aEBb1yfDbdnzwjCetjkC8io5oGeOmK2CBNdg0xr+tadRYKO0p7uQyZzvon0kXlZbvGrw== + dependencies: + core-js "^2.0.0" + deep-equal "^1.0.0" + espurify "^1.6.0" + estraverse "^4.0.0" + +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + +call-signature@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/call-signature/-/call-signature-0.0.2.tgz#a84abc825a55ef4cb2b028bd74e205a65b9a4996" + integrity sha1-qEq8glpV70yysCi9dOIFpluaSZY= + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsite@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" + integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +camelcase-keys@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= + dependencies: + camelcase "^4.1.0" + map-obj "^2.0.0" + quick-lru "^1.0.0" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= + +camelcase@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" + integrity sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8= + dependencies: + ansi-styles "~1.0.0" + has-color "~0.1.0" + strip-ansi "~0.1.0" + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +character-parser@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" + integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A= + dependencies: + is-regex "^1.0.3" + +chokidar@^2.0.0, chokidar@^2.0.4, chokidar@^2.1.5: + version "2.1.6" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" + integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.0.2.tgz#0d1cd6d04eb2df0327446188cd13736a3367d681" + integrity sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA== + dependencies: + anymatch "^3.0.1" + braces "^3.0.2" + glob-parent "^5.0.0" + is-binary-path "^2.1.0" + is-glob "^4.0.1" + normalize-path "^3.0.0" + readdirp "^3.1.1" + optionalDependencies: + fsevents "^2.0.6" + +chownr@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" + integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== + +chunkd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chunkd/-/chunkd-1.0.0.tgz#4ead4a3704bcce510c4bb4d4a8be30c557836dd1" + integrity sha512-xx3Pb5VF9QaqCotolyZ1ywFBgyuJmu6+9dLiqBxgelEse9Xsr3yUlpoX3O4Oh11M00GT2kYMsRByTKIMJW2Lkg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-parallel-vars@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ci-parallel-vars/-/ci-parallel-vars-1.0.0.tgz#af97729ed1c7381911ca37bcea263d62638701b3" + integrity sha512-u6dx20FBXm+apMi+5x7UVm6EH7BL1gc4XrcnQewjcB7HWRcor/V5qWc3RG2HwpgDJ26gIi2DSEu3B7sXynAw/g== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clean-css@^4.1.11: + version "4.2.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" + integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== + dependencies: + source-map "~0.6.0" + +clean-stack@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +clean-yaml-object@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" + integrity sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g= + +cli-boxes@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" + integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== + +cli-cursor@^2.0.0, cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" + integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== + +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + +cli-truncate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.0.0.tgz#68ff6aaa53b203b52ad89b8b1a80f1f61ad1e1d5" + integrity sha512-C4hp+8GCIFVsUUiXcw+ce+7wexVWImw8rQrgMBFsqerx9LvvcGlwm6sMjQYAEmV/Xb87xc1b5Ttx505MSpZVqg== + dependencies: + slice-ansi "^2.1.0" + string-width "^4.1.0" + +clipboard@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d" + integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^3.0.3, cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +code-excerpt@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.1.tgz#5fe3057bfbb71a5f300f659ef2cc0a47651ba77c" + integrity sha512-tJLhH3EpFm/1x7heIW0hemXJTUU5EWl2V0EIX558jp05Mt1U6DVryCgkp3l37cxqs+DNbNgxG43SkwJXpQ14Jw== + dependencies: + convert-to-spaces "^1.0.1" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.0.tgz#9851ac61cc0d3898a8a3088650d5bf447bf69d97" + integrity sha512-hzTicsCJIHdxih9+2aLR1tNGZX5qSJGRHDPVwSY26tVrEf55XNajLOBWz2UuWSIergszA09/bqnOiHyqx9fxQg== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@^2.13.0, commander@^2.14.1, commander@^2.16.0, commander@^2.19.0, commander@^2.2.0, commander@^2.8.1, commander@^2.9.0, commander@~2.20.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== + +common-path-prefix@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-1.0.0.tgz#cd52f6f0712e0baab97d6f9732874f22f47752c0" + integrity sha1-zVL28HEuC6q5fW+XModPIvR3UsA= + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-bind@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" + integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= + +component-emitter@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +component-inherit@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" + integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.4.7: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +concordance@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/concordance/-/concordance-4.0.0.tgz#5932fdee397d129bdbc3a1885fbe69839b1b7e15" + integrity sha512-l0RFuB8RLfCS0Pt2Id39/oCPykE01pyxgAFypWTlaGRgvLkZrtczZ8atEHpTeEIW+zYWXTBuA9cCSeEOScxReQ== + dependencies: + date-time "^2.1.0" + esutils "^2.0.2" + fast-diff "^1.1.2" + js-string-escape "^1.0.1" + lodash.clonedeep "^4.5.0" + lodash.flattendeep "^4.4.0" + lodash.islength "^4.0.1" + lodash.merge "^4.6.1" + md5-hex "^2.0.0" + semver "^5.5.1" + well-known-symbols "^2.0.0" + +condense-newlines@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f" + integrity sha1-PemFVTE5R10yUCyDsC9gaE0kxV8= + dependencies: + extend-shallow "^2.0.1" + is-whitespace "^0.3.0" + kind-of "^3.0.2" + +config-chain@^1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" + integrity sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ== + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +connect-history-api-fallback@^1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +connect@3.6.6: + version "3.6.6" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" + integrity sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ= + dependencies: + debug "2.6.9" + finalhandler "1.1.0" + parseurl "~1.3.2" + utils-merge "1.0.1" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +constantinople@^3.0.1, constantinople@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" + integrity sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw== + dependencies: + "@types/babel-types" "^7.0.0" + "@types/babylon" "^6.16.2" + babel-types "^6.26.0" + babylon "^6.18.0" + +convert-source-map@^1.1.0, convert-source-map@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== + dependencies: + safe-buffer "~5.1.1" + +convert-to-spaces@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715" + integrity sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU= + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js@^2.0.0, core-js@^2.4.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" + integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cosmiconfig@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cp-file@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d" + integrity sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA== + dependencies: + graceful-fs "^4.1.2" + make-dir "^2.0.0" + nested-error-stacks "^2.0.0" + pify "^4.0.1" + safe-buffer "^5.0.1" + +cross-spawn@^4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +csso@^3.5.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== + dependencies: + css-tree "1.0.0-alpha.29" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + +date-fns@^1.27.2: + version "1.30.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" + integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== + +date-time@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-0.1.1.tgz#ed2f6d93d9790ce2fd66d5b5ff3edd5bbcbf3b07" + integrity sha1-7S9tk9l5DOL9ZtW1/z7dW7y/Owc= + +date-time@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" + integrity sha512-/9+C44X7lot0IeiyfgJmETtRMhBidBYM2QFFIkGa0U1k+hSyY87Nw7PY3eDqpvCBm7I3WCSfPeZskW/YYq6m4g== + dependencies: + time-zone "^1.0.0" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4.1.1, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +debug@=3.1.0, debug@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^3.1.0, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +decamelize-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + +deep-equal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +default-require-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" + integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= + dependencies: + strip-bom "^3.0.0" + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +defer-to-connect@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" + integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== + +define-properties@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +del@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +del@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" + integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU= + dependencies: + globby "^6.1.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + p-map "^1.1.1" + pify "^3.0.0" + rimraf "^2.2.8" + +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + dependencies: + "@types/glob" "^7.1.1" + globby "^6.1.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +dependency-graph@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.8.0.tgz#2da2d35ed852ecc24a5d6c17788ba57c3708755b" + integrity sha512-DCvzSq2UiMsuLnj/9AL484ummEgLtZIcRS7YvtO38QnpX3vqh9nJ8P+zhu8Ja+SmLrBHO2iDbva20jq38qvBkQ== + +dependency-tree@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/dependency-tree/-/dependency-tree-6.5.0.tgz#666d6838c2d8eab0eeeb2e2d19eafcbdda336cde" + integrity sha512-r0KO5BkQy8sMbyTD8NxSDOexsySbGpSH5fIsxCLZjarFTXMryiZoR7+Ao6OWkwLz6OeQPYCOIjUDh+knWitMEw== + dependencies: + commander "^2.19.0" + debug "^4.1.1" + filing-cabinet "^2.3.0" + precinct "^5.3.1" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +detective-amd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/detective-amd/-/detective-amd-3.0.0.tgz#40c8e21e229df8bca1ee2d4b952a7b67b01e2a5a" + integrity sha512-kOpKHyabdSKF9kj7PqYHLeHPw+TJT8q2u48tZYMkIcas28el1CYeLEJ42Nm+563/Fq060T5WknfwDhdX9+kkBQ== + dependencies: + ast-module-types "^2.3.1" + escodegen "^1.8.0" + get-amd-module-type "^3.0.0" + node-source-walk "^4.0.0" + +detective-cjs@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/detective-cjs/-/detective-cjs-3.1.1.tgz#18da3e39a002d2098a1123d45ce1de1b0d9045a0" + integrity sha512-JQtNTBgFY6h8uT6pgph5QpV3IyxDv+z3qPk/FZRDT9TlFfm5dnRtpH39WtQEr1khqsUxVqXzKjZHpdoQvQbllg== + dependencies: + ast-module-types "^2.4.0" + node-source-walk "^4.0.0" + +detective-es6@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detective-es6/-/detective-es6-2.1.0.tgz#7848feaec92279d82f7b3a98d8e1f5d93483a0f7" + integrity sha512-QSHqKGOp/YBIfmIqKXaXeq2rlL+bp3bcIQMfZ+0PvKzRlELSOSZxKRvpxVcxlLuocQv4QnOfuWGniGrmPbz8MQ== + dependencies: + node-source-walk "^4.0.0" + +detective-less@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/detective-less/-/detective-less-1.0.2.tgz#a68af9ca5f69d74b7d0aa190218b211d83b4f7e3" + integrity sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA== + dependencies: + debug "^4.0.0" + gonzales-pe "^4.2.3" + node-source-walk "^4.0.0" + +detective-postcss@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/detective-postcss/-/detective-postcss-3.0.1.tgz#511921951f66135e17d0ece2e7604c6e4966c9c6" + integrity sha512-tfTS2GdpUal5NY0aCqI4dpEy8Xfr88AehYKB0iBIZvo8y2g3UsrcDnrp9PR2FbzoW7xD5Rip3NJW7eCSvtqdUw== + dependencies: + debug "^4.1.1" + is-url "^1.2.4" + postcss "^7.0.2" + postcss-values-parser "^1.5.0" + +detective-sass@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/detective-sass/-/detective-sass-3.0.1.tgz#496b819efd1f5c4dd3f0e19b43a8634bdd6927c4" + integrity sha512-oSbrBozRjJ+QFF4WJFbjPQKeakoaY1GiR380NPqwdbWYd5wfl5cLWv0l6LsJVqrgWfFN1bjFqSeo32Nxza8Lbw== + dependencies: + debug "^4.1.1" + gonzales-pe "^4.2.3" + node-source-walk "^4.0.0" + +detective-scss@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detective-scss/-/detective-scss-2.0.1.tgz#06f8c21ae6dedad1fccc26d544892d968083eaf8" + integrity sha512-VveyXW4WQE04s05KlJ8K0bG34jtHQVgTc9InspqoQxvnelj/rdgSAy7i2DXAazyQNFKlWSWbS+Ro2DWKFOKTPQ== + dependencies: + debug "^4.1.1" + gonzales-pe "^4.2.3" + node-source-walk "^4.0.0" + +detective-stylus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-1.0.0.tgz#50aee7db8babb990381f010c63fabba5b58e54cd" + integrity sha1-UK7n24uruZA4HwEMY/q7pbWOVM0= + +detective-typescript@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-4.1.2.tgz#796ef6215a948ce3a11ec7e787a6c2c03db62d35" + integrity sha512-jeQMIN/0hjMdMpFGoo9y+ibo+dTb1Vbg6z/peHoRMR69jqH691kgz1gT5XM5UfkDD/Ru0save1bSJBmUr2yjvQ== + dependencies: + node-source-walk "^4.0.0" + typescript "^3.0.3" + typescript-eslint-parser "^18.0.0" + +dev-ip@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0" + integrity sha1-p2o+0YVb56ASu4rBbLgPPADcKPA= + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctypes@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" + integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= + +dom-serializer@0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.0.0" + +dot-prop@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.1.0.tgz#bdd8c986a77b83e3fca524e53786df916cabbd8a" + integrity sha512-n1oC6NBF+KM9oVXtjmen4Yo7HyAVWV2UUl50dCYJdw2924K6dX9bf9TTTWaKtYlRn0FEtxG27KS80ayVLixxJA== + dependencies: + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +easy-extender@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/easy-extender/-/easy-extender-2.3.4.tgz#298789b64f9aaba62169c77a2b3b64b4c9589b8f" + integrity sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q== + dependencies: + lodash "^4.17.10" + +eazy-logger@^3: + version "3.0.2" + resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-3.0.2.tgz#a325aa5e53d13a2225889b2ac4113b2b9636f4fc" + integrity sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw= + dependencies: + tfunk "^3.0.1" + +editorconfig@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== + dependencies: + commander "^2.19.0" + lru-cache "^4.1.5" + semver "^5.6.0" + sigmund "^1.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +ejs@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.2.tgz#3a32c63d1cd16d11266cd4703b14fec4e74ab4f6" + integrity sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q== + +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= + +emitter-mixin@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/emitter-mixin/-/emitter-mixin-0.0.3.tgz#5948cb286f2e48edc3b251a7cfc1f7883396d65c" + integrity sha1-WUjLKG8uSO3DslGnz8H3iDOW1lw= + +emittery@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.4.1.tgz#abe9d3297389ba424ac87e53d1c701962ce7433d" + integrity sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +empower-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-1.2.0.tgz#ce3fb2484d5187fa29c23fba8344b0b2fdf5601c" + integrity sha512-g6+K6Geyc1o6FdXs9HwrXleCFan7d66G5xSCfSF7x1mJDCes6t0om9lFQG3zOrzh3Bkb/45N0cZ5Gqsf7YrzGQ== + dependencies: + call-signature "0.0.2" + core-js "^2.0.0" + +encodeurl@~1.0.1, encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +engine.io-client@~3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" + integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw== + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "~3.1.0" + engine.io-parser "~2.1.1" + has-cors "1.1.0" + indexof "0.0.1" + parseqs "0.0.5" + parseuri "0.0.5" + ws "~3.3.1" + xmlhttprequest-ssl "~1.5.4" + yeast "0.1.2" + +engine.io-client@~3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.3.2.tgz#04e068798d75beda14375a264bb3d742d7bc33aa" + integrity sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ== + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "~3.1.0" + engine.io-parser "~2.1.1" + has-cors "1.1.0" + indexof "0.0.1" + parseqs "0.0.5" + parseuri "0.0.5" + ws "~6.1.0" + xmlhttprequest-ssl "~1.5.4" + yeast "0.1.2" + +engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" + integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== + dependencies: + after "0.8.2" + arraybuffer.slice "~0.0.7" + base64-arraybuffer "0.1.5" + blob "0.0.5" + has-binary2 "~1.0.2" + +engine.io@~3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2" + integrity sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w== + dependencies: + accepts "~1.3.4" + base64id "1.0.0" + cookie "0.3.1" + debug "~3.1.0" + engine.io-parser "~2.1.0" + ws "~3.3.1" + +enhanced-resolve@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +equal-length@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" + integrity sha1-IcoRLUirJLTh5//A5TOdMf38J0w= + +errno@^0.1.2, errno@^0.1.3: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^1.8.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510" + integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +esm@^3.2.25: + version "3.2.25" + resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" + integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== + +espower-location-detector@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/espower-location-detector/-/espower-location-detector-1.0.0.tgz#a17b7ecc59d30e179e2bef73fb4137704cb331b5" + integrity sha1-oXt+zFnTDheeK+9z+0E3cEyzMbU= + dependencies: + is-url "^1.2.1" + path-is-absolute "^1.0.0" + source-map "^0.5.0" + xtend "^4.0.0" + +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +espurify@^1.6.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/espurify/-/espurify-1.8.1.tgz#5746c6c1ab42d302de10bd1d5bf7f0e8c0515056" + integrity sha512-ZDko6eY/o+D/gHCWyHTU85mKDgYcS4FJj7S+YD6WIInm7GQ6AnOjmcL4+buFV/JOztVLELi/7MmuGU5NHta0Mg== + dependencies: + core-js "^2.0.0" + +estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@1.8.1, etag@^1.8.1, etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eventemitter3@1.x.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" + integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg= + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^2.2.7: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + +fast-glob@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602" + integrity sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg== + dependencies: + "@nodelib/fs.stat" "^2.0.1" + "@nodelib/fs.walk" "^1.2.1" + glob-parent "^5.0.0" + is-glob "^4.0.1" + merge2 "^1.2.3" + micromatch "^4.0.2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + +figures@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +figures@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9" + integrity sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g== + dependencies: + escape-string-regexp "^1.0.5" + +file-exists-dazinatorfork@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/file-exists-dazinatorfork/-/file-exists-dazinatorfork-1.0.2.tgz#cd8d0d85f63e39dc81eceb0b687c44a2cca95c47" + integrity sha512-r70c72ln2YHzQINNfxDp02hAhbGkt1HffZ+Du8oetWDLjDtFja/Lm10lUaSh9e+wD+7VDvPee0b0C9SAy8pWZg== + +filing-cabinet@^2.3.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/filing-cabinet/-/filing-cabinet-2.3.3.tgz#77882b25ef0859c321a871b440823bc2ed590995" + integrity sha512-Lp9FNBm74UnZI/0tVcH8WlJZmnYf9/qImt1/VUaEj3rlBl+V7M5yVAzYPJ7X1T2WxQeCrSQN4jN64SlQa6Rbew== + dependencies: + app-module-path "^2.2.0" + commander "^2.13.0" + debug "^4.1.1" + enhanced-resolve "^4.1.0" + is-relative-path "^1.0.2" + module-definition "^3.0.0" + module-lookup-amd "^6.1.0" + resolve "^1.11.1" + resolve-dependency-path "^2.0.0" + sass-lookup "^3.0.0" + stylus-lookup "^3.0.1" + typescript "^3.0.3" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" + integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U= + dependencies: + debug "2.6.9" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.3.1" + unpipe "~1.0.0" + +find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/find/-/find-0.3.0.tgz#4082e8fc8d8320f1a382b5e4f521b9bc50775cb8" + integrity sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw== + dependencies: + traverse-chain "~0.1.0" + +flatten@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" + integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= + +fn-name@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" + integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc= + +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +foreground-child@^1.5.6: + version "1.5.6" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" + integrity sha1-T9ca0t/elnibmApcCilZN8svXOk= + dependencies: + cross-spawn "^4" + signal-exit "^3.0.0" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2, fresh@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-extra@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" + integrity sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" + integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== + dependencies: + minipass "^2.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.9" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" + integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + dependencies: + nan "^2.12.1" + node-pre-gyp "^0.12.0" + +fsevents@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.0.7.tgz#382c9b443c6cbac4c57187cdda23aa3bf1ccfc2a" + integrity sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +g-status@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/g-status/-/g-status-2.0.2.tgz#270fd32119e8fc9496f066fe5fe88e0a6bc78b97" + integrity sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA== + dependencies: + arrify "^1.0.1" + matcher "^1.0.0" + simple-git "^1.85.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-amd-module-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-amd-module-type/-/get-amd-module-type-3.0.0.tgz#bb334662fa04427018c937774570de495845c288" + integrity sha512-99Q7COuACPfVt18zH9N4VAMyb81S6TUgJm2NgV6ERtkh9VIkAaByZkW530wl3lLN5KTtSrK9jVLxYsoP5hQKsw== + dependencies: + ast-module-types "^2.3.2" + node-source-walk "^4.0.0" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" + integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg== + +get-port@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.0.0.tgz#aa22b6b86fd926dd7884de3e23332c9f70c031a6" + integrity sha512-imzMU0FjsZqNa6BqOjbbW6w5BivHIuQKopjpPqcnx0AVHJQKCxK1O+Ab3OrVXhrekqfVMjwA9ZYu062R+KcIsQ== + dependencies: + type-fest "^0.3.0" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0, get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" + integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= + +glob@^7.0.3, glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= + dependencies: + ini "^1.3.4" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globby@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" + integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +gonzales-pe@^4.2.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.4.tgz#356ae36a312c46fe0f1026dd6cb539039f8500d2" + integrity sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ== + dependencies: + minimist "1.1.x" + +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" + integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== + +gray-matter@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" + integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw== + dependencies: + js-yaml "^3.11.0" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" + +hamljs@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/hamljs/-/hamljs-0.6.2.tgz#7b7116cf6dbe7278e42b3f6ef8725a33e177c8e3" + integrity sha1-e3EWz22+cnjkKz9u+HJaM+F3yOM= + +handlebars@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" + integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-binary2@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" + integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== + dependencies: + isarray "2.0.1" + +has-color@~0.1.0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" + integrity sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8= + +has-cors@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" + integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + +has@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-sum@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" + integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= + +hasha@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39" + integrity sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk= + dependencies: + is-stream "^1.0.1" + +hasha@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.0.0.tgz#fdc3785caea03df29535fc8adb512c3d3a709004" + integrity sha512-PqWdhnQhq6tqD32hZv+l1e5mJHNSudjnaAzgAHfkGiU0ABN6lmbZF8abJIulQHbZ7oiHhP8yL6O910ICMc+5pw== + dependencies: + is-stream "^1.1.0" + type-fest "^0.3.0" + +he@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hosted-git-info@^2.1.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== + +html-escaper@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-1.0.1.tgz#ee029e2862674017941355a7f61fc2c7c0a6fd72" + integrity sha1-7gKeKGJnQBeUE1Wn9h/Cx8Cm/XI= + +htmlparser2@^3.9.2: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +http-cache-semantics@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" + integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== + +http-errors@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-proxy@1.15.2: + version "1.15.2" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.15.2.tgz#642fdcaffe52d3448d2bda3b0079e9409064da31" + integrity sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE= + dependencies: + eventemitter3 "1.x.x" + requires-port "1.x.x" + +iconv-lite@0.4.24, iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-by-default@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + dependencies: + minimatch "^3.0.4" + +ignore@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" + integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== + +immutable@^3: + version "3.8.2" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" + integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + +import-local@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^3.0.0, indent-string@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +irregular-plurals@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" + integrity sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw== + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-error@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843" + integrity sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg== + +is-expression@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f" + integrity sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8= + dependencies: + acorn "~4.0.2" + object-assign "^4.0.1" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + +is-npm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053" + integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA== + +is-number-like@^1.0.3: + version "1.0.8" + resolved "https://registry.yarnpkg.com/is-number-like/-/is-number-like-1.0.8.tgz#2e129620b50891042e44e9bbbb30593e75cfbbe3" + integrity sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA== + dependencies: + lodash.isfinite "^3.3.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^1.0.0, is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-observable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" + integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== + dependencies: + symbol-observable "^1.1.0" + +is-observable@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-2.0.0.tgz#327af1e8cdea9cd717f95911b87c5d34301721a6" + integrity sha512-fhBZv3eFKUbyHXZ1oHujdo2tZ+CNbdpdzzlENgCGZUC8keoGxUew2jYFLYcUB4qo7LDD03o4KK11m/QYD7kEjg== + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= + +is-path-cwd@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-in-cwd@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== + dependencies: + is-path-inside "^1.0.0" + +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= + dependencies: + path-is-inside "^1.0.1" + +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-plain-object@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" + integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== + dependencies: + isobject "^4.0.0" + +is-promise@^2.0.0, is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-regex@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + +is-relative-path@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-relative-path/-/is-relative-path-1.0.2.tgz#091b46a0d67c1ed0fe85f1f8cfdde006bb251d46" + integrity sha1-CRtGoNZ8HtD+hfH4z93gBrslHUY= + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + +is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-url@^1.2.1, is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0, is-utf8@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-whitespace@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f" + integrity sha1-Fjnssb4DauxppUy7QBz77XEUq38= + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isarray@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" + integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + +istanbul-lib-coverage@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" + integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== + +istanbul-lib-hook@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" + integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== + dependencies: + append-transform "^1.0.0" + +istanbul-lib-instrument@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" + integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== + dependencies: + "@babel/generator" "^7.4.0" + "@babel/parser" "^7.4.3" + "@babel/template" "^7.4.0" + "@babel/traverse" "^7.4.3" + "@babel/types" "^7.4.0" + istanbul-lib-coverage "^2.0.5" + semver "^6.0.0" + +istanbul-lib-report@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" + integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== + dependencies: + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + supports-color "^6.1.0" + +istanbul-lib-source-maps@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" + integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + rimraf "^2.6.3" + source-map "^0.6.1" + +istanbul-reports@^2.2.4: + version "2.2.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" + integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== + dependencies: + handlebars "^4.1.2" + +javascript-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.0.0.tgz#ef750216ae66504ffd670b68c8b8aa07bdf7b588" + integrity sha512-zzK8+ByrzvOL6N92hRewwUKL0wN0TOaIuUjX0Jj8lraxWvr5wHYs2YTjaj2lstF+8qMv5cmPPef47va8NT8lDw== + +js-beautify@^1.6.12: + version "1.10.1" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.1.tgz#bdfe738ddbcaa12e4fced5af2d7cfad59f60ac0a" + integrity sha512-4y8SHOIRC+/YQ2gs3zJEKBUraQerq49FJYyXRpdzUGYQzCq8q9xtIh0YXial1S5KmonVui4aiUb6XaGyjE51XA== + dependencies: + config-chain "^1.1.12" + editorconfig "^0.15.3" + glob "^7.1.3" + mkdirp "~0.5.1" + nopt "~4.0.1" + +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + +js-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" + integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json5@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" + integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + dependencies: + minimist "^1.2.0" + +jsonfile@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" + integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jstransformer@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" + integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= + dependencies: + is-promise "^2.0.0" + promise "^7.0.1" + +junk@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/junk/-/junk-1.0.3.tgz#87be63488649cbdca6f53ab39bec9ccd2347f592" + integrity sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI= + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +limiter@^1.0.5: + version "1.1.4" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.4.tgz#87c9c3972d389fdb0ba67a45aadbc5d2f8413bc1" + integrity sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg== + +linkify-it@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== + dependencies: + uc.micro "^1.0.1" + +lint-staged@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-8.2.1.tgz#752fcf222d9d28f323a3b80f1e668f3654ff221f" + integrity sha512-n0tDGR/rTCgQNwXnUf/eWIpPNddGWxC32ANTNYsj2k02iZb7Cz5ox2tytwBu+2r0zDXMEMKw7Y9OD/qsav561A== + dependencies: + chalk "^2.3.1" + commander "^2.14.1" + cosmiconfig "^5.2.0" + debug "^3.1.0" + dedent "^0.7.0" + del "^3.0.0" + execa "^1.0.0" + g-status "^2.0.2" + is-glob "^4.0.0" + is-windows "^1.0.2" + listr "^0.14.2" + listr-update-renderer "^0.5.0" + lodash "^4.17.11" + log-symbols "^2.2.0" + micromatch "^3.1.8" + npm-which "^3.0.1" + p-map "^1.1.1" + path-is-inside "^1.0.2" + pify "^3.0.0" + please-upgrade-node "^3.0.2" + staged-git-files "1.1.2" + string-argv "^0.0.2" + stringify-object "^3.2.2" + yup "^0.27.0" + +liquidjs@^6.4.3: + version "6.4.3" + resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-6.4.3.tgz#c7caf7a3f6c87dc6a22a5a351328cf8f7298c243" + integrity sha512-m1xSB10Ncu22NR3X0xdaqu/GvP1xadDCFYGqGgd6me8DAWjyA68BKE5DHJmSxw1CGsWPsX+Hj2v/87J2w/LvMQ== + +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= + +listr-update-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" + integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^2.3.0" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" + integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== + dependencies: + chalk "^2.4.1" + cli-cursor "^2.1.0" + date-fns "^1.27.2" + figures "^2.0.0" + +listr@^0.14.2: + version "0.14.3" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" + integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== + dependencies: + "@samverschueren/stream-to-observable" "^0.3.0" + is-observable "^1.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.5.0" + listr-verbose-renderer "^0.5.0" + p-map "^2.0.0" + rxjs "^6.3.3" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +load-json-file@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3" + integrity sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw== + dependencies: + graceful-fs "^4.1.15" + parse-json "^4.0.0" + pify "^4.0.1" + strip-bom "^3.0.0" + type-fest "^0.3.0" + +localtunnel@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-1.9.2.tgz#0012fcabc29cf964c130a01858768aa2bb65b5af" + integrity sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg== + dependencies: + axios "0.19.0" + debug "4.1.1" + openurl "1.1.1" + yargs "6.6.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + +lodash.isfinite@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3" + integrity sha1-+4m2WpqAKBgz8LdHizpRBPiY67M= + +lodash.islength@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.islength/-/lodash.islength-4.0.1.tgz#4e9868d452575d750affd358c979543dc20ed577" + integrity sha1-Tpho1FJXXXUK/9NYyXlUPcIO1Xc= + +lodash.merge@^4.6.1: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.template@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.unescape@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" + integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.4: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= + dependencies: + chalk "^1.0.0" + +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + +log-update@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" + integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= + dependencies: + ansi-escapes "^3.0.0" + cli-cursor "^2.0.0" + wrap-ansi "^3.0.1" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +loud-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-2.1.0.tgz#4020547ddbc39ed711c8434326df9fc7d2395355" + integrity sha512-g/6MQxUXYHeVqZ4PGpPL1fS1fOvlXoi7bay0pizmjAd/3JhyXwxzwrnr74yzdmhuerlslbRJ3x7IOXzFz0cE5w== + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.2" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^4.0.1, lru-cache@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +luxon@^1.16.0: + version "1.17.2" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.17.2.tgz#95189c450341cfddf5f826ef8c32b5b022943fd5" + integrity sha512-qELKtIj3HD41N+MvgoxArk8DZGUb4Gpiijs91oi+ZmKJzRlxY6CoyTwNoUwnogCVs4p8HuxVJDik9JbnYgrCng== + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-dir@^2.0.0, make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" + integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== + dependencies: + semver "^6.0.0" + +map-cache@^0.2.0, map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + +map-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-it-emoji@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc" + integrity sha1-m+4OmpkKljupbfaYDE/dsF37Tcw= + +markdown-it@^8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" + integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== + dependencies: + argparse "^1.0.7" + entities "~1.1.1" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +matcher@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.1.tgz#51d8301e138f840982b338b116bb0c09af62c1c2" + integrity sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg== + dependencies: + escape-string-regexp "^1.0.4" + +matcher@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-2.0.0.tgz#85fe38d97670dbd2a46590cf099401e2ffb4755c" + integrity sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng== + dependencies: + escape-string-regexp "^2.0.0" + +maximatch@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/maximatch/-/maximatch-0.1.0.tgz#86cd8d6b04c9f307c05a6b9419906d0360fb13a2" + integrity sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I= + dependencies: + array-differ "^1.0.0" + array-union "^1.0.1" + arrify "^1.0.0" + minimatch "^3.0.0" + +md5-hex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" + integrity sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM= + dependencies: + md5-o-matic "^0.1.1" + +md5-hex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" + integrity sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw== + dependencies: + blueimp-md5 "^2.10.0" + +md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + integrity sha1-givM1l4RfFFPqxdrJZRdVBAKA8M= + +mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + +memory-fs@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +meow@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" + integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + yargs-parser "^10.0.0" + +merge-source-map@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== + dependencies: + source-map "^0.6.1" + +merge2@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.4.tgz#c9269589e6885a60cf80605d9522d4b67ca646e3" + integrity sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A== + +micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +mime-db@1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== + +mime-types@~2.1.17, mime-types@~2.1.24: + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + dependencies: + mime-db "1.40.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@1.1.x: + version "1.1.3" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" + integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +minipass@^2.2.1, minipass@^2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== + dependencies: + minipass "^2.2.1" + +mitt@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.1.3.tgz#528c506238a05dce11cd914a741ea2cc332da9b8" + integrity sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA== + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +module-definition@^3.0.0, module-definition@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-3.2.0.tgz#a1741d5ddf60d76c60d5b1f41ba8744ba08d3ef4" + integrity sha512-PO6o0BajpdRR+fb3FUSeDISgJpnyxg8UDUEalR8LPQajl0M5+m4jHWhgrMGGSEl6D9+sVl/l1fjOCvpBXIQ+2Q== + dependencies: + ast-module-types "^2.4.0" + node-source-walk "^4.0.0" + +module-lookup-amd@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/module-lookup-amd/-/module-lookup-amd-6.2.0.tgz#70600008b3f26630fde9ef9ae6165ac69de6ecbb" + integrity sha512-uxHCj5Pw9psZiC1znjU2qPsubt6haCSsN9m7xmIdoTciEgfxUkE1vhtDvjHPuOXEZrVJhjKgkmkP+w73rRuelQ== + dependencies: + commander "^2.8.1" + debug "^4.1.0" + file-exists-dazinatorfork "^1.0.2" + find "^0.3.0" + requirejs "^2.3.5" + requirejs-config-file "^3.1.1" + +moo@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.0.tgz#72f949e6735aeb27d07eb7c087ea5a70143c56e5" + integrity sha512-AMv6iqhTEd5vT/cQlH6cammKS5ekyHhyqTRKi5zKMWl1RTyFnQ3ohPSBNSm8ySe2wlxSKwDonr9D5ZT44mdO3g== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1, ms@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +multimatch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b" + integrity sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA== + dependencies: + array-differ "^2.0.3" + array-union "^1.0.2" + arrify "^1.0.1" + minimatch "^3.0.4" + +mustache@^2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== + +nan@^2.12.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" + integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + +nested-error-stacks@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" + integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-source-walk@^4.0.0, node-source-walk@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-4.2.0.tgz#c2efe731ea8ba9c03c562aa0a9d984e54f27bc2c" + integrity sha512-hPs/QMe6zS94f5+jG3kk9E7TNm4P2SulrKiLWMzKszBfNZvL/V6wseHlTd7IvfW0NZWqPtK3+9yYNr+3USGteA== + dependencies: + "@babel/parser" "^7.0.0" + +nopt@^4.0.1, nopt@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" + integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +npm-packlist@^1.1.6: + version "1.4.4" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" + integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-path@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" + integrity sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw== + dependencies: + which "^1.2.10" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npm-which@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" + integrity sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo= + dependencies: + commander "^2.9.0" + npm-path "^2.0.2" + which "^1.2.10" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +nunjucks@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.0.tgz#53e95f43c9555e822e8950008a201b1002d49933" + integrity sha512-YS/qEQ6N7qCnUdm6EoYRBfJUdWNT0PpKbbRnogV2XyXbBm2STIP1O6yrdZHgwMVK7fIYUx7i8+yatEixnXSB1w== + dependencies: + a-sync-waterfall "^1.0.0" + asap "^2.0.3" + yargs "^3.32.0" + optionalDependencies: + chokidar "^2.0.0" + +nyc@^14.1.1: + version "14.1.1" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.1.1.tgz#151d64a6a9f9f5908a1b73233931e4a0a3075eeb" + integrity sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw== + dependencies: + archy "^1.0.0" + caching-transform "^3.0.2" + convert-source-map "^1.6.0" + cp-file "^6.2.0" + find-cache-dir "^2.1.0" + find-up "^3.0.0" + foreground-child "^1.5.6" + glob "^7.1.3" + istanbul-lib-coverage "^2.0.5" + istanbul-lib-hook "^2.0.7" + istanbul-lib-instrument "^3.3.0" + istanbul-lib-report "^2.0.8" + istanbul-lib-source-maps "^3.0.6" + istanbul-reports "^2.2.4" + js-yaml "^3.13.1" + make-dir "^2.1.0" + merge-source-map "^1.1.0" + resolve-from "^4.0.0" + rimraf "^2.6.3" + signal-exit "^3.0.2" + spawn-wrap "^1.4.2" + test-exclude "^5.2.3" + uuid "^3.3.2" + yargs "^13.2.2" + yargs-parser "^13.0.0" + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-component@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" + integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.11, object-keys@^1.0.12: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-path@^0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.9.2.tgz#0fd9a74fc5fad1ae3968b586bda5c632bd6c05a5" + integrity sha1-D9mnT8X60a45aLWGvaXGMr1sBaU= + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +observable-to-promise@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-1.0.0.tgz#37e136f16a15385ac063411ada0e1202bfff58f4" + integrity sha512-cqnGUrNsE6vdVDTPAX9/WeVzwy/z37vdxupdQXU8vgTXRFH72KCZiZga8aca2ulRPIeem8W3vW9rQHBwfIl2WA== + dependencies: + is-observable "^2.0.0" + symbol-observable "^1.0.4" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +openurl@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" + integrity sha1-OHW0sO96UsFW8NtB1GCduw+Us4c= + +opn@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" + integrity sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g== + dependencies: + is-wsl "^1.1.0" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +ora@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" + integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== + dependencies: + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-spinners "^2.0.0" + log-symbols "^2.2.0" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" + +os-homedir@^1.0.0, os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + +os-shim@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" + integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc= + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" + integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-3.0.0.tgz#50183f2d36c9e3e528ea0a8605dff57ce976f88e" + integrity sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA== + dependencies: + graceful-fs "^4.1.15" + hasha "^3.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +parse-filepath@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-ms@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-0.1.2.tgz#dd3fa25ed6c2efc7bdde12ad9b46c163aa29224e" + integrity sha1-3T+iXtbC78e93hKtm0bBY6opIk4= + +parse-ms@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" + integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== + +parseqs@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" + integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= + dependencies: + better-assert "~1.0.0" + +parseuri@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" + integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= + dependencies: + better-assert "~1.0.0" + +parseurl@~1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= + dependencies: + path-root-regex "^0.1.0" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.0.4, picomatch@^2.0.5: + version "2.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" + integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pkg-conf@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-3.1.0.tgz#d9f9c75ea1bae0e77938cde045b276dac7cc69ae" + integrity sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ== + dependencies: + find-up "^3.0.0" + load-json-file "^5.2.0" + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" + integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ== + dependencies: + semver-compare "^1.0.0" + +plur@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz#60267967866a8d811504fe58f2faaba237546a5b" + integrity sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w== + dependencies: + irregular-plurals "^2.0.0" + +portscanner@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/portscanner/-/portscanner-2.1.1.tgz#eabb409e4de24950f5a2a516d35ae769343fbb96" + integrity sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y= + dependencies: + async "1.5.2" + is-number-like "^1.0.3" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postcss-values-parser@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz#5d9fa63e2bcb0179ce48f3235303765eb89f3047" + integrity sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ== + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss@^7.0.2: + version "7.0.17" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" + integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +pre-commit@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.2.2.tgz#dbcee0ee9de7235e57f79c56d7ce94641a69eec6" + integrity sha1-287g7p3nI15X95xW186UZBpp7sY= + dependencies: + cross-spawn "^5.0.1" + spawn-sync "^1.0.15" + which "1.2.x" + +pre-push@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pre-push/-/pre-push-0.1.1.tgz#2a2a79827d243a76c91089897ac707f45e716aac" + integrity sha1-Kip5gn0kOnbJEImJescH9F5xaqw= + dependencies: + shelljs "0.3.x" + +precinct@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/precinct/-/precinct-5.3.1.tgz#4ab0ec1d1a8f1b2f4982b810d56419e7b3025870" + integrity sha512-HOIXDarP6S5JXYC5GhnpoAj9RqJ6yAwZ8VI71vQFlq1rmkBRPs+Mt60TOr7DUc/fx309iIQaniB4x3zueOOSdw== + dependencies: + commander "^2.19.0" + debug "^4.1.1" + detective-amd "^3.0.0" + detective-cjs "^3.1.1" + detective-es6 "^2.0.0" + detective-less "^1.0.2" + detective-postcss "^3.0.0" + detective-sass "^3.0.0" + detective-scss "^2.0.0" + detective-stylus "^1.0.0" + detective-typescript "^4.1.2" + module-definition "^3.1.0" + node-source-walk "^4.2.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +prettier@^1.18.2: + version "1.18.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" + integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== + +pretty-ms@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-0.2.2.tgz#da879a682ff33a37011046f13d627f67c73b84f6" + integrity sha1-2oeaaC/zOjcBEEbxPWJ/Z8c7hPY= + dependencies: + parse-ms "^0.1.0" + +pretty-ms@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-5.0.0.tgz#6133a8f55804b208e4728f6aa7bf01085e951e24" + integrity sha512-94VRYjL9k33RzfKiGokPBPpsmloBYSf5Ri+Pq19zlsEcUKFob+admeXr5eFDRuPjFmEOcjJvPGdillYOJyvZ7Q== + dependencies: + parse-ms "^2.1.0" + +pretty@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5" + integrity sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU= + dependencies: + condense-newlines "^0.2.1" + extend-shallow "^2.0.1" + js-beautify "^1.6.12" + +prismjs@^1.15.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.17.1.tgz#e669fcbd4cdd873c35102881c33b14d0d68519be" + integrity sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q== + optionalDependencies: + clipboard "^2.0.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +promise@^7.0.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + +property-expr@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" + integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g== + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +pug-attrs@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.4.tgz#b2f44c439e4eb4ad5d4ef25cac20d18ad28cc336" + integrity sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ== + dependencies: + constantinople "^3.0.1" + js-stringify "^1.0.1" + pug-runtime "^2.0.5" + +pug-code-gen@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.2.tgz#ad0967162aea077dcf787838d94ed14acb0217c2" + integrity sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw== + dependencies: + constantinople "^3.1.2" + doctypes "^1.1.0" + js-stringify "^1.0.1" + pug-attrs "^2.0.4" + pug-error "^1.3.3" + pug-runtime "^2.0.5" + void-elements "^2.0.1" + with "^5.0.0" + +pug-error@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.3.tgz#f342fb008752d58034c185de03602dd9ffe15fa6" + integrity sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ== + +pug-filters@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-3.1.1.tgz#ab2cc82db9eeccf578bda89130e252a0db026aa7" + integrity sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg== + dependencies: + clean-css "^4.1.11" + constantinople "^3.0.1" + jstransformer "1.0.0" + pug-error "^1.3.3" + pug-walk "^1.1.8" + resolve "^1.1.6" + uglify-js "^2.6.1" + +pug-lexer@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-4.1.0.tgz#531cde48c7c0b1fcbbc2b85485c8665e31489cfd" + integrity sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA== + dependencies: + character-parser "^2.1.1" + is-expression "^3.0.0" + pug-error "^1.3.3" + +pug-linker@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.6.tgz#f5bf218b0efd65ce6670f7afc51658d0f82989fb" + integrity sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg== + dependencies: + pug-error "^1.3.3" + pug-walk "^1.1.8" + +pug-load@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.12.tgz#d38c85eb85f6e2f704dea14dcca94144d35d3e7b" + integrity sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg== + dependencies: + object-assign "^4.1.0" + pug-walk "^1.1.8" + +pug-parser@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-5.0.1.tgz#03e7ada48b6840bd3822f867d7d90f842d0ffdc9" + integrity sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA== + dependencies: + pug-error "^1.3.3" + token-stream "0.0.1" + +pug-runtime@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.5.tgz#6da7976c36bf22f68e733c359240d8ae7a32953a" + integrity sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw== + +pug-strip-comments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz#cc1b6de1f6e8f5931cf02ec66cdffd3f50eaf8a8" + integrity sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw== + dependencies: + pug-error "^1.3.3" + +pug-walk@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.8.tgz#b408f67f27912f8c21da2f45b7230c4bd2a5ea7a" + integrity sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA== + +pug@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.4.tgz#ee7682ec0a60494b38d48a88f05f3b0ac931377d" + integrity sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw== + dependencies: + pug-code-gen "^2.0.2" + pug-filters "^3.1.1" + pug-lexer "^4.1.0" + pug-linker "^3.0.6" + pug-load "^2.0.12" + pug-parser "^5.0.1" + pug-runtime "^2.0.5" + pug-strip-comments "^1.0.4" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +qs@6.2.3: + version "6.2.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" + integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= + +quick-lru@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" + integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= + +range-parser@~1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@^2.3.2: + version "2.4.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" + integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== + dependencies: + bytes "3.1.0" + http-errors "1.7.3" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@^1.2.7, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + +read-pkg-up@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" + integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== + dependencies: + find-up "^3.0.0" + read-pkg "^3.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.1.1.tgz#b158123ac343c8b0f31d65680269cc0fc1025db1" + integrity sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ== + dependencies: + picomatch "^2.0.4" + +recursive-copy@^2.0.10: + version "2.0.10" + resolved "https://registry.yarnpkg.com/recursive-copy/-/recursive-copy-2.0.10.tgz#a39402f2270c5f8b562b48d438a42e2e6e5c644c" + integrity sha512-S9J9XJUnfZ2NUS3lK6lx6HWLl2nWui+f7AKuu+qoFs4ikEPYgZ3qKk1T6tmBnr7PzhtKnawE+6TREy9XQKmxCA== + dependencies: + del "^2.2.0" + emitter-mixin "0.0.3" + errno "^0.1.2" + graceful-fs "^4.1.4" + junk "^1.0.1" + maximatch "^0.1.0" + mkdirp "^0.5.1" + pify "^2.3.0" + promise "^7.0.1" + slash "^1.0.0" + +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + +regenerate-unicode-properties@^8.0.2: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" + integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpu-core@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" + integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.0.2" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +registry-auth-token@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.0.0.tgz#30e55961eec77379da551ea5c4cf43cbf03522be" + integrity sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw== + dependencies: + rc "^1.2.8" + safe-buffer "^5.0.1" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + +regjsgen@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" + integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== + +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" + integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + dependencies: + jsesc "~0.5.0" + +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + dependencies: + es6-error "^4.0.1" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.5.2, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +require-precompiled@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/require-precompiled/-/require-precompiled-0.1.0.tgz#5a1b52eb70ebed43eb982e974c85ab59571e56fa" + integrity sha1-WhtS63Dr7UPrmC6XTIWrWVceVvo= + +requirejs-config-file@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/requirejs-config-file/-/requirejs-config-file-3.1.2.tgz#de8c0b3eebdf243511c994a8a24b006f8b825997" + integrity sha512-sdLWywcDuNz7EIOhenSbRfT4YF84nItDv90coN2htbokjmU2QeyQuSBZILQUKNksepl8UPVU+hgYySFaDxbJPQ== + dependencies: + esprima "^4.0.0" + make-dir "^2.1.0" + stringify-object "^3.2.1" + +requirejs@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9" + integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg== + +requires-port@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-dependency-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz#11700e340717b865d216c66cabeb4a2a3c696736" + integrity sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w== + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.2.0, resolve@^1.3.2: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + +resp-modifier@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/resp-modifier/-/resp-modifier-6.0.2.tgz#b124de5c4fbafcba541f48ffa73970f4aa456b4f" + integrity sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08= + dependencies: + debug "^2.2.0" + minimatch "^3.0.2" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= + dependencies: + align-text "^0.1.1" + +rimraf@^2.2.8, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +rx@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" + integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= + +rxjs@^5.5.6: + version "5.5.12" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" + integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw== + dependencies: + symbol-observable "1.0.1" + +rxjs@^6.3.3: + version "6.5.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" + integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sass-lookup@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac" + integrity sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg== + dependencies: + commander "^2.16.0" + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" + integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== + dependencies: + extend-shallow "^2.0.1" + kind-of "^6.0.0" + +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= + dependencies: + semver "^5.0.3" + +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + +semver@5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== + +semver@^6.0.0, semver@^6.1.1, semver@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" + integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= + +serialize-javascript@^1.3.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" + integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== + +serve-index@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +server-destroy@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" + integrity sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0= + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + integrity sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E= + +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +simple-git@^1.85.0: + version "1.124.0" + resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.124.0.tgz#10a73cc1af303832b5c11720d4256e134fba35ca" + integrity sha512-ks9mBoO4ODQy/xGLC8Cc+YDvj/hho/IKgPhi6h5LI/sA+YUdHc3v0DEoHzM29VmulubpGCxMJUSFmyXNsjNMEA== + dependencies: + debug "^4.0.1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slugify@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.4.tgz#78d2792d7222b55cd9fc81fa018df99af779efeb" + integrity sha512-KP0ZYk5hJNBS8/eIjGkFDCzGQIoZ1mnfQRYS5WM3273z+fxGWXeN0fkwf2ebEweydv9tioZIHGZKoF21U07/nw== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +socket.io-adapter@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" + integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs= + +socket.io-client@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" + integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ== + dependencies: + backo2 "1.0.2" + base64-arraybuffer "0.1.5" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "~3.1.0" + engine.io-client "~3.2.0" + has-binary2 "~1.0.2" + has-cors "1.1.0" + indexof "0.0.1" + object-component "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + socket.io-parser "~3.2.0" + to-array "0.1.4" + +socket.io-client@^2.0.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.2.0.tgz#84e73ee3c43d5020ccc1a258faeeb9aec2723af7" + integrity sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA== + dependencies: + backo2 "1.0.2" + base64-arraybuffer "0.1.5" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "~3.1.0" + engine.io-client "~3.3.1" + has-binary2 "~1.0.2" + has-cors "1.1.0" + indexof "0.0.1" + object-component "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + socket.io-parser "~3.3.0" + to-array "0.1.4" + +socket.io-parser@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" + integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA== + dependencies: + component-emitter "1.2.1" + debug "~3.1.0" + isarray "2.0.1" + +socket.io-parser@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f" + integrity sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng== + dependencies: + component-emitter "1.2.1" + debug "~3.1.0" + isarray "2.0.1" + +socket.io@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" + integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA== + dependencies: + debug "~3.1.0" + engine.io "~3.2.0" + has-binary2 "~1.0.2" + socket.io-adapter "~1.1.0" + socket.io-client "2.1.1" + socket.io-parser "~3.2.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.5.12: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= + +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spawn-sync@^1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" + integrity sha1-sAeZVX63+wyDdsKdROih6mfldHY= + dependencies: + concat-stream "^1.4.7" + os-shim "^0.1.2" + +spawn-wrap@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" + integrity sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg== + dependencies: + foreground-child "^1.5.6" + mkdirp "^0.5.0" + os-homedir "^1.0.1" + rimraf "^2.6.2" + signal-exit "^3.0.2" + which "^1.3.0" + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +stack-utils@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" + integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== + +staged-git-files@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b" + integrity sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA== + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +statuses@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4= + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== + +stream-throttle@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/stream-throttle/-/stream-throttle-0.1.3.tgz#add57c8d7cc73a81630d31cd55d3961cfafba9c3" + integrity sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM= + dependencies: + commander "^2.2.0" + limiter "^1.0.5" + +string-argv@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" + integrity sha1-2sMECGkMIfPDYwo/86BYd73L1zY= + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff" + integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^5.2.0" + +string_decoder@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" + integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +stringify-object@^3.2.1, stringify-object@^3.2.2: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" + integrity sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE= + +strip-bom-buf@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-2.0.0.tgz#ff9c223937f8e7154b77e9de9bde094186885c15" + integrity sha512-gLFNHucd6gzb8jMsl5QmZ3QgnUJmp7qn4uUSHNwEXumAp7YizoGYw19ZUVfuq4aBOQUtyn2k8X/CwzWB73W2lQ== + dependencies: + is-utf8 "^0.2.1" + +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +stylus-lookup@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" + integrity sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg== + dependencies: + commander "^2.8.1" + debug "^4.1.0" + +supertap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e" + integrity sha512-HZJ3geIMPgVwKk2VsmO5YHqnnJYl6bV5A9JW2uzqV43WmpgliNEYbuvukfor7URpaqpxuw3CfZ3ONdVbZjCgIA== + dependencies: + arrify "^1.0.1" + indent-string "^3.2.0" + js-yaml "^3.10.0" + serialize-error "^2.1.0" + strip-ansi "^4.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.0.0.tgz#f2392c50ab35bb3cae7beebf24d254a19f880c06" + integrity sha512-WRt32iTpYEZWYOpcetGm0NPeSvaebccx7hhS/5M6sAiqnhedtFCHFxkjzZlJvFNCPowiKSFGiZk5USQDFy83vQ== + dependencies: + has-flag "^4.0.0" + +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= + +symbol-observable@^1.0.4, symbol-observable@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + +synchronous-promise@^2.0.6: + version "2.0.9" + resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.9.tgz#b83db98e9e7ae826bf9c8261fd8ac859126c780a" + integrity sha512-LO95GIW16x69LuND1nuuwM4pjgFGupg7pZ/4lU86AmchPKrhk0o2tpMU2unXRrqo81iAFe1YJ0nAGEVwsrZAgg== + +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tar@^4: + version "4.4.10" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" + integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.3.5" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= + dependencies: + execa "^0.7.0" + +test-exclude@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" + integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== + dependencies: + glob "^7.1.3" + minimatch "^3.0.4" + read-pkg-up "^4.0.0" + require-main-filename "^2.0.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +tfunk@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tfunk/-/tfunk-3.1.0.tgz#38e4414fc64977d87afdaa72facb6d29f82f7b5b" + integrity sha1-OORBT8ZJd9h6/apy+sttKfgve1s= + dependencies: + chalk "^1.1.1" + object-path "^0.9.0" + +time-require@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/time-require/-/time-require-0.1.2.tgz#f9e12cb370fc2605e11404582ba54ef5ca2b2d98" + integrity sha1-+eEss3D8JgXhFARYK6VO9corLZg= + dependencies: + chalk "^0.4.0" + date-time "^0.1.1" + pretty-ms "^0.2.1" + text-table "^0.2.0" + +time-zone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" + integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0= + +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +to-array@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" + integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +token-stream@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" + integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= + +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + +traverse-chain@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" + integrity sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE= + +trim-newlines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= + +trim-off-newlines@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" + integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== + +type-fest@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" + integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript-eslint-parser@^18.0.0: + version "18.0.0" + resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-18.0.0.tgz#3e5055a44980d69e4154350fc5d8b1ab4e2332a8" + integrity sha512-Pn/A/Cw9ysiXSX5U1xjBmPQlxtWGV2o7jDNiH/u7KgBO2yC/y37wNFl2ogSrGZBQFuglLzGq0Xl0Bt31Jv44oA== + dependencies: + lodash.unescape "4.0.1" + semver "5.5.0" + +typescript@^3.0.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" + integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== + +ua-parser-js@0.7.17: + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" + integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +uglify-js@^2.6.1: + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-js@^3.1.4, uglify-js@^3.3.27: + version "3.6.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" + integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== + dependencies: + commander "~2.20.0" + source-map "~0.6.1" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= + +uid2@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" + integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= + dependencies: + crypto-random-string "^1.0.0" + +unique-temp-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-temp-dir/-/unique-temp-dir-1.0.0.tgz#6dce95b2681ca003eebfb304a415f9cbabcc5385" + integrity sha1-bc6VsmgcoAPuv7MEpBX5y6vMU4U= + dependencies: + mkdirp "^0.5.1" + os-tmpdir "^1.0.1" + uid2 "0.0.3" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" + integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== + +update-notifier@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250" + integrity sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ== + dependencies: + boxen "^3.0.0" + chalk "^2.0.1" + configstore "^4.0.0" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.1.0" + is-npm "^3.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +valid-url@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" + integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +viperhtml@^2.17.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/viperhtml/-/viperhtml-2.17.0.tgz#a4958c83027a6ce796e0e20eb7ef2271bff61f5a" + integrity sha512-BjqqrwZPxpIZuwljESguNZzxXayLIzFHLhBF2kgz/3Yo9bhI41LR787LfNcILU4oqmUne2v3UT7hGb+2bwchMQ== + dependencies: + csso "^3.5.0" + html-escaper "^1.0.1" + htmlparser2 "^3.9.2" + uglify-js "^3.3.27" + +void-elements@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + +vue-server-renderer@^2.6.10: + version "2.6.10" + resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375" + integrity sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug== + dependencies: + chalk "^1.1.3" + hash-sum "^1.0.2" + he "^1.1.0" + lodash.template "^4.4.0" + lodash.uniq "^4.5.0" + resolve "^1.2.0" + serialize-javascript "^1.3.0" + source-map "0.5.6" + +vue@^2.6.10: + version "2.6.10" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" + integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ== + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +well-known-symbols@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-2.0.0.tgz#e9c7c07dbd132b7b84212c8174391ec1f9871ba5" + integrity sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q== + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.2.x: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + integrity sha1-mofEN48D6CfOyvGs31bHNsAcFOU= + dependencies: + isexe "^2.0.0" + +which@^1.2.10, which@^1.2.9, which@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +widest-line@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== + dependencies: + string-width "^2.1.1" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= + +window-size@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" + integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +with@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe" + integrity sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4= + dependencies: + acorn "^3.1.0" + acorn-globals "^3.0.0" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" + integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^2.0.0, write-file-atomic@^2.4.2: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write-file-atomic@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.0.tgz#1b64dbbf77cb58fd09056963d63e62667ab4fb21" + integrity sha512-EIgkf60l2oWsffja2Sf2AL384dx328c0B+cIYPTQq5q2rOYuDV00/iPFBOUiDKKwKMOhkymH8AidPaRvzfxY+Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@~3.3.1: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@~6.1.0: + version "6.1.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" + integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== + dependencies: + async-limiter "~1.0.0" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= + +xmlhttprequest-ssl@~1.5.4: + version "1.5.5" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" + integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^3.2.0, y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" + integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== + dependencies: + camelcase "^4.1.0" + +yargs-parser@^13.0.0, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^4.1.0, yargs-parser@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" + integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw= + dependencies: + camelcase "^3.0.0" + +yargs@6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.4.0.tgz#816e1a866d5598ccf34e5596ddce22d92da490d4" + integrity sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ= + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^4.1.0" + +yargs@6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" + +yargs@^13.2.2: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + +yargs@^3.32.0: + version "3.32.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" + integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= + dependencies: + camelcase "^2.0.1" + cliui "^3.0.3" + decamelize "^1.1.1" + os-locale "^1.4.0" + string-width "^1.0.1" + window-size "^0.1.4" + y18n "^3.2.0" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" + integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + +yup@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.27.0.tgz#f8cb198c8e7dd2124beddc2457571329096b06e7" + integrity sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ== + dependencies: + "@babel/runtime" "^7.0.0" + fn-name "~2.0.1" + lodash "^4.17.11" + property-expr "^1.5.0" + synchronous-promise "^2.0.6" + toposort "^2.0.2" From c18c3477c03240c1e427de08247e1ae5ed7563df Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 Aug 2019 09:22:58 +1000 Subject: [PATCH 013/746] Whoops! --- test/TemplateConfigTest.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 0da664515..403b88cd0 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -312,10 +312,21 @@ test("libraryOverrides", t => { }); test("Properly throws error on missing module #182", t => { - let templateCfg = new TemplateConfig( - require("../config.js"), - "./test/stubs/config.js" - ); + t.throws(function() { + new TemplateConfig( + require("../config.js"), + "./test/stubs/broken-config.js" + ); + }); +}); + +test("Properly throws error when config returns a Promise", t => { + t.throws(function() { + new TemplateConfig( + require("../config.js"), + "./test/stubs/config-promise.js" + ); + }); }); test(".addWatchTarget adds a watch target", t => { @@ -329,12 +340,3 @@ test(".addWatchTarget adds a watch target", t => { let cfg = templateCfg.getConfig(); t.deepEqual(cfg.additionalWatchTargets, ["/testdirectory/"]); }); - -test("Properly throws error when config returns a Promise", t => { - t.throws(function() { - new TemplateConfig( - require("../config.js"), - "./test/stubs/config-promise.js" - ); - }); -}); From 308b9e57d2b5438b7f5b895d09b2dc2bc41e8935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Thu, 20 Jun 2019 20:14:43 +0200 Subject: [PATCH 014/746] docs(jsdoc): basic setup of JSDoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Jaenisch --- .gitignore | 3 ++- .jsdoc.conf.json | 11 +++++++++++ package.json | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .jsdoc.conf.json diff --git a/.gitignore b/.gitignore index 7ac8ecb61..fe7a66ecf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ _site/ node_modules/ .nyc_output/ coverage/ -package-lock.json \ No newline at end of file +package-lock.json +api-docs/ \ No newline at end of file diff --git a/.jsdoc.conf.json b/.jsdoc.conf.json new file mode 100644 index 000000000..a12230dce --- /dev/null +++ b/.jsdoc.conf.json @@ -0,0 +1,11 @@ +{ + "plugins": ["plugins/markdown"], + "templates": { + "systemName": "Eleventy", + "theme": "cosmo", + "navType": "vertical", + "inverseNav": true, + "syntaxTheme": "dark", + "search": false + } +} diff --git a/package.json b/package.json index 53a81d067..f98a1b971 100755 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ }, "scripts": { "default": "npm run test", + "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/**/*.js", "test": "npx ava --verbose", "lint-staged": "lint-staged", "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js" @@ -68,6 +69,8 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^2.0.3", "ava": "^2.2.0", + "ink-docstrap": "1.3.2", + "jsdoc": "3.6.2", "lint-staged": "^8.2.1", "markdown-it-emoji": "^1.4.0", "nyc": "^14.1.1", From e3c7e3b92c8ba0832893d5c94a7da5283feb499e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Thu, 20 Jun 2019 20:54:34 +0200 Subject: [PATCH 015/746] docs(Eleventy): document Eleventy constructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Jaenisch --- package.json | 2 +- src/Eleventy.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f98a1b971..b01df4f8d 100755 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ }, "scripts": { "default": "npm run test", - "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/**/*.js", + "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/*.js", "test": "npx ava --verbose", "lint-staged": "lint-staged", "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js" diff --git a/src/Eleventy.js b/src/Eleventy.js index ad3e92a78..e93293465 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -11,22 +11,68 @@ const config = require("./Config"); const bench = require("./BenchmarkManager"); const debug = require("debug")("Eleventy"); +/** + * @module @11ty/eleventy/Eleventy + */ + +/** + * Runtime of eleventy. + * + * @param {String} input - Where to read files from. + * @param {Output} output - Where to write rendered files to. + * @returns {undefined} + */ class Eleventy { constructor(input, output) { + /** @member {Object} - tbd. */ this.config = config.getConfig(); + + /** + * @member {String} - The path to Eleventy's config file. + * @default null + */ this.configPath = null; + + /** + * @member {Boolean} - Is Eleventy running in verbose mode? + * @default true + */ this.isVerbose = true; + + /** + * @member {Boolean} - Is Eleventy running in debug mode? + * @default false + */ this.isDebug = false; + + /** + * @member {Boolean} - Is Eleventy running in dry mode? + * @default false + */ this.isDryRun = false; + /** @member {Date} - The time of instantiation. */ this.start = new Date(); + + /** + * @member {Array} - Subset of template types. + * @default null + */ this.formatsOverride = null; + + /** @member {Object} - tbd. */ this.eleventyServe = new EleventyServe(); + /** @member {String} - Holds the path to the input directory. */ this.rawInput = input; + + /** @member {String} - Holds the path to the output directory. */ this.rawOutput = output; + /** @member {Object} - tbd. */ this.watchTargets = new EleventyWatchTargets(); + + /** @member {Object} - tbd. */ this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; } From 534e7ac4d8d5b2f711282f633a2fcc25d4d3563a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Fri, 28 Jun 2019 20:59:32 +0200 Subject: [PATCH 016/746] docs(Eleventy): add docstrings to Eleventy class. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Jaenisch --- .jsdoc.conf.json | 12 ++-- src/Eleventy.js | 147 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 6 deletions(-) diff --git a/.jsdoc.conf.json b/.jsdoc.conf.json index a12230dce..371494113 100644 --- a/.jsdoc.conf.json +++ b/.jsdoc.conf.json @@ -1,11 +1,11 @@ { "plugins": ["plugins/markdown"], "templates": { - "systemName": "Eleventy", - "theme": "cosmo", - "navType": "vertical", - "inverseNav": true, - "syntaxTheme": "dark", - "search": false + "systemName": "Eleventy", + "theme": "cosmo", + "navType": "vertical", + "inverseNav": true, + "syntaxTheme": "dark", + "search": false } } diff --git a/src/Eleventy.js b/src/Eleventy.js index e93293465..a7891eb4d 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -76,14 +76,17 @@ class Eleventy { this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; } + /** @type {String} */ get input() { return this.rawInput || this.config.dir.input; } + /** @type {String} */ get inputDir() { return TemplatePath.getDir(this.input); } + /** @type {String} */ get outputDir() { let dir = this.rawOutput || this.config.dir.output; if (dir !== this._savedOutputDir) { @@ -94,14 +97,32 @@ class Eleventy { return dir; } + /** + * Updates the dry-run mode of Eleventy. + * + * @method + * @param {Boolean} isDryRun - Shall Eleventy run in dry mode? + */ setDryRun(isDryRun) { this.isDryRun = !!isDryRun; } + /** + * Updates the passthrough mode of Eleventy. + * + * @method + * @param {Boolean} isPassthroughAll - Shall Eleventy passthrough everything? + */ setPassthroughAll(isPassthroughAll) { this.isPassthroughAll = !!isPassthroughAll; } + /** + * Updates the path prefix used in the config. + * + * @method + * @param {String} pathPrefix - The new path prefix. + */ setPathPrefix(pathPrefix) { if (pathPrefix || pathPrefix === "") { config.setPathPrefix(pathPrefix); @@ -109,10 +130,22 @@ class Eleventy { } } + /** + * Updates the watch targets. + * + * @method + * @param {} watchTargets - The new watch targets. + */ setWatchTargets(watchTargets) { this.watchTargets = watchTargets; } + /** + * Updates the config path. + * + * @method + * @param {String} configPath - The new config path. + */ setConfigPathOverride(configPath) { if (configPath) { this.configPath = configPath; @@ -122,6 +155,12 @@ class Eleventy { } } + /** + * Restarts Eleventy. + * + * @async + * @method + */ async restart() { debug("Restarting"); this.start = new Date(); @@ -136,6 +175,11 @@ class Eleventy { await this.init(); } + /** + * Marks the finish of a run of Eleventy. + * + * @method + */ finish() { bench.finish(); @@ -143,6 +187,12 @@ class Eleventy { debug("Finished writing templates."); } + /** + * Logs some statistics after a complete run of Eleventy. + * + * @method + * @returns {String} ret - The log message. + */ logFinished() { if (!this.writer) { throw new Error( @@ -184,6 +234,13 @@ class Eleventy { return ret.join(" "); } + /** + * Starts Eleventy. + * + * @async + * @method + * @returns {} - tbd. + */ async init() { let formats = this.formatsOverride || this.config.templateFormats; this.eleventyFiles = new EleventyFiles( @@ -222,10 +279,22 @@ Template Formats: ${formats.join(",")}`); return this.templateData.cacheData(); } + /** + * Updates the debug mode of Eleventy. + * + * @method + * @param {Boolean} isDebug - Shall Eleventy run in debug mode? + */ setIsDebug(isDebug) { this.isDebug = !!isDebug; } + /** + * Updates the verbose mode of Eleventy. + * + * @method + * @param {Boolean} isVerbose - Shall Eleventy run in verbose mode? + */ setIsVerbose(isVerbose) { this.isVerbose = !!isVerbose; @@ -237,16 +306,34 @@ Template Formats: ${formats.join(",")}`); } } + /** + * Updates the template formats of Eleventy. + * + * @method + * @param {String} formats - The new template formats. + */ setFormats(formats) { if (formats && formats !== "*") { this.formatsOverride = formats.split(","); } } + /** + * Reads the version of Eleventy. + * + * @method + * @returns {String} - The version of Eleventy. + */ getVersion() { return require("../package.json").version; } + /** + * Shows a help message including usage. + * + * @method + * @returns {String} - The help mesage. + */ getHelp() { return `usage: eleventy eleventy --input=. --output=./_site @@ -275,6 +362,11 @@ Arguments: --help`; } + /** + * Resets the config of Eleventy. + * + * @method + */ resetConfig() { config.reset(); @@ -282,6 +374,13 @@ Arguments: this.eleventyServe.config = this.config; } + /** + * tbd. + * + * @private + * @method + * @param {String} path - Watch this file. + */ async _watch(path) { if (path) { path = TemplatePath.addLeadingDotSlash(path); @@ -328,10 +427,21 @@ Arguments: } } + /** + * tbd. + * + * @returns {} - tbd. + */ get watcherBench() { return bench.get("Watcher"); } + /** + * Set up watchers and benchmarks. + * + * @async + * @method + */ async initWatch() { this.watchTargets.add(this.eleventyFiles.getGlobWatcherFiles()); @@ -351,6 +461,13 @@ Arguments: benchmark.after(); } + /** + * Starts watching dependencies. + * + * @private + * @async + * @method + */ async _initWatchDependencies() { if (!this.watchTargets.watchJavaScriptDependencies) { return; @@ -381,10 +498,23 @@ Arguments: ); } + /** + * Returns all watched files. + * + * @async + * @method + * @returns {} targets - The watched files. + */ async getWatchedFiles() { return this.watchTargets.getTargets(); } + /** + * Start the watching of files. + * + * @async + * @method + */ async watch() { this.watcherBench.setMinimumThresholdMs(500); this.watcherBench.reset(); @@ -448,15 +578,32 @@ Arguments: ); } + /** + * Serve Eleventy on this port. + * + * @param {Number} port - The HTTP port to serve Eleventy from. + */ serve(port) { this.eleventyServe.serve(port); } /* For testing */ + /** + * Updates the logger. + * + * @param {} logger - The new logger. + */ setLogger(logger) { this.logger = logger; } + /** + * tbd. + * + * @async + * @method + * @returns {Promise<{}>} ret - tbd. + */ async write() { let ret; if (this.logger) { From bdd8a69853fa9d81fbd3a385c4358387cb9fb0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Tue, 16 Jul 2019 19:09:30 +0200 Subject: [PATCH 017/746] Fix brain fart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Peter Müller --- src/Eleventy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index a7891eb4d..ec0609ab8 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -19,7 +19,7 @@ const debug = require("debug")("Eleventy"); * Runtime of eleventy. * * @param {String} input - Where to read files from. - * @param {Output} output - Where to write rendered files to. + * @param {String} output - Where to write rendered files to. * @returns {undefined} */ class Eleventy { From 5118d6088a32343662460ca54d89330af619034d Mon Sep 17 00:00:00 2001 From: Gareth Cornish Date: Mon, 5 Aug 2019 18:53:28 +0200 Subject: [PATCH 018/746] Pass current template data to the Markdown engine --- src/Engines/Markdown.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index f064c5f21..8bb5db65d 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -69,7 +69,7 @@ class Markdown extends TemplateEngine { } else { return async function(data) { let preTemplateEngineRender = await fn(data); - let finishedRender = mdlib.render(preTemplateEngineRender); + let finishedRender = mdlib.render(preTemplateEngineRender, data); return finishedRender; }; } @@ -79,9 +79,8 @@ class Markdown extends TemplateEngine { return str; }; } else { - return function() { - // throw away data if preTemplateEngine is falsy - return mdlib.render(str); + return function(data) { + return mdlib.render(str, data); }; } } From 4d5d33a3cc66d92d8814a55b1c3af46cc4dcd411 Mon Sep 17 00:00:00 2001 From: Gareth Cornish Date: Tue, 6 Aug 2019 07:30:31 +0200 Subject: [PATCH 019/746] Add tests to see that we send context data through Markdown to plugins --- test/TemplateRenderMarkdownPluginTest.js | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 test/TemplateRenderMarkdownPluginTest.js diff --git a/test/TemplateRenderMarkdownPluginTest.js b/test/TemplateRenderMarkdownPluginTest.js new file mode 100644 index 000000000..7da6d7549 --- /dev/null +++ b/test/TemplateRenderMarkdownPluginTest.js @@ -0,0 +1,43 @@ +import test from "ava"; +import TemplateRender from "../src/TemplateRender"; +import md from "markdown-it"; + +const createTestMarkdownPlugin = () => { + const plugin = md => { + md.core.ruler.after("inline", "replace-link", function(state) { + plugin.environment = state.env; + return false; + }); + }; + plugin.environment = {}; + return plugin; +}; + +test("Markdown Render: with HTML prerender, sends context data to the markdown library", async t => { + let tr = new TemplateRender("md"); + + const plugin = createTestMarkdownPlugin(); + let mdLib = md().use(plugin); + tr.engine.setLibrary(mdLib); + + const data = { some: "data" }; + + let fn = await tr.getCompiledTemplate("[link text](http://link.com)"); + let result = await fn(data); + t.deepEqual(plugin.environment, data); +}); + +test("Markdown Render: without HTML prerender, sends context data to the markdown library", async t => { + let tr = new TemplateRender("md"); + + const plugin = createTestMarkdownPlugin(); + let mdLib = md().use(plugin); + tr.engine.setLibrary(mdLib); + tr.setHtmlEngine(false); + + const data = { some: "data" }; + + let fn = await tr.getCompiledTemplate("[link text](http://link.com)"); + let result = await fn(data); + t.deepEqual(plugin.environment, data); +}); From 47431cdbff5495b1eeb0a678d690cd8ff4061fe0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 29 Aug 2019 21:09:44 -0500 Subject: [PATCH 020/746] Fixes #429, adds promise/async support for shortcodes in Nunjucks (they were already working in Liquid). --- src/Engines/Nunjucks.js | 65 +++++++++++++++++++-------- src/UserConfig.js | 70 +++++++++++++++++++++++++----- test/TemplateRenderLiquidTest.js | 35 +++++++++++++++ test/TemplateRenderNunjucksTest.js | 43 ++++++++++++++++++ 4 files changed, 183 insertions(+), 30 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 3a6e81579..9b5b5b0ed 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -26,7 +26,12 @@ class Nunjucks extends TemplateEngine { // TODO these all go to the same place (addTag), add warnings for overwrites this.addCustomTags(this.config.nunjucksTags); this.addAllShortcodes(this.config.nunjucksShortcodes); + this.addAllShortcodes(this.config.nunjucksAsyncShortcodes, true); this.addAllPairedShortcodes(this.config.nunjucksPairedShortcodes); + this.addAllPairedShortcodes( + this.config.nunjucksAsyncPairedShortcodes, + true + ); } addFilters(helpers, isAsync) { @@ -54,19 +59,19 @@ class Nunjucks extends TemplateEngine { this.njkEnv.addExtension(name, tagObj); } - addAllShortcodes(shortcodes) { + addAllShortcodes(shortcodes, isAsync = false) { for (let name in shortcodes) { - this.addShortcode(name, shortcodes[name]); + this.addShortcode(name, shortcodes[name], isAsync); } } - addAllPairedShortcodes(shortcodes) { + addAllPairedShortcodes(shortcodes, isAsync = false) { for (let name in shortcodes) { - this.addPairedShortcode(name, shortcodes[name]); + this.addPairedShortcode(name, shortcodes[name], isAsync); } } - addShortcode(shortcodeName, shortcodeFn) { + addShortcode(shortcodeName, shortcodeFn, isAsync = false) { function ShortcodeFunction() { this.tags = [shortcodeName]; @@ -85,23 +90,36 @@ class Nunjucks extends TemplateEngine { parser.advanceAfterBlockEnd(tok.value); - // return new nodes.CallExtensionAsync(this, "run", args); - return new nodes.CallExtension(this, "run", args); + if (isAsync) { + return new nodes.CallExtensionAsync(this, "run", args); + } else { + return new nodes.CallExtension(this, "run", args); + } }; this.run = function(...args) { - // let callback = args.pop(); + let callback; + if (isAsync) { + callback = args.pop(); + } + let [context, ...argArray] = args; - let ret = new NunjucksLib.runtime.SafeString(shortcodeFn(...argArray)); - // callback(null, ret); - return ret; + let fnReturnValue = shortcodeFn(...argArray); + + if (isAsync && fnReturnValue.then) { + fnReturnValue.then(function(returnValue) { + callback(null, returnValue); + }); + } else { + return new NunjucksLib.runtime.SafeString(fnReturnValue); + } }; } this.njkEnv.addExtension(shortcodeName, new ShortcodeFunction()); } - addPairedShortcode(shortcodeName, shortcodeFn) { + addPairedShortcode(shortcodeName, shortcodeFn, isAsync = false) { function PairedShortcodeFunction() { this.tags = [shortcodeName]; @@ -114,19 +132,28 @@ class Nunjucks extends TemplateEngine { var body = parser.parseUntilBlocks("end" + shortcodeName); parser.advanceAfterBlockEnd(); - // return new nodes.CallExtensionAsync(this, "run", args, [body]); + if (isAsync) { + return new nodes.CallExtensionAsync(this, "run", args, [body]); + } return new nodes.CallExtension(this, "run", args, [body]); }; this.run = function(...args) { - // let callback = args.pop(); + let callback; + if (isAsync) { + callback = args.pop(); + } let body = args.pop(); let [context, ...argArray] = args; - let ret = new NunjucksLib.runtime.SafeString( - shortcodeFn(body(), ...argArray) - ); - // callback(null, ret); - return ret; + let fnReturnValue = shortcodeFn(body(), ...argArray); + + if (isAsync && fnReturnValue.then) { + fnReturnValue.then(function(returnValue) { + callback(null, returnValue); + }); + } else { + return new NunjucksLib.runtime.SafeString(fnReturnValue); + } }; } diff --git a/src/UserConfig.js b/src/UserConfig.js index 6a1ebe5b1..76fa25ad3 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -29,7 +29,9 @@ class UserConfig { this.nunjucksAsyncFilters = {}; this.nunjucksTags = {}; this.nunjucksShortcodes = {}; + this.nunjucksAsyncShortcodes = {}; this.nunjucksPairedShortcodes = {}; + this.nunjucksAsyncPairedShortcodes = {}; this.handlebarsHelpers = {}; this.handlebarsShortcodes = {}; this.handlebarsPairedShortcodes = {}; @@ -134,7 +136,7 @@ class UserConfig { } // Support the nunjucks style syntax for asynchronous filter add - addNunjucksFilter(name, callback, isAsync) { + addNunjucksFilter(name, callback, isAsync = false) { if (isAsync) { // namespacing happens downstream this.addNunjucksAsyncFilter(name, callback); @@ -344,24 +346,46 @@ class UserConfig { this.addJavaScriptFunction(name, callback); } - addNunjucksShortcode(name, callback) { + addNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); - if (this.nunjucksShortcodes[name]) { + if (this.nunjucksAsyncShortcodes[name]) { debug( chalk.yellow( - "Warning, overwriting a Nunjucks Shortcode with `addNunjucksShortcode(%o)`" + "Warning, overwriting a Nunjucks Async Shortcode with `addNunjucksAsyncShortcode(%o)`" ), name ); } - this.nunjucksShortcodes[name] = bench.add( - `"${name}" Nunjucks Shortcode`, + this.nunjucksAsyncShortcodes[name] = bench.add( + `"${name}" Nunjucks Async Shortcode`, callback ); } + addNunjucksShortcode(name, callback, isAsync = false) { + if (isAsync) { + this.addNunjucksAsyncShortcode(name, callback); + } else { + name = this.getNamespacedName(name); + + if (this.nunjucksShortcodes[name]) { + debug( + chalk.yellow( + "Warning, overwriting a Nunjucks Shortcode with `addNunjucksShortcode(%o)`" + ), + name + ); + } + + this.nunjucksShortcodes[name] = bench.add( + `"${name}" Nunjucks Shortcode`, + callback + ); + } + } + addLiquidShortcode(name, callback) { name = this.getNamespacedName(name); @@ -405,24 +429,46 @@ class UserConfig { this.addJavaScriptFunction(name, callback); } - addPairedNunjucksShortcode(name, callback) { + addPairedNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); - if (this.nunjucksPairedShortcodes[name]) { + if (this.nunjucksAsyncPairedShortcodes[name]) { debug( chalk.yellow( - "Warning, overwriting a Nunjucks Paired Shortcode with `addPairedNunjucksShortcode(%o)`" + "Warning, overwriting a Nunjucks Async Paired Shortcode with `addPairedNunjucksAsyncShortcode(%o)`" ), name ); } - this.nunjucksPairedShortcodes[name] = bench.add( - `"${name}" Nunjucks Paired Shortcode`, + this.nunjucksAsyncPairedShortcodes[name] = bench.add( + `"${name}" Nunjucks Async Paired Shortcode`, callback ); } + addPairedNunjucksShortcode(name, callback, isAsync = false) { + if (isAsync) { + this.addPairedNunjucksAsyncShortcode(name, callback); + } else { + name = this.getNamespacedName(name); + + if (this.nunjucksPairedShortcodes[name]) { + debug( + chalk.yellow( + "Warning, overwriting a Nunjucks Paired Shortcode with `addPairedNunjucksShortcode(%o)`" + ), + name + ); + } + + this.nunjucksPairedShortcodes[name] = bench.add( + `"${name}" Nunjucks Paired Shortcode`, + callback + ); + } + } + addPairedLiquidShortcode(name, callback) { name = this.getNamespacedName(name); @@ -516,7 +562,9 @@ class UserConfig { nunjucksFilters: this.nunjucksFilters, nunjucksAsyncFilters: this.nunjucksAsyncFilters, nunjucksTags: this.nunjucksTags, + nunjucksAsyncShortcodes: this.nunjucksAsyncShortcodes, nunjucksShortcodes: this.nunjucksShortcodes, + nunjucksAsyncPairedShortcodes: this.nunjucksAsyncPairedShortcodes, nunjucksPairedShortcodes: this.nunjucksPairedShortcodes, handlebarsHelpers: this.handlebarsHelpers, handlebarsShortcodes: this.handlebarsShortcodes, diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 0bed58f5c..38f6ac3ac 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -206,6 +206,22 @@ test("Liquid Shortcode", async t => { ); }); +test("Liquid Async Shortcode", async t => { + let tr = new TemplateRender("liquid", "./test/stubs/"); + tr.engine.addShortcode("postfixWithZach", function(str) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(str + "Zach"); + }); + }); + }); + + t.is( + await tr.render("{% postfixWithZach name %}", { name: "test" }), + "testZach" + ); +}); + test("Liquid Shortcode Safe Output", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { @@ -233,6 +249,25 @@ test("Liquid Paired Shortcode", async t => { ); }); +test("Liquid Async Paired Shortcode", async t => { + let tr = new TemplateRender("liquid", "./test/stubs/"); + tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(str + content + "Zach"); + }); + }); + }); + + t.is( + await tr.render( + "{% postfixWithZach name %}Content{% endpostfixWithZach %}", + { name: "test" } + ), + "testContentZach" + ); +}); + test("Liquid Render Include Subfolder", async t => { let fn = await new TemplateRender( "liquid", diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index d6ae963a2..241c1eb8f 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -246,6 +246,26 @@ test("Nunjucks Shortcode", async t => { ); }); +test("Nunjucks Async Shortcode", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addShortcode( + "postfixWithZach", + function(str) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(str + "Zach"); + }); + }); + }, + true + ); + + t.is( + await tr.render("{% postfixWithZach name %}", { name: "test" }), + "testZach" + ); +}); + test("Nunjucks Shortcode Safe Output", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { @@ -273,6 +293,29 @@ test("Nunjucks Paired Shortcode", async t => { ); }); +test("Nunjucks Async Paired Shortcode", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addPairedShortcode( + "postfixWithZach", + function(content, str) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(str + content + "Zach"); + }); + }); + }, + true + ); + + t.is( + await tr.render( + "{% postfixWithZach name %}Content{% endpostfixWithZach %}", + { name: "test" } + ), + "testContentZach" + ); +}); + test("Nunjucks Paired Shortcode without args", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content) { From d27cbd10cc4726678930e1467f0a0355a35ea2f2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 29 Aug 2019 21:24:36 -0500 Subject: [PATCH 021/746] Also added a test to show that this works with JavaScript template functions too. #429 --- test/TemplateRenderJavaScriptTest.js | 17 +++++++++++++++++ test/stubs/function-async-filter.11ty.js | 3 +++ 2 files changed, 20 insertions(+) create mode 100644 test/stubs/function-async-filter.11ty.js diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 80e78a690..3fd0c1631 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -174,6 +174,23 @@ test("JS Render with a function", async t => { t.is(await fn({ name: "Bill" }), "

BILLT9000

"); }); +test("JS Render with a function and async filter", async t => { + let tr = new TemplateRender("./test/stubs/function-async-filter.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(val) { + return new Promise(function(resolve) { + resolve(new String(val).toUpperCase()); + }); + } + } + }; + + let fn = await tr.getCompiledTemplate(); + t.is(await fn({ name: "Zach" }), "

ZACH

"); + t.is(await fn({ name: "Bill" }), "

BILL

"); +}); + test("JS Render with a function prototype", async t => { let tr = new TemplateRender("./test/stubs/function-prototype.11ty.js"); tr.config = { diff --git a/test/stubs/function-async-filter.11ty.js b/test/stubs/function-async-filter.11ty.js new file mode 100644 index 000000000..f71aab968 --- /dev/null +++ b/test/stubs/function-async-filter.11ty.js @@ -0,0 +1,3 @@ +module.exports = async function({ name }) { + return `

${await this.upper(name)}

`; +}; From a3c0b8906676c22a9312d8cdcca49f576587c269 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 29 Aug 2019 21:59:58 -0500 Subject: [PATCH 022/746] Oops needed safe string here #429 --- src/Engines/Nunjucks.js | 4 ++-- src/UserConfig.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 9b5b5b0ed..f451b0965 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -108,7 +108,7 @@ class Nunjucks extends TemplateEngine { if (isAsync && fnReturnValue.then) { fnReturnValue.then(function(returnValue) { - callback(null, returnValue); + callback(null, new NunjucksLib.runtime.SafeString(returnValue)); }); } else { return new NunjucksLib.runtime.SafeString(fnReturnValue); @@ -149,7 +149,7 @@ class Nunjucks extends TemplateEngine { if (isAsync && fnReturnValue.then) { fnReturnValue.then(function(returnValue) { - callback(null, returnValue); + callback(null, new NunjucksLib.runtime.SafeString(returnValue)); }); } else { return new NunjucksLib.runtime.SafeString(fnReturnValue); diff --git a/src/UserConfig.js b/src/UserConfig.js index 76fa25ad3..b7e157bca 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -346,6 +346,14 @@ class UserConfig { this.addJavaScriptFunction(name, callback); } + addAsyncShortcode(name, callback) { + debug("Adding universal async shortcode %o", this.getNamespacedName(name)); + this.addNunjucksAsyncShortcode(name, callback); + this.addLiquidShortcode(name, callback); + // this.addHandlebarsShortcode(name, callback); // not supported in Handlebars + this.addJavaScriptFunction(name, callback); + } + addNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); @@ -429,6 +437,14 @@ class UserConfig { this.addJavaScriptFunction(name, callback); } + addPairedAsyncShortcode(name, callback) { + debug("Adding universal async shortcode %o", this.getNamespacedName(name)); + this.addPairedNunjucksAsyncShortcode(name, callback); + this.addPairedLiquidShortcode(name, callback); + // this.addPairedHandlebarsShortcode(name, callback); // not supported in Handlebars + this.addJavaScriptFunction(name, callback); + } + addPairedNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); From 1b334de43ebf22f9a9b5a78805cff1934608f496 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 30 Aug 2019 17:52:06 +1000 Subject: [PATCH 023/746] Test a travis fix --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4468c9a8a..e3bc798be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,4 +13,5 @@ sudo: false os: - linux - osx - - windows \ No newline at end of file + - windows +YARN_GPG: no From a139ef8dd2d47e98ecc063f41e05775b7d8817c8 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 30 Aug 2019 18:03:07 +1000 Subject: [PATCH 024/746] Come'mon Mike, you knew it was ment to be an env var --- .travis.yml | 3 ++- .vscode/settings.json | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json diff --git a/.travis.yml b/.travis.yml index e3bc798be..e7614af13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,5 @@ os: - linux - osx - windows -YARN_GPG: no +env: + - YARN_GPG=no diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..564228219 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "workbench.colorCustomizations": {} +} \ No newline at end of file From b58f9960094fc5a565a12f5e814f6dd53d7c95da Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Aug 2019 08:31:13 -0500 Subject: [PATCH 025/746] More tests to verify stuff from docs for #429 #672 --- src/UserConfig.js | 16 ------------- test/TemplateRenderLiquidTest.js | 34 +++++++++++++++++++++++++- test/TemplateRenderNunjucksTest.js | 38 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index b7e157bca..76fa25ad3 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -346,14 +346,6 @@ class UserConfig { this.addJavaScriptFunction(name, callback); } - addAsyncShortcode(name, callback) { - debug("Adding universal async shortcode %o", this.getNamespacedName(name)); - this.addNunjucksAsyncShortcode(name, callback); - this.addLiquidShortcode(name, callback); - // this.addHandlebarsShortcode(name, callback); // not supported in Handlebars - this.addJavaScriptFunction(name, callback); - } - addNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); @@ -437,14 +429,6 @@ class UserConfig { this.addJavaScriptFunction(name, callback); } - addPairedAsyncShortcode(name, callback) { - debug("Adding universal async shortcode %o", this.getNamespacedName(name)); - this.addPairedNunjucksAsyncShortcode(name, callback); - this.addPairedLiquidShortcode(name, callback); - // this.addPairedHandlebarsShortcode(name, callback); // not supported in Handlebars - this.addJavaScriptFunction(name, callback); - } - addPairedNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 38f6ac3ac..315b80a51 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1,6 +1,14 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +async function getPromise(resolveTo) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(resolveTo); + }); + }); +} + // Liquid test("Liquid", t => { t.is(new TemplateRender("liquid").getEngineName(), "liquid"); @@ -206,7 +214,7 @@ test("Liquid Shortcode", async t => { ); }); -test("Liquid Async Shortcode", async t => { +test("Liquid Shortcode returns promise", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { return new Promise(function(resolve) { @@ -222,6 +230,30 @@ test("Liquid Async Shortcode", async t => { ); }); +test("Liquid Shortcode returns promise (await inside)", async t => { + let tr = new TemplateRender("liquid", "./test/stubs/"); + tr.engine.addShortcode("postfixWithZach", async function(str) { + return await getPromise(str + "Zach"); + }); + + t.is( + await tr.render("{% postfixWithZach name %}", { name: "test" }), + "testZach" + ); +}); + +test("Liquid Shortcode returns promise (no await inside)", async t => { + let tr = new TemplateRender("liquid", "./test/stubs/"); + tr.engine.addShortcode("postfixWithZach", async function(str) { + return getPromise(str + "Zach"); + }); + + t.is( + await tr.render("{% postfixWithZach name %}", { name: "test" }), + "testZach" + ); +}); + test("Liquid Shortcode Safe Output", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 241c1eb8f..53bf64800 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -1,6 +1,14 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +async function getPromise(resolveTo) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(resolveTo); + }); + }); +} + // Nunjucks test("Nunjucks", t => { t.is(new TemplateRender("njk").getEngineName(), "njk"); @@ -266,6 +274,22 @@ test("Nunjucks Async Shortcode", async t => { ); }); +test("Nunjucks Async function Shortcode", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addShortcode( + "postfixWithZach", + async function(str) { + return await getPromise(str + "Zach"); + }, + true + ); + + t.is( + await tr.render("{% postfixWithZach name %}", { name: "test" }), + "testZach" + ); +}); + test("Nunjucks Shortcode Safe Output", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { @@ -373,6 +397,20 @@ test("Nunjucks Shortcode Multiple Args", async t => { ); }); +test("Nunjucks Shortcode Multiple Args (Comma is not optional)", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addShortcode("postfixWithZach", function(str, str2) { + return str + str2 + "Zach"; + }); + + await t.throwsAsync(async () => { + await tr.render("{% postfixWithZach name other %}", { + name: "test", + other: "howdy" + }); + }); +}); + test("Nunjucks Shortcode Named Args", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { From f5b878efe17189849e4d5dde16fa7ef1ff463dcc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 5 Sep 2019 08:04:44 -0500 Subject: [PATCH 026/746] A bunch of work to make sure that throwing errors inside shortcodes outputs readable errors (especially when they are async). Related to #429. Fixes #681 --- cmd.js | 9 +- src/EleventyBaseError.js | 8 +- src/EleventyErrorHandler.js | 13 +- src/EleventyErrorUtil.js | 54 ++++++++ src/Engines/Nunjucks.js | 69 +++++++--- src/Engines/TemplateEngine.js | 10 +- src/TemplateConfig.js | 29 +++-- src/TemplateRender.js | 4 +- src/UserConfig.js | 22 ++++ test/TemplateRenderJavaScriptTest.js | 46 +++++++ test/TemplateRenderLiquidTest.js | 100 ++++++++++----- test/TemplateRenderNunjucksTest.js | 152 +++++++++++++++++++---- test/stubs/function-throws-async.11ty.js | 3 + test/stubs/function-throws.11ty.js | 3 + 14 files changed, 424 insertions(+), 98 deletions(-) create mode 100644 test/stubs/function-throws-async.11ty.js create mode 100644 test/stubs/function-throws.11ty.js diff --git a/cmd.js b/cmd.js index c7bc2f964..b58ea1345 100755 --- a/cmd.js +++ b/cmd.js @@ -21,10 +21,13 @@ try { const EleventyCommandCheck = require("./src/EleventyCommandCheck"); process.on("unhandledRejection", (error, promise) => { - EleventyErrorHandler.error(promise, "Unhandled rejection in promise"); + EleventyErrorHandler.error( + error, + `Unhandled rejection in promise (${promise})` + ); }); - process.on("uncaughtException", e => { - EleventyErrorHandler.fatal(e, "Uncaught exception"); + process.on("uncaughtException", error => { + EleventyErrorHandler.fatal(error, "Uncaught exception"); }); process.on("rejectionHandled", promise => { EleventyErrorHandler.warn( diff --git a/src/EleventyBaseError.js b/src/EleventyBaseError.js index ef2b30e8a..b27ac7d32 100644 --- a/src/EleventyBaseError.js +++ b/src/EleventyBaseError.js @@ -1,10 +1,14 @@ class EleventyBaseError extends Error { constructor(message, originalError) { super(message); - Error.captureStackTrace(this, this.constructor); + this.name = this.constructor.name; - this.originalError = originalError; + Error.captureStackTrace(this, this.constructor); + + if (originalError) { + this.originalError = originalError; + } } } module.exports = EleventyBaseError; diff --git a/src/EleventyErrorHandler.js b/src/EleventyErrorHandler.js index b6d5caebb..a7fa95d08 100644 --- a/src/EleventyErrorHandler.js +++ b/src/EleventyErrorHandler.js @@ -1,4 +1,5 @@ const chalk = require("chalk"); +const EleventyErrorUtil = require("./EleventyErrorUtil"); const debug = require("debug")("Eleventy:EleventyErrorHandler"); class EleventyErrorHandler { @@ -32,13 +33,21 @@ class EleventyErrorHandler { EleventyErrorHandler.log(e, "error"); } + //https://nodejs.org/api/process.html static log(e, type = "log", prefix = ">") { let ref = e; while (ref) { let nextRef = ref.originalError; + if (!nextRef && EleventyErrorUtil.hasEmbeddedError(ref.message)) { + nextRef = EleventyErrorUtil.deconvertErrorToObject(ref); + } + EleventyErrorHandler.message( (process.env.DEBUG ? "" : `${prefix} `) + - `${ref.message.trim()} + `${( + EleventyErrorUtil.cleanMessage(ref.message) || + "(No error message provided)" + ).trim()} \`${ref.name}\` was thrown${!nextRef && ref.stack ? ":" : ""}`, type @@ -49,8 +58,8 @@ class EleventyErrorHandler { } else if (!nextRef) { // last error in the loop let prefix = " "; + // remove duplicate error messages if the stack contains the original message output above - // let stackStr = ref.stack || ""; if (e.removeDuplicateErrorStringFromOutput) { stackStr = stackStr.replace( diff --git a/src/EleventyErrorUtil.js b/src/EleventyErrorUtil.js index 73291c563..148730835 100644 --- a/src/EleventyErrorUtil.js +++ b/src/EleventyErrorUtil.js @@ -1,6 +1,60 @@ const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); +/* Hack to workaround the variety of error handling schemes in template languages */ class EleventyErrorUtil { + static get prefix() { + return ">>>>>11ty>>>>>"; + } + static get suffix() { + return "<<<<<11ty<<<<<"; + } + + static hasEmbeddedError(msg) { + if (!msg) { + return false; + } + + return ( + msg.indexOf(EleventyErrorUtil.prefix) > -1 && + msg.indexOf(EleventyErrorUtil.suffix) > -1 + ); + } + + static cleanMessage(msg) { + if (!msg || !EleventyErrorUtil.hasEmbeddedError(msg)) { + return msg; + } + + return msg.substr(0, msg.indexOf(EleventyErrorUtil.prefix)); + } + + static deconvertErrorToObject(error) { + if (!error || !error.message) { + throw new Error(`Could not convert error object from: ${error}`); + } + if (!EleventyErrorUtil.hasEmbeddedError(error.message)) { + return error; + } + + let msg = error.message; + let objectString = msg.substring( + msg.indexOf(EleventyErrorUtil.prefix) + EleventyErrorUtil.prefix.length, + msg.lastIndexOf(EleventyErrorUtil.suffix) + ); + let obj = JSON.parse(objectString); + obj.name = error.name; + return obj; + } + + // pass an error through a random template engine’s error handling unscathed + static convertErrorToString(error) { + return ( + EleventyErrorUtil.prefix + + JSON.stringify({ message: error.message, stack: error.stack }) + + EleventyErrorUtil.suffix + ); + } + static isPrematureTemplateContentError(e) { // TODO the rest of the template engines return ( diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index f451b0965..aa7af7252 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -1,6 +1,10 @@ const NunjucksLib = require("nunjucks"); const TemplateEngine = require("./TemplateEngine"); const TemplatePath = require("../TemplatePath"); +const EleventyErrorUtil = require("../EleventyErrorUtil"); +const EleventyBaseError = require("../EleventyBaseError"); + +class EleventyShortcodeError extends EleventyBaseError {} class Nunjucks extends TemplateEngine { constructor(name, includesDir) { @@ -92,9 +96,8 @@ class Nunjucks extends TemplateEngine { if (isAsync) { return new nodes.CallExtensionAsync(this, "run", args); - } else { - return new nodes.CallExtension(this, "run", args); } + return new nodes.CallExtension(this, "run", args); }; this.run = function(...args) { @@ -104,14 +107,32 @@ class Nunjucks extends TemplateEngine { } let [context, ...argArray] = args; - let fnReturnValue = shortcodeFn(...argArray); - if (isAsync && fnReturnValue.then) { - fnReturnValue.then(function(returnValue) { - callback(null, new NunjucksLib.runtime.SafeString(returnValue)); - }); + if (isAsync) { + shortcodeFn(...argArray) + .then(function(returnValue) { + callback(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function(e) { + callback( + new EleventyShortcodeError( + `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ), + null + ); + }); } else { - return new NunjucksLib.runtime.SafeString(fnReturnValue); + try { + return new NunjucksLib.runtime.SafeString(shortcodeFn(...argArray)); + } catch (e) { + throw new EleventyShortcodeError( + `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ); + } } }; } @@ -145,14 +166,34 @@ class Nunjucks extends TemplateEngine { } let body = args.pop(); let [context, ...argArray] = args; - let fnReturnValue = shortcodeFn(body(), ...argArray); - if (isAsync && fnReturnValue.then) { - fnReturnValue.then(function(returnValue) { - callback(null, new NunjucksLib.runtime.SafeString(returnValue)); - }); + if (isAsync) { + shortcodeFn(body(), ...argArray) + .then(function(returnValue) { + callback(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function(e) { + callback( + new EleventyShortcodeError( + `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ), + null + ); + }); } else { - return new NunjucksLib.runtime.SafeString(fnReturnValue); + try { + return new NunjucksLib.runtime.SafeString( + shortcodeFn(body(), ...argArray) + ); + } catch (e) { + throw new EleventyShortcodeError( + `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ); + } } }; } diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 780d5038e..b2dc8d7c2 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -97,10 +97,14 @@ class TemplateEngine { return this.engineLib; } - async render(str, data) { + async _testRender(str, data) { /* TODO compile needs to pass in inputPath? */ - let fn = await this.compile(str); - return fn(data); + try { + let fn = await this.compile(str); + return fn(data); + } catch (e) { + return Promise.reject(e); + } } // JavaScript files defer to the module loader rather than read the files to strings diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 903544c4d..dc395c01c 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -3,7 +3,6 @@ const chalk = require("chalk"); const lodashMerge = require("lodash/merge"); const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); -const dependencyTree = require("dependency-tree"); const eleventyConfig = require("./EleventyConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); @@ -82,6 +81,20 @@ class TemplateConfig { localConfig = require(path); // debug( "localConfig require return value: %o", localConfig ); + + if (typeof localConfig === "function") { + localConfig = localConfig(eleventyConfig); + // debug( "localConfig is a function, after calling, eleventyConfig is %o", eleventyConfig ); + + if ( + typeof localConfig === "object" && + typeof localConfig.then === "function" + ) { + throw new EleventyConfigError( + `Error in your Eleventy config file '${path}': Returning a promise is not supported` + ); + } + } } catch (err) { throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + @@ -95,20 +108,6 @@ class TemplateConfig { debug("Eleventy local project config file not found, skipping."); } - if (typeof localConfig === "function") { - localConfig = localConfig(eleventyConfig); - // debug( "localConfig is a function, after calling, eleventyConfig is %o", eleventyConfig ); - - if ( - typeof localConfig === "object" && - typeof localConfig.then === "function" - ) { - throw new EleventyConfigError( - `Error in your Eleventy config file '${path}': Returning a promise is not supported` - ); - } - } - let eleventyConfigApiMergingObject = eleventyConfig.getMergingConfigObject(); localConfig = lodashMerge(localConfig, eleventyConfigApiMergingObject); diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 0c1b4436b..64dbbe4f9 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -182,8 +182,8 @@ class TemplateRender { this.parseHtmlWith = htmlEngineName; } - async render(str, data) { - return this.engine.render(str, data); + async _testRender(str, data) { + return this.engine._testRender(str, data); } async getCompiledTemplate(str) { diff --git a/src/UserConfig.js b/src/UserConfig.js index 76fa25ad3..76df00d94 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -346,6 +346,15 @@ class UserConfig { this.addJavaScriptFunction(name, callback); } + // Undocumented method as a mitigation to reduce risk of #498 + addAsyncShortcode(name, callback) { + debug("Adding universal async shortcode %o", this.getNamespacedName(name)); + this.addNunjucksAsyncShortcode(name, callback); + this.addLiquidShortcode(name, callback); + this.addJavaScriptFunction(name, callback); + // not supported in Handlebars + } + addNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); @@ -423,12 +432,25 @@ class UserConfig { } addPairedShortcode(name, callback) { + debug("Adding universal paired shortcode %o", this.getNamespacedName(name)); this.addPairedNunjucksShortcode(name, callback); this.addPairedLiquidShortcode(name, callback); this.addPairedHandlebarsShortcode(name, callback); this.addJavaScriptFunction(name, callback); } + // Undocumented method as a mitigation to reduce risk of #498 + addPairedAsyncShortcode(name, callback) { + debug( + "Adding universal async paired shortcode %o", + this.getNamespacedName(name) + ); + this.addPairedNunjucksAsyncShortcode(name, callback); + this.addPairedLiquidShortcode(name, callback); + this.addJavaScriptFunction(name, callback); + // not supported in Handlebars + } + addPairedNunjucksAsyncShortcode(name, callback) { name = this.getNamespacedName(name); diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 3fd0c1631..330cc54f6 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -236,3 +236,49 @@ test("JS Class Async Render with a function", async t => { t.is(await fn({ name: "Zach" }), "

ZACHBillTed

"); t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); }); + +test("JS Class Async Render with a function (sync function, throws error)", async t => { + let tr = new TemplateRender("./test/stubs/function-throws.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(val) { + throw new Error( + "JS Class Async Render with a function (sync function, throws error)" + ); + } + } + }; + + let error = await t.throwsAsync(async () => { + let fn = await tr.getCompiledTemplate(); + await fn({ name: "Zach" }); + }); + t.true( + error.message.indexOf( + "JS Class Async Render with a function (sync function, throws error)" + ) > -1 + ); +}); + +test("JS Class Async Render with a function (async function, throws error)", async t => { + let tr = new TemplateRender("./test/stubs/function-throws-async.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: async function(val) { + throw new Error( + "JS Class Async Render with a function (async function, throws error)" + ); + } + } + }; + + let error = await t.throwsAsync(async () => { + let fn = await tr.getCompiledTemplate(); + await fn({ name: "Zach" }); + }); + t.true( + error.message.indexOf( + "JS Class Async Render with a function (async function, throws error)" + ) > -1 + ); +}); diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 315b80a51..83b0e16d0 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -108,7 +108,7 @@ test("Liquid Custom Filter", async t => { return "Zach" + val; }); - t.is(await tr.render("{{ 'test' | prefixWithZach }}", {}), "Zachtest"); + t.is(await tr._testRender("{{ 'test' | prefixWithZach }}", {}), "Zachtest"); }); test("Liquid Custom Tag prefixWithZach", async t => { @@ -126,7 +126,7 @@ test("Liquid Custom Tag prefixWithZach", async t => { }); t.is( - await tr.render("{% prefixWithZach name %}", { name: "test" }), + await tr._testRender("{% prefixWithZach name %}", { name: "test" }), "Zachtest" ); }); @@ -146,7 +146,7 @@ test("Liquid Custom Tag postfixWithZach", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -165,7 +165,7 @@ test("Liquid Custom Tag Unquoted String", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% testUnquotedStringTag _posts/2016-07-26-name-of-post.md %}", { name: "test" } ), @@ -197,7 +197,7 @@ test("Liquid addTags", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -209,7 +209,7 @@ test("Liquid Shortcode", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -225,7 +225,7 @@ test("Liquid Shortcode returns promise", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -237,7 +237,7 @@ test("Liquid Shortcode returns promise (await inside)", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -249,7 +249,7 @@ test("Liquid Shortcode returns promise (no await inside)", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -261,7 +261,7 @@ test("Liquid Shortcode Safe Output", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "test" ); }); @@ -273,7 +273,7 @@ test("Liquid Paired Shortcode", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", { name: "test" } ), @@ -292,7 +292,7 @@ test("Liquid Async Paired Shortcode", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", { name: "test" } ), @@ -507,7 +507,7 @@ test("Liquid Paired Shortcode with Tag Inside", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% if tester %}If{% endif %}{% endpostfixWithZach %}", { name: "test", tester: true } ), @@ -522,7 +522,7 @@ test("Liquid Nested Paired Shortcode", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% postfixWithZach name2 %}Content{% endpostfixWithZach %}{% endpostfixWithZach %}", { name: "test", name2: "test2" } ), @@ -537,7 +537,7 @@ test("Liquid Shortcode Multiple Args", async t => { }); t.is( - await tr.render("{% postfixWithZach name other %}", { + await tr._testRender("{% postfixWithZach name other %}", { name: "test", other: "howdy" }), @@ -560,7 +560,7 @@ test("Liquid Missing Filter Issue #183 (no strict_filters)", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); try { - await tr.render("{{ 'test' | prefixWithZach }}", {}); + await tr._testRender("{{ 'test' | prefixWithZach }}", {}); t.pass("Did not error."); } catch (e) { t.fail("Threw an error."); @@ -572,7 +572,7 @@ test("Liquid Missing Filter Issue #183", async t => { tr.engine.setLiquidOptions({ strict_filters: true }); try { - await tr.render("{{ 'test' | prefixWithZach }}", {}); + await tr._testRender("{{ 'test' | prefixWithZach }}", {}); t.fail("Did not error."); } catch (e) { t.pass("Threw an error."); @@ -606,7 +606,7 @@ test("Issue 347: Liquid addTags with space in argument", async t => { }); t.is( - await tr.render("{% issue347CustomTag 'te st' %}", { + await tr._testRender("{% issue347CustomTag 'te st' %}", { name: "slkdjflksdjf" }), "te stZach" @@ -620,7 +620,7 @@ test("Issue 347: Liquid Shortcode, string argument", async t => { }); t.is( - await tr.render("{% issue347 'test' %}", { name: "alkdsjfkslja" }), + await tr._testRender("{% issue347 'test' %}", { name: "alkdsjfkslja" }), "testZach" ); }); @@ -632,7 +632,7 @@ test("Issue 347: Liquid Shortcode string argument with space, double quotes", as }); t.is( - await tr.render('{% issue347b "test 2" "test 3" %}', { + await tr._testRender('{% issue347b "test 2" "test 3" %}', { name: "alkdsjfkslja" }), "test 2Zach" @@ -646,7 +646,7 @@ test("Issue 347: Liquid Shortcode string argument with space, single quotes", as }); t.is( - await tr.render("{% issue347 'test 2' %}", { name: "alkdsjfkslja" }), + await tr._testRender("{% issue347 'test 2' %}", { name: "alkdsjfkslja" }), "test 2Zach" ); }); @@ -658,7 +658,7 @@ test("Issue 347: Liquid Shortcode string argument with space, combination of quo }); t.is( - await tr.render("{% issue347 'test 2' \"test 3\" %}", { + await tr._testRender("{% issue347 'test 2' \"test 3\" %}", { name: "alkdsjfkslja" }), "test 2test 3Zach" @@ -672,7 +672,7 @@ test("Issue 347: Liquid Shortcode multiple arguments, comma separated", async t }); t.is( - await tr.render("{% issue347 'test 2', \"test 3\" %}", { + await tr._testRender("{% issue347 'test 2', \"test 3\" %}", { name: "alkdsjfkslja" }), "test 2test 3Zach" @@ -686,7 +686,9 @@ test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is an }); t.is( - await tr.render("{% issue347 'test 2', 3 %}", { name: "alkdsjfkslja" }), + await tr._testRender("{% issue347 'test 2', 3 %}", { + name: "alkdsjfkslja" + }), "test 23Zach" ); }); @@ -698,7 +700,9 @@ test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is a }); t.is( - await tr.render("{% issue347 'test 2', 3.23 %}", { name: "alkdsjfkslja" }), + await tr._testRender("{% issue347 'test 2', 3.23 %}", { + name: "alkdsjfkslja" + }), "test 23.23Zach" ); }); @@ -710,11 +714,11 @@ test("Issue 347: Liquid Shortcode boolean argument", async t => { }); t.is( - await tr.render("{% issue347 true %}", { name: "alkdsjfkslja" }), + await tr._testRender("{% issue347 true %}", { name: "alkdsjfkslja" }), "Zach" ); t.is( - await tr.render("{% issue347 false %}", { name: "alkdsjfkslja" }), + await tr._testRender("{% issue347 false %}", { name: "alkdsjfkslja" }), "Not Zach" ); }); @@ -731,7 +735,7 @@ test("Issue 347: Liquid Paired Shortcode with Spaces", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach 'My Name', 1234, \"Other\" %}Content{% endpostfixWithZach %}", { name: "test" } ), @@ -753,7 +757,7 @@ test("Issue 600: Liquid Shortcode argument page.url", async t => { }); t.is( - await tr.render("{% issue600 page.url %}", { + await tr._testRender("{% issue600 page.url %}", { page: { url: "alkdsjfkslja" } }), "alkdsjfksljaZach" @@ -767,7 +771,7 @@ test("Issue 600: Liquid Shortcode argument with dashes", async t => { }); t.is( - await tr.render("{% issue600b page-url %}", { + await tr._testRender("{% issue600b page-url %}", { "page-url": "alkdsjfkslja" }), "alkdsjfksljaZach" @@ -781,7 +785,7 @@ test("Issue 600: Liquid Shortcode argument with underscores", async t => { }); t.is( - await tr.render("{% issue600c page_url %}", { + await tr._testRender("{% issue600c page_url %}", { page_url: "alkdsjfkslja" }), "alkdsjfksljaZach" @@ -793,7 +797,7 @@ test.skip("Issue 611: Run a function", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); t.is( - await tr.render("{{ test() }}", { + await tr._testRender("{{ test() }}", { test: function() { return "alkdsjfksljaZach"; } @@ -801,3 +805,35 @@ test.skip("Issue 611: Run a function", async t => { "alkdsjfksljaZach" ); }); + +test("Liquid Shortcode (with sync function, error throwing)", async t => { + let tr = new TemplateRender("liquid", "./test/stubs/"); + tr.engine.addShortcode("postfixWithZach", function(str) { + throw new Error("Liquid Shortcode (with sync function, error throwing)"); + }); + + let error = await t.throwsAsync(async () => { + await tr._testRender("{% postfixWithZach name %}", { name: "test" }); + }); + t.true( + error.message.indexOf( + "Liquid Shortcode (with sync function, error throwing)" + ) > -1 + ); +}); + +test("Liquid Shortcode (with async function, error throwing)", async t => { + let tr = new TemplateRender("liquid", "./test/stubs/"); + tr.engine.addShortcode("postfixWithZach", async function(str) { + throw new Error("Liquid Shortcode (with async function, error throwing)"); + }); + + let error = await t.throwsAsync(async () => { + await tr._testRender("{% postfixWithZach name %}", { name: "test" }); + }); + t.true( + error.message.indexOf( + "Liquid Shortcode (with async function, error throwing)" + ) > -1 + ); +}); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 53bf64800..2d179e2c9 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -1,6 +1,8 @@ import test from "ava"; import TemplateRender from "../src/TemplateRender"; +class TestEleventyError extends Error {} + async function getPromise(resolveTo) { return new Promise(function(resolve) { setTimeout(function() { @@ -239,7 +241,7 @@ test("Nunjucks Shortcode without args", async t => { return "Zach"; }); - t.is(await tr.render("{% postfixWithZach %}", {}), "Zach"); + t.is(await tr._testRender("{% postfixWithZach %}", {}), "Zach"); }); test("Nunjucks Shortcode", async t => { @@ -249,7 +251,7 @@ test("Nunjucks Shortcode", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -269,7 +271,7 @@ test("Nunjucks Async Shortcode", async t => { ); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); @@ -285,11 +287,105 @@ test("Nunjucks Async function Shortcode", async t => { ); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "testZach" ); }); +test("Nunjucks Async function Shortcode (with sync function, error throwing)", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addShortcode( + "postfixWithZach", + function(str) { + throw new Error( + "Nunjucks Async function Shortcode (with sync function, error throwing)" + ); + }, + true + ); + + let error = await t.throwsAsync(async () => { + await tr._testRender("{% postfixWithZach name %}", { name: "test" }); + }); + t.true( + error.message.indexOf( + "Nunjucks Async function Shortcode (with sync function, error throwing)" + ) > -1 + ); +}); + +test("Nunjucks Async function Shortcode (with async function, error throwing)", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addShortcode( + "postfixWithZachError", + async function(str) { + throw new Error( + "Nunjucks Async function Shortcode (with async function, error throwing)" + ); + }, + true + ); + + let error = await t.throwsAsync(async () => { + await tr._testRender("{% postfixWithZachError name %}", { name: "test" }); + }); + t.true( + error.message.indexOf( + "Nunjucks Async function Shortcode (with async function, error throwing)" + ) > -1 + ); +}); + +test("Nunjucks Async function paired Shortcode (with sync function, error throwing)", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addPairedShortcode( + "postfixWithZachError", + function(str) { + throw new Error( + "Nunjucks Async function paired Shortcode (with sync function, error throwing)" + ); + }, + true + ); + + let error = await t.throwsAsync(async () => { + await tr._testRender( + "{% postfixWithZachError name %}hi{% endpostfixWithZachError %}", + { name: "test" } + ); + }); + t.true( + error.message.indexOf( + "Nunjucks Async function paired Shortcode (with sync function, error throwing)" + ) > -1 + ); +}); + +test("Nunjucks Async function paired Shortcode (with async function, error throwing)", async t => { + let tr = new TemplateRender("njk", "./test/stubs/"); + tr.engine.addPairedShortcode( + "postfixWithZachError", + async function(str) { + throw new Error( + "Nunjucks Async function paired Shortcode (with async function, error throwing)" + ); + }, + true + ); + + let error = await t.throwsAsync(async () => { + await tr._testRender( + "{% postfixWithZachError name %}hi{% endpostfixWithZachError %}", + { name: "test" } + ); + }); + t.true( + error.message.indexOf( + "Nunjucks Async function paired Shortcode (with async function, error throwing)" + ) > -1 + ); +}); + test("Nunjucks Shortcode Safe Output", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { @@ -297,7 +393,7 @@ test("Nunjucks Shortcode Safe Output", async t => { }); t.is( - await tr.render("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { name: "test" }), "test" ); }); @@ -309,7 +405,7 @@ test("Nunjucks Paired Shortcode", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", { name: "test" } ), @@ -332,7 +428,7 @@ test("Nunjucks Async Paired Shortcode", async t => { ); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", { name: "test" } ), @@ -347,7 +443,10 @@ test("Nunjucks Paired Shortcode without args", async t => { }); t.is( - await tr.render("{% postfixWithZach %}Content{% endpostfixWithZach %}", {}), + await tr._testRender( + "{% postfixWithZach %}Content{% endpostfixWithZach %}", + {} + ), "ContentZach" ); }); @@ -359,7 +458,7 @@ test("Nunjucks Paired Shortcode with Tag Inside", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% if tester %}If{% endif %}{% endpostfixWithZach %}", { name: "test", tester: true } ), @@ -374,7 +473,7 @@ test("Nunjucks Nested Paired Shortcode", async t => { }); t.is( - await tr.render( + await tr._testRender( "{% postfixWithZach name %}Content{% postfixWithZach name2 %}Content{% endpostfixWithZach %}{% endpostfixWithZach %}", { name: "test", name2: "test2" } ), @@ -389,7 +488,7 @@ test("Nunjucks Shortcode Multiple Args", async t => { }); t.is( - await tr.render("{% postfixWithZach name, other %}", { + await tr._testRender("{% postfixWithZach name, other %}", { name: "test", other: "howdy" }), @@ -397,14 +496,14 @@ test("Nunjucks Shortcode Multiple Args", async t => { ); }); -test("Nunjucks Shortcode Multiple Args (Comma is not optional)", async t => { +test("Nunjucks Shortcode Multiple Args (Comma is required)", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str, str2) { return str + str2 + "Zach"; }); await t.throwsAsync(async () => { - await tr.render("{% postfixWithZach name other %}", { + await tr._testRender("{% postfixWithZach name other %}", { name: "test", other: "howdy" }); @@ -418,7 +517,7 @@ test("Nunjucks Shortcode Named Args", async t => { }); t.is( - await tr.render("{% postfixWithZach arg1=name, arg2=other %}", { + await tr._testRender("{% postfixWithZach arg1=name, arg2=other %}", { name: "test", other: "howdy" }), @@ -433,7 +532,7 @@ test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { }); t.is( - await tr.render("{% postfixWithZach arg2=other, arg1=name %}", { + await tr._testRender("{% postfixWithZach arg2=other, arg1=name %}", { name: "test", other: "howdy" }), @@ -448,7 +547,7 @@ test("Nunjucks Shortcode Named Args (JS notation)", async t => { }); t.is( - await tr.render("{% postfixWithZach { arg1: name, arg2: other } %}", { + await tr._testRender("{% postfixWithZach { arg1: name, arg2: other } %}", { name: "test", other: "howdy" }), @@ -460,21 +559,24 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); t.is( - await tr.render("{% if 'first' in tags %}Success.{% endif %}", { + await tr._testRender("{% if 'first' in tags %}Success.{% endif %}", { tags: ["first", "second"] }), "Success." ); t.is( - await tr.render("{% if 'sdfsdfs' in tags %}{% else %}Success.{% endif %}", { - tags: ["first", "second"] - }), + await tr._testRender( + "{% if 'sdfsdfs' in tags %}{% else %}Success.{% endif %}", + { + tags: ["first", "second"] + } + ), "Success." ); t.is( - await tr.render( + await tr._testRender( "{% if false %}{% elseif 'first' in tags %}Success.{% endif %}", { tags: ["first", "second"] @@ -484,14 +586,14 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { ); t.is( - await tr.render("{% if tags.includes('first') %}Success.{% endif %}", { + await tr._testRender("{% if tags.includes('first') %}Success.{% endif %}", { tags: ["first", "second"] }), "Success." ); t.is( - await tr.render( + await tr._testRender( "{% if tags.includes('dsds') %}{% else %}Success.{% endif %}", { tags: ["first", "second"] @@ -501,7 +603,7 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { ); t.is( - await tr.render( + await tr._testRender( "{% if false %}{% elseif tags.includes('first') %}Success.{% endif %}", { tags: ["first", "second"] @@ -516,7 +618,7 @@ test("Issue 611: Run a function", async t => { let tr = new TemplateRender("njk", "./test/stubs/"); t.is( - await tr.render("{{ test() }}", { + await tr._testRender("{{ test() }}", { test: function() { return "alkdsjfksljaZach"; } diff --git a/test/stubs/function-throws-async.11ty.js b/test/stubs/function-throws-async.11ty.js new file mode 100644 index 000000000..86eeee406 --- /dev/null +++ b/test/stubs/function-throws-async.11ty.js @@ -0,0 +1,3 @@ +module.exports = async function(data) { + return `

${await this.upper(data.name)}

`; +}; diff --git a/test/stubs/function-throws.11ty.js b/test/stubs/function-throws.11ty.js new file mode 100644 index 000000000..4072e7582 --- /dev/null +++ b/test/stubs/function-throws.11ty.js @@ -0,0 +1,3 @@ +module.exports = function(data) { + return `

${this.upper(data.name)}

`; +}; From 002e49bca857aecbddcb87a45680a2d28c081a9a Mon Sep 17 00:00:00 2001 From: Christian Schuller Date: Thu, 5 Sep 2019 19:39:19 +0200 Subject: [PATCH 027/746] Fix require cache cleanup on Windows (#596) --- src/Eleventy.js | 3 ++- src/EleventyWatchTargets.js | 3 ++- src/Engines/JavaScript.js | 5 +++-- src/TemplateConfig.js | 3 ++- src/TemplateData.js | 3 ++- src/Util/DeleteRequireCache.js | 11 +++++++++++ test/DeleteRequireCacheTest.js | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 src/Util/DeleteRequireCache.js create mode 100644 test/DeleteRequireCacheTest.js diff --git a/src/Eleventy.js b/src/Eleventy.js index e9fa1b06c..1bc4fe40b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -11,6 +11,7 @@ const simplePlural = require("./Util/Pluralize"); const config = require("./Config"); const bench = require("./BenchmarkManager"); const debug = require("debug")("Eleventy"); +const deleteRequireCache = require("./Util/DeleteRequireCache"); /** * @module @11ty/eleventy/Eleventy @@ -171,7 +172,7 @@ class Eleventy { // reload package.json values (if applicable) // TODO only reset this if it changed - delete require.cache[TemplatePath.absolutePath("package.json")]; + deleteRequireCache(TemplatePath.absolutePath("package.json")); await this.init(); } diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index 6965732a9..87dc3bc98 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -1,5 +1,6 @@ const dependencyTree = require("dependency-tree"); const TemplatePath = require("./TemplatePath"); +const deleteRequireCache = require("./Util/DeleteRequireCache"); class EleventyWatchTargets { constructor() { @@ -109,7 +110,7 @@ class EleventyWatchTargets { clearDependencyRequireCache() { for (let path of this.dependencies) { - delete require.cache[TemplatePath.absolutePath(path)]; + deleteRequireCache(TemplatePath.absolutePath(path)); } } diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 1a9869b95..ec676cab0 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -1,6 +1,7 @@ const TemplateEngine = require("./TemplateEngine"); const TemplatePath = require("../TemplatePath"); const EleventyBaseError = require("../EleventyBaseError"); +const deleteRequireCache = require("../Util/DeleteRequireCache"); class JavaScriptTemplateInvalidDataFormatError extends EleventyBaseError {} @@ -72,8 +73,8 @@ class JavaScript extends TemplateEngine { // only remove from cache once on startup (if it already exists) initRequireCache(inputPath) { let requirePath = TemplatePath.absolutePath(inputPath); - if (requirePath in require.cache) { - delete require.cache[requirePath]; + if (requirePath) { + deleteRequireCache(requirePath); } if (inputPath in this.instances) { diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index dc395c01c..1bcf39fe2 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -5,6 +5,7 @@ const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); const eleventyConfig = require("./EleventyConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); +const deleteRequireCache = require("./Util/DeleteRequireCache"); class EleventyConfigError extends EleventyBaseError {} @@ -76,7 +77,7 @@ class TemplateConfig { try { // remove from require cache so it will grab a fresh copy if (path in require.cache) { - delete require.cache[path]; + deleteRequireCache(path); } localConfig = require(path); diff --git a/src/TemplateData.js b/src/TemplateData.js index 06912f8f5..8aa5802de 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -14,6 +14,7 @@ const config = require("./Config"); const debugWarn = require("debug")("Eleventy:Warnings"); const debug = require("debug")("Eleventy:TemplateData"); const debugDev = require("debug")("Dev:Eleventy:TemplateData"); +const deleteRequireCache = require("./Util/DeleteRequireCache"); class TemplateDataParseError extends EleventyBaseError {} @@ -233,7 +234,7 @@ class TemplateData { if (await fs.pathExists(localPath)) { let dataBench = bench.get(`\`${path}\``); dataBench.before(); - delete require.cache[localPath]; + deleteRequireCache(localPath); let returnValue = require(localPath); if (typeof returnValue === "function") { returnValue = await returnValue(); diff --git a/src/Util/DeleteRequireCache.js b/src/Util/DeleteRequireCache.js new file mode 100644 index 000000000..5f94b7169 --- /dev/null +++ b/src/Util/DeleteRequireCache.js @@ -0,0 +1,11 @@ +const path = require("path"); + +/** + * Removes a nodejs module from the cache. + * The keys of the nodejs require cache are file paths based on the current operating system. + * @param {string} absoluteModulePath An absolute POSIX path to the module. + */ +module.exports = function deleteRequireCache(absoluteModulePath) { + const normalizedPath = path.normalize(absoluteModulePath); + delete require.cache[normalizedPath]; +}; diff --git a/test/DeleteRequireCacheTest.js b/test/DeleteRequireCacheTest.js new file mode 100644 index 000000000..4393f5bd1 --- /dev/null +++ b/test/DeleteRequireCacheTest.js @@ -0,0 +1,32 @@ +import test from "ava"; +import path from "path"; +import deleteRequireCache from "../src/Util/DeleteRequireCache"; +import template from "./stubs/function.11ty"; + +test("deleteRequireCache", t => { + const modulePath = path.normalize( + path.join(__dirname, "./stubs/function.11ty.js") + ); + const posixModulePath = useForwardSlashes(modulePath); + const windowsModulePath = useBackwardSlashes(modulePath); + + deleteRequireCache(posixModulePath); + + t.is(require.cache[windowsModulePath], undefined); +}); + +/** + * @param {string} path + * @returns {string} + */ +function useForwardSlashes(path) { + return path.replace(/\\/g, "/"); +} + +/** + * @param {string} path + * @returns {string} + */ +function useBackwardSlashes(path) { + return path.replace(/\//g, "\\"); +} From 6e294bd7160d44b400810bab84273336009c99db Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Sep 2019 23:20:48 -0500 Subject: [PATCH 028/746] =?UTF-8?q?Adds=20a=20really=20rough=20start=20--i?= =?UTF-8?q?ncremental=20that=20probably=20won=E2=80=99t=20be=20good=20enou?= =?UTF-8?q?gh=20for=20most=20people.=20Processes=20everything=20but=20only?= =?UTF-8?q?=20writes=20what=20triggered=20in=20--watch/--serve?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd.js | 1 + src/Eleventy.js | 47 +++++++++++++++++++++++-------------- src/EleventyCommandCheck.js | 3 ++- src/TemplateWriter.js | 27 +++++++++++++++++++-- 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/cmd.js b/cmd.js index b58ea1345..ff8f27c2a 100755 --- a/cmd.js +++ b/cmd.js @@ -43,6 +43,7 @@ try { elev.setConfigPathOverride(argv.config); elev.setPathPrefix(argv.pathprefix); elev.setDryRun(argv.dryrun); + elev.setIncrementalBuild(argv.incremental); elev.setPassthroughAll(argv.passthroughall); elev.setFormats(argv.formats); diff --git a/src/Eleventy.js b/src/Eleventy.js index e9fa1b06c..e7b17f6b4 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -108,6 +108,16 @@ class Eleventy { this.isDryRun = !!isDryRun; } + /** + * Sets the incremental build mode. + * + * @method + * @param {Boolean} isIncremental - Shall Eleventy run in incremental build mode and only write the files that trigger watch updates + */ + setIncrementalBuild(isIncremental) { + this.isIncremental = !!isIncremental; + } + /** * Updates the passthrough mode of Eleventy. * @@ -204,25 +214,19 @@ class Eleventy { let ret = []; let writeCount = this.writer.getWriteCount(); + let pretendWriteCount = this.writer.getPretendWriteCount(); let copyCount = this.writer.getCopyCount(); - if (this.isDryRun) { - ret.push("Pretended to"); - } - if (copyCount) { + if (!this.isDryRun && copyCount) { ret.push( - `${this.isDryRun ? "Copy" : "Copied"} ${copyCount} ${simplePlural( - copyCount, - "item", - "items" - )} and` + `Copied ${copyCount} ${simplePlural(copyCount, "item", "items")} /` ); } + if (pretendWriteCount) { + ret.push(`Processed ${writeCount + pretendWriteCount},`); + } + ret.push( - `${this.isDryRun ? "Process" : "Processed"} ${writeCount} ${simplePlural( - writeCount, - "file", - "files" - )}` + `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}` ); let time = ((new Date() - this.start) / 1000).toFixed(2); @@ -398,6 +402,10 @@ Arguments: this.active = true; + let isInclude = + path && + TemplatePath.startsWithSubPath(path, this.eleventyFiles.getIncludesDir()); + let localProjectConfigPath = config.getLocalProjectConfigFile(); // reset and reload global configuration :O if (path === localProjectConfigPath) { @@ -408,17 +416,22 @@ Arguments: await this.restart(); this.watchTargets.clearDependencyRequireCache(); + if (path && !isInclude && this.isIncremental) { + this.writer.setIncrementalFile(path); + } + await this.write(); + if (path && !isInclude && this.isIncremental) { + this.writer.resetIncrementalFile(); + } + this.watchTargets.reset(); await this._initWatchDependencies(); // Add new deps to chokidar this.watcher.add(this.watchTargets.getNewTargetsSinceLastReset()); - let isInclude = - path && - TemplatePath.startsWithSubPath(path, this.eleventyFiles.getIncludesDir()); this.eleventyServe.reload(path, isInclude); this.active = false; diff --git a/src/EleventyCommandCheck.js b/src/EleventyCommandCheck.js index cd32cf160..8d64a2fa1 100644 --- a/src/EleventyCommandCheck.js +++ b/src/EleventyCommandCheck.js @@ -21,7 +21,8 @@ class EleventyCommandCheck { "dryrun", "help", "serve", - "passthroughall" + "passthroughall", + "incremental" ]; this.args = argv; diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 1802dac6b..55356f6ed 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -29,6 +29,7 @@ function TemplateWriter( this.isVerbose = true; this.isDryRun = false; this.writeCount = 0; + this.pretendWriteCount = 0; // TODO can we get rid of this? It’s only used for tests in getFileManager() this.passthroughAll = isPassthroughAll; @@ -41,6 +42,7 @@ TemplateWriter.prototype.overrideConfig = function(config) { TemplateWriter.prototype.restart = function() { this.writeCount = 0; + this.pretendWriteCount = 0; debugDev("Resetting counts to 0"); }; @@ -77,7 +79,13 @@ TemplateWriter.prototype._createTemplate = function(path) { ); tmpl.setIsVerbose(this.isVerbose); - tmpl.setDryRun(this.isDryRun); + + // --incremental only writes files that trigger a build during --watch + if (this.incrementalFile && path !== this.incrementalFile) { + tmpl.setDryRun(true); + } else { + tmpl.setDryRun(this.isDryRun); + } /* * Sample filter: arg str, return pretty HTML string @@ -131,7 +139,11 @@ TemplateWriter.prototype._writeTemplate = async function(mapEntry) { let tmpl = mapEntry.template; // we don’t re-use the map templateContent because it doesn’t include layouts return tmpl.writeMapEntry(mapEntry).then(() => { - this.writeCount += tmpl.getWriteCount(); + if (tmpl.isDryRun) { + this.pretendWriteCount += tmpl.getWriteCount(); + } else { + this.writeCount += tmpl.getWriteCount(); + } }); }; @@ -207,6 +219,13 @@ TemplateWriter.prototype.setDryRun = function(isDryRun) { .setDryRun(this.isDryRun); }; +TemplateWriter.prototype.setIncrementalFile = function(incrementalFile) { + this.incrementalFile = incrementalFile; +}; +TemplateWriter.prototype.resetIncrementalFile = function() { + this.incrementalFile = null; +}; + TemplateWriter.prototype.getCopyCount = function() { return this.getFileManager() .getPassthroughManager() @@ -217,4 +236,8 @@ TemplateWriter.prototype.getWriteCount = function() { return this.writeCount; }; +TemplateWriter.prototype.getPretendWriteCount = function() { + return this.pretendWriteCount; +}; + module.exports = TemplateWriter; From cd039af83eabeb55549991772b4dc40f15632ee6 Mon Sep 17 00:00:00 2001 From: Christian Schuller Date: Sat, 7 Sep 2019 14:57:55 +0200 Subject: [PATCH 029/746] Ignore IDEA settings folders --- .gitignore | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index fe7a66ecf..8c3a0ad42 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,18 @@ -_site/ +# Ignore installed npm modules node_modules/ + +# Ignore build tool output, e.g. code coverage .nyc_output/ coverage/ + +# Ignore API documentation +api-docs/ + +# Ignore folders from source code editors +.vscode +.idea + +# Ignore eleventy output when doing manuell tests +_site/ + package-lock.json -api-docs/ \ No newline at end of file From f7fb0858ec4831cfe87e1da4de2cbdbad24121fc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 18 Sep 2019 17:43:55 -0500 Subject: [PATCH 030/746] Make --incremental work with passthrough copy #108 --- src/Eleventy.js | 4 +++- src/EleventyWatchTargets.js | 4 ++++ src/TemplatePassthroughManager.js | 20 +++++++++++++++----- src/TemplateWriter.js | 21 ++++++++++++--------- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 9f7ee77d8..f76a1d0a4 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -406,6 +406,8 @@ Arguments: let isInclude = path && TemplatePath.startsWithSubPath(path, this.eleventyFiles.getIncludesDir()); + let isJavaScriptDependency = + path && this.watchTargets.isJavaScriptDependency(path); let localProjectConfigPath = config.getLocalProjectConfigFile(); // reset and reload global configuration :O @@ -417,7 +419,7 @@ Arguments: await this.restart(); this.watchTargets.clearDependencyRequireCache(); - if (path && !isInclude && this.isIncremental) { + if (path && !isInclude && !isJavaScriptDependency && this.isIncremental) { this.writer.setIncrementalFile(path); } diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index 87dc3bc98..f85b4f087 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -18,6 +18,10 @@ class EleventyWatchTargets { return this._watchJavaScriptDependencies; } + isJavaScriptDependency(path) { + return this.dependencies.has(path); + } + _normalizeTargets(targets) { if (!targets) { return []; diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 8b769d705..462aa3c17 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -15,6 +15,7 @@ class TemplatePassthroughManager { reset() { this.count = 0; + this.incrementalFile = null; debug("Resetting counts to 0"); } @@ -34,6 +35,10 @@ class TemplatePassthroughManager { this.isDryRun = !!isDryRun; } + setIncrementalFile(path) { + this.incrementalFile = path; + } + _normalizePaths(path, outputPath) { return { inputPath: TemplatePath.addLeadingDotSlash(path), @@ -87,16 +92,21 @@ class TemplatePassthroughManager { async copyPath(path) { let pass = new TemplatePassthrough(path, this.outputDir, this.inputDir); - pass.setDryRun(this.isDryRun); + + if (this.incrementalFile && path.inputPath !== this.incrementalFile) { + pass.setDryRun(true); + } else { + pass.setDryRun(this.isDryRun); + } return pass .write() - .then( - function() { + .then(() => { + if (!pass.isDryRun) { this.count++; debug("Copied %o", path.inputPath); - }.bind(this) - ) + } + }) .catch(function(e) { return Promise.reject( new TemplatePassthroughManagerCopyError( diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 55356f6ed..d2c936dbb 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -151,16 +151,19 @@ TemplateWriter.prototype.write = async function() { let promises = []; let paths = await this._getAllPaths(); debug("Found: %o", paths); + + let passthroughManager = this.getFileManager().getPassthroughManager(); + passthroughManager.setIncrementalFile( + this.incrementalFile ? this.incrementalFile : false + ); + promises.push( - this.getFileManager() - .getPassthroughManager() - .copyAll(paths) - .catch(e => { - EleventyErrorHandler.warn(e, "Error with passthrough copy"); - return Promise.reject( - new TemplateWriterWriteError(`Having trouble copying`, e) - ); - }) + passthroughManager.copyAll(paths).catch(e => { + EleventyErrorHandler.warn(e, "Error with passthrough copy"); + return Promise.reject( + new TemplateWriterWriteError("Having trouble copying", e) + ); + }) ); // TODO optimize await here From bf7436024771b41cd1527083301215df860b8e52 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 18 Sep 2019 20:52:25 -0500 Subject: [PATCH 031/746] Use classes on TemplateWriter --- src/TemplateWriter.js | 406 +++++++++++++++++++++--------------------- 1 file changed, 204 insertions(+), 202 deletions(-) diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index d2c936dbb..bb0ac920d 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -13,234 +13,236 @@ const debugDev = require("debug")("Dev:Eleventy:TemplateWriter"); class TemplateWriterWriteError extends EleventyBaseError {} -function TemplateWriter( - inputPath, - outputDir, - templateFormats, // TODO remove this, see `.getFileManager()` first - templateData, - isPassthroughAll -) { - this.config = config.getConfig(); - this.input = inputPath; - this.inputDir = TemplatePath.getDir(inputPath); - this.outputDir = outputDir; - this.templateFormats = templateFormats; - this.templateData = templateData; - this.isVerbose = true; - this.isDryRun = false; - this.writeCount = 0; - this.pretendWriteCount = 0; - - // TODO can we get rid of this? It’s only used for tests in getFileManager() - this.passthroughAll = isPassthroughAll; -} +class TemplateWriter { + constructor( + inputPath, + outputDir, + templateFormats, // TODO remove this, see `.getFileManager()` first + templateData, + isPassthroughAll + ) { + this.config = config.getConfig(); + this.input = inputPath; + this.inputDir = TemplatePath.getDir(inputPath); + this.outputDir = outputDir; + this.templateFormats = templateFormats; + this.templateData = templateData; + this.isVerbose = true; + this.isDryRun = false; + this.writeCount = 0; + this.pretendWriteCount = 0; + + // TODO can we get rid of this? It’s only used for tests in getFileManager() + this.passthroughAll = isPassthroughAll; + } -/* For testing */ -TemplateWriter.prototype.overrideConfig = function(config) { - this.config = config; -}; - -TemplateWriter.prototype.restart = function() { - this.writeCount = 0; - this.pretendWriteCount = 0; - debugDev("Resetting counts to 0"); -}; - -TemplateWriter.prototype.setEleventyFiles = function(eleventyFiles) { - this.eleventyFiles = eleventyFiles; -}; - -TemplateWriter.prototype.getFileManager = function() { - // usually Eleventy.js will setEleventyFiles with the EleventyFiles manager - if (!this.eleventyFiles) { - // if not, we can create one (used only by tests) - this.eleventyFiles = new EleventyFiles( - this.input, - this.outputDir, - this.templateFormats, - this.passthroughAll - ); - this.eleventyFiles.init(); - } - - return this.eleventyFiles; -}; - -TemplateWriter.prototype._getAllPaths = async function() { - return await this.getFileManager().getFiles(); -}; - -TemplateWriter.prototype._createTemplate = function(path) { - let tmpl = new Template( - path, - this.inputDir, - this.outputDir, - this.templateData - ); - - tmpl.setIsVerbose(this.isVerbose); - - // --incremental only writes files that trigger a build during --watch - if (this.incrementalFile && path !== this.incrementalFile) { - tmpl.setDryRun(true); - } else { - tmpl.setDryRun(this.isDryRun); - } - - /* - * Sample filter: arg str, return pretty HTML string - * function(str) { - * return pretty(str, { ocd: true }); - * } - */ - for (let transformName in this.config.filters) { - let transform = this.config.filters[transformName]; - if (typeof transform === "function") { - tmpl.addTransform(transform); - } + /* For testing */ + overrideConfig(config) { + this.config = config; } - for (let linterName in this.config.linters) { - let linter = this.config.linters[linterName]; - if (typeof linter === "function") { - tmpl.addLinter(linter); - } + restart() { + this.writeCount = 0; + this.pretendWriteCount = 0; + debugDev("Resetting counts to 0"); } - return tmpl; -}; + setEleventyFiles(eleventyFiles) { + this.eleventyFiles = eleventyFiles; + } -TemplateWriter.prototype._addToTemplateMap = async function(paths) { - let promises = []; - for (let path of paths) { - if (TemplateRender.hasEngine(path)) { - promises.push( - this.templateMap.add(this._createTemplate(path)).then(() => { - debug(`${path} added to map.`); - }) + getFileManager() { + // usually Eleventy.js will setEleventyFiles with the EleventyFiles manager + if (!this.eleventyFiles) { + // if not, we can create one (used only by tests) + this.eleventyFiles = new EleventyFiles( + this.input, + this.outputDir, + this.templateFormats, + this.passthroughAll ); + this.eleventyFiles.init(); } - } - return Promise.all(promises); -}; + return this.eleventyFiles; + } -TemplateWriter.prototype._createTemplateMap = async function(paths) { - this.templateMap = new TemplateMap(); + async _getAllPaths() { + return await this.getFileManager().getFiles(); + } - await this._addToTemplateMap(paths); - await this.templateMap.cache(); + _createTemplate(path) { + let tmpl = new Template( + path, + this.inputDir, + this.outputDir, + this.templateData + ); - debugDev("TemplateMap cache complete."); - return this.templateMap; -}; + tmpl.setIsVerbose(this.isVerbose); -TemplateWriter.prototype._writeTemplate = async function(mapEntry) { - let tmpl = mapEntry.template; - // we don’t re-use the map templateContent because it doesn’t include layouts - return tmpl.writeMapEntry(mapEntry).then(() => { - if (tmpl.isDryRun) { - this.pretendWriteCount += tmpl.getWriteCount(); + // --incremental only writes files that trigger a build during --watch + if (this.incrementalFile && path !== this.incrementalFile) { + tmpl.setDryRun(true); } else { - this.writeCount += tmpl.getWriteCount(); + tmpl.setDryRun(this.isDryRun); + } + + /* + * Sample filter: arg str, return pretty HTML string + * function(str) { + * return pretty(str, { ocd: true }); + * } + */ + for (let transformName in this.config.filters) { + let transform = this.config.filters[transformName]; + if (typeof transform === "function") { + tmpl.addTransform(transform); + } } - }); -}; - -TemplateWriter.prototype.write = async function() { - let promises = []; - let paths = await this._getAllPaths(); - debug("Found: %o", paths); - - let passthroughManager = this.getFileManager().getPassthroughManager(); - passthroughManager.setIncrementalFile( - this.incrementalFile ? this.incrementalFile : false - ); - - promises.push( - passthroughManager.copyAll(paths).catch(e => { - EleventyErrorHandler.warn(e, "Error with passthrough copy"); - return Promise.reject( - new TemplateWriterWriteError("Having trouble copying", e) - ); - }) - ); - // TODO optimize await here - await this._createTemplateMap(paths); - debug("Template map created."); + for (let linterName in this.config.linters) { + let linter = this.config.linters[linterName]; + if (typeof linter === "function") { + tmpl.addLinter(linter); + } + } + + return tmpl; + } + + async _addToTemplateMap(paths) { + let promises = []; + for (let path of paths) { + if (TemplateRender.hasEngine(path)) { + promises.push( + this.templateMap.add(this._createTemplate(path)).then(() => { + debug(`${path} added to map.`); + }) + ); + } + } + + return Promise.all(promises); + } + + async _createTemplateMap(paths) { + this.templateMap = new TemplateMap(); + + await this._addToTemplateMap(paths); + await this.templateMap.cache(); + + debugDev("TemplateMap cache complete."); + return this.templateMap; + } + + async _writeTemplate(mapEntry) { + let tmpl = mapEntry.template; + // we don’t re-use the map templateContent because it doesn’t include layouts + return tmpl.writeMapEntry(mapEntry).then(() => { + if (tmpl.isDryRun) { + this.pretendWriteCount += tmpl.getWriteCount(); + } else { + this.writeCount += tmpl.getWriteCount(); + } + }); + } + + async write() { + let promises = []; + let paths = await this._getAllPaths(); + debug("Found: %o", paths); + + let passthroughManager = this.getFileManager().getPassthroughManager(); + passthroughManager.setIncrementalFile( + this.incrementalFile ? this.incrementalFile : false + ); - let mapEntry; - let usedTemplateContentTooEarlyMap = []; - for (mapEntry of this.templateMap.getMap()) { promises.push( - this._writeTemplate(mapEntry).catch(function(e) { - // Premature templateContent in layout render, this also happens in - // TemplateMap.populateContentDataInMap for non-layout content - if (EleventyErrorUtil.isPrematureTemplateContentError(e)) { - usedTemplateContentTooEarlyMap.push(mapEntry); - } else { + passthroughManager.copyAll(paths).catch(e => { + EleventyErrorHandler.warn(e, "Error with passthrough copy"); + return Promise.reject( + new TemplateWriterWriteError("Having trouble copying", e) + ); + }) + ); + + // TODO optimize await here + await this._createTemplateMap(paths); + debug("Template map created."); + + let mapEntry; + let usedTemplateContentTooEarlyMap = []; + for (mapEntry of this.templateMap.getMap()) { + promises.push( + this._writeTemplate(mapEntry).catch(function(e) { + // Premature templateContent in layout render, this also happens in + // TemplateMap.populateContentDataInMap for non-layout content + if (EleventyErrorUtil.isPrematureTemplateContentError(e)) { + usedTemplateContentTooEarlyMap.push(mapEntry); + } else { + return Promise.reject( + new TemplateWriterWriteError( + `Having trouble writing template: ${mapEntry.outputPath}`, + e + ) + ); + } + }) + ); + } + + for (mapEntry of usedTemplateContentTooEarlyMap) { + promises.push( + this._writeTemplate(mapEntry).catch(function(e) { return Promise.reject( new TemplateWriterWriteError( - `Having trouble writing template: ${mapEntry.outputPath}`, + `Having trouble writing template (second pass): ${mapEntry.outputPath}`, e ) ); - } - }) - ); + }) + ); + } + + return Promise.all(promises).catch(e => { + EleventyErrorHandler.error(e, "Error writing templates"); + throw e; + }); } - for (mapEntry of usedTemplateContentTooEarlyMap) { - promises.push( - this._writeTemplate(mapEntry).catch(function(e) { - return Promise.reject( - new TemplateWriterWriteError( - `Having trouble writing template (second pass): ${mapEntry.outputPath}`, - e - ) - ); - }) - ); + setVerboseOutput(isVerbose) { + this.isVerbose = isVerbose; } - return Promise.all(promises).catch(e => { - EleventyErrorHandler.error(e, "Error writing templates"); - throw e; - }); -}; - -TemplateWriter.prototype.setVerboseOutput = function(isVerbose) { - this.isVerbose = isVerbose; -}; - -TemplateWriter.prototype.setDryRun = function(isDryRun) { - this.isDryRun = !!isDryRun; - - this.getFileManager() - .getPassthroughManager() - .setDryRun(this.isDryRun); -}; - -TemplateWriter.prototype.setIncrementalFile = function(incrementalFile) { - this.incrementalFile = incrementalFile; -}; -TemplateWriter.prototype.resetIncrementalFile = function() { - this.incrementalFile = null; -}; - -TemplateWriter.prototype.getCopyCount = function() { - return this.getFileManager() - .getPassthroughManager() - .getCopyCount(); -}; - -TemplateWriter.prototype.getWriteCount = function() { - return this.writeCount; -}; - -TemplateWriter.prototype.getPretendWriteCount = function() { - return this.pretendWriteCount; -}; + setDryRun(isDryRun) { + this.isDryRun = !!isDryRun; + + this.getFileManager() + .getPassthroughManager() + .setDryRun(this.isDryRun); + } + + setIncrementalFile(incrementalFile) { + this.incrementalFile = incrementalFile; + } + resetIncrementalFile() { + this.incrementalFile = null; + } + + getCopyCount() { + return this.getFileManager() + .getPassthroughManager() + .getCopyCount(); + } + + getWriteCount() { + return this.writeCount; + } + + getPretendWriteCount() { + return this.pretendWriteCount; + } +} module.exports = TemplateWriter; From 8bd052a9eddded118f7de52e7235951315f4c606 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Sep 2019 08:29:30 -0500 Subject: [PATCH 032/746] Installation missing from GitHub readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a85c9c439..be5c35862 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,14 @@ Works with HTML, Markdown, Liquid, Nunjucks, Handlebars, Mustache, EJS, Haml, Pu [![npm Version](https://img.shields.io/npm/v/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy) [![GitHub issues](https://img.shields.io/github/issues/11ty/eleventy.svg?style=for-the-badge)](https://github.com/11ty/eleventy/issues) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=for-the-badge)](https://github.com/prettier/prettier) [![npm Downloads](https://img.shields.io/npm/dt/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy) +## Installation + +``` +npm install @11ty/eleventy --save-dev +``` + +Read our [Getting Started guide](https://www.11ty.io/docs/getting-started/). + ## Tests ``` From 24f78107adea0df8f80cd4db3e75b4e0bed6c757 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Sep 2019 08:36:13 -0500 Subject: [PATCH 033/746] Fixes #700 --- package.json | 2 +- src/EleventyWatchTargets.js | 17 ++--------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 0130a546d..d23f48ac9 100755 --- a/package.json +++ b/package.json @@ -84,12 +84,12 @@ "vue-server-renderer": "^2.6.10" }, "dependencies": { + "@11ty/dependency-tree": "^1.0.0", "browser-sync": "^2.26.7", "chalk": "^2.4.2", "chokidar": "^3.0.2", "debug": "^4.1.1", "dependency-graph": "^0.8.0", - "dependency-tree": "^7.0.2", "ejs": "^2.6.2", "fast-glob": "^3.0.4", "fs-extra": "^8.1.0", diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index f85b4f087..8f94e44b9 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -1,4 +1,4 @@ -const dependencyTree = require("dependency-tree"); +const dependencyTree = require("@11ty/dependency-tree"); const TemplatePath = require("./TemplatePath"); const deleteRequireCache = require("./Util/DeleteRequireCache"); @@ -68,7 +68,6 @@ class EleventyWatchTargets { } targets = this._normalizeTargets(targets); - let deps = this.getJavaScriptDependenciesFromList(targets); if (filterCallback) { deps = deps.filter(filterCallback); @@ -86,24 +85,12 @@ class EleventyWatchTargets { files .filter(file => file.endsWith(".js")) // TODO does this need to work with aliasing? what other JS extensions will have deps? .forEach(file => { - dependencyTree - .toList({ - filename: file, - directory: TemplatePath.absolutePath(), - filter: function(path) { - return path.indexOf("node_modules") === -1; - } - }) + dependencyTree(file, { allowNotFound: true }) .map(dependency => { return TemplatePath.addLeadingDotSlash( TemplatePath.relativePath(dependency) ); }) - .filter(dependency => { - return ( - dependency !== file && dependency.indexOf("node_modules") === -1 - ); - }) .forEach(dependency => { depSet.add(dependency); }); From 19fe59856e373de04384fbcea2424ec9fe871434 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Sep 2019 08:37:25 -0500 Subject: [PATCH 034/746] Fixes #699. --- src/Plugins/Pagination.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 9d25041ff..ac882a1cc 100644 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -117,9 +117,18 @@ class Pagination { return !this.isFiltered(value); }.bind(this) ); + + if ( + this.data.pagination.before && + typeof this.data.pagination.before === "function" + ) { + result = this.data.pagination.before(result.filter(() => true)); + } + if (this.data.pagination.reverse === true) { - return result.reverse(); + return result.filter(() => true).reverse(); } + return result; } From 844b3620b0ecfcd8bbf516b22cbfc340cef7ad10 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Sep 2019 08:43:33 -0500 Subject: [PATCH 035/746] Better counts for incremental and dryrun --- src/Eleventy.js | 18 +++++++++++------- src/Template.js | 25 +++++++++++++++++++------ src/TemplatePassthroughManager.js | 13 ++++++++++++- src/TemplateWriter.js | 21 ++++++++++++--------- 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index f76a1d0a4..6a533260b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -215,19 +215,23 @@ class Eleventy { let ret = []; let writeCount = this.writer.getWriteCount(); - let pretendWriteCount = this.writer.getPretendWriteCount(); + let skippedCount = this.writer.getSkippedCount(); + let copyCount = this.writer.getCopyCount(); - if (!this.isDryRun && copyCount) { + let skippedCopyCount = this.writer.getSkippedCopyCount(); + + if (copyCount) { ret.push( - `Copied ${copyCount} ${simplePlural(copyCount, "item", "items")} /` + `Copied ${copyCount} ${simplePlural(copyCount, "item", "items")}${ + skippedCopyCount ? ` (skipped ${skippedCopyCount})` : "" + } /` ); } - if (pretendWriteCount) { - ret.push(`Processed ${writeCount + pretendWriteCount},`); - } ret.push( - `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}` + `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}${ + skippedCount ? ` (skipped ${skippedCount})` : "" + }` ); let time = ((new Date() - this.start) / 1000).toFixed(2); diff --git a/src/Template.js b/src/Template.js index c226670c4..6c002d684 100644 --- a/src/Template.js +++ b/src/Template.js @@ -45,6 +45,7 @@ class Template extends TemplateContent { this.isVerbose = true; this.isDryRun = false; this.writeCount = 0; + this.skippedCount = 0; this.wrapWithLayouts = true; this.fileSlug = new TemplateFileSlug(this.inputPath, this.inputDir); this.fileSlugStr = this.fileSlug.getSlug(); @@ -481,6 +482,12 @@ class Template extends TemplateContent { } async _write(outputPath, finalContent) { + let shouldWriteFile = true; + + if (this.isDryRun) { + shouldWriteFile = false; + } + if (outputPath === false) { debug( "Ignored %o from %o (permalink: false).", @@ -490,17 +497,15 @@ class Template extends TemplateContent { return; } - this.writeCount++; - let lang = { start: "Writing", finished: "written." }; - if (this.isDryRun) { + if (!shouldWriteFile) { lang = { - start: "Pretending to write", - finished: "" // not used + start: "Skipping", + finished: "" // not used, promise doesn’t resolve }; } @@ -509,8 +514,12 @@ class Template extends TemplateContent { } else { debug(`${lang.start} %o from %o.`, outputPath, this.inputPath); } - if (!this.isDryRun) { + + if (!shouldWriteFile) { + this.skippedCount++; + } else { return fs.outputFile(outputPath, finalContent).then(() => { + this.writeCount++; debug(`${outputPath} ${lang.finished}.`); }); } @@ -587,6 +596,10 @@ class Template extends TemplateContent { return this.writeCount; } + getSkippedCount() { + return this.skippedCount; + } + async getMappedDate(data) { // should we use Luxon dates everywhere? Right now using built-in `Date` if ("date" in data) { diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 462aa3c17..294ab9a8e 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -15,6 +15,7 @@ class TemplatePassthroughManager { reset() { this.count = 0; + this.skippedCount = 0; this.incrementalFile = null; debug("Resetting counts to 0"); } @@ -90,6 +91,10 @@ class TemplatePassthroughManager { return this.count; } + getSkippedCount() { + return this.skippedCount; + } + async copyPath(path) { let pass = new TemplatePassthrough(path, this.outputDir, this.inputDir); @@ -102,7 +107,13 @@ class TemplatePassthroughManager { return pass .write() .then(() => { - if (!pass.isDryRun) { + if (pass.isDryRun) { + this.skippedCount++; + debug( + "Skipped %o (either from --dryrun or --incremental)", + path.inputPath + ); + } else { this.count++; debug("Copied %o", path.inputPath); } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index bb0ac920d..e1ce594a7 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -30,7 +30,7 @@ class TemplateWriter { this.isVerbose = true; this.isDryRun = false; this.writeCount = 0; - this.pretendWriteCount = 0; + this.skippedCount = 0; // TODO can we get rid of this? It’s only used for tests in getFileManager() this.passthroughAll = isPassthroughAll; @@ -43,7 +43,7 @@ class TemplateWriter { restart() { this.writeCount = 0; - this.pretendWriteCount = 0; + this.skippedCount = 0; debugDev("Resetting counts to 0"); } @@ -140,11 +140,8 @@ class TemplateWriter { let tmpl = mapEntry.template; // we don’t re-use the map templateContent because it doesn’t include layouts return tmpl.writeMapEntry(mapEntry).then(() => { - if (tmpl.isDryRun) { - this.pretendWriteCount += tmpl.getWriteCount(); - } else { - this.writeCount += tmpl.getWriteCount(); - } + this.skippedCount += tmpl.getSkippedCount(); + this.writeCount += tmpl.getWriteCount(); }); } @@ -236,12 +233,18 @@ class TemplateWriter { .getCopyCount(); } + getSkippedCopyCount() { + return this.getFileManager() + .getPassthroughManager() + .getSkippedCount(); + } + getWriteCount() { return this.writeCount; } - getPretendWriteCount() { - return this.pretendWriteCount; + getSkippedCount() { + return this.skippedCount; } } From 5a75821ca5d6d1468bbb5471b11010497562adc7 Mon Sep 17 00:00:00 2001 From: Micah Mills Date: Mon, 23 Sep 2019 20:16:31 +0300 Subject: [PATCH 036/746] Resolves #693 and #677 by checking for negative patterns in and not including and not processing them as files to ignore. This allows you to use the negative pattern (!filename) in your .gitignore and .eleventyignore files without eleventy skipping over everything and not processing your files. --- src/EleventyFiles.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 67e2dd94d..f65954390 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -183,7 +183,9 @@ class EleventyFiles { }) .filter(line => { // empty lines or comments get filtered out - return line.length > 0 && line.charAt(0) !== "#"; + return ( + line.length > 0 && line.charAt(0) !== "#" && line.charAt(0) !== "!" + ); }) .map(line => { let path = TemplateGlob.normalizePath(dir, "/", line); From 20292cde6ad9f01802020d95b1280519330d0055 Mon Sep 17 00:00:00 2001 From: Sascha Englert Date: Thu, 26 Sep 2019 12:21:07 +0200 Subject: [PATCH 037/746] Added getFilteredByTags method and tests --- src/TemplateCollection.js | 27 ++++++++++++++------ test/TemplateCollectionTest.js | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js index 8c6f0b810..8c2c5be18 100644 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -50,20 +50,31 @@ class TemplateCollection extends Sortable { } getFilteredByTag(tagName) { - return this.getAllSorted().filter(function(item) { - let match = false; + return this.getAllSorted().filter(item => { if (!tagName) { return true; } else if (Array.isArray(item.data.tags)) { - item.data.tags.forEach(tag => { - if (tag === tagName) { - match = true; - } - }); + return item.data.tags.some(tag => tag === tagName); } - return match; + return false; }); } + + getFilteredByTags(tags) { + if (!Array.isArray(tags)) { + return this.getFilteredByTag(tags); + } + return this.getAllSorted().filter(item => + tags.every(requiredTag => { + const itemTags = item.data.tags; + if (Array.isArray(itemTags)) { + return itemTags.includes(requiredTag); + } else { + return itemTags === requiredTag; + } + }) + ); + } } module.exports = TemplateCollection; diff --git a/test/TemplateCollectionTest.js b/test/TemplateCollectionTest.js index 842a4e7e8..7e5f189dd 100644 --- a/test/TemplateCollectionTest.js +++ b/test/TemplateCollectionTest.js @@ -76,6 +76,7 @@ test("getFilteredByTag", async t => { let cats = c.getFilteredByTag("cat"); t.is(cats.length, 2); t.deepEqual(cats[0].template, tmpl2); + t.deepEqual(cats[1].template, tmpl3); let dogs = c.getFilteredByTag("dog"); t.is(dogs.length, 1); @@ -97,12 +98,56 @@ test("getFilteredByTag (added out of order, sorted)", async t => { t.truthy(cats.length); t.is(cats.length, 2); t.deepEqual(cats[0].template, tmpl2); + t.deepEqual(cats[1].template, tmpl3); let dogs = c.getFilteredByTag("dog"); t.truthy(dogs.length); t.deepEqual(dogs[0].template, tmpl1); }); +test("getFilteredByTags", async t => { + let c = new Collection(); + await c._testAddTemplate(tmpl1); + await c._testAddTemplate(tmpl2); + await c._testAddTemplate(tmpl3); + + let postsAndCats = c.getFilteredByTags(["post", "cat"]); + t.is(postsAndCats.length, 1); + t.deepEqual(postsAndCats[0].template, tmpl3); + + let cats = c.getFilteredByTags(["cat"]); + t.is(cats.length, 2); + t.deepEqual(cats[0].template, tmpl2); + t.deepEqual(cats[1].template, tmpl3); + + let dogs = c.getFilteredByTags("dog"); + t.is(dogs.length, 1); + t.deepEqual(dogs[0].template, tmpl1); +}); + +test("getFilteredByTags (added out of order, sorted)", async t => { + let c = new Collection(); + await c._testAddTemplate(tmpl3); + await c._testAddTemplate(tmpl2); + await c._testAddTemplate(tmpl1); + + let postsAndCats = c.getFilteredByTags(["post", "cat"]); + t.truthy(postsAndCats.length); + t.is(postsAndCats.length, 1); + t.deepEqual(postsAndCats[0].template, tmpl3); + + let cats = c.getFilteredByTags(["cat"]); + t.truthy(cats.length); + t.is(cats.length, 2); + t.deepEqual(cats[0].template, tmpl2); + t.deepEqual(cats[1].template, tmpl3); + + let dogs = c.getFilteredByTags("dog"); + t.truthy(dogs.length); + t.is(dogs.length, 1); + t.deepEqual(dogs[0].template, tmpl1); +}); + test("getFilteredByGlob", async t => { let c = new Collection(); await c._testAddTemplate(tmpl1); From 3da2f8644393b153c6c32a408886748638dcf3cd Mon Sep 17 00:00:00 2001 From: Sascha Englert Date: Thu, 26 Sep 2019 13:18:37 +0200 Subject: [PATCH 038/746] Switched to rest parameters --- src/TemplateCollection.js | 5 +---- test/TemplateCollectionTest.js | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js index 8c2c5be18..dfc5992ce 100644 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -60,10 +60,7 @@ class TemplateCollection extends Sortable { }); } - getFilteredByTags(tags) { - if (!Array.isArray(tags)) { - return this.getFilteredByTag(tags); - } + getFilteredByTags(...tags) { return this.getAllSorted().filter(item => tags.every(requiredTag => { const itemTags = item.data.tags; diff --git a/test/TemplateCollectionTest.js b/test/TemplateCollectionTest.js index 7e5f189dd..2d0ee6df5 100644 --- a/test/TemplateCollectionTest.js +++ b/test/TemplateCollectionTest.js @@ -111,11 +111,11 @@ test("getFilteredByTags", async t => { await c._testAddTemplate(tmpl2); await c._testAddTemplate(tmpl3); - let postsAndCats = c.getFilteredByTags(["post", "cat"]); + let postsAndCats = c.getFilteredByTags("post", "cat"); t.is(postsAndCats.length, 1); t.deepEqual(postsAndCats[0].template, tmpl3); - let cats = c.getFilteredByTags(["cat"]); + let cats = c.getFilteredByTags("cat"); t.is(cats.length, 2); t.deepEqual(cats[0].template, tmpl2); t.deepEqual(cats[1].template, tmpl3); @@ -131,12 +131,12 @@ test("getFilteredByTags (added out of order, sorted)", async t => { await c._testAddTemplate(tmpl2); await c._testAddTemplate(tmpl1); - let postsAndCats = c.getFilteredByTags(["post", "cat"]); + let postsAndCats = c.getFilteredByTags("post", "cat"); t.truthy(postsAndCats.length); t.is(postsAndCats.length, 1); t.deepEqual(postsAndCats[0].template, tmpl3); - let cats = c.getFilteredByTags(["cat"]); + let cats = c.getFilteredByTags("cat"); t.truthy(cats.length); t.is(cats.length, 2); t.deepEqual(cats[0].template, tmpl2); From a3b594aca1ed2058035df461557bbd2f933b28eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Thu, 3 Oct 2019 12:27:05 +0200 Subject: [PATCH 039/746] Add JSDoc Comments for Config and TemplateConfig. Adjust references --- package.json | 2 +- src/Config.js | 8 +++++ src/Eleventy.js | 6 ++-- src/TemplateConfig.js | 77 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d23f48ac9..0cba02328 100755 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ }, "scripts": { "default": "npm run test", - "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/*.js", + "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/", "test": "npx ava --verbose", "lint-staged": "lint-staged", "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js" diff --git a/src/Config.js b/src/Config.js index 51425e068..51448f3ac 100644 --- a/src/Config.js +++ b/src/Config.js @@ -1,7 +1,15 @@ const TemplateConfig = require("./TemplateConfig"); const debug = require("debug")("Eleventy:Config"); +/** + * @module 11ty/eleventy/Config + */ + debug("Setting up global TemplateConfig."); +/** + * Provides global TemplateConfig. + * @type {module:11ty/eleventy/TemplateConfig~TemplateConfig} + */ let config = new TemplateConfig(); module.exports = config; diff --git a/src/Eleventy.js b/src/Eleventy.js index f76a1d0a4..83ce6dce5 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -14,7 +14,7 @@ const debug = require("debug")("Eleventy"); const deleteRequireCache = require("./Util/DeleteRequireCache"); /** - * @module @11ty/eleventy/Eleventy + * @module 11ty/eleventy/Eleventy */ /** @@ -22,11 +22,11 @@ const deleteRequireCache = require("./Util/DeleteRequireCache"); * * @param {String} input - Where to read files from. * @param {String} output - Where to write rendered files to. - * @returns {undefined} + * @returns {module:11ty/eleventy/Eleventy~Eleventy} */ class Eleventy { constructor(input, output) { - /** @member {Object} - tbd. */ + /** @member {module:11ty/eleventy/TemplateConfig~TemplateConfig~config} - TemplateConfig instance */ this.config = config.getConfig(); /** diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 1bcf39fe2..3e2193a2b 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -7,53 +7,124 @@ const eleventyConfig = require("./EleventyConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); const deleteRequireCache = require("./Util/DeleteRequireCache"); +/** + * @module 11ty/eleventy/TemplateConfig + */ + +/** + * Config as used by the template. + * @typedef {Object} module:11ty/eleventy/TemplateConfig~TemplateConfig~config + * @property {String=} pathPrefix - The path prefix. + */ + +/** + * Object holding override information for the template config. + * @typedef {Object} module:11ty/eleventy/TemplateConfig~TemplateConfig~override + * @property {String=} pathPrefix - The path prefix. + */ + +/** + * Errors in eleventy config. + */ class EleventyConfigError extends EleventyBaseError {} +/** + * Config for a template. + * + * @param {{}} customRootConfig - tbd. + * @param {String} localProjectConfigPath - Path to local project config. + */ class TemplateConfig { constructor(customRootConfig, localProjectConfigPath) { + /** @member {module:11ty/eleventy/TemplateConfig~TemplateConfig~override} - tbd. */ this.overrides = {}; + + /** + * @member {String} - Path to local project config. + * @default .eleventy.js + */ this.localProjectConfigPath = localProjectConfigPath || ".eleventy.js"; if (customRootConfig) { + /** + * @member {?{}} - Custom root config. + */ this.customRootConfig = customRootConfig; debug("Warning: Using custom root config!"); } else { this.customRootConfig = null; } + this.initializeRootConfig(); + + /** + * @member {module:11ty/eleventy/TemplateConfig~TemplateConfig~config} - tbd. + */ this.config = this.mergeConfig(this.localProjectConfigPath); } + /** + * Normalises local project config file path. + * + * @method + * @returns {String} - The normalised local project config file path. + */ getLocalProjectConfigFile() { return TemplatePath.addLeadingDotSlash(this.localProjectConfigPath); } + /** + * Resets the configuration. + */ reset() { eleventyConfig.reset(); this.initializeRootConfig(); this.config = this.mergeConfig(this.localProjectConfigPath); } + /** + * Resets the configuration while in watch mode. + * + * @todo Add implementation. + */ resetOnWatch() { // nothing yet } + /** + * Returns the config object. + * + * @returns {{}} - The config object. + */ getConfig() { return this.config; } + /** + * Overwrites the config path. + * + * @param {String} path - The new config path. + */ setProjectConfigPath(path) { this.localProjectConfigPath = path; this.config = this.mergeConfig(path); } + /** + * Overwrites the path prefix. + * + * @param {String} pathPrefix - The new path prefix. + */ setPathPrefix(pathPrefix) { debug("Setting pathPrefix to %o", pathPrefix); this.overrides.pathPrefix = pathPrefix; this.config.pathPrefix = pathPrefix; } + /** + * Bootstraps the config object. + */ initializeRootConfig() { this.rootConfig = this.customRootConfig || require("../config.js"); @@ -64,6 +135,12 @@ class TemplateConfig { debug("rootConfig %o", this.rootConfig); } + /** + * Merges different config files together. + * + * @param {String} localProjectConfigPath - Path to local project config. + * @returns {{}} merged - The merged config file. + */ mergeConfig(localProjectConfigPath) { let overrides = ["templateFormats"]; let localConfig = {}; From ac53b9ecece8e8b86b909b734076c3f6c9ca5801 Mon Sep 17 00:00:00 2001 From: Fredrik Ekelund Date: Wed, 9 Oct 2019 15:13:46 +0200 Subject: [PATCH 040/746] Scope mapEntry variable to for..of loop in TemplateWriter Fixes #722. Previously we wouldn't scope the value of the mapEntry variable to each iteration when looping over the templates to write. This became an issue of any of the generated promises threw an error, since the error message would always report that it stemmed from the template from the last iteration. --- src/TemplateWriter.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index bb0ac920d..38ebb2858 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -171,9 +171,8 @@ class TemplateWriter { await this._createTemplateMap(paths); debug("Template map created."); - let mapEntry; let usedTemplateContentTooEarlyMap = []; - for (mapEntry of this.templateMap.getMap()) { + for (let mapEntry of this.templateMap.getMap()) { promises.push( this._writeTemplate(mapEntry).catch(function(e) { // Premature templateContent in layout render, this also happens in @@ -192,7 +191,7 @@ class TemplateWriter { ); } - for (mapEntry of usedTemplateContentTooEarlyMap) { + for (let mapEntry of usedTemplateContentTooEarlyMap) { promises.push( this._writeTemplate(mapEntry).catch(function(e) { return Promise.reject( From 8dce40231f2bbb211ff5aad0bd2483b3dde00aef Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 11 Oct 2019 14:51:46 -0500 Subject: [PATCH 041/746] Oh, I can delete this? --- .vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 564228219..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workbench.colorCustomizations": {} -} \ No newline at end of file From c887d5910864218561687a440f2cf8dd70a9c6d3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 11 Oct 2019 14:52:05 -0500 Subject: [PATCH 042/746] Deleting yarn file --- yarn.lock | 6888 ----------------------------------------------------- 1 file changed, 6888 deletions(-) delete mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 9e4983929..000000000 --- a/yarn.lock +++ /dev/null @@ -1,6888 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@11ty/eleventy-plugin-syntaxhighlight@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@11ty/eleventy-plugin-syntaxhighlight/-/eleventy-plugin-syntaxhighlight-2.0.3.tgz#49193015d1bf561926ebd93c14800d83de27d752" - integrity sha512-tPoNaEawOG1kkOYAvr4fwKaMOXRhNueOH7z5aepA0vjfnGCagUlSbUipvjCcUUOf+nQgfJYW2rwR2g97Vv8/rg== - dependencies: - prismjs "^1.15.0" - -"@ava/babel-plugin-throws-helper@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-3.0.0.tgz#2c933ec22da0c4ce1fc5369f2b95452c70420586" - integrity sha512-mN9UolOs4WX09QkheU1ELkVy2WPnwonlO3XMdN8JF8fQqRVgVTR21xDbvEOUsbwz6Zwjq7ji9yzyjuXqDPalxg== - -"@ava/babel-preset-stage-4@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-3.0.0.tgz#32c46b22b640d1ba0c6e38ae4abd58efab965558" - integrity sha512-uI5UBx++UsckkfnbF0HH6jvTIvM4r/Kxt1ROO2YXKu5H15sScAtxUIAHiUVbPIw24zPqz/PlF3xxlIDuyFzlQw== - dependencies: - "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-transform-dotall-regex" "^7.4.3" - "@babel/plugin-transform-modules-commonjs" "^7.4.3" - -"@ava/babel-preset-transform-test-files@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-5.0.0.tgz#e06fc762069511e597531cc1120e22216aac6981" - integrity sha512-rqgyQwkT0+j2JzYP51dOv80u33rzAvjBtXRzUON+7+6u26mjoudRXci2+1s18rat8r4uOlZfbzm114YS6pwmYw== - dependencies: - "@ava/babel-plugin-throws-helper" "^3.0.0" - babel-plugin-espower "^3.0.1" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/core@^7.5.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" - integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helpers" "^7.5.5" - "@babel/parser" "^7.5.5" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - convert-source-map "^1.1.0" - debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.0.0", "@babel/generator@^7.4.0", "@babel/generator@^7.5.0", "@babel/generator@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" - integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== - dependencies: - "@babel/types" "^7.5.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== - dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-module-imports@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-module-transforms@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" - integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/template" "^7.4.4" - "@babel/types" "^7.5.5" - lodash "^4.17.13" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-regex@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" - integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-simple-access@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== - dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== - dependencies: - "@babel/types" "^7.4.4" - -"@babel/helper-wrap-function@^7.1.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" - integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.2.0" - -"@babel/helpers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" - integrity sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g== - dependencies: - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.0.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" - integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== - -"@babel/plugin-proposal-async-generator-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" - integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - -"@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - -"@babel/plugin-syntax-async-generators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" - integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-dotall-regex@^7.4.3": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" - integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" - -"@babel/plugin-transform-modules-commonjs@^7.4.3": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74" - integrity sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ== - dependencies: - "@babel/helper-module-transforms" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/runtime@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" - integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== - dependencies: - regenerator-runtime "^0.13.2" - -"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" - integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" - integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.5.5" - "@babel/types" "^7.5.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" - integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@concordance/react@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@concordance/react/-/react-2.0.0.tgz#aef913f27474c53731f4fd79cc2f54897de90fde" - integrity sha512-huLSkUuM2/P+U0uy2WwlKuixMsTODD8p4JVQBI4VKeopkiN0C7M3N9XYVawb4M+4spN5RrO/eLhk7KoQX6nsfA== - dependencies: - arrify "^1.0.1" - -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - -"@nodelib/fs.scandir@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" - integrity sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg== - dependencies: - "@nodelib/fs.stat" "2.0.1" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.1", "@nodelib/fs.stat@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz#814f71b1167390cfcb6a6b3d9cdeb0951a192c14" - integrity sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw== - -"@nodelib/fs.stat@^1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" - integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== - -"@nodelib/fs.walk@^1.2.1": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz#6a6450c5e17012abd81450eb74949a4d970d2807" - integrity sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ== - dependencies: - "@nodelib/fs.scandir" "2.1.1" - fastq "^1.6.0" - -"@samverschueren/stream-to-observable@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" - integrity sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg== - dependencies: - any-observable "^0.3.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@types/babel-types@*", "@types/babel-types@^7.0.0": - version "7.0.7" - resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.7.tgz#667eb1640e8039436028055737d2b9986ee336e3" - integrity sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ== - -"@types/babylon@^6.16.2": - version "6.16.5" - resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.5.tgz#1c5641db69eb8cdf378edd25b4be7754beeb48b4" - integrity sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w== - dependencies: - "@types/babel-types" "*" - -"@types/events@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" - integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== - -"@types/glob@^7.1.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" - integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== - dependencies: - "@types/events" "*" - "@types/minimatch" "*" - "@types/node" "*" - -"@types/minimatch@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - -"@types/node@*": - version "12.6.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.9.tgz#ffeee23afdc19ab16e979338e7b536fdebbbaeaf" - integrity sha512-+YB9FtyxXGyD54p8rXwWaN1EWEyar5L58GlGWgtH2I9rGmLGBQcw63+0jw+ujqVavNuO47S1ByAjm9zdHMnskw== - -a-sync-waterfall@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" - integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -accepts@~1.3.4: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-globals@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" - integrity sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8= - dependencies: - acorn "^4.0.4" - -acorn@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= - -acorn@^4.0.4, acorn@~4.0.2: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= - -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= - -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -ansi-align@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" - integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== - dependencies: - string-width "^3.0.0" - -ansi-escapes@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - -ansi-escapes@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.2.1.tgz#4dccdb846c3eee10f6d64dea66273eab90c37228" - integrity sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q== - dependencies: - type-fest "^0.5.2" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.0.0.tgz#f6b84e8fc97ea7add7a53b7530ef28f3fde0e048" - integrity sha512-8zjUtFJ3db/QoPXuuEMloS2AUf79/yeyttJ7Abr3hteopJu9HK8vsgGviGUMq+zyA6cZZO6gAyZoMTF6TgaEjA== - dependencies: - color-convert "^2.0.0" - -ansi-styles@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" - integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg= - -any-observable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" - integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -anymatch@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.0.3.tgz#2fb624fe0e84bccab00afee3d0006ed310f22f09" - integrity sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -app-module-path@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" - integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= - -append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== - dependencies: - default-require-extensions "^2.0.0" - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-differ@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1" - integrity sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w== - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - -array-union@^1.0.1, array-union@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-uniq@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-2.1.0.tgz#46603d5e28e79bfd02b046fcc1d77c6820bd8e98" - integrity sha512-bdHxtev7FN6+MXI1YFW0Q8mQ8dTJc2S8AMfju+ZR77pbg2yAdVyDlwkaUI7Har0LyOMRFPHrJ9lYdyjZZswdlQ== - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -arraybuffer.slice@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" - integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== - -arrify@^1.0.0, arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - -asap@^2.0.3, asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -ast-module-types@^2.3.1, ast-module-types@^2.3.2, ast-module-types@^2.4.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-2.5.0.tgz#44b8bcd51684329a77f2af6b2587df9ea6b4d5ff" - integrity sha512-dP6vhvatex3Q+OThhvcyGRvHn4noQBg1b8lCNKUAFL05up80hr2pAExveU3YQNDGMhfNPhQit/vzIkkvBPbSXw== - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-each-series@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/async-each-series/-/async-each-series-0.1.1.tgz#7617c1917401fd8ca4a28aadce3dbae98afeb432" - integrity sha1-dhfBkXQB/Yykooqtzj266Yr+tDI= - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== - -async@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -ava@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ava/-/ava-2.2.0.tgz#5a7d799c2c8cc5926f95d2b76bdfe6081fe9a4f8" - integrity sha512-lROj3eQ8L4ZjfiN5P8UGekEQLfKmseGMtat6pUOHgJLEb2K1kT0ZpR/IlWwuytjvwO6nZpzpD+QsTW/XiayIgg== - dependencies: - "@ava/babel-preset-stage-4" "^3.0.0" - "@ava/babel-preset-transform-test-files" "^5.0.0" - "@babel/core" "^7.5.0" - "@babel/generator" "^7.5.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@concordance/react" "^2.0.0" - ansi-escapes "^4.2.0" - ansi-styles "^4.0.0" - arr-flatten "^1.1.0" - array-union "^2.1.0" - array-uniq "^2.1.0" - arrify "^2.0.1" - bluebird "^3.5.5" - chalk "^2.4.2" - chokidar "^3.0.2" - chunkd "^1.0.0" - ci-parallel-vars "^1.0.0" - clean-stack "^2.1.0" - clean-yaml-object "^0.1.0" - cli-cursor "^3.1.0" - cli-truncate "^2.0.0" - code-excerpt "^2.1.1" - common-path-prefix "^1.0.0" - concordance "^4.0.0" - convert-source-map "^1.6.0" - currently-unhandled "^0.4.1" - debug "^4.1.1" - del "^4.1.1" - dot-prop "^5.1.0" - emittery "^0.4.1" - empower-core "^1.2.0" - equal-length "^1.0.0" - escape-string-regexp "^2.0.0" - esm "^3.2.25" - figures "^3.0.0" - find-up "^4.1.0" - get-port "^5.0.0" - globby "^10.0.1" - ignore-by-default "^1.0.0" - import-local "^3.0.1" - indent-string "^4.0.0" - is-ci "^2.0.0" - is-error "^2.2.2" - is-observable "^2.0.0" - is-plain-object "^3.0.0" - is-promise "^2.1.0" - lodash "^4.17.11" - loud-rejection "^2.1.0" - make-dir "^3.0.0" - matcher "^2.0.0" - md5-hex "^3.0.0" - meow "^5.0.0" - micromatch "^4.0.2" - ms "^2.1.2" - observable-to-promise "^1.0.0" - ora "^3.4.0" - package-hash "^4.0.0" - pkg-conf "^3.1.0" - plur "^3.1.1" - pretty-ms "^5.0.0" - require-precompiled "^0.1.0" - resolve-cwd "^3.0.0" - slash "^3.0.0" - source-map-support "^0.5.12" - stack-utils "^1.0.2" - strip-ansi "^5.2.0" - strip-bom-buf "^2.0.0" - supertap "^1.0.0" - supports-color "^7.0.0" - trim-off-newlines "^1.0.1" - trim-right "^1.0.1" - unique-temp-dir "^1.0.0" - update-notifier "^3.0.1" - write-file-atomic "^3.0.0" - -axios@0.19.0: - version "0.19.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" - integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== - dependencies: - follow-redirects "1.5.10" - is-buffer "^2.0.2" - -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-espower@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-espower/-/babel-plugin-espower-3.0.1.tgz#180db17126f88e754105b8b5216d21e520a6bd4e" - integrity sha512-Ms49U7VIAtQ/TtcqRbD6UBmJBUCSxiC3+zPc+eGqxKUIFO1lTshyEDRUjhoAbd2rWfwYf3cZ62oXozrd8W6J0A== - dependencies: - "@babel/generator" "^7.0.0" - "@babel/parser" "^7.0.0" - call-matcher "^1.0.0" - core-js "^2.0.0" - espower-location-detector "^1.0.0" - espurify "^1.6.0" - estraverse "^4.1.1" - -babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" - integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= - -base64id@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" - integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= - dependencies: - callsite "1.0.0" - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== - -blob@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" - integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== - -bluebird@^3.5.5: - version "3.5.5" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" - integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== - -blueimp-md5@^2.10.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.11.0.tgz#eff55d30fe3daddd7e801072e2c4483e5fcfc87c" - integrity sha512-xvA4mdnIevstCvNKTRLMOKi7L76U/X/CTs9Yz+PLWmWAC/7SuYi5Xv2J7bAhJnE2+LcLv+x4+0vusvKgM9LnZQ== - -boxen@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" - integrity sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A== - dependencies: - ansi-align "^3.0.0" - camelcase "^5.3.1" - chalk "^2.4.2" - cli-boxes "^2.2.0" - string-width "^3.0.0" - term-size "^1.2.0" - type-fest "^0.3.0" - widest-line "^2.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.1, braces@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browser-sync-client@^2.26.6: - version "2.26.6" - resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.26.6.tgz#e5201d3ace8aee88af17656b7b0c0620b6f8e4ab" - integrity sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw== - dependencies: - etag "1.8.1" - fresh "0.5.2" - mitt "^1.1.3" - rxjs "^5.5.6" - -browser-sync-ui@^2.26.4: - version "2.26.4" - resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz#3772f13c6b93f2d7d333f4be0ca1ec02aae97dba" - integrity sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA== - dependencies: - async-each-series "0.1.1" - connect-history-api-fallback "^1" - immutable "^3" - server-destroy "1.0.1" - socket.io-client "^2.0.4" - stream-throttle "^0.1.3" - -browser-sync@^2.26.7: - version "2.26.7" - resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.26.7.tgz#120287716eb405651a76cc74fe851c31350557f9" - integrity sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w== - dependencies: - browser-sync-client "^2.26.6" - browser-sync-ui "^2.26.4" - bs-recipes "1.3.4" - bs-snippet-injector "^2.0.1" - chokidar "^2.0.4" - connect "3.6.6" - connect-history-api-fallback "^1" - dev-ip "^1.0.1" - easy-extender "^2.3.4" - eazy-logger "^3" - etag "^1.8.1" - fresh "^0.5.2" - fs-extra "3.0.1" - http-proxy "1.15.2" - immutable "^3" - localtunnel "1.9.2" - micromatch "^3.1.10" - opn "5.3.0" - portscanner "2.1.1" - qs "6.2.3" - raw-body "^2.3.2" - resp-modifier "6.0.2" - rx "4.1.0" - send "0.16.2" - serve-index "1.9.1" - serve-static "1.13.2" - server-destroy "1.0.1" - socket.io "2.1.1" - ua-parser-js "0.7.17" - yargs "6.4.0" - -bs-recipes@1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/bs-recipes/-/bs-recipes-1.3.4.tgz#0d2d4d48a718c8c044769fdc4f89592dc8b69585" - integrity sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU= - -bs-snippet-injector@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz#61b5393f11f52559ed120693100343b6edb04dd5" - integrity sha1-YbU5PxH1JVntEgaTEANDtu2wTdU= - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -caching-transform@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70" - integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w== - dependencies: - hasha "^3.0.0" - make-dir "^2.0.0" - package-hash "^3.0.0" - write-file-atomic "^2.4.2" - -call-matcher@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/call-matcher/-/call-matcher-1.1.0.tgz#23b2c1bc7a8394c8be28609d77ddbd5786680432" - integrity sha512-IoQLeNwwf9KTNbtSA7aEBb1yfDbdnzwjCetjkC8io5oGeOmK2CBNdg0xr+tadRYKO0p7uQyZzvon0kXlZbvGrw== - dependencies: - core-js "^2.0.0" - deep-equal "^1.0.0" - espurify "^1.6.0" - estraverse "^4.0.0" - -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - -call-signature@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/call-signature/-/call-signature-0.0.2.tgz#a84abc825a55ef4cb2b028bd74e205a65b9a4996" - integrity sha1-qEq8glpV70yysCi9dOIFpluaSZY= - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - -camelcase-keys@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" - integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= - dependencies: - camelcase "^4.1.0" - map-obj "^2.0.0" - quick-lru "^1.0.0" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= - -camelcase@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - -chalk@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" - integrity sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8= - dependencies: - ansi-styles "~1.0.0" - has-color "~0.1.0" - strip-ansi "~0.1.0" - -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -character-parser@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" - integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A= - dependencies: - is-regex "^1.0.3" - -chokidar@^2.0.0, chokidar@^2.0.4, chokidar@^2.1.5: - version "2.1.6" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" - integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chokidar@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.0.2.tgz#0d1cd6d04eb2df0327446188cd13736a3367d681" - integrity sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA== - dependencies: - anymatch "^3.0.1" - braces "^3.0.2" - glob-parent "^5.0.0" - is-binary-path "^2.1.0" - is-glob "^4.0.1" - normalize-path "^3.0.0" - readdirp "^3.1.1" - optionalDependencies: - fsevents "^2.0.6" - -chownr@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" - integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== - -chunkd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chunkd/-/chunkd-1.0.0.tgz#4ead4a3704bcce510c4bb4d4a8be30c557836dd1" - integrity sha512-xx3Pb5VF9QaqCotolyZ1ywFBgyuJmu6+9dLiqBxgelEse9Xsr3yUlpoX3O4Oh11M00GT2kYMsRByTKIMJW2Lkg== - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -ci-parallel-vars@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ci-parallel-vars/-/ci-parallel-vars-1.0.0.tgz#af97729ed1c7381911ca37bcea263d62638701b3" - integrity sha512-u6dx20FBXm+apMi+5x7UVm6EH7BL1gc4XrcnQewjcB7HWRcor/V5qWc3RG2HwpgDJ26gIi2DSEu3B7sXynAw/g== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -clean-css@^4.1.11: - version "4.2.1" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" - integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== - dependencies: - source-map "~0.6.0" - -clean-stack@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -clean-yaml-object@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" - integrity sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g= - -cli-boxes@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" - integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== - -cli-cursor@^2.0.0, cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-spinners@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" - integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== - -cli-truncate@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" - integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= - dependencies: - slice-ansi "0.0.4" - string-width "^1.0.1" - -cli-truncate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.0.0.tgz#68ff6aaa53b203b52ad89b8b1a80f1f61ad1e1d5" - integrity sha512-C4hp+8GCIFVsUUiXcw+ce+7wexVWImw8rQrgMBFsqerx9LvvcGlwm6sMjQYAEmV/Xb87xc1b5Ttx505MSpZVqg== - dependencies: - slice-ansi "^2.1.0" - string-width "^4.1.0" - -clipboard@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d" - integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ== - dependencies: - good-listener "^1.2.2" - select "^1.1.2" - tiny-emitter "^2.0.0" - -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - -cliui@^3.0.3, cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -code-excerpt@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.1.tgz#5fe3057bfbb71a5f300f659ef2cc0a47651ba77c" - integrity sha512-tJLhH3EpFm/1x7heIW0hemXJTUU5EWl2V0EIX558jp05Mt1U6DVryCgkp3l37cxqs+DNbNgxG43SkwJXpQ14Jw== - dependencies: - convert-to-spaces "^1.0.1" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.0.tgz#9851ac61cc0d3898a8a3088650d5bf447bf69d97" - integrity sha512-hzTicsCJIHdxih9+2aLR1tNGZX5qSJGRHDPVwSY26tVrEf55XNajLOBWz2UuWSIergszA09/bqnOiHyqx9fxQg== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^2.13.0, commander@^2.14.1, commander@^2.16.0, commander@^2.19.0, commander@^2.2.0, commander@^2.8.1, commander@^2.9.0, commander@~2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== - -common-path-prefix@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-1.0.0.tgz#cd52f6f0712e0baab97d6f9732874f22f47752c0" - integrity sha1-zVL28HEuC6q5fW+XModPIvR3UsA= - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.4.7: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -concordance@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/concordance/-/concordance-4.0.0.tgz#5932fdee397d129bdbc3a1885fbe69839b1b7e15" - integrity sha512-l0RFuB8RLfCS0Pt2Id39/oCPykE01pyxgAFypWTlaGRgvLkZrtczZ8atEHpTeEIW+zYWXTBuA9cCSeEOScxReQ== - dependencies: - date-time "^2.1.0" - esutils "^2.0.2" - fast-diff "^1.1.2" - js-string-escape "^1.0.1" - lodash.clonedeep "^4.5.0" - lodash.flattendeep "^4.4.0" - lodash.islength "^4.0.1" - lodash.merge "^4.6.1" - md5-hex "^2.0.0" - semver "^5.5.1" - well-known-symbols "^2.0.0" - -condense-newlines@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f" - integrity sha1-PemFVTE5R10yUCyDsC9gaE0kxV8= - dependencies: - extend-shallow "^2.0.1" - is-whitespace "^0.3.0" - kind-of "^3.0.2" - -config-chain@^1.1.12: - version "1.1.12" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" - integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -configstore@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" - integrity sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ== - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - -connect-history-api-fallback@^1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -connect@3.6.6: - version "3.6.6" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" - integrity sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ= - dependencies: - debug "2.6.9" - finalhandler "1.1.0" - parseurl "~1.3.2" - utils-merge "1.0.1" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -constantinople@^3.0.1, constantinople@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" - integrity sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw== - dependencies: - "@types/babel-types" "^7.0.0" - "@types/babylon" "^6.16.2" - babel-types "^6.26.0" - babylon "^6.18.0" - -convert-source-map@^1.1.0, convert-source-map@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - -convert-to-spaces@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715" - integrity sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU= - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-js@^2.0.0, core-js@^2.4.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -cp-file@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d" - integrity sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA== - dependencies: - graceful-fs "^4.1.2" - make-dir "^2.0.0" - nested-error-stacks "^2.0.0" - pify "^4.0.1" - safe-buffer "^5.0.1" - -cross-spawn@^4: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= - -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -csso@^3.5.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== - dependencies: - css-tree "1.0.0-alpha.29" - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - -date-fns@^1.27.2: - version "1.30.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" - integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== - -date-time@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/date-time/-/date-time-0.1.1.tgz#ed2f6d93d9790ce2fd66d5b5ff3edd5bbcbf3b07" - integrity sha1-7S9tk9l5DOL9ZtW1/z7dW7y/Owc= - -date-time@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" - integrity sha512-/9+C44X7lot0IeiyfgJmETtRMhBidBYM2QFFIkGa0U1k+hSyY87Nw7PY3eDqpvCBm7I3WCSfPeZskW/YYq6m4g== - dependencies: - time-zone "^1.0.0" - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4.1.1, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -debug@=3.1.0, debug@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^3.1.0, debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -decamelize-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= - dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - -decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-equal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= - dependencies: - strip-bom "^3.0.0" - -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - -defer-to-connect@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" - integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== - -define-properties@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -del@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - -del@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" - integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU= - dependencies: - globby "^6.1.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - p-map "^1.1.1" - pify "^3.0.0" - rimraf "^2.2.8" - -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" - -delegate@^3.1.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" - integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -dependency-graph@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.8.0.tgz#2da2d35ed852ecc24a5d6c17788ba57c3708755b" - integrity sha512-DCvzSq2UiMsuLnj/9AL484ummEgLtZIcRS7YvtO38QnpX3vqh9nJ8P+zhu8Ja+SmLrBHO2iDbva20jq38qvBkQ== - -dependency-tree@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/dependency-tree/-/dependency-tree-6.5.0.tgz#666d6838c2d8eab0eeeb2e2d19eafcbdda336cde" - integrity sha512-r0KO5BkQy8sMbyTD8NxSDOexsySbGpSH5fIsxCLZjarFTXMryiZoR7+Ao6OWkwLz6OeQPYCOIjUDh+knWitMEw== - dependencies: - commander "^2.19.0" - debug "^4.1.1" - filing-cabinet "^2.3.0" - precinct "^5.3.1" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -detective-amd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/detective-amd/-/detective-amd-3.0.0.tgz#40c8e21e229df8bca1ee2d4b952a7b67b01e2a5a" - integrity sha512-kOpKHyabdSKF9kj7PqYHLeHPw+TJT8q2u48tZYMkIcas28el1CYeLEJ42Nm+563/Fq060T5WknfwDhdX9+kkBQ== - dependencies: - ast-module-types "^2.3.1" - escodegen "^1.8.0" - get-amd-module-type "^3.0.0" - node-source-walk "^4.0.0" - -detective-cjs@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/detective-cjs/-/detective-cjs-3.1.1.tgz#18da3e39a002d2098a1123d45ce1de1b0d9045a0" - integrity sha512-JQtNTBgFY6h8uT6pgph5QpV3IyxDv+z3qPk/FZRDT9TlFfm5dnRtpH39WtQEr1khqsUxVqXzKjZHpdoQvQbllg== - dependencies: - ast-module-types "^2.4.0" - node-source-walk "^4.0.0" - -detective-es6@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detective-es6/-/detective-es6-2.1.0.tgz#7848feaec92279d82f7b3a98d8e1f5d93483a0f7" - integrity sha512-QSHqKGOp/YBIfmIqKXaXeq2rlL+bp3bcIQMfZ+0PvKzRlELSOSZxKRvpxVcxlLuocQv4QnOfuWGniGrmPbz8MQ== - dependencies: - node-source-walk "^4.0.0" - -detective-less@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/detective-less/-/detective-less-1.0.2.tgz#a68af9ca5f69d74b7d0aa190218b211d83b4f7e3" - integrity sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA== - dependencies: - debug "^4.0.0" - gonzales-pe "^4.2.3" - node-source-walk "^4.0.0" - -detective-postcss@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/detective-postcss/-/detective-postcss-3.0.1.tgz#511921951f66135e17d0ece2e7604c6e4966c9c6" - integrity sha512-tfTS2GdpUal5NY0aCqI4dpEy8Xfr88AehYKB0iBIZvo8y2g3UsrcDnrp9PR2FbzoW7xD5Rip3NJW7eCSvtqdUw== - dependencies: - debug "^4.1.1" - is-url "^1.2.4" - postcss "^7.0.2" - postcss-values-parser "^1.5.0" - -detective-sass@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/detective-sass/-/detective-sass-3.0.1.tgz#496b819efd1f5c4dd3f0e19b43a8634bdd6927c4" - integrity sha512-oSbrBozRjJ+QFF4WJFbjPQKeakoaY1GiR380NPqwdbWYd5wfl5cLWv0l6LsJVqrgWfFN1bjFqSeo32Nxza8Lbw== - dependencies: - debug "^4.1.1" - gonzales-pe "^4.2.3" - node-source-walk "^4.0.0" - -detective-scss@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/detective-scss/-/detective-scss-2.0.1.tgz#06f8c21ae6dedad1fccc26d544892d968083eaf8" - integrity sha512-VveyXW4WQE04s05KlJ8K0bG34jtHQVgTc9InspqoQxvnelj/rdgSAy7i2DXAazyQNFKlWSWbS+Ro2DWKFOKTPQ== - dependencies: - debug "^4.1.1" - gonzales-pe "^4.2.3" - node-source-walk "^4.0.0" - -detective-stylus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-1.0.0.tgz#50aee7db8babb990381f010c63fabba5b58e54cd" - integrity sha1-UK7n24uruZA4HwEMY/q7pbWOVM0= - -detective-typescript@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-4.1.2.tgz#796ef6215a948ce3a11ec7e787a6c2c03db62d35" - integrity sha512-jeQMIN/0hjMdMpFGoo9y+ibo+dTb1Vbg6z/peHoRMR69jqH691kgz1gT5XM5UfkDD/Ru0save1bSJBmUr2yjvQ== - dependencies: - node-source-walk "^4.0.0" - typescript "^3.0.3" - typescript-eslint-parser "^18.0.0" - -dev-ip@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0" - integrity sha1-p2o+0YVb56ASu4rBbLgPPADcKPA= - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctypes@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" - integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= - -dom-serializer@0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== - dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== - dependencies: - is-obj "^1.0.0" - -dot-prop@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.1.0.tgz#bdd8c986a77b83e3fca524e53786df916cabbd8a" - integrity sha512-n1oC6NBF+KM9oVXtjmen4Yo7HyAVWV2UUl50dCYJdw2924K6dX9bf9TTTWaKtYlRn0FEtxG27KS80ayVLixxJA== - dependencies: - is-obj "^2.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -easy-extender@^2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/easy-extender/-/easy-extender-2.3.4.tgz#298789b64f9aaba62169c77a2b3b64b4c9589b8f" - integrity sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q== - dependencies: - lodash "^4.17.10" - -eazy-logger@^3: - version "3.0.2" - resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-3.0.2.tgz#a325aa5e53d13a2225889b2ac4113b2b9636f4fc" - integrity sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw= - dependencies: - tfunk "^3.0.1" - -editorconfig@^0.15.3: - version "0.15.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" - integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== - dependencies: - commander "^2.19.0" - lru-cache "^4.1.5" - semver "^5.6.0" - sigmund "^1.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -ejs@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.2.tgz#3a32c63d1cd16d11266cd4703b14fec4e74ab4f6" - integrity sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q== - -elegant-spinner@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" - integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= - -emitter-mixin@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/emitter-mixin/-/emitter-mixin-0.0.3.tgz#5948cb286f2e48edc3b251a7cfc1f7883396d65c" - integrity sha1-WUjLKG8uSO3DslGnz8H3iDOW1lw= - -emittery@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.4.1.tgz#abe9d3297389ba424ac87e53d1c701962ce7433d" - integrity sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ== - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -empower-core@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-1.2.0.tgz#ce3fb2484d5187fa29c23fba8344b0b2fdf5601c" - integrity sha512-g6+K6Geyc1o6FdXs9HwrXleCFan7d66G5xSCfSF7x1mJDCes6t0om9lFQG3zOrzh3Bkb/45N0cZ5Gqsf7YrzGQ== - dependencies: - call-signature "0.0.2" - core-js "^2.0.0" - -encodeurl@~1.0.1, encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - -engine.io-client@~3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" - integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw== - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.1.1" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~3.3.1" - xmlhttprequest-ssl "~1.5.4" - yeast "0.1.2" - -engine.io-client@~3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.3.2.tgz#04e068798d75beda14375a264bb3d742d7bc33aa" - integrity sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ== - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.1.1" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~6.1.0" - xmlhttprequest-ssl "~1.5.4" - yeast "0.1.2" - -engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" - integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== - dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" - blob "0.0.5" - has-binary2 "~1.0.2" - -engine.io@~3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2" - integrity sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w== - dependencies: - accepts "~1.3.4" - base64id "1.0.0" - cookie "0.3.1" - debug "~3.1.0" - engine.io-parser "~2.1.0" - ws "~3.3.1" - -enhanced-resolve@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - tapable "^1.0.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -equal-length@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" - integrity sha1-IcoRLUirJLTh5//A5TOdMf38J0w= - -errno@^0.1.2, errno@^0.1.3: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es6-error@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" - integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escodegen@^1.8.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510" - integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -esm@^3.2.25: - version "3.2.25" - resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" - integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== - -espower-location-detector@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/espower-location-detector/-/espower-location-detector-1.0.0.tgz#a17b7ecc59d30e179e2bef73fb4137704cb331b5" - integrity sha1-oXt+zFnTDheeK+9z+0E3cEyzMbU= - dependencies: - is-url "^1.2.1" - path-is-absolute "^1.0.0" - source-map "^0.5.0" - xtend "^4.0.0" - -esprima@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -espurify@^1.6.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/espurify/-/espurify-1.8.1.tgz#5746c6c1ab42d302de10bd1d5bf7f0e8c0515056" - integrity sha512-ZDko6eY/o+D/gHCWyHTU85mKDgYcS4FJj7S+YD6WIInm7GQ6AnOjmcL4+buFV/JOztVLELi/7MmuGU5NHta0Mg== - dependencies: - core-js "^2.0.0" - -estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@1.8.1, etag@^1.8.1, etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eventemitter3@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" - integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg= - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^2.2.7: - version "2.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" - integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.1.2" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.3" - micromatch "^3.1.10" - -fast-glob@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602" - integrity sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg== - dependencies: - "@nodelib/fs.stat" "^2.0.1" - "@nodelib/fs.walk" "^1.2.1" - glob-parent "^5.0.0" - is-glob "^4.0.1" - merge2 "^1.2.3" - micromatch "^4.0.2" - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fastq@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" - integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== - dependencies: - reusify "^1.0.0" - -figures@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= - dependencies: - escape-string-regexp "^1.0.5" - -figures@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9" - integrity sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g== - dependencies: - escape-string-regexp "^1.0.5" - -file-exists-dazinatorfork@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/file-exists-dazinatorfork/-/file-exists-dazinatorfork-1.0.2.tgz#cd8d0d85f63e39dc81eceb0b687c44a2cca95c47" - integrity sha512-r70c72ln2YHzQINNfxDp02hAhbGkt1HffZ+Du8oetWDLjDtFja/Lm10lUaSh9e+wD+7VDvPee0b0C9SAy8pWZg== - -filing-cabinet@^2.3.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/filing-cabinet/-/filing-cabinet-2.3.3.tgz#77882b25ef0859c321a871b440823bc2ed590995" - integrity sha512-Lp9FNBm74UnZI/0tVcH8WlJZmnYf9/qImt1/VUaEj3rlBl+V7M5yVAzYPJ7X1T2WxQeCrSQN4jN64SlQa6Rbew== - dependencies: - app-module-path "^2.2.0" - commander "^2.13.0" - debug "^4.1.1" - enhanced-resolve "^4.1.0" - is-relative-path "^1.0.2" - module-definition "^3.0.0" - module-lookup-amd "^6.1.0" - resolve "^1.11.1" - resolve-dependency-path "^2.0.0" - sass-lookup "^3.0.0" - stylus-lookup "^3.0.1" - typescript "^3.0.3" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" - integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U= - dependencies: - debug "2.6.9" - encodeurl "~1.0.1" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.3.1" - unpipe "~1.0.0" - -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/find/-/find-0.3.0.tgz#4082e8fc8d8320f1a382b5e4f521b9bc50775cb8" - integrity sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw== - dependencies: - traverse-chain "~0.1.0" - -flatten@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" - integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= - -fn-name@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" - integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc= - -follow-redirects@1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" - integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== - dependencies: - debug "=3.1.0" - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -foreground-child@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" - integrity sha1-T9ca0t/elnibmApcCilZN8svXOk= - dependencies: - cross-spawn "^4" - signal-exit "^3.0.0" - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2, fresh@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" - integrity sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^3.0.0" - universalify "^0.1.0" - -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== - dependencies: - minipass "^2.2.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== - dependencies: - nan "^2.12.1" - node-pre-gyp "^0.12.0" - -fsevents@^2.0.6: - version "2.0.7" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.0.7.tgz#382c9b443c6cbac4c57187cdda23aa3bf1ccfc2a" - integrity sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -g-status@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/g-status/-/g-status-2.0.2.tgz#270fd32119e8fc9496f066fe5fe88e0a6bc78b97" - integrity sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA== - dependencies: - arrify "^1.0.1" - matcher "^1.0.0" - simple-git "^1.85.0" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -get-amd-module-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-amd-module-type/-/get-amd-module-type-3.0.0.tgz#bb334662fa04427018c937774570de495845c288" - integrity sha512-99Q7COuACPfVt18zH9N4VAMyb81S6TUgJm2NgV6ERtkh9VIkAaByZkW530wl3lLN5KTtSrK9jVLxYsoP5hQKsw== - dependencies: - ast-module-types "^2.3.2" - node-source-walk "^4.0.0" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" - integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg== - -get-port@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.0.0.tgz#aa22b6b86fd926dd7884de3e23332c9f70c031a6" - integrity sha512-imzMU0FjsZqNa6BqOjbbW6w5BivHIuQKopjpPqcnx0AVHJQKCxK1O+Ab3OrVXhrekqfVMjwA9ZYu062R+KcIsQ== - dependencies: - type-fest "^0.3.0" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.0.0, get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== - dependencies: - pump "^3.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" - integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== - dependencies: - is-glob "^4.0.1" - -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= - -glob@^7.0.3, glob@^7.1.3: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= - dependencies: - ini "^1.3.4" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globby@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" - integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -gonzales-pe@^4.2.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.4.tgz#356ae36a312c46fe0f1026dd6cb539039f8500d2" - integrity sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ== - dependencies: - minimist "1.1.x" - -good-listener@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" - integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= - dependencies: - delegate "^3.1.2" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" - integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== - -gray-matter@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" - integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw== - dependencies: - js-yaml "^3.11.0" - kind-of "^6.0.2" - section-matter "^1.0.0" - strip-bom-string "^1.0.0" - -hamljs@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/hamljs/-/hamljs-0.6.2.tgz#7b7116cf6dbe7278e42b3f6ef8725a33e177c8e3" - integrity sha1-e3EWz22+cnjkKz9u+HJaM+F3yOM= - -handlebars@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" - integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-binary2@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" - integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== - dependencies: - isarray "2.0.1" - -has-color@~0.1.0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" - integrity sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8= - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - -has@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-sum@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" - integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= - -hasha@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39" - integrity sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk= - dependencies: - is-stream "^1.0.1" - -hasha@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.0.0.tgz#fdc3785caea03df29535fc8adb512c3d3a709004" - integrity sha512-PqWdhnQhq6tqD32hZv+l1e5mJHNSudjnaAzgAHfkGiU0ABN6lmbZF8abJIulQHbZ7oiHhP8yL6O910ICMc+5pw== - dependencies: - is-stream "^1.1.0" - type-fest "^0.3.0" - -he@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== - -html-escaper@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-1.0.1.tgz#ee029e2862674017941355a7f61fc2c7c0a6fd72" - integrity sha1-7gKeKGJnQBeUE1Wn9h/Cx8Cm/XI= - -htmlparser2@^3.9.2: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -http-cache-semantics@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" - integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== - -http-errors@1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-proxy@1.15.2: - version "1.15.2" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.15.2.tgz#642fdcaffe52d3448d2bda3b0079e9409064da31" - integrity sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE= - dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" - -iconv-lite@0.4.24, iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ignore-by-default@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= - -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" - -ignore@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" - integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== - -immutable@^3: - version "3.8.2" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" - integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -import-local@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^3.0.0, indent-string@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - -irregular-plurals@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" - integrity sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw== - -is-absolute@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" - integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== - dependencies: - is-relative "^1.0.0" - is-windows "^1.0.1" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-binary-path@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-buffer@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - -is-error@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843" - integrity sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg== - -is-expression@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f" - integrity sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8= - dependencies: - acorn "~4.0.2" - object-assign "^4.0.1" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-installed-globally@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" - integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= - dependencies: - global-dirs "^0.1.0" - is-path-inside "^1.0.0" - -is-npm@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053" - integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA== - -is-number-like@^1.0.3: - version "1.0.8" - resolved "https://registry.yarnpkg.com/is-number-like/-/is-number-like-1.0.8.tgz#2e129620b50891042e44e9bbbb30593e75cfbbe3" - integrity sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA== - dependencies: - lodash.isfinite "^3.3.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^1.0.0, is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-observable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" - integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== - dependencies: - symbol-observable "^1.1.0" - -is-observable@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-2.0.0.tgz#327af1e8cdea9cd717f95911b87c5d34301721a6" - integrity sha512-fhBZv3eFKUbyHXZ1oHujdo2tZ+CNbdpdzzlENgCGZUC8keoGxUew2jYFLYcUB4qo7LDD03o4KK11m/QYD7kEjg== - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= - -is-path-cwd@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== - dependencies: - is-path-inside "^1.0.0" - -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= - dependencies: - path-is-inside "^1.0.1" - -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-plain-object@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" - integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== - dependencies: - isobject "^4.0.0" - -is-promise@^2.0.0, is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-relative-path@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-relative-path/-/is-relative-path-1.0.2.tgz#091b46a0d67c1ed0fe85f1f8cfdde006bb251d46" - integrity sha1-CRtGoNZ8HtD+hfH4z93gBrslHUY= - -is-relative@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" - integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== - dependencies: - is-unc-path "^1.0.0" - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-unc-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" - integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== - dependencies: - unc-path-regex "^0.1.2" - -is-url@^1.2.1, is-url@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== - -is-utf8@^0.2.0, is-utf8@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-whitespace@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f" - integrity sha1-Fjnssb4DauxppUy7QBz77XEUq38= - -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - -istanbul-lib-coverage@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" - integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== - -istanbul-lib-hook@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" - integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== - dependencies: - append-transform "^1.0.0" - -istanbul-lib-instrument@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" - integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== - dependencies: - "@babel/generator" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - istanbul-lib-coverage "^2.0.5" - semver "^6.0.0" - -istanbul-lib-report@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" - integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== - dependencies: - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - supports-color "^6.1.0" - -istanbul-lib-source-maps@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" - integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - rimraf "^2.6.3" - source-map "^0.6.1" - -istanbul-reports@^2.2.4: - version "2.2.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" - integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== - dependencies: - handlebars "^4.1.2" - -javascript-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.0.0.tgz#ef750216ae66504ffd670b68c8b8aa07bdf7b588" - integrity sha512-zzK8+ByrzvOL6N92hRewwUKL0wN0TOaIuUjX0Jj8lraxWvr5wHYs2YTjaj2lstF+8qMv5cmPPef47va8NT8lDw== - -js-beautify@^1.6.12: - version "1.10.1" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.1.tgz#bdfe738ddbcaa12e4fced5af2d7cfad59f60ac0a" - integrity sha512-4y8SHOIRC+/YQ2gs3zJEKBUraQerq49FJYyXRpdzUGYQzCq8q9xtIh0YXial1S5KmonVui4aiUb6XaGyjE51XA== - dependencies: - config-chain "^1.1.12" - editorconfig "^0.15.3" - glob "^7.1.3" - mkdirp "~0.5.1" - nopt "~4.0.1" - -js-string-escape@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= - -js-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" - integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== - dependencies: - minimist "^1.2.0" - -jsonfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" - integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jstransformer@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" - integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= - dependencies: - is-promise "^2.0.0" - promise "^7.0.1" - -junk@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/junk/-/junk-1.0.3.tgz#87be63488649cbdca6f53ab39bec9ccd2347f592" - integrity sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI= - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -latest-version@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -limiter@^1.0.5: - version "1.1.4" - resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.4.tgz#87c9c3972d389fdb0ba67a45aadbc5d2f8413bc1" - integrity sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg== - -linkify-it@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" - integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== - dependencies: - uc.micro "^1.0.1" - -lint-staged@^8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-8.2.1.tgz#752fcf222d9d28f323a3b80f1e668f3654ff221f" - integrity sha512-n0tDGR/rTCgQNwXnUf/eWIpPNddGWxC32ANTNYsj2k02iZb7Cz5ox2tytwBu+2r0zDXMEMKw7Y9OD/qsav561A== - dependencies: - chalk "^2.3.1" - commander "^2.14.1" - cosmiconfig "^5.2.0" - debug "^3.1.0" - dedent "^0.7.0" - del "^3.0.0" - execa "^1.0.0" - g-status "^2.0.2" - is-glob "^4.0.0" - is-windows "^1.0.2" - listr "^0.14.2" - listr-update-renderer "^0.5.0" - lodash "^4.17.11" - log-symbols "^2.2.0" - micromatch "^3.1.8" - npm-which "^3.0.1" - p-map "^1.1.1" - path-is-inside "^1.0.2" - pify "^3.0.0" - please-upgrade-node "^3.0.2" - staged-git-files "1.1.2" - string-argv "^0.0.2" - stringify-object "^3.2.2" - yup "^0.27.0" - -liquidjs@^6.4.3: - version "6.4.3" - resolved "https://registry.yarnpkg.com/liquidjs/-/liquidjs-6.4.3.tgz#c7caf7a3f6c87dc6a22a5a351328cf8f7298c243" - integrity sha512-m1xSB10Ncu22NR3X0xdaqu/GvP1xadDCFYGqGgd6me8DAWjyA68BKE5DHJmSxw1CGsWPsX+Hj2v/87J2w/LvMQ== - -listr-silent-renderer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" - integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= - -listr-update-renderer@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" - integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== - dependencies: - chalk "^1.1.3" - cli-truncate "^0.2.1" - elegant-spinner "^1.0.1" - figures "^1.7.0" - indent-string "^3.0.0" - log-symbols "^1.0.2" - log-update "^2.3.0" - strip-ansi "^3.0.1" - -listr-verbose-renderer@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" - integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== - dependencies: - chalk "^2.4.1" - cli-cursor "^2.1.0" - date-fns "^1.27.2" - figures "^2.0.0" - -listr@^0.14.2: - version "0.14.3" - resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" - integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== - dependencies: - "@samverschueren/stream-to-observable" "^0.3.0" - is-observable "^1.1.0" - is-promise "^2.1.0" - is-stream "^1.1.0" - listr-silent-renderer "^1.1.1" - listr-update-renderer "^0.5.0" - listr-verbose-renderer "^0.5.0" - p-map "^2.0.0" - rxjs "^6.3.3" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -load-json-file@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3" - integrity sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw== - dependencies: - graceful-fs "^4.1.15" - parse-json "^4.0.0" - pify "^4.0.1" - strip-bom "^3.0.0" - type-fest "^0.3.0" - -localtunnel@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-1.9.2.tgz#0012fcabc29cf964c130a01858768aa2bb65b5af" - integrity sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg== - dependencies: - axios "0.19.0" - debug "4.1.1" - openurl "1.1.1" - yargs "6.6.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - -lodash.flattendeep@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" - integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= - -lodash.isfinite@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3" - integrity sha1-+4m2WpqAKBgz8LdHizpRBPiY67M= - -lodash.islength@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.islength/-/lodash.islength-4.0.1.tgz#4e9868d452575d750affd358c979543dc20ed577" - integrity sha1-Tpho1FJXXXUK/9NYyXlUPcIO1Xc= - -lodash.merge@^4.6.1: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.template@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - -lodash.unescape@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" - integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.4: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -log-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" - integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= - dependencies: - chalk "^1.0.0" - -log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -log-update@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" - integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= - dependencies: - ansi-escapes "^3.0.0" - cli-cursor "^2.0.0" - wrap-ansi "^3.0.1" - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= - -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -loud-rejection@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-2.1.0.tgz#4020547ddbc39ed711c8434326df9fc7d2395355" - integrity sha512-g/6MQxUXYHeVqZ4PGpPL1fS1fOvlXoi7bay0pizmjAd/3JhyXwxzwrnr74yzdmhuerlslbRJ3x7IOXzFz0cE5w== - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.2" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^4.0.1, lru-cache@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -luxon@^1.16.0: - version "1.17.2" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.17.2.tgz#95189c450341cfddf5f826ef8c32b5b022943fd5" - integrity sha512-qELKtIj3HD41N+MvgoxArk8DZGUb4Gpiijs91oi+ZmKJzRlxY6CoyTwNoUwnogCVs4p8HuxVJDik9JbnYgrCng== - -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" - integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== - dependencies: - semver "^6.0.0" - -map-cache@^0.2.0, map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - -map-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -markdown-it-emoji@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc" - integrity sha1-m+4OmpkKljupbfaYDE/dsF37Tcw= - -markdown-it@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" - integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== - dependencies: - argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" - mdurl "^1.0.1" - uc.micro "^1.0.5" - -matcher@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.1.tgz#51d8301e138f840982b338b116bb0c09af62c1c2" - integrity sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg== - dependencies: - escape-string-regexp "^1.0.4" - -matcher@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/matcher/-/matcher-2.0.0.tgz#85fe38d97670dbd2a46590cf099401e2ffb4755c" - integrity sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng== - dependencies: - escape-string-regexp "^2.0.0" - -maximatch@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/maximatch/-/maximatch-0.1.0.tgz#86cd8d6b04c9f307c05a6b9419906d0360fb13a2" - integrity sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -md5-hex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" - integrity sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM= - dependencies: - md5-o-matic "^0.1.1" - -md5-hex@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" - integrity sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw== - dependencies: - blueimp-md5 "^2.10.0" - -md5-o-matic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" - integrity sha1-givM1l4RfFFPqxdrJZRdVBAKA8M= - -mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== - -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -memory-fs@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -meow@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" - integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== - dependencies: - camelcase-keys "^4.0.0" - decamelize-keys "^1.0.0" - loud-rejection "^1.0.0" - minimist-options "^3.0.1" - normalize-package-data "^2.3.4" - read-pkg-up "^3.0.0" - redent "^2.0.0" - trim-newlines "^2.0.0" - yargs-parser "^10.0.0" - -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - -merge2@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.4.tgz#c9269589e6885a60cf80605d9522d4b67ca646e3" - integrity sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A== - -micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -mime-db@1.40.0: - version "1.40.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" - integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== - -mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.24" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" - integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== - dependencies: - mime-db "1.40.0" - -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist-options@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" - integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@1.1.x: - version "1.1.3" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" - integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -minipass@^2.2.1, minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" - -mitt@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.1.3.tgz#528c506238a05dce11cd914a741ea2cc332da9b8" - integrity sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA== - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -module-definition@^3.0.0, module-definition@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-3.2.0.tgz#a1741d5ddf60d76c60d5b1f41ba8744ba08d3ef4" - integrity sha512-PO6o0BajpdRR+fb3FUSeDISgJpnyxg8UDUEalR8LPQajl0M5+m4jHWhgrMGGSEl6D9+sVl/l1fjOCvpBXIQ+2Q== - dependencies: - ast-module-types "^2.4.0" - node-source-walk "^4.0.0" - -module-lookup-amd@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/module-lookup-amd/-/module-lookup-amd-6.2.0.tgz#70600008b3f26630fde9ef9ae6165ac69de6ecbb" - integrity sha512-uxHCj5Pw9psZiC1znjU2qPsubt6haCSsN9m7xmIdoTciEgfxUkE1vhtDvjHPuOXEZrVJhjKgkmkP+w73rRuelQ== - dependencies: - commander "^2.8.1" - debug "^4.1.0" - file-exists-dazinatorfork "^1.0.2" - find "^0.3.0" - requirejs "^2.3.5" - requirejs-config-file "^3.1.1" - -moo@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.0.tgz#72f949e6735aeb27d07eb7c087ea5a70143c56e5" - integrity sha512-AMv6iqhTEd5vT/cQlH6cammKS5ekyHhyqTRKi5zKMWl1RTyFnQ3ohPSBNSm8ySe2wlxSKwDonr9D5ZT44mdO3g== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@^2.1.1, ms@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -multimatch@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b" - integrity sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA== - dependencies: - array-differ "^2.0.3" - array-union "^1.0.2" - arrify "^1.0.1" - minimatch "^3.0.4" - -mustache@^2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" - integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== - -nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -nested-error-stacks@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" - integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-source-walk@^4.0.0, node-source-walk@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-4.2.0.tgz#c2efe731ea8ba9c03c562aa0a9d984e54f27bc2c" - integrity sha512-hPs/QMe6zS94f5+jG3kk9E7TNm4P2SulrKiLWMzKszBfNZvL/V6wseHlTd7IvfW0NZWqPtK3+9yYNr+3USGteA== - dependencies: - "@babel/parser" "^7.0.0" - -nopt@^4.0.1, nopt@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-url@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" - integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== - -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-path@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" - integrity sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw== - dependencies: - which "^1.2.10" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -npm-which@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" - integrity sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo= - dependencies: - commander "^2.9.0" - npm-path "^2.0.2" - which "^1.2.10" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -nunjucks@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.0.tgz#53e95f43c9555e822e8950008a201b1002d49933" - integrity sha512-YS/qEQ6N7qCnUdm6EoYRBfJUdWNT0PpKbbRnogV2XyXbBm2STIP1O6yrdZHgwMVK7fIYUx7i8+yatEixnXSB1w== - dependencies: - a-sync-waterfall "^1.0.0" - asap "^2.0.3" - yargs "^3.32.0" - optionalDependencies: - chokidar "^2.0.0" - -nyc@^14.1.1: - version "14.1.1" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.1.1.tgz#151d64a6a9f9f5908a1b73233931e4a0a3075eeb" - integrity sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw== - dependencies: - archy "^1.0.0" - caching-transform "^3.0.2" - convert-source-map "^1.6.0" - cp-file "^6.2.0" - find-cache-dir "^2.1.0" - find-up "^3.0.0" - foreground-child "^1.5.6" - glob "^7.1.3" - istanbul-lib-coverage "^2.0.5" - istanbul-lib-hook "^2.0.7" - istanbul-lib-instrument "^3.3.0" - istanbul-lib-report "^2.0.8" - istanbul-lib-source-maps "^3.0.6" - istanbul-reports "^2.2.4" - js-yaml "^3.13.1" - make-dir "^2.1.0" - merge-source-map "^1.1.0" - resolve-from "^4.0.0" - rimraf "^2.6.3" - signal-exit "^3.0.2" - spawn-wrap "^1.4.2" - test-exclude "^5.2.3" - uuid "^3.3.2" - yargs "^13.2.2" - yargs-parser "^13.0.0" - -object-assign@^4.0.1, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" - integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-keys@^1.0.11, object-keys@^1.0.12: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-path@^0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.9.2.tgz#0fd9a74fc5fad1ae3968b586bda5c632bd6c05a5" - integrity sha1-D9mnT8X60a45aLWGvaXGMr1sBaU= - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -observable-to-promise@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-1.0.0.tgz#37e136f16a15385ac063411ada0e1202bfff58f4" - integrity sha512-cqnGUrNsE6vdVDTPAX9/WeVzwy/z37vdxupdQXU8vgTXRFH72KCZiZga8aca2ulRPIeem8W3vW9rQHBwfIl2WA== - dependencies: - is-observable "^2.0.0" - symbol-observable "^1.0.4" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - -openurl@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" - integrity sha1-OHW0sO96UsFW8NtB1GCduw+Us4c= - -opn@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" - integrity sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g== - dependencies: - is-wsl "^1.1.0" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -ora@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" - integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== - dependencies: - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-spinners "^2.0.0" - log-symbols "^2.2.0" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - -os-homedir@^1.0.0, os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - -os-shim@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" - integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc= - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" - integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== - -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-hash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-3.0.0.tgz#50183f2d36c9e3e528ea0a8605dff57ce976f88e" - integrity sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA== - dependencies: - graceful-fs "^4.1.15" - hasha "^3.0.0" - lodash.flattendeep "^4.4.0" - release-zalgo "^1.0.0" - -package-hash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" - integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== - dependencies: - graceful-fs "^4.1.15" - hasha "^5.0.0" - lodash.flattendeep "^4.4.0" - release-zalgo "^1.0.0" - -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -parse-filepath@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" - integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= - dependencies: - is-absolute "^1.0.0" - map-cache "^0.2.0" - path-root "^0.1.1" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-ms@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-0.1.2.tgz#dd3fa25ed6c2efc7bdde12ad9b46c163aa29224e" - integrity sha1-3T+iXtbC78e93hKtm0bBY6opIk4= - -parse-ms@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" - integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= - dependencies: - better-assert "~1.0.0" - -parseurl@~1.3.2: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.1, path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-root-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" - integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= - -path-root@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" - integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= - dependencies: - path-root-regex "^0.1.0" - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picomatch@^2.0.4, picomatch@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" - integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pkg-conf@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-3.1.0.tgz#d9f9c75ea1bae0e77938cde045b276dac7cc69ae" - integrity sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ== - dependencies: - find-up "^3.0.0" - load-json-file "^5.2.0" - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" - integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ== - dependencies: - semver-compare "^1.0.0" - -plur@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz#60267967866a8d811504fe58f2faaba237546a5b" - integrity sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w== - dependencies: - irregular-plurals "^2.0.0" - -portscanner@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/portscanner/-/portscanner-2.1.1.tgz#eabb409e4de24950f5a2a516d35ae769343fbb96" - integrity sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y= - dependencies: - async "1.5.2" - is-number-like "^1.0.3" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-values-parser@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz#5d9fa63e2bcb0179ce48f3235303765eb89f3047" - integrity sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ== - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss@^7.0.2: - version "7.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" - integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -pre-commit@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.2.2.tgz#dbcee0ee9de7235e57f79c56d7ce94641a69eec6" - integrity sha1-287g7p3nI15X95xW186UZBpp7sY= - dependencies: - cross-spawn "^5.0.1" - spawn-sync "^1.0.15" - which "1.2.x" - -pre-push@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pre-push/-/pre-push-0.1.1.tgz#2a2a79827d243a76c91089897ac707f45e716aac" - integrity sha1-Kip5gn0kOnbJEImJescH9F5xaqw= - dependencies: - shelljs "0.3.x" - -precinct@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/precinct/-/precinct-5.3.1.tgz#4ab0ec1d1a8f1b2f4982b810d56419e7b3025870" - integrity sha512-HOIXDarP6S5JXYC5GhnpoAj9RqJ6yAwZ8VI71vQFlq1rmkBRPs+Mt60TOr7DUc/fx309iIQaniB4x3zueOOSdw== - dependencies: - commander "^2.19.0" - debug "^4.1.1" - detective-amd "^3.0.0" - detective-cjs "^3.1.1" - detective-es6 "^2.0.0" - detective-less "^1.0.2" - detective-postcss "^3.0.0" - detective-sass "^3.0.0" - detective-scss "^2.0.0" - detective-stylus "^1.0.0" - detective-typescript "^4.1.2" - module-definition "^3.1.0" - node-source-walk "^4.2.0" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -prettier@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== - -pretty-ms@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-0.2.2.tgz#da879a682ff33a37011046f13d627f67c73b84f6" - integrity sha1-2oeaaC/zOjcBEEbxPWJ/Z8c7hPY= - dependencies: - parse-ms "^0.1.0" - -pretty-ms@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-5.0.0.tgz#6133a8f55804b208e4728f6aa7bf01085e951e24" - integrity sha512-94VRYjL9k33RzfKiGokPBPpsmloBYSf5Ri+Pq19zlsEcUKFob+admeXr5eFDRuPjFmEOcjJvPGdillYOJyvZ7Q== - dependencies: - parse-ms "^2.1.0" - -pretty@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5" - integrity sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU= - dependencies: - condense-newlines "^0.2.1" - extend-shallow "^2.0.1" - js-beautify "^1.6.12" - -prismjs@^1.15.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.17.1.tgz#e669fcbd4cdd873c35102881c33b14d0d68519be" - integrity sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q== - optionalDependencies: - clipboard "^2.0.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise@^7.0.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -property-expr@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" - integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g== - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -pug-attrs@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.4.tgz#b2f44c439e4eb4ad5d4ef25cac20d18ad28cc336" - integrity sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ== - dependencies: - constantinople "^3.0.1" - js-stringify "^1.0.1" - pug-runtime "^2.0.5" - -pug-code-gen@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.2.tgz#ad0967162aea077dcf787838d94ed14acb0217c2" - integrity sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw== - dependencies: - constantinople "^3.1.2" - doctypes "^1.1.0" - js-stringify "^1.0.1" - pug-attrs "^2.0.4" - pug-error "^1.3.3" - pug-runtime "^2.0.5" - void-elements "^2.0.1" - with "^5.0.0" - -pug-error@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.3.tgz#f342fb008752d58034c185de03602dd9ffe15fa6" - integrity sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ== - -pug-filters@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-3.1.1.tgz#ab2cc82db9eeccf578bda89130e252a0db026aa7" - integrity sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg== - dependencies: - clean-css "^4.1.11" - constantinople "^3.0.1" - jstransformer "1.0.0" - pug-error "^1.3.3" - pug-walk "^1.1.8" - resolve "^1.1.6" - uglify-js "^2.6.1" - -pug-lexer@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-4.1.0.tgz#531cde48c7c0b1fcbbc2b85485c8665e31489cfd" - integrity sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA== - dependencies: - character-parser "^2.1.1" - is-expression "^3.0.0" - pug-error "^1.3.3" - -pug-linker@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.6.tgz#f5bf218b0efd65ce6670f7afc51658d0f82989fb" - integrity sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg== - dependencies: - pug-error "^1.3.3" - pug-walk "^1.1.8" - -pug-load@^2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.12.tgz#d38c85eb85f6e2f704dea14dcca94144d35d3e7b" - integrity sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg== - dependencies: - object-assign "^4.1.0" - pug-walk "^1.1.8" - -pug-parser@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-5.0.1.tgz#03e7ada48b6840bd3822f867d7d90f842d0ffdc9" - integrity sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA== - dependencies: - pug-error "^1.3.3" - token-stream "0.0.1" - -pug-runtime@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.5.tgz#6da7976c36bf22f68e733c359240d8ae7a32953a" - integrity sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw== - -pug-strip-comments@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz#cc1b6de1f6e8f5931cf02ec66cdffd3f50eaf8a8" - integrity sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw== - dependencies: - pug-error "^1.3.3" - -pug-walk@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.8.tgz#b408f67f27912f8c21da2f45b7230c4bd2a5ea7a" - integrity sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA== - -pug@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.4.tgz#ee7682ec0a60494b38d48a88f05f3b0ac931377d" - integrity sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw== - dependencies: - pug-code-gen "^2.0.2" - pug-filters "^3.1.1" - pug-lexer "^4.1.0" - pug-linker "^3.0.6" - pug-load "^2.0.12" - pug-parser "^5.0.1" - pug-runtime "^2.0.5" - pug-strip-comments "^1.0.4" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -qs@6.2.3: - version "6.2.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" - integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= - -quick-lru@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" - integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= - -range-parser@~1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@^2.3.2: - version "2.4.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" - integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== - dependencies: - bytes "3.1.0" - http-errors "1.7.3" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.2.7, rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - -read-pkg-up@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" - integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== - dependencies: - find-up "^3.0.0" - read-pkg "^3.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.1.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -readdirp@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.1.1.tgz#b158123ac343c8b0f31d65680269cc0fc1025db1" - integrity sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ== - dependencies: - picomatch "^2.0.4" - -recursive-copy@^2.0.10: - version "2.0.10" - resolved "https://registry.yarnpkg.com/recursive-copy/-/recursive-copy-2.0.10.tgz#a39402f2270c5f8b562b48d438a42e2e6e5c644c" - integrity sha512-S9J9XJUnfZ2NUS3lK6lx6HWLl2nWui+f7AKuu+qoFs4ikEPYgZ3qKk1T6tmBnr7PzhtKnawE+6TREy9XQKmxCA== - dependencies: - del "^2.2.0" - emitter-mixin "0.0.3" - errno "^0.1.2" - graceful-fs "^4.1.4" - junk "^1.0.1" - maximatch "^0.1.0" - mkdirp "^0.5.1" - pify "^2.3.0" - promise "^7.0.1" - slash "^1.0.0" - -redent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" - integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= - dependencies: - indent-string "^3.0.0" - strip-indent "^2.0.0" - -regenerate-unicode-properties@^8.0.2: - version "8.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" - integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-runtime@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexpu-core@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" - integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.0.2" - regjsgen "^0.5.0" - regjsparser "^0.6.0" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.1.0" - -registry-auth-token@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.0.0.tgz#30e55961eec77379da551ea5c4cf43cbf03522be" - integrity sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw== - dependencies: - rc "^1.2.8" - safe-buffer "^5.0.1" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -regjsgen@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" - integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== - -regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== - dependencies: - jsesc "~0.5.0" - -release-zalgo@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" - integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= - dependencies: - es6-error "^4.0.1" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.5.2, repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -require-precompiled@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/require-precompiled/-/require-precompiled-0.1.0.tgz#5a1b52eb70ebed43eb982e974c85ab59571e56fa" - integrity sha1-WhtS63Dr7UPrmC6XTIWrWVceVvo= - -requirejs-config-file@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/requirejs-config-file/-/requirejs-config-file-3.1.2.tgz#de8c0b3eebdf243511c994a8a24b006f8b825997" - integrity sha512-sdLWywcDuNz7EIOhenSbRfT4YF84nItDv90coN2htbokjmU2QeyQuSBZILQUKNksepl8UPVU+hgYySFaDxbJPQ== - dependencies: - esprima "^4.0.0" - make-dir "^2.1.0" - stringify-object "^3.2.1" - -requirejs@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9" - integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg== - -requires-port@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-dependency-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz#11700e340717b865d216c66cabeb4a2a3c696736" - integrity sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w== - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.2.0, resolve@^1.3.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== - dependencies: - path-parse "^1.0.6" - -resp-modifier@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/resp-modifier/-/resp-modifier-6.0.2.tgz#b124de5c4fbafcba541f48ffa73970f4aa456b4f" - integrity sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08= - dependencies: - debug "^2.2.0" - minimatch "^3.0.2" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -reusify@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= - dependencies: - align-text "^0.1.1" - -rimraf@^2.2.8, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== - -rx@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= - -rxjs@^5.5.6: - version "5.5.12" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" - integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw== - dependencies: - symbol-observable "1.0.1" - -rxjs@^6.3.3: - version "6.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" - integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== - dependencies: - tslib "^1.9.0" - -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sass-lookup@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac" - integrity sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg== - dependencies: - commander "^2.16.0" - -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -section-matter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" - integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== - dependencies: - extend-shallow "^2.0.1" - kind-of "^6.0.0" - -select@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" - integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= - -semver-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" - integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= - -semver-diff@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= - dependencies: - semver "^5.0.3" - -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== - -semver@5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== - -semver@^6.0.0, semver@^6.1.1, semver@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - -serialize-error@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" - integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= - -serialize-javascript@^1.3.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" - integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== - -serve-index@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" - -server-destroy@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" - integrity sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0= - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shelljs@0.3.x: - version "0.3.0" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" - integrity sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E= - -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -simple-git@^1.85.0: - version "1.124.0" - resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.124.0.tgz#10a73cc1af303832b5c11720d4256e134fba35ca" - integrity sha512-ks9mBoO4ODQy/xGLC8Cc+YDvj/hho/IKgPhi6h5LI/sA+YUdHc3v0DEoHzM29VmulubpGCxMJUSFmyXNsjNMEA== - dependencies: - debug "^4.0.1" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= - -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -slugify@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.4.tgz#78d2792d7222b55cd9fc81fa018df99af779efeb" - integrity sha512-KP0ZYk5hJNBS8/eIjGkFDCzGQIoZ1mnfQRYS5WM3273z+fxGWXeN0fkwf2ebEweydv9tioZIHGZKoF21U07/nw== - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -socket.io-adapter@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" - integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs= - -socket.io-client@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" - integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ== - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~3.1.0" - engine.io-client "~3.2.0" - has-binary2 "~1.0.2" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.2.0" - to-array "0.1.4" - -socket.io-client@^2.0.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.2.0.tgz#84e73ee3c43d5020ccc1a258faeeb9aec2723af7" - integrity sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA== - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~3.1.0" - engine.io-client "~3.3.1" - has-binary2 "~1.0.2" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.3.0" - to-array "0.1.4" - -socket.io-parser@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" - integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA== - dependencies: - component-emitter "1.2.1" - debug "~3.1.0" - isarray "2.0.1" - -socket.io-parser@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f" - integrity sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng== - dependencies: - component-emitter "1.2.1" - debug "~3.1.0" - isarray "2.0.1" - -socket.io@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" - integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA== - dependencies: - debug "~3.1.0" - engine.io "~3.2.0" - has-binary2 "~1.0.2" - socket.io-adapter "~1.1.0" - socket.io-client "2.1.1" - socket.io-parser "~3.2.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.5.12: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" - integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= - -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spawn-sync@^1.0.15: - version "1.0.15" - resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" - integrity sha1-sAeZVX63+wyDdsKdROih6mfldHY= - dependencies: - concat-stream "^1.4.7" - os-shim "^0.1.2" - -spawn-wrap@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" - integrity sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg== - dependencies: - foreground-child "^1.5.6" - mkdirp "^0.5.0" - os-homedir "^1.0.1" - rimraf "^2.6.2" - signal-exit "^3.0.2" - which "^1.3.0" - -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stack-utils@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== - -staged-git-files@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b" - integrity sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4= - -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== - -stream-throttle@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/stream-throttle/-/stream-throttle-0.1.3.tgz#add57c8d7cc73a81630d31cd55d3961cfafba9c3" - integrity sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM= - dependencies: - commander "^2.2.0" - limiter "^1.0.5" - -string-argv@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" - integrity sha1-2sMECGkMIfPDYwo/86BYd73L1zY= - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff" - integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^5.2.0" - -string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== - dependencies: - safe-buffer "~5.1.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-object@^3.2.1, stringify-object@^3.2.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" - integrity sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE= - -strip-bom-buf@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-2.0.0.tgz#ff9c223937f8e7154b77e9de9bde094186885c15" - integrity sha512-gLFNHucd6gzb8jMsl5QmZ3QgnUJmp7qn4uUSHNwEXumAp7YizoGYw19ZUVfuq4aBOQUtyn2k8X/CwzWB73W2lQ== - dependencies: - is-utf8 "^0.2.1" - -strip-bom-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -stylus-lookup@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" - integrity sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg== - dependencies: - commander "^2.8.1" - debug "^4.1.0" - -supertap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e" - integrity sha512-HZJ3geIMPgVwKk2VsmO5YHqnnJYl6bV5A9JW2uzqV43WmpgliNEYbuvukfor7URpaqpxuw3CfZ3ONdVbZjCgIA== - dependencies: - arrify "^1.0.1" - indent-string "^3.2.0" - js-yaml "^3.10.0" - serialize-error "^2.1.0" - strip-ansi "^4.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.0.0.tgz#f2392c50ab35bb3cae7beebf24d254a19f880c06" - integrity sha512-WRt32iTpYEZWYOpcetGm0NPeSvaebccx7hhS/5M6sAiqnhedtFCHFxkjzZlJvFNCPowiKSFGiZk5USQDFy83vQ== - dependencies: - has-flag "^4.0.0" - -symbol-observable@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= - -symbol-observable@^1.0.4, symbol-observable@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - -synchronous-promise@^2.0.6: - version "2.0.9" - resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.9.tgz#b83db98e9e7ae826bf9c8261fd8ac859126c780a" - integrity sha512-LO95GIW16x69LuND1nuuwM4pjgFGupg7pZ/4lU86AmchPKrhk0o2tpMU2unXRrqo81iAFe1YJ0nAGEVwsrZAgg== - -tapable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tar@^4: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.5" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= - dependencies: - execa "^0.7.0" - -test-exclude@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" - integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== - dependencies: - glob "^7.1.3" - minimatch "^3.0.4" - read-pkg-up "^4.0.0" - require-main-filename "^2.0.0" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -tfunk@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/tfunk/-/tfunk-3.1.0.tgz#38e4414fc64977d87afdaa72facb6d29f82f7b5b" - integrity sha1-OORBT8ZJd9h6/apy+sttKfgve1s= - dependencies: - chalk "^1.1.1" - object-path "^0.9.0" - -time-require@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/time-require/-/time-require-0.1.2.tgz#f9e12cb370fc2605e11404582ba54ef5ca2b2d98" - integrity sha1-+eEss3D8JgXhFARYK6VO9corLZg= - dependencies: - chalk "^0.4.0" - date-time "^0.1.1" - pretty-ms "^0.2.1" - text-table "^0.2.0" - -time-zone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" - integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0= - -tiny-emitter@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" - integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== - -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -token-stream@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" - integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= - -toposort@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" - integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= - -traverse-chain@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" - integrity sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE= - -trim-newlines@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" - integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= - -trim-off-newlines@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" - integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - -tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-fest@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" - integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== - -type-fest@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" - integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -typescript-eslint-parser@^18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-18.0.0.tgz#3e5055a44980d69e4154350fc5d8b1ab4e2332a8" - integrity sha512-Pn/A/Cw9ysiXSX5U1xjBmPQlxtWGV2o7jDNiH/u7KgBO2yC/y37wNFl2ogSrGZBQFuglLzGq0Xl0Bt31Jv44oA== - dependencies: - lodash.unescape "4.0.1" - semver "5.5.0" - -typescript@^3.0.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" - integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== - -ua-parser-js@0.7.17: - version "0.7.17" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" - integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== - -uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== - -uglify-js@^2.6.1: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= - dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - -uglify-js@^3.1.4, uglify-js@^3.3.27: - version "3.6.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" - integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== - dependencies: - commander "~2.20.0" - source-map "~0.6.1" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= - -uid2@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" - integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unc-path-regex@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" - integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= - dependencies: - crypto-random-string "^1.0.0" - -unique-temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-temp-dir/-/unique-temp-dir-1.0.0.tgz#6dce95b2681ca003eebfb304a415f9cbabcc5385" - integrity sha1-bc6VsmgcoAPuv7MEpBX5y6vMU4U= - dependencies: - mkdirp "^0.5.1" - os-tmpdir "^1.0.1" - uid2 "0.0.3" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" - integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== - -update-notifier@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250" - integrity sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ== - dependencies: - boxen "^3.0.0" - chalk "^2.0.1" - configstore "^4.0.0" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.1.0" - is-npm "^3.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -viperhtml@^2.17.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/viperhtml/-/viperhtml-2.17.0.tgz#a4958c83027a6ce796e0e20eb7ef2271bff61f5a" - integrity sha512-BjqqrwZPxpIZuwljESguNZzxXayLIzFHLhBF2kgz/3Yo9bhI41LR787LfNcILU4oqmUne2v3UT7hGb+2bwchMQ== - dependencies: - csso "^3.5.0" - html-escaper "^1.0.1" - htmlparser2 "^3.9.2" - uglify-js "^3.3.27" - -void-elements@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= - -vue-server-renderer@^2.6.10: - version "2.6.10" - resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375" - integrity sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug== - dependencies: - chalk "^1.1.3" - hash-sum "^1.0.2" - he "^1.1.0" - lodash.template "^4.4.0" - lodash.uniq "^4.5.0" - resolve "^1.2.0" - serialize-javascript "^1.3.0" - source-map "0.5.6" - -vue@^2.6.10: - version "2.6.10" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" - integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ== - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= - dependencies: - defaults "^1.0.3" - -well-known-symbols@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-2.0.0.tgz#e9c7c07dbd132b7b84212c8174391ec1f9871ba5" - integrity sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q== - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@1.2.x: - version "1.2.14" - resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" - integrity sha1-mofEN48D6CfOyvGs31bHNsAcFOU= - dependencies: - isexe "^2.0.0" - -which@^1.2.10, which@^1.2.9, which@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -widest-line@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== - dependencies: - string-width "^2.1.1" - -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= - -window-size@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" - integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= - -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= - -with@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe" - integrity sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4= - dependencies: - acorn "^3.1.0" - acorn-globals "^3.0.0" - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrap-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" - integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^2.0.0, write-file-atomic@^2.4.2: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -write-file-atomic@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.0.tgz#1b64dbbf77cb58fd09056963d63e62667ab4fb21" - integrity sha512-EIgkf60l2oWsffja2Sf2AL384dx328c0B+cIYPTQq5q2rOYuDV00/iPFBOUiDKKwKMOhkymH8AidPaRvzfxY+Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -ws@~3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -ws@~6.1.0: - version "6.1.4" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" - integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== - dependencies: - async-limiter "~1.0.0" - -xdg-basedir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= - -xmlhttprequest-ssl@~1.5.4: - version "1.5.5" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" - integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^3.2.0, y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yallist@^3.0.0, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== - -yargs-parser@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" - -yargs-parser@^13.0.0, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^4.1.0, yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw= - dependencies: - camelcase "^3.0.0" - -yargs@6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.4.0.tgz#816e1a866d5598ccf34e5596ddce22d92da490d4" - integrity sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^4.1.0" - -yargs@6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^4.2.0" - -yargs@^13.2.2: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" - -yargs@^3.32.0: - version "3.32.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" - integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= - dependencies: - camelcase "^2.0.1" - cliui "^3.0.3" - decamelize "^1.1.1" - os-locale "^1.4.0" - string-width "^1.0.1" - window-size "^0.1.4" - y18n "^3.2.0" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" - -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= - -yup@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/yup/-/yup-0.27.0.tgz#f8cb198c8e7dd2124beddc2457571329096b06e7" - integrity sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ== - dependencies: - "@babel/runtime" "^7.0.0" - fn-name "~2.0.1" - lodash "^4.17.11" - property-expr "^1.5.0" - synchronous-promise "^2.0.6" - toposort "^2.0.2" From a0aa9ec52ea18e2ea7e1732a82ef0eb11318e617 Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Wed, 16 Oct 2019 12:33:44 -0700 Subject: [PATCH 043/746] Fixes #676 --- src/Util/Merge.js | 9 ++++++--- test/MergeTest.js | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Util/Merge.js b/src/Util/Merge.js index 3eb57b905..17cb3eeb6 100644 --- a/src/Util/Merge.js +++ b/src/Util/Merge.js @@ -7,9 +7,12 @@ function getMergedItem(target, source, parentKey) { return source; } - if (!target) { - return source; - } else if (Array.isArray(target) && Array.isArray(source)) { + // deep copy objects to avoid sharing and to effect key renaming + if (!target && isPlainObject(source)) { + target = {}; + } + + if (Array.isArray(target) && Array.isArray(source)) { return target.concat(source); } else if (isPlainObject(target)) { if (isPlainObject(source)) { diff --git a/test/MergeTest.js b/test/MergeTest.js index f5e99fdd8..ce58d6a68 100644 --- a/test/MergeTest.js +++ b/test/MergeTest.js @@ -145,3 +145,10 @@ test("Deep, override: prefix at other placements", t => { } ); }); + +test("Deep, override: empty", t => { + t.deepEqual(Merge({}, { a: { b: [3, 4] } }), { a: { b: [3, 4] } }); + t.deepEqual(Merge({}, { a: [2] }), { a: [2] }); + t.deepEqual(Merge({}, { "override:a": [2] }), { a: [2] }); + t.deepEqual(Merge({}, { a: { "override:b": [3, 4] } }), { a: { b: [3, 4] } }); +}); From bf5e8c6455d7097f8b79097f30143d376a342c89 Mon Sep 17 00:00:00 2001 From: Ed Brannin Date: Tue, 29 Oct 2019 13:00:29 -0400 Subject: [PATCH 044/746] Improve Sortable test coverage; call out a bug; fix others --- src/Util/Sortable.js | 4 ++-- test/SortableTest.js | 49 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/Util/Sortable.js b/src/Util/Sortable.js index 176f90181..6d2805571 100644 --- a/src/Util/Sortable.js +++ b/src/Util/Sortable.js @@ -37,11 +37,11 @@ class Sortable { } sortAscending() { - return this.sort(this.getSortFunctionAscending); + return this.sort(this.getSortFunctionAscending()); } sortDescending() { - return this.sort(this.getSortFunctionDescending); + return this.sort(this.getSortFunctionDescending()); } isSortAscending() { diff --git a/test/SortableTest.js b/test/SortableTest.js index d43570088..82a51af16 100644 --- a/test/SortableTest.js +++ b/test/SortableTest.js @@ -9,24 +9,54 @@ test("get Sort Function", t => { test("Alphabetic Ascending", t => { let s = new Sortable(); + t.false(s.isSortNumeric()); + t.true(s.isSortAscending()); + s.add("a"); s.add("z"); s.add("m"); t.deepEqual(s.sort(), ["a", "m", "z"]); }); +test.skip("Alphabetic Ascending (shortcut)", t => { + /* FIXME THIS WILL NOT WORK because s.sortAscending() has been replaced by the boolean sortAscending. + * + * If backwards compatibility were not an issue, I'd recommend renaming the boolean properties + * to isSort(Ascending|Numeric) and renaming the getters & Setters to (get|set)IsSort(Ascending|Numeric) + */ + let s = new Sortable(); + s.add("a"); + s.add("z"); + s.add("m"); + t.deepEqual(s.sortAscending(), ["a", "m", "z"]); +}); + test("Alphabetic Descending", t => { let s = new Sortable(); s.setSortDescending(); + t.false(s.isSortNumeric()); + t.false(s.isSortAscending()); + s.add("a"); s.add("z"); s.add("m"); t.deepEqual(s.sort(), ["z", "m", "a"]); }); +test("Alphabetic Descending (shortcut)", t => { + let s = new Sortable(); + s.add("a"); + s.add("z"); + s.add("m"); + t.deepEqual(s.sortDescending(), ["z", "m", "a"]); +}); + test("Numeric Ascending", t => { let s = new Sortable(); s.setSortNumeric(true); + t.true(s.isSortNumeric()); + t.true(s.isSortAscending()); + s.add(1); s.add(4); s.add(2); @@ -37,6 +67,9 @@ test("Numeric Descending", t => { let s = new Sortable(); s.setSortNumeric(true); s.setSortDescending(); + t.true(s.isSortNumeric()); + t.false(s.isSortAscending()); + s.add(1); s.add(4); s.add(2); @@ -149,3 +182,19 @@ test("Alphabetic Descending (str sort arg)", t => { s.add("m"); t.deepEqual(s.sort("descending"), ["z", "m", "a"]); }); + +test("Alphabetic Ascending (short str sort arg)", t => { + let s = new Sortable(); + s.add("a"); + s.add("z"); + s.add("m"); + t.deepEqual(s.sort("A-Z"), ["a", "m", "z"]); +}); + +test("Alphabetic Descending (short str sort arg)", t => { + let s = new Sortable(); + s.add("a"); + s.add("z"); + s.add("m"); + t.deepEqual(s.sort("Z-A"), ["z", "m", "a"]); +}); From d6e3d465e1ea507c5b427318e88b0ae930a06427 Mon Sep 17 00:00:00 2001 From: Ed Brannin Date: Wed, 30 Oct 2019 22:16:46 -0400 Subject: [PATCH 045/746] Test coverage for EleventyErrorUtil --- test/EleventyErrorUtilTest.js | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 test/EleventyErrorUtilTest.js diff --git a/test/EleventyErrorUtilTest.js b/test/EleventyErrorUtilTest.js new file mode 100644 index 000000000..9fa210ec1 --- /dev/null +++ b/test/EleventyErrorUtilTest.js @@ -0,0 +1,51 @@ +import test from "ava"; +import EleventyErrorUtil from "../src/EleventyErrorUtil"; + +const SAMPLE_ERROR = new Error("Nothing to see here"); + +const { + cleanMessage, + hasEmbeddedError, + convertErrorToString, + deconvertErrorToObject +} = EleventyErrorUtil; + +test("hasEmbeddedError()", t => { + t.false(hasEmbeddedError("")); + t.true(hasEmbeddedError(convertErrorToString(SAMPLE_ERROR))); +}); + +test("cleanMessage()", t => { + const text = "I am the very model of a sample text input"; + t.is(cleanMessage(text), text); + t.is(cleanMessage(text + convertErrorToString(SAMPLE_ERROR)), text); +}); + +test("deconvertErrorToObject() should throw on invalid inputs", t => { + t.throws( + () => deconvertErrorToObject(undefined), + "Could not convert error object from: undefined" + ); + t.throws( + () => deconvertErrorToObject(""), + "Could not convert error object from: " + ); + t.throws( + () => deconvertErrorToObject("Not an error"), + "Could not convert error object from: Not an error" + ); +}); + +test("deconvertErrorToObject() should return its argument if it does not contain another error", t => { + t.is(deconvertErrorToObject(SAMPLE_ERROR), SAMPLE_ERROR); +}); + +test("deconvertErrorToObject() should get message and stack from convertErrorToString()", t => { + const nestingError = new Error( + "This error contains a sample error: " + convertErrorToString(SAMPLE_ERROR) + ); + const result = deconvertErrorToObject(nestingError); + t.is(result.name, nestingError.name); + t.is(result.message, SAMPLE_ERROR.message); + t.is(result.stack, SAMPLE_ERROR.stack); +}); From e0dc2ac00d8085c7ad3aa30f52e774110fb150c6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 5 Nov 2019 20:31:48 -0600 Subject: [PATCH 046/746] New pagination options, fixes #280. --- src/Plugins/Pagination.js | 110 ++++++++++++------ test/PaginationTest.js | 107 +++++++++++++++++ test/stubs/paged/paged-before-and-reverse.njk | 14 +++ test/stubs/paged/paged-before-filter.njk | 13 +++ test/stubs/paged/paged-before.njk | 13 +++ 5 files changed, 222 insertions(+), 35 deletions(-) create mode 100644 test/stubs/paged/paged-before-and-reverse.njk create mode 100644 test/stubs/paged/paged-before-filter.njk create mode 100644 test/stubs/paged/paged-before.njk diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index ac882a1cc..d94d4e61a 100644 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -74,7 +74,7 @@ class Pagination { return this.data.pagination.data; } - resolveObjectToValues() { + doResolveToObjectValues() { if ("resolve" in this.data.pagination) { return this.data.pagination.resolve === "values"; } @@ -97,36 +97,38 @@ class Pagination { _resolveItems() { let notFoundValue = "__NOT_FOUND_ERROR__"; let key = this._getDataKey(); - let ret = lodashGet(this.data, key, notFoundValue); - if (ret === notFoundValue) { + let fullDataSet = lodashGet(this.data, key, notFoundValue); + if (fullDataSet === notFoundValue) { throw new Error( `Could not resolve pagination key in template data: ${key}` ); } - if (!Array.isArray(ret)) { - if (this.resolveObjectToValues()) { - ret = Object.values(ret); - } else { - ret = Object.keys(ret); - } + let keys; + if (Array.isArray(fullDataSet)) { + keys = fullDataSet; + } else if (this.doResolveToObjectValues()) { + keys = Object.values(fullDataSet); + } else { + keys = Object.keys(fullDataSet); } - let result = ret.filter( - function(value) { - return !this.isFiltered(value); - }.bind(this) - ); + let result = keys.filter(() => true); if ( this.data.pagination.before && typeof this.data.pagination.before === "function" ) { - result = this.data.pagination.before(result.filter(() => true)); + // we don’t need to make a copy of this because we already .filter() above + result = this.data.pagination.before(result); } if (this.data.pagination.reverse === true) { - return result.filter(() => true).reverse(); + result = result.reverse(); + } + + if (this.data.pagination.filter) { + result = result.filter(value => !this.isFiltered(value)); } return result; @@ -190,6 +192,36 @@ class Pagination { pagination: { data: this.data.pagination.data, size: this.data.pagination.size, + alias: this.alias, + + pages: this.size === 1 ? items.map(entry => entry[0]) : items, + + // See Issue #345 for more examples + page: { + previous: + pageNumber > 0 + ? this.size === 1 + ? items[pageNumber - 1][0] + : items[pageNumber - 1] + : null, + next: + pageNumber < items.length - 1 + ? this.size === 1 + ? items[pageNumber + 1][0] + : items[pageNumber + 1] + : null, + first: items.length + ? this.size === 1 + ? items[0][0] + : items[0] + : null, + last: items.length + ? this.size === 1 + ? items[items.length - 1][0] + : items[items.length - 1] + : null + }, + items: items[pageNumber], pageNumber: pageNumber } @@ -214,38 +246,46 @@ class Pagination { // we loop twice to pass in the appropriate prev/next links (already full generated now) templates.forEach( function(cloned, pageNumber) { - // links - overrides[pageNumber].pagination.previousPageLink = + let pageObj = {}; + + // links are okay but hrefs are better + pageObj.previousPageLink = pageNumber > 0 ? links[pageNumber - 1] : null; - overrides[pageNumber].pagination.previous = - overrides[pageNumber].pagination.previousPageLink; + pageObj.previous = pageObj.previousPageLink; - overrides[pageNumber].pagination.nextPageLink = + pageObj.nextPageLink = pageNumber < templates.length - 1 ? links[pageNumber + 1] : null; - overrides[pageNumber].pagination.next = - overrides[pageNumber].pagination.nextPageLink; + pageObj.next = pageObj.nextPageLink; - overrides[pageNumber].pagination.firstPageLink = - links.length > 0 ? links[0] : null; - overrides[pageNumber].pagination.lastPageLink = + pageObj.firstPageLink = links.length > 0 ? links[0] : null; + pageObj.lastPageLink = links.length > 0 ? links[links.length - 1] : null; - overrides[pageNumber].pagination.links = links; + pageObj.links = links; // todo deprecated, consistency with collections and use links instead - overrides[pageNumber].pagination.pageLinks = links; + pageObj.pageLinks = links; - // hrefs - overrides[pageNumber].pagination.previousPageHref = + // hrefs are better than links + pageObj.previousPageHref = pageNumber > 0 ? hrefs[pageNumber - 1] : null; - overrides[pageNumber].pagination.nextPageHref = + pageObj.nextPageHref = pageNumber < templates.length - 1 ? hrefs[pageNumber + 1] : null; - overrides[pageNumber].pagination.firstPageHref = - hrefs.length > 0 ? hrefs[0] : null; - overrides[pageNumber].pagination.lastPageHref = + pageObj.firstPageHref = hrefs.length > 0 ? hrefs[0] : null; + pageObj.lastPageHref = hrefs.length > 0 ? hrefs[hrefs.length - 1] : null; - overrides[pageNumber].pagination.hrefs = hrefs; + pageObj.hrefs = hrefs; + + // better names + pageObj.href = { + previous: pageObj.previousPageHref, + next: pageObj.nextPageHref, + first: pageObj.firstPageHref, + last: pageObj.lastPageHref + }; + + Object.assign(overrides[pageNumber].pagination, pageObj); cloned.setPaginationData(overrides[pageNumber]); diff --git a/test/PaginationTest.js b/test/PaginationTest.js index ecf5fd606..2356e723b 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -672,3 +672,110 @@ test("Circular dependency but should not error because it uses eleventyExcludeFr t.true(true); }); + +test("Pagination `before` Callback", async t => { + let tmpl = new Template( + "./test/stubs/paged/paged-before.njk", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.deepEqual(templates[0].data.pagination.items, ["item6"]); +}); + +test("Pagination `before` Callback with a Filter", async t => { + let tmpl = new Template( + "./test/stubs/paged/paged-before-filter.njk", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.deepEqual(templates[0].data.pagination.items, ["item2"]); +}); + +test("Pagination `before` Callback with `reverse: true` (test order of operations)", async t => { + let tmpl = new Template( + "./test/stubs/paged/paged-before-and-reverse.njk", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.deepEqual(templates[0].data.pagination.items, ["item2"]); +}); + +test("Pagination new v0.10.0 href/hrefs", async t => { + let dataObj = new TemplateData("./test/stubs/"); + await dataObj.cacheData(); + + let tmpl = new Template( + "./test/stubs/paged/paged.njk", + "./test/stubs/", + "./dist", + dataObj + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.is(templates[0].data.pagination.hrefs.length, 2); + t.truthy(templates[0].data.pagination.href.first); + t.truthy(templates[0].data.pagination.href.last); + t.falsy(templates[0].data.pagination.href.previous); + t.truthy(templates[0].data.pagination.href.next); + + t.is(templates[1].data.pagination.hrefs.length, 2); + t.truthy(templates[1].data.pagination.href.first); + t.truthy(templates[1].data.pagination.href.last); + t.truthy(templates[1].data.pagination.href.previous); + t.falsy(templates[1].data.pagination.href.next); +}); + +test("Pagination new v0.10.0 page/pages", async t => { + let dataObj = new TemplateData("./test/stubs/"); + await dataObj.cacheData(); + + let tmpl = new Template( + "./test/stubs/paged/paged.njk", + "./test/stubs/", + "./dist", + dataObj + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + + t.is(templates[0].data.pagination.pages.length, 2); + t.is(templates[0].data.pagination.pages[0].length, 5); + t.is(templates[0].data.pagination.pages[1].length, 3); + t.truthy(templates[0].data.pagination.page.first); + t.truthy(templates[0].data.pagination.page.last); + t.falsy(templates[0].data.pagination.page.previous); + t.truthy(templates[0].data.pagination.page.next); + + t.is(templates[1].data.pagination.pages.length, 2); + t.is(templates[1].data.pagination.pages[0].length, 5); + t.is(templates[1].data.pagination.pages[1].length, 3); + t.truthy(templates[1].data.pagination.page.first); + t.truthy(templates[1].data.pagination.page.last); + t.truthy(templates[1].data.pagination.page.previous); + t.falsy(templates[1].data.pagination.page.next); +}); + +test("Pagination new v0.10.0 alias", async t => { + let tmpl = new Template( + "./test/stubs/paged/pagedalias.njk", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + + t.is(templates[0].data.pagination.alias, "font.test"); + t.is(templates[1].data.pagination.alias, "font.test"); +}); diff --git a/test/stubs/paged/paged-before-and-reverse.njk b/test/stubs/paged/paged-before-and-reverse.njk new file mode 100644 index 000000000..641e9ba6b --- /dev/null +++ b/test/stubs/paged/paged-before-and-reverse.njk @@ -0,0 +1,14 @@ +---js +{ + pagination: { + data: "items", + size: 1, + reverse: true, + before: function(data) { + return data.slice(0, 2); + } + }, + items: ["item1", "item2", "item3", "item4", "item5", "item6"] +} +--- +
    {% for item in pagination.items %}
  1. {{ item }}
  2. {% endfor %}
\ No newline at end of file diff --git a/test/stubs/paged/paged-before-filter.njk b/test/stubs/paged/paged-before-filter.njk new file mode 100644 index 000000000..bc16ac6db --- /dev/null +++ b/test/stubs/paged/paged-before-filter.njk @@ -0,0 +1,13 @@ +---js +{ + pagination: { + data: "items", + size: 1, + before: function(data) { + return data.slice(0, 2).reverse(); + } + }, + items: ["item1", "item2", "item3", "item4", "item5", "item6"] +} +--- +
    {% for item in pagination.items %}
  1. {{ item }}
  2. {% endfor %}
\ No newline at end of file diff --git a/test/stubs/paged/paged-before.njk b/test/stubs/paged/paged-before.njk new file mode 100644 index 000000000..168929fa7 --- /dev/null +++ b/test/stubs/paged/paged-before.njk @@ -0,0 +1,13 @@ +---js +{ + pagination: { + data: "items", + size: 1, + before: function(data) { + return data.reverse(); + } + }, + items: ["item1", "item2", "item3", "item4", "item5", "item6"] +} +--- +
    {% for item in pagination.items %}
  1. {{ item }}
  2. {% endfor %}
\ No newline at end of file From f02a17cb393aae8f52657c3fcee1e0bbcb5f3f63 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 5 Nov 2019 20:56:19 -0600 Subject: [PATCH 047/746] Make sure #699 works with aliasing --- test/PaginationTest.js | 2 ++ test/stubs/paged/paged-before-filter.njk | 3 ++- test/stubs/paged/paged-before.njk | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/PaginationTest.js b/test/PaginationTest.js index 2356e723b..a10fa3f1b 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -683,6 +683,7 @@ test("Pagination `before` Callback", async t => { let data = await tmpl.getData(); let templates = await tmpl.getTemplates(data); t.deepEqual(templates[0].data.pagination.items, ["item6"]); + t.deepEqual(templates[0].data.myalias, "item6"); }); test("Pagination `before` Callback with a Filter", async t => { @@ -695,6 +696,7 @@ test("Pagination `before` Callback with a Filter", async t => { let data = await tmpl.getData(); let templates = await tmpl.getTemplates(data); t.deepEqual(templates[0].data.pagination.items, ["item2"]); + t.deepEqual(templates[0].data.myalias, "item2"); }); test("Pagination `before` Callback with `reverse: true` (test order of operations)", async t => { diff --git a/test/stubs/paged/paged-before-filter.njk b/test/stubs/paged/paged-before-filter.njk index bc16ac6db..191c345f4 100644 --- a/test/stubs/paged/paged-before-filter.njk +++ b/test/stubs/paged/paged-before-filter.njk @@ -5,7 +5,8 @@ size: 1, before: function(data) { return data.slice(0, 2).reverse(); - } + }, + alias: "myalias" }, items: ["item1", "item2", "item3", "item4", "item5", "item6"] } diff --git a/test/stubs/paged/paged-before.njk b/test/stubs/paged/paged-before.njk index 168929fa7..61f2b622f 100644 --- a/test/stubs/paged/paged-before.njk +++ b/test/stubs/paged/paged-before.njk @@ -5,7 +5,8 @@ size: 1, before: function(data) { return data.reverse(); - } + }, + alias: 'myalias' }, items: ["item1", "item2", "item3", "item4", "item5", "item6"] } From 505dea5b455fb82d81cac9d4a35b62941dd0f3d4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 14 Nov 2019 21:00:20 -0600 Subject: [PATCH 048/746] Test for #759 --- test/TemplateRenderHandlebarsTest.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/TemplateRenderHandlebarsTest.js b/test/TemplateRenderHandlebarsTest.js index 261b468e6..1cf69a789 100644 --- a/test/TemplateRenderHandlebarsTest.js +++ b/test/TemplateRenderHandlebarsTest.js @@ -250,3 +250,16 @@ test("Handlebars Render Raw Output (Issue #436 with if statement)", async t => { {{/if}}` ); }); + +test("Handlebars Render #each with Global Variable (Issue #759)", async t => { + let fn = await new TemplateRender("hbs", "./test/stubs/").getCompiledTemplate( + `` + ); + t.is( + (await fn({ + name: "Zach", + navigation: [{ link: "a", text: "text" }] + })).trim(), + `` + ); +}); From ccbaf5af8cafeccbf5b0ecde9e8b75c2219f07c3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 15 Nov 2019 08:48:09 -0600 Subject: [PATCH 049/746] Tests for #760 --- test/PaginationTest.js | 13 +++++++++++++ test/TemplateRenderLiquidTest.js | 8 ++++++++ test/TemplateRenderNunjucksTest.js | 7 +++++++ 3 files changed, 28 insertions(+) diff --git a/test/PaginationTest.js b/test/PaginationTest.js index a10fa3f1b..1b7141970 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -781,3 +781,16 @@ test("Pagination new v0.10.0 alias", async t => { t.is(templates[0].data.pagination.alias, "font.test"); t.is(templates[1].data.pagination.alias, "font.test"); }); + +test("Pagination make sure pageNumber is numeric for {{ pageNumber + 1 }} Issue #760", async t => { + let tmpl = new Template( + "./test/stubs/paged/pagedinlinedata.njk", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.is(templates[0].data.pagination.pageNumber, 0); + t.not(templates[0].data.pagination.pageNumber, "0"); +}); diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 83b0e16d0..3fe431dc0 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -14,6 +14,14 @@ test("Liquid", t => { t.is(new TemplateRender("liquid").getEngineName(), "liquid"); }); +test("Liquid Render Addition", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + "

{{ number | plus: 1 }}

" + ); + // Important for pagination. This currently outputs 1. + t.is(await fn({ number: 1 }), "

2

"); +}); + test("Liquid Render (with Helper)", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{name | capitalize}}

" diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 2d179e2c9..ed3007f62 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -23,6 +23,13 @@ test("Nunjucks Render", async t => { t.is(await fn({ name: "Zach" }), "

Zach

"); }); +test("Nunjucks Render Addition", async t => { + let fn = await new TemplateRender("njk").getCompiledTemplate( + "

{{ number + 1 }}

" + ); + t.is(await fn({ number: 1 }), "

2

"); +}); + test("Nunjucks Render Extends", async t => { let fn = await new TemplateRender("njk", "test/stubs").getCompiledTemplate( "{% extends 'base.njk' %}{% block content %}This is a child.{% endblock %}" From ff33f7d64cfe07a8fd586e50cf8d001af03ce182 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Nov 2019 08:23:22 -0600 Subject: [PATCH 050/746] Check raw in Liquid --- test/TemplateRenderLiquidTest.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 3fe431dc0..1409ec6e9 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -18,10 +18,30 @@ test("Liquid Render Addition", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ number | plus: 1 }}

" ); - // Important for pagination. This currently outputs 1. t.is(await fn({ number: 1 }), "

2

"); }); +test("Liquid Render Raw", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + "

{% raw %}{{name}}{% endraw %}

" + ); + t.is(await fn({ name: "tim" }), "

{{name}}

"); +}); + +test("Liquid Render Raw Multiline", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + `

{% raw %} +{{name}} +{% endraw %}

` + ); + t.is( + await fn({ name: "tim" }), + `

+{{name}} +

` + ); +}); + test("Liquid Render (with Helper)", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{name | capitalize}}

" From 918ff772f062c815b308d3f0efdd63a4c3bcfd07 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Nov 2019 08:23:56 -0600 Subject: [PATCH 051/746] Adds skipped test for #789 (transforms and inputPath) --- test/TemplateTest.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/TemplateTest.js b/test/TemplateTest.js index f8a6ea2bb..6970f878d 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1138,6 +1138,26 @@ test("Test a transform", async t => { t.is(renders[0], "OVERRIDE BY A TRANSFORM"); }); +// #789: https://github.com/11ty/eleventy/issues/789 +test.skip("Test a transform (does it have inputPath?)", async t => { + t.plan(3); + + let tmpl = new Template( + "./test/stubs/template.ejs", + "./test/stubs/", + "./test/stubs/_site" + ); + + tmpl.addTransform(function(content, outputPath, inputPath) { + t.true(outputPath.endsWith(".html")); + t.true(!!inputPath); + return "OVERRIDE BY A TRANSFORM"; + }); + + let renders = await tmpl._testCompleteRender(); + t.is(renders[0], "OVERRIDE BY A TRANSFORM"); +}); + test("Test a transform with pages", async t => { t.plan(5); From 16a7bc45e3989afc6a549bb655c83a9578a7e3bd Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Nov 2019 08:24:09 -0600 Subject: [PATCH 052/746] Updates ava version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d23f48ac9..f6b7fbd7e 100755 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^2.0.3", - "ava": "^2.2.0", + "ava": "^2.4.0", "ink-docstrap": "1.3.2", "jsdoc": "3.6.2", "lint-staged": "^9.2.5", From 094c01ea92ebc417aa53a2813e4454ea50a64228 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Nov 2019 08:24:24 -0600 Subject: [PATCH 053/746] A few more release steps --- docs/meta-release.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/meta-release.md b/docs/meta-release.md index 01a219b77..1caa98964 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -22,16 +22,21 @@ ## If branch docs do not exist +1. Make sure `localDev: false` in `config.js` 1. Check in a new `11ty.io` site with updated `package.json` version. -2. Add version to 11ty.io `versions.json` -3. Create a new branch for branched version -4. Go to https://app.netlify.com/sites/11ty/settings/domain and set up a subdomain for it. +1. Add version to 11ty.io `versions.json` +1. Commit it +1. Run ./deploy.sh to push to production branch for 11ty.io +1. Create a new branch for branched version +1. Go to https://app.netlify.com/sites/11ty/settings/domain and set up a subdomain for it. ### Always: 1. Check out the previous version git branch and add `outdated: true` to `_data/config.json` and commit/push. 2. Update `eleventy-base-blog`? +--- + ## If Branch docs already exist, 11ty.io (unlikely, I don’t do this any more) 1. Check to make sure `"prerelease": false` in `_data/config.json` From a3b4433af8c8eccf1027e6c66c7c316280727c9c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 27 Nov 2019 08:19:58 -0600 Subject: [PATCH 054/746] When you watch a dir it needs to be a glob, for #641 --- src/Eleventy.js | 5 ++--- src/EleventyWatchTargets.js | 7 +++++++ test/EleventyWatchTargetsTest.js | 8 ++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index c491e7b80..4ad1f9b2a 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -73,7 +73,7 @@ class Eleventy { /** @member {Object} - tbd. */ this.watchTargets = new EleventyWatchTargets(); - this.watchTargets.add(this.config.additionalWatchTargets); + this.watchTargets.addAndMakeGlob(this.config.additionalWatchTargets); this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; } @@ -559,8 +559,7 @@ Arguments: debug("Watching for changes to: %o", rawFiles); let ignores = this.eleventyFiles.getGlobWatcherIgnores(); - debug("Watching but ignoring changes to: %o", ignores); - + debug("Ignoring watcher changes to: %o", ignores); let watcher = chokidar.watch(rawFiles, { ignored: ignores, ignoreInitial: true diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index 8f94e44b9..ca73e8850 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -61,6 +61,13 @@ class EleventyWatchTargets { this.addRaw(targets); } + addAndMakeGlob(targets) { + targets = this._normalizeTargets(targets).map(entry => + TemplatePath.convertToRecursiveGlob(entry) + ); + this.addRaw(targets); + } + // add only a target’s dependencies addDependencies(targets, filterCallback) { if (!this.watchJavaScriptDependencies) { diff --git a/test/EleventyWatchTargetsTest.js b/test/EleventyWatchTargetsTest.js index ea5ee01cd..b042a182b 100644 --- a/test/EleventyWatchTargetsTest.js +++ b/test/EleventyWatchTargetsTest.js @@ -25,6 +25,14 @@ test("Add array", t => { t.deepEqual(targets.getTargets(), ["./.eleventy.js", "./b.js", "./c.js"]); }); +test("Add and make glob", t => { + let targets = new EleventyWatchTargets(); + + // Note the `test` directory must exist here for this to pass. + targets.addAndMakeGlob(["test", "test/b.js"]); + t.deepEqual(targets.getTargets(), ["./test/**", "./test/b.js"]); +}); + test("JavaScript get dependencies", t => { let targets = new EleventyWatchTargets(); t.deepEqual( From dbb6c93645d1926dcc70933180fe0da3953b2c05 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 27 Nov 2019 22:52:24 -0600 Subject: [PATCH 055/746] Adds warning for lack of support for ! in .gitignore and .eleventyignore. Future support TBD at #693. --- src/EleventyFiles.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index f65954390..e88d1db8c 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -182,6 +182,16 @@ class EleventyFiles { return line.trim(); }) .filter(line => { + if (line.charAt(0) === "!") { + debug( + ">>> When processing .gitignore/.eleventyignore, Eleventy does not currently support negative patterns but encountered one:" + ); + debug(">>>", line); + debug( + "Follow along at https://github.com/11ty/eleventy/issues/693 to track support." + ); + } + // empty lines or comments get filtered out return ( line.length > 0 && line.charAt(0) !== "#" && line.charAt(0) !== "!" From e40fb33031831bf6438029195c19354ce6e6639e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 27 Nov 2019 22:52:56 -0600 Subject: [PATCH 056/746] Oops, the .gitignore and .eleventyignore files were being processed twice! --- src/EleventyFiles.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index e88d1db8c..0b0848db0 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -221,29 +221,28 @@ class EleventyFiles { getIgnores() { let files = []; + let rootDirectory = this.localPathRoot || TemplatePath.getWorkingDir(); + let absoluteInputDir = TemplatePath.absolutePath(this.inputDir); if (this.config.useGitIgnore) { + let gitIgnores = [TemplatePath.join(rootDirectory, ".gitignore")]; + if (rootDirectory !== absoluteInputDir) { + gitIgnores.push(TemplatePath.join(this.inputDir, ".gitignore")); + } + files = files.concat( - EleventyFiles.getFileIgnores( - [ - TemplatePath.join( - this.localPathRoot || TemplatePath.getWorkingDir(), - ".gitignore" - ), - TemplatePath.join(this.inputDir, ".gitignore") - ], - "node_modules/**" - ) + EleventyFiles.getFileIgnores(gitIgnores, "node_modules/**") ); } if (this.config.eleventyignoreOverride !== false) { let eleventyIgnores = [ - TemplatePath.join( - this.localPathRoot || TemplatePath.getWorkingDir(), - ".eleventyignore" - ), - TemplatePath.join(this.inputDir, ".eleventyignore") + TemplatePath.join(rootDirectory, ".eleventyignore") ]; + if (rootDirectory !== absoluteInputDir) { + eleventyIgnores.push( + TemplatePath.join(this.inputDir, ".eleventyignore") + ); + } files = files.concat( this.config.eleventyignoreOverride || From adac1bb9d97b91f833881f3869fb355d0902309a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 28 Nov 2019 13:13:06 -0600 Subject: [PATCH 057/746] Test for #709 --- test/EleventyFilesTest.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index be6850ea3..6d7debbc7 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -595,3 +595,14 @@ test("File extension aliasing", async t => { ].sort() ); }); + +test("Test that negations are ignored (for now) PR#709, will change when #693 is implemented", async t => { + t.deepEqual( + EleventyFiles.normalizeIgnoreContent( + "./", + `hello +!testing` + ), + ["!./hello"] + ); +}); From 7fe644d9a78605853c31d24299f6a880168f2d8f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 29 Nov 2019 13:54:30 -0600 Subject: [PATCH 058/746] Fix sortable issue surfaced by @edbrannin in #747 --- src/Util/Sortable.js | 24 ++++++++---------------- test/SortableTest.js | 23 +++++++++-------------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/Util/Sortable.js b/src/Util/Sortable.js index 6d2805571..8730b244f 100644 --- a/src/Util/Sortable.js +++ b/src/Util/Sortable.js @@ -2,8 +2,8 @@ const capitalize = require("./Capitalize"); class Sortable { constructor() { - this.sortAscending = true; - this.sortNumeric = false; + this.isSortAscending = true; + this.isSortNumeric = false; this.items = []; this.sortFunctionStringMap = { @@ -44,24 +44,16 @@ class Sortable { return this.sort(this.getSortFunctionDescending()); } - isSortAscending() { - return this.sortAscending; - } - - isSortNumeric() { - return this.sortNumeric; - } - setSortDescending() { - this.sortAscending = false; + this.isSortAscending = false; } setSortAscending(isAscending) { - this.sortAscending = isAscending; + this.isSortAscending = isAscending; } setSortNumeric(isNumeric) { - this.sortNumeric = isNumeric; + this.isSortNumeric = isNumeric; } /* Sort functions */ @@ -117,7 +109,7 @@ class Sortable { /* End sort functions */ getSortFunction() { - if (this.sortAscending) { + if (this.isSortAscending) { return this.getSortFunctionAscending(); } else { return this.getSortFunctionDescending(); @@ -125,7 +117,7 @@ class Sortable { } getSortFunctionAscending() { - if (this.sortNumeric) { + if (this.isSortNumeric) { return Sortable.sortFunctionNumericAscending; } else { return Sortable.sortFunctionAlphabeticAscending; @@ -133,7 +125,7 @@ class Sortable { } getSortFunctionDescending() { - if (this.sortNumeric) { + if (this.isSortNumeric) { return Sortable.sortFunctionNumericDescending; } else { return Sortable.sortFunctionAlphabeticDescending; diff --git a/test/SortableTest.js b/test/SortableTest.js index 82a51af16..ef5df7aa7 100644 --- a/test/SortableTest.js +++ b/test/SortableTest.js @@ -9,8 +9,8 @@ test("get Sort Function", t => { test("Alphabetic Ascending", t => { let s = new Sortable(); - t.false(s.isSortNumeric()); - t.true(s.isSortAscending()); + t.false(s.isSortNumeric); + t.true(s.isSortAscending); s.add("a"); s.add("z"); @@ -18,12 +18,7 @@ test("Alphabetic Ascending", t => { t.deepEqual(s.sort(), ["a", "m", "z"]); }); -test.skip("Alphabetic Ascending (shortcut)", t => { - /* FIXME THIS WILL NOT WORK because s.sortAscending() has been replaced by the boolean sortAscending. - * - * If backwards compatibility were not an issue, I'd recommend renaming the boolean properties - * to isSort(Ascending|Numeric) and renaming the getters & Setters to (get|set)IsSort(Ascending|Numeric) - */ +test("Alphabetic Ascending (shortcut)", t => { let s = new Sortable(); s.add("a"); s.add("z"); @@ -34,8 +29,8 @@ test.skip("Alphabetic Ascending (shortcut)", t => { test("Alphabetic Descending", t => { let s = new Sortable(); s.setSortDescending(); - t.false(s.isSortNumeric()); - t.false(s.isSortAscending()); + t.false(s.isSortNumeric); + t.false(s.isSortAscending); s.add("a"); s.add("z"); @@ -54,8 +49,8 @@ test("Alphabetic Descending (shortcut)", t => { test("Numeric Ascending", t => { let s = new Sortable(); s.setSortNumeric(true); - t.true(s.isSortNumeric()); - t.true(s.isSortAscending()); + t.true(s.isSortNumeric); + t.true(s.isSortAscending); s.add(1); s.add(4); @@ -67,8 +62,8 @@ test("Numeric Descending", t => { let s = new Sortable(); s.setSortNumeric(true); s.setSortDescending(); - t.true(s.isSortNumeric()); - t.false(s.isSortAscending()); + t.true(s.isSortNumeric); + t.false(s.isSortAscending); s.add(1); s.add(4); From e62ebfa7726de9c48736430af1c8e9324daf4702 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 30 Nov 2019 19:36:18 -0600 Subject: [PATCH 059/746] Show pathPrefix on the command line when in use. --- src/Eleventy.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 4ad1f9b2a..25e6f4dec 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -233,15 +233,21 @@ class Eleventy { }` ); + let versionStr = `v${pkg.version}`; let time = ((new Date() - this.start) / 1000).toFixed(2); ret.push(`in ${time} ${simplePlural(time, "second", "seconds")}`); if (writeCount >= 10) { ret.push( - `(${((time * 1000) / writeCount).toFixed(1)}ms each, v${pkg.version})` + `(${((time * 1000) / writeCount).toFixed(1)}ms each, ${versionStr})` ); } else { - ret.push(`(v${pkg.version})`); + ret.push(`(${versionStr})`); + } + + let pathPrefix = this.config.pathPrefix; + if (pathPrefix && pathPrefix !== "/") { + return `Using pathPrefix: ${pathPrefix}\n${ret.join(" ")}`; } return ret.join(" "); From 45a8135c0583fd379532c1cdaa5c7e8484183d98 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 30 Nov 2019 20:04:36 -0600 Subject: [PATCH 060/746] Fixes #808 --- cmd.js | 6 +++--- src/Eleventy.js | 5 +++-- src/UserConfig.js | 9 ++++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cmd.js b/cmd.js index ff8f27c2a..076cbff94 100755 --- a/cmd.js +++ b/cmd.js @@ -46,9 +46,9 @@ try { elev.setIncrementalBuild(argv.incremental); elev.setPassthroughAll(argv.passthroughall); elev.setFormats(argv.formats); - - let isVerbose = process.env.DEBUG ? false : !argv.quiet; - elev.setIsVerbose(isVerbose); + if (argv.quiet) { + elev.setIsVerbose(false); + } // careful, we can’t use async/await here to error properly // with old node versions in `please-upgrade-node` above. diff --git a/src/Eleventy.js b/src/Eleventy.js index 25e6f4dec..32f6d401b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -39,7 +39,7 @@ class Eleventy { * @member {Boolean} - Is Eleventy running in verbose mode? * @default true */ - this.isVerbose = true; + this.isVerbose = process.env.DEBUG ? false : !this.config.quietMode; /** * @member {Boolean} - Is Eleventy running in debug mode? @@ -290,7 +290,8 @@ Data: ${this.templateData.getDataDir()} Includes: ${this.eleventyFiles.getIncludesDir()} Layouts: ${this.eleventyFiles.getLayoutsDir()} Output: ${this.outputDir} -Template Formats: ${formats.join(",")}`); +Template Formats: ${formats.join(",")} +Verbose Output: ${this.isVerbose}`); this.writer.setVerboseOutput(this.isVerbose); this.writer.setDryRun(this.isDryRun); diff --git a/src/UserConfig.js b/src/UserConfig.js index e6a7ef8f6..b4930617d 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -60,6 +60,8 @@ class UserConfig { // using Map to preserve insertion order this.dataExtensions = new Map(); + + this.quietMode = false; } versionCheck(expected) { @@ -577,6 +579,10 @@ class UserConfig { this.frontMatterParsingOptions = options; } + setQuietMode(quietMode) { + this.quietMode = !!quietMode; + } + getMergingConfigObject() { return { templateFormats: this.templateFormats, @@ -613,7 +619,8 @@ class UserConfig { additionalWatchTargets: this.additionalWatchTargets, browserSyncConfig: this.browserSyncConfig, frontMatterParsingOptions: this.frontMatterParsingOptions, - dataExtensions: this.dataExtensions + dataExtensions: this.dataExtensions, + quietMode: this.quietMode }; } From 4247c4ca1f29aaf0e9f97205989c9f23dd8c4b98 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 8 Dec 2019 20:01:46 -0600 Subject: [PATCH 061/746] Update dependencies in preparation for 0.10.0-beta.1 --- cmd.js | 2 +- package.json | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cmd.js b/cmd.js index 076cbff94..bab8ee70f 100755 --- a/cmd.js +++ b/cmd.js @@ -1,6 +1,6 @@ #!/usr/bin/env node const pkg = require("./package.json"); -const chalk = require("chalk"); // node 4+ +const chalk = require("chalk"); // node 8+ require("please-upgrade-node")(pkg, { message: function(requiredVersion) { return chalk.red( diff --git a/package.json b/package.json index 457dd2ddc..c7e272f52 100755 --- a/package.json +++ b/package.json @@ -70,16 +70,16 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^2.0.3", "ava": "^2.4.0", "ink-docstrap": "1.3.2", - "jsdoc": "3.6.2", - "lint-staged": "^9.2.5", + "jsdoc": "3.6.3", + "lint-staged": "^9.5.0", "markdown-it-emoji": "^1.4.0", "nyc": "^14.1.1", "pre-commit": "^1.2.2", "pre-push": "^0.1.1", - "prettier": "^1.18.2", + "prettier": "^1.19.1", "rimraf": "^3.0.0", "toml": "^3.0.0", - "viperhtml": "^2.17.0", + "viperhtml": "^2.17.1", "vue": "^2.6.10", "vue-server-renderer": "^2.6.10", "js-yaml": "^3.13.1" @@ -87,23 +87,23 @@ "dependencies": { "@11ty/dependency-tree": "^1.0.0", "browser-sync": "^2.26.7", - "chalk": "^2.4.2", - "chokidar": "^3.0.2", + "chalk": "^3.0.0", + "chokidar": "^3.3.0", "debug": "^4.1.1", - "dependency-graph": "^0.8.0", + "dependency-graph": "^0.8.1", "ejs": "^2.6.2", - "fast-glob": "^3.0.4", + "fast-glob": "^3.1.1", "fs-extra": "^8.1.0", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", - "handlebars": "^4.1.2", - "javascript-stringify": "^2.0.0", + "handlebars": "^4.5.3", + "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", "lodash": "^4.17.15", - "luxon": "^1.17.2", + "luxon": "^1.21.3", "markdown-it": "^8.4.2", "minimist": "^1.2.0", - "moo": "^0.5.0", + "moo": "^0.5.1", "multimatch": "^4.0.0", "mustache": "^2.3.0", "normalize-path": "^3.0.0", @@ -114,7 +114,7 @@ "pug": "^2.0.4", "recursive-copy": "^2.0.10", "semver": "^6.3.0", - "slugify": "^1.3.4", + "slugify": "^1.3.6", "time-require": "^0.1.2", "valid-url": "^1.0.9" }, From 7ae29931d2de55b71190f9c8746ac7efcfa5a748 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 8 Dec 2019 20:04:36 -0600 Subject: [PATCH 062/746] v0.10.0-beta.1 --- docs-src/_data/coverage.json | 37 ++++++++++++++++++------------------ docs/coverage.md | 33 ++++++++++++++++---------------- package.json | 2 +- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index ce0974ce4..2122006ba 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,57 +1,58 @@ -{"total": {"lines":{"total":2763,"covered":2450,"skipped":0,"pct":88.67},"statements":{"total":2778,"covered":2465,"skipped":0,"pct":88.73},"functions":{"total":656,"covered":574,"skipped":0,"pct":87.5},"branches":{"total":1110,"covered":902,"skipped":0,"pct":81.26}} +{"total": {"lines":{"total":2919,"covered":2564,"skipped":0,"pct":87.84},"statements":{"total":2936,"covered":2581,"skipped":0,"pct":87.91},"functions":{"total":690,"covered":601,"skipped":0,"pct":87.1},"branches":{"total":1235,"covered":992,"skipped":0,"pct":80.32}} ,"/Users/zachleat/Code/eleventy/config.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":12,"covered":11,"skipped":0,"pct":91.67},"functions":{"total":6,"covered":5,"skipped":0,"pct":83.33},"statements":{"total":12,"covered":11,"skipped":0,"pct":91.67},"branches":{"total":6,"covered":4,"skipped":0,"pct":66.67}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":34,"covered":23,"skipped":0,"pct":67.65},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":34,"covered":23,"skipped":0,"pct":67.65},"branches":{"total":10,"covered":3,"skipped":0,"pct":30}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":17,"covered":13,"skipped":0,"pct":76.47},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":17,"covered":13,"skipped":0,"pct":76.47},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":177,"covered":97,"skipped":0,"pct":54.8},"functions":{"total":33,"covered":19,"skipped":0,"pct":57.58},"statements":{"total":177,"covered":97,"skipped":0,"pct":54.8},"branches":{"total":52,"covered":24,"skipped":0,"pct":46.15}} -,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":189,"covered":103,"skipped":0,"pct":54.5},"functions":{"total":34,"covered":19,"skipped":0,"pct":55.88},"statements":{"total":189,"covered":103,"skipped":0,"pct":54.5},"branches":{"total":69,"covered":27,"skipped":0,"pct":39.13}} +,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":36,"covered":33,"skipped":0,"pct":91.67},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":36,"covered":33,"skipped":0,"pct":91.67},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.57}} -,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":5,"covered":5,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":35,"skipped":0,"pct":89.74},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":39,"covered":35,"skipped":0,"pct":89.74},"branches":{"total":43,"covered":29,"skipped":0,"pct":67.44}} +,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":19,"covered":19,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":60,"covered":58,"skipped":0,"pct":96.67},"functions":{"total":25,"covered":23,"skipped":0,"pct":92},"statements":{"total":60,"covered":58,"skipped":0,"pct":96.67},"branches":{"total":27,"covered":27,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":126,"covered":119,"skipped":0,"pct":94.44},"functions":{"total":37,"covered":33,"skipped":0,"pct":89.19},"statements":{"total":126,"covered":119,"skipped":0,"pct":94.44},"branches":{"total":46,"covered":42,"skipped":0,"pct":91.3}} +,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":137,"covered":130,"skipped":0,"pct":94.89},"functions":{"total":37,"covered":33,"skipped":0,"pct":89.19},"statements":{"total":137,"covered":130,"skipped":0,"pct":94.89},"branches":{"total":51,"covered":47,"skipped":0,"pct":92.16}} ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":61,"covered":22,"skipped":0,"pct":36.07},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":61,"covered":22,"skipped":0,"pct":36.07},"branches":{"total":41,"covered":10,"skipped":0,"pct":24.39}} -,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":46,"covered":43,"skipped":0,"pct":93.48},"functions":{"total":20,"covered":18,"skipped":0,"pct":90},"statements":{"total":46,"covered":43,"skipped":0,"pct":93.48},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":282,"covered":267,"skipped":0,"pct":94.68},"functions":{"total":47,"covered":46,"skipped":0,"pct":97.87},"statements":{"total":284,"covered":269,"skipped":0,"pct":94.72},"branches":{"total":101,"covered":87,"skipped":0,"pct":86.14}} +,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":13,"covered":12,"skipped":0,"pct":92.31}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":288,"covered":271,"skipped":0,"pct":94.1},"functions":{"total":48,"covered":47,"skipped":0,"pct":97.92},"statements":{"total":290,"covered":273,"skipped":0,"pct":94.14},"branches":{"total":103,"covered":88,"skipped":0,"pct":85.44}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":29,"covered":27,"skipped":0,"pct":93.1},"functions":{"total":13,"covered":12,"skipped":0,"pct":92.31},"statements":{"total":31,"covered":29,"skipped":0,"pct":93.55},"branches":{"total":10,"covered":8,"skipped":0,"pct":80}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":57,"covered":52,"skipped":0,"pct":91.23},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":57,"covered":52,"skipped":0,"pct":91.23},"branches":{"total":24,"covered":22,"skipped":0,"pct":91.67}} ,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":81,"covered":76,"skipped":0,"pct":93.83},"functions":{"total":17,"covered":16,"skipped":0,"pct":94.12},"statements":{"total":81,"covered":76,"skipped":0,"pct":93.83},"branches":{"total":34,"covered":31,"skipped":0,"pct":91.18}} -,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":161,"covered":152,"skipped":0,"pct":94.41},"functions":{"total":27,"covered":27,"skipped":0,"pct":100},"statements":{"total":163,"covered":154,"skipped":0,"pct":94.48},"branches":{"total":50,"covered":41,"skipped":0,"pct":82}} +,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":193,"covered":178,"skipped":0,"pct":92.23},"functions":{"total":34,"covered":33,"skipped":0,"pct":97.06},"statements":{"total":195,"covered":180,"skipped":0,"pct":92.31},"branches":{"total":66,"covered":55,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateGlob.js": {"lines":{"total":15,"covered":14,"skipped":0,"pct":93.33},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":68,"covered":68,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":69,"covered":69,"skipped":0,"pct":100},"branches":{"total":14,"covered":14,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":47,"covered":45,"skipped":0,"pct":95.74},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":47,"covered":45,"skipped":0,"pct":95.74},"branches":{"total":18,"covered":16,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":238,"covered":233,"skipped":0,"pct":97.9},"functions":{"total":32,"covered":31,"skipped":0,"pct":96.88},"statements":{"total":238,"covered":233,"skipped":0,"pct":97.9},"branches":{"total":125,"covered":113,"skipped":0,"pct":90.4}} ,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":38,"covered":36,"skipped":0,"pct":94.74},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":38,"covered":36,"skipped":0,"pct":94.74},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":58,"covered":53,"skipped":0,"pct":91.38},"functions":{"total":17,"covered":17,"skipped":0,"pct":100},"statements":{"total":58,"covered":53,"skipped":0,"pct":91.38},"branches":{"total":14,"covered":10,"skipped":0,"pct":71.43}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":67,"covered":59,"skipped":0,"pct":88.06},"functions":{"total":19,"covered":19,"skipped":0,"pct":100},"statements":{"total":67,"covered":59,"skipped":0,"pct":88.06},"branches":{"total":20,"covered":13,"skipped":0,"pct":65}} ,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":74,"covered":74,"skipped":0,"pct":100},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":75,"covered":75,"skipped":0,"pct":100},"branches":{"total":38,"covered":38,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalinkNoWrite.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":77,"covered":76,"skipped":0,"pct":98.7},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":42,"covered":40,"skipped":0,"pct":95.24}} -,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":96,"covered":78,"skipped":0,"pct":81.25},"functions":{"total":21,"covered":15,"skipped":0,"pct":71.43},"statements":{"total":96,"covered":78,"skipped":0,"pct":81.25},"branches":{"total":10,"covered":3,"skipped":0,"pct":30}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":166,"covered":107,"skipped":0,"pct":64.46},"functions":{"total":45,"covered":23,"skipped":0,"pct":51.11},"statements":{"total":167,"covered":108,"skipped":0,"pct":64.67},"branches":{"total":66,"covered":36,"skipped":0,"pct":54.55}} +,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":93,"covered":71,"skipped":0,"pct":76.34},"functions":{"total":25,"covered":17,"skipped":0,"pct":68},"statements":{"total":93,"covered":71,"skipped":0,"pct":76.34},"branches":{"total":16,"covered":6,"skipped":0,"pct":37.5}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":195,"covered":114,"skipped":0,"pct":58.46},"functions":{"total":52,"covered":24,"skipped":0,"pct":46.15},"statements":{"total":196,"covered":115,"skipped":0,"pct":58.67},"branches":{"total":77,"covered":39,"skipped":0,"pct":50.65}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":50,"covered":48,"skipped":0,"pct":96},"functions":{"total":12,"covered":12,"skipped":0,"pct":100},"statements":{"total":51,"covered":49,"skipped":0,"pct":96.08},"branches":{"total":42,"covered":37,"skipped":0,"pct":88.1}} +,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.04},"functions":{"total":12,"covered":12,"skipped":0,"pct":100},"statements":{"total":52,"covered":51,"skipped":0,"pct":98.08},"branches":{"total":42,"covered":37,"skipped":0,"pct":88.1}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScriptTemplateLiteral.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":73,"covered":70,"skipped":0,"pct":95.89},"functions":{"total":26,"covered":25,"skipped":0,"pct":96.15},"statements":{"total":73,"covered":70,"skipped":0,"pct":95.89},"branches":{"total":15,"covered":13,"skipped":0,"pct":86.67}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":33,"covered":30,"skipped":0,"pct":90.91},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":33,"covered":30,"skipped":0,"pct":90.91},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":61,"covered":54,"skipped":0,"pct":88.52},"functions":{"total":19,"covered":18,"skipped":0,"pct":94.74},"statements":{"total":61,"covered":54,"skipped":0,"pct":88.52},"branches":{"total":13,"covered":11,"skipped":0,"pct":84.62}} +,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":83,"covered":74,"skipped":0,"pct":89.16},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":83,"covered":74,"skipped":0,"pct":89.16},"branches":{"total":29,"covered":27,"skipped":0,"pct":93.1}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":17,"covered":17,"skipped":0,"pct":100},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":51,"covered":51,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":53,"covered":53,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":53,"covered":53,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":55,"covered":55,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Slug.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":18,"covered":18,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":18,"covered":18,"skipped":0,"pct":100},"branches":{"total":21,"covered":21,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":107,"covered":99,"skipped":0,"pct":92.52},"functions":{"total":16,"covered":15,"skipped":0,"pct":93.75},"statements":{"total":109,"covered":101,"skipped":0,"pct":92.66},"branches":{"total":66,"covered":54,"skipped":0,"pct":81.82}} +,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":115,"covered":106,"skipped":0,"pct":92.17},"functions":{"total":18,"covered":17,"skipped":0,"pct":94.44},"statements":{"total":119,"covered":110,"skipped":0,"pct":92.44},"branches":{"total":90,"covered":75,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Util/Capitalize.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.86},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.86},"branches":{"total":22,"covered":19,"skipped":0,"pct":86.36}} +,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.86},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.86},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/Util/Pluralize.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":46,"covered":39,"skipped":0,"pct":84.78},"functions":{"total":23,"covered":17,"skipped":0,"pct":73.91},"statements":{"total":47,"covered":40,"skipped":0,"pct":85.11},"branches":{"total":18,"covered":17,"skipped":0,"pct":94.44}} +,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":44,"covered":42,"skipped":0,"pct":95.45},"functions":{"total":21,"covered":19,"skipped":0,"pct":90.48},"statements":{"total":45,"covered":43,"skipped":0,"pct":95.56},"branches":{"total":18,"covered":18,"skipped":0,"pct":100}} } diff --git a/docs/coverage.md b/docs/coverage.md index 001ee8756..9777caf75 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,60 +1,61 @@ -# Code Coverage for Eleventy v0.9.0 +# Code Coverage for Eleventy v0.10.0-beta.1 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 88.67% | 88.73% | 87.5% | 81.26% | +| `total` | 87.84% | 87.91% | 87.1% | 80.32% | | `config.js` | 100% | 100% | 100% | 100% | | `src/Benchmark.js` | 91.67% | 91.67% | 83.33% | 66.67% | | `src/BenchmarkGroup.js` | 67.65% | 67.65% | 71.43% | 30% | | `src/BenchmarkManager.js` | 76.47% | 76.47% | 71.43% | 75% | | `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 54.8% | 54.8% | 57.58% | 46.15% | +| `src/Eleventy.js` | 54.5% | 54.5% | 55.88% | 39.13% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | | `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | -| `src/EleventyErrorHandler.js` | 91.67% | 91.67% | 100% | 67.57% | +| `src/EleventyErrorHandler.js` | 89.74% | 89.74% | 100% | 67.44% | | `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | | `src/EleventyExtensionMap.js` | 96.67% | 96.67% | 92% | 100% | -| `src/EleventyFiles.js` | 94.44% | 94.44% | 89.19% | 91.3% | +| `src/EleventyFiles.js` | 94.89% | 94.89% | 89.19% | 92.16% | | `src/EleventyServe.js` | 36.07% | 36.07% | 56.25% | 24.39% | -| `src/EleventyWatchTargets.js` | 93.48% | 93.48% | 90% | 93.33% | -| `src/Template.js` | 94.68% | 94.72% | 97.87% | 86.14% | +| `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 92.31% | +| `src/Template.js` | 94.1% | 94.14% | 97.92% | 85.44% | | `src/TemplateCache.js` | 100% | 100% | 100% | 100% | | `src/TemplateCollection.js` | 93.1% | 93.55% | 92.31% | 80% | | `src/TemplateConfig.js` | 91.23% | 91.23% | 66.67% | 91.67% | | `src/TemplateContent.js` | 93.83% | 93.83% | 94.12% | 91.18% | -| `src/TemplateData.js` | 94.41% | 94.48% | 100% | 82% | +| `src/TemplateData.js` | 92.23% | 92.31% | 97.06% | 83.33% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | | `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | | `src/TemplateLayout.js` | 100% | 100% | 100% | 100% | | `src/TemplateLayoutPathResolver.js` | 95.74% | 95.74% | 100% | 88.89% | | `src/TemplateMap.js` | 97.9% | 97.9% | 96.88% | 90.4% | | `src/TemplatePassthrough.js` | 94.74% | 94.74% | 88.89% | 85.71% | -| `src/TemplatePassthroughManager.js` | 91.38% | 91.38% | 100% | 71.43% | +| `src/TemplatePassthroughManager.js` | 88.06% | 88.06% | 100% | 65% | | `src/TemplatePath.js` | 100% | 100% | 95.65% | 100% | | `src/TemplatePermalink.js` | 100% | 100% | 100% | 100% | | `src/TemplatePermalinkNoWrite.js` | 100% | 100% | 100% | 100% | | `src/TemplateRender.js` | 98.7% | 98.7% | 100% | 95.24% | -| `src/TemplateWriter.js` | 81.25% | 81.25% | 71.43% | 30% | -| `src/UserConfig.js` | 64.46% | 64.67% | 51.11% | 54.55% | +| `src/TemplateWriter.js` | 76.34% | 76.34% | 68% | 37.5% | +| `src/UserConfig.js` | 58.46% | 58.67% | 46.15% | 50.65% | | `src/Engines/Ejs.js` | 95% | 95% | 85.71% | 88.89% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | -| `src/Engines/JavaScript.js` | 96% | 96.08% | 100% | 88.1% | +| `src/Engines/JavaScript.js` | 98.04% | 98.08% | 100% | 88.1% | | `src/Engines/JavaScriptTemplateLiteral.js` | 94.44% | 94.44% | 100% | 100% | | `src/Engines/Liquid.js` | 95.89% | 95.89% | 96.15% | 86.67% | | `src/Engines/Markdown.js` | 90.91% | 90.91% | 88.89% | 81.25% | | `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | -| `src/Engines/Nunjucks.js` | 88.52% | 88.52% | 94.74% | 84.62% | +| `src/Engines/Nunjucks.js` | 89.16% | 89.16% | 95.65% | 93.1% | | `src/Engines/Pug.js` | 100% | 100% | 100% | 88.89% | | `src/Engines/TemplateEngine.js` | 100% | 100% | 100% | 100% | | `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | | `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | | `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | | `src/Filters/Url.js` | 100% | 100% | 100% | 100% | -| `src/Plugins/Pagination.js` | 92.52% | 92.66% | 93.75% | 81.82% | +| `src/Plugins/Pagination.js` | 92.17% | 92.44% | 94.44% | 83.33% | | `src/Util/Capitalize.js` | 100% | 100% | 100% | 100% | -| `src/Util/Merge.js` | 92.86% | 92.86% | 100% | 86.36% | +| `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | +| `src/Util/Merge.js` | 92.86% | 92.86% | 100% | 87.5% | | `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | -| `src/Util/Sortable.js` | 84.78% | 85.11% | 73.91% | 94.44% | +| `src/Util/Sortable.js` | 95.45% | 95.56% | 90.48% | 100% | diff --git a/package.json b/package.json index c7e272f52..4d7d8cf46 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.9.0", + "version": "0.10.0-beta.1", "description": "Transform a directory of templates into HTML.", "main": "src/Eleventy.js", "license": "MIT", From 19b97ff93765e3c48d0b572c1acd6fc8e59d5197 Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Fri, 13 Dec 2019 01:07:45 +0200 Subject: [PATCH 063/746] Add global data extension priority and merge data objects with the same base filename according to data file extension priority --- src/TemplateData.js | 53 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 83862e14f..670e7f427 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -2,6 +2,7 @@ const fs = require("fs-extra"); const fastglob = require("fast-glob"); const parsePath = require("parse-filepath"); const lodashset = require("lodash/set"); +const lodashget = require("lodash/get"); const lodashUniq = require("lodash/uniq"); const merge = require("./Util/Merge"); const TemplateRender = require("./TemplateRender"); @@ -135,26 +136,52 @@ class TemplateData { async getGlobalDataGlob() { let dir = await this.getInputDir(); - let userExtensions = ""; - // creating glob string for user extensions - if (this.hasUserDataExtensions()) { - userExtensions = this.getUserDataExtensions().join("|") + "|"; - } - return [ - this._getGlobalDataGlobByExtension(dir, "(" + userExtensions + "json|js)") - ]; + let extGlob = this.getGlobalDataExtensionPriorities().join("|"); + return [this._getGlobalDataGlobByExtension(dir, "(" + extGlob + ")")]; } getWatchPathCache() { return this.pathCache; } + getGlobalDataExtensionPriorities() { + return this.getUserDataExtensions().concat(["json", "js"]); + } + + static calculateExtensionPriority(path, priorities) { + for (let i = 0; i < priorities.length; i++) { + let ext = priorities[i]; + if (path.endsWith(ext)) { + return i; + } + } + return priorities.length; + } + async getGlobalDataFiles() { + let priorities = this.getGlobalDataExtensionPriorities(); + let paths = await fastglob(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, dot: true }); + + // sort paths according to extension priorities + // here we use reverse ordering, because paths with bigger index in array will override the first ones + // example [path/file.json, path/file.js] here js will override json + paths = paths.sort((first, second) => { + let p1 = TemplateData.calculateExtensionPriority(first, priorities); + let p2 = TemplateData.calculateExtensionPriority(second, priorities); + if (p1 < p2) { + return -1; + } + if (p1 > p2) { + return 1; + } + return 0; + }); + this.pathCache = paths; return paths; } @@ -179,17 +206,19 @@ class TemplateData { for (let j = 0, k = files.length; j < k; j++) { let folders = await this.getObjectPathForDataFile(files[j]); + let data = await this.getDataValue(files[j], rawImports); - // TODO maybe merge these two? (if both valid objects) if (dataFileConflicts[folders]) { debugWarn( - `Warning: the key for a global data file (${files[j]}) will overwrite data from an already existing global data file (${dataFileConflicts[folders]})` + `merging global data from ${files[j]} with an already existing global data file (${dataFileConflicts[folders]}). Overriding existing keys` ); + + let oldData = lodashget(globalData, folders); + data = TemplateData.mergeDeep(this.config, oldData, data); } - dataFileConflicts[folders] = files[j]; + dataFileConflicts[folders] = files[j]; debug(`Found global data file ${files[j]} and adding as: ${folders}`); - let data = await this.getDataValue(files[j], rawImports); lodashset(globalData, folders, data); } From c5966f8b5143ca681fa5b69044a3cfc308720bf6 Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Fri, 13 Dec 2019 01:11:48 +0200 Subject: [PATCH 064/746] add tests for new global data priority and merging --- test/UserDataExtensionsTest.js | 19 ++++++++++++++++++- test/stubs-630/_data/mergingGlobalData.js | 4 ++++ test/stubs-630/_data/mergingGlobalData.json | 5 +++++ test/stubs-630/_data/mergingGlobalData.nosj | 7 +++++++ test/stubs-630/_data/mergingGlobalData.yaml | 4 ++++ 5 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/stubs-630/_data/mergingGlobalData.js create mode 100644 test/stubs-630/_data/mergingGlobalData.json create mode 100644 test/stubs-630/_data/mergingGlobalData.nosj create mode 100644 test/stubs-630/_data/mergingGlobalData.yaml diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index fa5cc1e62..cffb98b5c 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -70,7 +70,6 @@ test("Global data", async t => { "./test/stubs-630/_data/**/*.(nosj|yaml|json|js)" ]); - let dataFilePaths = await dataObj.getGlobalDataFiles(); let data = await dataObj.getData(); // JS GLOBAL DATA @@ -90,3 +89,21 @@ test("Global data", async t => { t.is(data.subdir.globalDataSubdir.keyyaml, "yaml"); }); + +test("Global data merging and priority", async t => { + let dataObj = new TemplateData("./test/stubs-630/"); + injectDataExtensions(dataObj); + + let data = await dataObj.getData(); + + // TESTING GLOBAL DATA PRIORITY AND MERGING + t.is(data.mergingGlobalData.datakey1, "js-value1"); + t.is(data.mergingGlobalData.datakey2, "json-value2"); + t.is(data.mergingGlobalData.datakey3, "yaml-value3"); + t.is(data.mergingGlobalData.datakey4, "nosj-value4"); + + t.is(data.mergingGlobalData.jskey, "js"); + t.is(data.mergingGlobalData.jsonkey, "json"); + t.is(data.mergingGlobalData.yamlkey, "yaml"); + t.is(data.mergingGlobalData.nosjkey, "nosj"); +}); diff --git a/test/stubs-630/_data/mergingGlobalData.js b/test/stubs-630/_data/mergingGlobalData.js new file mode 100644 index 000000000..f99fc138d --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.js @@ -0,0 +1,4 @@ +module.exports = { + datakey1: "js-value1", + jskey: "js" +}; diff --git a/test/stubs-630/_data/mergingGlobalData.json b/test/stubs-630/_data/mergingGlobalData.json new file mode 100644 index 000000000..68aa73e11 --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.json @@ -0,0 +1,5 @@ +{ + "datakey1": "json-value1", + "datakey2": "json-value2", + "jsonkey": "json" +} diff --git a/test/stubs-630/_data/mergingGlobalData.nosj b/test/stubs-630/_data/mergingGlobalData.nosj new file mode 100644 index 000000000..6a0152298 --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.nosj @@ -0,0 +1,7 @@ +{ + "datakey1": "nosj-value1", + "datakey2": "nosj-value2", + "datakey3": "nosj-value3", + "datakey4": "nosj-value4", + "nosjkey": "nosj" +} diff --git a/test/stubs-630/_data/mergingGlobalData.yaml b/test/stubs-630/_data/mergingGlobalData.yaml new file mode 100644 index 000000000..916ef7b70 --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.yaml @@ -0,0 +1,4 @@ +datakey1: "yaml-value1" +datakey2: "yaml-value2" +datakey3: "yaml-value3" +yamlkey: "yaml" From a689764ca1a5db2146c75f360fcbec67a26808a3 Mon Sep 17 00:00:00 2001 From: Gareth Cornish Date: Fri, 13 Dec 2019 08:55:09 +0200 Subject: [PATCH 065/746] Update test to check that changes made by a plugin surface in the final markdown (cherry picked from commit 7424813eec7731ca8530f343416245de01d4a425) --- test/TemplateRenderMarkdownPluginTest.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/TemplateRenderMarkdownPluginTest.js b/test/TemplateRenderMarkdownPluginTest.js index 7da6d7549..74918a3e1 100644 --- a/test/TemplateRenderMarkdownPluginTest.js +++ b/test/TemplateRenderMarkdownPluginTest.js @@ -6,6 +6,8 @@ const createTestMarkdownPlugin = () => { const plugin = md => { md.core.ruler.after("inline", "replace-link", function(state) { plugin.environment = state.env; + const link = state.tokens[1].children[0].attrs[0][1]; + state.tokens[1].children[0].attrs[0][1] = `${link}?data=${state.env.some}`; return false; }); }; @@ -25,6 +27,7 @@ test("Markdown Render: with HTML prerender, sends context data to the markdown l let fn = await tr.getCompiledTemplate("[link text](http://link.com)"); let result = await fn(data); t.deepEqual(plugin.environment, data); + t.is(result, '

link text

\n'); }); test("Markdown Render: without HTML prerender, sends context data to the markdown library", async t => { @@ -40,4 +43,5 @@ test("Markdown Render: without HTML prerender, sends context data to the markdow let fn = await tr.getCompiledTemplate("[link text](http://link.com)"); let result = await fn(data); t.deepEqual(plugin.environment, data); + t.is(result, '

link text

\n'); }); From dd22c086cfb1f4aa628b01c47805d32c5303dd67 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 18 Dec 2019 08:20:37 -0600 Subject: [PATCH 066/746] Adds publishConfig and funding to package.json --- package.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d7d8cf46..9e8e4acad 100755 --- a/package.json +++ b/package.json @@ -2,11 +2,18 @@ "name": "@11ty/eleventy", "version": "0.10.0-beta.1", "description": "Transform a directory of templates into HTML.", + "publishConfig": { + "access": "public" + }, "main": "src/Eleventy.js", "license": "MIT", "engines": { "node": ">=8" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + }, "keywords": [ "static-site-generator", "static-site", @@ -120,4 +127,4 @@ }, "pre-commit": "lint-staged", "pre-push": "test" -} +} \ No newline at end of file From 0d18f4d1ca4c0587c1ebba298a9603ca11429243 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 18 Dec 2019 08:20:56 -0600 Subject: [PATCH 067/746] Adds `getFilter` to config API for plugins --- src/UserConfig.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index b4930617d..7a2a25d78 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -195,6 +195,15 @@ class UserConfig { this.addHandlebarsHelper(name, callback); } + getFilter(name) { + return ( + this.javascriptFunctions[name] || + this.nunjucksFilters[name] || + this.liquidFilters[name] || + this.handlebarsHelpers[name] + ); + } + addNunjucksTag(name, tagFn) { name = this.getNamespacedName(name); @@ -255,7 +264,8 @@ class UserConfig { addPlugin(plugin, options) { debug("Adding plugin (unknown name: check your config file)."); if (typeof plugin === "function") { - plugin(this); + let configFunction = plugin; + configFunction(this, options); } else if (plugin && plugin.configFunction) { if (options && typeof options.init === "function") { options.init.call(this, plugin.initArguments || {}); From 727607c0325bcceaba6dabc7a958663d40a25e49 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 18 Dec 2019 10:30:21 -0600 Subject: [PATCH 068/746] Adds --quiet=false support for #808. --- cmd.js | 14 +++++++++++--- src/Eleventy.js | 15 ++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/cmd.js b/cmd.js index bab8ee70f..d90231c0c 100755 --- a/cmd.js +++ b/cmd.js @@ -16,7 +16,12 @@ if (process.env.DEBUG) { const EleventyErrorHandler = require("./src/EleventyErrorHandler"); try { - const argv = require("minimist")(process.argv.slice(2)); + const argv = require("minimist")(process.argv.slice(2), { + boolean: ["quiet"], + default: { + quiet: null + } + }); const Eleventy = require("./src/Eleventy"); const EleventyCommandCheck = require("./src/EleventyCommandCheck"); @@ -36,6 +41,7 @@ try { ); }); + // TODO refactor to use minimist options.unknown callback? let cmdCheck = new EleventyCommandCheck(argv); cmdCheck.hasUnknownArguments(); @@ -46,8 +52,10 @@ try { elev.setIncrementalBuild(argv.incremental); elev.setPassthroughAll(argv.passthroughall); elev.setFormats(argv.formats); - if (argv.quiet) { - elev.setIsVerbose(false); + + // --quiet and --quiet=true resolves to true + if (argv.quiet === true || argv.quiet === false) { + elev.setIsVerbose(!argv.quiet); } // careful, we can’t use async/await here to error properly diff --git a/src/Eleventy.js b/src/Eleventy.js index 32f6d401b..bc0de196c 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -41,6 +41,12 @@ class Eleventy { */ this.isVerbose = process.env.DEBUG ? false : !this.config.quietMode; + /** + * @member {Boolean} - Was verbose mode overrode manually? + * @default false + */ + this.isVerboseOverride = false; + /** * @member {Boolean} - Is Eleventy running in debug mode? * @default false @@ -283,7 +289,6 @@ class Eleventy { this.writer.setEleventyFiles(this.eleventyFiles); - // TODO maybe isVerbose -> console.log? debug(`Directories: Input: ${this.inputDir} Data: ${this.templateData.getDataDir()} @@ -318,6 +323,10 @@ Verbose Output: ${this.isVerbose}`); setIsVerbose(isVerbose) { this.isVerbose = !!isVerbose; + // mark that this was changed from the default (probably from --quiet) + // this is used when we reset the config (only applies if not overridden) + this.isVerboseOverride = true; + if (this.writer) { this.writer.setVerboseOutput(this.isVerbose); } @@ -392,6 +401,10 @@ Arguments: this.config = config.getConfig(); this.eleventyServe.config = this.config; + + if (!this.isVerboseOverride && !process.env.DEBUG) { + this.isVerbose = !this.config.quietMode; + } } /** From e744329dcf62e8e7f79070e48a565d59b66c7ca6 Mon Sep 17 00:00:00 2001 From: Justin Fagnani Date: Wed, 18 Dec 2019 16:51:49 -0800 Subject: [PATCH 069/746] Add support for .11ty.cjs extensions --- src/EleventyExtensionMap.js | 3 ++- test/TemplateRenderJavaScriptTest.js | 37 +++++++++++++++++----------- test/TemplateWriterTest.js | 5 +++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 5b2940c81..db7a04852 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -150,7 +150,8 @@ class EleventyExtensionMap { pug: "pug", njk: "njk", liquid: "liquid", - "11ty.js": "11ty.js" + "11ty.js": "11ty.js", + "11ty.cjs": "11ty.js" }; for (let extension in aliases) { diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 330cc54f6..a212d0688 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -7,6 +7,11 @@ test("JS", t => { new TemplateRender("./test/stubs/filename.11ty.js").getEngineName(), "11ty.js" ); + t.is(new TemplateRender("11ty.cjs").getEngineName(), "11ty.js"); + t.is( + new TemplateRender("./test/stubs/filename.11ty.cjs").getEngineName(), + "11ty.js" + ); }); test("JS Render a string (no data)", async t => { @@ -67,22 +72,24 @@ test("JS Render a function (Collections)", async t => { let tr = new TemplateRender("./test/stubs/use-collection.11ty.js"); let fn = await tr.getCompiledTemplate(); t.is( - (await fn({ - collections: { - post: [ - { - data: { - title: "Testing" + ( + await fn({ + collections: { + post: [ + { + data: { + title: "Testing" + } + }, + { + data: { + title: "Testing2" + } } - }, - { - data: { - title: "Testing2" - } - } - ] - } - })).trim(), + ] + } + }) + ).trim(), `
  • Testing
  • Testing2
` ); }); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index bdce43126..a4a31c3f9 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -511,7 +511,10 @@ test("Write Test 11ty.js", async t => { evf.init(); let files = await fastglob(evf.getFileGlobs()); - t.deepEqual(evf.getRawFiles(), ["./test/stubs/writeTestJS/**/*.11ty.js"]); + t.deepEqual(evf.getRawFiles(), [ + "./test/stubs/writeTestJS/**/*.11ty.js", + "./test/stubs/writeTestJS/**/*.11ty.cjs" + ]); t.deepEqual(files, ["./test/stubs/writeTestJS/test.11ty.js"]); let tmpl = tw._createTemplate(files[0]); From 89b2f19c2bf4d17db465c8e48457b4565b1efba5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 29 Dec 2019 14:00:03 -0600 Subject: [PATCH 070/746] Tests for async filters in Liquid and Nunjucks --- test/TemplateRenderLiquidTest.js | 15 +++++++++++++++ test/TemplateRenderNunjucksTest.js | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 1409ec6e9..08ee13f39 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -139,6 +139,21 @@ test("Liquid Custom Filter", async t => { t.is(await tr._testRender("{{ 'test' | prefixWithZach }}", {}), "Zachtest"); }); +test.skip("Liquid Async Filter", async t => { + let tr = new TemplateRender("liquid", "test/stubs"); + tr.engine.addFilter({ + myAsyncFilter: function(value) { + return new Promise((resolve, reject) => { + setTimeout(function() { + resolve(`HI${value}`); + }, 100); + }); + } + }); + let fn = await tr.getCompiledTemplate("{{ 'test' | myAsyncFilter }}"); + t.is((await fn()).trim(), "HItest"); +}); + test("Liquid Custom Tag prefixWithZach", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addTag("prefixWithZach", function(liquidEngine) { diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index ed3007f62..a9aa8800e 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -139,6 +139,23 @@ test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes // t.is(await fn2(), "

HELLO FROM THE OTHER SIDE.

"); }); +test("Nunjucks Async Filter", async t => { + let tr = new TemplateRender("njk", "test/stubs"); + let engine = tr.engine; + engine.addFilters( + { + myAsyncFilter: function(value, callback) { + setTimeout(function() { + callback(null, `HI${value}`); + }, 100); + } + }, + true + ); + let fn = await tr.getCompiledTemplate("{{ 'test' | myAsyncFilter }}"); + t.is((await fn()).trim(), "HItest"); +}); + test("Nunjucks Render Include a JS file (Issue 398)", async t => { let tr = new TemplateRender("njk", "test/stubs"); let engine = tr.engine; From ab7f0dcba7692ae377b9bbb73ab8394299ad33c4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 29 Dec 2019 14:00:19 -0600 Subject: [PATCH 071/746] Add bugs and homepage to package.json --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 9e8e4acad..ed8ab8e0c 100755 --- a/package.json +++ b/package.json @@ -56,6 +56,8 @@ "type": "git", "url": "git://github.com/11ty/eleventy.git" }, + "bugs": "https://github.com/11ty/eleventy/issues", + "homepage": "https://www.11ty.dev/", "ava": { "files": [ "./test/*.js" From 3c4adbb72b7ef5d58c78c3dbda3445d01a5143eb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 4 Jan 2020 13:44:54 -0600 Subject: [PATCH 072/746] Updates dependencies --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index ed8ab8e0c..8e032271f 100755 --- a/package.json +++ b/package.json @@ -76,28 +76,28 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^2.0.3", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "ava": "^2.4.0", "ink-docstrap": "1.3.2", "jsdoc": "3.6.3", "lint-staged": "^9.5.0", "markdown-it-emoji": "^1.4.0", - "nyc": "^14.1.1", + "nyc": "^15.0.0", "pre-commit": "^1.2.2", "pre-push": "^0.1.1", "prettier": "^1.19.1", "rimraf": "^3.0.0", "toml": "^3.0.0", "viperhtml": "^2.17.1", - "vue": "^2.6.10", - "vue-server-renderer": "^2.6.10", + "vue": "^2.6.11", + "vue-server-renderer": "^2.6.11", "js-yaml": "^3.13.1" }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", "browser-sync": "^2.26.7", "chalk": "^3.0.0", - "chokidar": "^3.3.0", + "chokidar": "^3.3.1", "debug": "^4.1.1", "dependency-graph": "^0.8.1", "ejs": "^2.6.2", @@ -122,11 +122,11 @@ "pretty": "^2.0.0", "pug": "^2.0.4", "recursive-copy": "^2.0.10", - "semver": "^6.3.0", + "semver": "^7.1.0", "slugify": "^1.3.6", "time-require": "^0.1.2", "valid-url": "^1.0.9" }, "pre-commit": "lint-staged", "pre-push": "test" -} \ No newline at end of file +} From 5fa0ea9b4d2babb8d01e99b6a76beb3e3b5e08a5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 4 Jan 2020 13:45:08 -0600 Subject: [PATCH 073/746] v0.10.0-beta.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e032271f..0cfdf6c6a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.10.0-beta.1", + "version": "0.10.0-beta.2", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 241a0388b7adedc554f43f72cdf45c8d3b660fe1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 4 Jan 2020 13:49:19 -0600 Subject: [PATCH 074/746] Fix tests that broke with syntaxhighlight major version upgrade 2.0 to 3.0 --- test/TemplateRenderMarkdownTest.js | 44 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js index cca7dbbe6..e438d8c61 100644 --- a/test/TemplateRenderMarkdownTest.js +++ b/test/TemplateRenderMarkdownTest.js @@ -171,7 +171,7 @@ var key = "value"; \`\`\``); t.is( (await fn()).trim(), - `
var key = "value";
` + `
var key = "value";
` ); }); @@ -194,7 +194,7 @@ var key = "value"; \`\`\``); t.is( (await fn()).trim(), - `
var key = "value";
` + `
var key = "value";
` ); }); @@ -257,10 +257,12 @@ test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", let fn = await tr.getCompiledTemplate(`# {{title}} {% testShortcode %}`); t.is( - (await fn({ - title: "My Title", - otherTitle: "My Other Title" - })).trim(), + ( + await fn({ + title: "My Title", + otherTitle: "My Other Title" + }) + ).trim(), `

My Title

My Other Title

` ); @@ -279,10 +281,12 @@ test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)" let fn = await tr.getCompiledTemplate(`# {{title}} {% testShortcode %}`); t.is( - (await fn({ - title: "My Title", - otherTitle: "My Other Title" - })).trim(), + ( + await fn({ + title: "My Title", + otherTitle: "My Other Title" + }) + ).trim(), `

My Title

My Other Title

` ); @@ -301,10 +305,12 @@ test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue # let fn = await tr.getCompiledTemplate(`# {{title}} {% testShortcode %}## My Other Title{% endtestShortcode %}`); t.is( - (await fn({ - title: "My Title", - otherTitle: "My Other Title" - })).trim(), + ( + await fn({ + title: "My Title", + otherTitle: "My Other Title" + }) + ).trim(), `

My Title

My Other Title

` ); @@ -323,10 +329,12 @@ test("Markdown Render: use Markdown inside of a Nunjucks paired shortcode (Issue let fn = await tr.getCompiledTemplate(`# {{title}} {% testShortcode %}## My Other Title{% endtestShortcode %}`); t.is( - (await fn({ - title: "My Title", - otherTitle: "My Other Title" - })).trim(), + ( + await fn({ + title: "My Title", + otherTitle: "My Other Title" + }) + ).trim(), `

My Title

My Other Title

` ); From 4ea61135ab5e7eb3b658a8a8240e3fb5c0c90d72 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 4 Jan 2020 14:02:29 -0600 Subject: [PATCH 075/746] Coverage for 0.10.0-beta.2 --- docs-src/_data/coverage.json | 8 ++++---- docs/coverage.md | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 2122006ba..bda85037b 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,10 +1,10 @@ -{"total": {"lines":{"total":2919,"covered":2564,"skipped":0,"pct":87.84},"statements":{"total":2936,"covered":2581,"skipped":0,"pct":87.91},"functions":{"total":690,"covered":601,"skipped":0,"pct":87.1},"branches":{"total":1235,"covered":992,"skipped":0,"pct":80.32}} +{"total": {"lines":{"total":2928,"covered":2569,"skipped":0,"pct":87.74},"statements":{"total":2946,"covered":2587,"skipped":0,"pct":87.81},"functions":{"total":694,"covered":604,"skipped":0,"pct":87.03},"branches":{"total":1243,"covered":991,"skipped":0,"pct":79.73}} ,"/Users/zachleat/Code/eleventy/config.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":12,"covered":11,"skipped":0,"pct":91.67},"functions":{"total":6,"covered":5,"skipped":0,"pct":83.33},"statements":{"total":12,"covered":11,"skipped":0,"pct":91.67},"branches":{"total":6,"covered":4,"skipped":0,"pct":66.67}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":34,"covered":23,"skipped":0,"pct":67.65},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":34,"covered":23,"skipped":0,"pct":67.65},"branches":{"total":10,"covered":3,"skipped":0,"pct":30}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":17,"covered":13,"skipped":0,"pct":76.47},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":17,"covered":13,"skipped":0,"pct":76.47},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":189,"covered":103,"skipped":0,"pct":54.5},"functions":{"total":34,"covered":19,"skipped":0,"pct":55.88},"statements":{"total":189,"covered":103,"skipped":0,"pct":54.5},"branches":{"total":69,"covered":27,"skipped":0,"pct":39.13}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":193,"covered":105,"skipped":0,"pct":54.4},"functions":{"total":34,"covered":19,"skipped":0,"pct":55.88},"statements":{"total":193,"covered":105,"skipped":0,"pct":54.4},"branches":{"total":73,"covered":27,"skipped":0,"pct":36.99}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -16,7 +16,7 @@ ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":13,"covered":12,"skipped":0,"pct":92.31}} ,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":288,"covered":271,"skipped":0,"pct":94.1},"functions":{"total":48,"covered":47,"skipped":0,"pct":97.92},"statements":{"total":290,"covered":273,"skipped":0,"pct":94.14},"branches":{"total":103,"covered":88,"skipped":0,"pct":85.44}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":29,"covered":27,"skipped":0,"pct":93.1},"functions":{"total":13,"covered":12,"skipped":0,"pct":92.31},"statements":{"total":31,"covered":29,"skipped":0,"pct":93.55},"branches":{"total":10,"covered":8,"skipped":0,"pct":80}} +,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.63},"functions":{"total":16,"covered":15,"skipped":0,"pct":93.75},"statements":{"total":35,"covered":32,"skipped":0,"pct":91.43},"branches":{"total":10,"covered":7,"skipped":0,"pct":70}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":57,"covered":52,"skipped":0,"pct":91.23},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":57,"covered":52,"skipped":0,"pct":91.23},"branches":{"total":24,"covered":22,"skipped":0,"pct":91.67}} ,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":81,"covered":76,"skipped":0,"pct":93.83},"functions":{"total":17,"covered":16,"skipped":0,"pct":94.12},"statements":{"total":81,"covered":76,"skipped":0,"pct":93.83},"branches":{"total":34,"covered":31,"skipped":0,"pct":91.18}} ,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":193,"covered":178,"skipped":0,"pct":92.23},"functions":{"total":34,"covered":33,"skipped":0,"pct":97.06},"statements":{"total":195,"covered":180,"skipped":0,"pct":92.31},"branches":{"total":66,"covered":55,"skipped":0,"pct":83.33}} @@ -32,7 +32,7 @@ ,"/Users/zachleat/Code/eleventy/src/TemplatePermalinkNoWrite.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":77,"covered":76,"skipped":0,"pct":98.7},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":42,"covered":40,"skipped":0,"pct":95.24}} ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":93,"covered":71,"skipped":0,"pct":76.34},"functions":{"total":25,"covered":17,"skipped":0,"pct":68},"statements":{"total":93,"covered":71,"skipped":0,"pct":76.34},"branches":{"total":16,"covered":6,"skipped":0,"pct":37.5}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":195,"covered":114,"skipped":0,"pct":58.46},"functions":{"total":52,"covered":24,"skipped":0,"pct":46.15},"statements":{"total":196,"covered":115,"skipped":0,"pct":58.67},"branches":{"total":77,"covered":39,"skipped":0,"pct":50.65}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":197,"covered":115,"skipped":0,"pct":58.38},"functions":{"total":53,"covered":24,"skipped":0,"pct":45.28},"statements":{"total":198,"covered":116,"skipped":0,"pct":58.59},"branches":{"total":81,"covered":39,"skipped":0,"pct":48.15}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} diff --git a/docs/coverage.md b/docs/coverage.md index 9777caf75..57cb14e81 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,14 +1,14 @@ -# Code Coverage for Eleventy v0.10.0-beta.1 +# Code Coverage for Eleventy v0.10.0-beta.2 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 87.84% | 87.91% | 87.1% | 80.32% | +| `total` | 87.74% | 87.81% | 87.03% | 79.73% | | `config.js` | 100% | 100% | 100% | 100% | | `src/Benchmark.js` | 91.67% | 91.67% | 83.33% | 66.67% | | `src/BenchmarkGroup.js` | 67.65% | 67.65% | 71.43% | 30% | | `src/BenchmarkManager.js` | 76.47% | 76.47% | 71.43% | 75% | | `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 54.5% | 54.5% | 55.88% | 39.13% | +| `src/Eleventy.js` | 54.4% | 54.4% | 55.88% | 36.99% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | | `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | @@ -20,7 +20,7 @@ | `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 92.31% | | `src/Template.js` | 94.1% | 94.14% | 97.92% | 85.44% | | `src/TemplateCache.js` | 100% | 100% | 100% | 100% | -| `src/TemplateCollection.js` | 93.1% | 93.55% | 92.31% | 80% | +| `src/TemplateCollection.js` | 90.63% | 91.43% | 93.75% | 70% | | `src/TemplateConfig.js` | 91.23% | 91.23% | 66.67% | 91.67% | | `src/TemplateContent.js` | 93.83% | 93.83% | 94.12% | 91.18% | | `src/TemplateData.js` | 92.23% | 92.31% | 97.06% | 83.33% | @@ -36,7 +36,7 @@ | `src/TemplatePermalinkNoWrite.js` | 100% | 100% | 100% | 100% | | `src/TemplateRender.js` | 98.7% | 98.7% | 100% | 95.24% | | `src/TemplateWriter.js` | 76.34% | 76.34% | 68% | 37.5% | -| `src/UserConfig.js` | 58.46% | 58.67% | 46.15% | 50.65% | +| `src/UserConfig.js` | 58.38% | 58.59% | 45.28% | 48.15% | | `src/Engines/Ejs.js` | 95% | 95% | 85.71% | 88.89% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | From 17cb87cd1b0326049b978f8f11cbea88b0c17da7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 4 Jan 2020 14:18:47 -0600 Subject: [PATCH 076/746] Yep this hardcoded date definitely made two tests fail Cool cool cool --- test/stubs/collection/test5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/stubs/collection/test5.md b/test/stubs/collection/test5.md index 7d3ee6905..3f0f7dfc3 100644 --- a/test/stubs/collection/test5.md +++ b/test/stubs/collection/test5.md @@ -1,5 +1,5 @@ --- -date: 2020-01-01 +date: 2038-01-01 --- # Test 3 From 09e60a15fdb012b3c8889836a7293cec0d4e4a5c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 4 Jan 2020 14:18:47 -0600 Subject: [PATCH 077/746] Yep this hardcoded date definitely made two tests fail Cool cool cool --- test/stubs/collection/test5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/stubs/collection/test5.md b/test/stubs/collection/test5.md index 7d3ee6905..3f0f7dfc3 100644 --- a/test/stubs/collection/test5.md +++ b/test/stubs/collection/test5.md @@ -1,5 +1,5 @@ --- -date: 2020-01-01 +date: 2038-01-01 --- # Test 3 From bb443b7da7daae6b8b253a127431cc21d97adae1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 7 Jan 2020 15:05:48 -0600 Subject: [PATCH 078/746] v0.10.0 --- docs/coverage.md | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/coverage.md b/docs/coverage.md index 57cb14e81..fd05e2ccd 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,4 +1,4 @@ -# Code Coverage for Eleventy v0.10.0-beta.2 +# Code Coverage for Eleventy v0.10.0 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | diff --git a/package.json b/package.json index 0cfdf6c6a..28b2b6a84 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.10.0-beta.2", + "version": "0.10.0", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -129,4 +129,4 @@ }, "pre-commit": "lint-staged", "pre-push": "test" -} +} \ No newline at end of file From dcc3966e0c6037086457cd732cdac600e641e924 Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Fri, 10 Jan 2020 14:50:55 +0200 Subject: [PATCH 079/746] support for cjs extension in local and global template data --- src/TemplateData.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 83862e14f..48a33f25f 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -113,6 +113,7 @@ class TemplateData { let dir = await this.getInputDir(); let paths = [ `${dir}/**/*.json`, // covers .11tydata.json too + `${dir}/**/*${this.config.jsDataFileSuffix}.cjs`, `${dir}/**/*${this.config.jsDataFileSuffix}.js` ]; @@ -142,7 +143,10 @@ class TemplateData { } return [ - this._getGlobalDataGlobByExtension(dir, "(" + userExtensions + "json|js)") + this._getGlobalDataGlobByExtension( + dir, + "(" + userExtensions + "json|cjs|js)" + ) ]; } @@ -312,6 +316,7 @@ class TemplateData { // ignoreProcessing = true for local data files if ( extension === "js" || + extension === "cjs" || (extension === "json" && (ignoreProcessing || !this.dataTemplateEngine)) ) { // JS data file or require’d JSON (no preprocessing needed) @@ -379,6 +384,7 @@ class TemplateData { // data suffix paths.push(filePathNoExt + dataSuffix + ".js"); + paths.push(filePathNoExt + dataSuffix + ".cjs"); paths.push(filePathNoExt + dataSuffix + ".json"); // inject user extensions this._pushExtensionsToPaths( @@ -400,6 +406,7 @@ class TemplateData { if (!inputDir) { // data suffix paths.push(dirPathNoExt + dataSuffix + ".js"); + paths.push(dirPathNoExt + dataSuffix + ".cjs"); paths.push(dirPathNoExt + dataSuffix + ".json"); this._pushExtensionsToPaths( paths, @@ -415,6 +422,7 @@ class TemplateData { if (dir.indexOf(inputDir) === 0 && dir !== inputDir) { // data suffix paths.push(dirPathNoExt + dataSuffix + ".js"); + paths.push(dirPathNoExt + dataSuffix + ".cjs"); paths.push(dirPathNoExt + dataSuffix + ".json"); this._pushExtensionsToPaths( paths, From a6067d518e4c4124129b2435f5671ba8d21e6147 Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Fri, 10 Jan 2020 14:52:42 +0200 Subject: [PATCH 080/746] adds new tests for cjs data extension in TemplateDataTest and fixes a lot of checks of data files listings in old tests --- test/EleventyFilesTest.js | 1 + test/EleventyTest.js | 2 ++ test/TemplateDataTest.js | 34 +++++++++++++++++-- test/TemplateTest.js | 7 ++++ test/UserDataExtensionsTest.js | 4 ++- test/stubs/_data/globalDataFnCJS.cjs | 7 ++++ .../component-async/component.11tydata.cjs | 9 +++++ test/stubs/component/component.11tydata.cjs | 5 +++ test/stubs/component/component.11tydata.json | 3 +- 9 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 test/stubs/_data/globalDataFnCJS.cjs create mode 100644 test/stubs/component-async/component.11tydata.cjs create mode 100644 test/stubs/component/component.11tydata.cjs diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 6d7debbc7..915c02900 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -558,6 +558,7 @@ test("Glob Watcher Files with Config Passthroughs (no template formats)", async t.deepEqual(await evf.getGlobWatcherTemplateDataFiles(), [ "./test/stubs/**/*.json", + "./test/stubs/**/*.11tydata.cjs", "./test/stubs/**/*.11tydata.js" ]); }); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 19920cdaf..6d52bc36a 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -56,6 +56,7 @@ test("Eleventy file watching", async t => { "./test/stubs/_data/**", "./.eleventy.js", "./test/stubs/**/*.json", + "./test/stubs/**/*.11tydata.cjs", "./test/stubs/**/*.11tydata.js", "./test/stubs/deps/dep1.js", "./test/stubs/deps/dep2.js" @@ -78,6 +79,7 @@ test("Eleventy file watching (no JS dependencies)", async t => { "./test/stubs/_data/**", "./.eleventy.js", "./test/stubs/**/*.json", + "./test/stubs/**/*.11tydata.cjs", "./test/stubs/**/*.11tydata.js" ]); }); diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 9350c062f..490ec768a 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -53,6 +53,7 @@ test("Add local data", async t => { // from the js file // this checks priority/overrides + t.is(withLocalData.localdatakeyfromcjs, "common-js-howdydoody"); t.is(withLocalData.localdatakeyfromjs, "howdydoody"); t.is(withLocalData.localdatakeyfromjs2, "howdy2"); }); @@ -66,6 +67,7 @@ test("Get local data async JS", async t => { // from the js file t.is(withLocalData.localdatakeyfromjs, "howdydoody"); + t.is(withLocalData.localdatakeyfromcjs, "common-js-howdydoody"); }); test("addLocalData() doesn’t exist but doesn’t fail (template file does exist)", async t => { @@ -98,14 +100,16 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does not test("Global Dir Directory", async t => { let dataObj = new TemplateData("./"); - t.deepEqual(await dataObj.getGlobalDataGlob(), ["./_data/**/*.(json|js)"]); + t.deepEqual(await dataObj.getGlobalDataGlob(), [ + "./_data/**/*.(json|cjs|js)" + ]); }); test("Global Dir Directory with Constructor Path Arg", async t => { let dataObj = new TemplateData("./test/stubs/"); t.deepEqual(await dataObj.getGlobalDataGlob(), [ - "./test/stubs/_data/**/*.(json|js)" + "./test/stubs/_data/**/*.(json|cjs|js)" ]); }); @@ -155,7 +159,7 @@ test("getAllGlobalData() with js function data file", async t => { t.true( dataFilePaths.filter(path => { - return path.indexOf("./test/stubs/_data/globalData2.js") === 0; + return path.indexOf("./test/stubs/_data/globalDataFn.js") === 0; }).length > 0 ); @@ -163,6 +167,21 @@ test("getAllGlobalData() with js function data file", async t => { t.is(data.globalDataFn.datakeyfromjsfn, "howdy"); }); +test("getAllGlobalData() with common js function data file", async t => { + let dataObj = new TemplateData("./test/stubs/"); + let data = await dataObj.cacheData(); + let dataFilePaths = await dataObj.getGlobalDataFiles(); + + t.true( + dataFilePaths.filter(path => { + return path.indexOf("./test/stubs/_data/globalDataFnCJS.cjs") === 0; + }).length > 0 + ); + + t.truthy(data.globalDataFnCJS); + t.is(data.globalDataFnCJS.datakeyfromcjsfn, "common-js-howdy"); +}); + test("getDataValue() without a dataTemplateEngine", async t => { let dataObj = new TemplateData("./test/stubs/"); dataObj.setDataTemplateEngine(false); @@ -200,6 +219,7 @@ test("getLocalDataPaths", async t => { t.deepEqual(paths, [ "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", + "./test/stubs/component/component.11tydata.cjs", "./test/stubs/component/component.11tydata.js" ]); }); @@ -213,12 +233,15 @@ test("Deeper getLocalDataPaths", async t => { t.deepEqual(paths, [ "./test/test.json", "./test/test.11tydata.json", + "./test/test.11tydata.cjs", "./test/test.11tydata.js", "./test/stubs/stubs.json", "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.cjs", "./test/stubs/stubs.11tydata.js", "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", + "./test/stubs/component/component.11tydata.cjs", "./test/stubs/component/component.11tydata.js" ]); }); @@ -232,6 +255,7 @@ test("getLocalDataPaths with an 11ty js template", async t => { t.deepEqual(paths, [ "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", + "./test/stubs/component/component.11tydata.cjs", "./test/stubs/component/component.11tydata.js" ]); }); @@ -245,6 +269,7 @@ test("getLocalDataPaths with inputDir passed in (trailing slash)", async t => { t.deepEqual(paths, [ "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", + "./test/stubs/component/component.11tydata.cjs", "./test/stubs/component/component.11tydata.js" ]); }); @@ -258,6 +283,7 @@ test("getLocalDataPaths with inputDir passed in (no trailing slash)", async t => t.deepEqual(paths, [ "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", + "./test/stubs/component/component.11tydata.cjs", "./test/stubs/component/component.11tydata.js" ]); }); @@ -271,6 +297,7 @@ test("getLocalDataPaths with inputDir passed in (no leading slash)", async t => t.deepEqual(paths, [ "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", + "./test/stubs/component/component.11tydata.cjs", "./test/stubs/component/component.11tydata.js" ]); }); @@ -287,6 +314,7 @@ test("getTemplateDataFileGlob", async t => { t.deepEqual(await tw.getTemplateDataFileGlob(), [ "./test/stubs/**/*.json", + "./test/stubs/**/*.11tydata.cjs", "./test/stubs/**/*.11tydata.js" ]); }); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 6970f878d..260aebbab 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -443,6 +443,7 @@ test("Local template data file import (without a global data json)", async t => t.deepEqual(await dataObj.getLocalDataPaths(tmpl.getInputPath()), [ "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", + "./test/stubs/component/component.11tydata.cjs", "./test/stubs/component/component.11tydata.js" ]); t.is(data.localdatakey1, "localdatavalue1"); @@ -463,12 +464,15 @@ test("Local template data file import (two subdirectories deep)", async t => { t.deepEqual(await dataObj.getLocalDataPaths(tmpl.getInputPath()), [ "./test/stubs/firstdir/firstdir.json", "./test/stubs/firstdir/firstdir.11tydata.json", + "./test/stubs/firstdir/firstdir.11tydata.cjs", "./test/stubs/firstdir/firstdir.11tydata.js", "./test/stubs/firstdir/seconddir/seconddir.json", "./test/stubs/firstdir/seconddir/seconddir.11tydata.json", + "./test/stubs/firstdir/seconddir/seconddir.11tydata.cjs", "./test/stubs/firstdir/seconddir/seconddir.11tydata.js", "./test/stubs/firstdir/seconddir/component.json", "./test/stubs/firstdir/seconddir/component.11tydata.json", + "./test/stubs/firstdir/seconddir/component.11tydata.cjs", "./test/stubs/firstdir/seconddir/component.11tydata.js" ]); }); @@ -488,9 +492,11 @@ test("Posts inherits local JSON, layouts", async t => { t.deepEqual(localDataPaths, [ "./test/stubs/posts/posts.json", "./test/stubs/posts/posts.11tydata.json", + "./test/stubs/posts/posts.11tydata.cjs", "./test/stubs/posts/posts.11tydata.js", "./test/stubs/posts/post1.json", "./test/stubs/posts/post1.11tydata.json", + "./test/stubs/posts/post1.11tydata.cjs", "./test/stubs/posts/post1.11tydata.js" ]); @@ -523,6 +529,7 @@ test("Template and folder name are the same, make sure data imports work ok", as t.deepEqual(localDataPaths, [ "./test/stubs/posts/posts.json", "./test/stubs/posts/posts.11tydata.json", + "./test/stubs/posts/posts.11tydata.cjs", "./test/stubs/posts/posts.11tydata.js" ]); diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index fa5cc1e62..d0a15b71d 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -50,6 +50,7 @@ test("Local files", async t => { "./test/stubs-630/component-yaml/component-yaml.11tydata.yaml", "./test/stubs-630/component-yaml/component-yaml.11tydata.nosj", "./test/stubs-630/component-yaml/component-yaml.11tydata.json", + "./test/stubs-630/component-yaml/component-yaml.11tydata.cjs", "./test/stubs-630/component-yaml/component-yaml.11tydata.js", "./test/stubs-630/component-yaml/component.yaml", "./test/stubs-630/component-yaml/component.nosj", @@ -57,6 +58,7 @@ test("Local files", async t => { "./test/stubs-630/component-yaml/component.11tydata.yaml", "./test/stubs-630/component-yaml/component.11tydata.nosj", "./test/stubs-630/component-yaml/component.11tydata.json", + "./test/stubs-630/component-yaml/component.11tydata.cjs", "./test/stubs-630/component-yaml/component.11tydata.js" ]); }); @@ -67,7 +69,7 @@ test("Global data", async t => { injectDataExtensions(dataObj); t.deepEqual(await dataObj.getGlobalDataGlob(), [ - "./test/stubs-630/_data/**/*.(nosj|yaml|json|js)" + "./test/stubs-630/_data/**/*.(nosj|yaml|json|cjs|js)" ]); let dataFilePaths = await dataObj.getGlobalDataFiles(); diff --git a/test/stubs/_data/globalDataFnCJS.cjs b/test/stubs/_data/globalDataFnCJS.cjs new file mode 100644 index 000000000..52e9b3087 --- /dev/null +++ b/test/stubs/_data/globalDataFnCJS.cjs @@ -0,0 +1,7 @@ +const dep1 = require("../deps/dep1"); + +module.exports = function() { + return { + datakeyfromcjsfn: "common-js-howdy" + }; +}; diff --git a/test/stubs/component-async/component.11tydata.cjs b/test/stubs/component-async/component.11tydata.cjs new file mode 100644 index 000000000..b0ff52b2e --- /dev/null +++ b/test/stubs/component-async/component.11tydata.cjs @@ -0,0 +1,9 @@ +module.exports = async function() { + return new Promise(resolve => { + setTimeout(function() { + resolve({ + localdatakeyfromcjs: "common-js-howdydoody" + }); + }, 1); + }); +}; diff --git a/test/stubs/component/component.11tydata.cjs b/test/stubs/component/component.11tydata.cjs new file mode 100644 index 000000000..f9b055acb --- /dev/null +++ b/test/stubs/component/component.11tydata.cjs @@ -0,0 +1,5 @@ +const dep2 = require("../deps/dep2"); + +module.exports = { + localdatakeyfromcjs: "common-js-howdydoody" +}; diff --git a/test/stubs/component/component.11tydata.json b/test/stubs/component/component.11tydata.json index d0d637365..77c24c74d 100644 --- a/test/stubs/component/component.11tydata.json +++ b/test/stubs/component/component.11tydata.json @@ -1,4 +1,5 @@ { "localdatakeyfromjs": "this_is_overridden", + "localdatakeyfromcjs": "this_is_overridden", "localdatakeyfromjs2": "howdy2" -} \ No newline at end of file +} From f663ce2d151050d5df0c073165884eb139f47bc9 Mon Sep 17 00:00:00 2001 From: Frank Taillandier Date: Sun, 12 Jan 2020 15:41:50 +0100 Subject: [PATCH 081/746] fix: don't throw an error on null date fix #786 Co-Authored-By: Dave Ceddia --- src/Template.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Template.js b/src/Template.js index 6c002d684..2a0ac1000 100644 --- a/src/Template.js +++ b/src/Template.js @@ -602,7 +602,7 @@ class Template extends TemplateContent { async getMappedDate(data) { // should we use Luxon dates everywhere? Right now using built-in `Date` - if ("date" in data) { + if ("date" in data && data.date) { debug( "getMappedDate: using a date in the data for %o of %o", this.inputPath, From 58e373fdfa309fee7a61058adb4d31f3008c1c3b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 17 Jan 2020 17:07:20 -0600 Subject: [PATCH 082/746] =?UTF-8?q?Just=20testing=20that=20merge=20doesn?= =?UTF-8?q?=E2=80=99t=20need=20to=20return,=20it=20augments=20the=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/MergeTest.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/MergeTest.js b/test/MergeTest.js index ce58d6a68..ded2bb252 100644 --- a/test/MergeTest.js +++ b/test/MergeTest.js @@ -12,6 +12,12 @@ test("Shallow Merge", t => { t.deepEqual(Merge({ a: [1] }, { a: [2] }), { a: [1, 2] }); }); +test("Doesn’t need to return", t => { + var b = { a: 2 }; + Merge(b, { a: 1 }); + t.deepEqual(b, { a: 1 }); +}); + test("Invalid", t => { t.deepEqual(Merge({}, 1), {}); t.deepEqual(Merge({}, [1]), {}); From f3d90f97b40158946ed81ecffeefd3ece7cc8e8a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 17 Jan 2020 17:07:37 -0600 Subject: [PATCH 083/746] Match the test to the workaround in #567 --- test/TemplateRenderNunjucksTest.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index a9aa8800e..1598afd8e 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -246,15 +246,15 @@ test("Nunjucks Render with getGlobals Issue #567", async t => { t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); -test("Nunjucks Render with getVarByName Filter Issue #567", async t => { +test("Nunjucks Render with getVarFromString Filter Issue #567", async t => { let tr = new TemplateRender("njk"); let env = tr.engine.getEngineLib(); - env.addFilter("getVarByName", function(varName) { + env.addFilter("getVarFromString", function(varName) { return this.getVariables()[varName]; }); let fn = await tr.getCompiledTemplate( - "

{{ 'my-global-name' | getVarByName }}

" + "

{{ 'my-global-name' | getVarFromString }}

" ); t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); From f013fcd3de7b789b42c3e704cad0aa9ab43aba01 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Jan 2020 22:42:43 -0600 Subject: [PATCH 084/746] Updates ava --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 28b2b6a84..2cd7cccec 100755 --- a/package.json +++ b/package.json @@ -59,14 +59,13 @@ "bugs": "https://github.com/11ty/eleventy/issues", "homepage": "https://www.11ty.dev/", "ava": { + "babel": true, + "failFast": true, "files": [ "./test/*.js" ], - "sources": [ - "./**/.eleventyignore", - "./src/**/*.js", - "./test/stubs/**", - "!./test/stubs/**/_site/**" + "ignoredByWatcher": [ + "./test/stubs/**/*" ] }, "lint-staged": { @@ -77,7 +76,8 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", - "ava": "^2.4.0", + "@ava/babel": "^1.0.0", + "ava": "^3.0.0", "ink-docstrap": "1.3.2", "jsdoc": "3.6.3", "lint-staged": "^9.5.0", From 76fbae68f5f03af71698cf276fc5695442728496 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Jan 2020 22:43:39 -0600 Subject: [PATCH 085/746] js-yaml should be a devDependency not a dep --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2cd7cccec..21c725498 100755 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "@ava/babel": "^1.0.0", "ava": "^3.0.0", "ink-docstrap": "1.3.2", + "js-yaml": "^3.13.1", "jsdoc": "3.6.3", "lint-staged": "^9.5.0", "markdown-it-emoji": "^1.4.0", @@ -90,8 +91,7 @@ "toml": "^3.0.0", "viperhtml": "^2.17.1", "vue": "^2.6.11", - "vue-server-renderer": "^2.6.11", - "js-yaml": "^3.13.1" + "vue-server-renderer": "^2.6.11" }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", From 4d4e827cae4bf6d556a5e0e1820e89f9a7b38428 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Jan 2020 22:44:08 -0600 Subject: [PATCH 086/746] Adds times called to benchmarking --- src/Benchmark.js | 6 ++++++ src/BenchmarkGroup.js | 22 ++++++++++++++++++++-- src/Engines/Markdown.js | 1 - src/TemplatePassthrough.js | 11 ++++++++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/Benchmark.js b/src/Benchmark.js index 8f03679a1..988e37177 100644 --- a/src/Benchmark.js +++ b/src/Benchmark.js @@ -5,10 +5,12 @@ class Benchmark { reset() { this.timeSpent = 0; + this.timesCalled = 0; this.beforeDates = []; } before() { + this.timesCalled++; this.beforeDates.push(new Date()); } @@ -23,6 +25,10 @@ class Benchmark { } } + getTimesCalled() { + return this.timesCalled; + } + getTotal() { return this.timeSpent; } diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index bc1e786d7..4e34b4721 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -19,7 +19,7 @@ class BenchmarkGroup { } } - // TODO make this async + // TODO use addAsync everywhere instead add(type, callback) { let benchmark = (this.benchmarks[type] = new Benchmark()); @@ -31,6 +31,19 @@ class BenchmarkGroup { }; } + // callback must return a promise + async addAsync(type, callback) { + let benchmark = (this.benchmarks[type] = new Benchmark()); + + benchmark.before(); + // don’t await here. + let promise = callback(); + promise.then(function() { + benchmark.after(); + }); + return promise; + } + setMinimumThresholdMs(minimumThresholdMs) { let val = parseInt(minimumThresholdMs, 10); if (isNaN(val)) { @@ -55,10 +68,15 @@ class BenchmarkGroup { percent > thresholdPercent && totalForBenchmark >= this.minimumThresholdMs ) { + let timesCalledCount = bench.getTimesCalled(); + let timesCalled = ""; + if (timesCalledCount > 1) { + timesCalled = `, called ${timesCalledCount}×`; + } let str = chalk.yellow( `Benchmark (${label}): ${type} took ${bench.getTotal()}ms (${percent.toFixed( 1 - )}%)` + )}%${timesCalled})` ); if (isVerbose) { console.log(str); diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index 8bb5db65d..89bd5c20d 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -1,6 +1,5 @@ const markdownIt = require("markdown-it"); const TemplateEngine = require("./TemplateEngine"); -const config = require("../Config"); // const debug = require("debug")("Eleventy:Markdown"); class Markdown extends TemplateEngine { diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index 1a758b4d0..a5ad3f420 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -4,6 +4,7 @@ const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthrough"); const fastglob = require("fast-glob"); const EleventyBaseError = require("./EleventyBaseError"); +const bench = require("./BenchmarkManager").get("PassthroughCopy"); class TemplatePassthroughError extends EleventyBaseError {} @@ -64,12 +65,20 @@ class TemplatePassthrough { return files; } - copy(src, dest, copyOptions) { + async copy(src, dest, copyOptions) { if ( TemplatePath.stripLeadingDotSlash(dest).includes( TemplatePath.stripLeadingDotSlash(this.outputDir) ) ) { + // Uncomment this if you want to add benchmarking to copy + // (Warning, it seems to be noisy and low value feedback) + // return bench.addAsync(`Copying ${src}`, function() { + // // copy() returns a promise + // return copy(src, dest, copyOptions); + // }); + + // copy() returns a promise return copy(src, dest, copyOptions); } return Promise.reject( From 556f2d83196a3845e34b1d7f23c6cef2365f0e66 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Jan 2020 22:44:38 -0600 Subject: [PATCH 087/746] Ava 3.0 update to one test --- test/EleventyErrorUtilTest.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/test/EleventyErrorUtilTest.js b/test/EleventyErrorUtilTest.js index 9fa210ec1..e13036cbb 100644 --- a/test/EleventyErrorUtilTest.js +++ b/test/EleventyErrorUtilTest.js @@ -22,18 +22,15 @@ test("cleanMessage()", t => { }); test("deconvertErrorToObject() should throw on invalid inputs", t => { - t.throws( - () => deconvertErrorToObject(undefined), - "Could not convert error object from: undefined" - ); - t.throws( - () => deconvertErrorToObject(""), - "Could not convert error object from: " - ); - t.throws( - () => deconvertErrorToObject("Not an error"), - "Could not convert error object from: Not an error" - ); + t.throws(() => deconvertErrorToObject(undefined), { + message: "Could not convert error object from: undefined" + }); + t.throws(() => deconvertErrorToObject(""), { + message: "Could not convert error object from: " + }); + t.throws(() => deconvertErrorToObject("Not an error"), { + message: "Could not convert error object from: Not an error" + }); }); test("deconvertErrorToObject() should return its argument if it does not contain another error", t => { From b3adaabc5c1de0bcf59f00d2957483b2ec6aac4b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 24 Jan 2020 13:15:54 -0600 Subject: [PATCH 088/746] Slow move to async from sync directory checks --- src/EleventyExtensionMap.js | 2 +- src/EleventyWatchTargets.js | 2 +- src/TemplatePassthrough.js | 7 +--- src/TemplatePassthroughManager.js | 2 +- src/TemplatePath.js | 56 ++++++++++++++++++++++++- test/TemplatePathTest.js | 68 +++++++++++++++++++++++++++---- 6 files changed, 119 insertions(+), 18 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index db7a04852..f73a2e998 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -54,7 +54,7 @@ class EleventyExtensionMap { } _getGlobs(formatKeys, inputDir) { - let dir = TemplatePath.convertToRecursiveGlob(inputDir); + let dir = TemplatePath.convertToRecursiveGlobSync(inputDir); let globs = []; formatKeys.forEach( function(key) { diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index ca73e8850..3513edbac 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -63,7 +63,7 @@ class EleventyWatchTargets { addAndMakeGlob(targets) { targets = this._normalizeTargets(targets).map(entry => - TemplatePath.convertToRecursiveGlob(entry) + TemplatePath.convertToRecursiveGlobSync(entry) ); this.addRaw(targets); } diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index a5ad3f420..c514b2529 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -1,10 +1,9 @@ const copy = require("recursive-copy"); -const fs = require("fs"); const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthrough"); const fastglob = require("fast-glob"); const EleventyBaseError = require("./EleventyBaseError"); -const bench = require("./BenchmarkManager").get("PassthroughCopy"); +//const bench = require("./BenchmarkManager").get("PassthroughCopy"); class TemplatePassthroughError extends EleventyBaseError {} @@ -98,11 +97,9 @@ class TemplatePassthrough { if (!this.isDryRun) { debug("Copying %o", this.inputPath); - const isDirectory = TemplatePath.isDirectorySync(this.inputPath); - const isFile = fs.existsSync(this.inputPath); // If directory or file, recursive copy - if (isDirectory || isFile) { + if (await TemplatePath.exists(this.inputPath)) { // IMPORTANT: this returns a promise, does not await for promise to finish return this.copy(this.inputPath, this.getOutputPath(), copyOptions); } diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 294ab9a8e..d154ad838 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -67,7 +67,7 @@ class TemplatePassthroughManager { getConfigPathGlobs() { return this.getConfigPaths().map(path => { - return TemplatePath.convertToRecursiveGlob(path.inputPath); + return TemplatePath.convertToRecursiveGlobSync(path.inputPath); }); } diff --git a/src/TemplatePath.js b/src/TemplatePath.js index e006a1fcc..f971b7d25 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -1,7 +1,7 @@ const path = require("path"); const normalize = require("normalize-path"); const parsePath = require("parse-filepath"); -const fs = require("fs-extra"); +const fs = require("fs"); function TemplatePath() {} @@ -228,6 +228,36 @@ TemplatePath.isDirectorySync = function(path) { return fs.existsSync(path) && fs.statSync(path).isDirectory(); }; +/** + * @param {String} path A path + * @returns {Boolean} whether `path` points to an existing directory. + */ +TemplatePath.isDirectory = async function(path) { + return new Promise(resolve => { + fs.stat(path, (err, stats) => { + if (stats) { + resolve(stats.isDirectory()); + } + resolve(false); + }); + }); +}; + +/** + * @param {String} path A path + * @returns {Boolean} whether `path` points to a existing directory or file. + */ +TemplatePath.exists = async function(path) { + return new Promise(resolve => { + fs.stat(path, (err, stats) => { + if (stats) { + resolve(true); + } + resolve(false); + }); + }); +}; + /** * Appends a recursive wildcard glob pattern to `path` * unless `path` is not a directory; then, `path` is assumed to be a file path @@ -236,7 +266,7 @@ TemplatePath.isDirectorySync = function(path) { * @param {String} path * @returns {String} */ -TemplatePath.convertToRecursiveGlob = function(path) { +TemplatePath.convertToRecursiveGlobSync = function(path) { if (path === "") { return "./**"; } @@ -250,6 +280,28 @@ TemplatePath.convertToRecursiveGlob = function(path) { return path; }; +/** + * Appends a recursive wildcard glob pattern to `path` + * unless `path` is not a directory; then, `path` is assumed to be a file path + * and is left unchaged. + * + * @param {String} path + * @returns {String} + */ +TemplatePath.convertToRecursiveGlob = async function(path) { + if (path === "") { + return "./**"; + } + + path = TemplatePath.addLeadingDotSlash(path); + + if (await TemplatePath.isDirectory(path)) { + return path + (!path.endsWith("/") ? "/" : "") + "**"; + } + + return path; +}; + /** * Returns the extension of the path without the leading dot. * If the path has no extensions, the empty string is returned. diff --git a/test/TemplatePathTest.js b/test/TemplatePathTest.js index 57dc8d985..532ae57f8 100644 --- a/test/TemplatePathTest.js +++ b/test/TemplatePathTest.js @@ -225,15 +225,46 @@ test("stripLeadingSubPath", t => { t.is(TemplatePath.stripLeadingSubPath(".htaccess", "."), ".htaccess"); }); -test("convertToRecursiveGlob", t => { - t.is(TemplatePath.convertToRecursiveGlob(""), "./**"); - t.is(TemplatePath.convertToRecursiveGlob("."), "./**"); - t.is(TemplatePath.convertToRecursiveGlob("./"), "./**"); - t.is(TemplatePath.convertToRecursiveGlob("test/stubs"), "./test/stubs/**"); - t.is(TemplatePath.convertToRecursiveGlob("test/stubs/"), "./test/stubs/**"); - t.is(TemplatePath.convertToRecursiveGlob("./test/stubs/"), "./test/stubs/**"); +test("convertToRecursiveGlobSync", t => { + t.is(TemplatePath.convertToRecursiveGlobSync(""), "./**"); + t.is(TemplatePath.convertToRecursiveGlobSync("."), "./**"); + t.is(TemplatePath.convertToRecursiveGlobSync("./"), "./**"); t.is( - TemplatePath.convertToRecursiveGlob("./test/stubs/config.js"), + TemplatePath.convertToRecursiveGlobSync("test/stubs"), + "./test/stubs/**" + ); + t.is( + TemplatePath.convertToRecursiveGlobSync("test/stubs/"), + "./test/stubs/**" + ); + t.is( + TemplatePath.convertToRecursiveGlobSync("./test/stubs/"), + "./test/stubs/**" + ); + t.is( + TemplatePath.convertToRecursiveGlobSync("./test/stubs/config.js"), + "./test/stubs/config.js" + ); +}); + +test("convertToRecursiveGlob", async t => { + t.is(await TemplatePath.convertToRecursiveGlob(""), "./**"); + t.is(await TemplatePath.convertToRecursiveGlob("."), "./**"); + t.is(await TemplatePath.convertToRecursiveGlob("./"), "./**"); + t.is( + await TemplatePath.convertToRecursiveGlob("test/stubs"), + "./test/stubs/**" + ); + t.is( + await TemplatePath.convertToRecursiveGlob("test/stubs/"), + "./test/stubs/**" + ); + t.is( + await TemplatePath.convertToRecursiveGlob("./test/stubs/"), + "./test/stubs/**" + ); + t.is( + await TemplatePath.convertToRecursiveGlob("./test/stubs/config.js"), "./test/stubs/config.js" ); }); @@ -276,3 +307,24 @@ test("removeExtension", t => { "./test/stubs" ); }); + +test("isDirectorySync", t => { + t.is(TemplatePath.isDirectorySync("asdlkfjklsadjflkja"), false); + t.is(TemplatePath.isDirectorySync("test"), true); + t.is(TemplatePath.isDirectorySync("test/stubs"), true); + t.is(TemplatePath.isDirectorySync("test/stubs/.eleventyignore"), false); +}); + +test("isDirectory", async t => { + t.is(await TemplatePath.isDirectory("asdlkfjklsadjflkja"), false); + t.is(await TemplatePath.isDirectory("test"), true); + t.is(await TemplatePath.isDirectory("test/stubs"), true); + t.is(await TemplatePath.isDirectory("test/stubs/.eleventyignore"), false); +}); + +test("exists", async t => { + t.is(await TemplatePath.exists("asdlkfjklsadjflkja"), false); + t.is(await TemplatePath.exists("test"), true); + t.is(await TemplatePath.exists("test/stubs"), true); + t.is(await TemplatePath.exists("test/stubs/.eleventyignore"), true); +}); From c26302f2b592e8a3eb820c683d1fd34cb910f0a9 Mon Sep 17 00:00:00 2001 From: Frank Taillandier Date: Thu, 6 Feb 2020 22:11:53 +0100 Subject: [PATCH 089/746] chore(deps): bump lint-staged to 10.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 21c725498..fdfe04a70 100755 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", "jsdoc": "3.6.3", - "lint-staged": "^9.5.0", + "lint-staged": "^10.0.7", "markdown-it-emoji": "^1.4.0", "nyc": "^15.0.0", "pre-commit": "^1.2.2", @@ -129,4 +129,4 @@ }, "pre-commit": "lint-staged", "pre-push": "test" -} \ No newline at end of file +} From 5e2629cd2c599c649eb2cbf2a90244bfe66cdd7f Mon Sep 17 00:00:00 2001 From: Frank Taillandier Date: Thu, 6 Feb 2020 22:18:54 +0100 Subject: [PATCH 090/746] chore: remove git add from lint-staged config Automatically added since v10.0 --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index fdfe04a70..c99ce2185 100755 --- a/package.json +++ b/package.json @@ -70,8 +70,7 @@ }, "lint-staged": { "*.{js,css,md}": [ - "prettier --write", - "git add" + "prettier --write" ] }, "devDependencies": { From 5c46e5d9645922f4b7addd702b5fe0de67e5cb3e Mon Sep 17 00:00:00 2001 From: Frank Taillandier Date: Thu, 6 Feb 2020 22:34:51 +0100 Subject: [PATCH 091/746] chore(deps): minor bump luxon 1.22 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 21c725498..c263308b1 100755 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", "lodash": "^4.17.15", - "luxon": "^1.21.3", + "luxon": "^1.22.0", "markdown-it": "^8.4.2", "minimist": "^1.2.0", "moo": "^0.5.1", @@ -129,4 +129,4 @@ }, "pre-commit": "lint-staged", "pre-push": "test" -} \ No newline at end of file +} From ec4535dd4d623f8debfe41380fa55aad09b89b95 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 09:34:05 -0600 Subject: [PATCH 092/746] Adds new docs issue template --- .github/ISSUE_TEMPLATE/documentation.md | 7 ++++++ .github/ISSUE_TEMPLATE/education.md | 7 ++++++ .github/ISSUE_TEMPLATE/enhancement.md | 19 +++++++++++++++ .github/ISSUE_TEMPLATE/possible-bug.md | 32 +++++++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/documentation.md create mode 100644 .github/ISSUE_TEMPLATE/education.md create mode 100644 .github/ISSUE_TEMPLATE/enhancement.md create mode 100644 .github/ISSUE_TEMPLATE/possible-bug.md diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 000000000..8f2656d82 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,7 @@ +--- +name: The documentation needs improvement +about: A thing that Eleventy does needs to be documented better or is currently documented incorrectly! +title: "" +labels: documentation +assignees: "" +--- diff --git a/.github/ISSUE_TEMPLATE/education.md b/.github/ISSUE_TEMPLATE/education.md new file mode 100644 index 000000000..04aeed1cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/education.md @@ -0,0 +1,7 @@ +--- +name: I have a question about Eleventy +about: e.g. “How do I do this in Eleventy?” or “Can Eleventy do this?” +title: "" +labels: education +assignees: "" +--- diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 000000000..a9928d331 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -0,0 +1,19 @@ +--- +name: I want Eleventy do to this new thing +about: Suggest an idea for this project +title: "" +labels: enhancement +assignees: "" +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/possible-bug.md b/.github/ISSUE_TEMPLATE/possible-bug.md new file mode 100644 index 000000000..071aead03 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/possible-bug.md @@ -0,0 +1,32 @@ +--- +name: I’m having a problem with Eleventy +about: Create a report to help us improve +title: "" +labels: needs-triage +assignees: "" +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment:** + +- OS and Version: [e.g. Windows/Mac/Linux] +- Eleventy Version [via `eleventy --version` or `npx @11ty/eleventy --version`] + +**Additional context** +Add any other context about the problem here. From e707dbcb98df9f328039f14f375323209537b69d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 09:35:02 -0600 Subject: [PATCH 093/746] Missing deletes --- .../i-have-a-question-about-eleventy.md | 7 ---- .../i-m-having-a-problem-with-eleventy.md | 32 ------------------- .../i-want-eleventy-do-to-this-new-thing.md | 19 ----------- 3 files changed, 58 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/i-have-a-question-about-eleventy.md delete mode 100644 .github/ISSUE_TEMPLATE/i-m-having-a-problem-with-eleventy.md delete mode 100644 .github/ISSUE_TEMPLATE/i-want-eleventy-do-to-this-new-thing.md diff --git a/.github/ISSUE_TEMPLATE/i-have-a-question-about-eleventy.md b/.github/ISSUE_TEMPLATE/i-have-a-question-about-eleventy.md deleted file mode 100644 index 04aeed1cb..000000000 --- a/.github/ISSUE_TEMPLATE/i-have-a-question-about-eleventy.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: I have a question about Eleventy -about: e.g. “How do I do this in Eleventy?” or “Can Eleventy do this?” -title: "" -labels: education -assignees: "" ---- diff --git a/.github/ISSUE_TEMPLATE/i-m-having-a-problem-with-eleventy.md b/.github/ISSUE_TEMPLATE/i-m-having-a-problem-with-eleventy.md deleted file mode 100644 index 071aead03..000000000 --- a/.github/ISSUE_TEMPLATE/i-m-having-a-problem-with-eleventy.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: I’m having a problem with Eleventy -about: Create a report to help us improve -title: "" -labels: needs-triage -assignees: "" ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: - -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Environment:** - -- OS and Version: [e.g. Windows/Mac/Linux] -- Eleventy Version [via `eleventy --version` or `npx @11ty/eleventy --version`] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/i-want-eleventy-do-to-this-new-thing.md b/.github/ISSUE_TEMPLATE/i-want-eleventy-do-to-this-new-thing.md deleted file mode 100644 index a9928d331..000000000 --- a/.github/ISSUE_TEMPLATE/i-want-eleventy-do-to-this-new-thing.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: I want Eleventy do to this new thing -about: Suggest an idea for this project -title: "" -labels: enhancement -assignees: "" ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. From fb10b66ec83658f2835e62f95e14c3258b301afc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 09:53:53 -0600 Subject: [PATCH 094/746] Copy improvements to issue templates --- .github/ISSUE_TEMPLATE/documentation.md | 2 +- .github/ISSUE_TEMPLATE/education.md | 2 +- .github/ISSUE_TEMPLATE/enhancement.md | 4 ++-- .github/ISSUE_TEMPLATE/possible-bug.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md index 8f2656d82..cfc948081 100644 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -1,5 +1,5 @@ --- -name: The documentation needs improvement +name: Documentation! about: A thing that Eleventy does needs to be documented better or is currently documented incorrectly! title: "" labels: documentation diff --git a/.github/ISSUE_TEMPLATE/education.md b/.github/ISSUE_TEMPLATE/education.md index 04aeed1cb..649d96224 100644 --- a/.github/ISSUE_TEMPLATE/education.md +++ b/.github/ISSUE_TEMPLATE/education.md @@ -1,6 +1,6 @@ --- name: I have a question about Eleventy -about: e.g. “How do I do this in Eleventy?” or “Can Eleventy do this?” +about: General education e.g. “How do I do this in Eleventy?” or “Can Eleventy do this?” title: "" labels: education assignees: "" diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index a9928d331..bd5757287 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -1,6 +1,6 @@ --- -name: I want Eleventy do to this new thing -about: Suggest an idea for this project +name: Feature request! +about: Enhancements. e.g. “I wish Eleventy did this.” Suggest an idea! title: "" labels: enhancement assignees: "" diff --git a/.github/ISSUE_TEMPLATE/possible-bug.md b/.github/ISSUE_TEMPLATE/possible-bug.md index 071aead03..ef97685e9 100644 --- a/.github/ISSUE_TEMPLATE/possible-bug.md +++ b/.github/ISSUE_TEMPLATE/possible-bug.md @@ -1,6 +1,6 @@ --- -name: I’m having a problem with Eleventy -about: Create a report to help us improve +name: I’m having trouble with Eleventy +about: Have a problem? It might be a bug! Create a report to help us improve. title: "" labels: needs-triage assignees: "" From 94aa574f650a9095cbf516c2ddc23d805b0b5e0e Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Sun, 2 Feb 2020 12:24:05 +0200 Subject: [PATCH 095/746] merge with upstream master --- package.json | 16 +++--- src/Benchmark.js | 6 +++ src/BenchmarkGroup.js | 22 +++++++- src/Engines/Markdown.js | 8 ++- src/Template.js | 2 +- src/TemplateData.js | 56 +++++++++++++++------ src/TemplatePassthrough.js | 11 +++- test/EleventyErrorUtilTest.js | 21 ++++---- test/MergeTest.js | 6 +++ test/TemplateRenderMarkdownPluginTest.js | 47 +++++++++++++++++ test/TemplateRenderNunjucksTest.js | 6 +-- test/UserDataExtensionsTest.js | 19 ++++++- test/stubs-630/_data/mergingGlobalData.js | 4 ++ test/stubs-630/_data/mergingGlobalData.json | 5 ++ test/stubs-630/_data/mergingGlobalData.nosj | 7 +++ test/stubs-630/_data/mergingGlobalData.yaml | 4 ++ 16 files changed, 192 insertions(+), 48 deletions(-) create mode 100644 test/TemplateRenderMarkdownPluginTest.js create mode 100644 test/stubs-630/_data/mergingGlobalData.js create mode 100644 test/stubs-630/_data/mergingGlobalData.json create mode 100644 test/stubs-630/_data/mergingGlobalData.nosj create mode 100644 test/stubs-630/_data/mergingGlobalData.yaml diff --git a/package.json b/package.json index 28b2b6a84..21c725498 100755 --- a/package.json +++ b/package.json @@ -59,14 +59,13 @@ "bugs": "https://github.com/11ty/eleventy/issues", "homepage": "https://www.11ty.dev/", "ava": { + "babel": true, + "failFast": true, "files": [ "./test/*.js" ], - "sources": [ - "./**/.eleventyignore", - "./src/**/*.js", - "./test/stubs/**", - "!./test/stubs/**/_site/**" + "ignoredByWatcher": [ + "./test/stubs/**/*" ] }, "lint-staged": { @@ -77,8 +76,10 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", - "ava": "^2.4.0", + "@ava/babel": "^1.0.0", + "ava": "^3.0.0", "ink-docstrap": "1.3.2", + "js-yaml": "^3.13.1", "jsdoc": "3.6.3", "lint-staged": "^9.5.0", "markdown-it-emoji": "^1.4.0", @@ -90,8 +91,7 @@ "toml": "^3.0.0", "viperhtml": "^2.17.1", "vue": "^2.6.11", - "vue-server-renderer": "^2.6.11", - "js-yaml": "^3.13.1" + "vue-server-renderer": "^2.6.11" }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", diff --git a/src/Benchmark.js b/src/Benchmark.js index 8f03679a1..988e37177 100644 --- a/src/Benchmark.js +++ b/src/Benchmark.js @@ -5,10 +5,12 @@ class Benchmark { reset() { this.timeSpent = 0; + this.timesCalled = 0; this.beforeDates = []; } before() { + this.timesCalled++; this.beforeDates.push(new Date()); } @@ -23,6 +25,10 @@ class Benchmark { } } + getTimesCalled() { + return this.timesCalled; + } + getTotal() { return this.timeSpent; } diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index bc1e786d7..4e34b4721 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -19,7 +19,7 @@ class BenchmarkGroup { } } - // TODO make this async + // TODO use addAsync everywhere instead add(type, callback) { let benchmark = (this.benchmarks[type] = new Benchmark()); @@ -31,6 +31,19 @@ class BenchmarkGroup { }; } + // callback must return a promise + async addAsync(type, callback) { + let benchmark = (this.benchmarks[type] = new Benchmark()); + + benchmark.before(); + // don’t await here. + let promise = callback(); + promise.then(function() { + benchmark.after(); + }); + return promise; + } + setMinimumThresholdMs(minimumThresholdMs) { let val = parseInt(minimumThresholdMs, 10); if (isNaN(val)) { @@ -55,10 +68,15 @@ class BenchmarkGroup { percent > thresholdPercent && totalForBenchmark >= this.minimumThresholdMs ) { + let timesCalledCount = bench.getTimesCalled(); + let timesCalled = ""; + if (timesCalledCount > 1) { + timesCalled = `, called ${timesCalledCount}×`; + } let str = chalk.yellow( `Benchmark (${label}): ${type} took ${bench.getTotal()}ms (${percent.toFixed( 1 - )}%)` + )}%${timesCalled})` ); if (isVerbose) { console.log(str); diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index f064c5f21..89bd5c20d 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -1,6 +1,5 @@ const markdownIt = require("markdown-it"); const TemplateEngine = require("./TemplateEngine"); -const config = require("../Config"); // const debug = require("debug")("Eleventy:Markdown"); class Markdown extends TemplateEngine { @@ -69,7 +68,7 @@ class Markdown extends TemplateEngine { } else { return async function(data) { let preTemplateEngineRender = await fn(data); - let finishedRender = mdlib.render(preTemplateEngineRender); + let finishedRender = mdlib.render(preTemplateEngineRender, data); return finishedRender; }; } @@ -79,9 +78,8 @@ class Markdown extends TemplateEngine { return str; }; } else { - return function() { - // throw away data if preTemplateEngine is falsy - return mdlib.render(str); + return function(data) { + return mdlib.render(str, data); }; } } diff --git a/src/Template.js b/src/Template.js index 6c002d684..2a0ac1000 100644 --- a/src/Template.js +++ b/src/Template.js @@ -602,7 +602,7 @@ class Template extends TemplateContent { async getMappedDate(data) { // should we use Luxon dates everywhere? Right now using built-in `Date` - if ("date" in data) { + if ("date" in data && data.date) { debug( "getMappedDate: using a date in the data for %o of %o", this.inputPath, diff --git a/src/TemplateData.js b/src/TemplateData.js index 48a33f25f..11359d8a5 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -2,6 +2,7 @@ const fs = require("fs-extra"); const fastglob = require("fast-glob"); const parsePath = require("parse-filepath"); const lodashset = require("lodash/set"); +const lodashget = require("lodash/get"); const lodashUniq = require("lodash/uniq"); const merge = require("./Util/Merge"); const TemplateRender = require("./TemplateRender"); @@ -136,29 +137,52 @@ class TemplateData { async getGlobalDataGlob() { let dir = await this.getInputDir(); - let userExtensions = ""; - // creating glob string for user extensions - if (this.hasUserDataExtensions()) { - userExtensions = this.getUserDataExtensions().join("|") + "|"; - } - return [ - this._getGlobalDataGlobByExtension( - dir, - "(" + userExtensions + "json|cjs|js)" - ) - ]; + let extGlob = this.getGlobalDataExtensionPriorities().join("|"); + return [this._getGlobalDataGlobByExtension(dir, "(" + extGlob + ")")]; } getWatchPathCache() { return this.pathCache; } + getGlobalDataExtensionPriorities() { + return this.getUserDataExtensions().concat(["json", "cjs", "js"]); + } + + static calculateExtensionPriority(path, priorities) { + for (let i = 0; i < priorities.length; i++) { + let ext = priorities[i]; + if (path.endsWith(ext)) { + return i; + } + } + return priorities.length; + } + async getGlobalDataFiles() { + let priorities = this.getGlobalDataExtensionPriorities(); + let paths = await fastglob(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, dot: true }); + + // sort paths according to extension priorities + // here we use reverse ordering, because paths with bigger index in array will override the first ones + // example [path/file.json, path/file.js] here js will override json + paths = paths.sort((first, second) => { + let p1 = TemplateData.calculateExtensionPriority(first, priorities); + let p2 = TemplateData.calculateExtensionPriority(second, priorities); + if (p1 < p2) { + return -1; + } + if (p1 > p2) { + return 1; + } + return 0; + }); + this.pathCache = paths; return paths; } @@ -183,17 +207,19 @@ class TemplateData { for (let j = 0, k = files.length; j < k; j++) { let folders = await this.getObjectPathForDataFile(files[j]); + let data = await this.getDataValue(files[j], rawImports); - // TODO maybe merge these two? (if both valid objects) if (dataFileConflicts[folders]) { debugWarn( - `Warning: the key for a global data file (${files[j]}) will overwrite data from an already existing global data file (${dataFileConflicts[folders]})` + `merging global data from ${files[j]} with an already existing global data file (${dataFileConflicts[folders]}). Overriding existing keys` ); + + let oldData = lodashget(globalData, folders); + data = TemplateData.mergeDeep(this.config, oldData, data); } - dataFileConflicts[folders] = files[j]; + dataFileConflicts[folders] = files[j]; debug(`Found global data file ${files[j]} and adding as: ${folders}`); - let data = await this.getDataValue(files[j], rawImports); lodashset(globalData, folders, data); } diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index 1a758b4d0..a5ad3f420 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -4,6 +4,7 @@ const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthrough"); const fastglob = require("fast-glob"); const EleventyBaseError = require("./EleventyBaseError"); +const bench = require("./BenchmarkManager").get("PassthroughCopy"); class TemplatePassthroughError extends EleventyBaseError {} @@ -64,12 +65,20 @@ class TemplatePassthrough { return files; } - copy(src, dest, copyOptions) { + async copy(src, dest, copyOptions) { if ( TemplatePath.stripLeadingDotSlash(dest).includes( TemplatePath.stripLeadingDotSlash(this.outputDir) ) ) { + // Uncomment this if you want to add benchmarking to copy + // (Warning, it seems to be noisy and low value feedback) + // return bench.addAsync(`Copying ${src}`, function() { + // // copy() returns a promise + // return copy(src, dest, copyOptions); + // }); + + // copy() returns a promise return copy(src, dest, copyOptions); } return Promise.reject( diff --git a/test/EleventyErrorUtilTest.js b/test/EleventyErrorUtilTest.js index 9fa210ec1..e13036cbb 100644 --- a/test/EleventyErrorUtilTest.js +++ b/test/EleventyErrorUtilTest.js @@ -22,18 +22,15 @@ test("cleanMessage()", t => { }); test("deconvertErrorToObject() should throw on invalid inputs", t => { - t.throws( - () => deconvertErrorToObject(undefined), - "Could not convert error object from: undefined" - ); - t.throws( - () => deconvertErrorToObject(""), - "Could not convert error object from: " - ); - t.throws( - () => deconvertErrorToObject("Not an error"), - "Could not convert error object from: Not an error" - ); + t.throws(() => deconvertErrorToObject(undefined), { + message: "Could not convert error object from: undefined" + }); + t.throws(() => deconvertErrorToObject(""), { + message: "Could not convert error object from: " + }); + t.throws(() => deconvertErrorToObject("Not an error"), { + message: "Could not convert error object from: Not an error" + }); }); test("deconvertErrorToObject() should return its argument if it does not contain another error", t => { diff --git a/test/MergeTest.js b/test/MergeTest.js index ce58d6a68..ded2bb252 100644 --- a/test/MergeTest.js +++ b/test/MergeTest.js @@ -12,6 +12,12 @@ test("Shallow Merge", t => { t.deepEqual(Merge({ a: [1] }, { a: [2] }), { a: [1, 2] }); }); +test("Doesn’t need to return", t => { + var b = { a: 2 }; + Merge(b, { a: 1 }); + t.deepEqual(b, { a: 1 }); +}); + test("Invalid", t => { t.deepEqual(Merge({}, 1), {}); t.deepEqual(Merge({}, [1]), {}); diff --git a/test/TemplateRenderMarkdownPluginTest.js b/test/TemplateRenderMarkdownPluginTest.js new file mode 100644 index 000000000..74918a3e1 --- /dev/null +++ b/test/TemplateRenderMarkdownPluginTest.js @@ -0,0 +1,47 @@ +import test from "ava"; +import TemplateRender from "../src/TemplateRender"; +import md from "markdown-it"; + +const createTestMarkdownPlugin = () => { + const plugin = md => { + md.core.ruler.after("inline", "replace-link", function(state) { + plugin.environment = state.env; + const link = state.tokens[1].children[0].attrs[0][1]; + state.tokens[1].children[0].attrs[0][1] = `${link}?data=${state.env.some}`; + return false; + }); + }; + plugin.environment = {}; + return plugin; +}; + +test("Markdown Render: with HTML prerender, sends context data to the markdown library", async t => { + let tr = new TemplateRender("md"); + + const plugin = createTestMarkdownPlugin(); + let mdLib = md().use(plugin); + tr.engine.setLibrary(mdLib); + + const data = { some: "data" }; + + let fn = await tr.getCompiledTemplate("[link text](http://link.com)"); + let result = await fn(data); + t.deepEqual(plugin.environment, data); + t.is(result, '

link text

\n'); +}); + +test("Markdown Render: without HTML prerender, sends context data to the markdown library", async t => { + let tr = new TemplateRender("md"); + + const plugin = createTestMarkdownPlugin(); + let mdLib = md().use(plugin); + tr.engine.setLibrary(mdLib); + tr.setHtmlEngine(false); + + const data = { some: "data" }; + + let fn = await tr.getCompiledTemplate("[link text](http://link.com)"); + let result = await fn(data); + t.deepEqual(plugin.environment, data); + t.is(result, '

link text

\n'); +}); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index a9aa8800e..1598afd8e 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -246,15 +246,15 @@ test("Nunjucks Render with getGlobals Issue #567", async t => { t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); -test("Nunjucks Render with getVarByName Filter Issue #567", async t => { +test("Nunjucks Render with getVarFromString Filter Issue #567", async t => { let tr = new TemplateRender("njk"); let env = tr.engine.getEngineLib(); - env.addFilter("getVarByName", function(varName) { + env.addFilter("getVarFromString", function(varName) { return this.getVariables()[varName]; }); let fn = await tr.getCompiledTemplate( - "

{{ 'my-global-name' | getVarByName }}

" + "

{{ 'my-global-name' | getVarFromString }}

" ); t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index d0a15b71d..981c2ffd3 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -72,7 +72,6 @@ test("Global data", async t => { "./test/stubs-630/_data/**/*.(nosj|yaml|json|cjs|js)" ]); - let dataFilePaths = await dataObj.getGlobalDataFiles(); let data = await dataObj.getData(); // JS GLOBAL DATA @@ -92,3 +91,21 @@ test("Global data", async t => { t.is(data.subdir.globalDataSubdir.keyyaml, "yaml"); }); + +test("Global data merging and priority", async t => { + let dataObj = new TemplateData("./test/stubs-630/"); + injectDataExtensions(dataObj); + + let data = await dataObj.getData(); + + // TESTING GLOBAL DATA PRIORITY AND MERGING + t.is(data.mergingGlobalData.datakey1, "js-value1"); + t.is(data.mergingGlobalData.datakey2, "json-value2"); + t.is(data.mergingGlobalData.datakey3, "yaml-value3"); + t.is(data.mergingGlobalData.datakey4, "nosj-value4"); + + t.is(data.mergingGlobalData.jskey, "js"); + t.is(data.mergingGlobalData.jsonkey, "json"); + t.is(data.mergingGlobalData.yamlkey, "yaml"); + t.is(data.mergingGlobalData.nosjkey, "nosj"); +}); diff --git a/test/stubs-630/_data/mergingGlobalData.js b/test/stubs-630/_data/mergingGlobalData.js new file mode 100644 index 000000000..f99fc138d --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.js @@ -0,0 +1,4 @@ +module.exports = { + datakey1: "js-value1", + jskey: "js" +}; diff --git a/test/stubs-630/_data/mergingGlobalData.json b/test/stubs-630/_data/mergingGlobalData.json new file mode 100644 index 000000000..68aa73e11 --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.json @@ -0,0 +1,5 @@ +{ + "datakey1": "json-value1", + "datakey2": "json-value2", + "jsonkey": "json" +} diff --git a/test/stubs-630/_data/mergingGlobalData.nosj b/test/stubs-630/_data/mergingGlobalData.nosj new file mode 100644 index 000000000..6a0152298 --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.nosj @@ -0,0 +1,7 @@ +{ + "datakey1": "nosj-value1", + "datakey2": "nosj-value2", + "datakey3": "nosj-value3", + "datakey4": "nosj-value4", + "nosjkey": "nosj" +} diff --git a/test/stubs-630/_data/mergingGlobalData.yaml b/test/stubs-630/_data/mergingGlobalData.yaml new file mode 100644 index 000000000..916ef7b70 --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.yaml @@ -0,0 +1,4 @@ +datakey1: "yaml-value1" +datakey2: "yaml-value2" +datakey3: "yaml-value3" +yamlkey: "yaml" From 52414b8d9e6cdb65ff765e09f761a48e7193d205 Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Tue, 11 Feb 2020 16:02:15 +0200 Subject: [PATCH 096/746] bump ava/babel version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 21c725498..ef0c57493 100755 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", - "@ava/babel": "^1.0.0", + "@ava/babel": "^1.0.1", "ava": "^3.0.0", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", @@ -129,4 +129,4 @@ }, "pre-commit": "lint-staged", "pre-push": "test" -} \ No newline at end of file +} From 90e5a07bab90c68a53a75aeb1e9c3c8cc7008875 Mon Sep 17 00:00:00 2001 From: gloryofrobots Date: Wed, 12 Feb 2020 01:14:15 +0200 Subject: [PATCH 097/746] tests for cjs order in global data files resolution --- test/TemplateDataTest.js | 2 +- test/UserDataExtensionsTest.js | 27 +++++++++++-------- test/stubs-630/_data/globalData1.cjs | 3 +++ .../{globalData1.json => globalData2.json} | 2 +- .../{globalData2.yaml => globalData3.yaml} | 2 +- .../{globalData3.nosj => globalData4.nosj} | 2 +- test/stubs-630/_data/mergingGlobalData.cjs | 5 ++++ test/stubs-630/_data/mergingGlobalData.js | 2 +- test/stubs-630/_data/mergingGlobalData.json | 1 + test/stubs-630/_data/mergingGlobalData.nosj | 1 + test/stubs-630/_data/mergingGlobalData.yaml | 1 + test/stubs/_data/globalDataFnCJS.cjs | 2 +- 12 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 test/stubs-630/_data/globalData1.cjs rename test/stubs-630/_data/{globalData1.json => globalData2.json} (58%) rename test/stubs-630/_data/{globalData2.yaml => globalData3.yaml} (59%) rename test/stubs-630/_data/{globalData3.nosj => globalData4.nosj} (58%) create mode 100644 test/stubs-630/_data/mergingGlobalData.cjs diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 490ec768a..571795eb4 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -179,7 +179,7 @@ test("getAllGlobalData() with common js function data file", async t => { ); t.truthy(data.globalDataFnCJS); - t.is(data.globalDataFnCJS.datakeyfromcjsfn, "common-js-howdy"); + t.is(data.globalDataFnCJS.datakeyfromcjsfn, "common-cjs-howdy"); }); test("getDataValue() without a dataTemplateEngine", async t => { diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index 981c2ffd3..78464534a 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -16,12 +16,12 @@ test("Local data", async t => { let data = await dataObj.getData(); // YAML GLOBAL DATA - t.is(data.globalData2.datakey1, "datavalue2"); - t.is(data.globalData2.datakey2, "@11ty/eleventy--yaml"); + t.is(data.globalData3.datakey1, "datavalue3"); + t.is(data.globalData3.datakey2, "@11ty/eleventy--yaml"); // NOSJ (JSON) GLOBAL DATA - t.is(data.globalData3.datakey1, "datavalue3"); - t.is(data.globalData3.datakey2, "@11ty/eleventy--nosj"); + t.is(data.globalData4.datakey1, "datavalue4"); + t.is(data.globalData4.datakey2, "@11ty/eleventy--nosj"); let withLocalData = await dataObj.getLocalData( "./test/stubs-630/component-yaml/component.njk" @@ -77,17 +77,20 @@ test("Global data", async t => { // JS GLOBAL DATA t.is(data.globalData0.datakey1, "datavalue0"); - // JSON GLOBAL DATA + // CJS GLOBAL DATA t.is(data.globalData1.datakey1, "datavalue1"); - t.is(data.globalData1.datakey2, "@11ty/eleventy--json"); - // YAML GLOBAL DATA + // JSON GLOBAL DATA t.is(data.globalData2.datakey1, "datavalue2"); - t.is(data.globalData2.datakey2, "@11ty/eleventy--yaml"); + t.is(data.globalData2.datakey2, "@11ty/eleventy--json"); - // NOSJ (JSON) GLOBAL DATA + // YAML GLOBAL DATA t.is(data.globalData3.datakey1, "datavalue3"); - t.is(data.globalData3.datakey2, "@11ty/eleventy--nosj"); + t.is(data.globalData3.datakey2, "@11ty/eleventy--yaml"); + + // NOSJ (JSON) GLOBAL DATA + t.is(data.globalData4.datakey1, "datavalue4"); + t.is(data.globalData4.datakey2, "@11ty/eleventy--nosj"); t.is(data.subdir.globalDataSubdir.keyyaml, "yaml"); }); @@ -99,12 +102,14 @@ test("Global data merging and priority", async t => { let data = await dataObj.getData(); // TESTING GLOBAL DATA PRIORITY AND MERGING - t.is(data.mergingGlobalData.datakey1, "js-value1"); + t.is(data.mergingGlobalData.datakey0, "js-value0"); + t.is(data.mergingGlobalData.datakey1, "cjs-value1"); t.is(data.mergingGlobalData.datakey2, "json-value2"); t.is(data.mergingGlobalData.datakey3, "yaml-value3"); t.is(data.mergingGlobalData.datakey4, "nosj-value4"); t.is(data.mergingGlobalData.jskey, "js"); + t.is(data.mergingGlobalData.cjskey, "cjs"); t.is(data.mergingGlobalData.jsonkey, "json"); t.is(data.mergingGlobalData.yamlkey, "yaml"); t.is(data.mergingGlobalData.nosjkey, "nosj"); diff --git a/test/stubs-630/_data/globalData1.cjs b/test/stubs-630/_data/globalData1.cjs new file mode 100644 index 000000000..891d75752 --- /dev/null +++ b/test/stubs-630/_data/globalData1.cjs @@ -0,0 +1,3 @@ +module.exports = { + datakey1: "datavalue1" +}; diff --git a/test/stubs-630/_data/globalData1.json b/test/stubs-630/_data/globalData2.json similarity index 58% rename from test/stubs-630/_data/globalData1.json rename to test/stubs-630/_data/globalData2.json index 5f02feff3..52ad7edd3 100644 --- a/test/stubs-630/_data/globalData1.json +++ b/test/stubs-630/_data/globalData2.json @@ -1,4 +1,4 @@ { - "datakey1": "datavalue1", + "datakey1": "datavalue2", "datakey2": "{{pkg.name}}--json" } diff --git a/test/stubs-630/_data/globalData2.yaml b/test/stubs-630/_data/globalData3.yaml similarity index 59% rename from test/stubs-630/_data/globalData2.yaml rename to test/stubs-630/_data/globalData3.yaml index 9a852bfa8..6fad83308 100644 --- a/test/stubs-630/_data/globalData2.yaml +++ b/test/stubs-630/_data/globalData3.yaml @@ -1,2 +1,2 @@ -datakey1: datavalue2 +datakey1: datavalue3 datakey2: "{{pkg.name}}--yaml" diff --git a/test/stubs-630/_data/globalData3.nosj b/test/stubs-630/_data/globalData4.nosj similarity index 58% rename from test/stubs-630/_data/globalData3.nosj rename to test/stubs-630/_data/globalData4.nosj index 3f01a07ea..6bbdca34a 100644 --- a/test/stubs-630/_data/globalData3.nosj +++ b/test/stubs-630/_data/globalData4.nosj @@ -1,4 +1,4 @@ { - "datakey1": "datavalue3", + "datakey1": "datavalue4", "datakey2": "{{pkg.name}}--nosj" } diff --git a/test/stubs-630/_data/mergingGlobalData.cjs b/test/stubs-630/_data/mergingGlobalData.cjs new file mode 100644 index 000000000..a6b14c8a1 --- /dev/null +++ b/test/stubs-630/_data/mergingGlobalData.cjs @@ -0,0 +1,5 @@ +module.exports = { + datakey0: "cjs-value1", + datakey1: "cjs-value1", + cjskey: "cjs" +}; diff --git a/test/stubs-630/_data/mergingGlobalData.js b/test/stubs-630/_data/mergingGlobalData.js index f99fc138d..16712f966 100644 --- a/test/stubs-630/_data/mergingGlobalData.js +++ b/test/stubs-630/_data/mergingGlobalData.js @@ -1,4 +1,4 @@ module.exports = { - datakey1: "js-value1", + datakey0: "js-value0", jskey: "js" }; diff --git a/test/stubs-630/_data/mergingGlobalData.json b/test/stubs-630/_data/mergingGlobalData.json index 68aa73e11..8045904a0 100644 --- a/test/stubs-630/_data/mergingGlobalData.json +++ b/test/stubs-630/_data/mergingGlobalData.json @@ -1,4 +1,5 @@ { + "datakey0": "json-value1", "datakey1": "json-value1", "datakey2": "json-value2", "jsonkey": "json" diff --git a/test/stubs-630/_data/mergingGlobalData.nosj b/test/stubs-630/_data/mergingGlobalData.nosj index 6a0152298..3b853f51f 100644 --- a/test/stubs-630/_data/mergingGlobalData.nosj +++ b/test/stubs-630/_data/mergingGlobalData.nosj @@ -1,4 +1,5 @@ { + "datakey0": "nosj-value1", "datakey1": "nosj-value1", "datakey2": "nosj-value2", "datakey3": "nosj-value3", diff --git a/test/stubs-630/_data/mergingGlobalData.yaml b/test/stubs-630/_data/mergingGlobalData.yaml index 916ef7b70..046506a89 100644 --- a/test/stubs-630/_data/mergingGlobalData.yaml +++ b/test/stubs-630/_data/mergingGlobalData.yaml @@ -1,3 +1,4 @@ +datakey0: "yaml-value1" datakey1: "yaml-value1" datakey2: "yaml-value2" datakey3: "yaml-value3" diff --git a/test/stubs/_data/globalDataFnCJS.cjs b/test/stubs/_data/globalDataFnCJS.cjs index 52e9b3087..e6835df91 100644 --- a/test/stubs/_data/globalDataFnCJS.cjs +++ b/test/stubs/_data/globalDataFnCJS.cjs @@ -2,6 +2,6 @@ const dep1 = require("../deps/dep1"); module.exports = function() { return { - datakeyfromcjsfn: "common-js-howdy" + datakeyfromcjsfn: "common-cjs-howdy" }; }; From 46059ddb59a4ad17cdecdcadd2133b43e331a35a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 21:21:05 -0600 Subject: [PATCH 098/746] Adds 3 new filters: log, getPreviousCollectionItem, getNextCollectionItem. --- config.js | 4 ++++ src/TemplateCollection.js | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config.js b/config.js index 8f8374b4e..0703623ff 100644 --- a/config.js +++ b/config.js @@ -1,9 +1,13 @@ const urlFilter = require("./src/Filters/Url"); const slugFilter = require("./src/Filters/Slug"); +const getCollectionItem = require("./src/Filters/GetCollectionItem"); module.exports = function(config) { config.addFilter("slug", slugFilter); config.addFilter("url", urlFilter); + config.addFilter("log", console.log); + config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1)); + config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1)); return { templateFormats: [ diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js index dfc5992ce..b2d3b665d 100644 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -3,10 +3,6 @@ const Sortable = require("./Util/Sortable"); const TemplatePath = require("./TemplatePath"); class TemplateCollection extends Sortable { - constructor() { - super(); - } - // right now this is only used by the tests async _testAddTemplate(template) { let data = await template.getData(); From 3cdbaa4ee9c4a9945e4f5e37cafc31676b75987f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 21:34:44 -0600 Subject: [PATCH 099/746] Adds getNextCollectionItem and getPreviousCollectionItem filters and tests. --- config.js | 8 ++++++-- src/Filters/GetCollectionItem.js | 17 +++++++++++++++++ test/GetCollectionItemTest.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 src/Filters/GetCollectionItem.js create mode 100644 test/GetCollectionItemTest.js diff --git a/config.js b/config.js index 0703623ff..81938d67d 100644 --- a/config.js +++ b/config.js @@ -6,8 +6,12 @@ module.exports = function(config) { config.addFilter("slug", slugFilter); config.addFilter("url", urlFilter); config.addFilter("log", console.log); - config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1)); - config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1)); + config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => + getCollectionItem(collection, page, -1) + ); + config.addLiquidFilter("getNextCollectionItem", (collection, page) => + getCollectionItem(collection, page, 1) + ); return { templateFormats: [ diff --git a/src/Filters/GetCollectionItem.js b/src/Filters/GetCollectionItem.js new file mode 100644 index 000000000..f1ad87679 --- /dev/null +++ b/src/Filters/GetCollectionItem.js @@ -0,0 +1,17 @@ +module.exports = function getCollectionItem(collection, page, modifier = 0) { + let j = 0; + let index; + for(let item of collection) { + if(item.inputPath === page.inputPath && item.outputPath === page.outputPath) { + index = j; + break; + } + j++; + } + + if(index !== undefined && collection && collection.length) { + if( index + modifier >= 0 && index + modifier < collection.length ) { + return collection[index + modifier]; + } + } +}; \ No newline at end of file diff --git a/test/GetCollectionItemTest.js b/test/GetCollectionItemTest.js new file mode 100644 index 000000000..182ba130b --- /dev/null +++ b/test/GetCollectionItemTest.js @@ -0,0 +1,30 @@ +import test from "ava"; +import getCollectionItem from "../src/Filters/GetCollectionItem"; + +test("getCollectionItem", t => { + let first = { + inputPath: "hello.md", + outputPath: "/hello/" + }; + let second = { + inputPath: "hello2.md", + outputPath: "/hello2/" + }; + let third = { + inputPath: "hello3.md", + outputPath: "/hello3/" + }; + let collections = [first, second, third]; + + t.deepEqual(getCollectionItem(collections, first), first); + t.deepEqual(getCollectionItem(collections, second), second); + t.deepEqual(getCollectionItem(collections, third), third); + + t.deepEqual(getCollectionItem(collections, first, -1), undefined); + t.deepEqual(getCollectionItem(collections, second, -1), first); + t.deepEqual(getCollectionItem(collections, third, -1), second); + + t.deepEqual(getCollectionItem(collections, first, 1), second); + t.deepEqual(getCollectionItem(collections, second, 1), third); + t.deepEqual(getCollectionItem(collections, third, 1), undefined); +}); From e61053f4cff7aa806085043bee3a7cb51a1d4bf6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 21:35:07 -0600 Subject: [PATCH 100/746] Prettier changes. --- src/Filters/GetCollectionItem.js | 33 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/Filters/GetCollectionItem.js b/src/Filters/GetCollectionItem.js index f1ad87679..e7626ae66 100644 --- a/src/Filters/GetCollectionItem.js +++ b/src/Filters/GetCollectionItem.js @@ -1,17 +1,20 @@ module.exports = function getCollectionItem(collection, page, modifier = 0) { - let j = 0; - let index; - for(let item of collection) { - if(item.inputPath === page.inputPath && item.outputPath === page.outputPath) { - index = j; - break; - } - j++; - } + let j = 0; + let index; + for (let item of collection) { + if ( + item.inputPath === page.inputPath && + item.outputPath === page.outputPath + ) { + index = j; + break; + } + j++; + } - if(index !== undefined && collection && collection.length) { - if( index + modifier >= 0 && index + modifier < collection.length ) { - return collection[index + modifier]; - } - } -}; \ No newline at end of file + if (index !== undefined && collection && collection.length) { + if (index + modifier >= 0 && index + modifier < collection.length) { + return collection[index + modifier]; + } + } +}; From 38e5ba5e14db700b71d084b5ef9eb3cda7e92554 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 21:36:27 -0600 Subject: [PATCH 101/746] CI From 8b755ed5f48b4c8bfdb5c9631cbaa66d42ec78c1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 21:36:56 -0600 Subject: [PATCH 102/746] CI From d5be63fdbc8c4310e4baaaecd5641e66d2be4b48 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Feb 2020 22:09:11 -0600 Subject: [PATCH 103/746] Make sure Nunjucks `set = ` works with filters. --- test/TemplateRenderNunjucksTest.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 1598afd8e..1e490ef3c 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -156,6 +156,20 @@ test("Nunjucks Async Filter", async t => { t.is((await fn()).trim(), "HItest"); }); +test("Nunjucks Render set with a filter", async t => { + let tr = new TemplateRender("njk", "test/stubs"); + let engine = tr.engine; + engine.addFilters({ + uppercase: function(str) { + return str.toUpperCase(); + } + }); + let fn = await tr.getCompiledTemplate( + `{% set test = "hi" | uppercase %}{{ test }}` + ); + t.is((await fn()).trim(), `HI`); +}); + test("Nunjucks Render Include a JS file (Issue 398)", async t => { let tr = new TemplateRender("njk", "test/stubs"); let engine = tr.engine; From 47c13a832e7e00064935255f0981faf77d114547 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 07:31:16 -0600 Subject: [PATCH 104/746] CI From 101e3c85c9a5e6837c7ef9860057ead64d2e3f75 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 07:32:12 -0600 Subject: [PATCH 105/746] Whitespace commit --- config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/config.js b/config.js index 81938d67d..5f01afa57 100644 --- a/config.js +++ b/config.js @@ -6,6 +6,7 @@ module.exports = function(config) { config.addFilter("slug", slugFilter); config.addFilter("url", urlFilter); config.addFilter("log", console.log); + config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); From 96842ce3cd16070cf9d079fd9a727bbdaa1ca8df Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 07:35:14 -0600 Subject: [PATCH 106/746] Git hook issue --- config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/config.js b/config.js index 5f01afa57..06a6a1bc3 100644 --- a/config.js +++ b/config.js @@ -10,6 +10,7 @@ module.exports = function(config) { config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); + config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1) ); From 65e1674d91ec840831f86f9cea247c2f41ca3a80 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 07:41:04 -0600 Subject: [PATCH 107/746] Git hook issue --- config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/config.js b/config.js index 06a6a1bc3..5f01afa57 100644 --- a/config.js +++ b/config.js @@ -10,7 +10,6 @@ module.exports = function(config) { config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); - config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1) ); From 5789d7fac6eb1539af5469c43d3508360d7f700e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 07:44:15 -0600 Subject: [PATCH 108/746] Git hook issue --- config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/config.js b/config.js index 5f01afa57..06a6a1bc3 100644 --- a/config.js +++ b/config.js @@ -10,6 +10,7 @@ module.exports = function(config) { config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); + config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1) ); From f1440046f3ae0c378a79c398541b97258c03bce4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 07:52:32 -0600 Subject: [PATCH 109/746] Trying out husky again. --- package.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e833ca300..0084a7985 100755 --- a/package.json +++ b/package.json @@ -77,14 +77,13 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.0", "ava": "^3.0.0", + "husky": "^4.2.2", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", "jsdoc": "3.6.3", "lint-staged": "^10.0.7", "markdown-it-emoji": "^1.4.0", "nyc": "^15.0.0", - "pre-commit": "^1.2.2", - "pre-push": "^0.1.1", "prettier": "^1.19.1", "rimraf": "^3.0.0", "toml": "^3.0.0", @@ -126,6 +125,10 @@ "time-require": "^0.1.2", "valid-url": "^1.0.9" }, - "pre-commit": "lint-staged", - "pre-push": "test" + "husky": { + "hooks": { + "pre-commit": "lint-staged", + "pre-push": "test" + } + } } From 07e6bb94a8b41c3d3c36c1cd94394751c50f0ca8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 07:55:27 -0600 Subject: [PATCH 110/746] Git hooks --- config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/config.js b/config.js index 06a6a1bc3..5f01afa57 100644 --- a/config.js +++ b/config.js @@ -10,7 +10,6 @@ module.exports = function(config) { config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); - config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1) ); From 4cffd6e6302c6ec7c086031e799fd0b0860d14a0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 08:04:40 -0600 Subject: [PATCH 111/746] Git hooks --- config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/config.js b/config.js index 5f01afa57..06a6a1bc3 100644 --- a/config.js +++ b/config.js @@ -10,6 +10,7 @@ module.exports = function(config) { config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); + config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1) ); From 81ccea874d6d3d9fe7b75ee913471a1697af27c5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 08:09:52 -0600 Subject: [PATCH 112/746] Git hooks --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0084a7985..ecb8767a0 100755 --- a/package.json +++ b/package.json @@ -127,8 +127,8 @@ }, "husky": { "hooks": { - "pre-commit": "lint-staged", - "pre-push": "test" + "pre-commit": "npm run lint-staged", + "pre-push": "npm run test" } } } From d34f1614fe338f78fb7b2e20c8b7fdff037b4834 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 08:22:04 -0600 Subject: [PATCH 113/746] One more for #819 --- config.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.js b/config.js index 06a6a1bc3..bbfdd20c0 100644 --- a/config.js +++ b/config.js @@ -7,10 +7,12 @@ module.exports = function(config) { config.addFilter("url", urlFilter); config.addFilter("log", console.log); + config.addLiquidFilter("getCollectionItem", (collection, page) => + getCollectionItem(collection, page) + ); config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); - config.addLiquidFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1) ); From 37ff4895403494edcffec97760449090f5a2e8db Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Feb 2020 22:12:22 -0600 Subject: [PATCH 114/746] Duplicated code path --- src/Template.js | 12 +++--------- src/TemplateWriter.js | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Template.js b/src/Template.js index 2a0ac1000..8c285c49e 100644 --- a/src/Template.js +++ b/src/Template.js @@ -535,18 +535,12 @@ class Template extends TemplateContent { this.config ); content = await layout.render(page.data, page.templateContent); - await this.runLinters(content, page.inputPath, page.outputPath); - content = await this.runTransforms(content, page.outputPath); // pass in page.inputPath? - return content; } else { content = page.templateContent; - await this.runLinters( - page.templateContent, - page.inputPath, - page.outputPath - ); - content = await this.runTransforms(content, page.outputPath); // pass in page.inputPath? } + + await this.runLinters(content, page.inputPath, page.outputPath); + content = await this.runTransforms(content, page.outputPath); // pass in page.inputPath? return content; } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index de06b4144..db51e8119 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -138,7 +138,7 @@ class TemplateWriter { async _writeTemplate(mapEntry) { let tmpl = mapEntry.template; - // we don’t re-use the map templateContent because it doesn’t include layouts + return tmpl.writeMapEntry(mapEntry).then(() => { this.skippedCount += tmpl.getSkippedCount(); this.writeCount += tmpl.getWriteCount(); From 63ac0bb637783c6d39fc23db991049fdba42a1bf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 14 Feb 2020 10:27:02 -0600 Subject: [PATCH 115/746] Adds skipped test for #934 --- src/Engines/JavaScript.js | 9 ++++++++- test/TemplateRenderJavaScriptTest.js | 16 ++++++++++++++++ test/stubs/function-filter-arrow.11ty.js | 3 +++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 test/stubs/function-filter-arrow.11ty.js diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index ec676cab0..9336e3538 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -34,12 +34,18 @@ class JavaScript extends TemplateEngine { mod.prototype && ("data" in mod.prototype || "render" in mod.prototype) ) { + // render function is optional if (!("render" in mod.prototype)) { mod.prototype.render = noop; } return new mod(); } else { - return { render: mod }; + // let fn = function() {}; + // fn.prototype.render = mod; + // return new fn(); + return { + render: mod + }; } } else if ("data" in mod || "render" in mod) { if (!("render" in mod)) { @@ -103,6 +109,7 @@ class JavaScript extends TemplateEngine { let inst; if (str) { // When str has a value, it's being used for permalinks in data + // and maybe not be a str (could be any valid *.11ty.js) inst = this._getInstance(str); } else { // For normal templates, str will be falsy. diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index a212d0688..024620024 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -181,6 +181,22 @@ test("JS Render with a function", async t => { t.is(await fn({ name: "Bill" }), "

BILLT9000

"); }); +// This doesn’t work +test.skip("JS Render with an arrow function and javascript function", async t => { + let tr = new TemplateRender("./test/stubs/function-filter-arrow.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(val) { + return new String(val).toUpperCase(); + } + } + }; + + let fn = await tr.getCompiledTemplate(); + t.is(await fn({ name: "Zach" }), "

ZACH

"); + t.is(await fn({ name: "Bill" }), "

BILL

"); +}); + test("JS Render with a function and async filter", async t => { let tr = new TemplateRender("./test/stubs/function-async-filter.11ty.js"); tr.config = { diff --git a/test/stubs/function-filter-arrow.11ty.js b/test/stubs/function-filter-arrow.11ty.js new file mode 100644 index 000000000..d9adb2f05 --- /dev/null +++ b/test/stubs/function-filter-arrow.11ty.js @@ -0,0 +1,3 @@ +module.exports = ({ name }) => { + return `

${this.upper(name)}

`; +}; From 7a5dad7199d21e97bfb70453794d021ccaa8a787 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 14 Feb 2020 16:12:05 -0600 Subject: [PATCH 116/746] Code cleanup (duplicate code paths) --- src/TemplateData.js | 61 +++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 670e7f427..502b9ca6a 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -384,6 +384,20 @@ class TemplateData { paths.push(curpath + "." + extension); } } + _addBaseToPaths(paths, base, extensions) { + let dataSuffix = this.config.jsDataFileSuffix; + + // data suffix + paths.push(base + dataSuffix + ".js"); + paths.push(base + dataSuffix + ".json"); + + // inject user extensions + this._pushExtensionsToPaths(paths, base + dataSuffix, extensions); + + // top level + paths.push(base + ".json"); + this._pushExtensionsToPaths(paths, base, extensions); + } async getLocalDataPaths(templatePath) { let paths = []; @@ -406,55 +420,20 @@ class TemplateData { let dataSuffix = this.config.jsDataFileSuffix; debug("Using %o to find data files.", dataSuffix); - // data suffix - paths.push(filePathNoExt + dataSuffix + ".js"); - paths.push(filePathNoExt + dataSuffix + ".json"); - // inject user extensions - this._pushExtensionsToPaths( - paths, - filePathNoExt + dataSuffix, - userExtensions - ); - - // top level - paths.push(filePathNoExt + ".json"); - this._pushExtensionsToPaths(paths, filePathNoExt, userExtensions); + this._addBaseToPaths(paths, filePathNoExt, userExtensions); let allDirs = TemplatePath.getAllDirs(parsed.dir); + debugDev("allDirs: %o", allDirs); for (let dir of allDirs) { let lastDir = TemplatePath.getLastPathSegment(dir); let dirPathNoExt = dir + "/" + lastDir; - if (!inputDir) { - // data suffix - paths.push(dirPathNoExt + dataSuffix + ".js"); - paths.push(dirPathNoExt + dataSuffix + ".json"); - this._pushExtensionsToPaths( - paths, - dirPathNoExt + dataSuffix, - userExtensions - ); - - // top level - paths.push(dirPathNoExt + ".json"); - this._pushExtensionsToPaths(paths, dirPathNoExt, userExtensions); - } else { + if (inputDir) { debugDev("dirStr: %o; inputDir: %o", dir, inputDir); - if (dir.indexOf(inputDir) === 0 && dir !== inputDir) { - // data suffix - paths.push(dirPathNoExt + dataSuffix + ".js"); - paths.push(dirPathNoExt + dataSuffix + ".json"); - this._pushExtensionsToPaths( - paths, - dirPathNoExt + dataSuffix, - userExtensions - ); - - // top level - paths.push(dirPathNoExt + ".json"); - this._pushExtensionsToPaths(paths, dirPathNoExt, userExtensions); - } + } + if (!inputDir || (dir.indexOf(inputDir) === 0 && dir !== inputDir)) { + this._addBaseToPaths(paths, dirPathNoExt, userExtensions); } } } From e15f4d60d73813571576ed69df583e766f6a620e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 14 Feb 2020 16:48:57 -0600 Subject: [PATCH 117/746] Fixes #935. --- src/TemplateData.js | 11 +++++++++++ test/TemplateDataTest.js | 15 +++++++++++++++ test/TemplateTest.js | 12 ++++++++++++ test/UserDataExtensionsTest.js | 7 +++++++ 4 files changed, 45 insertions(+) diff --git a/src/TemplateData.js b/src/TemplateData.js index 502b9ca6a..d5500334f 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -436,6 +436,17 @@ class TemplateData { this._addBaseToPaths(paths, dirPathNoExt, userExtensions); } } + + // 0.11.0+ include root input dir files + // if using `docs/` as input dir, looks for docs/docs.json et al + if (inputDir) { + let lastInputDir = TemplatePath.addLeadingDotSlash( + TemplatePath.join(inputDir, TemplatePath.getLastPathSegment(inputDir)) + ); + if (lastInputDir !== "./") { + this._addBaseToPaths(paths, lastInputDir, userExtensions); + } + } } debug("getLocalDataPaths(%o): %o", templatePath, paths); diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 9350c062f..baa3aca06 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -198,6 +198,9 @@ test("getLocalDataPaths", async t => { ); t.deepEqual(paths, [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.js" @@ -230,6 +233,9 @@ test("getLocalDataPaths with an 11ty js template", async t => { ); t.deepEqual(paths, [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.js" @@ -243,6 +249,9 @@ test("getLocalDataPaths with inputDir passed in (trailing slash)", async t => { ); t.deepEqual(paths, [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.js" @@ -256,6 +265,9 @@ test("getLocalDataPaths with inputDir passed in (no trailing slash)", async t => ); t.deepEqual(paths, [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.js" @@ -269,6 +281,9 @@ test("getLocalDataPaths with inputDir passed in (no leading slash)", async t => ); t.deepEqual(paths, [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.js" diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 6970f878d..7f7be1495 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -441,6 +441,9 @@ test("Local template data file import (without a global data json)", async t => let data = await tmpl.getData(); t.deepEqual(await dataObj.getLocalDataPaths(tmpl.getInputPath()), [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.js" @@ -461,6 +464,9 @@ test("Local template data file import (two subdirectories deep)", async t => { ); t.deepEqual(await dataObj.getLocalDataPaths(tmpl.getInputPath()), [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/firstdir/firstdir.json", "./test/stubs/firstdir/firstdir.11tydata.json", "./test/stubs/firstdir/firstdir.11tydata.js", @@ -486,6 +492,9 @@ test("Posts inherits local JSON, layouts", async t => { let localDataPaths = await dataObj.getLocalDataPaths(tmpl.getInputPath()); t.deepEqual(localDataPaths, [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/posts/posts.json", "./test/stubs/posts/posts.11tydata.json", "./test/stubs/posts/posts.11tydata.js", @@ -521,6 +530,9 @@ test("Template and folder name are the same, make sure data imports work ok", as let localDataPaths = await dataObj.getLocalDataPaths(tmpl.getInputPath()); t.deepEqual(localDataPaths, [ + "./test/stubs/stubs.json", + "./test/stubs/stubs.11tydata.json", + "./test/stubs/stubs.11tydata.js", "./test/stubs/posts/posts.json", "./test/stubs/posts/posts.11tydata.json", "./test/stubs/posts/posts.11tydata.js" diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index cffb98b5c..3eb24863b 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -44,6 +44,13 @@ test("Local files", async t => { "./test/stubs-630/component-yaml/component.njk" ); t.deepEqual(files, [ + "./test/stubs-630/stubs-630.yaml", + "./test/stubs-630/stubs-630.nosj", + "./test/stubs-630/stubs-630.json", + "./test/stubs-630/stubs-630.11tydata.yaml", + "./test/stubs-630/stubs-630.11tydata.nosj", + "./test/stubs-630/stubs-630.11tydata.json", + "./test/stubs-630/stubs-630.11tydata.js", "./test/stubs-630/component-yaml/component-yaml.yaml", "./test/stubs-630/component-yaml/component-yaml.nosj", "./test/stubs-630/component-yaml/component-yaml.json", From 5f57ce0b597c27b765cd05b5e70ef3f774ab3739 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 16 Feb 2020 13:35:03 -0600 Subject: [PATCH 118/746] Look into cjs files to find watch target dependencies --- src/EleventyWatchTargets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index 3513edbac..0079a3213 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -90,7 +90,7 @@ class EleventyWatchTargets { getJavaScriptDependenciesFromList(files = []) { let depSet = new Set(); files - .filter(file => file.endsWith(".js")) // TODO does this need to work with aliasing? what other JS extensions will have deps? + .filter(file => file.endsWith(".js") || file.endsWith(".cjs")) // TODO does this need to work with aliasing? what other JS extensions will have deps? .forEach(file => { dependencyTree(file, { allowNotFound: true }) .map(dependency => { From 0bd6576d0374400e9b6ea10d409f0fad801a4832 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 16 Feb 2020 13:46:37 -0600 Subject: [PATCH 119/746] Get a layout chain from a template. Work preparing for the incremental data graph. Also fixes #915. --- src/Eleventy.js | 2 +- src/Template.js | 52 +++++++++-------- src/TemplateData.js | 16 +++--- src/TemplateLayout.js | 12 +++- src/TemplateLayoutPathResolver.js | 4 +- src/TemplateMap.js | 2 +- src/TemplateWriter.js | 6 +- test/TemplateLayoutTest.js | 25 ++++++++- test/TemplateMapTest.js | 56 +++++++++---------- test/TemplateTest.js | 25 +++++++++ test/TemplateWriterTest.js | 38 ++++++------- .../layout-data-files/_includes/base.njk | 3 + .../layout-data-files/test.11tydata.js | 3 + .../layout-data-files/test.njk | 3 + .../layout-chain/_includes/base.njk | 3 + .../layout-chain/_includes/parent.njk | 0 test/stubs-incremental/layout-chain/test.njk | 3 + 17 files changed, 165 insertions(+), 88 deletions(-) create mode 100644 test/stubs-data-cascade/layout-data-files/_includes/base.njk create mode 100644 test/stubs-data-cascade/layout-data-files/test.11tydata.js create mode 100644 test/stubs-data-cascade/layout-data-files/test.njk create mode 100644 test/stubs-incremental/layout-chain/_includes/base.njk create mode 100644 test/stubs-incremental/layout-chain/_includes/parent.njk create mode 100644 test/stubs-incremental/layout-chain/test.njk diff --git a/src/Eleventy.js b/src/Eleventy.js index bc0de196c..adcbb4b85 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -412,7 +412,7 @@ Arguments: * * @private * @method - * @param {String} path - Watch this file. + * @param {String} path - File that triggered a re-run (added or modified) */ async _watch(path) { if (path) { diff --git a/src/Template.js b/src/Template.js index 8c285c49e..7a8a6e16c 100644 --- a/src/Template.js +++ b/src/Template.js @@ -72,6 +72,26 @@ class Template extends TemplateContent { return TemplatePath.stripLeadingSubPath(this.parsed.dir, this.inputDir); } + getLayout(layoutKey) { + if(!this._layout || layoutKey !== this._layoutKey) { + this._layoutKey = layoutKey; + this._layout = TemplateLayout.getTemplate( + layoutKey, + this.getInputDir(), + this.config + ); + } + return this._layout; + } + + async getLayoutChain() { + if(!this._layout) { + await this.getData(); + } + + return this._layout.getLayoutChain(); + } + get baseFile() { return (this._extensionMap || EleventyExtensionMap).removeTemplateExtension( this.parsed.base @@ -189,11 +209,7 @@ class Template extends TemplateContent { async _testGetAllLayoutFrontMatterData() { let frontMatterData = await this.getFrontMatterData(); if (frontMatterData[this.config.keys.layout]) { - let layout = TemplateLayout.getTemplate( - frontMatterData[this.config.keys.layout], - this.getInputDir(), - this.config - ); + let layout = this.getLayout(frontMatterData[this.config.keys.layout]); return await layout.getData(); } return {}; @@ -210,17 +226,14 @@ class Template extends TemplateContent { } let frontMatterData = await this.getFrontMatterData(); - let foundLayout = + let layoutKey = frontMatterData[this.config.keys.layout] || localData[this.config.keys.layout]; let mergedLayoutData = {}; - if (foundLayout) { - let layout = TemplateLayout.getTemplate( - foundLayout, - this.getInputDir(), - this.config - ); + if (layoutKey) { + let layout = this.getLayout(layoutKey); + mergedLayoutData = await layout.getData(); debugDev( "%o getData() get merged layout chain front matter", @@ -231,8 +244,8 @@ class Template extends TemplateContent { let mergedData = TemplateData.mergeDeep( this.config, {}, - mergedLayoutData, localData, + mergedLayoutData, frontMatterData ); mergedData = await this.addPageDate(mergedData); @@ -319,11 +332,7 @@ class Template extends TemplateContent { async renderLayout(tmpl, tmplData) { let layoutKey = tmplData[tmpl.config.keys.layout]; - let layout = TemplateLayout.getTemplate( - layoutKey, - this.getInputDir(), - this.config - ); + let layout = this.getLayout(layoutKey); debug("%o is using layout %o", this.inputPath, layoutKey); // TODO reuse templateContent from templateMap @@ -529,11 +538,8 @@ class Template extends TemplateContent { let content; let layoutKey = mapEntry.data[this.config.keys.layout]; if (layoutKey) { - let layout = TemplateLayout.getTemplate( - layoutKey, - this.getInputDir(), - this.config - ); + let layout = this.getLayout(layoutKey); + content = await layout.render(page.data, page.templateContent); } else { content = page.templateContent; diff --git a/src/TemplateData.js b/src/TemplateData.js index d5500334f..7cc66a8ed 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -205,21 +205,23 @@ class TemplateData { let dataFileConflicts = {}; for (let j = 0, k = files.length; j < k; j++) { - let folders = await this.getObjectPathForDataFile(files[j]); + let objectPathTarget = await this.getObjectPathForDataFile(files[j]); let data = await this.getDataValue(files[j], rawImports); - if (dataFileConflicts[folders]) { + // if two global files have the same path (but different extensions) + // and conflict, let’s merge them. + if (dataFileConflicts[objectPathTarget]) { debugWarn( - `merging global data from ${files[j]} with an already existing global data file (${dataFileConflicts[folders]}). Overriding existing keys` + `merging global data from ${files[j]} with an already existing global data file (${dataFileConflicts[objectPathTarget]}). Overriding existing keys.` ); - let oldData = lodashget(globalData, folders); + let oldData = lodashget(globalData, objectPathTarget); data = TemplateData.mergeDeep(this.config, oldData, data); } - dataFileConflicts[folders] = files[j]; - debug(`Found global data file ${files[j]} and adding as: ${folders}`); - lodashset(globalData, folders, data); + dataFileConflicts[objectPathTarget] = files[j]; + debug(`Found global data file ${files[j]} and adding as: ${objectPathTarget}`); + lodashset(globalData, objectPathTarget, data); } return globalData; diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index 06943db68..cc4065625 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -5,7 +5,7 @@ const TemplatePath = require("./TemplatePath"); const templateCache = require("./TemplateCache"); const config = require("./Config"); -const debug = require("debug")("Eleventy:TemplateLayout"); +// const debug = require("debug")("Eleventy:TemplateLayout"); const debugDev = require("debug")("Dev:Eleventy:TemplateLayout"); class TemplateLayout extends TemplateContent { @@ -81,7 +81,9 @@ class TemplateLayout extends TemplateContent { let map = await this.getTemplateLayoutMap(); let dataToMerge = []; + let layoutChain = []; for (let j = map.length - 1; j >= 0; j--) { + layoutChain.push(map[j].template.inputPath); dataToMerge.push(map[j].frontMatterData); } @@ -89,10 +91,18 @@ class TemplateLayout extends TemplateContent { let data = TemplateData.mergeDeep(this.config, {}, ...dataToMerge); delete data[this.config.keys.layout]; + this.layoutChain = layoutChain.reverse(); this.dataCache = data; return data; } + async getLayoutChain() { + if(!this.layoutChain) { + await this.getData(); + } + return this.layoutChain; + } + async getCompiledLayoutFunctions() { if (this.compileCache) { return this.compileCache; diff --git a/src/TemplateLayoutPathResolver.js b/src/TemplateLayoutPathResolver.js index 9d1677e13..8be75bd8a 100644 --- a/src/TemplateLayoutPathResolver.js +++ b/src/TemplateLayoutPathResolver.js @@ -56,10 +56,10 @@ class TemplateLayoutPathResolver { fs.existsSync(this.pathAlreadyHasExtension) ) { this.filename = this.path; - this.fullPath = this.pathAlreadyHasExtension; + this.fullPath = TemplatePath.addLeadingDotSlash(this.pathAlreadyHasExtension); } else { this.filename = this.findFileName(); - this.fullPath = this.dir + "/" + this.filename; + this.fullPath = TemplatePath.addLeadingDotSlash(this.dir + "/" + this.filename); } } diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 28ba3d1da..72013231a 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -534,7 +534,7 @@ ${permalinks[page.url] } } - async getCollectionsData() { + async _testGetCollectionsData() { if (!this.cached) { await this.cache(); } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index db51e8119..7d9b8be3b 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -151,9 +151,9 @@ class TemplateWriter { debug("Found: %o", paths); let passthroughManager = this.getFileManager().getPassthroughManager(); - passthroughManager.setIncrementalFile( - this.incrementalFile ? this.incrementalFile : false - ); + if(this.incrementalFile) { + passthroughManager.setIncrementalFile(this.incrementalFile); + } promises.push( passthroughManager.copyAll(paths).catch(e => { diff --git a/test/TemplateLayoutTest.js b/test/TemplateLayoutTest.js index 6a0035f4e..b45e2f8d8 100644 --- a/test/TemplateLayoutTest.js +++ b/test/TemplateLayoutTest.js @@ -4,7 +4,7 @@ import TemplateLayout from "../src/TemplateLayout"; test("Creation", t => { t.is( new TemplateLayout("base", "./test/stubs").getInputPath(), - "test/stubs/_includes/base.njk" + "./test/stubs/_includes/base.njk" ); t.throws(() => { @@ -12,20 +12,39 @@ test("Creation", t => { }); }); +test("Get Layout Chain", async t => { + let tl = new TemplateLayout("layouts/layout-inherit-a.njk", "./test/stubs"); + + t.deepEqual(await tl.getLayoutChain(), [ + "./test/stubs/_includes/layouts/layout-inherit-a.njk", + "./test/stubs/_includes/layouts/layout-inherit-b.njk", + "./test/stubs/_includes/layouts/layout-inherit-c.njk" + ]); +}); + test("Get Front Matter Data", async t => { let tl = new TemplateLayout("layouts/layout-inherit-a.njk", "./test/stubs"); - t.is(tl.getInputPath(), "test/stubs/_includes/layouts/layout-inherit-a.njk"); + t.is(tl.getInputPath(), "./test/stubs/_includes/layouts/layout-inherit-a.njk"); - t.deepEqual(await tl.getData(), { + let data = await tl.getData(); + + t.deepEqual(data, { inherits: "a", secondinherits: "b", thirdinherits: "c" }); + t.deepEqual(await tl.getLayoutChain(), [ + "./test/stubs/_includes/layouts/layout-inherit-a.njk", + "./test/stubs/_includes/layouts/layout-inherit-b.njk", + "./test/stubs/_includes/layouts/layout-inherit-c.njk" + ]); + t.deepEqual(await tl.getData(), { inherits: "a", secondinherits: "b", thirdinherits: "c" }); + }); test("Augment data with layoutContent", async t => { diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index b14c0339f..b566bfed9 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -177,9 +177,9 @@ test("Issue #115, mixing pagination and collections", async t => { t.is(Object.keys(collections.all).length, 3); t.is(Object.keys(collections.foos).length, 1); t.is(Object.keys(collections.bars).length, 1); - t.is(Object.keys((await tm.getCollectionsData()).all).length, 3); - t.is(Object.keys((await tm.getCollectionsData()).foos).length, 1); - t.is(Object.keys((await tm.getCollectionsData()).bars).length, 1); + t.is(Object.keys((await tm._testGetCollectionsData()).all).length, 3); + t.is(Object.keys((await tm._testGetCollectionsData()).foos).length, 1); + t.is(Object.keys((await tm._testGetCollectionsData()).bars).length, 1); t.truthy(map[0].data.collections); t.truthy(map[1].data.collections); @@ -238,9 +238,9 @@ test("Issue #115 with layout, mixing pagination and collections", async t => { t.is(Object.keys(collections.all).length, 3); t.is(Object.keys(collections.foos).length, 1); t.is(Object.keys(collections.bars).length, 1); - t.is(Object.keys((await tm.getCollectionsData()).all).length, 3); - t.is(Object.keys((await tm.getCollectionsData()).foos).length, 1); - t.is(Object.keys((await tm.getCollectionsData()).bars).length, 1); + t.is(Object.keys((await tm._testGetCollectionsData()).all).length, 3); + t.is(Object.keys((await tm._testGetCollectionsData()).foos).length, 1); + t.is(Object.keys((await tm._testGetCollectionsData()).bars).length, 1); t.truthy(map[0].data.collections); t.truthy(map[1].data.collections); @@ -288,12 +288,12 @@ test("TemplateMap adds collections data and has page data values using .cache()" t.truthy(map[0].data.page.date); }); -test("TemplateMap adds collections data and has page data values using .getCollectionsData()", async t => { +test("TemplateMap adds collections data and has page data values using ._testGetCollectionsData()", async t => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all[0].url, "/templateMapCollection/test1/"); t.is( collections.all[0].outputPath, @@ -323,7 +323,7 @@ test("Url should be available in user config collections API calls", async t => } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.truthy(collections.userCollection); t.truthy(collections.userCollection.length); t.is(collections.userCollection[0].url, "/templateMapCollection/test1/"); @@ -379,7 +379,7 @@ test("Should be able to paginate a tag generated collection", async t => { ); await tm.add(pagedTmpl); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.truthy(collections.dog); t.truthy(collections.dog.length); }); @@ -403,7 +403,7 @@ test("Should be able to paginate a user config collection", async t => { } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.truthy(collections.userCollection); t.truthy(collections.userCollection.length); }); @@ -432,7 +432,7 @@ test("Should be able to paginate a user config collection (uses rendered permali } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.truthy(collections.userCollection); t.truthy(collections.userCollection.length); @@ -463,7 +463,7 @@ test("Should be able to paginate a user config collection (paged template is als } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.dog.length, 2); t.truthy(collections.haha); @@ -491,7 +491,7 @@ test("Should be able to paginate a user config collection (paged template is als } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.dog.length, 2); t.truthy(collections.haha); @@ -526,7 +526,7 @@ test("Should be able to paginate a user config collection (paged template is als } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.truthy(collections.haha); t.is(collections.haha.length, 1); t.is(collections.haha[0].url, "/test-title/goodbye/"); @@ -552,7 +552,7 @@ test("Should be able to paginate a user config collection (paged template is als } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.truthy(collections.haha); t.is(collections.haha.length, 2); t.is(collections.haha[0].url, "/test-title/goodbye/"); @@ -670,7 +670,7 @@ test("Issue #253: Paginated template with a tag should put multiple pages into a } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.dog.length, 2); t.truthy(collections.haha); @@ -719,7 +719,7 @@ test("Dependency Map should have nodes that have no dependencies and no dependen let deps = await tm.getMappedDependencies(); t.true(deps.filter(dep => dep.indexOf("test5.md") > -1).length > 0); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 2); }); @@ -744,7 +744,7 @@ test("Dependency Map should have include orphan user config collections (in the delayedDeps.filter(dep => dep.indexOf("userCollection") > -1).length > 0 ); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 2); t.is(collections.userCollection.length, 2); }); @@ -781,7 +781,7 @@ test("Template pages should not have layouts when added to collections", async t await tm.add(tmpl); t.is(await tmpl.render(), "
Layout Test
"); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 1); t.is(collections.all[0].templateContent, "Layout Test"); }); @@ -796,7 +796,7 @@ test("Paginated template pages should not have layouts when added to collections ); await tm.add(pagedTmpl); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 3); t.is(collections.all[0].templateContent, "one"); @@ -816,7 +816,7 @@ test("Tag pages. Allow pagination over all collections a la `data: collections`" await tm.add(tmpl1); await tm.add(tmpl2); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 3); let collectionTagPagesTemplateContents = new Set( @@ -843,7 +843,7 @@ test("Tag pages (all pages added to collections). Allow pagination over all coll await tm.add(tmpl1); await tm.add(tmpl2); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 5); let collectionTagPagesTemplateContents = new Set( @@ -876,7 +876,7 @@ test("eleventyExcludeFromCollections", async t => { t.is(tm.getMap().length, 2); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 1); t.is(collections.post.length, 1); t.is(collections.dog.length, 1); @@ -894,7 +894,7 @@ test("Paginate over collections.all", async t => { await tm.add(tmpl1); await tm.add(tmpl2); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 4); t.is( collections.all.filter(function(entry) { @@ -953,7 +953,7 @@ test("Paginate over collections.all WITH a paginate over collections (tag pages) await tm.add(tmpl1); await tm.add(tmpl2); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); // 2 individual templates, 3 pages for tagpagesall, 5 pages from paginateall to paginate the 2+3 t.is(collections.all.length, 10); }); @@ -1008,7 +1008,7 @@ test("Async user collection addCollection method", async t => { } }); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.userCollection[0].url, "/templateMapCollection/test1/"); t.is(collections.userCollection[0].data.collections.userCollection.length, 1); @@ -1104,6 +1104,6 @@ test("TemplateMap circular references (map.templateContent) using eleventyExclud await tm.cache(); t.is(tm.getMap().length, 2); - let collections = await tm.getCollectionsData(); + let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 1); }); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 7f7be1495..771fc4207 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1955,3 +1955,28 @@ test("global variable with dashes Issue #567 (liquid)", async t => { // t.is(data.permalink, "/{{ page.fileSlug }}/"); // t.is(data.page.url, "/test/"); // }); + +// Prior to and including 0.10.0 this mismatched the documentation)! +test("Layout front matter should override template files", async t => { + let dataObj = new TemplateData("./test/stubs-data-cascade/layout-data-files/"); + let tmpl = new Template( + "./test/stubs-data-cascade/layout-data-files/test.njk", + "./test/stubs-data-cascade/layout-data-files/", + "./dist", + dataObj + ); + + let data = await tmpl.getData(); + t.is(data.shared, "layout"); +}); + +test("Get Layout Chain", async t => { + let tmpl = new Template( + "./test/stubs-incremental/layout-chain/test.njk", + "./test/stubs-incremental/layout-chain/", + "./dist" + ); + + let layoutChain = await tmpl.getLayoutChain(); + t.deepEqual(layoutChain, ["./test/stubs-incremental/layout-chain/_includes/base.njk", "./test/stubs-incremental/layout-chain/_includes/parent.njk"]); +}); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index a4a31c3f9..0b106fa45 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -66,14 +66,14 @@ test("_createTemplateMap (no leading dot slash)", async t => { t.is(paths[0], "./test/stubs/writeTest/test.md"); }); -test("getCollectionsData", async t => { +test("_testGetCollectionsData", async t => { let tw = new TemplateWriter("./test/stubs/collection", "./test/stubs/_site", [ "md" ]); let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.post.length, 2); t.is(collectionsData.cat.length, 2); t.is(collectionsData.dog.length, 1); @@ -99,11 +99,11 @@ test("Collection of files sorted by date", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.dateTestTag.length, 6); }); -test("_getCollectionsData with custom collection (ascending)", async t => { +test("__testGetCollectionsData with custom collection (ascending)", async t => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -119,13 +119,13 @@ test("_getCollectionsData with custom collection (ascending)", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.customPostsAsc.length, 2); t.is(parsePath(collectionsData.customPostsAsc[0].inputPath).base, "test1.md"); t.is(parsePath(collectionsData.customPostsAsc[1].inputPath).base, "test2.md"); }); -test("_getCollectionsData with custom collection (descending)", async t => { +test("__testGetCollectionsData with custom collection (descending)", async t => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -141,13 +141,13 @@ test("_getCollectionsData with custom collection (descending)", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.customPosts.length, 2); t.is(parsePath(collectionsData.customPosts[0].inputPath).base, "test2.md"); t.is(parsePath(collectionsData.customPosts[1].inputPath).base, "test1.md"); }); -test("_getCollectionsData with custom collection (filter only to markdown input)", async t => { +test("__testGetCollectionsData with custom collection (filter only to markdown input)", async t => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -164,7 +164,7 @@ test("_getCollectionsData with custom collection (filter only to markdown input) let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.onlyMarkdown.length, 2); t.is(parsePath(collectionsData.onlyMarkdown[0].inputPath).base, "test1.md"); t.is(parsePath(collectionsData.onlyMarkdown[1].inputPath).base, "test2.md"); @@ -180,7 +180,7 @@ test("Pagination with a Collection", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.tag1.length, 3); t.is(collectionsData.pagingtag.length, 1); @@ -210,7 +210,7 @@ test("Pagination with a Collection from another Paged Template", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.tag1.length, 3); t.is(collectionsData.pagingtag.length, 2); @@ -243,7 +243,7 @@ test("Pagination with a Collection (apply all pages to collections)", async t => let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.tag1.length, 3); t.is(collectionsData.pagingtag.length, 2); @@ -294,7 +294,7 @@ test("Use a collection inside of a template", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.dog.length, 1); let mapEntry = templateMap.getMapEntryForInputPath( @@ -336,7 +336,7 @@ test("Use a collection inside of a layout", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.dog.length, 1); let mapEntry = templateMap.getMapEntryForInputPath( @@ -409,7 +409,7 @@ test("Custom collection returns array", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.returnAllInputPaths.length, 2); t.is(parsePath(collectionsData.returnAllInputPaths[0]).base, "test1.md"); t.is(parsePath(collectionsData.returnAllInputPaths[1]).base, "test2.md"); @@ -429,7 +429,7 @@ test("Custom collection returns a string", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.returnATestString, "test"); }); @@ -447,7 +447,7 @@ test("Custom collection returns an object", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.deepEqual(collectionsData.returnATestObject, { test: "value" }); }); @@ -461,7 +461,7 @@ test("fileSlug should exist in a collection", async t => { let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.dog.length, 1); let mapEntry = templateMap.getMapEntryForInputPath( @@ -485,7 +485,7 @@ test.skip("renderData should exist and be resolved in a collection (Issue #289)" let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); - let collectionsData = await templateMap.getCollectionsData(); + let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.dog.length, 1); let mapEntry = templateMap.getMapEntryForInputPath( diff --git a/test/stubs-data-cascade/layout-data-files/_includes/base.njk b/test/stubs-data-cascade/layout-data-files/_includes/base.njk new file mode 100644 index 000000000..d532f4886 --- /dev/null +++ b/test/stubs-data-cascade/layout-data-files/_includes/base.njk @@ -0,0 +1,3 @@ +--- +shared: layout +--- \ No newline at end of file diff --git a/test/stubs-data-cascade/layout-data-files/test.11tydata.js b/test/stubs-data-cascade/layout-data-files/test.11tydata.js new file mode 100644 index 000000000..243000be6 --- /dev/null +++ b/test/stubs-data-cascade/layout-data-files/test.11tydata.js @@ -0,0 +1,3 @@ +module.exports = { + shared: "datafile" +}; diff --git a/test/stubs-data-cascade/layout-data-files/test.njk b/test/stubs-data-cascade/layout-data-files/test.njk new file mode 100644 index 000000000..e23205c64 --- /dev/null +++ b/test/stubs-data-cascade/layout-data-files/test.njk @@ -0,0 +1,3 @@ +--- +layout: base.njk +--- \ No newline at end of file diff --git a/test/stubs-incremental/layout-chain/_includes/base.njk b/test/stubs-incremental/layout-chain/_includes/base.njk new file mode 100644 index 000000000..5157d1ba0 --- /dev/null +++ b/test/stubs-incremental/layout-chain/_includes/base.njk @@ -0,0 +1,3 @@ +--- +layout: parent.njk +--- \ No newline at end of file diff --git a/test/stubs-incremental/layout-chain/_includes/parent.njk b/test/stubs-incremental/layout-chain/_includes/parent.njk new file mode 100644 index 000000000..e69de29bb diff --git a/test/stubs-incremental/layout-chain/test.njk b/test/stubs-incremental/layout-chain/test.njk new file mode 100644 index 000000000..e23205c64 --- /dev/null +++ b/test/stubs-incremental/layout-chain/test.njk @@ -0,0 +1,3 @@ +--- +layout: base.njk +--- \ No newline at end of file From cde29307ef06722e5708e373f9ba6b38c11db018 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 16 Feb 2020 13:47:04 -0600 Subject: [PATCH 120/746] Uncomment test for #446 --- test/TemplateTest.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 771fc4207..74811a912 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1942,19 +1942,20 @@ test("global variable with dashes Issue #567 (liquid)", async t => { t.is(pages[0].templateContent.trim(), "Yes"); }); -// test("Issue #446: Layout has a permalink with a different template language than content", async t => { -// let tmpl = new Template( -// "./test/stubs/layout-permalink-difflang/test.md", -// "./test/stubs/layout-permalink-difflang/", -// "dist" -// ); - -// let data = await tmpl.getData(); -// let pages = await tmpl.getRenderedTemplates(data); - -// t.is(data.permalink, "/{{ page.fileSlug }}/"); -// t.is(data.page.url, "/test/"); -// }); +test("Issue #446: Layout has a permalink with a different template language than content", async t => { + let tmpl = new Template( + "./test/stubs/layout-permalink-difflang/test.md", + "./test/stubs/layout-permalink-difflang/", + "dist" + ); + + let data = await tmpl.getData(); + // this call is needed for page data to be added + let pages = await tmpl.getRenderedTemplates(data); + + t.is(data.permalink, "/{{ page.fileSlug }}/"); + t.is(data.page.url, "/test/"); +}); // Prior to and including 0.10.0 this mismatched the documentation)! test("Layout front matter should override template files", async t => { From 55e92c2abb60455be6f14dcbfe28b4b7dbdfa43e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 16 Feb 2020 13:51:23 -0600 Subject: [PATCH 121/746] Note about relevant issue #934 --- test/TemplateRenderJavaScriptTest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 024620024..9f29cd9f3 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -181,8 +181,8 @@ test("JS Render with a function", async t => { t.is(await fn({ name: "Bill" }), "

BILLT9000

"); }); -// This doesn’t work -test.skip("JS Render with an arrow function and javascript function", async t => { +// This doesn’t work, per arrow functions +test.skip("Issue #934: JS Render with an arrow function and javascript function", async t => { let tr = new TemplateRender("./test/stubs/function-filter-arrow.11ty.js"); tr.config = { javascriptFunctions: { From 4b09b43e5595fe736e6f3baf3feb4a915c9a7515 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 16 Feb 2020 22:16:03 -0600 Subject: [PATCH 122/746] Fixes #941, Fixes #816, Fixes #289. --- package.json | 2 +- src/Template.js | 62 +++---- src/TemplateMap.js | 2 + test/PaginationTest.js | 312 ++++++++++++-------------------- test/TemplateMapTest.js | 2 +- test/TemplateTest-JavaScript.js | 2 +- test/TemplateTest.js | 94 ++++++---- test/TemplateWriterTest.js | 5 +- 8 files changed, 201 insertions(+), 280 deletions(-) diff --git a/package.json b/package.json index ecb8767a0..b5e01b31c 100755 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "homepage": "https://www.11ty.dev/", "ava": { "babel": true, - "failFast": true, + "failFast": false, "files": [ "./test/*.js" ], diff --git a/src/Template.js b/src/Template.js index 7a8a6e16c..e4c159a7a 100644 --- a/src/Template.js +++ b/src/Template.js @@ -73,7 +73,7 @@ class Template extends TemplateContent { } getLayout(layoutKey) { - if(!this._layout || layoutKey !== this._layoutKey) { + if (!this._layout || layoutKey !== this._layoutKey) { this._layoutKey = layoutKey; this._layout = TemplateLayout.getTemplate( layoutKey, @@ -85,7 +85,7 @@ class Template extends TemplateContent { } async getLayoutChain() { - if(!this._layout) { + if (!this._layout) { await this.getData(); } @@ -159,7 +159,6 @@ class Template extends TemplateContent { return link.toHref(); } - // TODO check for conflicts, see if file already exists? async getOutputPath(data) { let uri = await this.getOutputLink(data); @@ -294,42 +293,6 @@ class Template extends TemplateContent { return data; } - async addPageRenderedData(data) { - if (!("page" in data)) { - data.page = {}; - } - - let newUrl = await this.getOutputHref(data); - if ("page" in data && "url" in data.page) { - if (data.page.url !== newUrl) { - debug( - "Warning: data.page.url is in use (%o) will be overwritten with: %o", - data.page.url, - newUrl - ); - } - } - - data.page.url = newUrl; - data.page.outputPath = await this.getOutputPath(data); - - return data; - } - - // getData (with renderData and page.url added) - async getRenderedData() { - let data = await this.getData(); - data = await this.addPageRenderedData(data); - - if (data.renderData) { - data.renderData = await this.mapDataAsRenderedTemplates( - data.renderData, - data - ); - } - return data; - } - async renderLayout(tmpl, tmplData) { let layoutKey = tmplData[tmpl.config.keys.layout]; let layout = this.getLayout(layoutKey); @@ -354,10 +317,12 @@ class Template extends TemplateContent { return super.render(str, data, bypassMarkdown); } + // TODO at least some of this isn’t being used in the normal build + // Render is used for `renderData` and `permalink` but otherwise `renderPageEntry` is being used async render(data) { debugDev("%o render()", this.inputPath); if (!data) { - data = await this.getRenderedData(); + throw new Error("`data` needs to be passed into render()"); } if (!this.wrapWithLayouts && data[this.config.keys.layout]) { @@ -407,6 +372,13 @@ class Template extends TemplateContent { data.page.url = await this.getOutputHref(data); data.page.outputPath = await this.getOutputPath(data); + if ("renderData" in data) { + data.renderData = await this.mapDataAsRenderedTemplates( + data.renderData, + data + ); + } + results.push({ template: this, inputPath: this.inputPath, @@ -438,7 +410,7 @@ class Template extends TemplateContent { let pageNumber = 0; for (let page of templates) { // TODO try to reuse data instead of a new copy - let pageData = await page.getRenderedData(); + let pageData = Object.assign({}, await page.getData()); // Issue #115 if (data.collections) { @@ -448,6 +420,13 @@ class Template extends TemplateContent { pageData.page.url = await page.getOutputHref(pageData); pageData.page.outputPath = await page.getOutputPath(pageData); + if ("renderData" in pageData) { + pageData.renderData = await page.mapDataAsRenderedTemplates( + pageData.renderData, + pageData + ); + } + results.push({ template: page, inputPath: this.inputPath, @@ -560,6 +539,7 @@ class Template extends TemplateContent { return Promise.all(promises); } + // TODO is this still used by anything but tests? async write(outputPath, data) { let templates = await this.getRenderedTemplates(data); let promises = []; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 72013231a..318046cf2 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -483,11 +483,13 @@ class TemplateMap { populateCollectionsWithContent() { for (let collectionName in this.collectionsData) { + // skip custom collections set in configuration files that have arbitrary types if (!Array.isArray(this.collectionsData[collectionName])) { continue; } for (let item of this.collectionsData[collectionName]) { + // skip custom collections set in configuration files that have arbitrary types if (!isPlainObject(item) || !("inputPath" in item)) { continue; } diff --git a/test/PaginationTest.js b/test/PaginationTest.js index 1b7141970..f0e807cb2 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -77,27 +77,18 @@ test("Paginate data in frontmatter", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - t.is(paging.getPageCount(), 2); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 2); + t.is(pages[0].outputPath, "./dist/paged/pagedinlinedata/index.html"); t.is( - await pages[0].getOutputPath(), - "./dist/paged/pagedinlinedata/index.html" - ); - t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. item1
  2. item2
  3. item3
  4. item4
" ); + t.is(pages[1].outputPath, "./dist/paged/pagedinlinedata/1/index.html"); t.is( - await pages[1].getOutputPath(), - "./dist/paged/pagedinlinedata/1/index.html" - ); - t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. item5
  2. item6
  3. item7
  4. item8
" ); }); @@ -118,21 +109,18 @@ test("Paginate external data file", async t => { // local data t.truthy(data.items.sub.length); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - t.is(paging.getPageCount(), 2); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 2); - t.is(await pages[0].getOutputPath(), "./dist/paged/index.html"); + t.is(pages[0].outputPath, "./dist/paged/index.html"); t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. item1
  2. item2
  3. item3
  4. item4
  5. item5
" ); - t.is(await pages[1].getOutputPath(), "./dist/paged/1/index.html"); + t.is(pages[1].outputPath, "./dist/paged/1/index.html"); t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. item6
  2. item7
  3. item8
" ); }); @@ -152,19 +140,10 @@ test("Permalink with pagination variables", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - t.is(paging.getPageCount(), 2); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); - t.is( - await pages[0].getOutputPath(), - "./dist/paged/slug-candidate/index.html" - ); - t.is( - await pages[1].getOutputPath(), - "./dist/paged/another-slug-candidate/index.html" - ); + t.is(pages[0].outputPath, "./dist/paged/slug-candidate/index.html"); + t.is(pages[1].outputPath, "./dist/paged/another-slug-candidate/index.html"); }); test("Permalink with pagination variables (numeric)", async t => { @@ -175,32 +154,27 @@ test("Permalink with pagination variables (numeric)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - t.is(paging.getPageCount(), 2); - let pages = await paging.getPageTemplates(); - - let page0Data = await pages[0].getData(); - t.truthy(page0Data.pagination.firstPageLink); - t.truthy(page0Data.pagination.firstPageHref); - t.truthy(page0Data.pagination.lastPageLink); - t.truthy(page0Data.pagination.lastPageHref); - t.is(await pages[0].getOutputPath(), "./dist/paged/page-0/index.html"); - t.falsy(page0Data.pagination.previousPageLink); - t.is(page0Data.pagination.nextPageLink, "/paged/page-1/index.html"); - t.is(page0Data.pagination.nextPageHref, "/paged/page-1/"); - t.is(page0Data.pagination.pageLinks.length, 2); - t.is(page0Data.pagination.links.length, 2); - t.is(page0Data.pagination.hrefs.length, 2); - - let page1Data = await pages[1].getData(); - t.is(await pages[1].getOutputPath(), "./dist/paged/page-1/index.html"); - t.is(page1Data.pagination.previousPageLink, "/paged/page-0/index.html"); - t.is(page1Data.pagination.previousPageHref, "/paged/page-0/"); - t.falsy(page1Data.pagination.nextPageLink); - t.is(page1Data.pagination.pageLinks.length, 2); - t.is(page1Data.pagination.links.length, 2); - t.is(page1Data.pagination.hrefs.length, 2); + let pages = await tmpl.getTemplates(data); + + t.truthy(pages[0].data.pagination.firstPageLink); + t.truthy(pages[0].data.pagination.firstPageHref); + t.truthy(pages[0].data.pagination.lastPageLink); + t.truthy(pages[0].data.pagination.lastPageHref); + t.is(pages[0].outputPath, "./dist/paged/page-0/index.html"); + t.falsy(pages[0].data.pagination.previousPageLink); + t.is(pages[0].data.pagination.nextPageLink, "/paged/page-1/index.html"); + t.is(pages[0].data.pagination.nextPageHref, "/paged/page-1/"); + t.is(pages[0].data.pagination.pageLinks.length, 2); + t.is(pages[0].data.pagination.links.length, 2); + t.is(pages[0].data.pagination.hrefs.length, 2); + + t.is(pages[1].outputPath, "./dist/paged/page-1/index.html"); + t.is(pages[1].data.pagination.previousPageLink, "/paged/page-0/index.html"); + t.is(pages[1].data.pagination.previousPageHref, "/paged/page-0/"); + t.falsy(pages[1].data.pagination.nextPageLink); + t.is(pages[1].data.pagination.pageLinks.length, 2); + t.is(pages[1].data.pagination.links.length, 2); + t.is(pages[1].data.pagination.hrefs.length, 2); }); test("Permalink with pagination variables (numeric, one indexed)", async t => { @@ -211,27 +185,23 @@ test("Permalink with pagination variables (numeric, one indexed)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); - - let page0Data = await pages[0].getData(); - t.is(await pages[0].getOutputPath(), "./dist/paged/page-1/index.html"); - t.falsy(page0Data.pagination.previousPageLink); - t.is(page0Data.pagination.nextPageLink, "/paged/page-2/index.html"); - t.is(page0Data.pagination.nextPageHref, "/paged/page-2/"); - t.is(page0Data.pagination.pageLinks.length, 2); - t.is(page0Data.pagination.links.length, 2); - t.is(page0Data.pagination.hrefs.length, 2); - - let page1Data = await pages[1].getData(); - t.is(await pages[1].getOutputPath(), "./dist/paged/page-2/index.html"); - t.is(page1Data.pagination.previousPageLink, "/paged/page-1/index.html"); - t.is(page1Data.pagination.previousPageHref, "/paged/page-1/"); - t.falsy(page1Data.pagination.nextPageLink); - t.is(page1Data.pagination.pageLinks.length, 2); - t.is(page1Data.pagination.links.length, 2); - t.is(page1Data.pagination.hrefs.length, 2); + let pages = await tmpl.getTemplates(data); + + t.is(pages[0].outputPath, "./dist/paged/page-1/index.html"); + t.falsy(pages[0].data.pagination.previousPageLink); + t.is(pages[0].data.pagination.nextPageLink, "/paged/page-2/index.html"); + t.is(pages[0].data.pagination.nextPageHref, "/paged/page-2/"); + t.is(pages[0].data.pagination.pageLinks.length, 2); + t.is(pages[0].data.pagination.links.length, 2); + t.is(pages[0].data.pagination.hrefs.length, 2); + + t.is(pages[1].outputPath, "./dist/paged/page-2/index.html"); + t.is(pages[1].data.pagination.previousPageLink, "/paged/page-1/index.html"); + t.is(pages[1].data.pagination.previousPageHref, "/paged/page-1/"); + t.falsy(pages[1].data.pagination.nextPageLink); + t.is(pages[1].data.pagination.pageLinks.length, 2); + t.is(pages[1].data.pagination.links.length, 2); + t.is(pages[1].data.pagination.hrefs.length, 2); }); test("Permalink first and last page link with pagination variables (numeric)", async t => { @@ -242,17 +212,13 @@ test("Permalink first and last page link with pagination variables (numeric)", a ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); - let page0Data = await pages[0].getData(); - t.is(page0Data.pagination.firstPageLink, "/paged/page-0/index.html"); - t.is(page0Data.pagination.lastPageLink, "/paged/page-1/index.html"); + t.is(pages[0].data.pagination.firstPageLink, "/paged/page-0/index.html"); + t.is(pages[0].data.pagination.lastPageLink, "/paged/page-1/index.html"); - let page1Data = await pages[1].getData(); - t.is(page1Data.pagination.firstPageLink, "/paged/page-0/index.html"); - t.is(page1Data.pagination.lastPageLink, "/paged/page-1/index.html"); + t.is(pages[1].data.pagination.firstPageLink, "/paged/page-0/index.html"); + t.is(pages[1].data.pagination.lastPageLink, "/paged/page-1/index.html"); }); test("Permalink first and last page link with pagination variables (numeric, one indexed)", async t => { @@ -263,17 +229,13 @@ test("Permalink first and last page link with pagination variables (numeric, one ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); - let page0Data = await pages[0].getData(); - t.is(page0Data.pagination.firstPageLink, "/paged/page-1/index.html"); - t.is(page0Data.pagination.lastPageLink, "/paged/page-2/index.html"); + t.is(pages[0].data.pagination.firstPageLink, "/paged/page-1/index.html"); + t.is(pages[0].data.pagination.lastPageLink, "/paged/page-2/index.html"); - let page1Data = await pages[1].getData(); - t.is(page0Data.pagination.firstPageLink, "/paged/page-1/index.html"); - t.is(page0Data.pagination.lastPageLink, "/paged/page-2/index.html"); + t.is(pages[1].data.pagination.firstPageLink, "/paged/page-1/index.html"); + t.is(pages[1].data.pagination.lastPageLink, "/paged/page-2/index.html"); }); test("Alias to page data", async t => { @@ -284,15 +246,13 @@ test("Alias to page data", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); - t.is(await pages[0].getOutputPath(), "./dist/pagedalias/item1/index.html"); - t.is(await pages[1].getOutputPath(), "./dist/pagedalias/item2/index.html"); + t.is(pages[0].outputPath, "./dist/pagedalias/item1/index.html"); + t.is(pages[1].outputPath, "./dist/pagedalias/item2/index.html"); - t.is((await pages[0].render()).trim(), "item1"); - t.is((await pages[1].render()).trim(), "item2"); + t.is((await pages[0].template.render(pages[0].data)).trim(), "item1"); + t.is((await pages[1].template.render(pages[1].data)).trim(), "item2"); }); test("Alias to page data (size 2)", async t => { @@ -303,15 +263,13 @@ test("Alias to page data (size 2)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); - t.is(await pages[0].getOutputPath(), "./dist/pagedalias/item1/index.html"); - t.is(await pages[1].getOutputPath(), "./dist/pagedalias/item3/index.html"); + t.is(pages[0].outputPath, "./dist/pagedalias/item1/index.html"); + t.is(pages[1].outputPath, "./dist/pagedalias/item3/index.html"); - t.is((await pages[0].render()).trim(), "item1"); - t.is((await pages[1].render()).trim(), "item3"); + t.is((await pages[0].template.render(pages[0].data)).trim(), "item1"); + t.is((await pages[1].template.render(pages[1].data)).trim(), "item3"); }); test("Permalink with pagination variables (and an if statement, nunjucks)", async t => { @@ -322,12 +280,10 @@ test("Permalink with pagination variables (and an if statement, nunjucks)", asyn ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); - t.is(await pages[0].getOutputPath(), "./dist/paged/index.html"); - t.is(await pages[1].getOutputPath(), "./dist/paged/page-1/index.html"); + t.is(pages[0].outputPath, "./dist/paged/index.html"); + t.is(pages[1].outputPath, "./dist/paged/page-1/index.html"); }); test("Permalink with pagination variables (and an if statement, liquid)", async t => { @@ -338,12 +294,10 @@ test("Permalink with pagination variables (and an if statement, liquid)", async ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); - t.is(await pages[0].getOutputPath(), "./dist/paged/index.html"); - t.is(await pages[1].getOutputPath(), "./dist/paged/page-1/index.html"); + t.is(pages[0].outputPath, "./dist/paged/index.html"); + t.is(pages[1].outputPath, "./dist/paged/page-1/index.html"); }); test("Template with Pagination, getRenderedTemplates", async t => { @@ -381,14 +335,9 @@ test("Issue 135", async t => { "./dist/blog/do-you-even-paginate-bro/index.html" ); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 1); - t.is( - await pages[0].getOutputPath(), - "./dist/blog/do-you-even-paginate-bro/index.html" - ); + t.is(pages[0].outputPath, "./dist/blog/do-you-even-paginate-bro/index.html"); }); test("Template with Pagination, getTemplates has page variables set", async t => { @@ -415,12 +364,12 @@ test("Template with Pagination, getRenderedTemplates has page variables set", as ); let data = await tmpl.getData(); - let templates = await tmpl.getRenderedTemplates(data); - t.is(templates[0].data.page.url, "/paged/"); - t.is(templates[0].data.page.outputPath, "./dist/paged/index.html"); + let pages = await tmpl.getRenderedTemplates(data); + t.is(pages[0].data.page.url, "/paged/"); + t.is(pages[0].data.page.outputPath, "./dist/paged/index.html"); - t.is(templates[1].data.page.url, "/paged/page-1/"); - t.is(templates[1].data.page.outputPath, "./dist/paged/page-1/index.html"); + t.is(pages[1].data.page.url, "/paged/page-1/"); + t.is(pages[1].data.page.outputPath, "./dist/paged/page-1/index.html"); }); test("Page over an object (use keys)", async t => { @@ -431,20 +380,18 @@ test("Page over an object (use keys)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 3); - t.is(await pages[0].getOutputPath(), "./dist/paged/pagedobject/index.html"); + t.is(pages[0].outputPath, "./dist/paged/pagedobject/index.html"); t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. item1
  2. item2
  3. item3
  4. item4
" ); - t.is(await pages[1].getOutputPath(), "./dist/paged/pagedobject/1/index.html"); + t.is(pages[1].outputPath, "./dist/paged/pagedobject/1/index.html"); t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. item5
  2. item6
  3. item7
  4. item8
" ); }); @@ -457,26 +404,18 @@ test("Page over an object (use values)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 3); + t.is(pages[0].outputPath, "./dist/paged/pagedobjectvalues/index.html"); t.is( - await pages[0].getOutputPath(), - "./dist/paged/pagedobjectvalues/index.html" - ); - t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. itemvalue1
  2. itemvalue2
  3. itemvalue3
  4. itemvalue4
" ); + t.is(pages[1].outputPath, "./dist/paged/pagedobjectvalues/1/index.html"); t.is( - await pages[1].getOutputPath(), - "./dist/paged/pagedobjectvalues/1/index.html" - ); - t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. itemvalue5
  2. itemvalue6
  3. itemvalue7
  4. itemvalue8
" ); }); @@ -489,18 +428,15 @@ test("Page over an object (filtered, array)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); - t.is(pages.length, 2); + let pages = await tmpl.getTemplates(data); t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. item1
  2. item2
  3. item3
  4. item5
" ); t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. item6
  2. item7
  3. item8
  4. item9
" ); }); @@ -513,18 +449,16 @@ test("Page over an object (filtered, string)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 2); t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. item1
  2. item2
  3. item3
  4. item5
" ); t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. item6
  2. item7
  3. item8
  4. item9
" ); }); @@ -543,26 +477,18 @@ test("Pagination with deep data merge #147", async t => { }; let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 2); + t.is(pages[0].outputPath, "./dist/paged/pagedinlinedata/index.html"); t.is( - await pages[0].getOutputPath(), - "./dist/paged/pagedinlinedata/index.html" - ); - t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. item1
  2. item2
  3. item3
  4. item4
" ); + t.is(pages[1].outputPath, "./dist/paged/pagedinlinedata/1/index.html"); t.is( - await pages[1].getOutputPath(), - "./dist/paged/pagedinlinedata/1/index.html" - ); - t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. item5
  2. item6
  3. item7
  4. item8
" ); }); @@ -583,14 +509,13 @@ test("Pagination with deep data merge with alias #147", async t => { }; let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); - t.is(await pages[0].getOutputPath(), "./dist/pagedalias/item1/index.html"); - t.is(await pages[1].getOutputPath(), "./dist/pagedalias/item2/index.html"); + let pages = await tmpl.getTemplates(data); + + t.is(pages[0].outputPath, "./dist/pagedalias/item1/index.html"); + t.is(pages[1].outputPath, "./dist/pagedalias/item2/index.html"); - t.is((await pages[0].render()).trim(), "item1"); - t.is((await pages[1].render()).trim(), "item2"); + t.is((await pages[0].template.render(pages[0].data)).trim(), "item1"); + t.is((await pages[1].template.render(pages[1].data)).trim(), "item2"); }); test("Paginate data in frontmatter (reversed)", async t => { @@ -601,26 +526,21 @@ test("Paginate data in frontmatter (reversed)", async t => { ); let data = await tmpl.getData(); - let paging = new Pagination(data); - paging.setTemplate(tmpl); - let pages = await paging.getPageTemplates(); + let pages = await tmpl.getTemplates(data); t.is(pages.length, 2); + t.is(pages[0].outputPath, "./dist/paged/pagedinlinedata-reverse/index.html"); t.is( - await pages[0].getOutputPath(), - "./dist/paged/pagedinlinedata-reverse/index.html" - ); - t.is( - (await pages[0].render()).trim(), + (await pages[0].template.render(pages[0].data)).trim(), "
  1. item8
  2. item7
  3. item6
  4. item5
" ); t.is( - await pages[1].getOutputPath(), + pages[1].outputPath, "./dist/paged/pagedinlinedata-reverse/1/index.html" ); t.is( - (await pages[1].render()).trim(), + (await pages[1].template.render(pages[1].data)).trim(), "
  1. item4
  2. item3
  3. item2
  4. item1
" ); }); diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index b566bfed9..80c045215 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -779,7 +779,7 @@ test("Template pages should not have layouts when added to collections", async t "./test/stubs/_site" ); await tm.add(tmpl); - t.is(await tmpl.render(), "
Layout Test
"); + t.is(await tmpl.render(await tmpl.getData()), "
Layout Test
"); let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 1); diff --git a/test/TemplateTest-JavaScript.js b/test/TemplateTest-JavaScript.js index 5fabb8284..621b8a8fc 100644 --- a/test/TemplateTest-JavaScript.js +++ b/test/TemplateTest-JavaScript.js @@ -199,7 +199,7 @@ test("JavaScript template type (class with renderData)", async t => { "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await tmpl.getData(); let pages = await tmpl.getRenderedTemplates(data); t.is( pages[0].templateContent.trim(), diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 74811a912..df369969f 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -10,6 +10,12 @@ import normalizeNewLines from "./Util/normalizeNewLines"; const config = templateConfig.getConfig(); +async function getRenderedData(tmpl, pageNumber = 0) { + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + return templates[pageNumber].data; +} + function cleanHtml(str) { return pretty(str, { ocd: true }); } @@ -334,7 +340,7 @@ test("Liquid template", async t => { dataObj ); - t.is(await tmpl.render(), `

Zach

`); + t.is(await tmpl.render(await tmpl.getData()), `

Zach

`); }); test("Liquid template with include", async t => { @@ -344,7 +350,10 @@ test("Liquid template with include", async t => { "dist" ); - t.is((await tmpl.render()).trim(), "

This is an include.

"); + t.is( + (await tmpl.render(await tmpl.getData())).trim(), + "

This is an include.

" + ); }); test("ES6 Template Literal (No Backticks)", async t => { @@ -356,7 +365,7 @@ test("ES6 Template Literal (No Backticks)", async t => { dataObj ); - t.is((await tmpl.render()).trim(), `

ZACH

`); + t.is((await tmpl.render(await tmpl.getData())).trim(), `

ZACH

`); }); test("ES6 Template Literal (with Backticks)", async t => { @@ -368,7 +377,7 @@ test("ES6 Template Literal (with Backticks)", async t => { dataObj ); - t.is((await tmpl.render()).trim(), `

ZACH

`); + t.is((await tmpl.render(await tmpl.getData())).trim(), `

ZACH

`); }); test("Permalink output directory", async t => { @@ -449,7 +458,7 @@ test("Local template data file import (without a global data json)", async t => "./test/stubs/component/component.11tydata.js" ]); t.is(data.localdatakey1, "localdatavalue1"); - t.is(await tmpl.render(), "localdatavalue1"); + t.is(await tmpl.render(data), "localdatavalue1"); }); test("Local template data file import (two subdirectories deep)", async t => { @@ -665,8 +674,8 @@ test("renderData", async t => { "./test/stubs/", "./dist" ); - - t.is((await tmpl.render()).trim(), "hi:value2-value1.css"); + let data = await getRenderedData(tmpl); + t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); }); test("renderData markdown (issue #40)", async t => { @@ -675,8 +684,8 @@ test("renderData markdown (issue #40)", async t => { "./test/stubs/", "./dist" ); - - t.is((await tmpl.render()).trim(), "value2-value1.css"); + let data = await getRenderedData(tmpl); + t.is((await tmpl.render(data)).trim(), "value2-value1.css"); }); test("getMappedDate (empty, assume created)", async t => { @@ -685,7 +694,7 @@ test("getMappedDate (empty, assume created)", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); let date = await tmpl.getMappedDate(data); t.true(date instanceof Date); @@ -698,7 +707,7 @@ test("getMappedDate (explicit date, yaml String)", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); let date = await tmpl.getMappedDate(data); t.true(date instanceof Date); @@ -711,7 +720,7 @@ test("getMappedDate (explicit date, yaml Date)", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); let date = await tmpl.getMappedDate(data); t.true(date instanceof Date); @@ -724,7 +733,7 @@ test("getMappedDate (explicit date, yaml Date and string should be the same)", a "./test/stubs/", "./dist" ); - let dataA = await tmplA.getRenderedData(); + let dataA = await getRenderedData(tmplA); let stringDate = await tmplA.getMappedDate(dataA); let tmplB = new Template( @@ -732,7 +741,7 @@ test("getMappedDate (explicit date, yaml Date and string should be the same)", a "./test/stubs/", "./dist" ); - let dataB = await tmplB.getRenderedData(); + let dataB = await getRenderedData(tmplB); let yamlDate = await tmplB.getMappedDate(dataB); t.truthy(stringDate); @@ -746,7 +755,7 @@ test("getMappedDate (modified date)", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); let date = await tmpl.getMappedDate(data); t.true(date instanceof Date); @@ -759,7 +768,7 @@ test("getMappedDate (created date)", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); let date = await tmpl.getMappedDate(data); t.true(date instanceof Date); @@ -772,7 +781,7 @@ test("getMappedDate (falls back to filename date)", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); let date = await tmpl.getMappedDate(data); t.true(date instanceof Date); @@ -785,7 +794,7 @@ test("getRenderedData() has all the page variables", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); t.truthy(data.page.url); t.is(data.page.url, "/template/"); @@ -895,7 +904,7 @@ test("getRenderedTemplates() data has all the page variables", async t => { test("getRenderedData() has good slug (empty, index)", async t => { let tmpl = new Template("./test/stubs/index.ejs", "./test/stubs/", "./dist"); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); t.is(data.page.fileSlug, ""); t.is(data.page.filePathStem, "/index"); }); @@ -906,7 +915,7 @@ test("getRenderedData() has good slug", async t => { "./test/stubs/", "./dist" ); - let data = await tmpl.getRenderedData(); + let data = await getRenderedData(tmpl); t.is(data.page.fileSlug, "includer"); t.is(data.page.filePathStem, "/includer"); }); @@ -918,7 +927,7 @@ test("Override base templating engine from .liquid to ejs", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "My Title"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "My Title"); }); test("Override base templating engine from markdown to 11ty.js, then markdown", async t => { @@ -928,7 +937,10 @@ test("Override base templating engine from markdown to 11ty.js, then markdown", "./dist" ); - t.is((await tmpl.render()).trim(), "

This is markdown

"); + t.is( + (await tmpl.render(await tmpl.getData())).trim(), + "

This is markdown

" + ); }); test("Override base templating engine from .liquid to md", async t => { @@ -938,7 +950,7 @@ test("Override base templating engine from .liquid to md", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "

My Title

"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); test("Override base templating engine from .liquid to ejs,md", async t => { @@ -948,7 +960,7 @@ test("Override base templating engine from .liquid to ejs,md", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "

My Title

"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); test("Override base templating engine from .njk to ejs,md", async t => { @@ -958,7 +970,7 @@ test("Override base templating engine from .njk to ejs,md", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "

My Title

"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); test("Override base templating engine from .html to ejs", async t => { @@ -968,7 +980,7 @@ test("Override base templating engine from .html to ejs", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "

My Title

"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); test("Override base templating engine from .html to (nothing)", async t => { @@ -978,7 +990,10 @@ test("Override base templating engine from .html to (nothing)", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "

<%= title %>

"); + t.is( + (await tmpl.render(await tmpl.getData())).trim(), + "

<%= title %>

" + ); }); test("Override base templating engine should error with bad string", async t => { @@ -989,7 +1004,7 @@ test("Override base templating engine should error with bad string", async t => ); await t.throwsAsync(async () => { - await tmpl.render(); + await tmpl.render(await tmpl.getData()); }); }); @@ -1000,7 +1015,7 @@ test("Override base templating engine (bypasses markdown)", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "# My Title"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "# My Title"); }); test("Override base templating engine to (nothing)", async t => { @@ -1011,7 +1026,7 @@ test("Override base templating engine to (nothing)", async t => { ); // not parsed - t.is((await tmpl.render()).trim(), "# <%= title %>"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "# <%= title %>"); }); test("Override base templating engine from .ejs to njk", async t => { @@ -1021,7 +1036,7 @@ test("Override base templating engine from .ejs to njk", async t => { "./dist" ); - t.is((await tmpl.render()).trim(), "My Title"); + t.is((await tmpl.render(await tmpl.getData())).trim(), "My Title"); }); test("Override base templating engine from .njk to ejs (with a layout that uses njk)", async t => { @@ -1032,7 +1047,7 @@ test("Override base templating engine from .njk to ejs (with a layout that uses ); t.is( - (await tmpl.render()).trim(), + (await tmpl.render(await tmpl.getData())).trim(), '

My Title

' ); }); @@ -1045,7 +1060,7 @@ test("Override base templating engine from .njk to nothing (with a layout that u ); t.is( - (await tmpl.render()).trim(), + (await tmpl.render(await tmpl.getData())).trim(), `

<%= title %>

` ); }); @@ -1058,7 +1073,7 @@ test("Using a markdown source file (with a layout that uses njk), markdown shoul ); t.is( - normalizeNewLines((await tmpl.render()).trim()), + normalizeNewLines((await tmpl.render(await tmpl.getData())).trim()), `# Layout header

My Title

@@ -1074,7 +1089,7 @@ test("Override base templating engine from .md to ejs,md (with a layout that use ); t.is( - normalizeNewLines((await tmpl.render()).trim()), + normalizeNewLines((await tmpl.render(await tmpl.getData())).trim()), `# Layout header

My Title

@@ -1959,7 +1974,9 @@ test("Issue #446: Layout has a permalink with a different template language than // Prior to and including 0.10.0 this mismatched the documentation)! test("Layout front matter should override template files", async t => { - let dataObj = new TemplateData("./test/stubs-data-cascade/layout-data-files/"); + let dataObj = new TemplateData( + "./test/stubs-data-cascade/layout-data-files/" + ); let tmpl = new Template( "./test/stubs-data-cascade/layout-data-files/test.njk", "./test/stubs-data-cascade/layout-data-files/", @@ -1979,5 +1996,8 @@ test("Get Layout Chain", async t => { ); let layoutChain = await tmpl.getLayoutChain(); - t.deepEqual(layoutChain, ["./test/stubs-incremental/layout-chain/_includes/base.njk", "./test/stubs-incremental/layout-chain/_includes/parent.njk"]); + t.deepEqual(layoutChain, [ + "./test/stubs-incremental/layout-chain/_includes/base.njk", + "./test/stubs-incremental/layout-chain/_includes/parent.njk" + ]); }); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 0b106fa45..bed25b6fa 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -474,8 +474,7 @@ test("fileSlug should exist in a collection", async t => { t.is(templates[0].templateContent.trim(), "fileSlug:/dog1/:dog1"); }); -// TODO -test.skip("renderData should exist and be resolved in a collection (Issue #289)", async t => { +test("renderData should exist and be resolved in a collection (Issue #289)", async t => { let tw = new TemplateWriter( "./test/stubs/collection-renderdata", "./test/stubs/collection-renderdata/_site", @@ -495,7 +494,7 @@ test.skip("renderData should exist and be resolved in a collection (Issue #289)" t.is(mapEntry.inputPath, "./test/stubs/collection-renderdata/template.njk"); let templates = await mapEntry.template.getRenderedTemplates(mapEntry.data); - t.is(templates[0].templateContent.trim(), "Test Title"); + t.is(templates[0].templateContent.trim(), "value2-value1.css"); }); test("Write Test 11ty.js", async t => { From 1059f8bc698506751ffcbf33ab3a5e05b55bdb78 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 18 Feb 2020 20:33:38 -0600 Subject: [PATCH 123/746] Issue #947 --- test/TemplateTest.js | 21 +++++++++++++++++++++ test/stubs/permalinkdata-jsfn.njk | 7 +++++++ test/stubs/permalinkdata-jspermalinkfn.njk | 9 +++++++++ 3 files changed, 37 insertions(+) create mode 100644 test/stubs/permalinkdata-jsfn.njk create mode 100644 test/stubs/permalinkdata-jspermalinkfn.njk diff --git a/test/TemplateTest.js b/test/TemplateTest.js index df369969f..374a2d8f1 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -584,6 +584,27 @@ test("Permalink with variables!", async t => { t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-candidate/index.html"); }); +test("Permalink with variables and JS front matter!", async t => { + let tmpl = new Template( + "./test/stubs/permalinkdata-jsfn.njk", + "./test/stubs/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/slug/index.html"); +}); + +// This is broken right now, permalink must use the same template language as the template +test.skip("Use a JavaScript function for permalink in any template language", async t => { + let tmpl = new Template( + "./test/stubs/permalinkdata-jspermalinkfn.njk", + "./test/stubs/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/slug/index.html"); +}); + test("Permalink with dates!", async t => { let tmpl = new Template( "./test/stubs/permalinkdate.liquid", diff --git a/test/stubs/permalinkdata-jsfn.njk b/test/stubs/permalinkdata-jsfn.njk new file mode 100644 index 000000000..1614b6f90 --- /dev/null +++ b/test/stubs/permalinkdata-jsfn.njk @@ -0,0 +1,7 @@ +---js +{ + title: "slug", + permalink: "subdir/{{title}}/" +} +--- +Slugged. diff --git a/test/stubs/permalinkdata-jspermalinkfn.njk b/test/stubs/permalinkdata-jspermalinkfn.njk new file mode 100644 index 000000000..b5e08fbd5 --- /dev/null +++ b/test/stubs/permalinkdata-jspermalinkfn.njk @@ -0,0 +1,9 @@ +---js +{ + title: "slug", + permalink: function(data) { + return `subdir/${data.title}/`; + } +} +--- +Slugged. From 99396db66d181dfaa15c0e8c5edf9e34421ef895 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 18 Feb 2020 20:58:59 -0600 Subject: [PATCH 124/746] Attempt to fix #899 --- src/EleventyErrorUtil.js | 7 +++++-- test/EleventyErrorUtilTest.js | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/EleventyErrorUtil.js b/src/EleventyErrorUtil.js index 148730835..af259838d 100644 --- a/src/EleventyErrorUtil.js +++ b/src/EleventyErrorUtil.js @@ -21,8 +21,11 @@ class EleventyErrorUtil { } static cleanMessage(msg) { - if (!msg || !EleventyErrorUtil.hasEmbeddedError(msg)) { - return msg; + if (!msg) { + return ""; + } + if (!EleventyErrorUtil.hasEmbeddedError(msg)) { + return "" + msg; } return msg.substr(0, msg.indexOf(EleventyErrorUtil.prefix)); diff --git a/test/EleventyErrorUtilTest.js b/test/EleventyErrorUtilTest.js index e13036cbb..2ba167fea 100644 --- a/test/EleventyErrorUtilTest.js +++ b/test/EleventyErrorUtilTest.js @@ -16,6 +16,11 @@ test("hasEmbeddedError()", t => { }); test("cleanMessage()", t => { + t.is(cleanMessage(null), ""); + t.is(cleanMessage(undefined), ""); + t.is(cleanMessage(false), ""); + t.is(cleanMessage(""), ""); + const text = "I am the very model of a sample text input"; t.is(cleanMessage(text), text); t.is(cleanMessage(text + convertErrorToString(SAMPLE_ERROR)), text); From d8f941e0e4cf04d47f965d324f29c0683b549b85 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 19 Feb 2020 09:49:17 -0600 Subject: [PATCH 125/746] Fixes #481 --- config.js | 3 +- src/ComputedData.js | 98 +++++++++++++++++ src/Template.js | 81 ++++++++++---- src/TemplateMap.js | 1 - test/ComputedDataTest.js | 123 ++++++++++++++++++++++ test/TemplateTest.js | 37 +++++++ test/stubs/eleventyComputed/first.njk | 6 ++ test/stubs/eleventyComputed/permalink.njk | 11 ++ test/stubs/eleventyComputed/second.njk | 14 +++ 9 files changed, 353 insertions(+), 21 deletions(-) create mode 100644 src/ComputedData.js create mode 100644 test/ComputedDataTest.js create mode 100644 test/stubs/eleventyComputed/first.njk create mode 100644 test/stubs/eleventyComputed/permalink.njk create mode 100644 test/stubs/eleventyComputed/second.njk diff --git a/config.js b/config.js index bbfdd20c0..12d741842 100644 --- a/config.js +++ b/config.js @@ -44,7 +44,8 @@ module.exports = function(config) { layout: "layout", permalink: "permalink", permalinkRoot: "permalinkBypassOutputDir", - engineOverride: "templateEngineOverride" + engineOverride: "templateEngineOverride", + computed: "eleventyComputed" }, dir: { input: ".", diff --git a/src/ComputedData.js b/src/ComputedData.js new file mode 100644 index 000000000..8ab86bd5f --- /dev/null +++ b/src/ComputedData.js @@ -0,0 +1,98 @@ +const lodashGet = require("lodash/get"); +const lodashSet = require("lodash/set"); +const DependencyGraph = require("dependency-graph").DepGraph; + +class ComputedData { + constructor() { + this.computed = {}; + this.computedKeys = new Set(); + this.declaredDependencies = {}; + + // is this ¯\_(lisp)_/¯ + // must be strings that won’t be escaped by template languages + this.prefix = "(((((hi((((("; + this.suffix = ")))))hi)))))"; + } + + add(key, fn, declaredDependencies = []) { + this.computedKeys.add(key); + this.declaredDependencies[key] = declaredDependencies; + lodashSet(this.computed, key, fn); + } + + getProxyData(data) { + let proxyData = {}; + + // use these special strings as a workaround to check the rendered output + // can’t use proxies here as some template languages trigger proxy for all + // keys in data + for (let key of this.computedKeys) { + // TODO don’t allow to set eleventyComputed.page? other disallowed computed things? + lodashSet(proxyData, key, this.prefix + key + this.suffix); + } + + return proxyData; + } + + findVarsInOutput(output = "") { + let vars = new Set(); + let splits = output.split(this.prefix); + for (let split of splits) { + let varName = split.substr(0, split.indexOf(this.suffix)); + if (varName) { + vars.add(varName); + } + } + return Array.from(vars); + } + + async getVarOrder(data) { + if (this.computedKeys.size > 0) { + let graph = new DependencyGraph(); + + let proxyData = this.getProxyData(data); + + for (let key of this.computedKeys) { + let computed = lodashGet(this.computed, key); + if (typeof computed === "function") { + graph.addNode(key); + if (this.declaredDependencies[key].length) { + for (let dep of this.declaredDependencies[key]) { + graph.addNode(dep); + graph.addDependency(key, dep); + } + } + + let output = await computed(proxyData); + + let vars = this.findVarsInOutput(output); + for (let usesVar of vars) { + if (usesVar !== key && this.computedKeys.has(usesVar)) { + graph.addNode(usesVar); + graph.addDependency(key, usesVar); + } + } + } + } + + return graph.overallOrder(); + } + + return []; + } + + async setupData(data) { + let order = await this.getVarOrder(data); + for (let key of order) { + let computed = lodashGet(this.computed, key); + + if (typeof computed === "function") { + lodashSet(data, key, await computed(data)); + } else if (computed) { + lodashSet(data, key, computed); + } + } + } +} + +module.exports = ComputedData; diff --git a/src/Template.js b/src/Template.js index e4c159a7a..0d3262f5a 100644 --- a/src/Template.js +++ b/src/Template.js @@ -12,6 +12,7 @@ const TemplatePermalink = require("./TemplatePermalink"); const TemplatePermalinkNoWrite = require("./TemplatePermalinkNoWrite"); const TemplateLayout = require("./TemplateLayout"); const TemplateFileSlug = require("./TemplateFileSlug"); +const ComputedData = require("./ComputedData"); const Pagination = require("./Plugins/Pagination"); const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); const debug = require("debug")("Eleventy:Template"); @@ -364,20 +365,71 @@ class Template extends TemplateContent { return str; } + _addComputedEntry(computedData, obj, parentKey, declaredDependencies) { + // this check must come before lodashIsObject + if (typeof obj === "function") { + computedData.add(parentKey, obj, declaredDependencies); + } else if (lodashIsObject(obj)) { + for (let key in obj) { + let keys = []; + if (parentKey) { + keys.push(parentKey); + } + keys.push(key); + this._addComputedEntry( + computedData, + obj[key], + keys.join("."), + declaredDependencies + ); + } + } else if (typeof obj === "string") { + computedData.add( + parentKey, + async innerData => { + return await super.render(obj, innerData, true); + }, + declaredDependencies + ); + } + } + + async augmentFinalData(data) { + // will _not_ consume renderData + let computedData = new ComputedData(); + // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly + this._addComputedEntry( + computedData, + { + page: { + url: async data => await this.getOutputHref(data), + outputPath: async data => await this.getOutputPath(data) + } + }, + null, + ["permalink"] + ); // declared dependency + + if (this.config.keys.computed in data) { + this._addComputedEntry(computedData, data[this.config.keys.computed]); + } + await computedData.setupData(data); + + // deprecated, use eleventyComputed instead. + if ("renderData" in data) { + data.renderData = await this.mapDataAsRenderedTemplates( + data.renderData, + data + ); + } + } + async getTemplates(data) { // TODO cache this let results = []; if (!Pagination.hasPagination(data)) { - data.page.url = await this.getOutputHref(data); - data.page.outputPath = await this.getOutputPath(data); - - if ("renderData" in data) { - data.renderData = await this.mapDataAsRenderedTemplates( - data.renderData, - data - ); - } + await this.augmentFinalData(data); results.push({ template: this, @@ -409,7 +461,6 @@ class Template extends TemplateContent { let templates = await this.paging.getPageTemplates(); let pageNumber = 0; for (let page of templates) { - // TODO try to reuse data instead of a new copy let pageData = Object.assign({}, await page.getData()); // Issue #115 @@ -417,15 +468,7 @@ class Template extends TemplateContent { pageData.collections = data.collections; } - pageData.page.url = await page.getOutputHref(pageData); - pageData.page.outputPath = await page.getOutputPath(pageData); - - if ("renderData" in pageData) { - pageData.renderData = await page.mapDataAsRenderedTemplates( - pageData.renderData, - pageData - ); - } + await page.augmentFinalData(pageData); results.push({ template: page, diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 318046cf2..a3e40f436 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -17,7 +17,6 @@ class DuplicatePermalinkOutputError extends EleventyBaseError { class TemplateMap { constructor() { this.map = []; - this.graph = new DependencyGraph(); this.collectionsData = null; this.cached = false; this.configCollections = null; diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js new file mode 100644 index 000000000..7806209fe --- /dev/null +++ b/test/ComputedDataTest.js @@ -0,0 +1,123 @@ +import test from "ava"; +import ComputedData from "../src/ComputedData"; + +test("Get fake proxy data", t => { + let cd = new ComputedData(); + cd.add("key1", () => {}); + cd.add("key2", () => {}); + t.deepEqual(cd.getProxyData({}), { + key1: `${cd.prefix}key1${cd.suffix}`, + key2: `${cd.prefix}key2${cd.suffix}` + }); +}); + +test("Get nested fake proxy data", t => { + let cd = new ComputedData(); + cd.add("key1.nested", () => {}); + cd.add("key2", () => {}); + t.deepEqual(cd.getProxyData({}), { + key1: { + nested: `${cd.prefix}key1.nested${cd.suffix}` + }, + key2: `${cd.prefix}key2${cd.suffix}` + }); +}); + +test("Get vars from output", t => { + let cd = new ComputedData(); + t.deepEqual(cd.findVarsInOutput(""), []); + t.deepEqual(cd.findVarsInOutput("slkdjfkljdsf"), []); + t.deepEqual( + cd.findVarsInOutput(`slkdjfkljdsf${cd.prefix}${cd.suffix}sldkjflkds`), + [] + ); + t.deepEqual( + cd.findVarsInOutput( + `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}sldkjflkds` + ), + ["firstVar"] + ); + t.deepEqual( + cd.findVarsInOutput( + `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}test${cd.prefix}firstVar${cd.suffix}sldkjflkds` + ), + ["firstVar"] + ); + t.deepEqual( + cd.findVarsInOutput( + `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}test${cd.prefix}secondVar${cd.suffix}sldkjflkds` + ), + ["firstVar", "secondVar"] + ); +}); + +test("Basic get/set", async t => { + let cd = new ComputedData(); + + cd.add("keystr", `this is a str`); + cd.add("key1", data => { + return `this is a test ${data.key2}${data.keystr}`; + }); + + let data = { + key2: "inject me" + }; + await cd.setupData(data); + + t.is(data.key1, "this is a test inject methis is a str"); + t.is(data.key2, "inject me"); + t.is(data.keystr, "this is a str"); +}); + +test("use a computed value in another computed", async t => { + let cd = new ComputedData(); + cd.add("keyComputed", data => { + return `this is a test ${data.keyOriginal}`; + }); + cd.add("keyComputed2nd", data => { + return `using computed ${data.keyComputed}`; + }); + + let data = { + keyOriginal: "inject me" + }; + await cd.setupData(data); + + t.is(data.keyComputed2nd, "using computed this is a test inject me"); +}); + +test("use a computed value in another computed (out of order)", async t => { + let cd = new ComputedData(); + cd.add("keyComputed2nd", data => { + return `using computed ${data.keyComputed}`; + }); + cd.add("keyComputed", data => { + return `this is a test ${data.keyOriginal}`; + }); + + let data = { + keyOriginal: "inject me" + }; + await cd.setupData(data); + + t.is(data.keyComputed2nd, "using computed this is a test inject me"); +}); + +test("use a computed value in another computed (out of order), async callbacks", async t => { + let cd = new ComputedData(); + cd.add("keyComputed2nd", async data => { + // await in data.keyComputed is optional 👀 + return `using computed ${data.keyComputed}`; + }); + cd.add("keyComputed", async data => { + // await in data.keyOriginal is optional 👀 + return `this is a test ${await data.keyOriginal}`; + }); + + let data = { + keyOriginal: "inject me" + }; + await cd.setupData(data); + + t.is(data.keyComputed2nd, "using computed this is a test inject me"); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 374a2d8f1..fed301a96 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2022,3 +2022,40 @@ test("Get Layout Chain", async t => { "./test/stubs-incremental/layout-chain/_includes/parent.njk" ]); }); + +test("eleventyComputed", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/first.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); +}); + +test("eleventyComputed permalink", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/permalink.njk", + "./test/stubs/", + "./dist" + ); + let templates = await tmpl.getTemplates(await tmpl.getData()); + let data = templates[0].data; + t.is(data.page.url, "/haha-value1.html"); + t.is(data.page.outputPath, "./dist/haha-value1.html"); + t.is(data.permalink, "haha-value1.html"); + t.is(data.nested.key3, "value1"); + t.is(data.nested.key4, "depends on computed value1"); + t.is(data.dependsOnPage, "depends:/haha-value1.html"); +}); + +test("eleventyComputed js front matter (function)", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/second.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key3, "value3-value2-value1.css"); + t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); +}); diff --git a/test/stubs/eleventyComputed/first.njk b/test/stubs/eleventyComputed/first.njk new file mode 100644 index 000000000..69b609b85 --- /dev/null +++ b/test/stubs/eleventyComputed/first.njk @@ -0,0 +1,6 @@ +--- +key1: value1 +eleventyComputed: + key2: value2-{{ key1 }}.css +--- +hi:{{ key2 }} diff --git a/test/stubs/eleventyComputed/permalink.njk b/test/stubs/eleventyComputed/permalink.njk new file mode 100644 index 000000000..c3f90fc6c --- /dev/null +++ b/test/stubs/eleventyComputed/permalink.njk @@ -0,0 +1,11 @@ +--- +key1: value1 +eleventyComputed: + permalink: "haha-{{key2}}.html" + key2: "{{key1}}" + dependsOnPage: "depends:{{page.url}}" + nested: + key3: "{{key1}}" + key4: "depends on computed {{key2}}" +--- +hi:{{ key2 }} diff --git a/test/stubs/eleventyComputed/second.njk b/test/stubs/eleventyComputed/second.njk new file mode 100644 index 000000000..b0e003511 --- /dev/null +++ b/test/stubs/eleventyComputed/second.njk @@ -0,0 +1,14 @@ +---js +{ + key1: "value1", + eleventyComputed: { + key3: function(data) { + return `value3-${data.key2}`; + }, + key2: function(data) { + return `value2-${data.key1}.css`; + } + } +} +--- +hi:{{ key2 }} From 8ead8886a8aedf81ffde318065217c5aae557e76 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 20 Feb 2020 10:50:17 -0600 Subject: [PATCH 126/746] v0.11.0-beta.1 --- docs-src/_data/coverage.json | 36 +++++++++++++++++++----------------- docs/coverage.md | 34 ++++++++++++++++++---------------- docs/meta-release.md | 10 ++++++---- package.json | 16 ++++++++-------- 4 files changed, 51 insertions(+), 45 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index bda85037b..b543ac8ab 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,38 +1,39 @@ -{"total": {"lines":{"total":2928,"covered":2569,"skipped":0,"pct":87.74},"statements":{"total":2946,"covered":2587,"skipped":0,"pct":87.81},"functions":{"total":694,"covered":604,"skipped":0,"pct":87.03},"branches":{"total":1243,"covered":991,"skipped":0,"pct":79.73}} -,"/Users/zachleat/Code/eleventy/config.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":12,"covered":11,"skipped":0,"pct":91.67},"functions":{"total":6,"covered":5,"skipped":0,"pct":83.33},"statements":{"total":12,"covered":11,"skipped":0,"pct":91.67},"branches":{"total":6,"covered":4,"skipped":0,"pct":66.67}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":34,"covered":23,"skipped":0,"pct":67.65},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":34,"covered":23,"skipped":0,"pct":67.65},"branches":{"total":10,"covered":3,"skipped":0,"pct":30}} +{"total": {"lines":{"total":3054,"covered":2685,"skipped":0,"pct":87.92},"statements":{"total":3073,"covered":2704,"skipped":0,"pct":87.99},"functions":{"total":724,"covered":626,"skipped":0,"pct":86.46},"branches":{"total":1309,"covered":1052,"skipped":0,"pct":80.37}} +,"/Users/zachleat/Code/eleventy/config.js": {"lines":{"total":14,"covered":11,"skipped":0,"pct":78.57},"functions":{"total":4,"covered":1,"skipped":0,"pct":25},"statements":{"total":14,"covered":11,"skipped":0,"pct":78.57},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":15,"covered":13,"skipped":0,"pct":86.67},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":15,"covered":13,"skipped":0,"pct":86.67},"branches":{"total":6,"covered":4,"skipped":0,"pct":66.67}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":44,"covered":23,"skipped":0,"pct":52.27},"functions":{"total":9,"covered":5,"skipped":0,"pct":55.56},"statements":{"total":44,"covered":23,"skipped":0,"pct":52.27},"branches":{"total":12,"covered":3,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":17,"covered":13,"skipped":0,"pct":76.47},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":17,"covered":13,"skipped":0,"pct":76.47},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":49,"covered":48,"skipped":0,"pct":97.96},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":49,"covered":48,"skipped":0,"pct":97.96},"branches":{"total":18,"covered":15,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":193,"covered":105,"skipped":0,"pct":54.4},"functions":{"total":34,"covered":19,"skipped":0,"pct":55.88},"statements":{"total":193,"covered":105,"skipped":0,"pct":54.4},"branches":{"total":73,"covered":27,"skipped":0,"pct":36.99}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":35,"skipped":0,"pct":89.74},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":39,"covered":35,"skipped":0,"pct":89.74},"branches":{"total":43,"covered":29,"skipped":0,"pct":67.44}} -,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":19,"covered":19,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":19,"covered":19,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":60,"covered":58,"skipped":0,"pct":96.67},"functions":{"total":25,"covered":23,"skipped":0,"pct":92},"statements":{"total":60,"covered":58,"skipped":0,"pct":96.67},"branches":{"total":27,"covered":27,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":137,"covered":130,"skipped":0,"pct":94.89},"functions":{"total":37,"covered":33,"skipped":0,"pct":89.19},"statements":{"total":137,"covered":130,"skipped":0,"pct":94.89},"branches":{"total":51,"covered":47,"skipped":0,"pct":92.16}} ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":61,"covered":22,"skipped":0,"pct":36.07},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":61,"covered":22,"skipped":0,"pct":36.07},"branches":{"total":41,"covered":10,"skipped":0,"pct":24.39}} -,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":13,"covered":12,"skipped":0,"pct":92.31}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":288,"covered":271,"skipped":0,"pct":94.1},"functions":{"total":48,"covered":47,"skipped":0,"pct":97.92},"statements":{"total":290,"covered":273,"skipped":0,"pct":94.14},"branches":{"total":103,"covered":88,"skipped":0,"pct":85.44}} +,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":298,"covered":283,"skipped":0,"pct":94.97},"functions":{"total":53,"covered":52,"skipped":0,"pct":98.11},"statements":{"total":300,"covered":285,"skipped":0,"pct":95},"branches":{"total":113,"covered":99,"skipped":0,"pct":87.61}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.63},"functions":{"total":16,"covered":15,"skipped":0,"pct":93.75},"statements":{"total":35,"covered":32,"skipped":0,"pct":91.43},"branches":{"total":10,"covered":7,"skipped":0,"pct":70}} +,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":31,"covered":28,"skipped":0,"pct":90.32},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":34,"covered":31,"skipped":0,"pct":91.18},"branches":{"total":10,"covered":7,"skipped":0,"pct":70}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":57,"covered":52,"skipped":0,"pct":91.23},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":57,"covered":52,"skipped":0,"pct":91.23},"branches":{"total":24,"covered":22,"skipped":0,"pct":91.67}} ,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":81,"covered":76,"skipped":0,"pct":93.83},"functions":{"total":17,"covered":16,"skipped":0,"pct":94.12},"statements":{"total":81,"covered":76,"skipped":0,"pct":93.83},"branches":{"total":34,"covered":31,"skipped":0,"pct":91.18}} -,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":193,"covered":178,"skipped":0,"pct":92.23},"functions":{"total":34,"covered":33,"skipped":0,"pct":97.06},"statements":{"total":195,"covered":180,"skipped":0,"pct":92.31},"branches":{"total":66,"covered":55,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":206,"covered":197,"skipped":0,"pct":95.63},"functions":{"total":38,"covered":37,"skipped":0,"pct":97.37},"statements":{"total":209,"covered":200,"skipped":0,"pct":95.69},"branches":{"total":75,"covered":65,"skipped":0,"pct":86.67}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateGlob.js": {"lines":{"total":15,"covered":14,"skipped":0,"pct":93.33},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} -,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":68,"covered":68,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":69,"covered":69,"skipped":0,"pct":100},"branches":{"total":14,"covered":14,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":73,"covered":73,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":74,"covered":74,"skipped":0,"pct":100},"branches":{"total":16,"covered":16,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":47,"covered":45,"skipped":0,"pct":95.74},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":47,"covered":45,"skipped":0,"pct":95.74},"branches":{"total":18,"covered":16,"skipped":0,"pct":88.89}} -,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":238,"covered":233,"skipped":0,"pct":97.9},"functions":{"total":32,"covered":31,"skipped":0,"pct":96.88},"statements":{"total":238,"covered":233,"skipped":0,"pct":97.9},"branches":{"total":125,"covered":113,"skipped":0,"pct":90.4}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":38,"covered":36,"skipped":0,"pct":94.74},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":38,"covered":36,"skipped":0,"pct":94.74},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":67,"covered":59,"skipped":0,"pct":88.06},"functions":{"total":19,"covered":19,"skipped":0,"pct":100},"statements":{"total":67,"covered":59,"skipped":0,"pct":88.06},"branches":{"total":20,"covered":13,"skipped":0,"pct":65}} -,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":74,"covered":74,"skipped":0,"pct":100},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":75,"covered":75,"skipped":0,"pct":100},"branches":{"total":38,"covered":38,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":237,"covered":232,"skipped":0,"pct":97.89},"functions":{"total":32,"covered":31,"skipped":0,"pct":96.88},"statements":{"total":237,"covered":232,"skipped":0,"pct":97.89},"branches":{"total":125,"covered":113,"skipped":0,"pct":90.4}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":35,"covered":33,"skipped":0,"pct":94.29},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":35,"covered":33,"skipped":0,"pct":94.29},"branches":{"total":12,"covered":10,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":67,"covered":58,"skipped":0,"pct":86.57},"functions":{"total":19,"covered":18,"skipped":0,"pct":94.74},"statements":{"total":67,"covered":58,"skipped":0,"pct":86.57},"branches":{"total":20,"covered":13,"skipped":0,"pct":65}} +,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":93,"covered":93,"skipped":0,"pct":100},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.67},"statements":{"total":94,"covered":94,"skipped":0,"pct":100},"branches":{"total":48,"covered":48,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalinkNoWrite.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":77,"covered":76,"skipped":0,"pct":98.7},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":42,"covered":40,"skipped":0,"pct":95.24}} -,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":93,"covered":71,"skipped":0,"pct":76.34},"functions":{"total":25,"covered":17,"skipped":0,"pct":68},"statements":{"total":93,"covered":71,"skipped":0,"pct":76.34},"branches":{"total":16,"covered":6,"skipped":0,"pct":37.5}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":197,"covered":115,"skipped":0,"pct":58.38},"functions":{"total":53,"covered":24,"skipped":0,"pct":45.28},"statements":{"total":198,"covered":116,"skipped":0,"pct":58.59},"branches":{"total":81,"covered":39,"skipped":0,"pct":48.15}} +,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":94,"covered":71,"skipped":0,"pct":75.53},"functions":{"total":25,"covered":17,"skipped":0,"pct":68},"statements":{"total":94,"covered":71,"skipped":0,"pct":75.53},"branches":{"total":16,"covered":6,"skipped":0,"pct":37.5}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":199,"covered":116,"skipped":0,"pct":58.29},"functions":{"total":54,"covered":24,"skipped":0,"pct":44.44},"statements":{"total":200,"covered":117,"skipped":0,"pct":58.5},"branches":{"total":82,"covered":39,"skipped":0,"pct":47.56}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} @@ -40,13 +41,14 @@ ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.04},"functions":{"total":12,"covered":12,"skipped":0,"pct":100},"statements":{"total":52,"covered":51,"skipped":0,"pct":98.08},"branches":{"total":42,"covered":37,"skipped":0,"pct":88.1}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScriptTemplateLiteral.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":73,"covered":70,"skipped":0,"pct":95.89},"functions":{"total":26,"covered":25,"skipped":0,"pct":96.15},"statements":{"total":73,"covered":70,"skipped":0,"pct":95.89},"branches":{"total":15,"covered":13,"skipped":0,"pct":86.67}} -,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":33,"covered":30,"skipped":0,"pct":90.91},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":33,"covered":30,"skipped":0,"pct":90.91},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} +,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.63},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.63},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":83,"covered":74,"skipped":0,"pct":89.16},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":83,"covered":74,"skipped":0,"pct":89.16},"branches":{"total":29,"covered":27,"skipped":0,"pct":93.1}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":17,"covered":17,"skipped":0,"pct":100},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":53,"covered":53,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":55,"covered":55,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Filters/GetCollectionItem.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.86}} ,"/Users/zachleat/Code/eleventy/src/Filters/Slug.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":18,"covered":18,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":18,"covered":18,"skipped":0,"pct":100},"branches":{"total":21,"covered":21,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":115,"covered":106,"skipped":0,"pct":92.17},"functions":{"total":18,"covered":17,"skipped":0,"pct":94.44},"statements":{"total":119,"covered":110,"skipped":0,"pct":92.44},"branches":{"total":90,"covered":75,"skipped":0,"pct":83.33}} diff --git a/docs/coverage.md b/docs/coverage.md index fd05e2ccd..ced09ccbd 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,12 +1,13 @@ -# Code Coverage for Eleventy v0.10.0 +# Code Coverage for Eleventy v0.11.0-beta.1 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 87.74% | 87.81% | 87.03% | 79.73% | -| `config.js` | 100% | 100% | 100% | 100% | -| `src/Benchmark.js` | 91.67% | 91.67% | 83.33% | 66.67% | -| `src/BenchmarkGroup.js` | 67.65% | 67.65% | 71.43% | 30% | +| `total` | 87.92% | 87.99% | 86.46% | 80.37% | +| `config.js` | 78.57% | 78.57% | 25% | 100% | +| `src/Benchmark.js` | 86.67% | 86.67% | 71.43% | 66.67% | +| `src/BenchmarkGroup.js` | 52.27% | 52.27% | 55.56% | 25% | | `src/BenchmarkManager.js` | 76.47% | 76.47% | 71.43% | 75% | +| `src/ComputedData.js` | 97.96% | 97.96% | 100% | 83.33% | | `src/Config.js` | 100% | 100% | 100% | 100% | | `src/Eleventy.js` | 54.4% | 54.4% | 55.88% | 36.99% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | @@ -17,26 +18,26 @@ | `src/EleventyExtensionMap.js` | 96.67% | 96.67% | 92% | 100% | | `src/EleventyFiles.js` | 94.89% | 94.89% | 89.19% | 92.16% | | `src/EleventyServe.js` | 36.07% | 36.07% | 56.25% | 24.39% | -| `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 92.31% | -| `src/Template.js` | 94.1% | 94.14% | 97.92% | 85.44% | +| `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 93.33% | +| `src/Template.js` | 94.97% | 95% | 98.11% | 87.61% | | `src/TemplateCache.js` | 100% | 100% | 100% | 100% | -| `src/TemplateCollection.js` | 90.63% | 91.43% | 93.75% | 70% | +| `src/TemplateCollection.js` | 90.32% | 91.18% | 93.33% | 70% | | `src/TemplateConfig.js` | 91.23% | 91.23% | 66.67% | 91.67% | | `src/TemplateContent.js` | 93.83% | 93.83% | 94.12% | 91.18% | -| `src/TemplateData.js` | 92.23% | 92.31% | 97.06% | 83.33% | +| `src/TemplateData.js` | 95.63% | 95.69% | 97.37% | 86.67% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | | `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | | `src/TemplateLayout.js` | 100% | 100% | 100% | 100% | | `src/TemplateLayoutPathResolver.js` | 95.74% | 95.74% | 100% | 88.89% | -| `src/TemplateMap.js` | 97.9% | 97.9% | 96.88% | 90.4% | -| `src/TemplatePassthrough.js` | 94.74% | 94.74% | 88.89% | 85.71% | -| `src/TemplatePassthroughManager.js` | 88.06% | 88.06% | 100% | 65% | -| `src/TemplatePath.js` | 100% | 100% | 95.65% | 100% | +| `src/TemplateMap.js` | 97.89% | 97.89% | 96.88% | 90.4% | +| `src/TemplatePassthrough.js` | 94.29% | 94.29% | 88.89% | 83.33% | +| `src/TemplatePassthroughManager.js` | 86.57% | 86.57% | 94.74% | 65% | +| `src/TemplatePath.js` | 100% | 100% | 96.67% | 100% | | `src/TemplatePermalink.js` | 100% | 100% | 100% | 100% | | `src/TemplatePermalinkNoWrite.js` | 100% | 100% | 100% | 100% | | `src/TemplateRender.js` | 98.7% | 98.7% | 100% | 95.24% | -| `src/TemplateWriter.js` | 76.34% | 76.34% | 68% | 37.5% | -| `src/UserConfig.js` | 58.38% | 58.59% | 45.28% | 48.15% | +| `src/TemplateWriter.js` | 75.53% | 75.53% | 68% | 37.5% | +| `src/UserConfig.js` | 58.29% | 58.5% | 44.44% | 47.56% | | `src/Engines/Ejs.js` | 95% | 95% | 85.71% | 88.89% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | @@ -44,13 +45,14 @@ | `src/Engines/JavaScript.js` | 98.04% | 98.08% | 100% | 88.1% | | `src/Engines/JavaScriptTemplateLiteral.js` | 94.44% | 94.44% | 100% | 100% | | `src/Engines/Liquid.js` | 95.89% | 95.89% | 96.15% | 86.67% | -| `src/Engines/Markdown.js` | 90.91% | 90.91% | 88.89% | 81.25% | +| `src/Engines/Markdown.js` | 90.63% | 90.63% | 88.89% | 81.25% | | `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | | `src/Engines/Nunjucks.js` | 89.16% | 89.16% | 95.65% | 93.1% | | `src/Engines/Pug.js` | 100% | 100% | 100% | 88.89% | | `src/Engines/TemplateEngine.js` | 100% | 100% | 100% | 100% | | `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | | `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | +| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.86% | | `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | | `src/Filters/Url.js` | 100% | 100% | 100% | 100% | | `src/Plugins/Pagination.js` | 92.17% | 92.44% | 94.44% | 83.33% | diff --git a/docs/meta-release.md b/docs/meta-release.md index 1caa98964..286f0283c 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -3,6 +3,7 @@ 1. update minor dependencies in package.json? 1. npmclean 1. npm audit +1. Make sure `npx ava` runs okay 1. Update version in `package.json`, include `-beta.1` suffix 1. Run `npm run coverage` 1. Check it all in and commit @@ -14,6 +15,7 @@ 1. update minor dependencies in package.json? `npm outdated` `npm update --save` 1. npmclean first 1. npm audit +1. Make sure `npx ava` runs okay 1. Update version in `package.json` 1. Run `npm run coverage` 1. Check it all in and commit @@ -23,10 +25,10 @@ ## If branch docs do not exist 1. Make sure `localDev: false` in `config.js` -1. Check in a new `11ty.io` site with updated `package.json` version. -1. Add version to 11ty.io `versions.json` +1. Check in a new `11ty-website` site with updated `package.json` version. +1. Add version to 11ty-website `versions.json` 1. Commit it -1. Run ./deploy.sh to push to production branch for 11ty.io +1. Run ./deploy.sh to push to production branch for 11ty-website 1. Create a new branch for branched version 1. Go to https://app.netlify.com/sites/11ty/settings/domain and set up a subdomain for it. @@ -37,7 +39,7 @@ --- -## If Branch docs already exist, 11ty.io (unlikely, I don’t do this any more) +## If Branch docs already exist, 11ty-website (unlikely, I don’t do this any more) 1. Check to make sure `"prerelease": false` in `_data/config.json` 2. Check to make sure `"prerelease": true` does not exist in current version in `_data/versions.json` diff --git a/package.json b/package.json index b5e01b31c..b93a85574 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.10.0", + "version": "0.11.0-beta.1", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -75,9 +75,9 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", - "@ava/babel": "^1.0.0", - "ava": "^3.0.0", - "husky": "^4.2.2", + "@ava/babel": "^1.0.1", + "ava": "^3.3.0", + "husky": "^4.2.3", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", "jsdoc": "3.6.3", @@ -85,7 +85,7 @@ "markdown-it-emoji": "^1.4.0", "nyc": "^15.0.0", "prettier": "^1.19.1", - "rimraf": "^3.0.0", + "rimraf": "^3.0.2", "toml": "^3.0.0", "viperhtml": "^2.17.1", "vue": "^2.6.11", @@ -97,13 +97,13 @@ "chalk": "^3.0.0", "chokidar": "^3.3.1", "debug": "^4.1.1", - "dependency-graph": "^0.8.1", + "dependency-graph": "^0.9.0", "ejs": "^2.6.2", "fast-glob": "^3.1.1", "fs-extra": "^8.1.0", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", - "handlebars": "^4.5.3", + "handlebars": "^4.7.3", "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", "lodash": "^4.17.15", @@ -120,7 +120,7 @@ "pretty": "^2.0.0", "pug": "^2.0.4", "recursive-copy": "^2.0.10", - "semver": "^7.1.0", + "semver": "^7.1.3", "slugify": "^1.3.6", "time-require": "^0.1.2", "valid-url": "^1.0.9" From 9c13e4d0fe24efa0fdd8ba9d0d39437b427609d3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 20 Feb 2020 23:22:12 -0600 Subject: [PATCH 127/746] A few more tests for #481 --- test/TemplateTest.js | 33 +++++++++++++++++++ .../stubs/eleventyComputed/override-reuse.njk | 6 ++++ test/stubs/eleventyComputed/override.njk | 6 ++++ test/stubs/eleventyComputed/third.njk | 11 +++++++ 4 files changed, 56 insertions(+) create mode 100644 test/stubs/eleventyComputed/override-reuse.njk create mode 100644 test/stubs/eleventyComputed/override.njk create mode 100644 test/stubs/eleventyComputed/third.njk diff --git a/test/TemplateTest.js b/test/TemplateTest.js index fed301a96..c17d0e3d5 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2033,6 +2033,28 @@ test("eleventyComputed", async t => { t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); }); +test("eleventyComputed overrides existing value.", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/override.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "override"); + t.is((await tmpl.render(data)).trim(), "hi:override"); +}); + +test("eleventyComputed overrides existing value and reuses that upstream value", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/override-reuse.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "over(value1)ride"); + t.is((await tmpl.render(data)).trim(), "hi:over(value1)ride"); +}); + test("eleventyComputed permalink", async t => { let tmpl = new Template( "./test/stubs/eleventyComputed/permalink.njk", @@ -2059,3 +2081,14 @@ test("eleventyComputed js front matter (function)", async t => { t.is(data.key3, "value3-value2-value1.css"); t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); }); + +test("eleventyComputed js front matter key reuses and overrides", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/third.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "value2-value1"); + t.is((await tmpl.render(data)).trim(), "hi:value2-value1"); +}); diff --git a/test/stubs/eleventyComputed/override-reuse.njk b/test/stubs/eleventyComputed/override-reuse.njk new file mode 100644 index 000000000..60d305914 --- /dev/null +++ b/test/stubs/eleventyComputed/override-reuse.njk @@ -0,0 +1,6 @@ +--- +key1: value1 +eleventyComputed: + key1: "over({{key1}})ride" +--- +hi:{{ key1 }} diff --git a/test/stubs/eleventyComputed/override.njk b/test/stubs/eleventyComputed/override.njk new file mode 100644 index 000000000..8aa9037fb --- /dev/null +++ b/test/stubs/eleventyComputed/override.njk @@ -0,0 +1,6 @@ +--- +key1: value1 +eleventyComputed: + key1: override +--- +hi:{{ key1 }} diff --git a/test/stubs/eleventyComputed/third.njk b/test/stubs/eleventyComputed/third.njk new file mode 100644 index 000000000..a63bece11 --- /dev/null +++ b/test/stubs/eleventyComputed/third.njk @@ -0,0 +1,11 @@ +---js +{ + key1: "value1", + eleventyComputed: { + key1: function(data) { + return `value2-${data.key1}`; + } + } +} +--- +hi:{{ key1 }} From 0d65518f4329bb29fec4b7c0860a2e05add5c8dc Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Sun, 23 Feb 2020 14:30:51 +0100 Subject: [PATCH 128/746] Correct verb conjugation mistake in comment The past participle of the verb "override" is "overridden", not "overrode". We say: "foo overrode bar", but "bar was overriden by foo". https://www.theconjugator.com/english/verb/to+override.html --- src/Eleventy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index adcbb4b85..d68c63f9c 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -42,7 +42,7 @@ class Eleventy { this.isVerbose = process.env.DEBUG ? false : !this.config.quietMode; /** - * @member {Boolean} - Was verbose mode overrode manually? + * @member {Boolean} - Was verbose mode overridden manually? * @default false */ this.isVerboseOverride = false; From 72c2e74e7760c383493ea1cf08d7a324d0a5b5bf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 23 Feb 2020 21:51:39 -0600 Subject: [PATCH 129/746] Even more tests for #481 --- test/ComputedDataTest.js | 58 ++++++++++++++++++++++++++++ test/TemplateTest.js | 13 +++++++ test/stubs/eleventyComputed/true.njk | 7 ++++ 3 files changed, 78 insertions(+) create mode 100644 test/stubs/eleventyComputed/true.njk diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index 7806209fe..5dcc148f7 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -121,3 +121,61 @@ test("use a computed value in another computed (out of order), async callbacks", t.is(data.keyComputed2nd, "using computed this is a test inject me"); }); + +test("Basic get/set nested", async t => { + let cd = new ComputedData(); + + cd.add("key1.nested", data => { + return `${data.key2}`; + }); + cd.add("key2", data => "hi"); + + let data = { + key2: "inject me" + }; + await cd.setupData(data); + + t.deepEqual(data.key1, { nested: "hi" }); + t.is(data.key1.nested, "hi"); + t.is(data.key2, "hi"); +}); + +test("Basic get/set nested deeper", async t => { + let cd = new ComputedData(); + + cd.add("key1.nested.deeperA", data => { + return `${data.key2}`; + }); + cd.add("key1.nested.deeperB", data => { + return `${data.key2}`; + }); + cd.add("key1.nested.deeperC.wow", data => { + return `${data.key2}`; + }); + cd.add("key2", data => "hi"); + + let data = { + key1: { + nonComputed: "hi" + }, + key2: "inject me" + }; + await cd.setupData(data); + + t.deepEqual(data.key1, { + nonComputed: "hi", + nested: { + deeperA: "hi", + deeperB: "hi", + deeperC: { + wow: "hi" + } + } + }); + + t.is(data.key1.nested.deeperA, "hi"); + t.is(data.key1.nested.deeperB, "hi"); + t.is(data.key1.nested.deeperC.wow, "hi"); + t.is(data.key1.nonComputed, "hi"); + t.is(data.key2, "hi"); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index c17d0e3d5..e952db3df 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2092,3 +2092,16 @@ test("eleventyComputed js front matter key reuses and overrides", async t => { t.is(data.key1, "value2-value1"); t.is((await tmpl.render(data)).trim(), "hi:value2-value1"); }); + +test("eleventyComputed true primitive", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/true.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "value1"); + t.is(data.key2, true); + t.is(data.key3, false); + t.is(data.key4, 324); +}); diff --git a/test/stubs/eleventyComputed/true.njk b/test/stubs/eleventyComputed/true.njk new file mode 100644 index 000000000..252978ff2 --- /dev/null +++ b/test/stubs/eleventyComputed/true.njk @@ -0,0 +1,7 @@ +--- +key1: value1 +eleventyComputed: + key2: true + key3: false + key4: 324 +--- From 9ecb8bec0cf981adb648cf8b55268e1a693d1769 Mon Sep 17 00:00:00 2001 From: Peter deHaan Date: Sun, 23 Feb 2020 19:53:26 -0800 Subject: [PATCH 130/746] Add .npmignore file --- .npmignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .npmignore diff --git a/.npmignore b/.npmignore new file mode 100644 index 000000000..eb693a273 --- /dev/null +++ b/.npmignore @@ -0,0 +1,4 @@ +docs +docs-src +test +.* From cfcf54b86a87b9bdde39f46430145392424d467b Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Wed, 26 Feb 2020 16:49:02 +0100 Subject: [PATCH 131/746] Inverse boolean logic to avoid empty statement I'm not sure what's the benefit of having a condition leading to an empty statement ? You may have a good reason that I have missed though. --- src/Engines/Ejs.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Engines/Ejs.js b/src/Engines/Ejs.js index 98ca1ebbf..5b456385f 100644 --- a/src/Engines/Ejs.js +++ b/src/Engines/Ejs.js @@ -40,9 +40,8 @@ class Ejs extends TemplateEngine { async compile(str, inputPath) { let options = this.getEjsOptions(); - if (!inputPath || inputPath === "ejs" || inputPath === "md") { - // do nothing - } else { + + if (inputPath && inputPath ==! "ejs" && inputPath ==! "md") { options.filename = inputPath; } From ea6f4239a27859b33919fc2503afff0659bfa701 Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Wed, 26 Feb 2020 17:07:27 +0100 Subject: [PATCH 132/746] Update Ejs.js --- src/Engines/Ejs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engines/Ejs.js b/src/Engines/Ejs.js index 5b456385f..14bbe9c41 100644 --- a/src/Engines/Ejs.js +++ b/src/Engines/Ejs.js @@ -41,7 +41,7 @@ class Ejs extends TemplateEngine { async compile(str, inputPath) { let options = this.getEjsOptions(); - if (inputPath && inputPath ==! "ejs" && inputPath ==! "md") { + if (inputPath && inputPath !== "ejs" && inputPath !== "md") { options.filename = inputPath; } From fdd8adb854146e60e8f8515657f018124b3317b0 Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Wed, 26 Feb 2020 17:16:41 +0100 Subject: [PATCH 133/746] Make code style more coherent on error file In most files in the project, there is a line break between the const declarations on top and the class definition. So I'm doing the same here to add some consistency. The contrast is obvious when opening the 2 error files right after the other, as they should have the same layout but don't. --- src/Errors/TemplateContentPrematureUseError.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Errors/TemplateContentPrematureUseError.js b/src/Errors/TemplateContentPrematureUseError.js index 36550613a..72822cc9a 100644 --- a/src/Errors/TemplateContentPrematureUseError.js +++ b/src/Errors/TemplateContentPrematureUseError.js @@ -1,4 +1,5 @@ const EleventyBaseError = require("../EleventyBaseError"); + class TemplateContentPrematureUseError extends EleventyBaseError {} module.exports = TemplateContentPrematureUseError; From a7b89458a2e5ba03c6855701be41acabe9151009 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 28 Feb 2020 08:43:26 -0600 Subject: [PATCH 134/746] Make dependency graph test file --- test/DependencyGraphTest.js | 46 +++++++++++++++++++++++++++++++++++++ test/TemplateMapTest.js | 22 ------------------ 2 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 test/DependencyGraphTest.js diff --git a/test/DependencyGraphTest.js b/test/DependencyGraphTest.js new file mode 100644 index 000000000..5c8990883 --- /dev/null +++ b/test/DependencyGraphTest.js @@ -0,0 +1,46 @@ +import test from "ava"; + +test("Dependency graph nodes don’t require dependencies", async t => { + const DependencyGraph = require("dependency-graph").DepGraph; + let graph = new DependencyGraph(); + + graph.addNode("all"); + graph.addNode("template-a"); + graph.addNode("template-b"); + graph.addNode("template-c"); + + t.not(graph.overallOrder().indexOf("all"), -1); + t.not(graph.overallOrder().indexOf("template-a"), -1); + t.not(graph.overallOrder().indexOf("template-b"), -1); + t.not(graph.overallOrder().indexOf("template-c"), -1); + + // in order of addition + t.deepEqual(graph.overallOrder(), [ + "all", + "template-a", + "template-b", + "template-c" + ]); +}); + +test("Dependency graph assumptions", async t => { + const DependencyGraph = require("dependency-graph").DepGraph; + let graph = new DependencyGraph(); + + graph.addNode("all"); + graph.addNode("template-a"); + graph.addNode("template-b"); + graph.addNode("template-c"); + graph.addNode("userCollection"); + graph.addDependency("all", "template-a"); + graph.addDependency("all", "template-b"); + graph.addDependency("all", "template-c"); + graph.addDependency("userCollection", "all"); + t.deepEqual(graph.overallOrder(), [ + "template-a", + "template-b", + "template-c", + "all", + "userCollection" + ]); +}); diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 80c045215..0285813e9 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -749,28 +749,6 @@ test("Dependency Map should have include orphan user config collections (in the t.is(collections.userCollection.length, 2); }); -test("Dependency graph assumptions", async t => { - const DependencyGraph = require("dependency-graph").DepGraph; - let graph = new DependencyGraph(); - - graph.addNode("all"); - graph.addNode("template-a"); - graph.addNode("template-b"); - graph.addNode("template-c"); - graph.addNode("userCollection"); - graph.addDependency("all", "template-a"); - graph.addDependency("all", "template-b"); - graph.addDependency("all", "template-c"); - graph.addDependency("userCollection", "all"); - t.deepEqual(graph.overallOrder(), [ - "template-a", - "template-b", - "template-c", - "all", - "userCollection" - ]); -}); - test("Template pages should not have layouts when added to collections", async t => { let tm = new TemplateMap(); let tmpl = new Template( From 070948127397b880019a62c53c512d4592fed1a5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 28 Feb 2020 23:05:30 -0600 Subject: [PATCH 135/746] Upgrade ava --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b93a85574..ee2a4ca11 100755 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.1", - "ava": "^3.3.0", + "ava": "^3.4.0", "husky": "^4.2.3", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", From 8ad24ab96f80802c39f28921f938a8a6c943e05a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 28 Feb 2020 23:07:27 -0600 Subject: [PATCH 136/746] #481 Tweaks to computed data that allow primitives to be used. No console.logs in first pass for dependency graph creation --- src/ComputedData.js | 21 +++++++++++++-------- src/Template.js | 2 ++ test/stubs/eleventyComputed/true.njk | 6 +++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/ComputedData.js b/src/ComputedData.js index 8ab86bd5f..9d62f5e01 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -10,8 +10,8 @@ class ComputedData { // is this ¯\_(lisp)_/¯ // must be strings that won’t be escaped by template languages - this.prefix = "(((((hi((((("; - this.suffix = ")))))hi)))))"; + this.prefix = "(((((11ty((((("; + this.suffix = ")))))11ty)))))"; } add(key, fn, declaredDependencies = []) { @@ -20,7 +20,7 @@ class ComputedData { lodashSet(this.computed, key, fn); } - getProxyData(data) { + getProxyData() { let proxyData = {}; // use these special strings as a workaround to check the rendered output @@ -46,16 +46,17 @@ class ComputedData { return Array.from(vars); } - async getVarOrder(data) { + async getVarOrder() { if (this.computedKeys.size > 0) { let graph = new DependencyGraph(); - let proxyData = this.getProxyData(data); + let proxyData = this.getProxyData(); for (let key of this.computedKeys) { let computed = lodashGet(this.computed, key); + graph.addNode(key); + if (typeof computed === "function") { - graph.addNode(key); if (this.declaredDependencies[key].length) { for (let dep of this.declaredDependencies[key]) { graph.addNode(dep); @@ -63,7 +64,11 @@ class ComputedData { } } + // squelch console logs for this fake proxy data pass 😅 + let savedLog = console.log; + console.log = () => {}; let output = await computed(proxyData); + console.log = savedLog; let vars = this.findVarsInOutput(output); for (let usesVar of vars) { @@ -82,13 +87,13 @@ class ComputedData { } async setupData(data) { - let order = await this.getVarOrder(data); + let order = await this.getVarOrder(); for (let key of order) { let computed = lodashGet(this.computed, key); if (typeof computed === "function") { lodashSet(data, key, await computed(data)); - } else if (computed) { + } else if (computed !== undefined) { lodashSet(data, key, computed); } } diff --git a/src/Template.js b/src/Template.js index 0d3262f5a..4ddb56457 100644 --- a/src/Template.js +++ b/src/Template.js @@ -391,6 +391,8 @@ class Template extends TemplateContent { }, declaredDependencies ); + } else { + computedData.add(parentKey, obj, declaredDependencies); } } diff --git a/test/stubs/eleventyComputed/true.njk b/test/stubs/eleventyComputed/true.njk index 252978ff2..88f1dc4bc 100644 --- a/test/stubs/eleventyComputed/true.njk +++ b/test/stubs/eleventyComputed/true.njk @@ -1,7 +1,7 @@ --- key1: value1 eleventyComputed: - key2: true - key3: false - key4: 324 + key2: true + key3: false + key4: 324 --- From 8e9496e7b63e425702aafc9de1a415e70570e2bf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 2 Mar 2020 07:24:35 -0600 Subject: [PATCH 137/746] Fixes #983 --- config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.js b/config.js index 12d741842..8890837ee 100644 --- a/config.js +++ b/config.js @@ -7,13 +7,13 @@ module.exports = function(config) { config.addFilter("url", urlFilter); config.addFilter("log", console.log); - config.addLiquidFilter("getCollectionItem", (collection, page) => + config.addFilter("getCollectionItem", (collection, page) => getCollectionItem(collection, page) ); - config.addLiquidFilter("getPreviousCollectionItem", (collection, page) => + config.addFilter("getPreviousCollectionItem", (collection, page) => getCollectionItem(collection, page, -1) ); - config.addLiquidFilter("getNextCollectionItem", (collection, page) => + config.addFilter("getNextCollectionItem", (collection, page) => getCollectionItem(collection, page, 1) ); From 1d86139d6c683385cf244ef77e00453db604c5f3 Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Mon, 2 Mar 2020 16:02:54 +0100 Subject: [PATCH 138/746] Add inputPath to Haml eng. to improve consistency --- src/Engines/Haml.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engines/Haml.js b/src/Engines/Haml.js index 693e8ad13..0728229f3 100644 --- a/src/Engines/Haml.js +++ b/src/Engines/Haml.js @@ -14,7 +14,7 @@ class Haml extends TemplateEngine { this.setEngineLib(lib); } - async compile(str) { + async compile(str, inputPath) { return this.hamlLib.compile(str); } } From f65e2c96f1691ec3456ab96c0a856a5d924343c8 Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Tue, 3 Mar 2020 16:00:05 +0100 Subject: [PATCH 139/746] Add getTemplateData caching test --- test/EleventyFilesTest.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 6d7debbc7..f98267cd9 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -383,6 +383,14 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore ha }); /* End .eleventyignore and .gitignore combos */ +test("getTemplateData caching", t => { + let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); + evf.init(); + let templateDataFirstCall = evf.getTemplateData(); + let templateDataSecondCall = evf.getTemplateData(); + t.is(templateDataFirstCall, templateDataSecondCall); +}); + test("getDataDir", t => { let evf = new EleventyFiles(".", "_site", []); evf.init(); From 060d1be05da0c5ffe828f4a9d150eeb75de1454d Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Tue, 3 Mar 2020 17:09:50 +0100 Subject: [PATCH 140/746] Replace concat by unshift as asked in comment Your comment (that made me smile by the way) said: > // todo use unshift or something (no wifi here to look up docs :D) So here we go :). PS. If you want to have the JS docs available offline, have a look at https://devdocs.io/offline. --- src/TemplateRender.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 64dbbe4f9..3f1e65831 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -112,8 +112,7 @@ class TemplateRender { // markdown should always be first if (usingMarkdown) { - // todo use unshift or something (no wifi here to look up docs :D) - engines = ["md"].concat(engines); + engines.unshift("md"); } return engines; From ff0af3470218417023691ab0a171284732e3e175 Mon Sep 17 00:00:00 2001 From: Max Schoening Date: Tue, 3 Mar 2020 10:42:22 -0800 Subject: [PATCH 141/746] Add GitHub Actions CI configuration --- .github/workflows/ci.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..74fdfbf69 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +on: + push: + branches-ignore: + - "gh-pages" +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: ["ubuntu-latest", "macos-latest", "windows-latest"] + node: ["8", "10", "12"] + name: Node.js ${{ matrix.node }} on ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Setup node + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + - run: npm install + - run: npm test +env: + - YARN_GPG=no From bbc2bdb3e1c7eaf4757883884ae478bd9006a932 Mon Sep 17 00:00:00 2001 From: Max Schoening Date: Tue, 3 Mar 2020 10:44:35 -0800 Subject: [PATCH 142/746] Correctly configure environment variables --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74fdfbf69..d6303a4cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,4 +19,4 @@ jobs: - run: npm install - run: npm test env: - - YARN_GPG=no + YARN_GPG: no From 05204918fa04ff0fe2339f0dd92afaf40c162af6 Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Thu, 5 Mar 2020 16:50:52 +0100 Subject: [PATCH 143/746] Use getter/setter for getTemplateData --- src/Eleventy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index d68c63f9c..e0aa427db 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -277,7 +277,7 @@ class Eleventy { this.eleventyFiles.init(); this.templateData = new TemplateData(this.inputDir); - this.eleventyFiles.setTemplateData(this.templateData); + this.eleventyFiles.templateData = this.templateData; this.writer = new TemplateWriter( this.input, From c7913b3aae22804143f00debc50814e4b193c6fd Mon Sep 17 00:00:00 2001 From: Samuel Path Date: Thu, 5 Mar 2020 16:52:10 +0100 Subject: [PATCH 144/746] use getter/setter for getTemplateData --- src/EleventyFiles.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 0b0848db0..0835c2992 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -94,20 +94,19 @@ class EleventyFiles { this.passthroughManager = mgr; } - setTemplateData(templateData) { - this.templateData = templateData; + set templateData(templateData) { + this._templateData = templateData; } - // TODO make this a getter - getTemplateData() { - if (!this.templateData) { - this.templateData = new TemplateData(this.inputDir); + get templateData() { + if (!this._templateData) { + this._templateData = new TemplateData(this.inputDir); } - return this.templateData; + return this._templateData; } getDataDir() { - let data = this.getTemplateData(); + let data = this.templateData; return data.getDataDir(); } @@ -297,13 +296,13 @@ class EleventyFiles { } async getGlobWatcherTemplateDataFiles() { - let templateData = this.getTemplateData(); + let templateData = this.templateData; return await templateData.getTemplateDataFileGlob(); } // TODO this isn’t great but reduces complexity avoiding using TemplateData:getLocalDataPaths for each template in the cache async getWatcherTemplateJavaScriptDataFiles() { - let globs = await this.getTemplateData().getTemplateJavaScriptDataFileGlob(); + let globs = await this.templateData.getTemplateJavaScriptDataFileGlob(); return TemplatePath.addLeadingDotSlashArray( await fastglob(globs, { ignore: ["**/node_modules/**"], From b82341721a3e7128dfd9d520064f3aee6ba08fb0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 5 Mar 2020 14:56:29 -0600 Subject: [PATCH 145/746] Just in time config includes to allow template compilation inside of configuration files --- src/EleventyExtensionMap.js | 5 ++--- src/Engines/TemplateEngine.js | 3 +-- src/TemplateRender.js | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index f73a2e998..cd55f2a6d 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -1,5 +1,4 @@ const TemplatePath = require("./TemplatePath"); -const config = require("./Config"); class EleventyExtensionMap { constructor(formatKeys = []) { @@ -17,7 +16,7 @@ class EleventyExtensionMap { } get config() { - return this.configOverride || config.getConfig(); + return this.configOverride || require("./Config").getConfig(); } set config(cfg) { this.configOverride = cfg; @@ -133,7 +132,7 @@ class EleventyExtensionMap { } static get keyMap() { return EleventyExtensionMap._getKeyMap( - config.getConfig().templateExtensionAliases || {} + require("./Config").getConfig().templateExtensionAliases || {} ); } diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index b2dc8d7c2..b94ff727d 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -2,7 +2,6 @@ const fastglob = require("fast-glob"); const fs = require("fs-extra"); const TemplatePath = require("../TemplatePath"); const EleventyExtensionMap = require("../EleventyExtensionMap"); -const config = require("../Config"); const debug = require("debug")("Eleventy:TemplateEngine"); class TemplateEngine { @@ -19,7 +18,7 @@ class TemplateEngine { get config() { if (!this._config) { - this._config = config.getConfig(); + this._config = require("../Config").getConfig(); } return this._config; } diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 64dbbe4f9..9b76ae497 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -2,7 +2,6 @@ const TemplatePath = require("./TemplatePath"); const TemplateEngine = require("./Engines/TemplateEngine"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyExtensionMap = require("./EleventyExtensionMap"); -const config = require("./Config"); // const debug = require("debug")("Eleventy:TemplateRender"); class TemplateRenderUnknownEngineError extends EleventyBaseError {} @@ -32,7 +31,7 @@ class TemplateRender { get config() { if (!this._config) { - this._config = config.getConfig(); + this._config = require("./Config").getConfig(); } return this._config; } From 5ee0cdea6e5f4ad82fe079286ee67de804e12d93 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 5 Mar 2020 14:59:03 -0600 Subject: [PATCH 146/746] Fixes #977 --- src/Eleventy.js | 149 +++++++++++------ src/EleventyServe.js | 15 +- src/EleventyWatch.js | 99 +++++++++++ src/TemplateConfig.js | 4 - src/TemplatePassthroughManager.js | 33 +++- src/TemplateWriter.js | 65 ++++++-- src/UserConfig.js | 12 ++ test/EleventyWatchTest.js | 222 +++++++++++++++++++++++++ test/TemplatePassthroughManagerTest.js | 32 +++- 9 files changed, 545 insertions(+), 86 deletions(-) create mode 100644 src/EleventyWatch.js create mode 100644 test/EleventyWatchTest.js diff --git a/src/Eleventy.js b/src/Eleventy.js index d68c63f9c..5207ec6c8 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -4,14 +4,15 @@ const TemplateData = require("./TemplateData"); const TemplateWriter = require("./TemplateWriter"); const EleventyErrorHandler = require("./EleventyErrorHandler"); const EleventyServe = require("./EleventyServe"); +const EleventyWatch = require("./EleventyWatch"); const EleventyWatchTargets = require("./EleventyWatchTargets"); const EleventyFiles = require("./EleventyFiles"); const templateCache = require("./TemplateCache"); const simplePlural = require("./Util/Pluralize"); +const deleteRequireCache = require("./Util/DeleteRequireCache"); const config = require("./Config"); const bench = require("./BenchmarkManager"); const debug = require("debug")("Eleventy"); -const deleteRequireCache = require("./Util/DeleteRequireCache"); /** * @module @11ty/eleventy/Eleventy @@ -77,6 +78,9 @@ class Eleventy { /** @member {String} - Holds the path to the output directory. */ this.rawOutput = output; + /** @member {Object} - tbd. */ + this.watchManager = new EleventyWatch(); + /** @member {Object} - tbd. */ this.watchTargets = new EleventyWatchTargets(); this.watchTargets.addAndMakeGlob(this.config.additionalWatchTargets); @@ -122,6 +126,7 @@ class Eleventy { */ setIncrementalBuild(isIncremental) { this.isIncremental = !!isIncremental; + this.watchManager.incremental = !!isIncremental; } /** @@ -412,60 +417,87 @@ Arguments: * * @private * @method - * @param {String} path - File that triggered a re-run (added or modified) + * @param {String} changedFilePath - File that triggered a re-run (added or modified) */ - async _watch(path) { - if (path) { - path = TemplatePath.addLeadingDotSlash(path); - } + async _addFileToWatchQueue(changedFilePath) { + this.watchManager.addToPendingQueue(changedFilePath); + } - if (this.active) { - this.queuedToRun = path; + /** + * tbd. + * + * @private + * @method + */ + async _watch() { + if (this.watchManager.isBuildRunning()) { return; } - this.active = true; - - let isInclude = - path && - TemplatePath.startsWithSubPath(path, this.eleventyFiles.getIncludesDir()); - let isJavaScriptDependency = - path && this.watchTargets.isJavaScriptDependency(path); + this.watchManager.setBuildRunning(); - let localProjectConfigPath = config.getLocalProjectConfigFile(); // reset and reload global configuration :O - if (path === localProjectConfigPath) { + if (this.watchManager.hasQueuedFile(config.getLocalProjectConfigFile())) { this.resetConfig(); } - config.resetOnWatch(); await this.restart(); + this.watchTargets.clearDependencyRequireCache(); - if (path && !isInclude && !isJavaScriptDependency && this.isIncremental) { - this.writer.setIncrementalFile(path); + let incrementalFile = this.watchManager.getIncrementalFile(); + if (incrementalFile) { + // TODO remove these and delegate to the template dependency graph + let isInclude = TemplatePath.startsWithSubPath( + incrementalFile, + this.eleventyFiles.getIncludesDir() + ); + let isJSDependency = this.watchTargets.isJavaScriptDependency( + incrementalFile + ); + if (!isInclude && !isJSDependency) { + this.writer.setIncrementalFile(incrementalFile); + } } await this.write(); - if (path && !isInclude && this.isIncremental) { - this.writer.resetIncrementalFile(); - } + this.writer.resetIncrementalFile(); this.watchTargets.reset(); + await this._initWatchDependencies(); // Add new deps to chokidar this.watcher.add(this.watchTargets.getNewTargetsSinceLastReset()); - this.eleventyServe.reload(path, isInclude); + // Is a CSS input file and is not in the includes folder + // TODO check output path file extension of this template (not input path) + // TODO add additional API for this, maybe a config callback? + let onlyCssChanges = this.watchManager.hasAllQueueFiles(path => { + return ( + path.endsWith(".css") && + // TODO how to make this work with relative includes? + !TemplatePath.startsWithSubPath( + path, + this.eleventyFiles.getIncludesDir() + ) + ); + }); - this.active = false; + if (onlyCssChanges) { + this.eleventyServe.reload("*.css"); + } else { + this.eleventyServe.reload(); + } + + this.watchManager.setBuildFinished(); - if (this.queuedToRun) { - console.log("You saved while Eleventy was running, let’s run again."); - this.queuedToRun = false; - await this._watch(this.queuedToRun); + if (this.watchManager.getPendingQueueSize() > 0) { + console.log( + `You saved while Eleventy was running, let’s run again. (${this.watchManager.getPendingQueueSize()} remain)` + ); + await this._watch(); } else { console.log("Watching…"); } @@ -487,6 +519,9 @@ Arguments: * @method */ async initWatch() { + this.watchManager = new EleventyWatch(); + this.watchManager.incremental = this.isIncremental; + this.watchTargets.add(this.eleventyFiles.getGlobWatcherFiles()); // Watch the local project config file @@ -553,6 +588,26 @@ Arguments: return this.watchTargets.getTargets(); } + getChokidarConfig() { + let ignores = this.eleventyFiles.getGlobWatcherIgnores(); + debug("Ignoring watcher changes to: %o", ignores); + + let configOptions = this.config.chokidarConfig; + + // can’t override these yet + // TODO maybe if array, merge the array? + delete configOptions.ignored; + + return Object.assign( + { + ignored: ignores, + ignoreInitial: true + // also interesting: awaitWriteFinish + }, + configOptions + ); + } + /** * Start the watching of files. * @@ -565,9 +620,6 @@ Arguments: const chokidar = require("chokidar"); - this.active = false; - this.queuedToRun = false; - // Note that watching indirectly depends on this for fetching dependencies from JS files // See: TemplateWriter:pathCache and EleventyWatchTargets await this.write(); @@ -578,12 +630,7 @@ Arguments: let rawFiles = await this.getWatchedFiles(); debug("Watching for changes to: %o", rawFiles); - let ignores = this.eleventyFiles.getGlobWatcherIgnores(); - debug("Ignoring watcher changes to: %o", ignores); - let watcher = chokidar.watch(rawFiles, { - ignored: ignores, - ignoreInitial: true - }); + let watcher = chokidar.watch(rawFiles, this.getChokidarConfig()); this.watcherBench.finish("Initialize --watch", 10, this.isVerbose); @@ -591,12 +638,17 @@ Arguments: this.watcher = watcher; + let watchDelay; async function watchRun(path) { try { - await this._watch(path); + this._addFileToWatchQueue(path); + clearTimeout(watchDelay); + watchDelay = setTimeout(async () => { + await this._watch(); + }, this.config.watchThrottleWaitTime); } catch (e) { EleventyErrorHandler.fatal(e, "Eleventy fatal watch error"); - watcher.close(); + this.stopWatch(); } } @@ -610,15 +662,14 @@ Arguments: await watchRun.call(this, path); }); - process.on( - "SIGINT", - function() { - debug("Cleaning up chokidar and browsersync (if exists) instances."); - this.eleventyServe.close(); - this.watcher.close(); - process.exit(); - }.bind(this) - ); + process.on("SIGINT", () => this.stopWatch()); + } + + stopWatch() { + debug("Cleaning up chokidar and browsersync (if exists) instances."); + this.eleventyServe.close(); + this.watcher.close(); + process.exit(); } /** diff --git a/src/EleventyServe.js b/src/EleventyServe.js index c1d80b805..94349a98c 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -124,9 +124,7 @@ class EleventyServe { let redirectFilename = this.getRedirectFilename(this.savedPathPrefix); if (!fs.existsSync(redirectFilename)) { debug( - `Redirecting BrowserSync from ${ - this.savedPathPrefix - } to ${pathPrefix}` + `Redirecting BrowserSync from ${this.savedPathPrefix} to ${pathPrefix}` ); this.serveRedirect(this.savedPathPrefix); } else { @@ -155,19 +153,14 @@ class EleventyServe { } } - reload(path, isInclude) { + /* filesToReload is optional */ + reload(filesToReload) { if (this.server) { if (this.getPathPrefix() !== this.savedPathPrefix) { this.server.exit(); this.serve(); } else { - // Is a CSS input file and is not in the includes folder - // TODO check output path file extension of this template (not input path) - if (path && path.split(".").pop() === "css" && !isInclude) { - this.server.reload("*.css"); - } else { - this.server.reload(); - } + this.server.reload(filesToReload); } } } diff --git a/src/EleventyWatch.js b/src/EleventyWatch.js new file mode 100644 index 000000000..b1e073eac --- /dev/null +++ b/src/EleventyWatch.js @@ -0,0 +1,99 @@ +const TemplatePath = require("./TemplatePath"); + +/* Decides when to watch and in what mode to watch + * Incremental builds don’t batch changes, they queue. + * Nonincremental builds batch. + */ + +class EleventyWatch { + constructor() { + this.incremental = false; + this.isActive = false; + this.activeQueue = []; + } + + isBuildRunning() { + return this.isActive; + } + + setBuildRunning() { + this.isActive = true; + + // pop waiting queue into the active queue + this.activeQueue = this.popNextActiveQueue(); + } + + setBuildFinished() { + this.isActive = false; + this.activeQueue = []; + } + + getIncrementalFile() { + if (!this.isActive || !this.incremental || this.activeQueue.length === 0) { + return false; + } + + return this.activeQueue[0]; + } + + _queueMatches(file) { + let filterCallback; + if (typeof file === "function") { + filterCallback = file; + } else { + filterCallback = path => path === file; + } + + return this.activeQueue.filter(filterCallback); + } + + hasAllQueueFiles(file) { + return ( + this.activeQueue.length > 0 && + this.activeQueue.length === this._queueMatches(file).length + ); + } + + hasQueuedFile(file) { + return this._queueMatches(file).length > 0; + } + + get pendingQueue() { + if (!this._queue) { + this._queue = []; + } + return this._queue; + } + + set pendingQueue(value) { + this._queue = value; + } + + addToPendingQueue(path) { + if (path) { + path = TemplatePath.addLeadingDotSlash(path); + this.pendingQueue.push(path); + } + } + + getPendingQueueSize() { + return this.pendingQueue.length; + } + + getActiveQueueSize() { + return this.activeQueue.length; + } + + // returns array + popNextActiveQueue() { + if (this.incremental) { + return this.pendingQueue.length ? [this.pendingQueue.shift()] : []; + } + + let ret = this.pendingQueue.filter(() => true); + this.pendingQueue = []; + return ret; + } +} + +module.exports = EleventyWatch; diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 1bcf39fe2..928b5d07a 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -34,10 +34,6 @@ class TemplateConfig { this.config = this.mergeConfig(this.localProjectConfigPath); } - resetOnWatch() { - // nothing yet - } - getConfig() { return this.config; } diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index d154ad838..fa9c25dde 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -71,7 +71,7 @@ class TemplatePassthroughManager { }); } - getFilePaths(paths) { + getNonTemplatePaths(paths) { if (!this.config.passthroughFileCopy) { debug("`passthroughFileCopy` is disabled in config, bypassing."); return []; @@ -128,6 +128,22 @@ class TemplatePassthroughManager { }); } + isPassthroughCopyFile(paths, changedFile) { + for (let path of paths) { + if (path === changedFile && !TemplateRender.hasEngine(path)) { + return true; + } + } + + for (let path of this.getConfigPaths()) { + if (TemplatePath.startsWithSubPath(changedFile, path.inputPath)) { + return true; + } + } + + return false; + } + // Performance note: these can actually take a fair bit of time, but aren’t a // bottleneck to eleventy. The copies are performed asynchronously and don’t affect eleventy // write times in a significant way. @@ -137,6 +153,19 @@ class TemplatePassthroughManager { return; } + if ( + this.incrementalFile && + this.isPassthroughCopyFile(paths, this.incrementalFile) + ) { + return this.copyPath(this._normalizePaths(this.incrementalFile)).then( + () => { + debug( + `TemplatePassthrough --incremental copy finished. Current count: ${this.count}` + ); + } + ); + } + let promises = []; debug("TemplatePassthrough copy started."); for (let path of this.getConfigPaths()) { @@ -144,7 +173,7 @@ class TemplatePassthroughManager { promises.push(this.copyPath(path)); } - let passthroughPaths = this.getFilePaths(paths); + let passthroughPaths = this.getNonTemplatePaths(paths); for (let path of passthroughPaths) { let normalizedPath = this._normalizePaths(path); debug( diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 7d9b8be3b..038229d83 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -25,7 +25,10 @@ class TemplateWriter { this.input = inputPath; this.inputDir = TemplatePath.getDir(inputPath); this.outputDir = outputDir; + + this.needToSearchForFiles = null; this.templateFormats = templateFormats; + this.templateData = templateData; this.isVerbose = true; this.isDryRun = false; @@ -36,6 +39,18 @@ class TemplateWriter { this.passthroughAll = isPassthroughAll; } + get templateFormats() { + return this._templateFormats; + } + + set templateFormats(value) { + if (value !== this._templateFormats) { + this.needToSearchForFiles = true; + } + + this._templateFormats = value; + } + /* For testing */ overrideConfig(config) { this.config = config; @@ -68,7 +83,11 @@ class TemplateWriter { } async _getAllPaths() { - return await this.getFileManager().getFiles(); + if (!this.allPaths || this.needToSearchForFiles) { + this.allPaths = await this.getFileManager().getFiles(); + debug("Found: %o", this.allPaths); + } + return this.allPaths; } _createTemplate(path) { @@ -145,24 +164,22 @@ class TemplateWriter { }); } - async write() { - let promises = []; - let paths = await this._getAllPaths(); - debug("Found: %o", paths); - + async writePassthroughCopy(paths) { let passthroughManager = this.getFileManager().getPassthroughManager(); - if(this.incrementalFile) { + if (this.incrementalFile) { passthroughManager.setIncrementalFile(this.incrementalFile); } - promises.push( - passthroughManager.copyAll(paths).catch(e => { - EleventyErrorHandler.warn(e, "Error with passthrough copy"); - return Promise.reject( - new TemplateWriterWriteError("Having trouble copying", e) - ); - }) - ); + return passthroughManager.copyAll(paths).catch(e => { + EleventyErrorHandler.warn(e, "Error with passthrough copy"); + return Promise.reject( + new TemplateWriterWriteError("Having trouble copying", e) + ); + }); + } + + async writeTemplates(paths) { + let promises = []; // TODO optimize await here await this._createTemplateMap(paths); @@ -201,6 +218,24 @@ class TemplateWriter { ); } + return promises; + } + + async write() { + let paths = await this._getAllPaths(); + let promises = []; + promises.push(this.writePassthroughCopy(paths)); + + // Only write templates if not using incremental OR if incremental file was *not* a passthrough copy + if ( + !this.incrementalFile || + !this.getFileManager() + .getPassthroughManager() + .isPassthroughCopyFile(paths, this.incrementalFile) + ) { + promises.push(...(await this.writeTemplates(paths))); + } + return Promise.all(promises).catch(e => { EleventyErrorHandler.error(e, "Error writing templates"); throw e; diff --git a/src/UserConfig.js b/src/UserConfig.js index 7a2a25d78..9de601da8 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -57,6 +57,8 @@ class UserConfig { this.watchJavaScriptDependencies = true; this.additionalWatchTargets = []; this.browserSyncConfig = {}; + this.chokidarConfig = {}; + this.watchThrottleWaitTime = 0; //ms // using Map to preserve insertion order this.dataExtensions = new Map(); @@ -585,6 +587,14 @@ class UserConfig { this.browserSyncConfig = options; } + setChokidarConfig(options = {}) { + this.chokidarConfig = options; + } + + setWatchThrottleWaitTime(time = 0) { + this.watchThrottleWaitTime = time; + } + setFrontMatterParsingOptions(options = {}) { this.frontMatterParsingOptions = options; } @@ -628,6 +638,8 @@ class UserConfig { watchJavaScriptDependencies: this.watchJavaScriptDependencies, additionalWatchTargets: this.additionalWatchTargets, browserSyncConfig: this.browserSyncConfig, + chokidarConfig: this.chokidarConfig, + watchThrottleWaitTime: this.watchThrottleWaitTime, frontMatterParsingOptions: this.frontMatterParsingOptions, dataExtensions: this.dataExtensions, quietMode: this.quietMode diff --git a/test/EleventyWatchTest.js b/test/EleventyWatchTest.js new file mode 100644 index 000000000..e7f26cd7b --- /dev/null +++ b/test/EleventyWatchTest.js @@ -0,0 +1,222 @@ +import test from "ava"; +import EleventyWatch from "../src/EleventyWatch"; + +test("Standard", t => { + let watch = new EleventyWatch(); + t.is(watch.isBuildRunning(), false); + + watch.setBuildRunning(); + t.is(watch.isBuildRunning(), true); + + watch.setBuildFinished(); + t.is(watch.isBuildRunning(), false); +}); + +test("Incremental", t => { + let watch = new EleventyWatch(); + t.is(watch.getIncrementalFile(), false); + + watch.incremental = true; + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.addToPendingQueue("test.md"); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildRunning(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 1); + t.is(watch.getIncrementalFile(), "./test.md"); + + watch.setBuildFinished(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); +}); + +test("Incremental queue 2", t => { + let watch = new EleventyWatch(); + t.is(watch.getIncrementalFile(), false); + + watch.incremental = true; + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.addToPendingQueue("test.md"); + watch.addToPendingQueue("test2.md"); + t.is(watch.getPendingQueueSize(), 2); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildRunning(); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 1); + t.is(watch.getIncrementalFile(), "./test.md"); + + watch.setBuildFinished(); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); +}); + +test("Incremental add while active", t => { + let watch = new EleventyWatch(); + t.is(watch.getIncrementalFile(), false); + + watch.incremental = true; + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.addToPendingQueue("test.md"); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildRunning(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 1); + t.is(watch.getIncrementalFile(), "./test.md"); + + watch.addToPendingQueue("test2.md"); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 1); + t.is(watch.getIncrementalFile(), "./test.md"); + + watch.setBuildFinished(); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); +}); + +test("Non-incremental", t => { + let watch = new EleventyWatch(); + t.is(watch.getIncrementalFile(), false); + + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.addToPendingQueue("test.md"); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildRunning(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 1); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildFinished(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); +}); + +test("Non-incremental queue 2", t => { + let watch = new EleventyWatch(); + t.is(watch.getIncrementalFile(), false); + + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.addToPendingQueue("test.md"); + watch.addToPendingQueue("test2.md"); + t.is(watch.getPendingQueueSize(), 2); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildRunning(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 2); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildFinished(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); +}); + +test("Non-incremental add while active", t => { + let watch = new EleventyWatch(); + t.is(watch.getIncrementalFile(), false); + + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.addToPendingQueue("test.md"); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildRunning(); + t.is(watch.getPendingQueueSize(), 0); + t.is(watch.getActiveQueueSize(), 1); + t.is(watch.getIncrementalFile(), false); + + watch.addToPendingQueue("test.md"); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 1); + t.is(watch.getIncrementalFile(), false); + + watch.setBuildFinished(); + t.is(watch.getPendingQueueSize(), 1); + t.is(watch.getActiveQueueSize(), 0); + t.is(watch.getIncrementalFile(), false); +}); + +test("Active queue tests", t => { + let watch = new EleventyWatch(); + watch.addToPendingQueue("test.md"); + watch.addToPendingQueue("test2.md"); + watch.addToPendingQueue("test.css"); + + t.is( + watch.hasAllQueueFiles(path => path.startsWith("./test")), + false + ); + + watch.setBuildRunning(); + t.is(watch.hasAllQueueFiles("slkdjflkjsdlkfj"), false); + t.is( + watch.hasAllQueueFiles(path => path.startsWith("./test")), + true + ); + t.is( + watch.hasAllQueueFiles(path => path.endsWith(".css")), + false + ); + + t.is(watch.hasQueuedFile("./test.md"), true); + t.is(watch.hasQueuedFile("./testsdkljfklja.md"), false); + watch.setBuildFinished(); + + t.is( + watch.hasAllQueueFiles(path => path.startsWith("./test")), + false + ); +}); + +test("Active queue tests, all CSS files", t => { + let watch = new EleventyWatch(); + watch.addToPendingQueue("test.css"); + watch.addToPendingQueue("test2.css"); + watch.addToPendingQueue("test3.css"); + + t.is( + watch.hasAllQueueFiles(path => path.endsWith(".css")), + false + ); + + watch.setBuildRunning(); + t.is( + watch.hasAllQueueFiles(path => path.endsWith(".css")), + true + ); + watch.setBuildFinished(); + + t.is( + watch.hasAllQueueFiles(path => path.endsWith(".css")), + false + ); +}); diff --git a/test/TemplatePassthroughManagerTest.js b/test/TemplatePassthroughManagerTest.js index fddc7a7ed..b648d1daf 100644 --- a/test/TemplatePassthroughManagerTest.js +++ b/test/TemplatePassthroughManagerTest.js @@ -14,6 +14,28 @@ test("Get paths from Config", async t => { t.deepEqual(mgr.getConfigPaths(), [{ inputPath: "./img", outputPath: true }]); }); +test("isPassthroughCopyFile", async t => { + let mgr = new TemplatePassthroughManager(); + mgr.setConfig({ + passthroughFileCopy: true, + passthroughCopies: { + img: true, + fonts: true + } + }); + + t.true(mgr.isPassthroughCopyFile([], "./img/test.png")); + t.true(mgr.isPassthroughCopyFile([], "./fonts/Roboto.woff")); + t.false(mgr.isPassthroughCopyFile([], "./docs/test.njk")); + t.false(mgr.isPassthroughCopyFile([], "./other-dir/test.png")); + t.true( + mgr.isPassthroughCopyFile( + ["hi", "./other-dir/test.png"], + "./other-dir/test.png" + ) + ); +}); + test("Empty config paths when disabled in config", async t => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ @@ -50,7 +72,7 @@ test("Get file paths", async t => { passthroughFileCopy: true }); - t.deepEqual(mgr.getFilePaths(["test.png"]), ["test.png"]); + t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), ["test.png"]); }); test("Get file paths (filter out real templates)", async t => { @@ -59,7 +81,7 @@ test("Get file paths (filter out real templates)", async t => { passthroughFileCopy: true }); - t.deepEqual(mgr.getFilePaths(["test.njk"]), []); + t.deepEqual(mgr.getNonTemplatePaths(["test.njk"]), []); }); test("Get file paths (filter out real templates), multiple", async t => { @@ -68,7 +90,7 @@ test("Get file paths (filter out real templates), multiple", async t => { passthroughFileCopy: true }); - t.deepEqual(mgr.getFilePaths(["test.njk", "test.png"]), ["test.png"]); + t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.png"]), ["test.png"]); }); test("Get file paths with a js file (filter out real templates), multiple", async t => { @@ -77,7 +99,7 @@ test("Get file paths with a js file (filter out real templates), multiple", asyn passthroughFileCopy: true }); - t.deepEqual(mgr.getFilePaths(["test.njk", "test.js"]), ["test.js"]); + t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.js"]), ["test.js"]); }); test("Get file paths when disabled in config", async t => { @@ -86,7 +108,7 @@ test("Get file paths when disabled in config", async t => { passthroughFileCopy: false }); - t.deepEqual(mgr.getFilePaths(["test.png"]), []); + t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), []); }); test("Naughty paths outside of project dir", async t => { From 9f10498cfbd45b9d3c6336f738b8fc4f84d96635 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 5 Mar 2020 16:31:38 -0600 Subject: [PATCH 147/746] Beta 2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ee2a4ca11..859f76260 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.11.0-beta.1", + "version": "0.11.0-beta.2", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From efb8edee3a3ca6f3fc0c6111ac9c2bc608773ff8 Mon Sep 17 00:00:00 2001 From: samuelpath Date: Fri, 6 Mar 2020 16:03:54 +0100 Subject: [PATCH 148/746] Refactor command check to use minimist options.unknown callback --- cmd.js | 25 +++++++--- src/EleventyCommandCheck.js | 83 -------------------------------- src/EleventyCommandCheckError.js | 3 ++ test/EleventyCommandCheckTest.js | 51 -------------------- 4 files changed, 22 insertions(+), 140 deletions(-) delete mode 100644 src/EleventyCommandCheck.js create mode 100644 src/EleventyCommandCheckError.js delete mode 100644 test/EleventyCommandCheckTest.js diff --git a/cmd.js b/cmd.js index d90231c0c..eb140ed68 100755 --- a/cmd.js +++ b/cmd.js @@ -8,6 +8,7 @@ require("please-upgrade-node")(pkg, { ); } }); +const debug = require("debug")("Eleventy:cmd"); if (process.env.DEBUG) { require("time-require"); @@ -16,14 +17,30 @@ if (process.env.DEBUG) { const EleventyErrorHandler = require("./src/EleventyErrorHandler"); try { + const EleventyCommandCheckError = require("./src/EleventyCommandCheckError"); const argv = require("minimist")(process.argv.slice(2), { - boolean: ["quiet"], + string: ["input", "output", "formats", "config", "pathprefix", "port"], + boolean: [ + "quiet", + "version", + "watch", + "dryrun", + "help", + "serve", + "passthroughall", + "incremental" + ], default: { quiet: null + }, + unknown: function(unknownArgument) { + throw new EleventyCommandCheckError( + `We don’t know what '${unknownArgument}' is. Use --help to see the list of supported commands.` + ); } }); + debug("command: eleventy ", argv.toString()); const Eleventy = require("./src/Eleventy"); - const EleventyCommandCheck = require("./src/EleventyCommandCheck"); process.on("unhandledRejection", (error, promise) => { EleventyErrorHandler.error( @@ -41,10 +58,6 @@ try { ); }); - // TODO refactor to use minimist options.unknown callback? - let cmdCheck = new EleventyCommandCheck(argv); - cmdCheck.hasUnknownArguments(); - let elev = new Eleventy(argv.input, argv.output); elev.setConfigPathOverride(argv.config); elev.setPathPrefix(argv.pathprefix); diff --git a/src/EleventyCommandCheck.js b/src/EleventyCommandCheck.js deleted file mode 100644 index 8d64a2fa1..000000000 --- a/src/EleventyCommandCheck.js +++ /dev/null @@ -1,83 +0,0 @@ -const EleventyBaseError = require("./EleventyBaseError"); -const debug = require("debug")("Eleventy:CommandCheck"); - -class EleventyCommandCheckError extends EleventyBaseError {} - -class EleventyCommandCheck { - constructor(argv) { - this.valueArgs = [ - "input", - "output", - "formats", - "config", - "pathprefix", - "port" - ]; - - this.booleanArgs = [ - "quiet", - "version", - "watch", - "dryrun", - "help", - "serve", - "passthroughall", - "incremental" - ]; - - this.args = argv; - this.argsMap = this.getArgumentLookupMap(); - - debug("command: eleventy ", this.toString()); - } - - toString() { - let cmd = []; - - for (let valueArgName of this.valueArgs) { - if (this.args[valueArgName]) { - cmd.push(`--${valueArgName}=${this.args[valueArgName]}`); - } - } - - for (let booleanArgName of this.booleanArgs) { - if (this.args[booleanArgName]) { - cmd.push(`--${booleanArgName}`); - } - } - - return cmd.join(" "); - } - - getArgumentLookupMap() { - let obj = {}; - for (let valueArgName of this.valueArgs) { - obj[valueArgName] = true; - } - for (let booleanArgName of this.booleanArgs) { - obj[booleanArgName] = true; - } - return obj; - } - - isKnownArgument(name) { - // _ is the default keyless parameter - if (name === "_") { - return true; - } - - return !!this.argsMap[name]; - } - - hasUnknownArguments() { - for (let argName in this.args) { - if (!this.isKnownArgument(argName)) { - throw new EleventyCommandCheckError( - `We don’t know what '${argName}' is. Use --help to see the list of supported commands.` - ); - } - } - } -} - -module.exports = EleventyCommandCheck; diff --git a/src/EleventyCommandCheckError.js b/src/EleventyCommandCheckError.js new file mode 100644 index 000000000..b36fe94f0 --- /dev/null +++ b/src/EleventyCommandCheckError.js @@ -0,0 +1,3 @@ +const EleventyBaseError = require("./EleventyBaseError"); +class EleventyCommandCheckError extends EleventyBaseError {} +module.exports = EleventyCommandCheckError; diff --git a/test/EleventyCommandCheckTest.js b/test/EleventyCommandCheckTest.js deleted file mode 100644 index 1a26e1af5..000000000 --- a/test/EleventyCommandCheckTest.js +++ /dev/null @@ -1,51 +0,0 @@ -import test from "ava"; -import EleventyCommandCheck from "../src/EleventyCommandCheck"; - -test("Constructor", t => { - let cmdCheck = new EleventyCommandCheck({}); - t.is(cmdCheck.toString(), ""); -}); - -test("Has an argument", t => { - let cmdCheck = new EleventyCommandCheck({ - input: "src" - }); - t.is(cmdCheck.toString(), "--input=src"); -}); - -test("Boolean argument", t => { - let cmdCheck = new EleventyCommandCheck({ - version: true - }); - t.is(cmdCheck.toString(), "--version"); -}); - -test("Multiple arguments", t => { - let cmdCheck = new EleventyCommandCheck({ - input: "src", - version: true - }); - - // technically invalid but eleventy should quit early on --version - t.is(cmdCheck.toString(), "--input=src --version"); -}); - -test("getArgumentLookupMap", t => { - let cmdCheck = new EleventyCommandCheck({}); - t.is(cmdCheck.getArgumentLookupMap()["input"], true); - t.is(cmdCheck.getArgumentLookupMap()["version"], true); - t.falsy(cmdCheck.getArgumentLookupMap()["not-an-arg"]); - - t.is(cmdCheck.isKnownArgument("input"), true); - t.is(cmdCheck.isKnownArgument("version"), true); - t.is(cmdCheck.isKnownArgument("unknown-thing"), false); - - t.is(cmdCheck.isKnownArgument("_"), true); -}); - -test("throws", t => { - let cmdCheck = new EleventyCommandCheck({ "unknown-argument": true }); - t.throws(() => { - cmdCheck.hasUnknownArguments(); - }); -}); From 5e8ebdb1a5a1f5ede9d186dfaf862ef332307ff6 Mon Sep 17 00:00:00 2001 From: samuelpath Date: Fri, 6 Mar 2020 16:07:13 +0100 Subject: [PATCH 149/746] Add proper formatting with line breaks to string property --- cmd.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd.js b/cmd.js index eb140ed68..c654581cb 100755 --- a/cmd.js +++ b/cmd.js @@ -19,7 +19,14 @@ const EleventyErrorHandler = require("./src/EleventyErrorHandler"); try { const EleventyCommandCheckError = require("./src/EleventyCommandCheckError"); const argv = require("minimist")(process.argv.slice(2), { - string: ["input", "output", "formats", "config", "pathprefix", "port"], + string: [ + "input", + "output", + "formats", + "config", + "pathprefix", + "port" + ], boolean: [ "quiet", "version", From 2604277a6ce6d3ab5fb6e5449075a7feb37baa66 Mon Sep 17 00:00:00 2001 From: samuelpath Date: Fri, 6 Mar 2020 16:42:13 +0100 Subject: [PATCH 150/746] Move Template.write in TemplateTest, since only used there (TODO fix) --- src/Template.js | 11 ----------- test/TemplateTest.js | 11 ++++++++++- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Template.js b/src/Template.js index 4ddb56457..500dbe0e3 100644 --- a/src/Template.js +++ b/src/Template.js @@ -584,17 +584,6 @@ class Template extends TemplateContent { return Promise.all(promises); } - // TODO is this still used by anything but tests? - async write(outputPath, data) { - let templates = await this.getRenderedTemplates(data); - let promises = []; - for (let tmpl of templates) { - promises.push(this._write(tmpl.outputPath, tmpl.templateContent)); - } - - return Promise.all(promises); - } - // TODO this but better clone() { let tmpl = new Template( diff --git a/test/TemplateTest.js b/test/TemplateTest.js index e952db3df..a0c177cc0 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -16,6 +16,15 @@ async function getRenderedData(tmpl, pageNumber = 0) { return templates[pageNumber].data; } +async function write(tmpl, data) { + let templates = await tmpl.getRenderedTemplates(data); + let promises = []; + for (let template of templates) { + promises.push(tmpl._write(template.outputPath, template.templateContent)); + } + return Promise.all(promises); +} + function cleanHtml(str) { return pretty(str, { ocd: true }); } @@ -1330,7 +1339,7 @@ test("permalink: false", async t => { t.is(await tmpl.getOutputHref(), false); let data = await tmpl.getData(); - await tmpl.write(false, data); + await write(tmpl, data); // Input file exists (sanity check for paths) t.is(fs.existsSync("./test/stubs/permalink-false/"), true); From 3931ddd6392497346493f4b06a2b26dfc454b883 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Mar 2020 16:01:02 -0600 Subject: [PATCH 151/746] Fix tests --- src/EleventyFiles.js | 42 ++++++++++----------- src/Template.js | 6 ++- src/TemplateFileSlug.js | 7 +--- src/TemplatePassthroughManager.js | 2 +- src/TemplateRender.js | 7 +++- src/TemplateWriter.js | 2 +- test/EleventyFilesTest.js | 4 +- test/TemplateFileSlugTest.js | 61 +++++++++++++++++-------------- test/TemplateWriterTest.js | 6 +-- 9 files changed, 73 insertions(+), 64 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 52acf4fbf..b3b722442 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -51,19 +51,30 @@ class EleventyFiles { this.setupGlobs(); } - get validTemplateAndPassthroughCopyGlobs() { - if (!this._validTemplateAndPassthroughCopyGlobs) { + get validTemplateGlobs() { + if (!this._validTemplateGlobs) { let globs; if (this.input === this.inputDir) { globs = this.extensionMap.getValidGlobs(this.inputDir); } else { globs = this.templateGlobs; } - this._validTemplateAndPassthroughCopyGlobs = globs.concat( - this._getPassthroughPaths() - ); + this._validTemplateGlobs = globs; } - return this._validTemplateAndPassthroughCopyGlobs; + return this._validTemplateGlobs; + } + + get passthroughGlobs() { + let paths = new Set(); + // stuff added in addPassthroughCopy() + for (let path of this.passthroughManager.getConfigPathGlobs()) { + paths.add(path); + } + // non-template language extensions + for (let path of this.extensionMap.getPassthroughCopyGlobs(this.inputDir)) { + paths.add(path); + } + return Array.from(paths); } restart() { @@ -329,9 +340,9 @@ class EleventyFiles { /* For `eleventy --watch` */ getGlobWatcherFiles() { // TODO is it better to tie the includes and data to specific file extensions or keep the **? - return this.validTemplateAndPassthroughCopyGlobs - .concat(this._getIncludesAndDataDirs()) - .concat(this.getPassthroughManager().getConfigPathGlobs()); + return this.validTemplateGlobs + .concat(this.passthroughGlobs) + .concat(this._getIncludesAndDataDirs()); } /* For `eleventy --watch` */ @@ -361,19 +372,6 @@ class EleventyFiles { ); } - _getPassthroughPaths() { - let paths = new Set(); - // stuff added in addPassthroughCopy() - for (let path of this.passthroughManager.getConfigPathGlobs()) { - paths.add(path); - } - // non-template language extensions - for (let path of this.extensionMap.getPassthroughCopyGlobs(this.inputDir)) { - paths.add(path); - } - return Array.from(paths); - } - _getIncludesAndDataDirs() { let files = []; // we want this to fail on "" because we don’t want to ignore the diff --git a/src/Template.js b/src/Template.js index 1031d8083..d722e516a 100644 --- a/src/Template.js +++ b/src/Template.js @@ -47,7 +47,11 @@ class Template extends TemplateContent { this.writeCount = 0; this.skippedCount = 0; this.wrapWithLayouts = true; - this.fileSlug = new TemplateFileSlug(this.inputPath, this.inputDir); + this.fileSlug = new TemplateFileSlug( + this.inputPath, + this.inputDir, + this.extensionMap + ); this.fileSlugStr = this.fileSlug.getSlug(); this.filePathStem = this.fileSlug.getFullPathWithoutExtension(); } diff --git a/src/TemplateFileSlug.js b/src/TemplateFileSlug.js index 8bb39485d..18616c372 100644 --- a/src/TemplateFileSlug.js +++ b/src/TemplateFileSlug.js @@ -1,9 +1,8 @@ const parsePath = require("parse-filepath"); const TemplatePath = require("./TemplatePath"); -const EleventyExtensionMap = require("./EleventyExtensionMap"); class TemplateFileSlug { - constructor(inputPath, inputDir) { + constructor(inputPath, inputDir, extensionMap) { if (inputDir) { inputPath = TemplatePath.stripLeadingSubPath(inputPath, inputDir); } @@ -17,9 +16,7 @@ class TemplateFileSlug { this.parsed = parsePath(inputPath); // TODO update this after the fix for issue #117 merges - this.filenameNoExt = EleventyExtensionMap.removeTemplateExtension( - this.parsed.base - ); + this.filenameNoExt = extensionMap.removeTemplateExtension(this.parsed.base); } getFullPathWithoutExtension() { diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index fed60ca43..4a522b5b3 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -142,7 +142,7 @@ class TemplatePassthroughManager { isPassthroughCopyFile(paths, changedFile) { for (let path of paths) { - if (path === changedFile && !TemplateRender.hasEngine(path)) { + if (path === changedFile && !this.extensionMap.hasEngine(path)) { return true; } } diff --git a/src/TemplateRender.js b/src/TemplateRender.js index ee2652b3f..87a5501b3 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -1,19 +1,21 @@ const TemplatePath = require("./TemplatePath"); const TemplateEngineManager = require("./TemplateEngineManager"); const EleventyBaseError = require("./EleventyBaseError"); +const EleventyExtensionMap = require("./EleventyExtensionMap"); // const debug = require("debug")("Eleventy:TemplateRender"); class TemplateRenderUnknownEngineError extends EleventyBaseError {} // works with full path names or short engine name class TemplateRender { - constructor(tmplPath, inputDir) { + constructor(tmplPath, inputDir, extensionMap) { if (!tmplPath) { throw new Error( `TemplateRender requires a tmplPath argument, instead of ${tmplPath}` ); } + this.extensionMap = extensionMap; this.engineNameOrPath = tmplPath; this.inputDir = inputDir; @@ -40,6 +42,9 @@ class TemplateRender { } get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap(); + } return this._extensionMap; } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index ff584d7ea..9fef9026e 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -101,7 +101,7 @@ class TemplateWriter { async _getAllPaths() { if (!this.allPaths || this.needToSearchForFiles) { - this.allPaths = await this.getFileManager().getFiles(); + this.allPaths = await this.eleventyFiles.getFiles(); debug("Found: %o", this.allPaths); } return this.allPaths; diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 870f5a868..67cd63aa4 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -445,7 +445,7 @@ test("Input to 'src' and empty includes dir (issue #403)", t => { }); evf.init(); - t.deepEqual(evf._testGetFileGlobs(), [ + t.deepEqual(evf.getFileGlobs(), [ "./src/**/*.md", "./src/**/*.liquid", "./src/**/*.html", @@ -513,7 +513,7 @@ test("Issue #403: all .eleventyignores should be relative paths not absolute pat }); evf.init(); - let globs = await evf._testGetFileGlobs(); + let globs = await evf.getFileGlobs(); t.is( globs.filter(glob => { return glob.indexOf(TemplatePath.absolutePath()) > -1; diff --git a/test/TemplateFileSlugTest.js b/test/TemplateFileSlugTest.js index 56fb8335b..36d59d163 100644 --- a/test/TemplateFileSlugTest.js +++ b/test/TemplateFileSlugTest.js @@ -1,44 +1,51 @@ import test from "ava"; import TemplateFileSlug from "../src/TemplateFileSlug"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getNewSlugInstance(path, inputDir) { + let extensionMap = new EleventyExtensionMap(); + let fs = new TemplateFileSlug(path, inputDir, extensionMap); + return fs; +} test("Easy slug", t => { - let fs = new TemplateFileSlug("./file.html"); + let fs = getNewSlugInstance("./file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); test("Easy slug with dot", t => { - let fs = new TemplateFileSlug("./file.test.html"); + let fs = getNewSlugInstance("./file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); test("Easy slug with dot 11ty.js", t => { - let fs = new TemplateFileSlug("./file.test.11ty.js"); + let fs = getNewSlugInstance("./file.test.11ty.js"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); test("Easy slug with date", t => { - let fs = new TemplateFileSlug("./2018-01-01-file.html"); + let fs = getNewSlugInstance("./2018-01-01-file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); test("Easy slug with date and dot in slug", t => { - let fs = new TemplateFileSlug("./2018-01-01-file.test.html"); + let fs = getNewSlugInstance("./2018-01-01-file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); test("Easy slug, index", t => { - let fs = new TemplateFileSlug("./index.html"); + let fs = getNewSlugInstance("./index.html"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); test("Easy slug with date, index", t => { - let fs = new TemplateFileSlug("./2018-01-01-index.html"); + let fs = getNewSlugInstance("./2018-01-01-index.html"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); @@ -46,74 +53,74 @@ test("Easy slug with date, index", t => { /* Directories */ test("Easy slug with dir", t => { - let fs = new TemplateFileSlug("./test/file.html"); + let fs = getNewSlugInstance("./test/file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/test/file"); }); test("Easy slug with dot with dir", t => { - let fs = new TemplateFileSlug("./test/file.test.html"); + let fs = getNewSlugInstance("./test/file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/test/file.test"); }); test("Easy slug with date with dir", t => { - let fs = new TemplateFileSlug("./test/2018-01-01-file.html"); + let fs = getNewSlugInstance("./test/2018-01-01-file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/test/file"); }); test("Easy slug with date and dot in slug with dir", t => { - let fs = new TemplateFileSlug("./test/2018-01-01-file.test.html"); + let fs = getNewSlugInstance("./test/2018-01-01-file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/test/file.test"); }); test("Easy slug, index with dir", t => { - let fs = new TemplateFileSlug("./test/index.html"); + let fs = getNewSlugInstance("./test/index.html"); t.is(fs.getSlug(), "test"); t.is(fs.getFullPathWithoutExtension(), "/test/index"); }); test("Easy slug with date, index with dir", t => { - let fs = new TemplateFileSlug("./test/2018-01-01-index.html"); + let fs = getNewSlugInstance("./test/2018-01-01-index.html"); t.is(fs.getSlug(), "test"); t.is(fs.getFullPathWithoutExtension(), "/test/index"); }); /* Pass Input dir */ test("Easy slug, input dir", t => { - let fs = new TemplateFileSlug("./file.html", "."); + let fs = getNewSlugInstance("./file.html", "."); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); test("Easy slug with dot, input dir", t => { - let fs = new TemplateFileSlug("./file.test.html", "."); + let fs = getNewSlugInstance("./file.test.html", "."); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); test("Easy slug with date, input dir", t => { - let fs = new TemplateFileSlug("./2018-01-01-file.html", "."); + let fs = getNewSlugInstance("./2018-01-01-file.html", "."); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); test("Easy slug with date and dot in slug, input dir", t => { - let fs = new TemplateFileSlug("./2018-01-01-file.test.html", "."); + let fs = getNewSlugInstance("./2018-01-01-file.test.html", "."); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); test("Easy slug, index, input dir", t => { - let fs = new TemplateFileSlug("./index.html", "."); + let fs = getNewSlugInstance("./index.html", "."); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); test("Easy slug with date, index, input dir", t => { - let fs = new TemplateFileSlug("./2018-01-01-index.html", "."); + let fs = getNewSlugInstance("./2018-01-01-index.html", "."); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); @@ -121,49 +128,49 @@ test("Easy slug with date, index, input dir", t => { /* Directories and Input Dir */ test("Easy slug with dir and input dir", t => { - let fs = new TemplateFileSlug("./test/file.html", "./test"); + let fs = getNewSlugInstance("./test/file.html", "./test"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); test("Easy slug with dot with dir and input dir", t => { - let fs = new TemplateFileSlug("./test/file.test.html", "./test"); + let fs = getNewSlugInstance("./test/file.test.html", "./test"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); test("Easy slug with date with dir and input dir", t => { - let fs = new TemplateFileSlug("./test/2018-01-01-file.html", "./test"); + let fs = getNewSlugInstance("./test/2018-01-01-file.html", "./test"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); test("Easy slug with date and dot in slug with dir and input dir", t => { - let fs = new TemplateFileSlug("./test/2018-01-01-file.test.html", "./test"); + let fs = getNewSlugInstance("./test/2018-01-01-file.test.html", "./test"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); test("Easy slug, index with dir and input dir", t => { - let fs = new TemplateFileSlug("./test/index.html", "./test"); + let fs = getNewSlugInstance("./test/index.html", "./test"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); test("Easy slug with date, index with dir and input dir", t => { - let fs = new TemplateFileSlug("./test/2018-01-01-index.html", "./test"); + let fs = getNewSlugInstance("./test/2018-01-01-index.html", "./test"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); test("Easy slug with multiple dirs", t => { - let fs = new TemplateFileSlug("./dir1/dir2/dir3/file.html", "."); + let fs = getNewSlugInstance("./dir1/dir2/dir3/file.html", "."); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/dir1/dir2/dir3/file"); }); test("Easy slug with multiple dirs and an index file", t => { - let fs = new TemplateFileSlug("./dir1/dir2/dir3/index.html", "."); + let fs = getNewSlugInstance("./dir1/dir2/dir3/index.html", "."); t.is(fs.getSlug(), "dir3"); t.is(fs.getFullPathWithoutExtension(), "/dir1/dir2/dir3/index"); }); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 4e48cc1bf..3b766403e 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -367,9 +367,7 @@ Layout 1 dog` test("Glob Watcher Files with Passthroughs", t => { let tw = new TemplateWriter("test/stubs", "test/stubs/_site", ["njk", "png"]); - t.deepEqual(tw.eleventyFiles._getPassthroughPaths(), [ - "./test/stubs/**/*.png" - ]); + t.deepEqual(tw.eleventyFiles.passthroughGlobs, ["./test/stubs/**/*.png"]); }); test("Pagination and TemplateContent", async t => { @@ -622,7 +620,7 @@ test("Passthrough file output", async t => { ["njk", "md"] ); - const mgr = tw.getFileManager().getPassthroughManager(); + const mgr = tw.eleventyFiles.getPassthroughManager(); mgr.setConfig({ passthroughFileCopy: true, passthroughCopies: { From e19faba01beecc1f7c6d1251d0899cbf3649bec3 Mon Sep 17 00:00:00 2001 From: Michael Stillwell Date: Mon, 9 Mar 2020 22:41:11 +0000 Subject: [PATCH 152/746] Throw error if nothing useful is returned --- src/Engines/JavaScript.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 9336e3538..3d12a74f7 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -4,6 +4,7 @@ const EleventyBaseError = require("../EleventyBaseError"); const deleteRequireCache = require("../Util/DeleteRequireCache"); class JavaScriptTemplateInvalidDataFormatError extends EleventyBaseError {} +class JavaScriptTemplateNotDefined extends EleventyBaseError {} class JavaScript extends TemplateEngine { constructor(name, includesDir) { @@ -34,18 +35,12 @@ class JavaScript extends TemplateEngine { mod.prototype && ("data" in mod.prototype || "render" in mod.prototype) ) { - // render function is optional if (!("render" in mod.prototype)) { mod.prototype.render = noop; } return new mod(); } else { - // let fn = function() {}; - // fn.prototype.render = mod; - // return new fn(); - return { - render: mod - }; + return { render: mod }; } } else if ("data" in mod || "render" in mod) { if (!("render" in mod)) { @@ -63,7 +58,13 @@ class JavaScript extends TemplateEngine { const mod = this._getRequire(inputPath); let inst = this._getInstance(mod); - this.instances[inputPath] = inst; + if (inst) { + this.instances[inputPath] = inst; + } else { + throw new JavaScriptTemplateNotDefined( + `No JavaScript template returned from ${inputPath} (did you assign to module.exports?)` + ); + } return inst; } @@ -109,7 +110,6 @@ class JavaScript extends TemplateEngine { let inst; if (str) { // When str has a value, it's being used for permalinks in data - // and maybe not be a str (could be any valid *.11ty.js) inst = this._getInstance(str); } else { // For normal templates, str will be falsy. From a1338070837f2c07fdd31f723757f7aa94ed166d Mon Sep 17 00:00:00 2001 From: samuelpath Date: Tue, 10 Mar 2020 14:37:32 +0100 Subject: [PATCH 153/746] Use getter for pagedItems in Pagination class ("TODO" fix) --- src/Plugins/Pagination.js | 5 ++--- test/PaginationTest.js | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index d94d4e61a..cee6d4c73 100644 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -63,7 +63,7 @@ class Pagination { this.alias = data.pagination.alias; this.target = this._resolveItems(); - this.items = this.getPagedItems(); + this.items = this.pagedItems; } setTemplate(tmpl) { @@ -134,8 +134,7 @@ class Pagination { return result; } - getPagedItems() { - // TODO switch to a getter + get pagedItems() { if (!this.data) { throw new Error("Missing `setData` call for Pagination object."); } diff --git a/test/PaginationTest.js b/test/PaginationTest.js index f0e807cb2..2bb6dccb6 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -13,7 +13,7 @@ test("No data passed to pagination", async t => { let paging = new Pagination(); paging.setTemplate(tmpl); - t.is(paging.getPagedItems().length, 0); + t.is(paging.pagedItems.length, 0); t.is((await paging.getPageTemplates()).length, 0); }); @@ -30,7 +30,7 @@ test("No pagination", async t => { t.falsy(data.pagination); t.is(paging.getPageCount(), 0); - t.is(paging.getPagedItems().length, 0); + t.is(paging.pagedItems.length, 0); t.is((await paging.getPageTemplates()).length, 0); }); @@ -66,7 +66,7 @@ test("Resolve paged data in frontmatter", async t => { paging.setTemplate(tmpl); t.is(paging._resolveItems().length, 8); t.is(paging.getPageCount(), 2); - t.is(paging.getPagedItems().length, 2); + t.is(paging.pagedItems.length, 2); }); test("Paginate data in frontmatter", async t => { From c8e04f0bf767bb12d71266403822a2987477adc4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 18 Mar 2020 17:17:19 -0500 Subject: [PATCH 154/746] Adds support for `init` in custom template engines (in this case to support loading Vue single file components) --- src/Engines/Custom.js | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 4c3c665dc..db9b2d7e0 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -3,13 +3,18 @@ const TemplateEngine = require("./TemplateEngine"); class CustomEngine extends TemplateEngine { constructor(name, includesDir) { super(name, includesDir); + + this.entry = this.getExtensionMapEntry(); + this.needsInit = + "init" in this.entry && typeof this.entry.init === "function"; + this.initFinished = false; } - get compileFunction() { + getExtensionMapEntry() { if ("extensionMap" in this.config) { for (let entry of this.config.extensionMap) { if (entry.key.toLowerCase() === this.name.toLowerCase()) { - return entry.compile; + return entry; } } } @@ -19,23 +24,25 @@ class CustomEngine extends TemplateEngine { ); } + needsToReadFileContents() { + if ("read" in this.entry) { + return this.entry.read; + } + return true; + } + async compile(str, inputPath) { + if (this.needsInit && !this.initFinished) { + await this.entry.init(); + this.initFinished = true; + } + // TODO generalize this (look at JavaScript.js) - return this.compileFunction(str, inputPath); + return this.entry.compile(str, inputPath); } get defaultTemplateFileExtension() { - if ("extensionMap" in this.config) { - for (let entry of this.config.extensionMap) { - if (entry.key.toLowerCase() === this.name.toLowerCase()) { - return entry.outputFileExtension; - } - } - } - - throw Error( - `Could not find a custom extension for ${this.name}. Did you add it to your config file?` - ); + return this.entry.outputFileExtension; } } From 041db759ff02c59ea7cb890c5a3f39be00dd6269 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 19 Mar 2020 07:47:14 -0500 Subject: [PATCH 155/746] Allow access to the config in the custom template methods --- src/Engines/Custom.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index db9b2d7e0..154521f48 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -33,12 +33,12 @@ class CustomEngine extends TemplateEngine { async compile(str, inputPath) { if (this.needsInit && !this.initFinished) { - await this.entry.init(); + await this.entry.init.bind({ config: this.config })(); this.initFinished = true; } // TODO generalize this (look at JavaScript.js) - return this.entry.compile(str, inputPath); + return this.entry.compile.bind({ config: this.config })(str, inputPath); } get defaultTemplateFileExtension() { From 2f4b39b62066ebcfe13c8eb630cd8b8920e5e326 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 19 Mar 2020 11:51:43 -0500 Subject: [PATCH 156/746] Adds `addTemplateFormat` config API method to allow additive templateFormats inside of plugins for #117 --- src/TemplateConfig.js | 35 ++++++---- src/TemplateFileSlug.js | 1 - src/TemplateMap.js | 1 + src/UserConfig.js | 19 +++++- config.js => src/defaultConfig.js | 6 +- test/TemplateConfigTest.js | 106 +++++++++++++++++++++++------- test/UserConfigTest.js | 30 +++++++++ 7 files changed, 157 insertions(+), 41 deletions(-) rename config.js => src/defaultConfig.js (90%) create mode 100644 test/UserConfigTest.js diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 928b5d07a..f2ae37e3d 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -1,5 +1,6 @@ const fs = require("fs-extra"); const chalk = require("chalk"); +const lodashUniq = require("lodash/uniq"); const lodashMerge = require("lodash/merge"); const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); @@ -51,7 +52,7 @@ class TemplateConfig { } initializeRootConfig() { - this.rootConfig = this.customRootConfig || require("../config.js"); + this.rootConfig = this.customRootConfig || require("./defaultConfig.js"); if (typeof this.rootConfig === "function") { this.rootConfig = this.rootConfig(eleventyConfig); @@ -61,7 +62,6 @@ class TemplateConfig { } mergeConfig(localProjectConfigPath) { - let overrides = ["templateFormats"]; let localConfig = {}; let path = TemplatePath.join( TemplatePath.getWorkingDir(), @@ -106,14 +106,19 @@ class TemplateConfig { } let eleventyConfigApiMergingObject = eleventyConfig.getMergingConfigObject(); + + // remove special merge keys from object + let savedForSpecialMerge = { + templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded + }; + delete eleventyConfigApiMergingObject.templateFormatsAdded; + localConfig = lodashMerge(localConfig, eleventyConfigApiMergingObject); // blow away any templateFormats set in config return object and prefer those set in config API. - for (let localConfigKey of overrides) { - localConfig[localConfigKey] = - eleventyConfigApiMergingObject[localConfigKey] || - localConfig[localConfigKey]; - } + localConfig.templateFormats = + eleventyConfigApiMergingObject.templateFormats || + localConfig.templateFormats; // debug("eleventyConfig.getMergingConfigObject: %o", eleventyConfig.getMergingConfigObject()); debug("localConfig: %o", localConfig); @@ -121,12 +126,20 @@ class TemplateConfig { // Object assign overrides original values (good only for templateFormats) but not good for anything else let merged = lodashMerge({}, this.rootConfig, localConfig, this.overrides); - - // blow away any templateFormats upstream (don’t merge) - for (let key of overrides) { - merged[key] = localConfig[key] || this.rootConfig[key]; + // blow away any templateFormats upstream (don’t deep merge) + merged.templateFormats = + localConfig.templateFormats || this.rootConfig.templateFormats; + + // Additive should preserve original templateFormats, wherever those come from (config API or config return object) + if (savedForSpecialMerge.templateFormatsAdded) { + merged.templateFormats = merged.templateFormats.concat( + savedForSpecialMerge.templateFormatsAdded + ); } + // Unique + merged.templateFormats = lodashUniq(merged.templateFormats); + debug("Current configuration: %o", merged); return merged; diff --git a/src/TemplateFileSlug.js b/src/TemplateFileSlug.js index 18616c372..435714266 100644 --- a/src/TemplateFileSlug.js +++ b/src/TemplateFileSlug.js @@ -15,7 +15,6 @@ class TemplateFileSlug { this.dirs.pop(); this.parsed = parsePath(inputPath); - // TODO update this after the fix for issue #117 merges this.filenameNoExt = extensionMap.removeTemplateExtension(this.parsed.base); } diff --git a/src/TemplateMap.js b/src/TemplateMap.js index a3e40f436..2b1a7a514 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -3,6 +3,7 @@ const DependencyGraph = require("dependency-graph").DepGraph; const TemplateCollection = require("./TemplateCollection"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const UsingCircularTemplateContentReferenceError = require("./Errors/UsingCircularTemplateContentReferenceError"); +// TODO the config setup here is overly complex. Why aren’t we injecting config instance like everywhere else? const eleventyConfig = require("./EleventyConfig"); const debug = require("debug")("Eleventy:TemplateMap"); const debugDev = require("debug")("Dev:Eleventy:TemplateMap"); diff --git a/src/UserConfig.js b/src/UserConfig.js index a5c99bc39..4470d4b16 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -19,6 +19,7 @@ class UserConfig { debug("Resetting EleventyConfig to initial values."); this.events = new EventEmitter(); this.collections = {}; + this.templateFormats = undefined; this.liquidOptions = {}; this.liquidTags = {}; @@ -316,12 +317,25 @@ class UserConfig { return this; } - setTemplateFormats(templateFormats) { + _normalizeTemplateFormats(templateFormats) { if (typeof templateFormats === "string") { templateFormats = templateFormats.split(",").map(format => format.trim()); } + return templateFormats; + } - this.templateFormats = templateFormats; + setTemplateFormats(templateFormats) { + this.templateFormats = this._normalizeTemplateFormats(templateFormats); + } + + // additive, usually for plugins + addTemplateFormats(templateFormats) { + if (!this.templateFormatsAdded) { + this.templateFormatsAdded = []; + } + this.templateFormatsAdded = this.templateFormatsAdded.concat( + this._normalizeTemplateFormats(templateFormats) + ); } setLibrary(engineName, libraryInstance) { @@ -617,6 +631,7 @@ class UserConfig { getMergingConfigObject() { return { templateFormats: this.templateFormats, + templateFormatsAdded: this.templateFormatsAdded, filters: this.filters, // now called transforms linters: this.linters, layoutAliases: this.layoutAliases, diff --git a/config.js b/src/defaultConfig.js similarity index 90% rename from config.js rename to src/defaultConfig.js index 8890837ee..fa1b08ca5 100644 --- a/config.js +++ b/src/defaultConfig.js @@ -1,6 +1,6 @@ -const urlFilter = require("./src/Filters/Url"); -const slugFilter = require("./src/Filters/Slug"); -const getCollectionItem = require("./src/Filters/GetCollectionItem"); +const urlFilter = require("./Filters/Url"); +const slugFilter = require("./Filters/Slug"); +const getCollectionItem = require("./Filters/GetCollectionItem"); module.exports = function(config) { config.addFilter("slug", slugFilter); diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 403b88cd0..037254151 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -5,7 +5,7 @@ import eleventyConfig from "../src/EleventyConfig"; test("Template Config local config overrides base config", async t => { let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -38,7 +38,7 @@ test("Add liquid tag", t => { eleventyConfig.addLiquidTag("myTagName", function() {}); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -50,7 +50,7 @@ test("Add nunjucks tag", t => { eleventyConfig.addNunjucksTag("myNunjucksTag", function() {}); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -64,7 +64,7 @@ test("Add liquid filter", t => { }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -76,7 +76,7 @@ test("Add handlebars helper", t => { eleventyConfig.addHandlebarsHelper("myHelperName", function() {}); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -88,7 +88,7 @@ test("Add nunjucks filter", t => { eleventyConfig.addNunjucksFilter("myFilterName", function() {}); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -100,7 +100,7 @@ test("Add universal filter", t => { eleventyConfig.addFilter("myFilterName", function() {}); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -116,7 +116,7 @@ test("Add namespaced universal filter", t => { }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -141,7 +141,7 @@ test("Add namespaced universal filter using underscore", t => { }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -166,7 +166,7 @@ test("Empty namespace", t => { }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -182,7 +182,7 @@ test("Nested Empty Inner namespace", t => { }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -198,7 +198,7 @@ test("Nested Empty Outer namespace", t => { }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -215,7 +215,7 @@ test("Non-string namespaces are ignored", t => { }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -231,7 +231,7 @@ test(".addPlugin oddity: I don’t think pluginNamespace was ever passed in here }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -240,7 +240,7 @@ test(".addPlugin oddity: I don’t think pluginNamespace was ever passed in here test("Test url universal filter with custom pathPrefix (no slash)", t => { let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); templateCfg.setPathPrefix("/testdirectory/"); @@ -250,10 +250,11 @@ test("Test url universal filter with custom pathPrefix (no slash)", t => { test("setTemplateFormats(string)", t => { eleventyConfig.reset(); - eleventyConfig.setTemplateFormats("ejs,njk, liquid"); + // 0.11.0 removes dupes + eleventyConfig.setTemplateFormats("ejs,njk, liquid, njk"); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -265,7 +266,7 @@ test("setTemplateFormats(array)", t => { eleventyConfig.setTemplateFormats(["ejs", "njk", "liquid"]); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -277,7 +278,7 @@ test("setTemplateFormats(array, size 1)", t => { eleventyConfig.setTemplateFormats(["liquid"]); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -289,19 +290,76 @@ test("setTemplateFormats(empty array)", t => { eleventyConfig.setTemplateFormats([]); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); t.deepEqual(cfg.templateFormats, []); }); +test("setTemplateFormats(null)", t => { + eleventyConfig.reset(); + eleventyConfig.setTemplateFormats(null); + + let templateCfg = new TemplateConfig( + require("../src/defaultConfig.js"), + "./test/stubs/config.js" + ); + let cfg = templateCfg.getConfig(); + t.true(cfg.templateFormats.length > 0); +}); + +test("multiple setTemplateFormats calls", t => { + eleventyConfig.reset(); + eleventyConfig.setTemplateFormats("njk"); + eleventyConfig.setTemplateFormats("pug"); + + let templateCfg = new TemplateConfig( + require("../src/defaultConfig.js"), + "./test/stubs/config.js" + ); + let cfg = templateCfg.getConfig(); + t.deepEqual(cfg.templateFormats, ["pug"]); +}); + +test("addTemplateFormats()", t => { + eleventyConfig.reset(); + eleventyConfig.addTemplateFormats("vue"); + + let templateCfg = new TemplateConfig( + require("../src/defaultConfig.js"), + "./test/stubs/config.js" + ); + let cfg = templateCfg.getConfig(); + // should have ALL of the original defaults + t.deepEqual(cfg.templateFormats, ["md", "njk", "vue"]); +}); + +test("both setTemplateFormats and addTemplateFormats", t => { + // Template Formats can come from three places + // defaultConfig.js config API (not used yet) + // defaultConfig.js config return object + // project config file config API + // project config file config return object + + eleventyConfig.reset(); + eleventyConfig.addTemplateFormats("vue"); + eleventyConfig.setTemplateFormats("pug"); + + let templateCfg = new TemplateConfig( + require("../src/defaultConfig.js"), + "./test/stubs/config.js" + ); + let cfg = templateCfg.getConfig(); + t.deepEqual(cfg.templateFormats, ["pug", "vue"]); +}); + test("libraryOverrides", t => { let mdLib = md(); eleventyConfig.setLibrary("md", mdLib); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); @@ -314,7 +372,7 @@ test("libraryOverrides", t => { test("Properly throws error on missing module #182", t => { t.throws(function() { new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/broken-config.js" ); }); @@ -323,7 +381,7 @@ test("Properly throws error on missing module #182", t => { test("Properly throws error when config returns a Promise", t => { t.throws(function() { new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config-promise.js" ); }); @@ -334,7 +392,7 @@ test(".addWatchTarget adds a watch target", t => { eleventyConfig.addWatchTarget("/testdirectory/"); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); diff --git a/test/UserConfigTest.js b/test/UserConfigTest.js new file mode 100644 index 000000000..efebe6902 --- /dev/null +++ b/test/UserConfigTest.js @@ -0,0 +1,30 @@ +import test from "ava"; +import UserConfig from "../src/UserConfig"; + +test("Template Formats", t => { + let cfg = new UserConfig(); + + t.falsy(cfg.getMergingConfigObject().templateFormats); + + cfg.setTemplateFormats("njk,liquid"); + t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); + + // setting multiple times takes the last one + cfg.setTemplateFormats("njk,liquid,pug"); + cfg.setTemplateFormats("njk,liquid"); + t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); +}); + +test("Template Formats (Arrays)", t => { + let cfg = new UserConfig(); + + t.falsy(cfg.getMergingConfigObject().templateFormats); + + cfg.setTemplateFormats(["njk", "liquid"]); + t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); + + // setting multiple times takes the last one + cfg.setTemplateFormats(["njk", "liquid", "pug"]); + cfg.setTemplateFormats(["njk", "liquid"]); + t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); +}); From cf9d7b5f57d0a4bc8689cb984d1af9d21ed7c03c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 19 Mar 2020 13:01:38 -0500 Subject: [PATCH 157/746] Remove unused experiments API --- src/UserConfig.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index 4470d4b16..fa825c96c 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -52,7 +52,6 @@ class UserConfig { this.dynamicPermalinks = true; this.useGitIgnore = true; this.dataDeepMerge = false; - this.experiments = new Set(); this.extensionMap = new Set(); this.watchJavaScriptDependencies = true; this.additionalWatchTargets = []; @@ -576,10 +575,6 @@ class UserConfig { ); } - addExperiment(key) { - this.experiments.add(key); - } - setDataDeepMerge(deepMerge) { this.dataDeepMerge = !!deepMerge; } @@ -659,7 +654,6 @@ class UserConfig { dynamicPermalinks: this.dynamicPermalinks, useGitIgnore: this.useGitIgnore, dataDeepMerge: this.dataDeepMerge, - experiments: this.experiments, watchJavaScriptDependencies: this.watchJavaScriptDependencies, additionalWatchTargets: this.additionalWatchTargets, browserSyncConfig: this.browserSyncConfig, From 24155cc6446b47f0363249d524eae3bafaa99957 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 19 Mar 2020 17:05:56 -0500 Subject: [PATCH 158/746] Get current input directory from this.config --- src/Eleventy.js | 2 ++ src/TemplateConfig.js | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/Eleventy.js b/src/Eleventy.js index cf9a0488f..f6349e0e6 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -273,6 +273,8 @@ class Eleventy { * @returns {} - tbd. */ async init() { + this.config.inputDir = this.inputDir; + let formats = this.formatsOverride || this.config.templateFormats; this.extensionMap = new EleventyExtensionMap(formats); diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index f2ae37e3d..041f92fa1 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -29,6 +29,14 @@ class TemplateConfig { return TemplatePath.addLeadingDotSlash(this.localProjectConfigPath); } + get inputDir() { + return this._inputDir; + } + + set inputDir(inputDir) { + this._inputDir = inputDir; + } + reset() { eleventyConfig.reset(); this.initializeRootConfig(); From d44f9ee089697989f0db11faff081a4681f07e3e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 19 Mar 2020 20:36:26 -0500 Subject: [PATCH 159/746] Add warning about unstable addExtension --- src/UserConfig.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/UserConfig.js b/src/UserConfig.js index fa825c96c..a82823200 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -608,6 +608,11 @@ class UserConfig { } addExtension(fileExtension, options = {}) { + console.log( + chalk.yellow( + "Warning: Configuration API `addExtension` is an undocumented experimental feature of Eleventy with an unstable API. Be careful!" + ) + ); this.extensionMap.add( Object.assign( { From 679d353805e80155b43f8803bbe59bb8a474d793 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Mar 2020 07:11:10 -0500 Subject: [PATCH 160/746] Updating experimental warning --- src/UserConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index a82823200..bcb2440a8 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -610,7 +610,7 @@ class UserConfig { addExtension(fileExtension, options = {}) { console.log( chalk.yellow( - "Warning: Configuration API `addExtension` is an undocumented experimental feature of Eleventy with an unstable API. Be careful!" + "Warning: Configuration API `addExtension` is an experimental Eleventy feature with an unstable API. Be careful!" ) ); this.extensionMap.add( From b49765e95a6be004282b32928c79113f5b6710a9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Mar 2020 07:17:57 -0500 Subject: [PATCH 161/746] #117 needs more testing before release --- src/UserConfig.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index bcb2440a8..bb4f08bf9 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -52,7 +52,6 @@ class UserConfig { this.dynamicPermalinks = true; this.useGitIgnore = true; this.dataDeepMerge = false; - this.extensionMap = new Set(); this.watchJavaScriptDependencies = true; this.additionalWatchTargets = []; this.browserSyncConfig = {}; @@ -607,23 +606,6 @@ class UserConfig { this.quietMode = !!quietMode; } - addExtension(fileExtension, options = {}) { - console.log( - chalk.yellow( - "Warning: Configuration API `addExtension` is an experimental Eleventy feature with an unstable API. Be careful!" - ) - ); - this.extensionMap.add( - Object.assign( - { - key: fileExtension, - extension: fileExtension - }, - options - ) - ); - } - addDataExtension(formatExtension, formatParser) { this.dataExtensions.set(formatExtension, formatParser); } @@ -666,7 +648,6 @@ class UserConfig { watchThrottleWaitTime: this.watchThrottleWaitTime, frontMatterParsingOptions: this.frontMatterParsingOptions, dataExtensions: this.dataExtensions, - extensionMap: this.extensionMap, quietMode: this.quietMode }; } From 21b7dbfa8cac9722082970619de21349da6b8d63 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Mar 2020 07:19:51 -0500 Subject: [PATCH 162/746] #117 needs more testing before release --- src/UserConfig.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/UserConfig.js b/src/UserConfig.js index bb4f08bf9..a09292f4b 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -52,6 +52,7 @@ class UserConfig { this.dynamicPermalinks = true; this.useGitIgnore = true; this.dataDeepMerge = false; + this.extensionMap = new Set(); this.watchJavaScriptDependencies = true; this.additionalWatchTargets = []; this.browserSyncConfig = {}; @@ -606,6 +607,23 @@ class UserConfig { this.quietMode = !!quietMode; } + // addExtension(fileExtension, options = {}) { + // console.log( + // chalk.yellow( + // "Warning: Configuration API `addExtension` is an experimental Eleventy feature with an unstable API. Be careful!" + // ) + // ); + // this.extensionMap.add( + // Object.assign( + // { + // key: fileExtension, + // extension: fileExtension + // }, + // options + // ) + // ); + // } + addDataExtension(formatExtension, formatParser) { this.dataExtensions.set(formatExtension, formatParser); } @@ -648,6 +666,7 @@ class UserConfig { watchThrottleWaitTime: this.watchThrottleWaitTime, frontMatterParsingOptions: this.frontMatterParsingOptions, dataExtensions: this.dataExtensions, + extensionMap: this.extensionMap, quietMode: this.quietMode }; } From 565d58814d3a4119076e7e90f83d8bbbe3ffe5ac Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Mar 2020 07:40:17 -0500 Subject: [PATCH 163/746] Fixes #1023 Fixes #1025 --- package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 97b98e1b3..3d66a2ca9 100755 --- a/package.json +++ b/package.json @@ -76,14 +76,14 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.1", - "ava": "^3.4.0", + "ava": "^3.5.0", "husky": "^4.2.3", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", "jsdoc": "3.6.3", - "lint-staged": "^10.0.7", + "lint-staged": "^10.0.8", "markdown-it-emoji": "^1.4.0", - "node-sass": "^4.12.0", + "node-sass": "^4.13.1", "nyc": "^15.0.0", "prettier": "^1.19.1", "rimraf": "^3.0.2", @@ -99,8 +99,8 @@ "chokidar": "^3.3.1", "debug": "^4.1.1", "dependency-graph": "^0.9.0", - "ejs": "^2.6.2", - "fast-glob": "^3.1.1", + "ejs": "^2.7.4", + "fast-glob": "^3.2.2", "fs-extra": "^8.1.0", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", @@ -110,19 +110,19 @@ "lodash": "^4.17.15", "luxon": "^1.22.0", "markdown-it": "^8.4.2", - "minimist": "^1.2.0", + "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^4.0.0", - "mustache": "^2.3.0", + "mustache": "^2.3.2", "normalize-path": "^3.0.0", - "nunjucks": "^3.2.0", + "nunjucks": "^3.2.1", "parse-filepath": "^1.0.2", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^2.0.4", "recursive-copy": "^2.0.10", "semver": "^7.1.3", - "slugify": "^1.3.6", + "slugify": "^1.4.0", "time-require": "^0.1.2", "valid-url": "^1.0.9" }, From 9b47286fa56ed1aa5d9c09a9976ad430d77abc97 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Mar 2020 09:52:53 -0500 Subject: [PATCH 164/746] =?UTF-8?q?Uncomments=20addExtension=20?= =?UTF-8?q?=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/UserConfig.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index a09292f4b..bcb2440a8 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -607,22 +607,22 @@ class UserConfig { this.quietMode = !!quietMode; } - // addExtension(fileExtension, options = {}) { - // console.log( - // chalk.yellow( - // "Warning: Configuration API `addExtension` is an experimental Eleventy feature with an unstable API. Be careful!" - // ) - // ); - // this.extensionMap.add( - // Object.assign( - // { - // key: fileExtension, - // extension: fileExtension - // }, - // options - // ) - // ); - // } + addExtension(fileExtension, options = {}) { + console.log( + chalk.yellow( + "Warning: Configuration API `addExtension` is an experimental Eleventy feature with an unstable API. Be careful!" + ) + ); + this.extensionMap.add( + Object.assign( + { + key: fileExtension, + extension: fileExtension + }, + options + ) + ); + } addDataExtension(formatExtension, formatParser) { this.dataExtensions.set(formatExtension, formatParser); From b2e84639d7fc144142e6f32f5a6200a25757dbe8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Mar 2020 12:05:57 -0500 Subject: [PATCH 165/746] Experimental features require ELEVENTY_EXPERIMENTAL environment variable to opt-in --- src/UserConfig.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/UserConfig.js b/src/UserConfig.js index bcb2440a8..70018c687 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -608,11 +608,16 @@ class UserConfig { } addExtension(fileExtension, options = {}) { + if (!process.env.ELEVENTY_EXPERIMENTAL) { + return; + } + console.log( chalk.yellow( "Warning: Configuration API `addExtension` is an experimental Eleventy feature with an unstable API. Be careful!" ) ); + this.extensionMap.add( Object.assign( { From 404e57b5cbfd8d1687a78b517a0941acfd71ba56 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 20 Mar 2020 12:13:52 -0500 Subject: [PATCH 166/746] v0.11.0-beta.2 --- docs-src/_data/coverage.json | 41 +++++++++++++++++++----------------- docs/coverage.md | 39 ++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index b543ac8ab..24a2d05ed 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,40 +1,43 @@ -{"total": {"lines":{"total":3054,"covered":2685,"skipped":0,"pct":87.92},"statements":{"total":3073,"covered":2704,"skipped":0,"pct":87.99},"functions":{"total":724,"covered":626,"skipped":0,"pct":86.46},"branches":{"total":1309,"covered":1052,"skipped":0,"pct":80.37}} -,"/Users/zachleat/Code/eleventy/config.js": {"lines":{"total":14,"covered":11,"skipped":0,"pct":78.57},"functions":{"total":4,"covered":1,"skipped":0,"pct":25},"statements":{"total":14,"covered":11,"skipped":0,"pct":78.57},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":3232,"covered":2842,"skipped":0,"pct":87.93},"statements":{"total":3254,"covered":2863,"skipped":0,"pct":87.98},"functions":{"total":777,"covered":670,"skipped":0,"pct":86.23},"branches":{"total":1392,"covered":1123,"skipped":0,"pct":80.68}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":15,"covered":13,"skipped":0,"pct":86.67},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":15,"covered":13,"skipped":0,"pct":86.67},"branches":{"total":6,"covered":4,"skipped":0,"pct":66.67}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":44,"covered":23,"skipped":0,"pct":52.27},"functions":{"total":9,"covered":5,"skipped":0,"pct":55.56},"statements":{"total":44,"covered":23,"skipped":0,"pct":52.27},"branches":{"total":12,"covered":3,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":17,"covered":13,"skipped":0,"pct":76.47},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":17,"covered":13,"skipped":0,"pct":76.47},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} -,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":49,"covered":48,"skipped":0,"pct":97.96},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":49,"covered":48,"skipped":0,"pct":97.96},"branches":{"total":18,"covered":15,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":52,"covered":51,"skipped":0,"pct":98.08},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":51,"skipped":0,"pct":98.08},"branches":{"total":18,"covered":16,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":193,"covered":105,"skipped":0,"pct":54.4},"functions":{"total":34,"covered":19,"skipped":0,"pct":55.88},"statements":{"total":193,"covered":105,"skipped":0,"pct":54.4},"branches":{"total":73,"covered":27,"skipped":0,"pct":36.99}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":208,"covered":115,"skipped":0,"pct":55.29},"functions":{"total":39,"covered":19,"skipped":0,"pct":48.72},"statements":{"total":209,"covered":115,"skipped":0,"pct":55.02},"branches":{"total":66,"covered":27,"skipped":0,"pct":40.91}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":35,"skipped":0,"pct":89.74},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":39,"covered":35,"skipped":0,"pct":89.74},"branches":{"total":43,"covered":29,"skipped":0,"pct":67.44}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":19,"covered":19,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":60,"covered":58,"skipped":0,"pct":96.67},"functions":{"total":25,"covered":23,"skipped":0,"pct":92},"statements":{"total":60,"covered":58,"skipped":0,"pct":96.67},"branches":{"total":27,"covered":27,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":137,"covered":130,"skipped":0,"pct":94.89},"functions":{"total":37,"covered":33,"skipped":0,"pct":89.19},"statements":{"total":137,"covered":130,"skipped":0,"pct":94.89},"branches":{"total":51,"covered":47,"skipped":0,"pct":92.16}} -,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":61,"covered":22,"skipped":0,"pct":36.07},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":61,"covered":22,"skipped":0,"pct":36.07},"branches":{"total":41,"covered":10,"skipped":0,"pct":24.39}} +,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":59,"covered":59,"skipped":0,"pct":100},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":59,"covered":59,"skipped":0,"pct":100},"branches":{"total":29,"covered":29,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":157,"covered":147,"skipped":0,"pct":93.63},"functions":{"total":40,"covered":36,"skipped":0,"pct":90},"statements":{"total":157,"covered":147,"skipped":0,"pct":93.63},"branches":{"total":61,"covered":51,"skipped":0,"pct":83.61}} +,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":59,"covered":22,"skipped":0,"pct":37.29},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":59,"covered":22,"skipped":0,"pct":37.29},"branches":{"total":36,"covered":10,"skipped":0,"pct":27.78}} +,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":33,"covered":33,"skipped":0,"pct":100},"functions":{"total":16,"covered":16,"skipped":0,"pct":100},"statements":{"total":35,"covered":35,"skipped":0,"pct":100},"branches":{"total":17,"covered":15,"skipped":0,"pct":88.24}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":298,"covered":283,"skipped":0,"pct":94.97},"functions":{"total":53,"covered":52,"skipped":0,"pct":98.11},"statements":{"total":300,"covered":285,"skipped":0,"pct":95},"branches":{"total":113,"covered":99,"skipped":0,"pct":87.61}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":298,"covered":283,"skipped":0,"pct":94.97},"functions":{"total":53,"covered":52,"skipped":0,"pct":98.11},"statements":{"total":300,"covered":285,"skipped":0,"pct":95},"branches":{"total":111,"covered":98,"skipped":0,"pct":88.29}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":31,"covered":28,"skipped":0,"pct":90.32},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":34,"covered":31,"skipped":0,"pct":91.18},"branches":{"total":10,"covered":7,"skipped":0,"pct":70}} -,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":57,"covered":52,"skipped":0,"pct":91.23},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":57,"covered":52,"skipped":0,"pct":91.23},"branches":{"total":24,"covered":22,"skipped":0,"pct":91.67}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":81,"covered":76,"skipped":0,"pct":93.83},"functions":{"total":17,"covered":16,"skipped":0,"pct":94.12},"statements":{"total":81,"covered":76,"skipped":0,"pct":93.83},"branches":{"total":34,"covered":31,"skipped":0,"pct":91.18}} -,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":206,"covered":197,"skipped":0,"pct":95.63},"functions":{"total":38,"covered":37,"skipped":0,"pct":97.37},"statements":{"total":209,"covered":200,"skipped":0,"pct":95.69},"branches":{"total":75,"covered":65,"skipped":0,"pct":86.67}} -,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":62,"covered":55,"skipped":0,"pct":88.71},"functions":{"total":10,"covered":6,"skipped":0,"pct":60},"statements":{"total":62,"covered":55,"skipped":0,"pct":88.71},"branches":{"total":26,"covered":24,"skipped":0,"pct":92.31}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":87,"covered":83,"skipped":0,"pct":95.4},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":87,"covered":83,"skipped":0,"pct":95.4},"branches":{"total":36,"covered":33,"skipped":0,"pct":91.67}} +,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":214,"covered":205,"skipped":0,"pct":95.79},"functions":{"total":40,"covered":39,"skipped":0,"pct":97.5},"statements":{"total":217,"covered":208,"skipped":0,"pct":95.85},"branches":{"total":78,"covered":68,"skipped":0,"pct":87.18}} +,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateGlob.js": {"lines":{"total":15,"covered":14,"skipped":0,"pct":93.33},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":73,"covered":73,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":74,"covered":74,"skipped":0,"pct":100},"branches":{"total":16,"covered":16,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":47,"covered":45,"skipped":0,"pct":95.74},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":47,"covered":45,"skipped":0,"pct":95.74},"branches":{"total":18,"covered":16,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":237,"covered":232,"skipped":0,"pct":97.89},"functions":{"total":32,"covered":31,"skipped":0,"pct":96.88},"statements":{"total":237,"covered":232,"skipped":0,"pct":97.89},"branches":{"total":125,"covered":113,"skipped":0,"pct":90.4}} ,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":35,"covered":33,"skipped":0,"pct":94.29},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":35,"covered":33,"skipped":0,"pct":94.29},"branches":{"total":12,"covered":10,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":67,"covered":58,"skipped":0,"pct":86.57},"functions":{"total":19,"covered":18,"skipped":0,"pct":94.74},"statements":{"total":67,"covered":58,"skipped":0,"pct":86.57},"branches":{"total":20,"covered":13,"skipped":0,"pct":65}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":82,"covered":71,"skipped":0,"pct":86.59},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":82,"covered":71,"skipped":0,"pct":86.59},"branches":{"total":32,"covered":23,"skipped":0,"pct":71.88}} ,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":93,"covered":93,"skipped":0,"pct":100},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.67},"statements":{"total":94,"covered":94,"skipped":0,"pct":100},"branches":{"total":48,"covered":48,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":32,"covered":32,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":32,"covered":32,"skipped":0,"pct":100},"branches":{"total":27,"covered":26,"skipped":0,"pct":96.3}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalinkNoWrite.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":77,"covered":76,"skipped":0,"pct":98.7},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":42,"covered":40,"skipped":0,"pct":95.24}} -,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":94,"covered":71,"skipped":0,"pct":75.53},"functions":{"total":25,"covered":17,"skipped":0,"pct":68},"statements":{"total":94,"covered":71,"skipped":0,"pct":75.53},"branches":{"total":16,"covered":6,"skipped":0,"pct":37.5}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":199,"covered":116,"skipped":0,"pct":58.29},"functions":{"total":54,"covered":24,"skipped":0,"pct":44.44},"statements":{"total":200,"covered":117,"skipped":0,"pct":58.5},"branches":{"total":82,"covered":39,"skipped":0,"pct":47.56}} -,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} +,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":87,"covered":83,"skipped":0,"pct":95.4},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":87,"covered":83,"skipped":0,"pct":95.4},"branches":{"total":48,"covered":45,"skipped":0,"pct":93.75}} +,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":113,"covered":90,"skipped":0,"pct":79.65},"functions":{"total":32,"covered":24,"skipped":0,"pct":75},"statements":{"total":113,"covered":90,"skipped":0,"pct":79.65},"branches":{"total":28,"covered":14,"skipped":0,"pct":50}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":209,"covered":122,"skipped":0,"pct":58.37},"functions":{"total":57,"covered":26,"skipped":0,"pct":45.61},"statements":{"total":210,"covered":123,"skipped":0,"pct":58.57},"branches":{"total":88,"covered":41,"skipped":0,"pct":46.59}} +,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":14,"covered":11,"skipped":0,"pct":78.57},"functions":{"total":4,"covered":1,"skipped":0,"pct":25},"statements":{"total":14,"covered":11,"skipped":0,"pct":78.57},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":19,"covered":12,"skipped":0,"pct":63.16},"functions":{"total":5,"covered":3,"skipped":0,"pct":60},"statements":{"total":19,"covered":12,"skipped":0,"pct":63.16},"branches":{"total":12,"covered":6,"skipped":0,"pct":50}} +,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.74},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.74},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} @@ -45,7 +48,7 @@ ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":83,"covered":74,"skipped":0,"pct":89.16},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":83,"covered":74,"skipped":0,"pct":89.16},"branches":{"total":29,"covered":27,"skipped":0,"pct":93.1}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":17,"covered":17,"skipped":0,"pct":100},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":53,"covered":53,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":55,"covered":55,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":49,"covered":49,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":51,"covered":51,"skipped":0,"pct":100},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/GetCollectionItem.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.86}} diff --git a/docs/coverage.md b/docs/coverage.md index ced09ccbd..ef5901d29 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,44 +1,47 @@ -# Code Coverage for Eleventy v0.11.0-beta.1 +# Code Coverage for Eleventy v0.11.0-beta.2 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 87.92% | 87.99% | 86.46% | 80.37% | -| `config.js` | 78.57% | 78.57% | 25% | 100% | +| `total` | 87.93% | 87.98% | 86.23% | 80.68% | | `src/Benchmark.js` | 86.67% | 86.67% | 71.43% | 66.67% | | `src/BenchmarkGroup.js` | 52.27% | 52.27% | 55.56% | 25% | | `src/BenchmarkManager.js` | 76.47% | 76.47% | 71.43% | 75% | -| `src/ComputedData.js` | 97.96% | 97.96% | 100% | 83.33% | +| `src/ComputedData.js` | 98.08% | 98.08% | 85.71% | 88.89% | | `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 54.4% | 54.4% | 55.88% | 36.99% | +| `src/Eleventy.js` | 55.29% | 55.02% | 48.72% | 40.91% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | | `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | | `src/EleventyErrorHandler.js` | 89.74% | 89.74% | 100% | 67.44% | | `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | -| `src/EleventyExtensionMap.js` | 96.67% | 96.67% | 92% | 100% | -| `src/EleventyFiles.js` | 94.89% | 94.89% | 89.19% | 92.16% | -| `src/EleventyServe.js` | 36.07% | 36.07% | 56.25% | 24.39% | +| `src/EleventyExtensionMap.js` | 100% | 100% | 100% | 100% | +| `src/EleventyFiles.js` | 93.63% | 93.63% | 90% | 83.61% | +| `src/EleventyServe.js` | 37.29% | 37.29% | 56.25% | 27.78% | +| `src/EleventyWatch.js` | 100% | 100% | 100% | 88.24% | | `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 93.33% | -| `src/Template.js` | 94.97% | 95% | 98.11% | 87.61% | +| `src/Template.js` | 94.97% | 95% | 98.11% | 88.29% | | `src/TemplateCache.js` | 100% | 100% | 100% | 100% | | `src/TemplateCollection.js` | 90.32% | 91.18% | 93.33% | 70% | -| `src/TemplateConfig.js` | 91.23% | 91.23% | 66.67% | 91.67% | -| `src/TemplateContent.js` | 93.83% | 93.83% | 94.12% | 91.18% | -| `src/TemplateData.js` | 95.63% | 95.69% | 97.37% | 86.67% | +| `src/TemplateConfig.js` | 88.71% | 88.71% | 60% | 92.31% | +| `src/TemplateContent.js` | 95.4% | 95.4% | 100% | 91.67% | +| `src/TemplateData.js` | 95.79% | 95.85% | 97.5% | 87.18% | +| `src/TemplateEngineManager.js` | 100% | 100% | 100% | 100% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | | `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | | `src/TemplateLayout.js` | 100% | 100% | 100% | 100% | | `src/TemplateLayoutPathResolver.js` | 95.74% | 95.74% | 100% | 88.89% | | `src/TemplateMap.js` | 97.89% | 97.89% | 96.88% | 90.4% | | `src/TemplatePassthrough.js` | 94.29% | 94.29% | 88.89% | 83.33% | -| `src/TemplatePassthroughManager.js` | 86.57% | 86.57% | 94.74% | 65% | +| `src/TemplatePassthroughManager.js` | 86.59% | 86.59% | 91.3% | 71.88% | | `src/TemplatePath.js` | 100% | 100% | 96.67% | 100% | -| `src/TemplatePermalink.js` | 100% | 100% | 100% | 100% | +| `src/TemplatePermalink.js` | 100% | 100% | 100% | 96.3% | | `src/TemplatePermalinkNoWrite.js` | 100% | 100% | 100% | 100% | -| `src/TemplateRender.js` | 98.7% | 98.7% | 100% | 95.24% | -| `src/TemplateWriter.js` | 75.53% | 75.53% | 68% | 37.5% | -| `src/UserConfig.js` | 58.29% | 58.5% | 44.44% | 47.56% | -| `src/Engines/Ejs.js` | 95% | 95% | 85.71% | 88.89% | +| `src/TemplateRender.js` | 95.4% | 95.4% | 95.65% | 93.75% | +| `src/TemplateWriter.js` | 79.65% | 79.65% | 75% | 50% | +| `src/UserConfig.js` | 58.37% | 58.57% | 45.61% | 46.59% | +| `src/defaultConfig.js` | 78.57% | 78.57% | 25% | 100% | +| `src/Engines/Custom.js` | 63.16% | 63.16% | 60% | 50% | +| `src/Engines/Ejs.js` | 94.74% | 94.74% | 85.71% | 88.89% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | From 72d2c1a63e95da7b0117c2a6778357301ca29ac5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 25 Mar 2020 16:53:46 -0500 Subject: [PATCH 167/746] Adds `beforeWatch` event that fires when a watch build runs (only on re-runs, not on first run). Code for #1042. Related to #729 --- src/Eleventy.js | 2 ++ src/UserConfig.js | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index f6349e0e6..e4b5dbfd2 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -442,6 +442,8 @@ Arguments: return; } + this.config.events.emit("beforeWatch"); + this.watchManager.setBuildRunning(); // reset and reload global configuration :O diff --git a/src/UserConfig.js b/src/UserConfig.js index 70018c687..5cfd103be 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -672,7 +672,8 @@ class UserConfig { frontMatterParsingOptions: this.frontMatterParsingOptions, dataExtensions: this.dataExtensions, extensionMap: this.extensionMap, - quietMode: this.quietMode + quietMode: this.quietMode, + events: this.events }; } } From 25d90fbb9ec946241aee6cee3438a709a06d6a23 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 25 Mar 2020 23:39:52 -0500 Subject: [PATCH 168/746] Fixes #741. --- src/BenchmarkGroup.js | 20 +++---- src/Engines/Handlebars.js | 3 +- src/Engines/JavaScript.js | 15 +++++- src/Engines/Liquid.js | 13 +++-- src/Engines/Nunjucks.js | 34 +++++++----- test/TemplateRenderHandlebarsTest.js | 39 ++++++++++++++ test/TemplateRenderJavaScriptTest.js | 80 +++++++++++++++++++++++++++- test/TemplateRenderLiquidTest.js | 28 ++++++++++ test/TemplateRenderNunjucksTest.js | 64 +++++++++++++++++++++- 9 files changed, 265 insertions(+), 31 deletions(-) diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index 4e34b4721..29832eae8 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -32,17 +32,17 @@ class BenchmarkGroup { } // callback must return a promise - async addAsync(type, callback) { - let benchmark = (this.benchmarks[type] = new Benchmark()); + // async addAsync(type, callback) { + // let benchmark = (this.benchmarks[type] = new Benchmark()); - benchmark.before(); - // don’t await here. - let promise = callback(); - promise.then(function() { - benchmark.after(); - }); - return promise; - } + // benchmark.before(); + // // don’t await here. + // let promise = callback.call(this); + // promise.then(function() { + // benchmark.after(); + // }); + // return promise; + // } setMinimumThresholdMs(minimumThresholdMs) { let val = parseInt(minimumThresholdMs, 10); diff --git a/src/Engines/Handlebars.js b/src/Engines/Handlebars.js index 54c07dfb4..504aaea18 100644 --- a/src/Engines/Handlebars.js +++ b/src/Engines/Handlebars.js @@ -50,7 +50,8 @@ class Handlebars extends TemplateEngine { content = options.fn(this); } - return callback.apply(this, [content, ...args]); + // TODO breaking change, use { data: this } for consistency with Nunjucks, Liquid, 11ty.js + return callback.call(this, content, ...args); }); } } diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 9336e3538..47fcfc87b 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -105,6 +105,17 @@ class JavaScript extends TemplateEngine { } } + getJavaScriptFunctions(inst, data) { + let fns = {}; + let configFns = this.config.javascriptFunctions; + for (let key in configFns) { + fns[key] = configFns[key].bind( + Object.assign(inst, { templateData: data }) + ); + } + return fns; + } + async compile(str, inputPath) { let inst; if (str) { @@ -117,9 +128,9 @@ class JavaScript extends TemplateEngine { } if (inst && "render" in inst) { - Object.assign(inst, this.config.javascriptFunctions); - return function(data) { + Object.assign(inst, this.getJavaScriptFunctions(inst, data)); + return this.normalize(inst.render.call(inst, data)); }.bind(this); } diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index e2b6ca9cf..913353b81 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -135,8 +135,9 @@ class Liquid extends TemplateEngine { }, render: function(scope, hash) { let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope); - - return Promise.resolve(shortcodeFn(...argArray)); + return Promise.resolve( + shortcodeFn.call({ templateData: scope.contexts[0] }, ...argArray) + ); } }; }); @@ -168,7 +169,13 @@ class Liquid extends TemplateEngine { liquidEngine.renderer .renderTemplates(this.templates, scope) .then(function(html) { - resolve(shortcodeFn(html, ...argArray)); + resolve( + shortcodeFn.call( + { templateData: scope.contexts[0] }, + html, + ...argArray + ) + ); }); }); } diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index aa7af7252..9490acc04 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -93,7 +93,6 @@ class Nunjucks extends TemplateEngine { } parser.advanceAfterBlockEnd(tok.value); - if (isAsync) { return new nodes.CallExtensionAsync(this, "run", args); } @@ -101,20 +100,21 @@ class Nunjucks extends TemplateEngine { }; this.run = function(...args) { - let callback; + let resolve; if (isAsync) { - callback = args.pop(); + resolve = args.pop(); } let [context, ...argArray] = args; if (isAsync) { - shortcodeFn(...argArray) + shortcodeFn + .call({ templateData: context.ctx }, ...argArray) .then(function(returnValue) { - callback(null, new NunjucksLib.runtime.SafeString(returnValue)); + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) .catch(function(e) { - callback( + resolve( new EleventyShortcodeError( `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( e @@ -125,7 +125,10 @@ class Nunjucks extends TemplateEngine { }); } else { try { - return new NunjucksLib.runtime.SafeString(shortcodeFn(...argArray)); + // console.log( shortcodeFn.toString() ); + return new NunjucksLib.runtime.SafeString( + shortcodeFn.call({ templateData: context.ctx }, ...argArray) + ); } catch (e) { throw new EleventyShortcodeError( `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( @@ -160,20 +163,21 @@ class Nunjucks extends TemplateEngine { }; this.run = function(...args) { - let callback; + let resolve; if (isAsync) { - callback = args.pop(); + resolve = args.pop(); } let body = args.pop(); let [context, ...argArray] = args; if (isAsync) { - shortcodeFn(body(), ...argArray) + shortcodeFn + .call({ templateData: context.ctx }, body(), ...argArray) .then(function(returnValue) { - callback(null, new NunjucksLib.runtime.SafeString(returnValue)); + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) .catch(function(e) { - callback( + resolve( new EleventyShortcodeError( `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( e @@ -185,7 +189,11 @@ class Nunjucks extends TemplateEngine { } else { try { return new NunjucksLib.runtime.SafeString( - shortcodeFn(body(), ...argArray) + shortcodeFn.call( + { templateData: context.ctx }, + body(), + ...argArray + ) ); } catch (e) { throw new EleventyShortcodeError( diff --git a/test/TemplateRenderHandlebarsTest.js b/test/TemplateRenderHandlebarsTest.js index 46d4e6107..fd50302bf 100644 --- a/test/TemplateRenderHandlebarsTest.js +++ b/test/TemplateRenderHandlebarsTest.js @@ -114,9 +114,13 @@ test("Handlebars Render Helper (uses argument)", async t => { }); test("Handlebars Render Shortcode", async t => { + t.plan(2); let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodename: function(name) { + // Data in context + t.is(this.name, "Howdy"); + return name.toUpperCase(); } }); @@ -128,9 +132,13 @@ test("Handlebars Render Shortcode", async t => { }); test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { + t.plan(2); let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodenamehtml: function(name) { + // Data in context + t.is(this.name, "Howdy"); + return `${name.toUpperCase()}`; } }); @@ -142,9 +150,15 @@ test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { }); test("Handlebars Render Shortcode (Multiple args)", async t => { + t.plan(3); + let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodename2: function(name, name2) { + // Data in context + t.is(this.name, "Howdy"); + t.is(this.name2, "Zach"); + return name.toUpperCase() + name2.toUpperCase(); } }); @@ -159,9 +173,14 @@ test("Handlebars Render Shortcode (Multiple args)", async t => { }); test("Handlebars Render Paired Shortcode", async t => { + t.plan(2); + let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ shortcodename3: function(content, name, options) { + // Data in context + t.is(this.name, "Howdy"); + return (content + name).toUpperCase(); } }); @@ -173,9 +192,14 @@ test("Handlebars Render Paired Shortcode", async t => { }); test("Handlebars Render Paired Shortcode (HTML)", async t => { + t.plan(2); + let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ shortcodename3html: function(content, name, options) { + // Data in context + t.is(this.name, "Howdy"); + return `${(content + name).toUpperCase()}`; } }); @@ -190,9 +214,14 @@ test("Handlebars Render Paired Shortcode (HTML)", async t => { }); test("Handlebars Render Paired Shortcode (Spaces)", async t => { + t.plan(2); + let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ shortcodename4: function(content, name, options) { + // Data in context + t.is(this.name, "Howdy"); + return (content + name).toUpperCase(); } }); @@ -204,15 +233,25 @@ test("Handlebars Render Paired Shortcode (Spaces)", async t => { }); test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async t => { + t.plan(5); + let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodechild: function(txt, options) { + // Data in context + t.is(this.name, "Howdy"); + t.is(this.name2, "Zach"); + return txt; } }); tr.engine.addPairedShortcodes({ shortcodeparent: function(content, name, name2, options) { + // Data in context + t.is(this.name, "Howdy"); + t.is(this.name2, "Zach"); + return (content + name + name2).toUpperCase(); } }); diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 19fc7f966..f35564cd8 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -188,6 +188,21 @@ test("JS Render with a function", async t => { t.is(await fn({ name: "Bill" }), "

BILLT9000

"); }); +test("JS Render with a function (using `this` instead of arg)", async t => { + let tr = getNewTemplateRender("./test/stubs/function-filter.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(ignoredVal) { + return new String(this.templateData.name).toUpperCase(); + } + } + }; + + let fn = await tr.getCompiledTemplate(); + t.is(await fn({ name: "Zach" }), "

ZACHT9000

"); + t.is(await fn({ name: "Bill" }), "

BILLT9000

"); +}); + // This doesn’t work, per arrow functions test.skip("Issue #934: JS Render with an arrow function and javascript function", async t => { let tr = new TemplateRender("./test/stubs/function-filter-arrow.11ty.js"); @@ -209,7 +224,7 @@ test("JS Render with a function and async filter", async t => { tr.config = { javascriptFunctions: { upper: function(val) { - return new Promise(function(resolve) { + return new Promise(resolve => { resolve(new String(val).toUpperCase()); }); } @@ -221,6 +236,23 @@ test("JS Render with a function and async filter", async t => { t.is(await fn({ name: "Bill" }), "

BILL

"); }); +test("JS Render with a function and async filter (using `this` instead of arg)", async t => { + let tr = new TemplateRender("./test/stubs/function-async-filter.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(val) { + return new Promise(resolve => { + resolve(new String(this.templateData.name).toUpperCase()); + }); + } + } + }; + + let fn = await tr.getCompiledTemplate(); + t.is(await fn({ name: "Zach" }), "

ZACH

"); + t.is(await fn({ name: "Bill" }), "

BILL

"); +}); + test("JS Render with a function prototype", async t => { let tr = getNewTemplateRender("./test/stubs/function-prototype.11ty.js"); tr.config = { @@ -236,6 +268,21 @@ test("JS Render with a function prototype", async t => { t.is(await fn({ name: "Bill" }), "

BILLBillT9001

"); }); +test("JS Render with a function prototype (using `this` instead of arg)", async t => { + let tr = getNewTemplateRender("./test/stubs/function-prototype.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(val) { + return new String(this.templateData.name).toUpperCase(); + } + } + }; + + let fn = await tr.getCompiledTemplate(); + t.is(await fn({ name: "Zach" }), "

ZACHBillT9001

"); + t.is(await fn({ name: "Bill" }), "

BILLBillT9001

"); +}); + test("JS Class Render with a function", async t => { let tr = getNewTemplateRender("./test/stubs/class-filter.11ty.js"); tr.config = { @@ -251,6 +298,21 @@ test("JS Class Render with a function", async t => { t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); }); +test("JS Class Render with a function (using `this` instead of arg)", async t => { + let tr = getNewTemplateRender("./test/stubs/class-filter.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(val) { + return new String(this.templateData.name).toUpperCase(); + } + } + }; + + let fn = await tr.getCompiledTemplate(); + t.is(await fn({ name: "Zach" }), "

ZACHBillTed

"); + t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); +}); + test("JS Class Async Render with a function", async t => { let tr = getNewTemplateRender("./test/stubs/class-async-filter.11ty.js"); tr.config = { @@ -267,6 +329,22 @@ test("JS Class Async Render with a function", async t => { t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); }); +test("JS Class Async Render with a function (using `this` instead of arg)", async t => { + let tr = getNewTemplateRender("./test/stubs/class-async-filter.11ty.js"); + tr.config = { + javascriptFunctions: { + upper: function(val) { + return new String(this.templateData.name).toUpperCase(); + } + } + }; + + let fn = await tr.getCompiledTemplate(); + // Overrides all names to Ted + t.is(await fn({ name: "Zach" }), "

ZACHBillTed

"); + t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); +}); + test("JS Class Async Render with a function (sync function, throws error)", async t => { let tr = new TemplateRender("./test/stubs/function-throws.11ty.js"); tr.config = { diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 84b7a2c27..431efa901 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -268,8 +268,13 @@ test("Liquid addTags", async t => { }); test("Liquid Shortcode", async t => { + t.plan(2); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { + // Data in context + t.is(this.templateData.name, "test"); + return str + "Zach"; }); @@ -280,8 +285,13 @@ test("Liquid Shortcode", async t => { }); test("Liquid Shortcode returns promise", async t => { + t.plan(2); + let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { + // Data in context + t.is(this.templateData.name, "test"); + return new Promise(function(resolve) { setTimeout(function() { resolve(str + "Zach"); @@ -296,8 +306,13 @@ test("Liquid Shortcode returns promise", async t => { }); test("Liquid Shortcode returns promise (await inside)", async t => { + t.plan(2); + let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", async function(str) { + // Data in context + t.is(this.templateData.name, "test"); + return await getPromise(str + "Zach"); }); @@ -308,8 +323,12 @@ test("Liquid Shortcode returns promise (await inside)", async t => { }); test("Liquid Shortcode returns promise (no await inside)", async t => { + t.plan(2); + let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", async function(str) { + // Data in context + t.is(this.templateData.name, "test"); return getPromise(str + "Zach"); }); @@ -320,8 +339,11 @@ test("Liquid Shortcode returns promise (no await inside)", async t => { }); test("Liquid Shortcode Safe Output", async t => { + t.plan(2); let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { + // Data in context + t.is(this.templateData.name, "test"); return `${str}`; }); @@ -332,8 +354,11 @@ test("Liquid Shortcode Safe Output", async t => { }); test("Liquid Paired Shortcode", async t => { + t.plan(2); let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + // Data in context + t.is(this.templateData.name, "test"); return str + content + "Zach"; }); @@ -347,8 +372,11 @@ test("Liquid Paired Shortcode", async t => { }); test("Liquid Async Paired Shortcode", async t => { + t.plan(2); let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + // Data in context + t.is(this.templateData.name, "test"); return new Promise(function(resolve) { setTimeout(function() { resolve(str + content + "Zach"); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index d108d1c36..cf3ab6371 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -290,8 +290,13 @@ test("Nunjucks Shortcode without args", async t => { }); test("Nunjucks Shortcode", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { + // Data in context + t.is(this.templateData.name, "test"); + return str + "Zach"; }); @@ -302,10 +307,15 @@ test("Nunjucks Shortcode", async t => { }); test("Nunjucks Async Shortcode", async t => { + t.plan(2); + let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", function(str) { + // Data in context + t.is(this.templateData.name, "test"); + return new Promise(function(resolve) { setTimeout(function() { resolve(str + "Zach"); @@ -322,10 +332,14 @@ test("Nunjucks Async Shortcode", async t => { }); test("Nunjucks Async function Shortcode", async t => { + t.plan(2); + let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", async function(str) { + // Data in context + t.is(this.templateData.name, "test"); return await getPromise(str + "Zach"); }, true @@ -432,8 +446,13 @@ test("Nunjucks Async function paired Shortcode (with async function, error throw }); test("Nunjucks Shortcode Safe Output", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { + // Data in context + t.is(this.templateData.name, "test"); + return `${str}`; }); @@ -444,8 +463,13 @@ test("Nunjucks Shortcode Safe Output", async t => { }); test("Nunjucks Paired Shortcode", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + // Data in context + t.is(this.templateData.name, "test"); + return str + content + "Zach"; }); @@ -459,10 +483,15 @@ test("Nunjucks Paired Shortcode", async t => { }); test("Nunjucks Async Paired Shortcode", async t => { + t.plan(2); + let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode( "postfixWithZach", function(content, str) { + // Data in context + t.is(this.templateData.name, "test"); + return new Promise(function(resolve) { setTimeout(function() { resolve(str + content + "Zach"); @@ -484,21 +513,29 @@ test("Nunjucks Async Paired Shortcode", async t => { test("Nunjucks Paired Shortcode without args", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content) { + // Data in context + t.is(this.templateData.name, "test"); + return content + "Zach"; }); t.is( await tr._testRender( "{% postfixWithZach %}Content{% endpostfixWithZach %}", - {} + { name: "test" } ), "ContentZach" ); }); test("Nunjucks Paired Shortcode with Tag Inside", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + // Data in context + t.is(this.templateData.name, "test"); + return str + content + "Zach"; }); @@ -512,8 +549,13 @@ test("Nunjucks Paired Shortcode with Tag Inside", async t => { }); test("Nunjucks Nested Paired Shortcode", async t => { + t.plan(3); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + // Data in context + t.is(this.templateData.name, "test"); + return str + content + "Zach"; }); @@ -527,8 +569,13 @@ test("Nunjucks Nested Paired Shortcode", async t => { }); test("Nunjucks Shortcode Multiple Args", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str, str2) { + // Data in context + t.is(this.templateData.name, "test"); + return str + str2 + "Zach"; }); @@ -556,8 +603,13 @@ test("Nunjucks Shortcode Multiple Args (Comma is required)", async t => { }); test("Nunjucks Shortcode Named Args", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { + // Data in context + t.is(this.templateData.name, "test"); + return arg.arg1 + arg.arg2 + "Zach"; }); @@ -571,8 +623,13 @@ test("Nunjucks Shortcode Named Args", async t => { }); test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { + // Data in context + t.is(this.templateData.name, "test"); + return arg.arg1 + arg.arg2 + "Zach"; }); @@ -586,8 +643,13 @@ test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { }); test("Nunjucks Shortcode Named Args (JS notation)", async t => { + t.plan(2); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { + // Data in context + t.is(this.templateData.name, "test"); + return arg.arg1 + arg.arg2 + "Zach"; }); From c1ed84a01a4dde3ad8c5e70ccb1d831f18ab9069 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 26 Mar 2020 09:49:37 -0500 Subject: [PATCH 169/746] Going to limit #741 to just the `page` data right now. --- src/Engines/JavaScript.js | 4 +- src/Engines/Liquid.js | 15 +++- src/Engines/Nunjucks.js | 23 ++++- test/TemplateRenderJavaScriptTest.js | 121 ++++++++------------------- test/TemplateRenderLiquidTest.js | 66 +++++++++++---- test/TemplateRenderNunjucksTest.js | 116 +++++++++++++++++++------ 6 files changed, 206 insertions(+), 139 deletions(-) diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 47fcfc87b..09fa00976 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -109,9 +109,7 @@ class JavaScript extends TemplateEngine { let fns = {}; let configFns = this.config.javascriptFunctions; for (let key in configFns) { - fns[key] = configFns[key].bind( - Object.assign(inst, { templateData: data }) - ); + fns[key] = configFns[key].bind(Object.assign(inst, { page: data.page })); } return fns; } diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 913353b81..5a56dccc8 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -125,6 +125,14 @@ class Liquid extends TemplateEngine { return argArray; } + static _normalizeShortcodeScope(scope) { + let obj = {}; + if (scope && scope.contexts && scope.contexts[0]) { + obj.page = scope.contexts[0].page; + } + return obj; + } + addShortcode(shortcodeName, shortcodeFn) { let _t = this; this.addTag(shortcodeName, function(liquidEngine) { @@ -136,7 +144,10 @@ class Liquid extends TemplateEngine { render: function(scope, hash) { let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope); return Promise.resolve( - shortcodeFn.call({ templateData: scope.contexts[0] }, ...argArray) + shortcodeFn.call( + Liquid._normalizeShortcodeScope(scope), + ...argArray + ) ); } }; @@ -171,7 +182,7 @@ class Liquid extends TemplateEngine { .then(function(html) { resolve( shortcodeFn.call( - { templateData: scope.contexts[0] }, + Liquid._normalizeShortcodeScope(scope), html, ...argArray ) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 9490acc04..821d19811 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -75,6 +75,14 @@ class Nunjucks extends TemplateEngine { } } + static _normalizeShortcodeContext(context) { + let obj = {}; + if (context.ctx && context.ctx.page) { + obj.page = context.ctx.page; + } + return obj; + } + addShortcode(shortcodeName, shortcodeFn, isAsync = false) { function ShortcodeFunction() { this.tags = [shortcodeName]; @@ -109,7 +117,7 @@ class Nunjucks extends TemplateEngine { if (isAsync) { shortcodeFn - .call({ templateData: context.ctx }, ...argArray) + .call(Nunjucks._normalizeShortcodeContext(context), ...argArray) .then(function(returnValue) { resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) @@ -127,7 +135,10 @@ class Nunjucks extends TemplateEngine { try { // console.log( shortcodeFn.toString() ); return new NunjucksLib.runtime.SafeString( - shortcodeFn.call({ templateData: context.ctx }, ...argArray) + shortcodeFn.call( + Nunjucks._normalizeShortcodeContext(context), + ...argArray + ) ); } catch (e) { throw new EleventyShortcodeError( @@ -172,7 +183,11 @@ class Nunjucks extends TemplateEngine { if (isAsync) { shortcodeFn - .call({ templateData: context.ctx }, body(), ...argArray) + .call( + Nunjucks._normalizeShortcodeContext(context), + body(), + ...argArray + ) .then(function(returnValue) { resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) @@ -190,7 +205,7 @@ class Nunjucks extends TemplateEngine { try { return new NunjucksLib.runtime.SafeString( shortcodeFn.call( - { templateData: context.ctx }, + Nunjucks._normalizeShortcodeContext(context), body(), ...argArray ) diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index f35564cd8..580d733e0 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -174,33 +174,24 @@ test("JS Render using ViperHTML", async t => { }); test("JS Render with a function", async t => { + t.plan(8); + let tr = getNewTemplateRender("./test/stubs/function-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { + t.is(this.page.url, "/hi/"); + // sanity check to make sure data didn’t propagate + t.not(this.name, "Zach"); + t.not(this.name, "Bill"); return new String(val).toUpperCase(); } } }; let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACHT9000

"); - t.is(await fn({ name: "Bill" }), "

BILLT9000

"); -}); - -test("JS Render with a function (using `this` instead of arg)", async t => { - let tr = getNewTemplateRender("./test/stubs/function-filter.11ty.js"); - tr.config = { - javascriptFunctions: { - upper: function(ignoredVal) { - return new String(this.templateData.name).toUpperCase(); - } - } - }; - - let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACHT9000

"); - t.is(await fn({ name: "Bill" }), "

BILLT9000

"); + t.is(await fn({ name: "Zach", page: { url: "/hi/" } }), "

ZACHT9000

"); + t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILLT9000

"); }); // This doesn’t work, per arrow functions @@ -220,129 +211,83 @@ test.skip("Issue #934: JS Render with an arrow function and javascript function" }); test("JS Render with a function and async filter", async t => { - let tr = new TemplateRender("./test/stubs/function-async-filter.11ty.js"); - tr.config = { - javascriptFunctions: { - upper: function(val) { - return new Promise(resolve => { - resolve(new String(val).toUpperCase()); - }); - } - } - }; + t.plan(4); - let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACH

"); - t.is(await fn({ name: "Bill" }), "

BILL

"); -}); - -test("JS Render with a function and async filter (using `this` instead of arg)", async t => { let tr = new TemplateRender("./test/stubs/function-async-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { return new Promise(resolve => { - resolve(new String(this.templateData.name).toUpperCase()); + t.is(this.page.url, "/hi/"); + resolve(new String(val).toUpperCase()); }); } } }; let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACH

"); - t.is(await fn({ name: "Bill" }), "

BILL

"); + t.is(await fn({ name: "Zach", page: { url: "/hi/" } }), "

ZACH

"); + t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILL

"); }); test("JS Render with a function prototype", async t => { + t.plan(4); let tr = getNewTemplateRender("./test/stubs/function-prototype.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { + t.is(this.page.url, "/hi/"); return new String(val).toUpperCase(); } } }; let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACHBillT9001

"); - t.is(await fn({ name: "Bill" }), "

BILLBillT9001

"); -}); - -test("JS Render with a function prototype (using `this` instead of arg)", async t => { - let tr = getNewTemplateRender("./test/stubs/function-prototype.11ty.js"); - tr.config = { - javascriptFunctions: { - upper: function(val) { - return new String(this.templateData.name).toUpperCase(); - } - } - }; - - let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACHBillT9001

"); - t.is(await fn({ name: "Bill" }), "

BILLBillT9001

"); + t.is( + await fn({ name: "Zach", page: { url: "/hi/" } }), + "

ZACHBillT9001

" + ); + t.is( + await fn({ name: "Bill", page: { url: "/hi/" } }), + "

BILLBillT9001

" + ); }); test("JS Class Render with a function", async t => { - let tr = getNewTemplateRender("./test/stubs/class-filter.11ty.js"); - tr.config = { - javascriptFunctions: { - upper: function(val) { - return new String(val).toUpperCase(); - } - } - }; + t.plan(4); - let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACHBillTed

"); - t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); -}); - -test("JS Class Render with a function (using `this` instead of arg)", async t => { let tr = getNewTemplateRender("./test/stubs/class-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { - return new String(this.templateData.name).toUpperCase(); + t.is(this.page.url, "/hi/"); + return new String(val).toUpperCase(); } } }; let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACHBillTed

"); - t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); + t.is(await fn({ name: "Zach", page: { url: "/hi/" } }), "

ZACHBillTed

"); + t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILLBillTed

"); }); test("JS Class Async Render with a function", async t => { - let tr = getNewTemplateRender("./test/stubs/class-async-filter.11ty.js"); - tr.config = { - javascriptFunctions: { - upper: function(val) { - return new String(val).toUpperCase(); - } - } - }; - - let fn = await tr.getCompiledTemplate(); - // Overrides all names to Ted - t.is(await fn({ name: "Zach" }), "

ZACHBillTed

"); - t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); -}); + t.plan(4); -test("JS Class Async Render with a function (using `this` instead of arg)", async t => { let tr = getNewTemplateRender("./test/stubs/class-async-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function(val) { - return new String(this.templateData.name).toUpperCase(); + t.is(this.page.url, "/hi/"); + return new String(val).toUpperCase(); } } }; let fn = await tr.getCompiledTemplate(); // Overrides all names to Ted - t.is(await fn({ name: "Zach" }), "

ZACHBillTed

"); - t.is(await fn({ name: "Bill" }), "

BILLBillTed

"); + t.is(await fn({ name: "Zach", page: { url: "/hi/" } }), "

ZACHBillTed

"); + t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILLBillTed

"); }); test("JS Class Async Render with a function (sync function, throws error)", async t => { diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 431efa901..7eae65faf 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -268,18 +268,24 @@ test("Liquid addTags", async t => { }); test("Liquid Shortcode", async t => { - t.plan(2); + t.plan(3); let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); + t.not(this.name, "test"); return str + "Zach"; }); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "testZach" ); }); @@ -290,7 +296,7 @@ test("Liquid Shortcode returns promise", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return new Promise(function(resolve) { setTimeout(function() { @@ -300,7 +306,12 @@ test("Liquid Shortcode returns promise", async t => { }); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "testZach" ); }); @@ -311,13 +322,18 @@ test("Liquid Shortcode returns promise (await inside)", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", async function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return await getPromise(str + "Zach"); }); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "testZach" ); }); @@ -328,12 +344,17 @@ test("Liquid Shortcode returns promise (no await inside)", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", async function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return getPromise(str + "Zach"); }); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "testZach" ); }); @@ -343,12 +364,17 @@ test("Liquid Shortcode Safe Output", async t => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return `${str}`; }); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "test" ); }); @@ -358,14 +384,19 @@ test("Liquid Paired Shortcode", async t => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return str + content + "Zach"; }); t.is( await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", - { name: "test" } + { + name: "test", + page: { + url: "/hi/" + } + } ), "testContentZach" ); @@ -376,7 +407,7 @@ test("Liquid Async Paired Shortcode", async t => { let tr = new TemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return new Promise(function(resolve) { setTimeout(function() { resolve(str + content + "Zach"); @@ -387,7 +418,12 @@ test("Liquid Async Paired Shortcode", async t => { t.is( await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", - { name: "test" } + { + name: "test", + page: { + url: "/hi/" + } + } ), "testContentZach" ); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index cf3ab6371..2f0ab7710 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -290,18 +290,25 @@ test("Nunjucks Shortcode without args", async t => { }); test("Nunjucks Shortcode", async t => { - t.plan(2); + t.plan(3); let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); + // sanity check that all data is not carried forward + t.not(this.name, "test"); return str + "Zach"; }); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "testZach" ); }); @@ -314,7 +321,7 @@ test("Nunjucks Async Shortcode", async t => { "postfixWithZach", function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return new Promise(function(resolve) { setTimeout(function() { @@ -326,7 +333,12 @@ test("Nunjucks Async Shortcode", async t => { ); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "testZach" ); }); @@ -339,14 +351,20 @@ test("Nunjucks Async function Shortcode", async t => { "postfixWithZach", async function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); + return await getPromise(str + "Zach"); }, true ); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "testZach" ); }); @@ -451,13 +469,18 @@ test("Nunjucks Shortcode Safe Output", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return `${str}`; }); t.is( - await tr._testRender("{% postfixWithZach name %}", { name: "test" }), + await tr._testRender("{% postfixWithZach name %}", { + name: "test", + page: { + url: "/hi/" + } + }), "test" ); }); @@ -468,7 +491,7 @@ test("Nunjucks Paired Shortcode", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return str + content + "Zach"; }); @@ -476,7 +499,12 @@ test("Nunjucks Paired Shortcode", async t => { t.is( await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", - { name: "test" } + { + name: "test", + page: { + url: "/hi/" + } + } ), "testContentZach" ); @@ -490,7 +518,7 @@ test("Nunjucks Async Paired Shortcode", async t => { "postfixWithZach", function(content, str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return new Promise(function(resolve) { setTimeout(function() { @@ -504,7 +532,12 @@ test("Nunjucks Async Paired Shortcode", async t => { t.is( await tr._testRender( "{% postfixWithZach name %}Content{% endpostfixWithZach %}", - { name: "test" } + { + name: "test", + page: { + url: "/hi/" + } + } ), "testContentZach" ); @@ -514,7 +547,7 @@ test("Nunjucks Paired Shortcode without args", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return content + "Zach"; }); @@ -522,7 +555,12 @@ test("Nunjucks Paired Shortcode without args", async t => { t.is( await tr._testRender( "{% postfixWithZach %}Content{% endpostfixWithZach %}", - { name: "test" } + { + name: "test", + page: { + url: "/hi/" + } + } ), "ContentZach" ); @@ -534,7 +572,7 @@ test("Nunjucks Paired Shortcode with Tag Inside", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return str + content + "Zach"; }); @@ -542,7 +580,13 @@ test("Nunjucks Paired Shortcode with Tag Inside", async t => { t.is( await tr._testRender( "{% postfixWithZach name %}Content{% if tester %}If{% endif %}{% endpostfixWithZach %}", - { name: "test", tester: true } + { + name: "test", + tester: true, + page: { + url: "/hi/" + } + } ), "testContentIfZach" ); @@ -554,7 +598,7 @@ test("Nunjucks Nested Paired Shortcode", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return str + content + "Zach"; }); @@ -562,7 +606,13 @@ test("Nunjucks Nested Paired Shortcode", async t => { t.is( await tr._testRender( "{% postfixWithZach name %}Content{% postfixWithZach name2 %}Content{% endpostfixWithZach %}{% endpostfixWithZach %}", - { name: "test", name2: "test2" } + { + name: "test", + name2: "test2", + page: { + url: "/hi/" + } + } ), "testContenttest2ContentZachZach" ); @@ -574,7 +624,7 @@ test("Nunjucks Shortcode Multiple Args", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(str, str2) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return str + str2 + "Zach"; }); @@ -582,7 +632,10 @@ test("Nunjucks Shortcode Multiple Args", async t => { t.is( await tr._testRender("{% postfixWithZach name, other %}", { name: "test", - other: "howdy" + other: "howdy", + page: { + url: "/hi/" + } }), "testhowdyZach" ); @@ -608,7 +661,7 @@ test("Nunjucks Shortcode Named Args", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return arg.arg1 + arg.arg2 + "Zach"; }); @@ -616,7 +669,10 @@ test("Nunjucks Shortcode Named Args", async t => { t.is( await tr._testRender("{% postfixWithZach arg1=name, arg2=other %}", { name: "test", - other: "howdy" + other: "howdy", + page: { + url: "/hi/" + } }), "testhowdyZach" ); @@ -628,7 +684,7 @@ test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return arg.arg1 + arg.arg2 + "Zach"; }); @@ -636,7 +692,10 @@ test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { t.is( await tr._testRender("{% postfixWithZach arg2=other, arg1=name %}", { name: "test", - other: "howdy" + other: "howdy", + page: { + url: "/hi/" + } }), "testhowdyZach" ); @@ -648,7 +707,7 @@ test("Nunjucks Shortcode Named Args (JS notation)", async t => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function(arg) { // Data in context - t.is(this.templateData.name, "test"); + t.is(this.page.url, "/hi/"); return arg.arg1 + arg.arg2 + "Zach"; }); @@ -656,7 +715,10 @@ test("Nunjucks Shortcode Named Args (JS notation)", async t => { t.is( await tr._testRender("{% postfixWithZach { arg1: name, arg2: other } %}", { name: "test", - other: "howdy" + other: "howdy", + page: { + url: "/hi/" + } }), "testhowdyZach" ); From 141a71b4424e98b6e596ed357fb1f64533fb7174 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 26 Mar 2020 09:54:20 -0500 Subject: [PATCH 170/746] Add a handlebars test for #741 --- src/Engines/Handlebars.js | 1 - test/TemplateRenderHandlebarsTest.js | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Engines/Handlebars.js b/src/Engines/Handlebars.js index 504aaea18..57a810e9d 100644 --- a/src/Engines/Handlebars.js +++ b/src/Engines/Handlebars.js @@ -50,7 +50,6 @@ class Handlebars extends TemplateEngine { content = options.fn(this); } - // TODO breaking change, use { data: this } for consistency with Nunjucks, Liquid, 11ty.js return callback.call(this, content, ...args); }); } diff --git a/test/TemplateRenderHandlebarsTest.js b/test/TemplateRenderHandlebarsTest.js index fd50302bf..321b0b403 100644 --- a/test/TemplateRenderHandlebarsTest.js +++ b/test/TemplateRenderHandlebarsTest.js @@ -114,12 +114,14 @@ test("Handlebars Render Helper (uses argument)", async t => { }); test("Handlebars Render Shortcode", async t => { - t.plan(2); + t.plan(3); let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ shortcodename: function(name) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); + t.is(this.page.url, "/hi/"); return name.toUpperCase(); } @@ -128,7 +130,10 @@ test("Handlebars Render Shortcode", async t => { let fn = await tr.getCompiledTemplate( "

This is a {{shortcodename name}}.

" ); - t.is(await fn({ name: "Howdy" }), "

This is a HOWDY.

"); + t.is( + await fn({ name: "Howdy", page: { url: "/hi/" } }), + "

This is a HOWDY.

" + ); }); test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { @@ -137,6 +142,7 @@ test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { tr.engine.addShortcodes({ shortcodenamehtml: function(name) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return `${name.toUpperCase()}`; @@ -156,6 +162,7 @@ test("Handlebars Render Shortcode (Multiple args)", async t => { tr.engine.addShortcodes({ shortcodename2: function(name, name2) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); t.is(this.name2, "Zach"); @@ -179,6 +186,7 @@ test("Handlebars Render Paired Shortcode", async t => { tr.engine.addPairedShortcodes({ shortcodename3: function(content, name, options) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return (content + name).toUpperCase(); @@ -198,6 +206,7 @@ test("Handlebars Render Paired Shortcode (HTML)", async t => { tr.engine.addPairedShortcodes({ shortcodename3html: function(content, name, options) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return `${(content + name).toUpperCase()}`; @@ -220,6 +229,7 @@ test("Handlebars Render Paired Shortcode (Spaces)", async t => { tr.engine.addPairedShortcodes({ shortcodename4: function(content, name, options) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return (content + name).toUpperCase(); @@ -239,6 +249,7 @@ test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async tr.engine.addShortcodes({ shortcodechild: function(txt, options) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); t.is(this.name2, "Zach"); @@ -249,6 +260,7 @@ test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async tr.engine.addPairedShortcodes({ shortcodeparent: function(content, name, name2, options) { // Data in context + // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); t.is(this.name2, "Zach"); From 9de36e8fcf9bbedf6199a8f82f12a7e9ca37a62e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 26 Mar 2020 20:52:17 -0500 Subject: [PATCH 171/746] Only set `page` on JavaScript functions if page is not set #741 --- src/Engines/JavaScript.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 09fa00976..7981583e1 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -109,7 +109,12 @@ class JavaScript extends TemplateEngine { let fns = {}; let configFns = this.config.javascriptFunctions; for (let key in configFns) { - fns[key] = configFns[key].bind(Object.assign(inst, { page: data.page })); + // If collision on `page`, prefer user’s `page` + if (!inst || !inst.page) { + fns[key] = configFns[key].bind( + Object.assign(inst, { page: data.page }) + ); + } } return fns; } From 0c9ca1f297837fd0df5b602a8073f5ba2a6c9864 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 27 Mar 2020 16:34:55 -0500 Subject: [PATCH 172/746] v0.11.0-beta.3 --- docs-src/_data/coverage.json | 12 ++++++------ docs/coverage.md | 14 +++++++------- docs/meta-release.md | 4 ++-- package.json | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 24a2d05ed..97ae63326 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,10 +1,10 @@ -{"total": {"lines":{"total":3232,"covered":2842,"skipped":0,"pct":87.93},"statements":{"total":3254,"covered":2863,"skipped":0,"pct":87.98},"functions":{"total":777,"covered":670,"skipped":0,"pct":86.23},"branches":{"total":1392,"covered":1123,"skipped":0,"pct":80.68}} +{"total": {"lines":{"total":3241,"covered":2856,"skipped":0,"pct":88.12},"statements":{"total":3263,"covered":2877,"skipped":0,"pct":88.17},"functions":{"total":778,"covered":673,"skipped":0,"pct":86.5},"branches":{"total":1405,"covered":1135,"skipped":0,"pct":80.78}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":15,"covered":13,"skipped":0,"pct":86.67},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":15,"covered":13,"skipped":0,"pct":86.67},"branches":{"total":6,"covered":4,"skipped":0,"pct":66.67}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":44,"covered":23,"skipped":0,"pct":52.27},"functions":{"total":9,"covered":5,"skipped":0,"pct":55.56},"statements":{"total":44,"covered":23,"skipped":0,"pct":52.27},"branches":{"total":12,"covered":3,"skipped":0,"pct":25}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":38,"covered":23,"skipped":0,"pct":60.53},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":38,"covered":23,"skipped":0,"pct":60.53},"branches":{"total":12,"covered":3,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":17,"covered":13,"skipped":0,"pct":76.47},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":17,"covered":13,"skipped":0,"pct":76.47},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} ,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":52,"covered":51,"skipped":0,"pct":98.08},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":51,"skipped":0,"pct":98.08},"branches":{"total":18,"covered":16,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":208,"covered":115,"skipped":0,"pct":55.29},"functions":{"total":39,"covered":19,"skipped":0,"pct":48.72},"statements":{"total":209,"covered":115,"skipped":0,"pct":55.02},"branches":{"total":66,"covered":27,"skipped":0,"pct":40.91}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":209,"covered":115,"skipped":0,"pct":55.02},"functions":{"total":39,"covered":19,"skipped":0,"pct":48.72},"statements":{"total":210,"covered":115,"skipped":0,"pct":54.76},"branches":{"total":66,"covered":27,"skipped":0,"pct":40.91}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -41,12 +41,12 @@ ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.04},"functions":{"total":12,"covered":12,"skipped":0,"pct":100},"statements":{"total":52,"covered":51,"skipped":0,"pct":98.08},"branches":{"total":42,"covered":37,"skipped":0,"pct":88.1}} +,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":57,"covered":56,"skipped":0,"pct":98.25},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":58,"covered":57,"skipped":0,"pct":98.28},"branches":{"total":46,"covered":41,"skipped":0,"pct":89.13}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScriptTemplateLiteral.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":73,"covered":70,"skipped":0,"pct":95.89},"functions":{"total":26,"covered":25,"skipped":0,"pct":96.15},"statements":{"total":73,"covered":70,"skipped":0,"pct":95.89},"branches":{"total":15,"covered":13,"skipped":0,"pct":86.67}} +,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":77,"covered":74,"skipped":0,"pct":96.1},"functions":{"total":27,"covered":26,"skipped":0,"pct":96.3},"statements":{"total":77,"covered":74,"skipped":0,"pct":96.1},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.63},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.63},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":83,"covered":74,"skipped":0,"pct":89.16},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":83,"covered":74,"skipped":0,"pct":89.16},"branches":{"total":29,"covered":27,"skipped":0,"pct":93.1}} +,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":87,"covered":78,"skipped":0,"pct":89.66},"functions":{"total":24,"covered":23,"skipped":0,"pct":95.83},"statements":{"total":87,"covered":78,"skipped":0,"pct":89.66},"branches":{"total":33,"covered":31,"skipped":0,"pct":93.94}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":17,"covered":17,"skipped":0,"pct":100},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":49,"covered":49,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":51,"covered":51,"skipped":0,"pct":100},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} diff --git a/docs/coverage.md b/docs/coverage.md index ef5901d29..e3cab2522 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,14 +1,14 @@ -# Code Coverage for Eleventy v0.11.0-beta.2 +# Code Coverage for Eleventy v0.11.0-beta.3 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 87.93% | 87.98% | 86.23% | 80.68% | +| `total` | 88.12% | 88.17% | 86.5% | 80.78% | | `src/Benchmark.js` | 86.67% | 86.67% | 71.43% | 66.67% | -| `src/BenchmarkGroup.js` | 52.27% | 52.27% | 55.56% | 25% | +| `src/BenchmarkGroup.js` | 60.53% | 60.53% | 71.43% | 25% | | `src/BenchmarkManager.js` | 76.47% | 76.47% | 71.43% | 75% | | `src/ComputedData.js` | 98.08% | 98.08% | 85.71% | 88.89% | | `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 55.29% | 55.02% | 48.72% | 40.91% | +| `src/Eleventy.js` | 55.02% | 54.76% | 48.72% | 40.91% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | | `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | @@ -45,12 +45,12 @@ | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | -| `src/Engines/JavaScript.js` | 98.04% | 98.08% | 100% | 88.1% | +| `src/Engines/JavaScript.js` | 98.25% | 98.28% | 100% | 89.13% | | `src/Engines/JavaScriptTemplateLiteral.js` | 94.44% | 94.44% | 100% | 100% | -| `src/Engines/Liquid.js` | 95.89% | 95.89% | 96.15% | 86.67% | +| `src/Engines/Liquid.js` | 96.1% | 96.1% | 96.3% | 85% | | `src/Engines/Markdown.js` | 90.63% | 90.63% | 88.89% | 81.25% | | `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | -| `src/Engines/Nunjucks.js` | 89.16% | 89.16% | 95.65% | 93.1% | +| `src/Engines/Nunjucks.js` | 89.66% | 89.66% | 95.83% | 93.94% | | `src/Engines/Pug.js` | 100% | 100% | 100% | 88.89% | | `src/Engines/TemplateEngine.js` | 100% | 100% | 100% | 100% | | `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | diff --git a/docs/meta-release.md b/docs/meta-release.md index 286f0283c..9eb568102 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -1,7 +1,7 @@ # Beta Release Procedure 1. update minor dependencies in package.json? -1. npmclean +1. npmclean aka `rm -rf node_modules && rm -f package-lock.json && npm install` 1. npm audit 1. Make sure `npx ava` runs okay 1. Update version in `package.json`, include `-beta.1` suffix @@ -13,7 +13,7 @@ # Release Procedure 1. update minor dependencies in package.json? `npm outdated` `npm update --save` -1. npmclean first +1. npmclean aka `rm -rf node_modules && rm -f package-lock.json && npm install` 1. npm audit 1. Make sure `npx ava` runs okay 1. Update version in `package.json` diff --git a/package.json b/package.json index 3d66a2ca9..8bc3b3974 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.11.0-beta.2", + "version": "0.11.0-beta.3", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -76,12 +76,12 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.1", - "ava": "^3.5.0", + "ava": "^3.5.1", "husky": "^4.2.3", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", "jsdoc": "3.6.3", - "lint-staged": "^10.0.8", + "lint-staged": "^10.0.9", "markdown-it-emoji": "^1.4.0", "node-sass": "^4.13.1", "nyc": "^15.0.0", @@ -108,7 +108,7 @@ "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", "lodash": "^4.17.15", - "luxon": "^1.22.0", + "luxon": "^1.22.2", "markdown-it": "^8.4.2", "minimist": "^1.2.5", "moo": "^0.5.1", From 87ed8a0b649acc64bdf1565331244dfbcbc69e2a Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 27 Mar 2020 15:41:07 -0700 Subject: [PATCH 173/746] Defer template parsing --- src/Eleventy.js | 8 ++++---- src/Engines/Html.js | 3 ++- src/Engines/Liquid.js | 3 ++- src/Engines/Markdown.js | 6 +++--- src/Engines/TemplateEngine.js | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index e4b5dbfd2..8bbf1b8ca 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -649,7 +649,7 @@ Arguments: this.watcher = watcher; let watchDelay; - async function watchRun(path) { + let watchRun = async path => { try { this._addFileToWatchQueue(path); clearTimeout(watchDelay); @@ -660,16 +660,16 @@ Arguments: EleventyErrorHandler.fatal(e, "Eleventy fatal watch error"); this.stopWatch(); } - } + }; watcher.on("change", async path => { console.log("File changed:", path); - await watchRun.call(this, path); + await watchRun(path); }); watcher.on("add", async path => { console.log("File added:", path); - await watchRun.call(this, path); + await watchRun(path); }); process.on("SIGINT", () => this.stopWatch()); diff --git a/src/Engines/Html.js b/src/Engines/Html.js index 2e50f4fdd..3548bb570 100644 --- a/src/Engines/Html.js +++ b/src/Engines/Html.js @@ -7,9 +7,10 @@ class Html extends TemplateEngine { preTemplateEngine, super.getIncludesDir() ); - let fn = await engine.compile(str, inputPath); + let fnReady = engine.compile(str, inputPath); return async function(data) { + let fn = await fnReady; return fn(data); }; } else { diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 5a56dccc8..e3baf8290 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -196,7 +196,7 @@ class Liquid extends TemplateEngine { async compile(str, inputPath) { let engine = this.liquidLib; - let tmpl = await engine.parse(str, inputPath); + let tmplReady = engine.parse(str, inputPath); // Required for relative includes let options = {}; @@ -209,6 +209,7 @@ class Liquid extends TemplateEngine { ]; } return async function(data) { + let tmpl = await tmplReady; return engine.render(tmpl, data, options); }; } diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index 184e43766..4cc2f4476 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -47,8 +47,6 @@ class Markdown extends TemplateEngine { let mdlib = this.mdLib; if (preTemplateEngine) { - let fn; - let engine; if (typeof preTemplateEngine === "string") { engine = this.engineManager.getEngine( @@ -59,14 +57,16 @@ class Markdown extends TemplateEngine { engine = preTemplateEngine; } - fn = await engine.compile(str, inputPath); + let fnReady = engine.compile(str, inputPath); if (bypassMarkdown) { return async function(data) { + let fn = await fnReady; return fn(data); }; } else { return async function(data) { + let fn = await fnReady; let preTemplateEngineRender = await fn(data); let finishedRender = mdlib.render(preTemplateEngineRender, data); return finishedRender; diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 222d33f20..344cec0a4 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -110,7 +110,7 @@ class TemplateEngine { let fn = await this.compile(str); return fn(data); } catch (e) { - return Promise.reject(e); + throw e; } } From feb5a1eb2dfff20452f802f79ce651cee0dd01df Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 27 Mar 2020 15:49:28 -0700 Subject: [PATCH 174/746] Parellel template processing --- src/Plugins/Pagination.js | 8 ++- src/Template.js | 139 ++++++++++++++++++++------------------ 2 files changed, 80 insertions(+), 67 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index d94d4e61a..3ac93d02d 100644 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -239,8 +239,12 @@ class Pagination { cloned.setPaginationData(override); // TO DO subdirectory to links if the site doesn’t live at / - links.push("/" + (await cloned.getOutputLink())); - hrefs.push(await cloned.getOutputHref()); + let [outputLink, outputHref] = await Promise.all([ + cloned.getOutputLink(), + cloned.getOutputHref() + ]); + links.push("/" + outputLink); + hrefs.push(outputHref); } // we loop twice to pass in the appropriate prev/next links (already full generated now) diff --git a/src/Template.js b/src/Template.js index d722e516a..a14296f72 100644 --- a/src/Template.js +++ b/src/Template.js @@ -189,19 +189,19 @@ class Template extends TemplateContent { let str = await super.render(data, templateData, true); return str; } else if (Array.isArray(data)) { - let arr = []; - for (let j = 0, k = data.length; j < k; j++) { - arr.push(await this.mapDataAsRenderedTemplates(data[j], templateData)); - } - return arr; + return Promise.all( + data.map(item => this.mapDataAsRenderedTemplates(item, templateData)) + ); } else if (lodashIsObject(data)) { let obj = {}; - for (let value in data) { - obj[value] = await this.mapDataAsRenderedTemplates( - data[value], - templateData - ); - } + await Promise.all( + Object.keys(data).map(async value => { + obj[value] = await this.mapDataAsRenderedTemplates( + data[value], + templateData + ); + }) + ); return obj; } @@ -463,40 +463,42 @@ class Template extends TemplateContent { this.paging = new Pagination(data); this.paging.setTemplate(this); let templates = await this.paging.getPageTemplates(); - let pageNumber = 0; - for (let page of templates) { - let pageData = Object.assign({}, await page.getData()); - // Issue #115 - if (data.collections) { - pageData.collections = data.collections; - } + results = await Promise.all( + templates.map(async (page, pageNumber) => { + let pageData = Object.assign({}, await page.getData()); - await page.augmentFinalData(pageData); - - results.push({ - template: page, - inputPath: this.inputPath, - fileSlug: this.fileSlugStr, - filePathStem: this.filePathStem, - data: pageData, - date: pageData.page.date, - pageNumber: pageNumber++, - outputPath: pageData.page.outputPath, - url: pageData.page.url, - set templateContent(content) { - this._templateContent = content; - }, - get templateContent() { - if (this._templateContent === undefined) { - throw new TemplateContentPrematureUseError( - `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` - ); - } - return this._templateContent; + // Issue #115 + if (data.collections) { + pageData.collections = data.collections; } - }); - } + + await page.augmentFinalData(pageData); + + return { + template: page, + inputPath: this.inputPath, + fileSlug: this.fileSlugStr, + filePathStem: this.filePathStem, + data: pageData, + date: pageData.page.date, + pageNumber: pageNumber, + outputPath: pageData.page.outputPath, + url: pageData.page.url, + set templateContent(content) { + this._templateContent = content; + }, + get templateContent() { + if (this._templateContent === undefined) { + throw new TemplateContentPrematureUseError( + `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` + ); + } + return this._templateContent; + } + }; + }) + ); } return results; @@ -504,11 +506,16 @@ class Template extends TemplateContent { async getRenderedTemplates(data) { let pages = await this.getTemplates(data); - for (let page of pages) { - let content = await page.template._getContent(page.outputPath, page.data); + await Promise.all( + pages.map(async page => { + let content = await page.template._getContent( + page.outputPath, + page.data + ); - page.templateContent = content; - } + page.templateContent = content; + }) + ); return pages; } @@ -577,13 +584,12 @@ class Template extends TemplateContent { } async writeMapEntry(mapEntry) { - let promises = []; - for (let page of mapEntry._pages) { - let content = await this.renderPageEntry(mapEntry, page); - promises.push(this._write(page.outputPath, content)); - } - - return Promise.all(promises); + await Promise.all( + mapEntry._pages.map(async page => { + let content = await this.renderPageEntry(mapEntry, page); + return this._write(page.outputPath, content); + }) + ); } // TODO is this still used by anything but tests? @@ -594,7 +600,7 @@ class Template extends TemplateContent { promises.push(this._write(tmpl.outputPath, tmpl.templateContent)); } - return Promise.all(promises); + await Promise.all(promises); } // TODO this but better @@ -718,19 +724,22 @@ class Template extends TemplateContent { async _testCompleteRender() { let entries = await this.getTemplateMapEntries(); - let contents = []; - for (let entry of entries) { - entry._pages = await entry.template.getTemplates(entry.data); + let nestedContent = await Promise.all( + entries.map(async entry => { + entry._pages = await entry.template.getTemplates(entry.data); + return Promise.all( + entry._pages.map(async page => { + page.templateContent = await entry.template.getTemplateMapContent( + page + ); + return this.renderPageEntry(entry, page); + }) + ); + }) + ); - let page; - for (page of entry._pages) { - page.templateContent = await entry.template.getTemplateMapContent(page); - } - for (page of entry._pages) { - contents.push(await this.renderPageEntry(entry, page)); - } - } + let contents = [].concat(...nestedContent); return contents; } } From 02b70c2f39234a031f295ddd3bbee0ab196a4a25 Mon Sep 17 00:00:00 2001 From: harttle Date: Sun, 29 Mar 2020 18:43:30 +0800 Subject: [PATCH 175/746] chore: upgrade 2x performant LiquidJS v9 --- package.json | 2 +- src/Engines/Liquid.js | 57 +++++++++++++++++--------------- test/TemplateRenderLiquidTest.js | 27 ++++++++------- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 8bc3b3974..77da816a0 100755 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "hamljs": "^0.6.2", "handlebars": "^4.7.3", "javascript-stringify": "^2.0.1", - "liquidjs": "^6.4.3", + "liquidjs": "^9.11.7", "lodash": "^4.17.15", "luxon": "^1.22.2", "markdown-it": "^8.4.2", diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 5a56dccc8..4b43164e9 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -1,5 +1,5 @@ const moo = require("moo"); -const LiquidLib = require("liquidjs"); +const liquidLib = require("liquidjs"); const TemplateEngine = require("./TemplateEngine"); const TemplatePath = require("../TemplatePath"); // const debug = require("debug")("Eleventy:Liquid"); @@ -26,7 +26,7 @@ class Liquid extends TemplateEngine { this.liquidLibOverride = lib; // warning, the include syntax supported here does not exactly match what Jekyll uses. - this.liquidLib = lib || LiquidLib(this.getLiquidOptions()); + this.liquidLib = lib || new liquidLib.Liquid(this.getLiquidOptions()); this.setEngineLib(this.liquidLib); this.addFilters(this.config.liquidFilters); @@ -48,7 +48,7 @@ class Liquid extends TemplateEngine { root: [super.getIncludesDir()], // overrides in compile with inputPath below extname: ".liquid", dynamicPartials: false, - strict_filters: false + strictFilters: false }; let options = Object.assign(defaults, this.liquidOptions || {}); @@ -97,7 +97,7 @@ class Liquid extends TemplateEngine { } } - static parseArguments(lexer, str, scope) { + static async parseArguments(lexer, str, scope, engine) { let argArray = []; if (typeof str === "string") { @@ -116,7 +116,7 @@ class Liquid extends TemplateEngine { line: 1, col: 1 }*/ if (arg.type.indexOf("ignore:") === -1) { - argArray.push(LiquidLib.evalExp(arg.value, scope)); // or evalValue + argArray.push(await engine.evalValue(arg.value, scope)); } arg = lexer.next(); } @@ -125,10 +125,10 @@ class Liquid extends TemplateEngine { return argArray; } - static _normalizeShortcodeScope(scope) { + static _normalizeShortcodeScope(ctx) { let obj = {}; - if (scope && scope.contexts && scope.contexts[0]) { - obj.page = scope.contexts[0].page; + if (ctx) { + obj.page = ctx.get(["page"]); } return obj; } @@ -141,8 +141,13 @@ class Liquid extends TemplateEngine { this.name = tagToken.name; this.args = tagToken.args; }, - render: function(scope, hash) { - let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope); + render: async function(scope, hash) { + let argArray = await Liquid.parseArguments( + _t.argLexer, + this.args, + scope, + this.liquid + ); return Promise.resolve( shortcodeFn.call( Liquid._normalizeShortcodeScope(scope), @@ -173,22 +178,22 @@ class Liquid extends TemplateEngine { stream.start(); }, - render: function(scope, hash) { - let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope); - - return new Promise((resolve, reject) => { - liquidEngine.renderer - .renderTemplates(this.templates, scope) - .then(function(html) { - resolve( - shortcodeFn.call( - Liquid._normalizeShortcodeScope(scope), - html, - ...argArray - ) - ); - }); - }); + render: function*(ctx, hash) { + let argArray = yield Liquid.parseArguments( + _t.argLexer, + this.args, + ctx, + this.liquid + ); + const html = yield this.liquid.renderer.renderTemplates( + this.templates, + ctx + ); + return shortcodeFn.call( + Liquid._normalizeShortcodeScope(ctx), + html, + ...argArray + ); } }; }); diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 7eae65faf..ac964daca 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -184,7 +184,7 @@ test("Liquid Custom Tag prefixWithZach", async t => { this.str = tagToken.args; // name }, render: function(scope, hash) { - var str = liquidEngine.evalValue(this.str, scope); // 'alice' + var str = liquidEngine.evalValueSync(this.str, scope); // 'alice' return Promise.resolve("Zach" + str); // 'Alice' } }; @@ -203,8 +203,8 @@ test("Liquid Custom Tag postfixWithZach", async t => { parse: function(tagToken, remainTokens) { this.str = tagToken.args; }, - render: function(scope, hash) { - var str = liquidEngine.evalValue(this.str, scope); + render: async function(scope, hash) { + var str = await liquidEngine.evalValue(this.str, scope); return Promise.resolve(str + "Zach"); } }; @@ -253,8 +253,8 @@ test("Liquid addTags", async t => { parse: function(tagToken, remainTokens) { this.str = tagToken.args; }, - render: function(scope, hash) { - var str = liquidEngine.evalValue(this.str, scope); + render: async function(scope, hash) { + var str = await liquidEngine.evalValue(this.str, scope); return Promise.resolve(str + "Zach"); } }; @@ -620,12 +620,11 @@ test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true, d }); test("Liquid Render: with Library Override", async t => { - let tr = getNewTemplateRender("liquid"); - - let lib = require("liquidjs")(); - tr.engine.setLibrary(lib); + const tr = getNewTemplateRender("liquid"); + const { Liquid } = require("liquidjs"); + tr.engine.setLibrary(new Liquid()); - let fn = await tr.getCompiledTemplate("

{{name | capitalize}}

"); + const fn = await tr.getCompiledTemplate("

{{name | capitalize}}

"); t.is(await fn({ name: "tim" }), "

Tim

"); }); @@ -688,7 +687,7 @@ test.skip("Liquid Include Scope Leak", async t => { }); // TODO this will change in 1.0 -test("Liquid Missing Filter Issue #183 (no strict_filters)", async t => { +test("Liquid Missing Filter Issue #183 (no strictFilters)", async t => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); try { @@ -701,7 +700,7 @@ test("Liquid Missing Filter Issue #183 (no strict_filters)", async t => { test("Liquid Missing Filter Issue #183", async t => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ strict_filters: true }); + tr.engine.setLiquidOptions({ strictFilters: true }); try { await tr._testRender("{{ 'test' | prefixWithZach }}", {}); @@ -729,8 +728,8 @@ test("Issue 347: Liquid addTags with space in argument", async t => { parse: function(tagToken, remainTokens) { this.str = tagToken.args; }, - render: function(scope, hash) { - var str = liquidEngine.evalValue(this.str, scope); + render: async function(scope, hash) { + var str = await liquidEngine.evalValue(this.str, scope); return Promise.resolve(str + "Zach"); } }; From b8a0bdd9059a0018cf18e778e212d40f5ca210aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20G=C3=BCnsche?= Date: Sun, 29 Mar 2020 21:49:59 +0200 Subject: [PATCH 176/746] allow registering Nunjucks globals --- src/Engines/Nunjucks.js | 11 +++++++++++ src/UserConfig.js | 17 +++++++++++++++++ test/TemplateConfigTest.js | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 821d19811..eac33fbf3 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -36,6 +36,7 @@ class Nunjucks extends TemplateEngine { this.config.nunjucksAsyncPairedShortcodes, true ); + this.addGlobals(this.config.nunjucksGlobals); } addFilters(helpers, isAsync) { @@ -63,6 +64,16 @@ class Nunjucks extends TemplateEngine { this.njkEnv.addExtension(name, tagObj); } + addGlobals(globals) { + for (let name in globals) { + this.addGlobal(name, globals[name]); + } + } + + addGlobal(name, globalFn) { + this.njkEnv.addGlobal(name, globalFn); + } + addAllShortcodes(shortcodes, isAsync = false) { for (let name in shortcodes) { this.addShortcode(name, shortcodes[name], isAsync); diff --git a/src/UserConfig.js b/src/UserConfig.js index 5cfd103be..4391fec36 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -29,6 +29,7 @@ class UserConfig { this.nunjucksFilters = {}; this.nunjucksAsyncFilters = {}; this.nunjucksTags = {}; + this.nunjucksGlobals = {}; this.nunjucksShortcodes = {}; this.nunjucksAsyncShortcodes = {}; this.nunjucksPairedShortcodes = {}; @@ -226,6 +227,21 @@ class UserConfig { this.nunjucksTags[name] = bench.add(`"${name}" Nunjucks Custom Tag`, tagFn); } + addNunjucksGlobal(name, globalFn) { + name = this.getNamespacedName(name); + + if (this.nunjucksGlobals[name]) { + debug( + chalk.yellow( + "Warning, overwriting a Nunjucks global with `addNunjucksGlobal(%o)`" + ), + name + ); + } + + this.nunjucksGlobals[name] = bench.add(`"${name}" Nunjucks Global`, globalFn); + } + addTransform(name, callback) { name = this.getNamespacedName(name); @@ -649,6 +665,7 @@ class UserConfig { nunjucksFilters: this.nunjucksFilters, nunjucksAsyncFilters: this.nunjucksAsyncFilters, nunjucksTags: this.nunjucksTags, + nunjucksGlobals: this.nunjucksGlobals, nunjucksAsyncShortcodes: this.nunjucksAsyncShortcodes, nunjucksShortcodes: this.nunjucksShortcodes, nunjucksAsyncPairedShortcodes: this.nunjucksAsyncPairedShortcodes, diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 037254151..3cfe225b3 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -57,6 +57,20 @@ test("Add nunjucks tag", t => { t.not(Object.keys(cfg.nunjucksTags).indexOf("myNunjucksTag"), -1); }); +test("Add nunjucks global", t => { + eleventyConfig.reset(); + eleventyConfig.addNunjucksGlobal("myNunjucksGlobal1", function() {}); + eleventyConfig.addNunjucksGlobal("myNunjucksGlobal2", 42); + + let templateCfg = new TemplateConfig( + require("../src/defaultConfig.js"), + "./test/stubs/config.js" + ); + let cfg = templateCfg.getConfig(); + t.not(Object.keys(cfg.nunjucksGlobals).indexOf("myNunjucksGlobal1"), -1); + t.not(Object.keys(cfg.nunjucksGlobals).indexOf("myNunjucksGlobal2"), -1); +}); + test("Add liquid filter", t => { eleventyConfig.reset(); eleventyConfig.addLiquidFilter("myFilterName", function(liquidEngine) { From b6b4014d221323b7b44fc748c68bca9139e914d2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 31 Mar 2020 08:34:56 -0500 Subject: [PATCH 177/746] Fixes #1056 --- src/Engines/JavaScript.js | 20 ++++++++++++-------- test/TemplateRenderJavaScriptTest.js | 24 ++++++++++++++++++++++++ test/stubs/class-fns-has-page.11ty.js | 12 ++++++++++++ test/stubs/class-fns.11ty.js | 12 ++++++++++++ test/stubs/function-fns.11ty.js | 10 ++++++++++ 5 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 test/stubs/class-fns-has-page.11ty.js create mode 100644 test/stubs/class-fns.11ty.js create mode 100644 test/stubs/function-fns.11ty.js diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 7981583e1..b1aabaf3e 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -105,15 +105,16 @@ class JavaScript extends TemplateEngine { } } - getJavaScriptFunctions(inst, data) { + getJavaScriptFunctions(inst) { let fns = {}; let configFns = this.config.javascriptFunctions; + for (let key in configFns) { - // If collision on `page`, prefer user’s `page` - if (!inst || !inst.page) { - fns[key] = configFns[key].bind( - Object.assign(inst, { page: data.page }) - ); + // prefer pre-existing `page` javascriptFunction, if one exists + if (key === "page") { + // do nothing + } else { + fns[key] = configFns[key].bind(inst); } } return fns; @@ -129,10 +130,13 @@ class JavaScript extends TemplateEngine { // For normal templates, str will be falsy. inst = this.getInstanceFromInputPath(inputPath); } - if (inst && "render" in inst) { return function(data) { - Object.assign(inst, this.getJavaScriptFunctions(inst, data)); + // only blow away existing inst.page if it has a page.url + if (!inst.page || inst.page.url) { + inst.page = data.page; + } + Object.assign(inst, this.getJavaScriptFunctions(inst)); return this.normalize(inst.render.call(inst, data)); }.bind(this); diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 580d733e0..f8f88712f 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -335,3 +335,27 @@ test("JS Class Async Render with a function (async function, throws error)", asy ) > -1 ); }); + +test("JS function has access to built in filters", async t => { + t.plan(6); + let tr = getNewTemplateRender("./test/stubs/function-fns.11ty.js"); + + let fn = await tr.getCompiledTemplate(); + await fn({ avaTest: t, page: { url: "/hi/" } }); +}); + +test("Class has access to built in filters", async t => { + t.plan(6); + let tr = getNewTemplateRender("./test/stubs/class-fns.11ty.js"); + + let fn = await tr.getCompiledTemplate(); + await fn({ avaTest: t, page: { url: "/hi/" } }); +}); + +test("Class has page property already and keeps it", async t => { + t.plan(2); + let tr = getNewTemplateRender("./test/stubs/class-fns-has-page.11ty.js"); + + let fn = await tr.getCompiledTemplate(); + await fn({ avaTest: t, page: { url: "/hi/" } }); +}); diff --git a/test/stubs/class-fns-has-page.11ty.js b/test/stubs/class-fns-has-page.11ty.js new file mode 100644 index 000000000..d7c2608fc --- /dev/null +++ b/test/stubs/class-fns-has-page.11ty.js @@ -0,0 +1,12 @@ +class TestWithPage { + get page() { + return "this-is-my-page"; + } + + render(data) { + data.avaTest.is(this.page, "this-is-my-page"); + data.avaTest.is(data.page.url, "/hi/"); + } +} + +module.exports = TestWithPage; diff --git a/test/stubs/class-fns.11ty.js b/test/stubs/class-fns.11ty.js new file mode 100644 index 000000000..fc12d346f --- /dev/null +++ b/test/stubs/class-fns.11ty.js @@ -0,0 +1,12 @@ +class Test { + render({ avaTest }) { + avaTest.truthy(this.url); + avaTest.truthy(this.slug); + avaTest.truthy(this.log); + avaTest.truthy(this.getPreviousCollectionItem); + avaTest.truthy(this.getNextCollectionItem); + avaTest.truthy(this.page); + } +} + +module.exports = Test; diff --git a/test/stubs/function-fns.11ty.js b/test/stubs/function-fns.11ty.js new file mode 100644 index 000000000..ff40f4196 --- /dev/null +++ b/test/stubs/function-fns.11ty.js @@ -0,0 +1,10 @@ +module.exports = function({ avaTest }) { + avaTest.truthy(this.url); + avaTest.truthy(this.slug); + avaTest.truthy(this.log); + avaTest.truthy(this.getPreviousCollectionItem); + avaTest.truthy(this.getNextCollectionItem); + avaTest.truthy(this.page); + + return "test"; +}; From 7a55e2d721bbfd345ef5c6882f0c1406b5c0f406 Mon Sep 17 00:00:00 2001 From: harttle Date: Wed, 1 Apr 2020 11:46:05 +0800 Subject: [PATCH 178/746] chore: upgrade liquidjs to the latest --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77da816a0..4250c15fd 100755 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "js-yaml": "^3.13.1", "jsdoc": "3.6.3", "lint-staged": "^10.0.9", + "liquidjs": "^9.11.9", "markdown-it-emoji": "^1.4.0", "node-sass": "^4.13.1", "nyc": "^15.0.0", @@ -106,7 +107,6 @@ "hamljs": "^0.6.2", "handlebars": "^4.7.3", "javascript-stringify": "^2.0.1", - "liquidjs": "^9.11.7", "lodash": "^4.17.15", "luxon": "^1.22.2", "markdown-it": "^8.4.2", From 115ff705cccd6ebebcd62be9968602551785f878 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 1 Apr 2020 09:07:15 -0500 Subject: [PATCH 179/746] Fixes #1061 --- src/ComputedData.js | 10 +++++-- test/TemplateTest.js | 26 +++++++++++++++++++ .../eleventyComputed/permalink-simple.njk | 6 +++++ .../stubs/eleventyComputed/permalink-slug.njk | 5 ++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/stubs/eleventyComputed/permalink-simple.njk create mode 100644 test/stubs/eleventyComputed/permalink-slug.njk diff --git a/src/ComputedData.js b/src/ComputedData.js index 9d62f5e01..ead57d251 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -1,5 +1,6 @@ const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); +const debug = require("debug")("Eleventy:ComputedData"); const DependencyGraph = require("dependency-graph").DepGraph; class ComputedData { @@ -51,7 +52,6 @@ class ComputedData { let graph = new DependencyGraph(); let proxyData = this.getProxyData(); - for (let key of this.computedKeys) { let computed = lodashGet(this.computed, key); graph.addNode(key); @@ -65,9 +65,15 @@ class ComputedData { } // squelch console logs for this fake proxy data pass 😅 + let output; let savedLog = console.log; console.log = () => {}; - let output = await computed(proxyData); + try { + // Mitigation for #1061, errors on the first pass shouldn’t fail the whole thing. + output = await computed(proxyData); + } catch (e) { + debug("Computed Data first pass data resolution error: %o", e); + } console.log = savedLog; let vars = this.findVarsInOutput(output); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 69d099e15..74d9d9a22 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2082,6 +2082,32 @@ test("eleventyComputed permalink", async t => { t.is(data.dependsOnPage, "depends:/haha-value1.html"); }); +test("eleventyComputed simple permalink", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/permalink-simple.njk", + "./test/stubs/", + "./dist" + ); + let templates = await tmpl.getTemplates(await tmpl.getData()); + let data = templates[0].data; + t.is(data.page.url, "/haha-value1.html"); + t.is(data.page.outputPath, "./dist/haha-value1.html"); + t.is(data.permalink, "haha-value1.html"); +}); + +test("eleventyComputed permalink using slug", async t => { + let tmpl = new Template( + "./test/stubs/eleventyComputed/permalink-slug.njk", + "./test/stubs/", + "./dist" + ); + let templates = await tmpl.getTemplates(await tmpl.getData()); + let data = templates[0].data; + t.is(data.page.url, "/haha-this-is-a-string.html"); + t.is(data.page.outputPath, "./dist/haha-this-is-a-string.html"); + t.is(data.permalink, "haha-this-is-a-string.html"); +}); + test("eleventyComputed js front matter (function)", async t => { let tmpl = new Template( "./test/stubs/eleventyComputed/second.njk", diff --git a/test/stubs/eleventyComputed/permalink-simple.njk b/test/stubs/eleventyComputed/permalink-simple.njk new file mode 100644 index 000000000..039f63910 --- /dev/null +++ b/test/stubs/eleventyComputed/permalink-simple.njk @@ -0,0 +1,6 @@ +--- +key1: value1 +eleventyComputed: + permalink: "haha-{{key1}}.html" +--- +hi:{{ key2 }} \ No newline at end of file diff --git a/test/stubs/eleventyComputed/permalink-slug.njk b/test/stubs/eleventyComputed/permalink-slug.njk new file mode 100644 index 000000000..544853307 --- /dev/null +++ b/test/stubs/eleventyComputed/permalink-slug.njk @@ -0,0 +1,5 @@ +--- +key1: "This is a string" +eleventyComputed: + permalink: "haha-{{key1 | slug}}.html" +--- \ No newline at end of file From 8ffbb9927ea8482c5a46515f3a2ed25cd8830ad8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 1 Apr 2020 11:02:48 -0500 Subject: [PATCH 180/746] Looks like the mitigation for #1061 fixes #1043 --- src/ComputedData.js | 2 +- test/TemplateTest.js | 15 +++++++++++++++ test/stubs/eleventyComputed/use-global-data.njk | 10 ++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/stubs/eleventyComputed/use-global-data.njk diff --git a/src/ComputedData.js b/src/ComputedData.js index ead57d251..093988e0c 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -68,8 +68,8 @@ class ComputedData { let output; let savedLog = console.log; console.log = () => {}; + // Mitigation for #1061, errors on the first pass shouldn’t fail the whole thing. try { - // Mitigation for #1061, errors on the first pass shouldn’t fail the whole thing. output = await computed(proxyData); } catch (e) { debug("Computed Data first pass data resolution error: %o", e); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 74d9d9a22..baa3b79eb 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2142,3 +2142,18 @@ test("eleventyComputed true primitive", async t => { t.is(data.key3, false); t.is(data.key4, 324); }); + +test("eleventyComputed relies on global data", async t => { + let dataObj = new TemplateData("./test/stubs/"); + let tmpl = new Template( + "./test/stubs/eleventyComputed/use-global-data.njk", + "./test/stubs/", + "./dist", + dataObj + ); + + let fetchedData = await tmpl.getData(); + let templates = await tmpl.getTemplates(fetchedData); + let data = templates[0].data; + t.is(data.image, "datavalue1"); +}); diff --git a/test/stubs/eleventyComputed/use-global-data.njk b/test/stubs/eleventyComputed/use-global-data.njk new file mode 100644 index 000000000..31db4e295 --- /dev/null +++ b/test/stubs/eleventyComputed/use-global-data.njk @@ -0,0 +1,10 @@ +---js +{ + eleventyComputed: { + image: data => { + return data.globalData.datakey1; + } + } +} +--- +Issue #1043 \ No newline at end of file From d7b1377429978a04d06dd9d0b4c073beb3c8f9dd Mon Sep 17 00:00:00 2001 From: Steven Petryk Date: Fri, 3 Apr 2020 17:09:19 -0700 Subject: [PATCH 181/746] Fix "[object Object]" in TemplatePassthrough debug message Just something I noticed when running in debug mode. It's useful to see this path properly. --- src/TemplatePassthroughManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 4a522b5b3..9a66b286f 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -189,7 +189,7 @@ class TemplatePassthroughManager { for (let path of passthroughPaths) { let normalizedPath = this._normalizePaths(path); debug( - `TemplatePassthrough copying from non-matching file extension: ${normalizedPath}` + `TemplatePassthrough copying from non-matching file extension: ${normalizedPath.inputPath}` ); promises.push(this.copyPath(normalizedPath)); } From b8144add8a5ecd7d41fb3c602237189e67ffb252 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 4 Apr 2020 14:38:08 -0500 Subject: [PATCH 182/746] Fixes `[object Object]` output in debug --- src/TemplatePassthroughManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 4a522b5b3..8973e0e72 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -181,7 +181,7 @@ class TemplatePassthroughManager { let promises = []; debug("TemplatePassthrough copy started."); for (let path of this.getConfigPaths()) { - debug(`TemplatePassthrough copying from config: ${path}`); + debug(`TemplatePassthrough copying from config: %o`, path); promises.push(this.copyPath(path)); } From c442c45e72dd67f3a4eb1ab8bd540e5f34441246 Mon Sep 17 00:00:00 2001 From: Steven Petryk Date: Sun, 5 Apr 2020 18:34:57 -0700 Subject: [PATCH 183/746] Prevent unhandled errors from breaking the build This closes #833 and replaces #1066 as a solution. When I did some digging, I found out that the real problem here is that some errors are never caught by the `watchRun` callback. The `try` / `catch` is unused because the error is thrown inside of a `setTimeout`. The fact that an exception is thrown means the build never gets marked as finished, causing `_watch` to do nothing: https://github.com/11ty/eleventy/blob/8ffbb9927ea8482c5a46515f3a2ed25cd8830ad8/src/Eleventy.js#L441-L443 _But_ since the `try` / `catch` also doesn't work, Eleventy doesn't crash. Instead, it remains in this weird limbo state where the watcher continues to run but builds cease. The fix has two parts: 1. Awaiting the `setTimeout` so that `try/catch` works 2. Making sure that we catch non-fatal errors and mark the build as finished. --- src/Eleventy.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index e4b5dbfd2..b8fde2445 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -4,6 +4,7 @@ const TemplateData = require("./TemplateData"); const TemplateWriter = require("./TemplateWriter"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyErrorHandler = require("./EleventyErrorHandler"); +const EleventyBaseError = require("./EleventyBaseError"); const EleventyServe = require("./EleventyServe"); const EleventyWatch = require("./EleventyWatch"); const EleventyWatchTargets = require("./EleventyWatchTargets"); @@ -653,12 +654,20 @@ Arguments: try { this._addFileToWatchQueue(path); clearTimeout(watchDelay); - watchDelay = setTimeout(async () => { - await this._watch(); + + await new Promise((resolve, reject) => { + watchDelay = setTimeout(async () => { + this._watch().then(resolve, reject); + }); }, this.config.watchThrottleWaitTime); } catch (e) { - EleventyErrorHandler.fatal(e, "Eleventy fatal watch error"); - this.stopWatch(); + if (e instanceof EleventyBaseError) { + EleventyErrorHandler.error(e, "Eleventy watch error"); + this.watchManager.setBuildFinished(); + } else { + EleventyErrorHandler.fatal(e, "Eleventy fatal watch error"); + this.stopWatch(); + } } } From 82d83f55b92624b7b307c3814c80c7f83b264d7f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 8 Apr 2020 17:28:30 -0500 Subject: [PATCH 184/746] Now shows total files copied in passthrough copy output. Fixes #1077. Adds aggregate benchmarks. Changes threshold percent from 10% to 8%. --- src/Benchmark.js | 25 ++++++----- src/BenchmarkGroup.js | 69 +++++++++++++++++++++---------- src/BenchmarkManager.js | 40 +++++++++++++----- src/Eleventy.js | 14 ++++--- src/EleventyFiles.js | 10 ++++- src/Engines/TemplateEngine.js | 4 ++ src/Template.js | 8 +++- src/TemplateContent.js | 18 ++++++-- src/TemplateData.js | 11 ++++- src/TemplatePassthrough.js | 26 ++++++++---- src/TemplatePassthroughManager.js | 13 ++---- src/UserConfig.js | 7 ++++ test/BenchmarkTest.js | 4 +- 13 files changed, 175 insertions(+), 74 deletions(-) diff --git a/src/Benchmark.js b/src/Benchmark.js index 988e37177..5861a8199 100644 --- a/src/Benchmark.js +++ b/src/Benchmark.js @@ -1,27 +1,36 @@ +const { performance } = require("perf_hooks"); + class Benchmark { constructor() { this.reset(); } + getNewTimestamp() { + if (performance) { + return performance.now(); + } + return new Date().getTime(); + } + reset() { this.timeSpent = 0; this.timesCalled = 0; - this.beforeDates = []; + this.beforeTimers = []; } before() { this.timesCalled++; - this.beforeDates.push(new Date()); + this.beforeTimers.push(this.getNewTimestamp()); } after() { - if (!this.beforeDates.length) { + if (!this.beforeTimers.length) { throw new Error("You called Benchmark after() without a before()."); } - let before = this.beforeDates.pop(); - if (!this.beforeDates.length) { - this.timeSpent += new Date().getTime() - before.getTime(); + let before = this.beforeTimers.pop(); + if (!this.beforeTimers.length) { + this.timeSpent += this.getNewTimestamp() - before; } } @@ -32,10 +41,6 @@ class Benchmark { getTotal() { return this.timeSpent; } - - getTotalString() { - return this.timeSpent > 0 ? ` (${this.timeSpent}ms)` : ""; - } } module.exports = Benchmark; diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index 29832eae8..b1b983f10 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -1,19 +1,21 @@ const chalk = require("chalk"); const Benchmark = require("./Benchmark"); -const debugWarn = require("debug")("Eleventy:Warnings"); +const debugBenchmark = require("debug")("Eleventy:Benchmark"); class BenchmarkGroup { constructor() { this.benchmarks = {}; - this.start = new Date(); this.isVerbose = true; this.minimumThresholdMs = 0; + this.minimumThresholdPercent = 8; } - reset() { - this.start = new Date(); + setIsVerbose(isVerbose) { + this.isVerbose = isVerbose; + } + reset() { for (var type in this.benchmarks) { this.benchmarks[type].reset(); } @@ -52,37 +54,60 @@ class BenchmarkGroup { this.minimumThresholdMs = val; } + setMinimumThresholdPercent(minimumThresholdPercent) { + let val = parseInt(minimumThresholdPercent, 10); + if (isNaN(val)) { + throw new Error( + "`setMinimumThresholdPercent` expects a number argument." + ); + } + this.minimumThresholdPercent = val; + } + get(type) { - this.benchmarks[type] = new Benchmark(); + if (!this.benchmarks[type]) { + this.benchmarks[type] = new Benchmark(); + } return this.benchmarks[type]; } - finish(label, thresholdPercent, isVerbose) { - let totalTimeSpent = new Date().getTime() - this.start.getTime(); - thresholdPercent = thresholdPercent !== undefined ? thresholdPercent : 10; + finish(label, totalTimeSpent) { for (var type in this.benchmarks) { let bench = this.benchmarks[type]; + let isAbsoluteMinimumComparison = this.minimumThresholdMs > 0; let totalForBenchmark = bench.getTotal(); let percent = (totalForBenchmark * 100) / totalTimeSpent; + + let extraOutput = []; + if (!isAbsoluteMinimumComparison) { + extraOutput.push(`${percent.toFixed(1)}%`); + } + let timesCalledCount = bench.getTimesCalled(); + if (timesCalledCount > 1) { + extraOutput.push(`called ${timesCalledCount}×`); + extraOutput.push( + `${(totalForBenchmark / timesCalledCount).toFixed(1)}ms each` + ); + } + + let str = chalk.yellow( + `Benchmark (${label}): ${type} took ${totalForBenchmark.toFixed(0)}ms ${ + extraOutput.length ? `(${extraOutput.join(", ")})` : "" + }` + ); + if ( - percent > thresholdPercent && - totalForBenchmark >= this.minimumThresholdMs + (isAbsoluteMinimumComparison && + totalForBenchmark >= this.minimumThresholdMs) || + percent > this.minimumThresholdPercent ) { - let timesCalledCount = bench.getTimesCalled(); - let timesCalled = ""; - if (timesCalledCount > 1) { - timesCalled = `, called ${timesCalledCount}×`; - } - let str = chalk.yellow( - `Benchmark (${label}): ${type} took ${bench.getTotal()}ms (${percent.toFixed( - 1 - )}%${timesCalled})` - ); - if (isVerbose) { + if (this.isVerbose) { console.log(str); } + } - debugWarn(str); + if (totalForBenchmark.toFixed(0) > 0) { + debugBenchmark(str); } } } diff --git a/src/BenchmarkManager.js b/src/BenchmarkManager.js index 8ea166a52..1f2d1537f 100644 --- a/src/BenchmarkManager.js +++ b/src/BenchmarkManager.js @@ -1,31 +1,50 @@ const BenchmarkGroup = require("./BenchmarkGroup"); +const { performance } = require("perf_hooks"); class BenchmarkManager { constructor() { - this.benches = {}; + this.benchmarkGroups = {}; this.isVerbose = true; + this.start = this.getNewTimestamp(); } reset() { - for (var j in this.benches) { - this.benches[j].reset(); + this.start = this.getNewTimestamp(); + + for (var j in this.benchmarkGroups) { + this.benchmarkGroups[j].reset(); } } + getNewTimestamp() { + if (performance) { + return performance.now(); + } + return new Date().getTime(); + } + setVerboseOutput(isVerbose) { this.isVerbose = !!isVerbose; } getBenchmarkGroup(name) { - if (!this.benches[name]) { - this.benches[name] = new BenchmarkGroup(); + if (!this.benchmarkGroups[name]) { + this.benchmarkGroups[name] = new BenchmarkGroup(); + + // Special behavior for aggregate benchmarks + // so they don’t console.log every time + if (name === "Aggregate") { + this.benchmarkGroups[name].setIsVerbose(false); + } else { + this.benchmarkGroups[name].setIsVerbose(this.isVerbose); + } } - return this.benches[name]; + return this.benchmarkGroups[name]; } getAll() { - return this.benches; + return this.benchmarkGroups; } get(name) { @@ -36,9 +55,10 @@ class BenchmarkManager { return this.getAll(); } - finish(thresholdPercent) { - for (var j in this.benches) { - this.benches[j].finish(j, thresholdPercent, this.isVerbose); + finish() { + let totalTimeSpentBenchmarking = this.getNewTimestamp() - this.start; + for (var j in this.benchmarkGroups) { + this.benchmarkGroups[j].finish(j, totalTimeSpentBenchmarking); } } } diff --git a/src/Eleventy.js b/src/Eleventy.js index e4b5dbfd2..965140527 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -227,15 +227,11 @@ class Eleventy { let writeCount = this.writer.getWriteCount(); let skippedCount = this.writer.getSkippedCount(); - let copyCount = this.writer.getCopyCount(); - let skippedCopyCount = this.writer.getSkippedCopyCount(); if (copyCount) { ret.push( - `Copied ${copyCount} ${simplePlural(copyCount, "item", "items")}${ - skippedCopyCount ? ` (skipped ${skippedCopyCount})` : "" - } /` + `Copied ${copyCount} ${simplePlural(copyCount, "file", "files")} /` ); } @@ -634,6 +630,9 @@ Arguments: // See: TemplateWriter:pathCache and EleventyWatchTargets await this.write(); + let initWatchBench = this.watcherBench.get("Start up --watch"); + initWatchBench.before(); + await this.initWatch(); // TODO improve unwatching if JS dependencies are removed (or files are deleted) @@ -642,7 +641,10 @@ Arguments: let watcher = chokidar.watch(rawFiles, this.getChokidarConfig()); - this.watcherBench.finish("Initialize --watch", 10, this.isVerbose); + initWatchBench.after(); + + this.watcherBench.setIsVerbose(true); + this.watcherBench.finish("Watch"); console.log("Watching…"); diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index b3b722442..3e6f341fb 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -10,6 +10,7 @@ const TemplatePassthroughManager = require("./TemplatePassthroughManager"); const config = require("./Config"); const debug = require("debug")("Eleventy:EleventyFiles"); // const debugDev = require("debug")("Dev:Eleventy:EleventyFiles"); +const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class EleventyFiles { constructor(input, outputDir, formats, passthroughAll) { @@ -313,12 +314,15 @@ class EleventyFiles { let globs = this.getFileGlobs(); debug("Searching for: %o", globs); + let bench = aggregateBench.get("Searching the file system"); + bench.before(); let paths = TemplatePath.addLeadingDotSlashArray( await fastglob(globs, { caseSensitiveMatch: false, dot: true }) ); + bench.after(); if ("extensionMap" in this.config) { let extensions = this.config.extensionMap; @@ -355,13 +359,17 @@ class EleventyFiles { // TODO this isn’t great but reduces complexity avoiding using TemplateData:getLocalDataPaths for each template in the cache async getWatcherTemplateJavaScriptDataFiles() { let globs = await this.getTemplateData().getTemplateJavaScriptDataFileGlob(); - return TemplatePath.addLeadingDotSlashArray( + let bench = aggregateBench.get("Searching the file system"); + bench.before(); + let results = TemplatePath.addLeadingDotSlashArray( await fastglob(globs, { ignore: ["**/node_modules/**"], caseSensitiveMatch: false, dot: true }) ); + bench.after(); + return results; } /* Ignored by `eleventy --watch` */ diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 222d33f20..b5aa5f64d 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -3,6 +3,7 @@ const fs = require("fs-extra"); const TemplatePath = require("../TemplatePath"); const EleventyExtensionMap = require("../EleventyExtensionMap"); const debug = require("debug")("Eleventy:TemplateEngine"); +const aggregateBench = require("../BenchmarkManager").get("Aggregate"); class TemplateEngine { constructor(name, includesDir) { @@ -61,6 +62,8 @@ class TemplateEngine { // TODO: reuse mustache partials in handlebars? let partialFiles = []; if (this.includesDir) { + let bench = aggregateBench.get("Searching the file system"); + bench.before(); this.extensions.forEach(function(extension) { partialFiles = partialFiles.concat( fastglob.sync(prefix + extension, { @@ -69,6 +72,7 @@ class TemplateEngine { }) ); }); + bench.after(); } partialFiles = TemplatePath.addLeadingDotSlashArray(partialFiles); diff --git a/src/Template.js b/src/Template.js index d722e516a..b03b2f3b5 100644 --- a/src/Template.js +++ b/src/Template.js @@ -14,8 +14,10 @@ const TemplateFileSlug = require("./TemplateFileSlug"); const ComputedData = require("./ComputedData"); const Pagination = require("./Plugins/Pagination"); const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); + const debug = require("debug")("Eleventy:Template"); const debugDev = require("debug")("Dev:Eleventy:Template"); +const bench = require("./BenchmarkManager").get("Aggregate"); class Template extends TemplateContent { constructor(path, inputDir, outputDir, templateData) { @@ -553,7 +555,10 @@ class Template extends TemplateContent { if (!shouldWriteFile) { this.skippedCount++; } else { + let templateBenchmark = bench.get("Template Write"); + templateBenchmark.before(); return fs.outputFile(outputPath, finalContent).then(() => { + templateBenchmark.after(); this.writeCount++; debug(`${outputPath} ${lang.finished}.`); }); @@ -580,7 +585,8 @@ class Template extends TemplateContent { let promises = []; for (let page of mapEntry._pages) { let content = await this.renderPageEntry(mapEntry, page); - promises.push(this._write(page.outputPath, content)); + let promise = this._write(page.outputPath, content); + promises.push(promise); } return Promise.all(promises); diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 0c82a159a..77d8be06a 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -12,6 +12,7 @@ const EleventyErrorUtil = require("./EleventyErrorUtil"); const config = require("./Config"); const debug = require("debug")("Eleventy:TemplateContent"); const debugDev = require("debug")("Dev:Eleventy:TemplateContent"); +const bench = require("./BenchmarkManager").get("Aggregate"); class TemplateContentCompileError extends EleventyBaseError {} class TemplateContentRenderError extends EleventyBaseError {} @@ -107,11 +108,16 @@ class TemplateContent { } async getInputContent() { - if (this.engine.needsToReadFileContents()) { - return fs.readFile(this.inputPath, "utf-8"); + if (!this.engine.needsToReadFileContents()) { + return ""; } - return ""; + let templateBenchmark = bench.get("Template Read"); + templateBenchmark.before(); + let content = await fs.readFile(this.inputPath, "utf-8"); + templateBenchmark.after(); + + return content; } async getFrontMatter() { @@ -170,7 +176,10 @@ class TemplateContent { ); try { + let templateBenchmark = bench.get("Template Compile"); + templateBenchmark.before(); let fn = await this.templateRender.getCompiledTemplate(str); + templateBenchmark.after(); debugDev("%o getCompiledTemplate function created", this.inputPath); return fn; } catch (e) { @@ -185,7 +194,10 @@ class TemplateContent { async render(str, data, bypassMarkdown) { try { let fn = await this.compile(str, bypassMarkdown); + let templateBenchmark = bench.get("Template Render"); + templateBenchmark.before(); let rendered = await fn(data); + templateBenchmark.after(); debugDev( "%o getCompiledTemplate called, rendered content created", this.inputPath diff --git a/src/TemplateData.js b/src/TemplateData.js index d200dffa2..1f22aca2e 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -10,13 +10,16 @@ const TemplatePath = require("./TemplatePath"); const TemplateGlob = require("./TemplateGlob"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); -const bench = require("./BenchmarkManager").get("Data"); + const config = require("./Config"); const debugWarn = require("debug")("Eleventy:Warnings"); const debug = require("debug")("Eleventy:TemplateData"); const debugDev = require("debug")("Dev:Eleventy:TemplateData"); const deleteRequireCache = require("./Util/DeleteRequireCache"); +const bench = require("./BenchmarkManager").get("Data"); +const aggregateBench = require("./BenchmarkManager").get("Aggregate"); + class TemplateDataParseError extends EleventyBaseError {} class TemplateData { @@ -175,10 +178,13 @@ class TemplateData { async getGlobalDataFiles() { let priorities = this.getGlobalDataExtensionPriorities(); + let fsBench = aggregateBench.get("Searching the file system"); + fsBench.before(); let paths = await fastglob(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, dot: true }); + fsBench.after(); // sort paths according to extension priorities // here we use reverse ordering, because paths with bigger index in array will override the first ones @@ -368,6 +374,8 @@ class TemplateData { return {}; } + let aggregateDataBench = aggregateBench.get("Data File"); + aggregateDataBench.before(); let dataBench = bench.get(`\`${path}\``); dataBench.before(); deleteRequireCache(localPath); @@ -378,6 +386,7 @@ class TemplateData { } dataBench.after(); + aggregateDataBench.after(); return returnValue; } else if (this.isUserDataExtension(extension)) { // Other extensions diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index c514b2529..908749cde 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -3,7 +3,7 @@ const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthrough"); const fastglob = require("fast-glob"); const EleventyBaseError = require("./EleventyBaseError"); -//const bench = require("./BenchmarkManager").get("PassthroughCopy"); +const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class TemplatePassthroughError extends EleventyBaseError {} @@ -55,12 +55,15 @@ class TemplatePassthrough { async getFiles(glob) { debug("Searching for: %o", glob); + let bench = aggregateBench.get("Searching the file system"); + bench.before(); const files = TemplatePath.addLeadingDotSlashArray( await fastglob(glob, { caseSensitiveMatch: false, dot: true }) ); + bench.after(); return files; } @@ -70,15 +73,20 @@ class TemplatePassthrough { TemplatePath.stripLeadingDotSlash(this.outputDir) ) ) { - // Uncomment this if you want to add benchmarking to copy - // (Warning, it seems to be noisy and low value feedback) - // return bench.addAsync(`Copying ${src}`, function() { - // // copy() returns a promise - // return copy(src, dest, copyOptions); - // }); - + let fileCopyCount = 0; // copy() returns a promise - return copy(src, dest, copyOptions); + return copy(src, dest, copyOptions) + .on(copy.events.COPY_FILE_START, function(copyOp) { + // Access to individual files at `copyOp.src` + aggregateBench.get("Passthrough Copy File").before(); + }) + .on(copy.events.COPY_FILE_COMPLETE, function() { + fileCopyCount++; + aggregateBench.get("Passthrough Copy File").after(); + }) + .then(() => { + return fileCopyCount; + }); } return Promise.reject( new TemplatePassthroughError( diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 8973e0e72..6249d3570 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -15,7 +15,6 @@ class TemplatePassthroughManager { reset() { this.count = 0; - this.skippedCount = 0; this.incrementalFile = null; debug("Resetting counts to 0"); } @@ -103,10 +102,6 @@ class TemplatePassthroughManager { return this.count; } - getSkippedCount() { - return this.skippedCount; - } - async copyPath(path) { let pass = new TemplatePassthrough(path, this.outputDir, this.inputDir); @@ -118,16 +113,16 @@ class TemplatePassthroughManager { return pass .write() - .then(() => { + .then(fileCopyCount => { if (pass.isDryRun) { - this.skippedCount++; + // We don’t count the skipped files as we need to iterate over them debug( "Skipped %o (either from --dryrun or --incremental)", path.inputPath ); } else { - this.count++; - debug("Copied %o", path.inputPath); + this.count += fileCopyCount; + debug("Copied %o (%d files)", path.inputPath, fileCopyCount); } }) .catch(function(e) { diff --git a/src/UserConfig.js b/src/UserConfig.js index 5cfd103be..9b9f1259b 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -4,6 +4,7 @@ const semver = require("semver"); const { DateTime } = require("luxon"); const EleventyBaseError = require("./EleventyBaseError"); const bench = require("./BenchmarkManager").get("Configuration"); +const aggregateBench = require("./BenchmarkManager").get("Aggregate"); const debug = require("debug")("Eleventy:UserConfig"); const pkg = require("../package.json"); @@ -263,16 +264,22 @@ class UserConfig { } addPlugin(plugin, options) { + // TODO support function.name in plugin config functions debug("Adding plugin (unknown name: check your config file)."); + let pluginBench = aggregateBench.get("Configuration addPlugin"); if (typeof plugin === "function") { + pluginBench.before(); let configFunction = plugin; configFunction(this, options); + pluginBench.after(); } else if (plugin && plugin.configFunction) { + pluginBench.before(); if (options && typeof options.init === "function") { options.init.call(this, plugin.initArguments || {}); } plugin.configFunction(this, options); + pluginBench.after(); } else { throw new UserConfigError( "Invalid EleventyConfig.addPlugin signature. Should be a function or a valid Eleventy plugin object." diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index 19c3c51f3..9e62a6a89 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -25,7 +25,7 @@ test.cb( setTimeout(function() { b.before(); b.after(); - t.is(b.getTotal(), 0); + t.truthy(b.getTotal() <= 0.1); b.after(); t.truthy(b.getTotal() >= 10); @@ -42,7 +42,7 @@ test.cb("Reset Benchmark", t => { setTimeout(function() { b.before(); b.after(); - t.is(b.getTotal(), 0); + t.truthy(b.getTotal() <= 0.1); t.throws(function() { // throws because we reset From 0494e5af010a7f2fef7ac63709936ddf8579d65c Mon Sep 17 00:00:00 2001 From: Ger Hobbelt Date: Thu, 9 Apr 2020 00:04:08 +0200 Subject: [PATCH 185/746] Improve user feedback when 11ty reports 'Unsupported engine': list the supported engine extensions too as part of the error report. This one had me thwarted for quite a while until I found out I had missed the **mandatory** `11ty` in `11ty.js` JavaScript Layout Template file naming. --- src/TemplateRender.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 87a5501b3..3527dfd13 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -53,7 +53,7 @@ class TemplateRender { this._engineName = this.extensionMap.getKey(engineNameOrPath); if (!this._engineName) { throw new TemplateRenderUnknownEngineError( - `Unknown engine for ${engineNameOrPath}` + `Unknown engine for ${engineNameOrPath} (supported extensions: ${Object.keys(this.extensionMap.extensionToKeyMap).join(' ')})` ); } From fc115dc1440a2bb91b6b2088292ad98d0b0c0b30 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 8 Apr 2020 20:43:54 -0500 Subject: [PATCH 186/746] Better output during incremental passthrough copy changes --- src/Eleventy.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 965140527..364d36ad4 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -231,15 +231,17 @@ class Eleventy { if (copyCount) { ret.push( - `Copied ${copyCount} ${simplePlural(copyCount, "file", "files")} /` + `Copied ${copyCount} ${simplePlural(copyCount, "file", "files")}` ); } - ret.push( - `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}${ - skippedCount ? ` (skipped ${skippedCount})` : "" - }` - ); + if (writeCount || skippedCount) { + ret.push( + `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}${ + skippedCount ? ` (skipped ${skippedCount})` : "" + }` + ); + } let versionStr = `v${pkg.version}`; let time = ((new Date() - this.start) / 1000).toFixed(2); From 645a767c65c2333ae6d28776e7b8568f0a8a2fae Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 8 Apr 2020 21:04:51 -0500 Subject: [PATCH 187/746] Use high resolution timers for full build time. Adds initial performance.now() warm up time to debug --- src/Eleventy.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 364d36ad4..d7844e4ce 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -8,6 +8,8 @@ const EleventyServe = require("./EleventyServe"); const EleventyWatch = require("./EleventyWatch"); const EleventyWatchTargets = require("./EleventyWatchTargets"); const EleventyFiles = require("./EleventyFiles"); +const { performance } = require("perf_hooks"); + const templateCache = require("./TemplateCache"); const simplePlural = require("./Util/Pluralize"); const deleteRequireCache = require("./Util/DeleteRequireCache"); @@ -61,8 +63,12 @@ class Eleventy { */ this.isDryRun = false; - /** @member {Date} - The time of instantiation. */ - this.start = new Date(); + if (performance) { + debug("Eleventy warm up time (in ms) %o", performance.now()); + } + + /** @member {Number} - The timestamp of Eleventy start. */ + this.start = this.getNewTimestamp(); /** * @member {Array} - Subset of template types. @@ -88,6 +94,13 @@ class Eleventy { this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; } + getNewTimestamp() { + if (performance) { + return performance.now(); + } + return new Date().getTime(); + } + /** @type {String} */ get input() { return this.rawInput || this.config.dir.input; @@ -186,7 +199,7 @@ class Eleventy { */ async restart() { debug("Restarting"); - this.start = new Date(); + this.start = this.getNewTimestamp(); templateCache.clear(); bench.reset(); this.eleventyFiles.restart(); @@ -229,22 +242,27 @@ class Eleventy { let skippedCount = this.writer.getSkippedCount(); let copyCount = this.writer.getCopyCount(); + let slashRet = []; + if (copyCount) { - ret.push( + slashRet.push( `Copied ${copyCount} ${simplePlural(copyCount, "file", "files")}` ); } if (writeCount || skippedCount) { - ret.push( + slashRet.push( `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}${ skippedCount ? ` (skipped ${skippedCount})` : "" }` ); } + if (slashRet.length) { + ret.push(slashRet.join(" / ")); + } let versionStr = `v${pkg.version}`; - let time = ((new Date() - this.start) / 1000).toFixed(2); + let time = ((this.getNewTimestamp() - this.start) / 1000).toFixed(2); ret.push(`in ${time} ${simplePlural(time, "second", "seconds")}`); if (writeCount >= 10) { From 0d185a0fb69c9175e819273baac1099d9a4d8d3c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 13 Apr 2020 21:54:43 -0500 Subject: [PATCH 188/746] Attempt to use real Proxy instead of template string compatible fake-proxies for Computed Data. --- src/ComputedData.js | 70 ++++++--------- src/ComputedDataProxy.js | 45 ++++++++++ src/ComputedDataTemplateString.js | 57 +++++++++++++ src/Template.js | 22 ++--- test/ComputedDataTest.js | 137 +++++++++++++++++++++++++++--- 5 files changed, 264 insertions(+), 67 deletions(-) create mode 100644 src/ComputedDataProxy.js create mode 100644 src/ComputedDataTemplateString.js diff --git a/src/ComputedData.js b/src/ComputedData.js index 093988e0c..9212442fd 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -1,59 +1,39 @@ const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); -const debug = require("debug")("Eleventy:ComputedData"); const DependencyGraph = require("dependency-graph").DepGraph; +const ComputedDataTemplateString = require("./ComputedDataTemplateString"); +const ComputedDataProxy = require("./ComputedDataProxy"); + +// const debug = require("debug")("Eleventy:ComputedData"); + class ComputedData { constructor() { this.computed = {}; + this.templateStringKeyLookup = {}; this.computedKeys = new Set(); this.declaredDependencies = {}; - - // is this ¯\_(lisp)_/¯ - // must be strings that won’t be escaped by template languages - this.prefix = "(((((11ty((((("; - this.suffix = ")))))11ty)))))"; } add(key, fn, declaredDependencies = []) { this.computedKeys.add(key); this.declaredDependencies[key] = declaredDependencies; - lodashSet(this.computed, key, fn); - } - - getProxyData() { - let proxyData = {}; - // use these special strings as a workaround to check the rendered output - // can’t use proxies here as some template languages trigger proxy for all - // keys in data - for (let key of this.computedKeys) { - // TODO don’t allow to set eleventyComputed.page? other disallowed computed things? - lodashSet(proxyData, key, this.prefix + key + this.suffix); - } - - return proxyData; + lodashSet(this.computed, key, fn); } - findVarsInOutput(output = "") { - let vars = new Set(); - let splits = output.split(this.prefix); - for (let split of splits) { - let varName = split.substr(0, split.indexOf(this.suffix)); - if (varName) { - vars.add(varName); - } - } - return Array.from(vars); + addTemplateString(key, fn, declaredDependencies = []) { + this.add(key, fn, declaredDependencies); + this.templateStringKeyLookup[key] = true; } async getVarOrder() { if (this.computedKeys.size > 0) { let graph = new DependencyGraph(); - let proxyData = this.getProxyData(); for (let key of this.computedKeys) { let computed = lodashGet(this.computed, key); + graph.addNode(key); if (typeof computed === "function") { @@ -64,23 +44,20 @@ class ComputedData { } } - // squelch console logs for this fake proxy data pass 😅 - let output; - let savedLog = console.log; - console.log = () => {}; - // Mitigation for #1061, errors on the first pass shouldn’t fail the whole thing. - try { - output = await computed(proxyData); - } catch (e) { - debug("Computed Data first pass data resolution error: %o", e); + let varsUsed; + let proxy; + let isTemplateString = !!this.templateStringKeyLookup[key]; + if (isTemplateString) { + proxy = new ComputedDataTemplateString(this.computedKeys); + } else { + proxy = new ComputedDataProxy(); } - console.log = savedLog; + varsUsed = await proxy.findVarsUsed(computed); - let vars = this.findVarsInOutput(output); - for (let usesVar of vars) { - if (usesVar !== key && this.computedKeys.has(usesVar)) { - graph.addNode(usesVar); - graph.addDependency(key, usesVar); + for (let varUsed of varsUsed) { + if (varUsed !== key && this.computedKeys.has(varUsed)) { + graph.addNode(varUsed); + graph.addDependency(key, varUsed); } } } @@ -94,6 +71,7 @@ class ComputedData { async setupData(data) { let order = await this.getVarOrder(); + for (let key of order) { let computed = lodashGet(this.computed, key); diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js new file mode 100644 index 000000000..e02f88330 --- /dev/null +++ b/src/ComputedDataProxy.js @@ -0,0 +1,45 @@ +class ComputedDataProxy { + _createDeepProxy(keyReference, path = []) { + let self = this; + return new Proxy( + {}, + { + get(target, key) { + if (target[key]) { + return target[key]; + } + let newPath = [...path, key]; + if (typeof key === "string") { + // if `page.url`, remove `page` etc + let parentIndex = keyReference.indexOf(path.join(".")); + if (parentIndex > -1) { + keyReference.splice(parentIndex, 1); + } + keyReference.push(newPath.join(".")); + return self._createDeepProxy(keyReference, newPath); + } + } + } + ); + } + + getProxyData(keyReference) { + return this._createDeepProxy(keyReference); + } + + async findVarsUsed(fn) { + let keyReference = []; + // careful, logging proxyData will mess with test results! + let proxyData = this.getProxyData(keyReference); + + // squelch console logs for this fake proxy data pass 😅 + let savedLog = console.log; + console.log = () => {}; + await fn(proxyData); + console.log = savedLog; + + return keyReference; + } +} + +module.exports = ComputedDataProxy; diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js new file mode 100644 index 000000000..1c3ae6e0e --- /dev/null +++ b/src/ComputedDataTemplateString.js @@ -0,0 +1,57 @@ +const lodashSet = require("lodash/set"); +const debug = require("debug")("Eleventy:ComputedDataTemplateString"); + +class ComputedDataTemplateString { + constructor(computedKeys) { + this.computedKeys = computedKeys; + + // is this ¯\_(lisp)_/¯ + // must be strings that won’t be escaped by template languages + this.prefix = "(((((11ty((((("; + this.suffix = ")))))11ty)))))"; + } + + getProxyData() { + let proxyData = {}; + + // use these special strings as a workaround to check the rendered output + // can’t use proxies here as some template languages trigger proxy for all + // keys in data + for (let key of this.computedKeys) { + // TODO don’t allow to set eleventyComputed.page? other disallowed computed things? + lodashSet(proxyData, key, this.prefix + key + this.suffix); + } + + return proxyData; + } + + findVarsInOutput(output = "") { + let vars = new Set(); + let splits = output.split(this.prefix); + for (let split of splits) { + let varName = split.substr(0, split.indexOf(this.suffix)); + if (varName) { + vars.add(varName); + } + } + return Array.from(vars); + } + + async findVarsUsed(fn) { + let proxyData = this.getProxyData(); + let output; + let savedLog = console.log; + console.log = () => {}; + // Mitigation for #1061, errors with filters in the first pass shouldn’t fail the whole thing. + try { + output = await fn(proxyData); + } catch (e) { + debug("Computed Data first pass data resolution error: %o", e); + } + console.log = savedLog; + + return this.findVarsInOutput(output); + } +} + +module.exports = ComputedDataTemplateString; diff --git a/src/Template.js b/src/Template.js index b03b2f3b5..f7714e4b7 100644 --- a/src/Template.js +++ b/src/Template.js @@ -388,7 +388,7 @@ class Template extends TemplateContent { ); } } else if (typeof obj === "string") { - computedData.add( + computedData.addTemplateString( parentKey, async innerData => { return await super.render(obj, innerData, true); @@ -396,6 +396,7 @@ class Template extends TemplateContent { declaredDependencies ); } else { + // Numbers, booleans, etc computedData.add(parentKey, obj, declaredDependencies); } } @@ -404,17 +405,16 @@ class Template extends TemplateContent { // will _not_ consume renderData let computedData = new ComputedData(); // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly - this._addComputedEntry( - computedData, - { - page: { - url: async data => await this.getOutputHref(data), - outputPath: async data => await this.getOutputPath(data) - } - }, - null, + computedData.addTemplateString( + "page.url", + async data => await this.getOutputHref(data), + ["permalink"] + ); + computedData.addTemplateString( + "page.outputPath", + async data => await this.getOutputPath(data), ["permalink"] - ); // declared dependency + ); if (this.config.keys.computed in data) { this._addComputedEntry(computedData, data[this.config.keys.computed]); diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index 5dcc148f7..f61c86bff 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -1,21 +1,19 @@ import test from "ava"; import ComputedData from "../src/ComputedData"; +import ComputedDataProxy from "../src/ComputedDataProxy"; +import ComputedDataTemplateString from "../src/ComputedDataTemplateString"; test("Get fake proxy data", t => { - let cd = new ComputedData(); - cd.add("key1", () => {}); - cd.add("key2", () => {}); - t.deepEqual(cd.getProxyData({}), { + let cd = new ComputedDataTemplateString(["key1", "key2"]); + t.deepEqual(cd.getProxyData(), { key1: `${cd.prefix}key1${cd.suffix}`, key2: `${cd.prefix}key2${cd.suffix}` }); }); test("Get nested fake proxy data", t => { - let cd = new ComputedData(); - cd.add("key1.nested", () => {}); - cd.add("key2", () => {}); - t.deepEqual(cd.getProxyData({}), { + let cd = new ComputedDataTemplateString(["key1.nested", "key2"]); + t.deepEqual(cd.getProxyData(), { key1: { nested: `${cd.prefix}key1.nested${cd.suffix}` }, @@ -24,7 +22,7 @@ test("Get nested fake proxy data", t => { }); test("Get vars from output", t => { - let cd = new ComputedData(); + let cd = new ComputedDataTemplateString(); t.deepEqual(cd.findVarsInOutput(""), []); t.deepEqual(cd.findVarsInOutput("slkdjfkljdsf"), []); t.deepEqual( @@ -54,7 +52,7 @@ test("Get vars from output", t => { test("Basic get/set", async t => { let cd = new ComputedData(); - cd.add("keystr", `this is a str`); + cd.add("keystr", "this is a str"); cd.add("key1", data => { return `this is a test ${data.key2}${data.keystr}`; }); @@ -69,6 +67,83 @@ test("Basic get/set", async t => { t.is(data.keystr, "this is a str"); }); +test("Basic get/set (reverse order of adds)", async t => { + let cd = new ComputedData(); + + cd.add("key1", data => { + return `this is a test ${data.key2}${data.keystr}`; + }); + cd.add("keystr", "this is a str"); + + let data = { + key2: "inject me" + }; + await cd.setupData(data); + + t.is(data.key1, "this is a test inject methis is a str"); + t.is(data.key2, "inject me"); + t.is(data.keystr, "this is a str"); +}); + +test("Basic get/set (reverse order of adds) nested two deep", async t => { + let cd = new ComputedData(); + + cd.add("key1.key3", data => { + return `this is a test ${data.key2}${data.keystr}`; + }); + cd.add("key1.key4", data => { + return `this is a test ${data.key1.key3}`; + }); + cd.add("keystr", "this is a str"); + + let data = { + key2: "inject me" + }; + await cd.setupData(data); + + t.is(data.key1.key3, "this is a test inject methis is a str"); + t.is(data.key1.key4, "this is a test this is a test inject methis is a str"); + t.is(data.key2, "inject me"); + t.is(data.keystr, "this is a str"); +}); + +test("Get vars used by function", async t => { + let cd = new ComputedDataProxy(); + let key1Fn = () => {}; + let key2Fn = data => { + return `${data.key1}`; + }; + + t.deepEqual(await cd.findVarsUsed(key1Fn), []); + t.deepEqual(await cd.findVarsUsed(key2Fn), ["key1"]); +}); + +test("Get vars used by function (not a computed key)", async t => { + let cd = new ComputedDataProxy(); + let key1Fn = data => { + return `${data.page.url}`; + }; + + t.deepEqual(await cd.findVarsUsed(key1Fn), ["page.url"]); +}); + +test("Get vars used by function (multiple functions—not computed keys)", async t => { + let cd = new ComputedDataProxy(); + let key1Fn = data => { + return `${data.page.url}`; + }; + let key2Fn = data => { + return `${data.key1}${data.very.deep.reference}${data.very.other.deep.reference}`; + }; + + t.deepEqual(await cd.findVarsUsed(key1Fn), ["page.url"]); + t.deepEqual(await cd.findVarsUsed(key2Fn), [ + "key1", + "very.deep.reference", + "very.other.deep.reference" + ]); +}); + test("use a computed value in another computed", async t => { let cd = new ComputedData(); cd.add("keyComputed", data => { @@ -179,3 +254,45 @@ test("Basic get/set nested deeper", async t => { t.is(data.key1.nonComputed, "hi"); t.is(data.key2, "hi"); }); + +test("template string versus function types", async t => { + let cd = new ComputedData(); + + cd.add("key1.nested.deeperA", data => { + return `${data.key2}`; + }); + cd.add("key2", () => "hi"); + + let data = { + key1: { + nonComputed: "hi" + }, + key2: "inject me" + }; + await cd.setupData(data); + + t.deepEqual(data.key1, { + nonComputed: "hi", + nested: { + deeperA: "hi" + } + }); +}); + +test("Basic get/set with template string", async t => { + let cd = new ComputedData(); + + cd.addTemplateString("keystr", "this is a str"); + cd.addTemplateString("key1", data => { + return `this is a test ${data.key2}${data.keystr}`; + }); + + let data = { + key2: "inject me" + }; + await cd.setupData(data); + + t.is(data.key1, "this is a test inject methis is a str"); + t.is(data.key2, "inject me"); + t.is(data.keystr, "this is a str"); +}); From 9109e76f1fccc98d1809613c61b2a441152a7f13 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 13 Apr 2020 22:38:44 -0500 Subject: [PATCH 189/746] Fixes #973 --- src/ComputedData.js | 2 +- src/ComputedDataProxy.js | 17 ++++++++++++++++- src/ComputedDataTemplateString.js | 6 +++++- test/ComputedDataTest.js | 19 ++++++++++++++++--- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/ComputedData.js b/src/ComputedData.js index 9212442fd..9663e14e9 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -50,7 +50,7 @@ class ComputedData { if (isTemplateString) { proxy = new ComputedDataTemplateString(this.computedKeys); } else { - proxy = new ComputedDataProxy(); + proxy = new ComputedDataProxy(this.computedKeys); } varsUsed = await proxy.findVarsUsed(computed); diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index e02f88330..0b350c9bd 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -1,4 +1,12 @@ class ComputedDataProxy { + constructor(computedKeys) { + if (Array.isArray(computedKeys)) { + this.computedKeys = new Set(computedKeys); + } else { + this.computedKeys = computedKeys; + } + } + _createDeepProxy(keyReference, path = []) { let self = this; return new Proxy( @@ -15,7 +23,14 @@ class ComputedDataProxy { if (parentIndex > -1) { keyReference.splice(parentIndex, 1); } - keyReference.push(newPath.join(".")); + let fullPath = newPath.join("."); + keyReference.push(fullPath); + + // return string for computed key values + if (self.computedKeys.has(fullPath)) { + return ""; + } + return self._createDeepProxy(keyReference, newPath); } } diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js index 1c3ae6e0e..67b609fb2 100644 --- a/src/ComputedDataTemplateString.js +++ b/src/ComputedDataTemplateString.js @@ -3,7 +3,11 @@ const debug = require("debug")("Eleventy:ComputedDataTemplateString"); class ComputedDataTemplateString { constructor(computedKeys) { - this.computedKeys = computedKeys; + if (Array.isArray(computedKeys)) { + this.computedKeys = new Set(computedKeys); + } else { + this.computedKeys = computedKeys; + } // is this ¯\_(lisp)_/¯ // must be strings that won’t be escaped by template languages diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index f61c86bff..c6ab9f355 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -108,7 +108,7 @@ test("Basic get/set (reverse order of adds) nested two deep", async t => { }); test("Get vars used by function", async t => { - let cd = new ComputedDataProxy(); + let cd = new ComputedDataProxy(["key1"]); let key1Fn = () => {}; let key2Fn = data => { return `${data.key1}`; @@ -119,7 +119,7 @@ test("Get vars used by function", async t => { }); test("Get vars used by function (not a computed key)", async t => { - let cd = new ComputedDataProxy(); + let cd = new ComputedDataProxy(["page.url"]); let key1Fn = data => { return `${data.page.url}`; }; @@ -128,7 +128,12 @@ test("Get vars used by function (not a computed key)", async t => { }); test("Get vars used by function (multiple functions—not computed keys)", async t => { - let cd = new ComputedDataProxy(); + let cd = new ComputedDataProxy([ + "page.url", + "key1", + "very.deep.reference", + "very.other.deep.reference" + ]); let key1Fn = data => { return `${data.page.url}`; }; @@ -296,3 +301,11 @@ test("Basic get/set with template string", async t => { t.is(data.key2, "inject me"); t.is(data.keystr, "this is a str"); }); + +test("Proxy shouldn’t always return {}", async t => { + let cd = new ComputedDataProxy(["page.fileSlug"]); + let proxy = cd.getProxyData([]); + + t.notDeepEqual(proxy.page.fileSlug, {}); + t.is(proxy.page.fileSlug, ""); +}); From 1fd4f024969e7b83cab43808f0a3ac3ddac4b4f3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 19 Apr 2020 21:10:34 -0500 Subject: [PATCH 190/746] COMPUTED DATA PROXIES --- src/ComputedData.js | 9 +- src/ComputedDataProxy.js | 87 ++++++---- src/ComputedDataTemplateString.js | 2 +- test/ComputedDataProxyTest.js | 212 +++++++++++++++++++++++++ test/ComputedDataTemplateStringTest.js | 48 ++++++ test/ComputedDataTest.js | 116 +++----------- 6 files changed, 341 insertions(+), 133 deletions(-) create mode 100644 test/ComputedDataProxyTest.js create mode 100644 test/ComputedDataTemplateStringTest.js diff --git a/src/ComputedData.js b/src/ComputedData.js index 9663e14e9..8ac0327d0 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -27,7 +27,7 @@ class ComputedData { this.templateStringKeyLookup[key] = true; } - async getVarOrder() { + async getVarOrder(data) { if (this.computedKeys.size > 0) { let graph = new DependencyGraph(); @@ -44,16 +44,15 @@ class ComputedData { } } - let varsUsed; let proxy; let isTemplateString = !!this.templateStringKeyLookup[key]; + // TODO move this out of the loop?? if (isTemplateString) { proxy = new ComputedDataTemplateString(this.computedKeys); } else { proxy = new ComputedDataProxy(this.computedKeys); } - varsUsed = await proxy.findVarsUsed(computed); - + let varsUsed = await proxy.findVarsUsed(computed, data); for (let varUsed of varsUsed) { if (varUsed !== key && this.computedKeys.has(varUsed)) { graph.addNode(varUsed); @@ -70,7 +69,7 @@ class ComputedData { } async setupData(data) { - let order = await this.getVarOrder(); + let order = await this.getVarOrder(data); for (let key of order) { let computed = lodashGet(this.computed, key); diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index 0b350c9bd..4487b5c10 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -1,3 +1,7 @@ +const lodashSet = require("lodash/set"); +const lodashGet = require("lodash/get"); +const lodashIsPlainObject = require("lodash/isPlainObject"); + class ComputedDataProxy { constructor(computedKeys) { if (Array.isArray(computedKeys)) { @@ -7,45 +11,64 @@ class ComputedDataProxy { } } - _createDeepProxy(keyReference, path = []) { - let self = this; - return new Proxy( - {}, - { - get(target, key) { - if (target[key]) { - return target[key]; - } - let newPath = [...path, key]; - if (typeof key === "string") { - // if `page.url`, remove `page` etc - let parentIndex = keyReference.indexOf(path.join(".")); - if (parentIndex > -1) { - keyReference.splice(parentIndex, 1); - } - let fullPath = newPath.join("."); - keyReference.push(fullPath); - - // return string for computed key values - if (self.computedKeys.has(fullPath)) { - return ""; - } + isArrayOrPlainObject(data) { + return Array.isArray(data) || lodashIsPlainObject(data); + } - return self._createDeepProxy(keyReference, newPath); - } + getProxyData(data, keyRef) { + let undefinedValue = "__11TY_UNDEFINED__"; + if (this.computedKeys) { + for (let key of this.computedKeys) { + if (lodashGet(data, key, undefinedValue) === undefinedValue) { + lodashSet(data, key, ""); } } - ); + } + + return this._getProxyData(data, keyRef); } - getProxyData(keyReference) { - return this._createDeepProxy(keyReference); + _getProxyData(data, keyRef, parentKey = "") { + if (lodashIsPlainObject(data)) { + return new Proxy( + {}, + { + get: (obj, key) => { + // console.log( obj, key, parentKey ); + if (typeof key !== "string") { + return obj[key]; + } + let newKey = `${parentKey ? `${parentKey}.` : ""}${key}`; + let newData = this._getProxyData(data[key], keyRef, newKey); + if (!this.isArrayOrPlainObject(newData)) { + keyRef.add(newKey); + } + return newData; + } + } + ); + } else if (Array.isArray(data)) { + return new Proxy([], { + get: (obj, key) => { + let newKey = `${parentKey}[${key}]`; + let newData = this._getProxyData(data[key], keyRef, newKey); + if (!this.isArrayOrPlainObject(newData)) { + keyRef.add(newKey); + } + return newData; + } + }); + } + + // everything else! + return data; } - async findVarsUsed(fn) { - let keyReference = []; + async findVarsUsed(fn, data = {}) { + let keyRef = new Set(); + // careful, logging proxyData will mess with test results! - let proxyData = this.getProxyData(keyReference); + let proxyData = this.getProxyData(data, keyRef); // squelch console logs for this fake proxy data pass 😅 let savedLog = console.log; @@ -53,7 +76,7 @@ class ComputedDataProxy { await fn(proxyData); console.log = savedLog; - return keyReference; + return Array.from(keyRef); } } diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js index 67b609fb2..2064b4b94 100644 --- a/src/ComputedDataTemplateString.js +++ b/src/ComputedDataTemplateString.js @@ -41,7 +41,7 @@ class ComputedDataTemplateString { return Array.from(vars); } - async findVarsUsed(fn) { + async findVarsUsed(fn, data = {}) { let proxyData = this.getProxyData(); let output; let savedLog = console.log; diff --git a/test/ComputedDataProxyTest.js b/test/ComputedDataProxyTest.js new file mode 100644 index 000000000..fb64c5ddf --- /dev/null +++ b/test/ComputedDataProxyTest.js @@ -0,0 +1,212 @@ +import test from "ava"; +import ComputedDataProxy from "../src/ComputedDataProxy"; + +test("Get vars used by function", async t => { + let cd = new ComputedDataProxy(["key1"]); + let key1Fn = () => {}; + let key2Fn = data => { + return `${data.key1}`; + }; + + t.deepEqual(await cd.findVarsUsed(key1Fn), []); + t.deepEqual(await cd.findVarsUsed(key2Fn), ["key1"]); +}); + +test("Get vars used by function (not a computed key)", async t => { + let cd = new ComputedDataProxy(["page.url"]); + let key1Fn = data => { + return `${data.page.url}`; + }; + + t.deepEqual( + await cd.findVarsUsed(key1Fn, { + page: { url: "" } + }), + ["page.url"] + ); +}); + +test("Get vars used by function (multiple functions—not computed keys)", async t => { + let cd = new ComputedDataProxy([ + "page.url", + "key1", + "very.deep.reference", + "very.other.deep.reference" + ]); + + // this would be real + let sampleData = { + key1: "", + page: { + url: "" + }, + very: { + deep: { + reference: "" + }, + other: { + deep: { + reference: "" + } + } + } + }; + + let key1Fn = data => { + return `${data.page.url}`; + }; + let key2Fn = data => { + return `${data.key1}${data.very.deep.reference}${data.very.other.deep.reference}`; + }; + + t.deepEqual(await cd.findVarsUsed(key1Fn, sampleData), ["page.url"]); + t.deepEqual(await cd.findVarsUsed(key2Fn, sampleData), [ + "key1", + "very.deep.reference", + "very.other.deep.reference" + ]); +}); + +test("Proxy shouldn’t always return {}", async t => { + let cd = new ComputedDataProxy(["page.fileSlug"]); + let proxy = cd.getProxyData( + { + page: { + fileSlug: "" + } + }, + new Set() + ); + + t.notDeepEqual(proxy.page.fileSlug, {}); + t.is(proxy.page.fileSlug, ""); +}); + +test("isArrayOrPlainObject", async t => { + let cd = new ComputedDataProxy(); + + t.is(cd.isArrayOrPlainObject(true), false); + t.is(cd.isArrayOrPlainObject(false), false); + t.is(cd.isArrayOrPlainObject(1), false); + t.is( + cd.isArrayOrPlainObject(() => {}), + false + ); + t.is( + cd.isArrayOrPlainObject(function() {}), + false + ); + t.is(cd.isArrayOrPlainObject(new Date()), false); + t.is(cd.isArrayOrPlainObject({}), true); + t.is(cd.isArrayOrPlainObject([]), true); +}); + +test("findVarsUsed empty", async t => { + let cdg = new ComputedDataProxy(); + t.deepEqual(await cdg.findVarsUsed(() => {}), []); + t.deepEqual(await cdg.findVarsUsed(({}) => {}), []); + + let data = { key: "value" }; + t.deepEqual(await cdg.findVarsUsed(data => {}), []); + t.deepEqual(await cdg.findVarsUsed(data => data.key), ["key"]); +}); + +test("findVarsUsed with a computed key (target a string)", async t => { + let cdg = new ComputedDataProxy(); + let data = { + key: "value", + computed: { + key: function(data) { + return data.key; + } + } + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["key"]); +}); + +test("findVarsUsed with a computed key (target an array)", async t => { + let cdg = new ComputedDataProxy(); + let data = { + arr: [0, 1, 2], + computed: { + key: function(data) { + return data.arr[1]; + } + } + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["arr[1]"]); +}); + +test("findVarsUsed with a computed key (target an object)", async t => { + let cdg = new ComputedDataProxy(); + let data = { + obj: { + b: 1 + }, + computed: { + key: function(data) { + return data.obj.b; + } + } + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["obj.b"]); +}); + +test("findVarsUsed with a computed key (target an object in an array)", async t => { + let cdg = new ComputedDataProxy(); + let data = { + obj: [{ b: 1 }, { a: 2 }], + computed: { + key: function(data) { + return data.obj[1].a; + } + } + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["obj[1].a"]); +}); + +test("findVarsUsed with a computed key (target a string not used in the output)", async t => { + let cdg = new ComputedDataProxy(); + let data = { + key1: "value1", + key2: "value2", + computed: { + key: function(data) { + let b = data.key2; + return data.key1; + } + } + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), [ + "key2", + "key1" + ]); +}); + +test("findVarsUsed with a deep computed reference that doesn’t exist in parent data", async t => { + let cdg = new ComputedDataProxy(["deep.deep1", "deep.deep2"]); + let data = { + key1: "value1", + key2: "value2", + computed: { + deep: { + deep1: function(data) { + return data.key2; + }, + deep2: function(data) { + return data.deep.deep1; + } + } + } + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.deep.deep2, data), [ + "deep.deep1" + ]); + t.deepEqual(await cdg.findVarsUsed(data.computed.deep.deep1, data), ["key2"]); +}); diff --git a/test/ComputedDataTemplateStringTest.js b/test/ComputedDataTemplateStringTest.js new file mode 100644 index 000000000..dc182799d --- /dev/null +++ b/test/ComputedDataTemplateStringTest.js @@ -0,0 +1,48 @@ +import test from "ava"; +import ComputedDataTemplateString from "../src/ComputedDataTemplateString"; + +test("Get fake proxy data", t => { + let cd = new ComputedDataTemplateString(["key1", "key2"]); + t.deepEqual(cd.getProxyData(), { + key1: `${cd.prefix}key1${cd.suffix}`, + key2: `${cd.prefix}key2${cd.suffix}` + }); +}); + +test("Get nested fake proxy data", t => { + let cd = new ComputedDataTemplateString(["key1.nested", "key2"]); + t.deepEqual(cd.getProxyData(), { + key1: { + nested: `${cd.prefix}key1.nested${cd.suffix}` + }, + key2: `${cd.prefix}key2${cd.suffix}` + }); +}); + +test("Get vars from output", t => { + let cd = new ComputedDataTemplateString(); + t.deepEqual(cd.findVarsInOutput(""), []); + t.deepEqual(cd.findVarsInOutput("slkdjfkljdsf"), []); + t.deepEqual( + cd.findVarsInOutput(`slkdjfkljdsf${cd.prefix}${cd.suffix}sldkjflkds`), + [] + ); + t.deepEqual( + cd.findVarsInOutput( + `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}sldkjflkds` + ), + ["firstVar"] + ); + t.deepEqual( + cd.findVarsInOutput( + `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}test${cd.prefix}firstVar${cd.suffix}sldkjflkds` + ), + ["firstVar"] + ); + t.deepEqual( + cd.findVarsInOutput( + `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}test${cd.prefix}secondVar${cd.suffix}sldkjflkds` + ), + ["firstVar", "secondVar"] + ); +}); diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index c6ab9f355..68224ff4f 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -1,53 +1,5 @@ import test from "ava"; import ComputedData from "../src/ComputedData"; -import ComputedDataProxy from "../src/ComputedDataProxy"; -import ComputedDataTemplateString from "../src/ComputedDataTemplateString"; - -test("Get fake proxy data", t => { - let cd = new ComputedDataTemplateString(["key1", "key2"]); - t.deepEqual(cd.getProxyData(), { - key1: `${cd.prefix}key1${cd.suffix}`, - key2: `${cd.prefix}key2${cd.suffix}` - }); -}); - -test("Get nested fake proxy data", t => { - let cd = new ComputedDataTemplateString(["key1.nested", "key2"]); - t.deepEqual(cd.getProxyData(), { - key1: { - nested: `${cd.prefix}key1.nested${cd.suffix}` - }, - key2: `${cd.prefix}key2${cd.suffix}` - }); -}); - -test("Get vars from output", t => { - let cd = new ComputedDataTemplateString(); - t.deepEqual(cd.findVarsInOutput(""), []); - t.deepEqual(cd.findVarsInOutput("slkdjfkljdsf"), []); - t.deepEqual( - cd.findVarsInOutput(`slkdjfkljdsf${cd.prefix}${cd.suffix}sldkjflkds`), - [] - ); - t.deepEqual( - cd.findVarsInOutput( - `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}sldkjflkds` - ), - ["firstVar"] - ); - t.deepEqual( - cd.findVarsInOutput( - `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}test${cd.prefix}firstVar${cd.suffix}sldkjflkds` - ), - ["firstVar"] - ); - t.deepEqual( - cd.findVarsInOutput( - `slkdjfkljdsf${cd.prefix}firstVar${cd.suffix}test${cd.prefix}secondVar${cd.suffix}sldkjflkds` - ), - ["firstVar", "secondVar"] - ); -}); test("Basic get/set", async t => { let cd = new ComputedData(); @@ -107,48 +59,6 @@ test("Basic get/set (reverse order of adds) nested two deep", async t => { t.is(data.keystr, "this is a str"); }); -test("Get vars used by function", async t => { - let cd = new ComputedDataProxy(["key1"]); - let key1Fn = () => {}; - let key2Fn = data => { - return `${data.key1}`; - }; - - t.deepEqual(await cd.findVarsUsed(key1Fn), []); - t.deepEqual(await cd.findVarsUsed(key2Fn), ["key1"]); -}); - -test("Get vars used by function (not a computed key)", async t => { - let cd = new ComputedDataProxy(["page.url"]); - let key1Fn = data => { - return `${data.page.url}`; - }; - - t.deepEqual(await cd.findVarsUsed(key1Fn), ["page.url"]); -}); - -test("Get vars used by function (multiple functions—not computed keys)", async t => { - let cd = new ComputedDataProxy([ - "page.url", - "key1", - "very.deep.reference", - "very.other.deep.reference" - ]); - let key1Fn = data => { - return `${data.page.url}`; - }; - let key2Fn = data => { - return `${data.key1}${data.very.deep.reference}${data.very.other.deep.reference}`; - }; - - t.deepEqual(await cd.findVarsUsed(key1Fn), ["page.url"]); - t.deepEqual(await cd.findVarsUsed(key2Fn), [ - "key1", - "very.deep.reference", - "very.other.deep.reference" - ]); -}); - test("use a computed value in another computed", async t => { let cd = new ComputedData(); cd.add("keyComputed", data => { @@ -302,10 +212,26 @@ test("Basic get/set with template string", async t => { t.is(data.keystr, "this is a str"); }); -test("Proxy shouldn’t always return {}", async t => { - let cd = new ComputedDataProxy(["page.fileSlug"]); - let proxy = cd.getProxyData([]); +test("Basic get/set using array data", async t => { + t.plan(5); + let cd = new ComputedData(); - t.notDeepEqual(proxy.page.fileSlug, {}); - t.is(proxy.page.fileSlug, ""); + cd.add("keystr", "this is a str"); + cd.add("key1", data => { + t.is(Array.isArray(data.arr), true); + return `this is a test ${data.arr[0]}${data.keystr}`; + }); + + let data = { + arr: ["inject me"], + collections: { + first: [], + second: [] + } + }; + await cd.setupData(data); + + t.is(data.key1, "this is a test inject methis is a str"); + t.is(data.arr[0], "inject me"); + t.is(data.keystr, "this is a str"); }); From 62bd4dff735f69b90cfce3cdec3946ee12e165d1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 23 Apr 2020 21:16:51 -0500 Subject: [PATCH 191/746] Test for #1069 --- test/TemplateRenderLiquidTest.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 7eae65faf..b13169ecb 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -969,3 +969,10 @@ test("Liquid Shortcode (with async function, error throwing)", async t => { ) > -1 ); }); + +test("Liquid Render a false #1069", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + "{{ falseValue }}" + ); + t.is(await fn({ falseValue: false }), "false"); +}); From 65ff465f2954642ed02ac3873862ace0dde7d2a3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 24 Apr 2020 17:40:59 -0500 Subject: [PATCH 192/746] Fixed: Passthrough copy globs were not adding to individual file copy counts correctly. --- src/TemplatePassthrough.js | 1 + src/TemplatePassthroughManager.js | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index 908749cde..0571dd652 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -78,6 +78,7 @@ class TemplatePassthrough { return copy(src, dest, copyOptions) .on(copy.events.COPY_FILE_START, function(copyOp) { // Access to individual files at `copyOp.src` + debug("Copying individual file %o", copyOp.src); aggregateBench.get("Passthrough Copy File").before(); }) .on(copy.events.COPY_FILE_COMPLETE, function() { diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 6249d3570..3bff7caaf 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -121,7 +121,14 @@ class TemplatePassthroughManager { path.inputPath ); } else { - this.count += fileCopyCount; + if (Array.isArray(fileCopyCount)) { + // globs + for (let count of fileCopyCount) { + this.count += count; + } + } else { + this.count += fileCopyCount; + } debug("Copied %o (%d files)", path.inputPath, fileCopyCount); } }) From 0467409a3b69560971a09e2742723b86c4406f9f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 25 Apr 2020 22:05:09 -0500 Subject: [PATCH 193/746] =?UTF-8?q?Centralize=20to=20one=20instance=20of?= =?UTF-8?q?=20EleventyExtensionMap=20so=20that=20we=20can=20re-use=20Templ?= =?UTF-8?q?ateEngine=20instances=20and=20don=E2=80=99t=20have=20to=20recre?= =?UTF-8?q?ate=20them=20every=20time.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EleventyExtensionMap.js | 10 + src/Engines/Html.js | 3 +- src/Engines/Markdown.js | 3 +- src/Engines/TemplateEngine.js | 22 +- src/Template.js | 10 +- src/TemplateEngineManager.js | 16 +- src/TemplateLayout.js | 19 +- src/TemplateLayoutPathResolver.js | 28 ++- src/TemplateRender.js | 19 +- src/TemplateWriter.js | 4 +- test/TemplateLayoutPathResolverTest.js | 107 ++++----- test/TemplateLayoutTest.js | 92 ++++++-- test/TemplateTest.js | 292 ++++++++++++++----------- 13 files changed, 365 insertions(+), 260 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index eb57ab153..086f1c2da 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -1,3 +1,4 @@ +const TemplateEngineManager = require("./TemplateEngineManager"); const TemplatePath = require("./TemplatePath"); class EleventyExtensionMap { @@ -28,6 +29,15 @@ class EleventyExtensionMap { this.configOverride = cfg; } + get engineManager() { + if (!this._engineManager) { + this._engineManager = new TemplateEngineManager(); + this._engineManager.config = this.config; + } + + return this._engineManager; + } + /* Used for layout path resolution */ getFileList(path, dir) { if (!path) { diff --git a/src/Engines/Html.js b/src/Engines/Html.js index 2e50f4fdd..223cd45a8 100644 --- a/src/Engines/Html.js +++ b/src/Engines/Html.js @@ -5,7 +5,8 @@ class Html extends TemplateEngine { if (preTemplateEngine) { let engine = this.engineManager.getEngine( preTemplateEngine, - super.getIncludesDir() + super.getIncludesDir(), + this.extensionMap ); let fn = await engine.compile(str, inputPath); diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index 184e43766..9110ceaf4 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -53,7 +53,8 @@ class Markdown extends TemplateEngine { if (typeof preTemplateEngine === "string") { engine = this.engineManager.getEngine( preTemplateEngine, - super.getIncludesDir() + super.getIncludesDir(), + this.extensionMap ); } else { engine = preTemplateEngine; diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index b5aa5f64d..7d704c751 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -8,9 +8,6 @@ const aggregateBench = require("../BenchmarkManager").get("Aggregate"); class TemplateEngine { constructor(name, includesDir) { this.name = name; - - this.extensionMap = new EleventyExtensionMap(); - this.extensions = this.extensionMap.getExtensionsFromKey(name); this.includesDir = includesDir; this.partialsHaveBeenCached = false; this.partials = []; @@ -36,6 +33,25 @@ class TemplateEngine { this._engineManager = manager; } + get extensionMap() { + if (!this._extensionMap) { + this._extensionMap = new EleventyExtensionMap(); + // this._extensionMap.config = this.config; + } + return this._extensionMap; + } + + set extensionMap(map) { + this._extensionMap = map; + } + + get extensions() { + if (!this._extensions) { + this._extensions = this.extensionMap.getExtensionsFromKey(this.name); + } + return this._extensions; + } + getName() { return this.name; } diff --git a/src/Template.js b/src/Template.js index f7714e4b7..47581434e 100644 --- a/src/Template.js +++ b/src/Template.js @@ -20,7 +20,7 @@ const debugDev = require("debug")("Dev:Eleventy:Template"); const bench = require("./BenchmarkManager").get("Aggregate"); class Template extends TemplateContent { - constructor(path, inputDir, outputDir, templateData) { + constructor(path, inputDir, outputDir, templateData, extensionMap) { debugDev("new Template(%o)", path); super(path, inputDir); @@ -35,6 +35,8 @@ class Template extends TemplateContent { this.outputDir = false; } + this.extensionMap = extensionMap; + this.linters = []; this.transforms = []; this.plugins = {}; @@ -84,7 +86,8 @@ class Template extends TemplateContent { this._layout = TemplateLayout.getTemplate( layoutKey, this.getInputDir(), - this.config + this.config, + this.extensionMap ); } return this._layout; @@ -609,7 +612,8 @@ class Template extends TemplateContent { this.inputPath, this.inputDir, this.outputDir, - this.templateData + this.templateData, + this.extensionMap ); tmpl.config = this.config; diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index a482efbda..42dc91b11 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -1,7 +1,9 @@ const config = require("./Config"); class TemplateEngineManager { - constructor() {} + constructor() { + this.engineCache = {}; + } get config() { if (!this._config) { @@ -49,17 +51,25 @@ class TemplateEngineManager { return !!this.getClassNameFromTemplateKey(name); } - getEngine(name, includesDir) { + getEngine(name, includesDir, extensionMap) { if (!this.hasEngine(name)) { throw new Error( `Template Engine ${name} does not exist in getEngine (includes dir: ${includesDir})` ); } - const cls = require("./Engines/" + this.getClassNameFromTemplateKey(name)); + if (this.engineCache[name]) { + return this.engineCache[name]; + } + + let path = "./Engines/" + this.getClassNameFromTemplateKey(name); + const cls = require(path); let instance = new cls(name, includesDir); + instance.extensionMap = extensionMap; instance.config = this.config; instance.engineManager = this; + + this.engineCache[name] = instance; return instance; } } diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index cc4065625..c90c8599a 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -3,21 +3,27 @@ const TemplateContent = require("./TemplateContent"); const TemplateData = require("./TemplateData"); const TemplatePath = require("./TemplatePath"); +// TODO move this into the constructor const templateCache = require("./TemplateCache"); const config = require("./Config"); // const debug = require("debug")("Eleventy:TemplateLayout"); const debugDev = require("debug")("Dev:Eleventy:TemplateLayout"); class TemplateLayout extends TemplateContent { - constructor(key, inputDir) { + constructor(key, inputDir, extensionMap) { // TODO getConfig() is duplicated in TemplateContent (super) let cfg = config.getConfig(); let resolvedPath = new TemplateLayoutPathResolver( key, - inputDir + inputDir, + extensionMap ).getFullPath(); super(resolvedPath, inputDir); + if (!extensionMap) { + throw new Error("Expected `extensionMap` in TemplateLayout constructor."); + } + this.extensionMap = extensionMap; this.dataKeyLayoutPath = key; this.inputPath = resolvedPath; this.inputDir = inputDir; @@ -28,14 +34,14 @@ class TemplateLayout extends TemplateContent { return TemplatePath.join(inputDir, key); } - static getTemplate(key, inputDir, config) { + static getTemplate(key, inputDir, config, extensionMap) { let fullKey = TemplateLayout.resolveFullKey(key, inputDir); if (templateCache.has(fullKey)) { debugDev("Found %o in TemplateCache", key); return templateCache.get(fullKey); } - let tmpl = new TemplateLayout(key, inputDir); + let tmpl = new TemplateLayout(key, inputDir, extensionMap); tmpl.config = config; templateCache.add(fullKey, tmpl); @@ -64,7 +70,8 @@ class TemplateLayout extends TemplateContent { let layout = TemplateLayout.getTemplate( mapEntry.frontMatterData[cfgKey], this.inputDir, - this.config + this.config, + this.extensionMap ); mapEntry = await layout.getTemplateLayoutMapEntry(); map.push(mapEntry); @@ -97,7 +104,7 @@ class TemplateLayout extends TemplateContent { } async getLayoutChain() { - if(!this.layoutChain) { + if (!this.layoutChain) { await this.getData(); } return this.layoutChain; diff --git a/src/TemplateLayoutPathResolver.js b/src/TemplateLayoutPathResolver.js index 8be75bd8a..e5da02ebd 100644 --- a/src/TemplateLayoutPathResolver.js +++ b/src/TemplateLayoutPathResolver.js @@ -5,12 +5,18 @@ const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplateLayoutPathResolver"); class TemplateLayoutPathResolver { - constructor(path, inputDir) { + constructor(path, inputDir, extensionMap) { this._config = config.getConfig(); this.inputDir = inputDir; this.originalPath = path; this.path = path; this.aliases = {}; + this.extensionMap = extensionMap; + if (!extensionMap) { + throw new Error( + "Expected `extensionMap` in TemplateLayoutPathResolver constructor." + ); + } this.init(); } @@ -50,16 +56,19 @@ class TemplateLayoutPathResolver { } this.pathAlreadyHasExtension = this.dir + "/" + this.path; - if ( this.path.split(".").length > 0 && fs.existsSync(this.pathAlreadyHasExtension) ) { this.filename = this.path; - this.fullPath = TemplatePath.addLeadingDotSlash(this.pathAlreadyHasExtension); + this.fullPath = TemplatePath.addLeadingDotSlash( + this.pathAlreadyHasExtension + ); } else { this.filename = this.findFileName(); - this.fullPath = TemplatePath.addLeadingDotSlash(this.dir + "/" + this.filename); + this.fullPath = TemplatePath.addLeadingDotSlash( + this.dir + "/" + this.filename + ); } } @@ -70,9 +79,7 @@ class TemplateLayoutPathResolver { getFileName() { if (!this.filename) { throw new Error( - `You’re trying to use a layout that does not exist: ${ - this.originalPath - } (${this.filename})` + `You’re trying to use a layout that does not exist: ${this.originalPath} (${this.filename})` ); } @@ -82,9 +89,7 @@ class TemplateLayoutPathResolver { getFullPath() { if (!this.filename) { throw new Error( - `You’re trying to use a layout that does not exist: ${ - this.originalPath - } (${this.filename})` + `You’re trying to use a layout that does not exist: ${this.originalPath} (${this.filename})` ); } @@ -101,8 +106,7 @@ class TemplateLayoutPathResolver { ); } - let extensionMap = new EleventyExtensionMap(this.config.templateFormats); - for (let filename of extensionMap.getFileList(this.path)) { + for (let filename of this.extensionMap.getFileList(this.path)) { // TODO async if (fs.existsSync(this.dir + "/" + filename)) { return filename; diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 87a5501b3..1f89aa1f1 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -1,5 +1,4 @@ const TemplatePath = require("./TemplatePath"); -const TemplateEngineManager = require("./TemplateEngineManager"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyExtensionMap = require("./EleventyExtensionMap"); // const debug = require("debug")("Eleventy:TemplateRender"); @@ -8,14 +7,13 @@ class TemplateRenderUnknownEngineError extends EleventyBaseError {} // works with full path names or short engine name class TemplateRender { - constructor(tmplPath, inputDir, extensionMap) { + constructor(tmplPath, inputDir) { if (!tmplPath) { throw new Error( `TemplateRender requires a tmplPath argument, instead of ${tmplPath}` ); } - this.extensionMap = extensionMap; this.engineNameOrPath = tmplPath; this.inputDir = inputDir; @@ -57,12 +55,10 @@ class TemplateRender { ); } - this._engineManager = new TemplateEngineManager(); - this._engineManager.config = this.config; - - this._engine = this._engineManager.getEngine( + this._engine = this.extensionMap.engineManager.getEngine( this._engineName, - this.includesDir + this.includesDir, + this.extensionMap ); this._engine.config = this.config; this._engine.initRequireCache(engineNameOrPath); @@ -86,13 +82,6 @@ class TemplateRender { return this._engine; } - get engineManager() { - if (!this._engineManager) { - this.init(this.engineNameOrPath); - } - return this._engineManager; - } - static parseEngineOverrides(engineName) { let overlappingEngineWarningCount = 0; let engines = []; diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 9fef9026e..88b960ba4 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -112,10 +112,10 @@ class TemplateWriter { path, this.inputDir, this.outputDir, - this.templateData + this.templateData, + this.extensionMap ); - tmpl.extensionMap = this.extensionMap; tmpl.setIsVerbose(this.isVerbose); // --incremental only writes files that trigger a build during --watch diff --git a/test/TemplateLayoutPathResolverTest.js b/test/TemplateLayoutPathResolverTest.js index 09990fae7..0f33c74d4 100644 --- a/test/TemplateLayoutPathResolverTest.js +++ b/test/TemplateLayoutPathResolverTest.js @@ -1,25 +1,38 @@ import test from "ava"; import TemplateLayoutPathResolver from "../src/TemplateLayoutPathResolver"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getResolverInstance(path, inputDir, map) { + if (!map) { + map = new EleventyExtensionMap([ + "liquid", + "ejs", + "md", + "hbs", + "mustache", + "haml", + "pug", + "njk", + "html", + "jstl", + "11ty.js" + ]); + } + return new TemplateLayoutPathResolver(path, inputDir, map); +} test("Layout", t => { - t.is( - new TemplateLayoutPathResolver("default", "./test/stubs").getFileName(), - "default.ejs" - ); + let res = getResolverInstance("default", "./test/stubs"); + t.is(res.getFileName(), "default.ejs"); }); test("Layout already has extension", t => { - t.is( - new TemplateLayoutPathResolver("default.ejs", "./test/stubs").getFileName(), - "default.ejs" - ); + let res = getResolverInstance("default.ejs", "./test/stubs"); + t.is(res.getFileName(), "default.ejs"); }); test("Layout (uses empty string includes folder)", t => { - let res = new TemplateLayoutPathResolver( - "includesemptystring", - "./test/stubs" - ); + let res = getResolverInstance("includesemptystring", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { @@ -31,10 +44,7 @@ test("Layout (uses empty string includes folder)", t => { }); test("Layout (uses empty string includes folder) already has extension", t => { - let res = new TemplateLayoutPathResolver( - "includesemptystring.ejs", - "./test/stubs" - ); + let res = getResolverInstance("includesemptystring.ejs", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { @@ -46,7 +56,7 @@ test("Layout (uses empty string includes folder) already has extension", t => { }); test("Layout (uses layouts folder)", t => { - let res = new TemplateLayoutPathResolver("layoutsdefault", "./test/stubs"); + let res = getResolverInstance("layoutsdefault", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { @@ -59,10 +69,7 @@ test("Layout (uses layouts folder)", t => { }); test("Layout (uses layouts folder) already has extension", t => { - let res = new TemplateLayoutPathResolver( - "layoutsdefault.ejs", - "./test/stubs" - ); + let res = getResolverInstance("layoutsdefault.ejs", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { @@ -75,10 +82,7 @@ test("Layout (uses layouts folder) already has extension", t => { }); test("Layout (uses empty string layouts folder)", t => { - let res = new TemplateLayoutPathResolver( - "layoutsemptystring", - "./test/stubs" - ); + let res = getResolverInstance("layoutsemptystring", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { @@ -91,10 +95,7 @@ test("Layout (uses empty string layouts folder)", t => { }); test("Layout (uses empty string layouts folder) already has extension", t => { - let res = new TemplateLayoutPathResolver( - "layoutsemptystring.ejs", - "./test/stubs" - ); + let res = getResolverInstance("layoutsemptystring.ejs", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { @@ -107,49 +108,31 @@ test("Layout (uses empty string layouts folder) already has extension", t => { }); test("Layout subdir", t => { - t.is( - new TemplateLayoutPathResolver( - "layouts/inasubdir", - "./test/stubs" - ).getFileName(), - "layouts/inasubdir.njk" - ); + let res = getResolverInstance("layouts/inasubdir", "./test/stubs"); + t.is(res.getFileName(), "layouts/inasubdir.njk"); }); test("Layout subdir already has extension", t => { - t.is( - new TemplateLayoutPathResolver( - "layouts/inasubdir.njk", - "./test/stubs" - ).getFileName(), - "layouts/inasubdir.njk" - ); + let res = getResolverInstance("layouts/inasubdir.njk", "./test/stubs"); + t.is(res.getFileName(), "layouts/inasubdir.njk"); }); test("Multiple layouts exist with the same file base, pick one", t => { + let res = getResolverInstance("multiple", "./test/stubs"); // pick the first one if multiple exist. - t.is( - new TemplateLayoutPathResolver("multiple", "./test/stubs").getFileName(), - "multiple.ejs" - ); + t.is(res.getFileName(), "multiple.ejs"); }); test("Multiple layouts exist but we are being explicit—layout already has extension", t => { - t.is( - new TemplateLayoutPathResolver( - "multiple.ejs", - "./test/stubs" - ).getFileName(), - "multiple.ejs" - ); - t.is( - new TemplateLayoutPathResolver("multiple.md", "./test/stubs").getFileName(), - "multiple.md" - ); + let res = getResolverInstance("multiple.ejs", "./test/stubs"); + t.is(res.getFileName(), "multiple.ejs"); + + let res2 = getResolverInstance("multiple.md", "./test/stubs"); + t.is(res2.getFileName(), "multiple.md"); }); test("Layout is aliased to a new location", t => { - let tl = new TemplateLayoutPathResolver("post", "./test/stubs"); + let tl = getResolverInstance("post", "./test/stubs"); tl.addLayoutAlias("post", "layouts/post.ejs"); tl.init(); @@ -157,7 +140,7 @@ test("Layout is aliased to a new location", t => { }); test("Global default with empty string alias", t => { - let tl = new TemplateLayoutPathResolver("", "./test/stubs"); + let tl = getResolverInstance("", "./test/stubs"); tl.addLayoutAlias("", "layouts/post.ejs"); tl.init(); @@ -165,7 +148,7 @@ test("Global default with empty string alias", t => { }); test("Global default with empty string alias (but no alias exists for this instance)", t => { - let tl = new TemplateLayoutPathResolver("layout.ejs", "./test/stubs"); + let tl = getResolverInstance("layout.ejs", "./test/stubs"); tl.addLayoutAlias("", "layouts/post.ejs"); tl.init(); @@ -175,7 +158,7 @@ test("Global default with empty string alias (but no alias exists for this insta }); test("Layout has no alias and does not exist", async t => { - let tl = new TemplateLayoutPathResolver("shouldnotexist", "./test/stubs"); + let tl = getResolverInstance("shouldnotexist", "./test/stubs"); tl.addLayoutAlias("post", "layouts/post.ejs"); tl.init(); diff --git a/test/TemplateLayoutTest.js b/test/TemplateLayoutTest.js index b45e2f8d8..6c67b00c7 100644 --- a/test/TemplateLayoutTest.js +++ b/test/TemplateLayoutTest.js @@ -1,19 +1,43 @@ import test from "ava"; import TemplateLayout from "../src/TemplateLayout"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; + +function getTemplateLayoutInstance(key, inputDir, map) { + if (!map) { + map = new EleventyExtensionMap([ + "liquid", + "ejs", + "md", + "hbs", + "mustache", + "haml", + "pug", + "njk", + "html", + "jstl", + "11ty.js" + ]); + } + let layout = new TemplateLayout(key, inputDir, map); + return layout; +} test("Creation", t => { t.is( - new TemplateLayout("base", "./test/stubs").getInputPath(), + getTemplateLayoutInstance("base", "./test/stubs").getInputPath(), "./test/stubs/_includes/base.njk" ); t.throws(() => { - new TemplateLayout("doesnotexist", "./test/stubs").getInputPath(); + getTemplateLayoutInstance("doesnotexist", "./test/stubs").getInputPath(); }); }); test("Get Layout Chain", async t => { - let tl = new TemplateLayout("layouts/layout-inherit-a.njk", "./test/stubs"); + let tl = getTemplateLayoutInstance( + "layouts/layout-inherit-a.njk", + "./test/stubs" + ); t.deepEqual(await tl.getLayoutChain(), [ "./test/stubs/_includes/layouts/layout-inherit-a.njk", @@ -23,8 +47,14 @@ test("Get Layout Chain", async t => { }); test("Get Front Matter Data", async t => { - let tl = new TemplateLayout("layouts/layout-inherit-a.njk", "./test/stubs"); - t.is(tl.getInputPath(), "./test/stubs/_includes/layouts/layout-inherit-a.njk"); + let tl = getTemplateLayoutInstance( + "layouts/layout-inherit-a.njk", + "./test/stubs" + ); + t.is( + tl.getInputPath(), + "./test/stubs/_includes/layouts/layout-inherit-a.njk" + ); let data = await tl.getData(); @@ -44,7 +74,6 @@ test("Get Front Matter Data", async t => { secondinherits: "b", thirdinherits: "c" }); - }); test("Augment data with layoutContent", async t => { @@ -77,30 +106,43 @@ test("Augment data with layoutContent", async t => { }); test("Render Layout", async t => { - let tl = new TemplateLayout("layouts/layout-inherit-a.njk", "./test/stubs"); + let tl = getTemplateLayoutInstance( + "layouts/layout-inherit-a.njk", + "./test/stubs" + ); t.is( - (await tl.render({ - inherits: "a", - secondinherits: "b", - thirdinherits: "c" - })).trim(), + ( + await tl.render({ + inherits: "a", + secondinherits: "b", + thirdinherits: "c" + }) + ).trim(), "a b a c" ); }); test("Render Layout (Pass in template content)", async t => { - let tl = new TemplateLayout("layouts/layout-inherit-a.njk", "./test/stubs"); + let tl = getTemplateLayoutInstance( + "layouts/layout-inherit-a.njk", + "./test/stubs" + ); t.is( - (await tl.render( - { inherits: "a", secondinherits: "b", thirdinherits: "c" }, - "TEMPLATE_CONTENT" - )).trim(), + ( + await tl.render( + { inherits: "a", secondinherits: "b", thirdinherits: "c" }, + "TEMPLATE_CONTENT" + ) + ).trim(), "TEMPLATE_CONTENT a b a c" ); }); test("Render Layout (Pass in undefined template content)", async t => { - let tl = new TemplateLayout("layouts/layout-contentdump.njk", "./test/stubs"); + let tl = getTemplateLayoutInstance( + "layouts/layout-contentdump.njk", + "./test/stubs" + ); t.is( await tl.render( { inherits: "a", secondinherits: "b", thirdinherits: "c" }, @@ -111,7 +153,10 @@ test("Render Layout (Pass in undefined template content)", async t => { }); test("Render Layout (Pass in null template content)", async t => { - let tl = new TemplateLayout("layouts/layout-contentdump.njk", "./test/stubs"); + let tl = getTemplateLayoutInstance( + "layouts/layout-contentdump.njk", + "./test/stubs" + ); t.is( await tl.render( { inherits: "a", secondinherits: "b", thirdinherits: "c" }, @@ -122,7 +167,10 @@ test("Render Layout (Pass in null template content)", async t => { }); test("Render Layout (Pass in empty template content)", async t => { - let tl = new TemplateLayout("layouts/layout-contentdump.njk", "./test/stubs"); + let tl = getTemplateLayoutInstance( + "layouts/layout-contentdump.njk", + "./test/stubs" + ); t.is( await tl.render( { inherits: "a", secondinherits: "b", thirdinherits: "c" }, @@ -134,13 +182,13 @@ test("Render Layout (Pass in empty template content)", async t => { test("Cache Duplicates (use full key for cache)", async t => { // if two different layouts used the same filename but had different inputdirs, make sure templatelayout cache is unique - let tla = new TemplateLayout( + let tla = getTemplateLayoutInstance( "layout.njk", "./test/stubs/templateLayoutCacheDuplicates" ); t.is((await tla.render({})).trim(), "Hello A"); - let tlb = new TemplateLayout( + let tlb = getTemplateLayoutInstance( "layout.njk", "./test/stubs/templateLayoutCacheDuplicates-b" ); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index baa3b79eb..77cd2da70 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -3,6 +3,7 @@ import fs from "fs-extra"; import pretty from "pretty"; import TemplateData from "../src/TemplateData"; import Template from "../src/Template"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; import EleventyErrorUtil from "../src/EleventyErrorUtil"; import TemplateContentPrematureUseError from "../src/Errors/TemplateContentPrematureUseError"; import normalizeNewLines from "./Util/normalizeNewLines"; @@ -16,12 +17,38 @@ async function getRenderedData(tmpl, pageNumber = 0) { return templates[pageNumber].data; } +function getNewTemplate( + path, + inputDir, + outputDir, + templateData = null, + map = null +) { + if (!map) { + map = new EleventyExtensionMap([ + "liquid", + "ejs", + "md", + "hbs", + "mustache", + "haml", + "pug", + "njk", + "html", + "jstl", + "11ty.js" + ]); + } + let tmpl = new Template(path, inputDir, outputDir, templateData, map); + return tmpl; +} + function cleanHtml(str) { return pretty(str, { ocd: true }); } test("getTemplateSubFolder", t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -30,7 +57,7 @@ test("getTemplateSubFolder", t => { }); test("getTemplateSubFolder, output is a subdir of input", t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./test/stubs/_site" @@ -39,7 +66,7 @@ test("getTemplateSubFolder, output is a subdir of input", t => { }); test("output path maps to an html file", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -52,7 +79,7 @@ test("output path maps to an html file", async t => { }); test("subfolder outputs to a subfolder", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/subfolder/subfolder.ejs", "./test/stubs/", "./dist" @@ -63,7 +90,7 @@ test("subfolder outputs to a subfolder", async t => { }); test("subfolder outputs to double subfolder", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/subfolder/subfolder/subfolder.ejs", "./test/stubs/", "./dist" @@ -74,7 +101,7 @@ test("subfolder outputs to double subfolder", async t => { }); test("HTML files output to the same as the input directory have a file suffix added (only if index, this is not index).", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/testing.html", "./test/stubs", "./test/stubs" @@ -83,7 +110,7 @@ test("HTML files output to the same as the input directory have a file suffix ad }); test("HTML files output to the same as the input directory have a file suffix added (only if index, this _is_ index).", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/index.html", "./test/stubs", "./test/stubs" @@ -92,7 +119,7 @@ test("HTML files output to the same as the input directory have a file suffix ad }); test("HTML files output to the same as the input directory have a file suffix added (only if index, this _is_ index, subfolder).", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/subfolder/index.html", "./test/stubs", "./test/stubs" @@ -102,7 +129,7 @@ test("HTML files output to the same as the input directory have a file suffix ad test("Test raw front matter from template (yaml)", async t => { // https://github.com/jonschlinkert/gray-matter/blob/master/examples/yaml.js - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateFrontMatter.ejs", "./test/stubs/", "./dist" @@ -122,7 +149,7 @@ test("Test raw front matter from template (yaml)", async t => { test("Test raw front matter from template (json)", async t => { // https://github.com/jonschlinkert/gray-matter/blob/master/examples/json.js - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateFrontMatterJson.ejs", "./test/stubs/", "./dist" @@ -141,7 +168,7 @@ test("Test raw front matter from template (json)", async t => { test("Test raw front matter from template (js)", async t => { // https://github.com/jonschlinkert/gray-matter/blob/master/examples/javascript.js - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateFrontMatterJs.ejs", "./test/stubs/", "./dist" @@ -159,7 +186,7 @@ test("Test raw front matter from template (js)", async t => { }); test("Test that getData() works", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateFrontMatter.ejs", "./test/stubs/", "./dist" @@ -172,7 +199,7 @@ test("Test that getData() works", async t => { test("One Layout (using new content var)", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateWithLayout.ejs", "./test/stubs/", "dist", @@ -197,7 +224,7 @@ test("One Layout (using new content var)", async t => { test("One Layout (using layoutContent)", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutContent.ejs", "./test/stubs/", "dist", @@ -225,7 +252,7 @@ test("One Layout (using layoutContent)", async t => { test("One Layout (layouts disabled)", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutContent.ejs", "./test/stubs/", "dist", @@ -250,7 +277,7 @@ test("One Layout (layouts disabled)", async t => { test("One Layout (_layoutContent deprecated but supported)", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutBackCompat.ejs", "./test/stubs/", "dist", @@ -278,7 +305,7 @@ test("One Layout (_layoutContent deprecated but supported)", async t => { test("One Layout (liquid test)", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateWithLayout.liquid", "./test/stubs/", "dist", @@ -306,7 +333,7 @@ test("One Layout (liquid test)", async t => { test("Two Layouts", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templateTwoLayouts.ejs", "./test/stubs/", "dist", @@ -333,7 +360,7 @@ test("Two Layouts", async t => { test("Liquid template", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/formatTest.liquid", "./test/stubs/", "dist", @@ -344,7 +371,7 @@ test("Liquid template", async t => { }); test("Liquid template with include", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/includer.liquid", "./test/stubs/", "dist" @@ -358,7 +385,7 @@ test("Liquid template with include", async t => { test("ES6 Template Literal (No Backticks)", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/formatTest.jstl", "./test/stubs/", "dist", @@ -370,7 +397,7 @@ test("ES6 Template Literal (No Backticks)", async t => { test("ES6 Template Literal (with Backticks)", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/formatTestBackticks.jstl", "./test/stubs/", "dist", @@ -381,7 +408,7 @@ test("ES6 Template Literal (with Backticks)", async t => { }); test("Permalink output directory", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalinked.ejs", "./test/stubs/", "./dist" @@ -390,7 +417,7 @@ test("Permalink output directory", async t => { }); test("Permalink output directory from layout", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalink-in-layout.ejs", "./test/stubs/", "./dist" @@ -399,7 +426,7 @@ test("Permalink output directory from layout", async t => { }); test("Permalink output directory from layout (fileslug)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalink-in-layout-fileslug.ejs", "./test/stubs/", "./dist" @@ -412,7 +439,7 @@ test("Permalink output directory from layout (fileslug)", async t => { test("Layout from template-data-file that has a permalink (fileslug) Issue #121", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalink-data-layout/test.njk", "./test/stubs/", "./dist", @@ -426,7 +453,7 @@ test("Layout from template-data-file that has a permalink (fileslug) Issue #121" }); test("Fileslug in an 11ty.js template Issue #588", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/fileslug.11ty.js", "./test/stubs/", "./dist" @@ -441,7 +468,7 @@ test("Local template data file import (without a global data json)", async t => let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/component/component.njk", "./test/stubs/", "./dist", @@ -467,7 +494,7 @@ test("Local template data file import (two subdirectories deep)", async t => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/firstdir/seconddir/component.njk", "./test/stubs/", "./dist", @@ -498,7 +525,7 @@ test("Posts inherits local JSON, layouts", async t => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/posts/post1.njk", "./test/stubs/", "./dist", @@ -539,7 +566,7 @@ test("Template and folder name are the same, make sure data imports work ok", as let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/posts/posts.njk", "./test/stubs/", "./dist", @@ -573,7 +600,7 @@ test("Template and folder name are the same, make sure data imports work ok", as }); test("Clone the template", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/default.ejs", "./test/stubs/", "./dist" @@ -583,10 +610,11 @@ test("Clone the template", async t => { t.is(await tmpl.getOutputPath(), "./dist/default/index.html"); t.is(await cloned.getOutputPath(), "./dist/default/index.html"); + t.is(cloned.extensionMap, tmpl.extensionMap); }); test("Permalink with variables!", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalinkdata.njk", "./test/stubs/", "./dist" @@ -596,7 +624,7 @@ test("Permalink with variables!", async t => { }); test("Permalink with variables and JS front matter!", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalinkdata-jsfn.njk", "./test/stubs/", "./dist" @@ -607,7 +635,7 @@ test("Permalink with variables and JS front matter!", async t => { // This is broken right now, permalink must use the same template language as the template test.skip("Use a JavaScript function for permalink in any template language", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalinkdata-jspermalinkfn.njk", "./test/stubs/", "./dist" @@ -617,7 +645,7 @@ test.skip("Use a JavaScript function for permalink in any template language", as }); test("Permalink with dates!", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalinkdate.liquid", "./test/stubs/", "./dist" @@ -627,7 +655,7 @@ test("Permalink with dates!", async t => { }); test("Permalink with dates on file name regex!", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/2016-02-01-permalinkdate.liquid", "./test/stubs/", "./dist" @@ -638,7 +666,7 @@ test("Permalink with dates on file name regex!", async t => { test("Reuse permalink in directory specific data file", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/reuse-permalink/test1.liquid", "./test/stubs/", "./dist", @@ -649,7 +677,7 @@ test("Reuse permalink in directory specific data file", async t => { }); test("mapDataAsRenderedTemplates", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/default.ejs", "./test/stubs/", "./dist" @@ -701,7 +729,7 @@ test("mapDataAsRenderedTemplates", async t => { }); test("renderData", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/renderData/renderData.njk", "./test/stubs/", "./dist" @@ -711,7 +739,7 @@ test("renderData", async t => { }); test("renderData markdown (issue #40)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/renderData/renderData.md", "./test/stubs/", "./dist" @@ -721,7 +749,7 @@ test("renderData markdown (issue #40)", async t => { }); test("getMappedDate (empty, assume created)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/dates/file1.md", "./test/stubs/", "./dist" @@ -734,7 +762,7 @@ test("getMappedDate (empty, assume created)", async t => { }); test("getMappedDate (explicit date, yaml String)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/dates/file2.md", "./test/stubs/", "./dist" @@ -747,7 +775,7 @@ test("getMappedDate (explicit date, yaml String)", async t => { }); test("getMappedDate (explicit date, yaml Date)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/dates/file2b.md", "./test/stubs/", "./dist" @@ -760,7 +788,7 @@ test("getMappedDate (explicit date, yaml Date)", async t => { }); test("getMappedDate (explicit date, yaml Date and string should be the same)", async t => { - let tmplA = new Template( + let tmplA = getNewTemplate( "./test/stubs/dates/file2.md", "./test/stubs/", "./dist" @@ -768,7 +796,7 @@ test("getMappedDate (explicit date, yaml Date and string should be the same)", a let dataA = await getRenderedData(tmplA); let stringDate = await tmplA.getMappedDate(dataA); - let tmplB = new Template( + let tmplB = getNewTemplate( "./test/stubs/dates/file2b.md", "./test/stubs/", "./dist" @@ -782,7 +810,7 @@ test("getMappedDate (explicit date, yaml Date and string should be the same)", a }); test("getMappedDate (modified date)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/dates/file3.md", "./test/stubs/", "./dist" @@ -795,7 +823,7 @@ test("getMappedDate (modified date)", async t => { }); test("getMappedDate (created date)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/dates/file4.md", "./test/stubs/", "./dist" @@ -808,7 +836,7 @@ test("getMappedDate (created date)", async t => { }); test("getMappedDate (falls back to filename date)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/dates/2018-01-01-file5.md", "./test/stubs/", "./dist" @@ -821,7 +849,7 @@ test("getMappedDate (falls back to filename date)", async t => { }); test("getRenderedData() has all the page variables", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -838,7 +866,7 @@ test("getRenderedData() has all the page variables", async t => { }); test("Issue #603: page.date Liquid", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/pagedate.liquid", "./test/stubs/", "./dist" @@ -853,7 +881,7 @@ test("Issue #603: page.date Liquid", async t => { }); test("Issue #603: page.date Nunjucks", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/pagedate.njk", "./test/stubs/", "./dist" @@ -869,7 +897,7 @@ test("Issue #603: page.date Nunjucks", async t => { test("Issue #603: page.date.toUTCString() Nunjucks", async t => { // Note this is not supported in Liquid - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/pagedateutc.njk", "./test/stubs/", "./dist" @@ -884,7 +912,7 @@ test("Issue #603: page.date.toUTCString() Nunjucks", async t => { }); test("getTemplates() data has all the root variables", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -901,7 +929,7 @@ test("getTemplates() data has all the root variables", async t => { }); test("getTemplates() data has all the page variables", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -918,7 +946,7 @@ test("getTemplates() data has all the page variables", async t => { }); test("getRenderedTemplates() data has all the page variables", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -935,14 +963,18 @@ test("getRenderedTemplates() data has all the page variables", async t => { }); test("getRenderedData() has good slug (empty, index)", async t => { - let tmpl = new Template("./test/stubs/index.ejs", "./test/stubs/", "./dist"); + let tmpl = getNewTemplate( + "./test/stubs/index.ejs", + "./test/stubs/", + "./dist" + ); let data = await getRenderedData(tmpl); t.is(data.page.fileSlug, ""); t.is(data.page.filePathStem, "/index"); }); test("getRenderedData() has good slug", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/includer.liquid", "./test/stubs/", "./dist" @@ -953,7 +985,7 @@ test("getRenderedData() has good slug", async t => { }); test("Override base templating engine from .liquid to ejs", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-ejs.liquid", "./test/stubs/", "./dist" @@ -963,7 +995,7 @@ test("Override base templating engine from .liquid to ejs", async t => { }); test("Override base templating engine from markdown to 11ty.js, then markdown", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/test-override-js-markdown.11ty.js", "./test/stubs/", "./dist" @@ -976,7 +1008,7 @@ test("Override base templating engine from markdown to 11ty.js, then markdown", }); test("Override base templating engine from .liquid to md", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-md.liquid", "./test/stubs/", "./dist" @@ -986,7 +1018,7 @@ test("Override base templating engine from .liquid to md", async t => { }); test("Override base templating engine from .liquid to ejs,md", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-multiple.md", "./test/stubs/", "./dist" @@ -996,7 +1028,7 @@ test("Override base templating engine from .liquid to ejs,md", async t => { }); test("Override base templating engine from .njk to ejs,md", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-multiple2.njk", "./test/stubs/", "./dist" @@ -1006,7 +1038,7 @@ test("Override base templating engine from .njk to ejs,md", async t => { }); test("Override base templating engine from .html to ejs", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test.html", "./test/stubs/", "./dist" @@ -1016,7 +1048,7 @@ test("Override base templating engine from .html to ejs", async t => { }); test("Override base templating engine from .html to (nothing)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-empty.html", "./test/stubs/", "./dist" @@ -1029,7 +1061,7 @@ test("Override base templating engine from .html to (nothing)", async t => { }); test("Override base templating engine should error with bad string", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-error.njk", "./test/stubs/", "./dist" @@ -1041,7 +1073,7 @@ test("Override base templating engine should error with bad string", async t => }); test("Override base templating engine (bypasses markdown)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-bypass.md", "./test/stubs/", "./dist" @@ -1051,7 +1083,7 @@ test("Override base templating engine (bypasses markdown)", async t => { }); test("Override base templating engine to (nothing)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test-empty.md", "./test/stubs/", "./dist" @@ -1062,7 +1094,7 @@ test("Override base templating engine to (nothing)", async t => { }); test("Override base templating engine from .ejs to njk", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test.ejs", "./test/stubs/", "./dist" @@ -1072,7 +1104,7 @@ test("Override base templating engine from .ejs to njk", async t => { }); test("Override base templating engine from .njk to ejs (with a layout that uses njk)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/layout.njk", "./test/stubs/", "./dist" @@ -1085,7 +1117,7 @@ test("Override base templating engine from .njk to ejs (with a layout that uses }); test("Override base templating engine from .njk to nothing (with a layout that uses njk)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/layoutfalse.njk", "./test/stubs/", "./dist" @@ -1098,7 +1130,7 @@ test("Override base templating engine from .njk to nothing (with a layout that u }); test("Using a markdown source file (with a layout that uses njk), markdown shouldn’t render in layout file", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test.md", "./test/stubs/", "./dist" @@ -1114,7 +1146,7 @@ test("Using a markdown source file (with a layout that uses njk), markdown shoul }); test("Override base templating engine from .md to ejs,md (with a layout that uses njk), markdown shouldn’t render in layout file", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/overrides/test2.md", "./test/stubs/", "./dist" @@ -1130,7 +1162,7 @@ test("Override base templating engine from .md to ejs,md (with a layout that use }); test("renderContent on a markdown file, permalink should not render markdown", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalink-markdown.md", "./test/stubs/", "./dist" @@ -1145,7 +1177,7 @@ test("renderContent on a markdown file, permalink should not render markdown", a }); test("renderContent on a markdown file, permalink should not render markdown (with variable)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalink-markdown-var.md", "./test/stubs/", "./dist" @@ -1164,7 +1196,7 @@ test("renderContent on a markdown file, permalink should not render markdown (wi }); test("renderContent on a markdown file, permalink should not render markdown (has override)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalink-markdown-override.md", "./test/stubs/", "./dist" @@ -1182,7 +1214,7 @@ test("renderContent on a markdown file, permalink should not render markdown (ha test("Test a transform", async t => { t.plan(2); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./test/stubs/_site" @@ -1201,7 +1233,7 @@ test("Test a transform", async t => { test.skip("Test a transform (does it have inputPath?)", async t => { t.plan(3); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./test/stubs/_site" @@ -1220,7 +1252,7 @@ test.skip("Test a transform (does it have inputPath?)", async t => { test("Test a transform with pages", async t => { t.plan(5); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/transform-pages/template.njk", "./test/stubs/", "./test/stubs/_site" @@ -1240,7 +1272,7 @@ test("Test a transform with pages", async t => { test("Test a transform with a layout", async t => { t.plan(3); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs-475/transform-layout/transform-layout.njk", "./test/stubs-475/", "./test/stubs-475/_site" @@ -1259,7 +1291,7 @@ test("Test a transform with a layout", async t => { test("Test a single asynchronous transform", async t => { t.plan(2); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./test/stubs/_site" @@ -1282,7 +1314,7 @@ test("Test a single asynchronous transform", async t => { test("Test multiple asynchronous transforms", async t => { t.plan(3); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./test/stubs/_site" @@ -1316,7 +1348,7 @@ test("Test multiple asynchronous transforms", async t => { test("Test a linter", async t => { t.plan(4); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/transform-pages/template.njk", "./test/stubs/", "./test/stubs/_site" @@ -1331,7 +1363,7 @@ test("Test a linter", async t => { }); test("permalink: false", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/permalink-false/test.md", "./test/stubs/", "./test/stubs/_site" @@ -1357,7 +1389,7 @@ test("permalink: false", async t => { }); test("Disable dynamic permalinks", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/dynamic-permalink/test.njk", "./test/stubs/", "./test/stubs/_site" @@ -1368,7 +1400,7 @@ test("Disable dynamic permalinks", async t => { }); test("Front Matter Tags (Single)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templatetest-frontmatter/single.njk", "./test/stubs/", "dist" @@ -1384,7 +1416,7 @@ test("Front Matter Tags (Single)", async t => { }); test("Front Matter Tags (Multiple)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/templatetest-frontmatter/multiple.njk", "./test/stubs/", "dist" @@ -1400,7 +1432,7 @@ test("Front Matter Tags (Multiple)", async t => { }); test("Front matter date with quotes (liquid), issue #258", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/frontmatter-date/test.liquid", "./test/stubs/", "dist" @@ -1414,7 +1446,7 @@ test("Front matter date with quotes (liquid), issue #258", async t => { }); test("Front matter date with quotes (njk), issue #258", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/frontmatter-date/test.njk", "./test/stubs/", "dist" @@ -1435,7 +1467,7 @@ test("Data Cascade (Deep merge)", async t => { dataObj._setConfig(newConfig); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", @@ -1466,7 +1498,7 @@ test("Data Cascade (Shallow merge)", async t => { let dataObj = new TemplateData("./test/"); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", @@ -1496,7 +1528,7 @@ test("Data Cascade Tag Merge (Deep merge)", async t => { dataObj._setConfig(newConfig); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", @@ -1512,7 +1544,7 @@ test("Data Cascade Tag Merge (Shallow merge)", async t => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", @@ -1527,7 +1559,7 @@ test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async t let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/local-data-tags/component.njk", "./test/stubs/", "./dist", @@ -1546,7 +1578,7 @@ test('Local data inherits tags string ([tags] vs "tags") Deep Merge', async t => dataObj._setConfig(newConfig); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/local-data-tags/component.njk", "./test/stubs/", "./dist", @@ -1559,7 +1591,7 @@ test('Local data inherits tags string ([tags] vs "tags") Deep Merge', async t => }); test("Throws a Premature Template Content Error (njk)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.njk", "./test/stubs/", "./test/stubs/_site" @@ -1574,7 +1606,7 @@ test("Throws a Premature Template Content Error (njk)", async t => { }); test("Throws a Premature Template Content Error from rendering (njk)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.njk", "./test/stubs/", "./test/stubs/_site" @@ -1598,7 +1630,7 @@ test("Throws a Premature Template Content Error from rendering (njk)", async t = }); test("Throws a Premature Template Content Error (liquid)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.liquid", "./test/stubs/", "./test/stubs/_site" @@ -1613,7 +1645,7 @@ test("Throws a Premature Template Content Error (liquid)", async t => { }); test("Throws a Premature Template Content Error (11ty.js)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.11ty.js", "./test/stubs/", "./test/stubs/_site" @@ -1628,7 +1660,7 @@ test("Throws a Premature Template Content Error (11ty.js)", async t => { }); test("Throws a Premature Template Content Error (pug)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.pug", "./test/stubs/", "./test/stubs/_site" @@ -1643,7 +1675,7 @@ test("Throws a Premature Template Content Error (pug)", async t => { }); test("Throws a Premature Template Content Error from rendering (pug)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.pug", "./test/stubs/", "./test/stubs/_site" @@ -1667,7 +1699,7 @@ test("Throws a Premature Template Content Error from rendering (pug)", async t = }); test("Throws a Premature Template Content Error (md)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.md", "./test/stubs/", "./test/stubs/_site" @@ -1682,7 +1714,7 @@ test("Throws a Premature Template Content Error (md)", async t => { }); test("Throws a Premature Template Content Error from rendering (md)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.md", "./test/stubs/", "./test/stubs/_site" @@ -1706,7 +1738,7 @@ test("Throws a Premature Template Content Error from rendering (md)", async t => }); test("Throws a Premature Template Content Error (hbs)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.hbs", "./test/stubs/", "./test/stubs/_site" @@ -1721,7 +1753,7 @@ test("Throws a Premature Template Content Error (hbs)", async t => { }); test("Throws a Premature Template Content Error from rendering (hbs)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.hbs", "./test/stubs/", "./test/stubs/_site" @@ -1745,7 +1777,7 @@ test("Throws a Premature Template Content Error from rendering (hbs)", async t = }); test("Throws a Premature Template Content Error (mustache)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.mustache", "./test/stubs/", "./test/stubs/_site" @@ -1760,7 +1792,7 @@ test("Throws a Premature Template Content Error (mustache)", async t => { }); test("Throws a Premature Template Content Error (ejs)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.ejs", "./test/stubs/", "./test/stubs/_site" @@ -1775,7 +1807,7 @@ test("Throws a Premature Template Content Error (ejs)", async t => { }); test("Throws a Premature Template Content Error (haml)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.haml", "./test/stubs/", "./test/stubs/_site" @@ -1790,7 +1822,7 @@ test("Throws a Premature Template Content Error (haml)", async t => { }); test.skip("Issue 413 weird date format", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs-413/date-frontmatter.md", "./test/stubs-413/", "./dist" @@ -1806,7 +1838,7 @@ test("Custom Front Matter Parsing Options", async t => { excerpt: true }; - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template.njk", "./test/stubs/", "./dist" @@ -1835,7 +1867,7 @@ test("Custom Front Matter Parsing Options (using alias)", async t => { excerpt_alias: "my_excerpt" }; - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template.njk", "./test/stubs/", "./dist" @@ -1861,7 +1893,7 @@ test("Custom Front Matter Parsing Options (no newline before excerpt separator)" excerpt: true }; - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-newline1.njk", "./test/stubs/", "./dist" @@ -1889,7 +1921,7 @@ test("Custom Front Matter Parsing Options (no newline after excerpt separator)", excerpt: true }; - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-newline3.njk", "./test/stubs/", "./dist" @@ -1910,7 +1942,7 @@ test("Custom Front Matter Parsing Options (no newlines before or after excerpt s excerpt: true }; - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-newline2.njk", "./test/stubs/", "./dist" @@ -1928,7 +1960,7 @@ test("Custom Front Matter Parsing Options (html comment separator)", async t => excerpt_separator: "" }; - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-excerpt-comment.njk", "./test/stubs/", "./dist" @@ -1958,7 +1990,7 @@ test.skip("Custom Front Matter Parsing Options (using TOML)", async t => { } }; - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-toml.njk", "./test/stubs/", "./dist" @@ -1976,7 +2008,7 @@ test.skip("Custom Front Matter Parsing Options (using TOML)", async t => { }); test("global variable with dashes Issue #567 (liquid)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/global-dash-variable.liquid", "./test/stubs/", "./dist" @@ -1990,7 +2022,7 @@ test("global variable with dashes Issue #567 (liquid)", async t => { }); test("Issue #446: Layout has a permalink with a different template language than content", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/layout-permalink-difflang/test.md", "./test/stubs/layout-permalink-difflang/", "dist" @@ -2009,7 +2041,7 @@ test("Layout front matter should override template files", async t => { let dataObj = new TemplateData( "./test/stubs-data-cascade/layout-data-files/" ); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs-data-cascade/layout-data-files/test.njk", "./test/stubs-data-cascade/layout-data-files/", "./dist", @@ -2021,7 +2053,7 @@ test("Layout front matter should override template files", async t => { }); test("Get Layout Chain", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs-incremental/layout-chain/test.njk", "./test/stubs-incremental/layout-chain/", "./dist" @@ -2035,7 +2067,7 @@ test("Get Layout Chain", async t => { }); test("eleventyComputed", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/first.njk", "./test/stubs/", "./dist" @@ -2045,7 +2077,7 @@ test("eleventyComputed", async t => { }); test("eleventyComputed overrides existing value.", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/override.njk", "./test/stubs/", "./dist" @@ -2056,7 +2088,7 @@ test("eleventyComputed overrides existing value.", async t => { }); test("eleventyComputed overrides existing value and reuses that upstream value", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/override-reuse.njk", "./test/stubs/", "./dist" @@ -2067,7 +2099,7 @@ test("eleventyComputed overrides existing value and reuses that upstream value", }); test("eleventyComputed permalink", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/permalink.njk", "./test/stubs/", "./dist" @@ -2083,7 +2115,7 @@ test("eleventyComputed permalink", async t => { }); test("eleventyComputed simple permalink", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/permalink-simple.njk", "./test/stubs/", "./dist" @@ -2096,7 +2128,7 @@ test("eleventyComputed simple permalink", async t => { }); test("eleventyComputed permalink using slug", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/permalink-slug.njk", "./test/stubs/", "./dist" @@ -2109,7 +2141,7 @@ test("eleventyComputed permalink using slug", async t => { }); test("eleventyComputed js front matter (function)", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/second.njk", "./test/stubs/", "./dist" @@ -2120,7 +2152,7 @@ test("eleventyComputed js front matter (function)", async t => { }); test("eleventyComputed js front matter key reuses and overrides", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/third.njk", "./test/stubs/", "./dist" @@ -2131,7 +2163,7 @@ test("eleventyComputed js front matter key reuses and overrides", async t => { }); test("eleventyComputed true primitive", async t => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/true.njk", "./test/stubs/", "./dist" @@ -2145,7 +2177,7 @@ test("eleventyComputed true primitive", async t => { test("eleventyComputed relies on global data", async t => { let dataObj = new TemplateData("./test/stubs/"); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/use-global-data.njk", "./test/stubs/", "./dist", From 838d2480dce814c11762f2a62afde14d2e901f12 Mon Sep 17 00:00:00 2001 From: Ru Singh Date: Mon, 27 Apr 2020 11:49:52 +0530 Subject: [PATCH 194/746] Named broswer-sync instance --- src/EleventyServe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 94349a98c..7d97df76b 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -116,7 +116,7 @@ class EleventyServe { serve(port) { // only load on serve—this is pretty expensive const browserSync = require("browser-sync"); - this.server = browserSync.create(); + this.server = browserSync.create("eleventyServer"); let pathPrefix = this.getPathPrefix(); From de1f8c5a4293ed0d04f88b3a586c2365717b1f90 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Apr 2020 16:06:13 -0500 Subject: [PATCH 195/746] Test for #1105 --- test/TemplateTest.js | 30 +++++++++++++++++++ .../_data/eleventyComputed.js | 13 ++++++++ test/stubs-computed-global/intermix.njk | 13 ++++++++ 3 files changed, 56 insertions(+) create mode 100644 test/stubs-computed-global/_data/eleventyComputed.js create mode 100644 test/stubs-computed-global/intermix.njk diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 77cd2da70..144fa5925 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -7,6 +7,7 @@ import EleventyExtensionMap from "../src/EleventyExtensionMap"; import EleventyErrorUtil from "../src/EleventyErrorUtil"; import TemplateContentPrematureUseError from "../src/Errors/TemplateContentPrematureUseError"; import normalizeNewLines from "./Util/normalizeNewLines"; +import { cloneDeep } from "lodash"; import templateConfig from "../src/Config"; const config = templateConfig.getConfig(); @@ -2189,3 +2190,32 @@ test("eleventyComputed relies on global data", async t => { let data = templates[0].data; t.is(data.image, "datavalue1"); }); + +test("eleventyComputed intermixes with global data", async t => { + let dataObj = new TemplateData("./test/stubs-computed-global/"); + + let config = cloneDeep(dataObj.config); + config.dataDeepMerge = true; + dataObj._setConfig(config); + + let tmpl = getNewTemplate( + "./test/stubs-computed-global/intermix.njk", + "./test/stubs-computed-global/", + "./dist", + dataObj + ); + tmpl.config = config; + + let fetchedData = await tmpl.getData(); + t.truthy(fetchedData.eleventyComputed.image); + t.truthy(fetchedData.eleventyComputed.image2); + t.truthy(fetchedData.eleventyComputed.image3); + t.truthy(fetchedData.eleventyComputed.eleventyNavigation.key); + + let templates = await tmpl.getTemplates(fetchedData); + let data = templates[0].data; + t.is(data.image, "first"); + t.is(data.image2, "second"); + t.is(data.image3, "third-global"); + t.is(data.eleventyNavigation.key, "nested-first-global"); +}); diff --git a/test/stubs-computed-global/_data/eleventyComputed.js b/test/stubs-computed-global/_data/eleventyComputed.js new file mode 100644 index 000000000..3c67361b1 --- /dev/null +++ b/test/stubs-computed-global/_data/eleventyComputed.js @@ -0,0 +1,13 @@ +module.exports = { + eleventyNavigation: { + key: data => { + return "nested-first-global"; + } + }, + image2: data => { + return "second-global"; + }, + image3: data => { + return "third-global"; + } +}; diff --git a/test/stubs-computed-global/intermix.njk b/test/stubs-computed-global/intermix.njk new file mode 100644 index 000000000..637477eb3 --- /dev/null +++ b/test/stubs-computed-global/intermix.njk @@ -0,0 +1,13 @@ +---js +{ + eleventyComputed: { + image: data => { + return "first"; + }, + image2: data => { + return "second"; + } + } +} +--- +Issue #1043 \ No newline at end of file From 9bc8ae11cf873b1fd64f825565f6e2526fd93fd3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Apr 2020 16:14:00 -0500 Subject: [PATCH 196/746] Test for issue #1114 --- test/ComputedDataTest.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index 68224ff4f..edd7850ef 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -19,6 +19,20 @@ test("Basic get/set", async t => { t.is(data.keystr, "this is a str"); }); +test("Boolean computed value Issue #1114", async t => { + let cd = new ComputedData(); + + cd.add("bool1", true); + + let data = { + key2: "inject me" + }; + await cd.setupData(data); + + t.is(data.bool1, true); + t.is(data.key2, "inject me"); +}); + test("Basic get/set (reverse order of adds)", async t => { let cd = new ComputedData(); From a0b19a3920a7d1ef18ce60aef7394a7ce4060268 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Apr 2020 17:06:38 -0500 Subject: [PATCH 197/746] Some debug output for computed data --- src/ComputedData.js | 4 +++- src/ComputedDataProxy.js | 7 +++---- src/ComputedDataTemplateString.js | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ComputedData.js b/src/ComputedData.js index 8ac0327d0..bcd016759 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -5,7 +5,7 @@ const DependencyGraph = require("dependency-graph").DepGraph; const ComputedDataTemplateString = require("./ComputedDataTemplateString"); const ComputedDataProxy = require("./ComputedDataProxy"); -// const debug = require("debug")("Eleventy:ComputedData"); +const debug = require("debug")("Eleventy:ComputedData"); class ComputedData { constructor() { @@ -53,6 +53,7 @@ class ComputedData { proxy = new ComputedDataProxy(this.computedKeys); } let varsUsed = await proxy.findVarsUsed(computed, data); + debug("%o accesses %o variables", key, varsUsed); for (let varUsed of varsUsed) { if (varUsed !== key && this.computedKeys.has(varUsed)) { graph.addNode(varUsed); @@ -70,6 +71,7 @@ class ComputedData { async setupData(data) { let order = await this.getVarOrder(data); + debug("Computed data order of execution: %o", order); for (let key of order) { let computed = lodashGet(this.computed, key); diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index 4487b5c10..52840fe4b 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -34,7 +34,6 @@ class ComputedDataProxy { {}, { get: (obj, key) => { - // console.log( obj, key, parentKey ); if (typeof key !== "string") { return obj[key]; } @@ -71,10 +70,10 @@ class ComputedDataProxy { let proxyData = this.getProxyData(data, keyRef); // squelch console logs for this fake proxy data pass 😅 - let savedLog = console.log; - console.log = () => {}; + // let savedLog = console.log; + // console.log = () => {}; await fn(proxyData); - console.log = savedLog; + // console.log = savedLog; return Array.from(keyRef); } diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js index 2064b4b94..bd9d2c8df 100644 --- a/src/ComputedDataTemplateString.js +++ b/src/ComputedDataTemplateString.js @@ -44,15 +44,15 @@ class ComputedDataTemplateString { async findVarsUsed(fn, data = {}) { let proxyData = this.getProxyData(); let output; - let savedLog = console.log; - console.log = () => {}; + // let savedLog = console.log; + // console.log = () => {}; // Mitigation for #1061, errors with filters in the first pass shouldn’t fail the whole thing. try { output = await fn(proxyData); } catch (e) { debug("Computed Data first pass data resolution error: %o", e); } - console.log = savedLog; + // console.log = savedLog; return this.findVarsInOutput(output); } From e528cec008ba9016b07990b2cb6f6b8742cc6f8f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Apr 2020 17:07:31 -0500 Subject: [PATCH 198/746] Another test for #1105 --- test/ComputedDataTest.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index edd7850ef..c2ad6ea4b 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -249,3 +249,29 @@ test("Basic get/set using array data", async t => { t.is(data.arr[0], "inject me"); t.is(data.keystr, "this is a str"); }); + +test("Computed returns deep object", async t => { + let cd = new ComputedData(); + + cd.add("returnobj", data => { + return { + key1: "value1", + nest: { + key2: "value2" + } + }; + }); + + let data = { + returnobj: { + key1: "bad1", + nest: { + key2: "bad2" + } + } + }; + await cd.setupData(data); + + t.is(data.returnobj.key1, "value1"); + t.is(data.returnobj.nest.key2, "value2"); +}); From 58858b16e24d20ae85b14c29ec80f6d07b5f100f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 28 Apr 2020 17:19:20 -0500 Subject: [PATCH 199/746] Delay computed data processing when they depend on collections. Fix for #1114 --- src/ComputedData.js | 82 ++++---- src/ComputedDataProxy.js | 5 + src/ComputedDataQueue.js | 60 ++++++ src/Template.js | 32 ++- src/TemplateMap.js | 12 ++ test/ComputedDataQueueTest.js | 79 ++++++++ test/ComputedDataTest.js | 124 ++++++++++-- test/TemplateMapTest-ComputedData.js | 46 +++++ test/TemplateTest-ComputedData.js | 164 ++++++++++++++++ test/TemplateTest.js | 185 +----------------- test/_getNewTemplate.js | 28 +++ .../collections.njk | 11 ++ test/stubs-computed-collections/dog.njk | 4 + 13 files changed, 586 insertions(+), 246 deletions(-) create mode 100644 src/ComputedDataQueue.js create mode 100644 test/ComputedDataQueueTest.js create mode 100644 test/TemplateMapTest-ComputedData.js create mode 100644 test/TemplateTest-ComputedData.js create mode 100644 test/_getNewTemplate.js create mode 100644 test/stubs-computed-collections/collections.njk create mode 100644 test/stubs-computed-collections/dog.njk diff --git a/src/ComputedData.js b/src/ComputedData.js index bcd016759..d8593db49 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -1,7 +1,7 @@ const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); -const DependencyGraph = require("dependency-graph").DepGraph; +const ComputedDataQueue = require("./ComputedDataQueue"); const ComputedDataTemplateString = require("./ComputedDataTemplateString"); const ComputedDataProxy = require("./ComputedDataProxy"); @@ -13,6 +13,7 @@ class ComputedData { this.templateStringKeyLookup = {}; this.computedKeys = new Set(); this.declaredDependencies = {}; + this.queue = new ComputedDataQueue(); } add(key, fn, declaredDependencies = []) { @@ -27,50 +28,39 @@ class ComputedData { this.templateStringKeyLookup[key] = true; } - async getVarOrder(data) { - if (this.computedKeys.size > 0) { - let graph = new DependencyGraph(); - - for (let key of this.computedKeys) { - let computed = lodashGet(this.computed, key); - - graph.addNode(key); - - if (typeof computed === "function") { - if (this.declaredDependencies[key].length) { - for (let dep of this.declaredDependencies[key]) { - graph.addNode(dep); - graph.addDependency(key, dep); - } - } - - let proxy; - let isTemplateString = !!this.templateStringKeyLookup[key]; - // TODO move this out of the loop?? - if (isTemplateString) { - proxy = new ComputedDataTemplateString(this.computedKeys); - } else { - proxy = new ComputedDataProxy(this.computedKeys); - } - let varsUsed = await proxy.findVarsUsed(computed, data); - debug("%o accesses %o variables", key, varsUsed); - for (let varUsed of varsUsed) { - if (varUsed !== key && this.computedKeys.has(varUsed)) { - graph.addNode(varUsed); - graph.addDependency(key, varUsed); - } - } + async resolveVarOrder(data) { + for (let key of this.computedKeys) { + let computed = lodashGet(this.computed, key); + + if (typeof computed !== "function") { + // add nodes for non functions (primitives like booleans, etc) + this.queue.addNode(key); + } else { + this.queue.uses(key, this.declaredDependencies[key]); + + let proxy; + let isTemplateString = !!this.templateStringKeyLookup[key]; + // TODO move this out of the loop?? + if (isTemplateString) { + proxy = new ComputedDataTemplateString(this.computedKeys); + } else { + proxy = new ComputedDataProxy(this.computedKeys); } - } - return graph.overallOrder(); + let varsUsed = await proxy.findVarsUsed(computed, data); + debug("%o accesses %o variables", key, varsUsed); + let filteredVarsUsed = varsUsed.filter(varUsed => { + return ( + (varUsed !== key && this.computedKeys.has(varUsed)) || + varUsed.startsWith("collections.") + ); + }); + this.queue.uses(key, filteredVarsUsed); + } } - - return []; } - async setupData(data) { - let order = await this.getVarOrder(data); + async _setupDataEntry(data, order) { debug("Computed data order of execution: %o", order); for (let key of order) { @@ -83,6 +73,18 @@ class ComputedData { } } } + + async setupData(data, orderFilter) { + await this.resolveVarOrder(data); + + // process all variables + let order = this.queue.getOrder(); + if (orderFilter && typeof orderFilter === "function") { + order = order.filter(orderFilter.bind(this.queue)); + } + await this._setupDataEntry(data, order); + this.queue.markComputed(order); + } } module.exports = ComputedData; diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index 52840fe4b..d086afe4f 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -49,6 +49,11 @@ class ComputedDataProxy { } else if (Array.isArray(data)) { return new Proxy([], { get: (obj, key) => { + // why + if (key === "then") { + keyRef.add(parentKey); + return; + } let newKey = `${parentKey}[${key}]`; let newData = this._getProxyData(data[key], keyRef, newKey); if (!this.isArrayOrPlainObject(newData)) { diff --git a/src/ComputedDataQueue.js b/src/ComputedDataQueue.js new file mode 100644 index 000000000..51abb8ee3 --- /dev/null +++ b/src/ComputedDataQueue.js @@ -0,0 +1,60 @@ +const DependencyGraph = require("dependency-graph").DepGraph; + +class ComputedDataQueue { + constructor() { + this.graph = new DependencyGraph(); + } + + getOrder() { + return this.graph.overallOrder(); + } + + getOrderFor(name) { + return this.graph.dependenciesOf(name); + } + + getDependsOn(name) { + return this.graph.dependantsOf(name); + } + + isDependsOnStartsWith(name, prefix) { + if (name.startsWith(prefix)) { + return true; + } + return ( + this.graph.dependantsOf(name).filter(entry => entry.startsWith(prefix)) + .length > 0 + ); + } + + addNode(name) { + if (!this.graph.hasNode(name)) { + this.graph.addNode(name); + } + } + + _uses(graph, name, varsUsed = []) { + if (!graph.hasNode(name)) { + graph.addNode(name); + } + + for (let varUsed of varsUsed) { + if (!graph.hasNode(varUsed)) { + graph.addNode(varUsed); + } + graph.addDependency(name, varUsed); + } + } + + uses(name, varsUsed = []) { + this._uses(this.graph, name, varsUsed); + } + + markComputed(varsComputed = []) { + for (let varComputed of varsComputed) { + this.graph.removeNode(varComputed); + } + } +} + +module.exports = ComputedDataQueue; diff --git a/src/Template.js b/src/Template.js index 47581434e..023d093ce 100644 --- a/src/Template.js +++ b/src/Template.js @@ -404,25 +404,33 @@ class Template extends TemplateContent { } } - async augmentFinalData(data) { + async addComputedData(data) { // will _not_ consume renderData - let computedData = new ComputedData(); + this.computedData = new ComputedData(); // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly - computedData.addTemplateString( + this.computedData.addTemplateString( "page.url", async data => await this.getOutputHref(data), ["permalink"] ); - computedData.addTemplateString( + this.computedData.addTemplateString( "page.outputPath", async data => await this.getOutputPath(data), ["permalink"] ); if (this.config.keys.computed in data) { - this._addComputedEntry(computedData, data[this.config.keys.computed]); + this._addComputedEntry( + this.computedData, + data[this.config.keys.computed] + ); } - await computedData.setupData(data); + + // limited run of computed data, do most of it later when collections are available. + // await this.computedData.setupData(data); + await this.computedData.setupData(data, function(entry) { + return !this.isDependsOnStartsWith(entry, "collections."); + }); // deprecated, use eleventyComputed instead. if ("renderData" in data) { @@ -433,12 +441,16 @@ class Template extends TemplateContent { } } + async resolveRemainingComputedData(data) { + await this.computedData.setupData(data); + } + async getTemplates(data) { // TODO cache this let results = []; if (!Pagination.hasPagination(data)) { - await this.augmentFinalData(data); + await this.addComputedData(data); results.push({ template: this, @@ -467,9 +479,9 @@ class Template extends TemplateContent { // but individual pagination entries won’t be part of a collection this.paging = new Pagination(data); this.paging.setTemplate(this); - let templates = await this.paging.getPageTemplates(); + let pageTemplates = await this.paging.getPageTemplates(); let pageNumber = 0; - for (let page of templates) { + for (let page of pageTemplates) { let pageData = Object.assign({}, await page.getData()); // Issue #115 @@ -477,7 +489,7 @@ class Template extends TemplateContent { pageData.collections = data.collections; } - await page.augmentFinalData(pageData); + await page.addComputedData(pageData); results.push({ template: page, diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 2b1a7a514..b3e3e90c4 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -287,6 +287,8 @@ class TemplateMap { let secondPaginatedDepMap = this.getPaginatedOverAllCollectionMappedDependencies(); await this.initDependencyMap(secondPaginatedDepMap); + await this.resolveRemainingComputedData(); + let orderedPaths = this.getOrderedInputPaths( dependencyMap, delayedDependencyMap, @@ -501,6 +503,16 @@ class TemplateMap { } } + async resolveRemainingComputedData() { + let promises = []; + for (let entry of this.map) { + for (let page of entry._pages) { + promises.push(page.template.resolveRemainingComputedData(page.data)); + } + } + return Promise.all(promises); + } + checkForDuplicatePermalinks() { let permalinks = {}; let warnings = {}; diff --git a/test/ComputedDataQueueTest.js b/test/ComputedDataQueueTest.js new file mode 100644 index 000000000..5c8f02c35 --- /dev/null +++ b/test/ComputedDataQueueTest.js @@ -0,0 +1,79 @@ +import test from "ava"; +import ComputedDataQueue from "../src/ComputedDataQueue"; + +test("Standard uses", t => { + let queue = new ComputedDataQueue(); + queue.uses("permalink", ["var1", "var2"]); + queue.uses("collections.all", ["var2", "var3"]); + t.deepEqual(queue.getOrder(), [ + "var1", + "var2", + "permalink", + "var3", + "collections.all" + ]); +}); + +test("What does permalink use", t => { + let queue = new ComputedDataQueue(); + queue.uses("permalink", ["var1", "var2"]); + queue.uses("collections.all", ["var2", "var3"]); + + let varsUsedByPermalink = queue.getOrderFor("permalink"); + t.deepEqual(varsUsedByPermalink, ["var1", "var2"]); + + // After we process these + queue.markComputed(["permalink", ...varsUsedByPermalink]); + t.deepEqual(queue.getOrder(), ["var3", "collections.all"]); +}); + +test("What does page.url and page.outputPath use", t => { + let queue = new ComputedDataQueue(); + queue.uses("page.url", ["permalink"]); + queue.uses("page.url", ["var1", "var2"]); + queue.uses("page.outputPath", ["permalink"]); + queue.uses("page.outputPath", ["var2", "var3"]); + + let varsUsedByPageUrl = queue.getOrderFor("page.url"); + t.deepEqual(varsUsedByPageUrl, ["permalink", "var1", "var2"]); + queue.markComputed([...varsUsedByPageUrl, "page.url"]); + t.deepEqual(queue.getOrder(), ["var3", "page.outputPath"]); + + let varsUsedByPageOutput = queue.getOrderFor("page.outputPath"); + // even though page.outputPath used permalink and var2, + // they were already computed above by page.url + t.deepEqual(varsUsedByPageOutput, ["var3"]); + queue.markComputed([...varsUsedByPageOutput, "page.outputPath"]); + t.deepEqual(queue.getOrder(), []); +}); + +test("Permalink uses a collection (not yet supported in Eleventy)", t => { + let queue = new ComputedDataQueue(); + queue.uses("permalink", ["collections.dog", "var2"]); + queue.uses("collections.all", ["var2", "var3"]); + queue.uses("collections.dog", ["hi"]); + queue.uses("unrelated", ["test"]); + + t.deepEqual(queue.getDependsOn("collections.dog"), ["permalink"]); + t.deepEqual(queue.getDependsOn("var2"), ["permalink", "collections.all"]); + t.deepEqual(queue.getDependsOn("collections.all"), []); + t.deepEqual(queue.getDependsOn("hi"), ["permalink", "collections.dog"]); + t.is(queue.isDependsOnStartsWith("hi", "collections."), true); + t.is(queue.isDependsOnStartsWith("collections.all", "collections."), true); + t.is(queue.isDependsOnStartsWith("var2", "collections."), true); + t.is(queue.isDependsOnStartsWith("unrelated", "collections."), false); + + t.deepEqual(queue.getOrderFor("unrelated"), ["test"]); + + let varsUsedByPermalink = queue.getOrderFor("permalink"); + t.deepEqual(varsUsedByPermalink, ["hi", "collections.dog", "var2"]); + + // After we process these + queue.markComputed(["permalink", ...varsUsedByPermalink]); + t.deepEqual(queue.getOrder(), [ + "var3", + "collections.all", + "test", + "unrelated" + ]); +}); diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index c2ad6ea4b..4662687ce 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -19,20 +19,6 @@ test("Basic get/set", async t => { t.is(data.keystr, "this is a str"); }); -test("Boolean computed value Issue #1114", async t => { - let cd = new ComputedData(); - - cd.add("bool1", true); - - let data = { - key2: "inject me" - }; - await cd.setupData(data); - - t.is(data.bool1, true); - t.is(data.key2, "inject me"); -}); - test("Basic get/set (reverse order of adds)", async t => { let cd = new ComputedData(); @@ -275,3 +261,113 @@ test("Computed returns deep object", async t => { t.is(data.returnobj.key1, "value1"); t.is(data.returnobj.nest.key2, "value2"); }); + +test("Boolean computed value Issue #1114", async t => { + let cd = new ComputedData(); + + cd.add("bool1", true); + + let data = { + key2: "inject me" + }; + await cd.setupData(data); + + t.is(data.bool1, true); + t.is(data.key2, "inject me"); +}); + +test("Expect collections in data callback #1114", async t => { + t.plan(4); + let cd = new ComputedData(); + + cd.add("key1", data => { + t.is(data.collections.first[0], 1); + t.is(data.collections.second[0], 2); + return ``; + }); + + let data = { + collections: { + first: [1], + second: [2] + } + }; + await cd.setupData(data); +}); + +test("Get var order", async t => { + let cd = new ComputedData(); + + cd.add("key1", data => data.collections.all); + cd.add("key2", data => data.collections.dog); + cd.add("key0", data => ""); + + let data = { + key2: "inject me", + collections: { + all: [1], + dog: [2] + } + }; + + await cd.resolveVarOrder(data); + t.deepEqual(cd.queue.getOrder(), [ + "collections.all", + "key1", + "collections.dog", + "key2", + "key0" + ]); +}); + +test("Get var order and process it in two stages", async t => { + let cd = new ComputedData(); + + cd.add("page.url", data => data.key2); + cd.add("page.outputPath", data => `${data.key2}${data.collections.dog[0]}`); + cd.add("key0", data => "hi"); + cd.add("collections.processed", data => "hi"); + + let data = { + key2: "/my-path/", + collections: { + dog: [2] + } + }; + + // set page.url, page.outputPath, key2, collections.dog[0] + await cd.setupData(data, function(entry) { + return !this.isDependsOnStartsWith(entry, "collections."); + }); + + t.deepEqual(data, { + collections: { + dog: [2], + processed: "" + }, + key0: "hi", + key2: "/my-path/", + page: { + url: "/my-path/", + outputPath: "/my-path/2" + } + }); + + // set collections.processed + await cd.setupData(data); + + t.deepEqual(data, { + collections: { + dog: [2], + processed: "hi" + }, + key0: "hi", + key2: "/my-path/", + page: { + url: "/my-path/", + outputPath: "/my-path/2" + } + }); + + // t.deepEqual(cd.queue.getOrder(), ["collections.all", "key1", "collections.dog", "key2", "key0"]); +}); diff --git a/test/TemplateMapTest-ComputedData.js b/test/TemplateMapTest-ComputedData.js new file mode 100644 index 000000000..e5b922540 --- /dev/null +++ b/test/TemplateMapTest-ComputedData.js @@ -0,0 +1,46 @@ +import test from "ava"; +import Template from "../src/Template"; +import TemplateData from "../src/TemplateData"; +import TemplateMap from "../src/TemplateMap"; +import getNewTemplate from "./_getNewTemplate"; + +test("Computed data can see tag generated collections", async t => { + let tm = new TemplateMap(); + + let dataObj = new TemplateData("./test/stubs-computed-collections/"); + let tmpl = getNewTemplate( + "./test/stubs-computed-collections/collections.njk", + "./test/stubs-computed-collections/", + "./dist", + dataObj + ); + + await tm.add(tmpl); + + let dataObj2 = new TemplateData("./test/stubs-computed-collections/"); + let tmpl2 = getNewTemplate( + "./test/stubs-computed-collections/dog.njk", + "./test/stubs-computed-collections/", + "./dist", + dataObj2 + ); + + await tm.add(tmpl2); + + await tm.cache(); + + let map = tm.getMap(); + + t.is(map[0].inputPath.endsWith("collections.njk"), true); + + t.truthy(map[0].data.collections.all); + t.is(map[0].data.collections.all.length, 2); + t.truthy(map[0].data.collections.dog); + t.is(map[0].data.collections.dog.length, 1); + t.truthy(map[0].data.dogCollection); + t.is(map[0].data.dogCollection.length, 1); + t.is(map[0].data.test, "hello"); + + // THEY ARE THE SAME + t.is(map[0].data.dogCollection, map[0].data.collections.dog); +}); diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js new file mode 100644 index 000000000..7b194fb2d --- /dev/null +++ b/test/TemplateTest-ComputedData.js @@ -0,0 +1,164 @@ +import test from "ava"; +import Template from "../src/Template"; +import TemplateData from "../src/TemplateData"; +import { cloneDeep } from "lodash"; +import getNewTemplate from "./_getNewTemplate"; + +async function getRenderedData(tmpl, pageNumber = 0) { + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + return templates[pageNumber].data; +} + +test("eleventyComputed", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/first.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); +}); + +test("eleventyComputed overrides existing value.", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/override.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "override"); + t.is((await tmpl.render(data)).trim(), "hi:override"); +}); + +test("eleventyComputed overrides existing value and reuses that upstream value", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/override-reuse.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "over(value1)ride"); + t.is((await tmpl.render(data)).trim(), "hi:over(value1)ride"); +}); + +test("eleventyComputed permalink", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/permalink.njk", + "./test/stubs/", + "./dist" + ); + let templates = await tmpl.getTemplates(await tmpl.getData()); + let data = templates[0].data; + t.is(data.page.url, "/haha-value1.html"); + t.is(data.page.outputPath, "./dist/haha-value1.html"); + t.is(data.permalink, "haha-value1.html"); + t.is(data.nested.key3, "value1"); + t.is(data.nested.key4, "depends on computed value1"); + t.is(data.dependsOnPage, "depends:/haha-value1.html"); +}); + +test("eleventyComputed simple permalink", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/permalink-simple.njk", + "./test/stubs/", + "./dist" + ); + let templates = await tmpl.getTemplates(await tmpl.getData()); + let data = templates[0].data; + t.is(data.page.url, "/haha-value1.html"); + t.is(data.page.outputPath, "./dist/haha-value1.html"); + t.is(data.permalink, "haha-value1.html"); +}); + +test("eleventyComputed permalink using slug", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/permalink-slug.njk", + "./test/stubs/", + "./dist" + ); + let templates = await tmpl.getTemplates(await tmpl.getData()); + let data = templates[0].data; + t.is(data.page.url, "/haha-this-is-a-string.html"); + t.is(data.page.outputPath, "./dist/haha-this-is-a-string.html"); + t.is(data.permalink, "haha-this-is-a-string.html"); +}); + +test("eleventyComputed js front matter (function)", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/second.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key3, "value3-value2-value1.css"); + t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); +}); + +test("eleventyComputed js front matter key reuses and overrides", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/third.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "value2-value1"); + t.is((await tmpl.render(data)).trim(), "hi:value2-value1"); +}); + +test("eleventyComputed true primitive", async t => { + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/true.njk", + "./test/stubs/", + "./dist" + ); + let data = await getRenderedData(tmpl); + t.is(data.key1, "value1"); + t.is(data.key2, true); + t.is(data.key3, false); + t.is(data.key4, 324); +}); + +test("eleventyComputed relies on global data", async t => { + let dataObj = new TemplateData("./test/stubs/"); + let tmpl = getNewTemplate( + "./test/stubs/eleventyComputed/use-global-data.njk", + "./test/stubs/", + "./dist", + dataObj + ); + + let fetchedData = await tmpl.getData(); + let templates = await tmpl.getTemplates(fetchedData); + let data = templates[0].data; + t.is(data.image, "datavalue1"); +}); + +test("eleventyComputed intermixes with global data", async t => { + let dataObj = new TemplateData("./test/stubs-computed-global/"); + + let config = cloneDeep(dataObj.config); + config.dataDeepMerge = true; + dataObj._setConfig(config); + + let tmpl = getNewTemplate( + "./test/stubs-computed-global/intermix.njk", + "./test/stubs-computed-global/", + "./dist", + dataObj + ); + tmpl.config = config; + + let fetchedData = await tmpl.getData(); + t.truthy(fetchedData.eleventyComputed.image); + t.truthy(fetchedData.eleventyComputed.image2); + t.truthy(fetchedData.eleventyComputed.image3); + t.truthy(fetchedData.eleventyComputed.eleventyNavigation.key); + + let templates = await tmpl.getTemplates(fetchedData); + let data = templates[0].data; + t.is(data.image, "first"); + t.is(data.image2, "second"); + t.is(data.image3, "third-global"); + t.is(data.eleventyNavigation.key, "nested-first-global"); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 144fa5925..5dcb09207 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1,49 +1,23 @@ import test from "ava"; import fs from "fs-extra"; import pretty from "pretty"; -import TemplateData from "../src/TemplateData"; import Template from "../src/Template"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +import TemplateData from "../src/TemplateData"; import EleventyErrorUtil from "../src/EleventyErrorUtil"; import TemplateContentPrematureUseError from "../src/Errors/TemplateContentPrematureUseError"; import normalizeNewLines from "./Util/normalizeNewLines"; -import { cloneDeep } from "lodash"; import templateConfig from "../src/Config"; const config = templateConfig.getConfig(); +import getNewTemplate from "./_getNewTemplate"; + async function getRenderedData(tmpl, pageNumber = 0) { let data = await tmpl.getData(); let templates = await tmpl.getTemplates(data); return templates[pageNumber].data; } -function getNewTemplate( - path, - inputDir, - outputDir, - templateData = null, - map = null -) { - if (!map) { - map = new EleventyExtensionMap([ - "liquid", - "ejs", - "md", - "hbs", - "mustache", - "haml", - "pug", - "njk", - "html", - "jstl", - "11ty.js" - ]); - } - let tmpl = new Template(path, inputDir, outputDir, templateData, map); - return tmpl; -} - function cleanHtml(str) { return pretty(str, { ocd: true }); } @@ -2066,156 +2040,3 @@ test("Get Layout Chain", async t => { "./test/stubs-incremental/layout-chain/_includes/parent.njk" ]); }); - -test("eleventyComputed", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/first.njk", - "./test/stubs/", - "./dist" - ); - let data = await getRenderedData(tmpl); - t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); -}); - -test("eleventyComputed overrides existing value.", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/override.njk", - "./test/stubs/", - "./dist" - ); - let data = await getRenderedData(tmpl); - t.is(data.key1, "override"); - t.is((await tmpl.render(data)).trim(), "hi:override"); -}); - -test("eleventyComputed overrides existing value and reuses that upstream value", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/override-reuse.njk", - "./test/stubs/", - "./dist" - ); - let data = await getRenderedData(tmpl); - t.is(data.key1, "over(value1)ride"); - t.is((await tmpl.render(data)).trim(), "hi:over(value1)ride"); -}); - -test("eleventyComputed permalink", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/permalink.njk", - "./test/stubs/", - "./dist" - ); - let templates = await tmpl.getTemplates(await tmpl.getData()); - let data = templates[0].data; - t.is(data.page.url, "/haha-value1.html"); - t.is(data.page.outputPath, "./dist/haha-value1.html"); - t.is(data.permalink, "haha-value1.html"); - t.is(data.nested.key3, "value1"); - t.is(data.nested.key4, "depends on computed value1"); - t.is(data.dependsOnPage, "depends:/haha-value1.html"); -}); - -test("eleventyComputed simple permalink", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/permalink-simple.njk", - "./test/stubs/", - "./dist" - ); - let templates = await tmpl.getTemplates(await tmpl.getData()); - let data = templates[0].data; - t.is(data.page.url, "/haha-value1.html"); - t.is(data.page.outputPath, "./dist/haha-value1.html"); - t.is(data.permalink, "haha-value1.html"); -}); - -test("eleventyComputed permalink using slug", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/permalink-slug.njk", - "./test/stubs/", - "./dist" - ); - let templates = await tmpl.getTemplates(await tmpl.getData()); - let data = templates[0].data; - t.is(data.page.url, "/haha-this-is-a-string.html"); - t.is(data.page.outputPath, "./dist/haha-this-is-a-string.html"); - t.is(data.permalink, "haha-this-is-a-string.html"); -}); - -test("eleventyComputed js front matter (function)", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/second.njk", - "./test/stubs/", - "./dist" - ); - let data = await getRenderedData(tmpl); - t.is(data.key3, "value3-value2-value1.css"); - t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); -}); - -test("eleventyComputed js front matter key reuses and overrides", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/third.njk", - "./test/stubs/", - "./dist" - ); - let data = await getRenderedData(tmpl); - t.is(data.key1, "value2-value1"); - t.is((await tmpl.render(data)).trim(), "hi:value2-value1"); -}); - -test("eleventyComputed true primitive", async t => { - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/true.njk", - "./test/stubs/", - "./dist" - ); - let data = await getRenderedData(tmpl); - t.is(data.key1, "value1"); - t.is(data.key2, true); - t.is(data.key3, false); - t.is(data.key4, 324); -}); - -test("eleventyComputed relies on global data", async t => { - let dataObj = new TemplateData("./test/stubs/"); - let tmpl = getNewTemplate( - "./test/stubs/eleventyComputed/use-global-data.njk", - "./test/stubs/", - "./dist", - dataObj - ); - - let fetchedData = await tmpl.getData(); - let templates = await tmpl.getTemplates(fetchedData); - let data = templates[0].data; - t.is(data.image, "datavalue1"); -}); - -test("eleventyComputed intermixes with global data", async t => { - let dataObj = new TemplateData("./test/stubs-computed-global/"); - - let config = cloneDeep(dataObj.config); - config.dataDeepMerge = true; - dataObj._setConfig(config); - - let tmpl = getNewTemplate( - "./test/stubs-computed-global/intermix.njk", - "./test/stubs-computed-global/", - "./dist", - dataObj - ); - tmpl.config = config; - - let fetchedData = await tmpl.getData(); - t.truthy(fetchedData.eleventyComputed.image); - t.truthy(fetchedData.eleventyComputed.image2); - t.truthy(fetchedData.eleventyComputed.image3); - t.truthy(fetchedData.eleventyComputed.eleventyNavigation.key); - - let templates = await tmpl.getTemplates(fetchedData); - let data = templates[0].data; - t.is(data.image, "first"); - t.is(data.image2, "second"); - t.is(data.image3, "third-global"); - t.is(data.eleventyNavigation.key, "nested-first-global"); -}); diff --git a/test/_getNewTemplate.js b/test/_getNewTemplate.js new file mode 100644 index 000000000..327602624 --- /dev/null +++ b/test/_getNewTemplate.js @@ -0,0 +1,28 @@ +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const Template = require("../src/Template"); + +module.exports = function getNewTemplate( + path, + inputDir, + outputDir, + templateData = null, + map = null +) { + if (!map) { + map = new EleventyExtensionMap([ + "liquid", + "ejs", + "md", + "hbs", + "mustache", + "haml", + "pug", + "njk", + "html", + "jstl", + "11ty.js" + ]); + } + let tmpl = new Template(path, inputDir, outputDir, templateData, map); + return tmpl; +}; diff --git a/test/stubs-computed-collections/collections.njk b/test/stubs-computed-collections/collections.njk new file mode 100644 index 000000000..2eeb9b439 --- /dev/null +++ b/test/stubs-computed-collections/collections.njk @@ -0,0 +1,11 @@ +---js +{ + eleventyComputed: { + test: "hello", + dogCollection: data => { + return data.collections.dog; + } + } +} +--- +Issue #1114 \ No newline at end of file diff --git a/test/stubs-computed-collections/dog.njk b/test/stubs-computed-collections/dog.njk new file mode 100644 index 000000000..a51aa14a0 --- /dev/null +++ b/test/stubs-computed-collections/dog.njk @@ -0,0 +1,4 @@ +--- +tags: dog +--- +Hi from dog \ No newline at end of file From 2a5b2cd90cbd97485092c7f3c80d928f8f9af14e Mon Sep 17 00:00:00 2001 From: "Stuart P. Bentley" Date: Wed, 29 Apr 2020 10:40:10 +0000 Subject: [PATCH 200/746] Don't ignore output paths that contain all input (fixes #1129) --- src/EleventyFiles.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 3e6f341fb..e568e6a6e 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -285,7 +285,10 @@ class EleventyFiles { ); } - files = files.concat(TemplateGlob.map("!" + this.outputDir + "/**")); + // ignore output dir unless that would occlude all input + if (!TemplatePath.startsWithSubPath(this.inputDir, this.outputDir)) { + files = files.concat(TemplateGlob.map("!" + this.outputDir + "/**")); + } return files; } From b39203040702d49752064ca7384ab39abb93cef6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 29 Apr 2020 07:57:32 -0500 Subject: [PATCH 201/746] Adds test for template engine singletons --- test/TemplateMapTest-ComputedData.js | 2 +- test/TemplateTest-ComputedData.js | 2 +- test/TemplateTest.js | 23 ++++++++++++++++++- ...Template.js => _getNewTemplateForTests.js} | 0 test/stubs/engine-singletons/first.njk | 0 test/stubs/engine-singletons/second.njk | 0 6 files changed, 24 insertions(+), 3 deletions(-) rename test/{_getNewTemplate.js => _getNewTemplateForTests.js} (100%) create mode 100644 test/stubs/engine-singletons/first.njk create mode 100644 test/stubs/engine-singletons/second.njk diff --git a/test/TemplateMapTest-ComputedData.js b/test/TemplateMapTest-ComputedData.js index e5b922540..13537d5a1 100644 --- a/test/TemplateMapTest-ComputedData.js +++ b/test/TemplateMapTest-ComputedData.js @@ -2,7 +2,7 @@ import test from "ava"; import Template from "../src/Template"; import TemplateData from "../src/TemplateData"; import TemplateMap from "../src/TemplateMap"; -import getNewTemplate from "./_getNewTemplate"; +import getNewTemplate from "./_getNewTemplateForTests"; test("Computed data can see tag generated collections", async t => { let tm = new TemplateMap(); diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index 7b194fb2d..acf42c39e 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -2,7 +2,7 @@ import test from "ava"; import Template from "../src/Template"; import TemplateData from "../src/TemplateData"; import { cloneDeep } from "lodash"; -import getNewTemplate from "./_getNewTemplate"; +import getNewTemplate from "./_getNewTemplateForTests"; async function getRenderedData(tmpl, pageNumber = 0) { let data = await tmpl.getData(); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 5dcb09207..548c21b19 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -3,6 +3,7 @@ import fs from "fs-extra"; import pretty from "pretty"; import Template from "../src/Template"; import TemplateData from "../src/TemplateData"; +import EleventyExtensionMap from "../src/EleventyExtensionMap"; import EleventyErrorUtil from "../src/EleventyErrorUtil"; import TemplateContentPrematureUseError from "../src/Errors/TemplateContentPrematureUseError"; import normalizeNewLines from "./Util/normalizeNewLines"; @@ -10,7 +11,7 @@ import normalizeNewLines from "./Util/normalizeNewLines"; import templateConfig from "../src/Config"; const config = templateConfig.getConfig(); -import getNewTemplate from "./_getNewTemplate"; +import getNewTemplate from "./_getNewTemplateForTests"; async function getRenderedData(tmpl, pageNumber = 0) { let data = await tmpl.getData(); @@ -2040,3 +2041,23 @@ test("Get Layout Chain", async t => { "./test/stubs-incremental/layout-chain/_includes/parent.njk" ]); }); + +test("Engine Singletons", async t => { + let map = new EleventyExtensionMap(["njk"]); + let tmpl1 = getNewTemplate( + "./test/stubs/engine-singletons/first.njk", + "./test/stubs/engine-singletons/", + "./dist", + null, + map + ); + let tmpl2 = getNewTemplate( + "./test/stubs/engine-singletons/second.njk", + "./test/stubs/engine-singletons/", + "./dist", + null, + map + ); + + t.deepEqual(tmpl1.engine, tmpl2.engine); +}); diff --git a/test/_getNewTemplate.js b/test/_getNewTemplateForTests.js similarity index 100% rename from test/_getNewTemplate.js rename to test/_getNewTemplateForTests.js diff --git a/test/stubs/engine-singletons/first.njk b/test/stubs/engine-singletons/first.njk new file mode 100644 index 000000000..e69de29bb diff --git a/test/stubs/engine-singletons/second.njk b/test/stubs/engine-singletons/second.njk new file mode 100644 index 000000000..e69de29bb From 3b0fdf25d6d49fa69a801ae0c8e7a0ace3295267 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 29 Apr 2020 08:17:36 -0500 Subject: [PATCH 202/746] A little performance optimization for computed data --- src/ComputedData.js | 15 +++++++-------- src/ComputedDataProxy.js | 1 + src/ComputedDataQueue.js | 3 +++ src/ComputedDataTemplateString.js | 5 +++++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/ComputedData.js b/src/ComputedData.js index d8593db49..e09b4221a 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -29,6 +29,11 @@ class ComputedData { } async resolveVarOrder(data) { + let proxyByTemplateString = new ComputedDataTemplateString( + this.computedKeys + ); + let proxyByProxy = new ComputedDataProxy(this.computedKeys); + for (let key of this.computedKeys) { let computed = lodashGet(this.computed, key); @@ -38,16 +43,10 @@ class ComputedData { } else { this.queue.uses(key, this.declaredDependencies[key]); - let proxy; let isTemplateString = !!this.templateStringKeyLookup[key]; - // TODO move this out of the loop?? - if (isTemplateString) { - proxy = new ComputedDataTemplateString(this.computedKeys); - } else { - proxy = new ComputedDataProxy(this.computedKeys); - } - + let proxy = isTemplateString ? proxyByTemplateString : proxyByProxy; let varsUsed = await proxy.findVarsUsed(computed, data); + debug("%o accesses %o variables", key, varsUsed); let filteredVarsUsed = varsUsed.filter(varUsed => { return ( diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index d086afe4f..5825c4bcd 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -2,6 +2,7 @@ const lodashSet = require("lodash/set"); const lodashGet = require("lodash/get"); const lodashIsPlainObject = require("lodash/isPlainObject"); +/* Calculates computed data using Proxies */ class ComputedDataProxy { constructor(computedKeys) { if (Array.isArray(computedKeys)) { diff --git a/src/ComputedDataQueue.js b/src/ComputedDataQueue.js index 51abb8ee3..bf1e766a6 100644 --- a/src/ComputedDataQueue.js +++ b/src/ComputedDataQueue.js @@ -1,5 +1,8 @@ const DependencyGraph = require("dependency-graph").DepGraph; +/* Keeps track of the dependency graph between computed data variables + * Removes keys from the graph when they are computed. + */ class ComputedDataQueue { constructor() { this.graph = new DependencyGraph(); diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js index bd9d2c8df..90f7cf328 100644 --- a/src/ComputedDataTemplateString.js +++ b/src/ComputedDataTemplateString.js @@ -1,6 +1,11 @@ const lodashSet = require("lodash/set"); const debug = require("debug")("Eleventy:ComputedDataTemplateString"); +/* Calculates computed data in Template Strings. + * Ideally we would use the Proxy approach but it doesn’t work + * in some template languages that visit all available data even if + * it isn’t used in the template (Nunjucks) + */ class ComputedDataTemplateString { constructor(computedKeys) { if (Array.isArray(computedKeys)) { From 08b427351d519a1b20bcd57517776e6ac68e5615 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 29 Apr 2020 12:29:17 -0500 Subject: [PATCH 203/746] v0.11.0-beta.4 --- docs/meta-release.md | 2 ++ package.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/meta-release.md b/docs/meta-release.md index 9eb568102..837224c6f 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -22,6 +22,8 @@ 1. Tag new version 1. `npm publish --access=public` +1. Bonus for 0.x branch, make sure it still works in node 8 (see `Temp/eleventy-node-8` sample project) + ## If branch docs do not exist 1. Make sure `localDev: false` in `config.js` diff --git a/package.json b/package.json index 8bc3b3974..2b5a3118a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.11.0-beta.3", + "version": "0.11.0-beta.4", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -132,4 +132,4 @@ "pre-push": "npm run test" } } -} +} \ No newline at end of file From 85def1448283c0ba6e5e66e9e1fd43010b7b4895 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 29 Apr 2020 13:52:35 -0500 Subject: [PATCH 204/746] Dependency updates --- package.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 2b5a3118a..d3d31ac01 100755 --- a/package.json +++ b/package.json @@ -76,16 +76,16 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.1", - "ava": "^3.5.1", - "husky": "^4.2.3", + "ava": "^3.8.1", + "husky": "^4.2.5", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", - "jsdoc": "3.6.3", - "lint-staged": "^10.0.9", + "jsdoc": "3.6.4", + "lint-staged": "^10.2.0", "markdown-it-emoji": "^1.4.0", - "node-sass": "^4.13.1", - "nyc": "^15.0.0", - "prettier": "^1.19.1", + "node-sass": "^4.14.0", + "nyc": "^15.0.1", + "prettier": "^2.0.5", "rimraf": "^3.0.2", "toml": "^3.0.0", "viperhtml": "^2.17.1", @@ -96,7 +96,7 @@ "@11ty/dependency-tree": "^1.0.0", "browser-sync": "^2.26.7", "chalk": "^3.0.0", - "chokidar": "^3.3.1", + "chokidar": "^3.4.0", "debug": "^4.1.1", "dependency-graph": "^0.9.0", "ejs": "^2.7.4", @@ -104,12 +104,12 @@ "fs-extra": "^8.1.0", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", - "handlebars": "^4.7.3", + "handlebars": "^4.7.6", "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", "lodash": "^4.17.15", - "luxon": "^1.22.2", - "markdown-it": "^8.4.2", + "luxon": "^1.23.0", + "markdown-it": "^10.0.0", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^4.0.0", @@ -121,7 +121,7 @@ "pretty": "^2.0.0", "pug": "^2.0.4", "recursive-copy": "^2.0.10", - "semver": "^7.1.3", + "semver": "^7.3.2", "slugify": "^1.4.0", "time-require": "^0.1.2", "valid-url": "^1.0.9" @@ -132,4 +132,4 @@ "pre-push": "npm run test" } } -} \ No newline at end of file +} From 68f75053071aaefc3efb8c2ebdbdae8361117b48 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 29 Apr 2020 13:53:59 -0500 Subject: [PATCH 205/746] v0.11.0-beta.4 coverage --- docs-src/_data/coverage.json | 47 +++++++++++++++++++----------------- docs/coverage.md | 43 ++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 42 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 97ae63326..9e2d083db 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,54 +1,57 @@ -{"total": {"lines":{"total":3241,"covered":2856,"skipped":0,"pct":88.12},"statements":{"total":3263,"covered":2877,"skipped":0,"pct":88.17},"functions":{"total":778,"covered":673,"skipped":0,"pct":86.5},"branches":{"total":1405,"covered":1135,"skipped":0,"pct":80.78}} -,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":15,"covered":13,"skipped":0,"pct":86.67},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":15,"covered":13,"skipped":0,"pct":86.67},"branches":{"total":6,"covered":4,"skipped":0,"pct":66.67}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":38,"covered":23,"skipped":0,"pct":60.53},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":38,"covered":23,"skipped":0,"pct":60.53},"branches":{"total":12,"covered":3,"skipped":0,"pct":25}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":17,"covered":13,"skipped":0,"pct":76.47},"functions":{"total":7,"covered":5,"skipped":0,"pct":71.43},"statements":{"total":17,"covered":13,"skipped":0,"pct":76.47},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} -,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":52,"covered":51,"skipped":0,"pct":98.08},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":51,"skipped":0,"pct":98.08},"branches":{"total":18,"covered":16,"skipped":0,"pct":88.89}} +{"total": {"lines":{"total":3428,"covered":3039,"skipped":0,"pct":88.65},"statements":{"total":3450,"covered":3060,"skipped":0,"pct":88.7},"functions":{"total":811,"covered":708,"skipped":0,"pct":87.3},"branches":{"total":1482,"covered":1204,"skipped":0,"pct":81.24}} +,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":34,"skipped":0,"pct":73.91},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":46,"covered":34,"skipped":0,"pct":73.91},"branches":{"total":21,"covered":11,"skipped":0,"pct":52.38}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.78},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.78},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":44,"covered":44,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":44,"covered":44,"skipped":0,"pct":100},"branches":{"total":17,"covered":17,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":38,"covered":38,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":38,"covered":38,"skipped":0,"pct":100},"branches":{"total":24,"covered":24,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.73}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":24,"covered":24,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":209,"covered":115,"skipped":0,"pct":55.02},"functions":{"total":39,"covered":19,"skipped":0,"pct":48.72},"statements":{"total":210,"covered":115,"skipped":0,"pct":54.76},"branches":{"total":66,"covered":27,"skipped":0,"pct":40.91}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":222,"covered":121,"skipped":0,"pct":54.5},"functions":{"total":40,"covered":20,"skipped":0,"pct":50},"statements":{"total":223,"covered":121,"skipped":0,"pct":54.26},"branches":{"total":74,"covered":32,"skipped":0,"pct":43.24}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":35,"skipped":0,"pct":89.74},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":39,"covered":35,"skipped":0,"pct":89.74},"branches":{"total":43,"covered":29,"skipped":0,"pct":67.44}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":19,"covered":19,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":59,"covered":59,"skipped":0,"pct":100},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":59,"covered":59,"skipped":0,"pct":100},"branches":{"total":29,"covered":29,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":157,"covered":147,"skipped":0,"pct":93.63},"functions":{"total":40,"covered":36,"skipped":0,"pct":90},"statements":{"total":157,"covered":147,"skipped":0,"pct":93.63},"branches":{"total":61,"covered":51,"skipped":0,"pct":83.61}} +,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":64,"covered":64,"skipped":0,"pct":100},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":64,"covered":64,"skipped":0,"pct":100},"branches":{"total":31,"covered":31,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":165,"covered":155,"skipped":0,"pct":93.94},"functions":{"total":40,"covered":36,"skipped":0,"pct":90},"statements":{"total":165,"covered":155,"skipped":0,"pct":93.94},"branches":{"total":61,"covered":51,"skipped":0,"pct":83.61}} ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":59,"covered":22,"skipped":0,"pct":37.29},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":59,"covered":22,"skipped":0,"pct":37.29},"branches":{"total":36,"covered":10,"skipped":0,"pct":27.78}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":33,"covered":33,"skipped":0,"pct":100},"functions":{"total":16,"covered":16,"skipped":0,"pct":100},"statements":{"total":35,"covered":35,"skipped":0,"pct":100},"branches":{"total":17,"covered":15,"skipped":0,"pct":88.24}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":298,"covered":283,"skipped":0,"pct":94.97},"functions":{"total":53,"covered":52,"skipped":0,"pct":98.11},"statements":{"total":300,"covered":285,"skipped":0,"pct":95},"branches":{"total":111,"covered":98,"skipped":0,"pct":88.29}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":307,"covered":292,"skipped":0,"pct":95.11},"functions":{"total":55,"covered":54,"skipped":0,"pct":98.18},"statements":{"total":309,"covered":294,"skipped":0,"pct":95.15},"branches":{"total":111,"covered":98,"skipped":0,"pct":88.29}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":31,"covered":28,"skipped":0,"pct":90.32},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":34,"covered":31,"skipped":0,"pct":91.18},"branches":{"total":10,"covered":7,"skipped":0,"pct":70}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":62,"covered":55,"skipped":0,"pct":88.71},"functions":{"total":10,"covered":6,"skipped":0,"pct":60},"statements":{"total":62,"covered":55,"skipped":0,"pct":88.71},"branches":{"total":26,"covered":24,"skipped":0,"pct":92.31}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":87,"covered":83,"skipped":0,"pct":95.4},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":87,"covered":83,"skipped":0,"pct":95.4},"branches":{"total":36,"covered":33,"skipped":0,"pct":91.67}} -,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":214,"covered":205,"skipped":0,"pct":95.79},"functions":{"total":40,"covered":39,"skipped":0,"pct":97.5},"statements":{"total":217,"covered":208,"skipped":0,"pct":95.85},"branches":{"total":78,"covered":68,"skipped":0,"pct":87.18}} -,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":98,"covered":94,"skipped":0,"pct":95.92},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":98,"covered":94,"skipped":0,"pct":95.92},"branches":{"total":36,"covered":33,"skipped":0,"pct":91.67}} +,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":221,"covered":212,"skipped":0,"pct":95.93},"functions":{"total":40,"covered":39,"skipped":0,"pct":97.5},"statements":{"total":224,"covered":215,"skipped":0,"pct":95.98},"branches":{"total":78,"covered":68,"skipped":0,"pct":87.18}} +,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":10,"covered":10,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateGlob.js": {"lines":{"total":15,"covered":14,"skipped":0,"pct":93.33},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} -,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":73,"covered":73,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":74,"covered":74,"skipped":0,"pct":100},"branches":{"total":16,"covered":16,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":47,"covered":45,"skipped":0,"pct":95.74},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":47,"covered":45,"skipped":0,"pct":95.74},"branches":{"total":18,"covered":16,"skipped":0,"pct":88.89}} -,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":237,"covered":232,"skipped":0,"pct":97.89},"functions":{"total":32,"covered":31,"skipped":0,"pct":96.88},"statements":{"total":237,"covered":232,"skipped":0,"pct":97.89},"branches":{"total":125,"covered":113,"skipped":0,"pct":90.4}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":35,"covered":33,"skipped":0,"pct":94.29},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":35,"covered":33,"skipped":0,"pct":94.29},"branches":{"total":12,"covered":10,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":82,"covered":71,"skipped":0,"pct":86.59},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":82,"covered":71,"skipped":0,"pct":86.59},"branches":{"total":32,"covered":23,"skipped":0,"pct":71.88}} +,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":76,"covered":75,"skipped":0,"pct":98.68},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":18,"covered":17,"skipped":0,"pct":94.44}} +,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":49,"covered":46,"skipped":0,"pct":93.88},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":49,"covered":46,"skipped":0,"pct":93.88},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} +,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":243,"covered":238,"skipped":0,"pct":97.94},"functions":{"total":33,"covered":32,"skipped":0,"pct":96.97},"statements":{"total":243,"covered":238,"skipped":0,"pct":97.94},"branches":{"total":125,"covered":113,"skipped":0,"pct":90.4}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":45,"covered":43,"skipped":0,"pct":95.56},"functions":{"total":12,"covered":11,"skipped":0,"pct":91.67},"statements":{"total":45,"covered":43,"skipped":0,"pct":95.56},"branches":{"total":12,"covered":10,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":82,"covered":72,"skipped":0,"pct":87.8},"functions":{"total":22,"covered":20,"skipped":0,"pct":90.91},"statements":{"total":82,"covered":72,"skipped":0,"pct":87.8},"branches":{"total":34,"covered":25,"skipped":0,"pct":73.53}} ,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":93,"covered":93,"skipped":0,"pct":100},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.67},"statements":{"total":94,"covered":94,"skipped":0,"pct":100},"branches":{"total":48,"covered":48,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":32,"covered":32,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":32,"covered":32,"skipped":0,"pct":100},"branches":{"total":27,"covered":26,"skipped":0,"pct":96.3}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalinkNoWrite.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":87,"covered":83,"skipped":0,"pct":95.4},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":87,"covered":83,"skipped":0,"pct":95.4},"branches":{"total":48,"covered":45,"skipped":0,"pct":93.75}} -,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":113,"covered":90,"skipped":0,"pct":79.65},"functions":{"total":32,"covered":24,"skipped":0,"pct":75},"statements":{"total":113,"covered":90,"skipped":0,"pct":79.65},"branches":{"total":28,"covered":14,"skipped":0,"pct":50}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":209,"covered":122,"skipped":0,"pct":58.37},"functions":{"total":57,"covered":26,"skipped":0,"pct":45.61},"statements":{"total":210,"covered":123,"skipped":0,"pct":58.57},"branches":{"total":88,"covered":41,"skipped":0,"pct":46.59}} +,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":80,"covered":79,"skipped":0,"pct":98.75},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":80,"covered":79,"skipped":0,"pct":98.75},"branches":{"total":46,"covered":45,"skipped":0,"pct":97.83}} +,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":112,"covered":88,"skipped":0,"pct":78.57},"functions":{"total":32,"covered":23,"skipped":0,"pct":71.88},"statements":{"total":112,"covered":88,"skipped":0,"pct":78.57},"branches":{"total":28,"covered":14,"skipped":0,"pct":50}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":215,"covered":128,"skipped":0,"pct":59.53},"functions":{"total":57,"covered":26,"skipped":0,"pct":45.61},"statements":{"total":216,"covered":129,"skipped":0,"pct":59.72},"branches":{"total":88,"covered":41,"skipped":0,"pct":46.59}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":14,"covered":11,"skipped":0,"pct":78.57},"functions":{"total":4,"covered":1,"skipped":0,"pct":25},"statements":{"total":14,"covered":11,"skipped":0,"pct":78.57},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":19,"covered":12,"skipped":0,"pct":63.16},"functions":{"total":5,"covered":3,"skipped":0,"pct":60},"statements":{"total":19,"covered":12,"skipped":0,"pct":63.16},"branches":{"total":12,"covered":6,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.74},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.74},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":57,"covered":56,"skipped":0,"pct":98.25},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":58,"covered":57,"skipped":0,"pct":98.28},"branches":{"total":46,"covered":41,"skipped":0,"pct":89.13}} +,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":61,"covered":59,"skipped":0,"pct":96.72},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":62,"covered":60,"skipped":0,"pct":96.77},"branches":{"total":50,"covered":43,"skipped":0,"pct":86}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScriptTemplateLiteral.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":77,"covered":74,"skipped":0,"pct":96.1},"functions":{"total":27,"covered":26,"skipped":0,"pct":96.3},"statements":{"total":77,"covered":74,"skipped":0,"pct":96.1},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.63},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.63},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":87,"covered":78,"skipped":0,"pct":89.66},"functions":{"total":24,"covered":23,"skipped":0,"pct":95.83},"statements":{"total":87,"covered":78,"skipped":0,"pct":89.66},"branches":{"total":33,"covered":31,"skipped":0,"pct":93.94}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":17,"covered":17,"skipped":0,"pct":100},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":49,"covered":49,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":51,"covered":51,"skipped":0,"pct":100},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":58,"covered":58,"skipped":0,"pct":100},"functions":{"total":21,"covered":21,"skipped":0,"pct":100},"statements":{"total":60,"covered":60,"skipped":0,"pct":100},"branches":{"total":10,"covered":10,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/GetCollectionItem.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.86}} diff --git a/docs/coverage.md b/docs/coverage.md index e3cab2522..46d88a6f5 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,51 +1,54 @@ -# Code Coverage for Eleventy v0.11.0-beta.3 +# Code Coverage for Eleventy v0.11.0-beta.4 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 88.12% | 88.17% | 86.5% | 80.78% | -| `src/Benchmark.js` | 86.67% | 86.67% | 71.43% | 66.67% | -| `src/BenchmarkGroup.js` | 60.53% | 60.53% | 71.43% | 25% | -| `src/BenchmarkManager.js` | 76.47% | 76.47% | 71.43% | 75% | -| `src/ComputedData.js` | 98.08% | 98.08% | 85.71% | 88.89% | +| `total` | 88.65% | 88.7% | 87.3% | 81.24% | +| `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | +| `src/BenchmarkGroup.js` | 73.91% | 73.91% | 66.67% | 52.38% | +| `src/BenchmarkManager.js` | 77.78% | 77.78% | 75% | 75% | +| `src/ComputedData.js` | 100% | 100% | 100% | 100% | +| `src/ComputedDataProxy.js` | 100% | 100% | 100% | 100% | +| `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.73% | +| `src/ComputedDataTemplateString.js` | 100% | 100% | 100% | 83.33% | | `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 55.02% | 54.76% | 48.72% | 40.91% | +| `src/Eleventy.js` | 54.5% | 54.26% | 50% | 43.24% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | | `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | | `src/EleventyErrorHandler.js` | 89.74% | 89.74% | 100% | 67.44% | | `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | | `src/EleventyExtensionMap.js` | 100% | 100% | 100% | 100% | -| `src/EleventyFiles.js` | 93.63% | 93.63% | 90% | 83.61% | +| `src/EleventyFiles.js` | 93.94% | 93.94% | 90% | 83.61% | | `src/EleventyServe.js` | 37.29% | 37.29% | 56.25% | 27.78% | | `src/EleventyWatch.js` | 100% | 100% | 100% | 88.24% | | `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 93.33% | -| `src/Template.js` | 94.97% | 95% | 98.11% | 88.29% | +| `src/Template.js` | 95.11% | 95.15% | 98.18% | 88.29% | | `src/TemplateCache.js` | 100% | 100% | 100% | 100% | | `src/TemplateCollection.js` | 90.32% | 91.18% | 93.33% | 70% | | `src/TemplateConfig.js` | 88.71% | 88.71% | 60% | 92.31% | -| `src/TemplateContent.js` | 95.4% | 95.4% | 100% | 91.67% | -| `src/TemplateData.js` | 95.79% | 95.85% | 97.5% | 87.18% | +| `src/TemplateContent.js` | 95.92% | 95.92% | 100% | 91.67% | +| `src/TemplateData.js` | 95.93% | 95.98% | 97.5% | 87.18% | | `src/TemplateEngineManager.js` | 100% | 100% | 100% | 100% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | | `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | -| `src/TemplateLayout.js` | 100% | 100% | 100% | 100% | -| `src/TemplateLayoutPathResolver.js` | 95.74% | 95.74% | 100% | 88.89% | -| `src/TemplateMap.js` | 97.89% | 97.89% | 96.88% | 90.4% | -| `src/TemplatePassthrough.js` | 94.29% | 94.29% | 88.89% | 83.33% | -| `src/TemplatePassthroughManager.js` | 86.59% | 86.59% | 91.3% | 71.88% | +| `src/TemplateLayout.js` | 98.68% | 98.7% | 100% | 94.44% | +| `src/TemplateLayoutPathResolver.js` | 93.88% | 93.88% | 100% | 85% | +| `src/TemplateMap.js` | 97.94% | 97.94% | 96.97% | 90.4% | +| `src/TemplatePassthrough.js` | 95.56% | 95.56% | 91.67% | 83.33% | +| `src/TemplatePassthroughManager.js` | 87.8% | 87.8% | 90.91% | 73.53% | | `src/TemplatePath.js` | 100% | 100% | 96.67% | 100% | | `src/TemplatePermalink.js` | 100% | 100% | 100% | 96.3% | | `src/TemplatePermalinkNoWrite.js` | 100% | 100% | 100% | 100% | -| `src/TemplateRender.js` | 95.4% | 95.4% | 95.65% | 93.75% | -| `src/TemplateWriter.js` | 79.65% | 79.65% | 75% | 50% | -| `src/UserConfig.js` | 58.37% | 58.57% | 45.61% | 46.59% | +| `src/TemplateRender.js` | 98.75% | 98.75% | 100% | 97.83% | +| `src/TemplateWriter.js` | 78.57% | 78.57% | 71.88% | 50% | +| `src/UserConfig.js` | 59.53% | 59.72% | 45.61% | 46.59% | | `src/defaultConfig.js` | 78.57% | 78.57% | 25% | 100% | | `src/Engines/Custom.js` | 63.16% | 63.16% | 60% | 50% | | `src/Engines/Ejs.js` | 94.74% | 94.74% | 85.71% | 88.89% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | -| `src/Engines/JavaScript.js` | 98.25% | 98.28% | 100% | 89.13% | +| `src/Engines/JavaScript.js` | 96.72% | 96.77% | 100% | 86% | | `src/Engines/JavaScriptTemplateLiteral.js` | 94.44% | 94.44% | 100% | 100% | | `src/Engines/Liquid.js` | 96.1% | 96.1% | 96.3% | 85% | | `src/Engines/Markdown.js` | 90.63% | 90.63% | 88.89% | 81.25% | From a1ce30a478123765ba7211955b5c2a58c624cfd9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 30 Apr 2020 12:51:00 -0500 Subject: [PATCH 206/746] Test was already passing for #1138 --- src/ComputedData.js | 7 +-- src/Template.js | 23 ++++---- test/TemplateMapTest-ComputedData.js | 55 +++++++++++++++++++- test/stubs-computed-pagination/child.11ty.js | 7 +++ test/stubs-computed-pagination/paginated.njk | 14 +++++ 5 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 test/stubs-computed-pagination/child.11ty.js create mode 100644 test/stubs-computed-pagination/paginated.njk diff --git a/src/ComputedData.js b/src/ComputedData.js index e09b4221a..b1a1aa186 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -48,7 +48,7 @@ class ComputedData { let varsUsed = await proxy.findVarsUsed(computed, data); debug("%o accesses %o variables", key, varsUsed); - let filteredVarsUsed = varsUsed.filter(varUsed => { + let filteredVarsUsed = varsUsed.filter((varUsed) => { return ( (varUsed !== key && this.computedKeys.has(varUsed)) || varUsed.startsWith("collections.") @@ -64,9 +64,9 @@ class ComputedData { for (let key of order) { let computed = lodashGet(this.computed, key); - if (typeof computed === "function") { - lodashSet(data, key, await computed(data)); + let ret = await computed(data); + lodashSet(data, key, ret); } else if (computed !== undefined) { lodashSet(data, key, computed); } @@ -81,6 +81,7 @@ class ComputedData { if (orderFilter && typeof orderFilter === "function") { order = order.filter(orderFilter.bind(this.queue)); } + await this._setupDataEntry(data, order); this.queue.markComputed(order); } diff --git a/src/Template.js b/src/Template.js index 023d093ce..ace5361cf 100644 --- a/src/Template.js +++ b/src/Template.js @@ -354,7 +354,7 @@ class Template extends TemplateContent { } async runLinters(str, inputPath, outputPath) { - this.linters.forEach(function(linter) { + this.linters.forEach(function (linter) { // these can be asynchronous but no guarantee of order when they run linter.call(this, str, inputPath, outputPath); }); @@ -393,7 +393,7 @@ class Template extends TemplateContent { } else if (typeof obj === "string") { computedData.addTemplateString( parentKey, - async innerData => { + async (innerData) => { return await super.render(obj, innerData, true); }, declaredDependencies @@ -410,12 +410,12 @@ class Template extends TemplateContent { // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly this.computedData.addTemplateString( "page.url", - async data => await this.getOutputHref(data), + async (data) => await this.getOutputHref(data), ["permalink"] ); this.computedData.addTemplateString( "page.outputPath", - async data => await this.getOutputPath(data), + async (data) => await this.getOutputPath(data), ["permalink"] ); @@ -427,12 +427,11 @@ class Template extends TemplateContent { } // limited run of computed data, do most of it later when collections are available. - // await this.computedData.setupData(data); - await this.computedData.setupData(data, function(entry) { + await this.computedData.setupData(data, function (entry) { return !this.isDependsOnStartsWith(entry, "collections."); }); - // deprecated, use eleventyComputed instead. + // Deprecated, use eleventyComputed instead. if ("renderData" in data) { data.renderData = await this.mapDataAsRenderedTemplates( data.renderData, @@ -472,7 +471,7 @@ class Template extends TemplateContent { ); } return this._templateContent; - } + }, }); } else { // needs collections for pagination items @@ -511,7 +510,7 @@ class Template extends TemplateContent { ); } return this._templateContent; - } + }, }); } } @@ -551,13 +550,13 @@ class Template extends TemplateContent { let lang = { start: "Writing", - finished: "written." + finished: "written.", }; if (!shouldWriteFile) { lang = { start: "Skipping", - finished: "" // not used, promise doesn’t resolve + finished: "", // not used, promise doesn’t resolve }; } @@ -733,7 +732,7 @@ class Template extends TemplateContent { entries.push({ template: this, inputPath: this.inputPath, - data: data + data: data, }); return entries; } diff --git a/test/TemplateMapTest-ComputedData.js b/test/TemplateMapTest-ComputedData.js index 13537d5a1..4fafaf914 100644 --- a/test/TemplateMapTest-ComputedData.js +++ b/test/TemplateMapTest-ComputedData.js @@ -4,7 +4,7 @@ import TemplateData from "../src/TemplateData"; import TemplateMap from "../src/TemplateMap"; import getNewTemplate from "./_getNewTemplateForTests"; -test("Computed data can see tag generated collections", async t => { +test("Computed data can see tag generated collections", async (t) => { let tm = new TemplateMap(); let dataObj = new TemplateData("./test/stubs-computed-collections/"); @@ -44,3 +44,56 @@ test("Computed data can see tag generated collections", async t => { // THEY ARE THE SAME t.is(map[0].data.dogCollection, map[0].data.collections.dog); }); + +test("Computed data can see paginated data, Issue #1138", async (t) => { + let tm = new TemplateMap(); + + let dataObj = new TemplateData("./test/stubs-computed-pagination/"); + let tmpl = getNewTemplate( + "./test/stubs-computed-pagination/paginated.njk", + "./test/stubs-computed-pagination/", + "./dist", + dataObj + ); + + await tm.add(tmpl); + + let dataObj2 = new TemplateData("./test/stubs-computed-pagination/"); + let tmpl2 = getNewTemplate( + "./test/stubs-computed-pagination/child.11ty.js", + "./test/stubs-computed-pagination/", + "./dist", + dataObj2 + ); + + await tm.add(tmpl2); + + await tm.cache(); + + let map = tm.getMap(); + + t.is(map.length, 2); + + // paginated template tests + t.is(map[0].inputPath.endsWith("paginated.njk"), true); + t.is(map[0]._pages.length, 2); + + t.is(map[0]._pages[0].data.venue, "first"); + t.is(map[0]._pages[0].data.title, "first"); + t.is(map[0]._pages[0].url, "/venues/first/"); + t.truthy(map[0]._pages[0].data.collections); + t.truthy(map[0]._pages[0].data.collections.venue); + t.is(map[0]._pages[0].data.collections.venue.length, 2); + + t.is(map[0]._pages[1].data.venue, "second"); + t.is(map[0]._pages[1].data.title, "second"); + t.is(map[0]._pages[1].url, "/venues/second/"); + t.truthy(map[0]._pages[1].data.collections.venue); + t.is(map[0]._pages[1].data.collections.venue.length, 2); + + // consumer of paginated template tests + t.is(map[1]._pages.length, 1); + // computed prop from venues + t.truthy(map[1]._pages[0].data.venues); + t.is(map[1]._pages[0].data.venues.length, 2); +}); diff --git a/test/stubs-computed-pagination/child.11ty.js b/test/stubs-computed-pagination/child.11ty.js new file mode 100644 index 000000000..84e87170d --- /dev/null +++ b/test/stubs-computed-pagination/child.11ty.js @@ -0,0 +1,7 @@ +module.exports.data = { + eleventyComputed: { + venues: (data) => { + return data.collections.venue; + }, + }, +}; diff --git a/test/stubs-computed-pagination/paginated.njk b/test/stubs-computed-pagination/paginated.njk new file mode 100644 index 000000000..fdf91ff4a --- /dev/null +++ b/test/stubs-computed-pagination/paginated.njk @@ -0,0 +1,14 @@ +--- +venues: + - first + - second +pagination: + data: venues + size: 1 + alias: venue + addAllPagesToCollections: true +permalink: "venues/{{ venue }}/" +tags: venue +eleventyComputed: + title: "{{ venue }}" +--- \ No newline at end of file From d6c324ce780fd0cef831907e57f205cce04a796c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 30 Apr 2020 15:07:48 -0500 Subject: [PATCH 207/746] Test for #1137 --- test/TemplateMapTest-ComputedData.js | 32 +++++++++++++++++++ .../dir/dir.11tydata.js | 7 ++++ test/stubs-computed-dirdata/dir/first.11ty.js | 7 ++++ .../stubs-computed-dirdata/dir/second.11ty.js | 7 ++++ 4 files changed, 53 insertions(+) create mode 100644 test/stubs-computed-dirdata/dir/dir.11tydata.js create mode 100644 test/stubs-computed-dirdata/dir/first.11ty.js create mode 100644 test/stubs-computed-dirdata/dir/second.11ty.js diff --git a/test/TemplateMapTest-ComputedData.js b/test/TemplateMapTest-ComputedData.js index 4fafaf914..131178760 100644 --- a/test/TemplateMapTest-ComputedData.js +++ b/test/TemplateMapTest-ComputedData.js @@ -97,3 +97,35 @@ test("Computed data can see paginated data, Issue #1138", async (t) => { t.truthy(map[1]._pages[0].data.venues); t.is(map[1]._pages[0].data.venues.length, 2); }); + +test("Computed data in directory data file consumes data file data, Issue #1137", async (t) => { + let tm = new TemplateMap(); + + let dataObj = new TemplateData("./test/stubs-computed-dirdata/"); + let tmpl = getNewTemplate( + "./test/stubs-computed-dirdata/dir/first.11ty.js", + "./test/stubs-computed-dirdata/", + "./dist", + dataObj + ); + + await tm.add(tmpl); + + let dataObj2 = new TemplateData("./test/stubs-computed-dirdata/"); + let tmpl2 = getNewTemplate( + "./test/stubs-computed-dirdata/dir/second.11ty.js", + "./test/stubs-computed-dirdata/", + "./dist", + dataObj2 + ); + + await tm.add(tmpl2); + + await tm.cache(); + + let map = tm.getMap(); + + t.is(map.length, 2); + t.is(map[0]._pages[0].data.webmentions, "first"); + t.is(map[1]._pages[0].data.webmentions, "second"); +}); diff --git a/test/stubs-computed-dirdata/dir/dir.11tydata.js b/test/stubs-computed-dirdata/dir/dir.11tydata.js new file mode 100644 index 000000000..083daf8be --- /dev/null +++ b/test/stubs-computed-dirdata/dir/dir.11tydata.js @@ -0,0 +1,7 @@ +module.exports = { + eleventyComputed: { + webmentions: (data) => { + return data.test; + }, + }, +}; diff --git a/test/stubs-computed-dirdata/dir/first.11ty.js b/test/stubs-computed-dirdata/dir/first.11ty.js new file mode 100644 index 000000000..7e12cbe33 --- /dev/null +++ b/test/stubs-computed-dirdata/dir/first.11ty.js @@ -0,0 +1,7 @@ +module.exports.data = { + test: "first", +}; + +module.exports.render = function (data) { + return "first"; +}; diff --git a/test/stubs-computed-dirdata/dir/second.11ty.js b/test/stubs-computed-dirdata/dir/second.11ty.js new file mode 100644 index 000000000..fd30d53fe --- /dev/null +++ b/test/stubs-computed-dirdata/dir/second.11ty.js @@ -0,0 +1,7 @@ +module.exports.data = { + test: "second", +}; + +module.exports.render = function (data) { + return "second"; +}; From e8f4004d749a0bf9f023e0a04c955e19acf52113 Mon Sep 17 00:00:00 2001 From: Sam Richard Date: Fri, 1 May 2020 14:13:06 -0500 Subject: [PATCH 208/746] Add before/after build events --- src/Eleventy.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Eleventy.js b/src/Eleventy.js index d7844e4ce..3cfe466fd 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -736,10 +736,13 @@ Arguments: EleventyErrorHandler.logger = this.logger; } + this.config.events.emit("beforeBuild"); + try { let promise = this.writer.write(); ret = await promise; + this.config.events.emit("afterBuild"); } catch (e) { EleventyErrorHandler.initialMessage( "Problem writing Eleventy templates", From 1d1c6fd40ce355ad12e0745c0e5f124fb914c689 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 6 May 2020 21:37:40 -0500 Subject: [PATCH 209/746] =?UTF-8?q?Better=20two=20stage=20computed=20data?= =?UTF-8?q?=20processing.=20Don=E2=80=99t=20reprocess=20variable=20order?= =?UTF-8?q?=20on=20second=20stage.=20Better=20handling=20of=20arrays.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ComputedData.js | 4 + src/ComputedDataProxy.js | 16 +++- src/ComputedDataQueue.js | 7 +- src/Template.js | 11 ++- test/ComputedDataProxyTest.js | 148 ++++++++++++++++++----------- test/ComputedDataQueueTest.js | 19 ++-- test/ComputedDataTest.js | 171 +++++++++++++++++----------------- 7 files changed, 217 insertions(+), 159 deletions(-) diff --git a/src/ComputedData.js b/src/ComputedData.js index b1a1aa186..61560e4ab 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -76,6 +76,10 @@ class ComputedData { async setupData(data, orderFilter) { await this.resolveVarOrder(data); + await this.processRemainingData(data, orderFilter); + } + + async processRemainingData(data, orderFilter) { // process all variables let order = this.queue.getOrder(); if (orderFilter && typeof orderFilter === "function") { diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index 5825c4bcd..75663b693 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -17,6 +17,7 @@ class ComputedDataProxy { } getProxyData(data, keyRef) { + // Set defaults for keys not already set on parent data let undefinedValue = "__11TY_UNDEFINED__"; if (this.computedKeys) { for (let key of this.computedKeys) { @@ -44,24 +45,31 @@ class ComputedDataProxy { keyRef.add(newKey); } return newData; - } + }, } ); } else if (Array.isArray(data)) { - return new Proxy([], { + return new Proxy(new Array(data.length), { get: (obj, key) => { - // why + if (Array.prototype.hasOwnProperty(key)) { + // remove `filter`, `constructor`, `map`, etc + keyRef.add(parentKey); + return obj[key]; + } + + // Hm, this needs to be better if (key === "then") { keyRef.add(parentKey); return; } + let newKey = `${parentKey}[${key}]`; let newData = this._getProxyData(data[key], keyRef, newKey); if (!this.isArrayOrPlainObject(newData)) { keyRef.add(newKey); } return newData; - } + }, }); } diff --git a/src/ComputedDataQueue.js b/src/ComputedDataQueue.js index bf1e766a6..c61517e0e 100644 --- a/src/ComputedDataQueue.js +++ b/src/ComputedDataQueue.js @@ -20,13 +20,14 @@ class ComputedDataQueue { return this.graph.dependantsOf(name); } - isDependsOnStartsWith(name, prefix) { + isUsesStartsWith(name, prefix) { if (name.startsWith(prefix)) { return true; } return ( - this.graph.dependantsOf(name).filter(entry => entry.startsWith(prefix)) - .length > 0 + this.graph.dependenciesOf(name).filter((entry) => { + return entry.startsWith(prefix); + }).length > 0 ); } diff --git a/src/Template.js b/src/Template.js index ace5361cf..a1a5e7b4d 100644 --- a/src/Template.js +++ b/src/Template.js @@ -411,12 +411,13 @@ class Template extends TemplateContent { this.computedData.addTemplateString( "page.url", async (data) => await this.getOutputHref(data), - ["permalink"] + data.permalink ? ["permalink"] : undefined ); + this.computedData.addTemplateString( "page.outputPath", async (data) => await this.getOutputPath(data), - ["permalink"] + data.permalink ? ["permalink"] : undefined ); if (this.config.keys.computed in data) { @@ -426,9 +427,9 @@ class Template extends TemplateContent { ); } - // limited run of computed data, do most of it later when collections are available. + // limited run of computed data—save the stuff that relies on collections for later. await this.computedData.setupData(data, function (entry) { - return !this.isDependsOnStartsWith(entry, "collections."); + return !this.isUsesStartsWith(entry, "collections."); }); // Deprecated, use eleventyComputed instead. @@ -441,7 +442,7 @@ class Template extends TemplateContent { } async resolveRemainingComputedData(data) { - await this.computedData.setupData(data); + await this.computedData.processRemainingData(data); } async getTemplates(data) { diff --git a/test/ComputedDataProxyTest.js b/test/ComputedDataProxyTest.js index fb64c5ddf..0f3eea7f3 100644 --- a/test/ComputedDataProxyTest.js +++ b/test/ComputedDataProxyTest.js @@ -1,10 +1,10 @@ import test from "ava"; import ComputedDataProxy from "../src/ComputedDataProxy"; -test("Get vars used by function", async t => { +test("Get vars used by function", async (t) => { let cd = new ComputedDataProxy(["key1"]); let key1Fn = () => {}; - let key2Fn = data => { + let key2Fn = (data) => { return `${data.key1}`; }; @@ -12,50 +12,50 @@ test("Get vars used by function", async t => { t.deepEqual(await cd.findVarsUsed(key2Fn), ["key1"]); }); -test("Get vars used by function (not a computed key)", async t => { +test("Get vars used by function (not a computed key)", async (t) => { let cd = new ComputedDataProxy(["page.url"]); - let key1Fn = data => { + let key1Fn = (data) => { return `${data.page.url}`; }; t.deepEqual( await cd.findVarsUsed(key1Fn, { - page: { url: "" } + page: { url: "" }, }), ["page.url"] ); }); -test("Get vars used by function (multiple functions—not computed keys)", async t => { +test("Get vars used by function (multiple functions—not computed keys)", async (t) => { let cd = new ComputedDataProxy([ "page.url", "key1", "very.deep.reference", - "very.other.deep.reference" + "very.other.deep.reference", ]); // this would be real let sampleData = { key1: "", page: { - url: "" + url: "", }, very: { deep: { - reference: "" + reference: "", }, other: { deep: { - reference: "" - } - } - } + reference: "", + }, + }, + }, }; - let key1Fn = data => { + let key1Fn = (data) => { return `${data.page.url}`; }; - let key2Fn = data => { + let key2Fn = (data) => { return `${data.key1}${data.very.deep.reference}${data.very.other.deep.reference}`; }; @@ -63,17 +63,17 @@ test("Get vars used by function (multiple functions—not computed keys)", async t.deepEqual(await cd.findVarsUsed(key2Fn, sampleData), [ "key1", "very.deep.reference", - "very.other.deep.reference" + "very.other.deep.reference", ]); }); -test("Proxy shouldn’t always return {}", async t => { +test("Proxy shouldn’t always return {}", async (t) => { let cd = new ComputedDataProxy(["page.fileSlug"]); let proxy = cd.getProxyData( { page: { - fileSlug: "" - } + fileSlug: "", + }, }, new Set() ); @@ -82,7 +82,7 @@ test("Proxy shouldn’t always return {}", async t => { t.is(proxy.page.fileSlug, ""); }); -test("isArrayOrPlainObject", async t => { +test("isArrayOrPlainObject", async (t) => { let cd = new ComputedDataProxy(); t.is(cd.isArrayOrPlainObject(true), false); @@ -93,7 +93,7 @@ test("isArrayOrPlainObject", async t => { false ); t.is( - cd.isArrayOrPlainObject(function() {}), + cd.isArrayOrPlainObject(function () {}), false ); t.is(cd.isArrayOrPlainObject(new Date()), false); @@ -101,112 +101,154 @@ test("isArrayOrPlainObject", async t => { t.is(cd.isArrayOrPlainObject([]), true); }); -test("findVarsUsed empty", async t => { +test("findVarsUsed empty", async (t) => { let cdg = new ComputedDataProxy(); t.deepEqual(await cdg.findVarsUsed(() => {}), []); t.deepEqual(await cdg.findVarsUsed(({}) => {}), []); let data = { key: "value" }; - t.deepEqual(await cdg.findVarsUsed(data => {}), []); - t.deepEqual(await cdg.findVarsUsed(data => data.key), ["key"]); + t.deepEqual(await cdg.findVarsUsed((data) => {}), []); + t.deepEqual(await cdg.findVarsUsed((data) => data.key), ["key"]); }); -test("findVarsUsed with a computed key (target a string)", async t => { +test("findVarsUsed with a computed key (target a string)", async (t) => { let cdg = new ComputedDataProxy(); let data = { key: "value", computed: { - key: function(data) { + key: function (data) { return data.key; - } - } + }, + }, }; t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["key"]); }); -test("findVarsUsed with a computed key (target an array)", async t => { +test("findVarsUsed with a computed key (target an array)", async (t) => { let cdg = new ComputedDataProxy(); let data = { arr: [0, 1, 2], computed: { - key: function(data) { + key: function (data) { return data.arr[1]; - } - } + }, + }, }; t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["arr[1]"]); }); -test("findVarsUsed with a computed key (target an object)", async t => { +test("findVarsUsed with a computed key (target an object)", async (t) => { let cdg = new ComputedDataProxy(); let data = { obj: { - b: 1 + b: 1, }, computed: { - key: function(data) { + key: function (data) { return data.obj.b; - } - } + }, + }, }; t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["obj.b"]); }); -test("findVarsUsed with a computed key (target an object in an array)", async t => { +test("findVarsUsed with a computed key (target an object in an array)", async (t) => { let cdg = new ComputedDataProxy(); let data = { obj: [{ b: 1 }, { a: 2 }], computed: { - key: function(data) { + key: function (data) { return data.obj[1].a; - } - } + }, + }, }; t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["obj[1].a"]); }); -test("findVarsUsed with a computed key (target a string not used in the output)", async t => { +test("findVarsUsed with a computed key (target a string not used in the output)", async (t) => { let cdg = new ComputedDataProxy(); let data = { key1: "value1", key2: "value2", computed: { - key: function(data) { + key: function (data) { let b = data.key2; return data.key1; - } - } + }, + }, }; t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), [ "key2", - "key1" + "key1", ]); }); -test("findVarsUsed with a deep computed reference that doesn’t exist in parent data", async t => { +test("findVarsUsed with a deep computed reference that doesn’t exist in parent data", async (t) => { let cdg = new ComputedDataProxy(["deep.deep1", "deep.deep2"]); let data = { key1: "value1", key2: "value2", computed: { deep: { - deep1: function(data) { + deep1: function (data) { return data.key2; }, - deep2: function(data) { + deep2: function (data) { return data.deep.deep1; - } - } - } + }, + }, + }, }; t.deepEqual(await cdg.findVarsUsed(data.computed.deep.deep2, data), [ - "deep.deep1" + "deep.deep1", ]); t.deepEqual(await cdg.findVarsUsed(data.computed.deep.deep1, data), ["key2"]); }); + +test("findVarsUsed with a array should filter out array methods", async (t) => { + let cdg = new ComputedDataProxy(); + let data = { + arr: [0, 1, 2], + computed: { + key: function (data) { + return data.arr.filter((entry) => entry === 2); + }, + }, + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["arr"]); +}); + +test("findVarsUsed with a array can still reference length", async (t) => { + let cdg = new ComputedDataProxy(); + let data = { + arr: [0, 1, 2], + computed: { + key: function (data) { + return data.arr.length; + }, + }, + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["arr"]); +}); + +test("findVarsUsed can work with empty arrays", async (t) => { + let cdg = new ComputedDataProxy(); + let data = { + arr: [], + computed: { + key: function (data) { + return data.arr; + }, + }, + }; + + t.deepEqual(await cdg.findVarsUsed(data.computed.key, data), ["arr"]); +}); diff --git a/test/ComputedDataQueueTest.js b/test/ComputedDataQueueTest.js index 5c8f02c35..fd14a82ae 100644 --- a/test/ComputedDataQueueTest.js +++ b/test/ComputedDataQueueTest.js @@ -1,7 +1,7 @@ import test from "ava"; import ComputedDataQueue from "../src/ComputedDataQueue"; -test("Standard uses", t => { +test("Standard uses", (t) => { let queue = new ComputedDataQueue(); queue.uses("permalink", ["var1", "var2"]); queue.uses("collections.all", ["var2", "var3"]); @@ -10,11 +10,11 @@ test("Standard uses", t => { "var2", "permalink", "var3", - "collections.all" + "collections.all", ]); }); -test("What does permalink use", t => { +test("What does permalink use", (t) => { let queue = new ComputedDataQueue(); queue.uses("permalink", ["var1", "var2"]); queue.uses("collections.all", ["var2", "var3"]); @@ -27,7 +27,7 @@ test("What does permalink use", t => { t.deepEqual(queue.getOrder(), ["var3", "collections.all"]); }); -test("What does page.url and page.outputPath use", t => { +test("What does page.url and page.outputPath use", (t) => { let queue = new ComputedDataQueue(); queue.uses("page.url", ["permalink"]); queue.uses("page.url", ["var1", "var2"]); @@ -47,7 +47,7 @@ test("What does page.url and page.outputPath use", t => { t.deepEqual(queue.getOrder(), []); }); -test("Permalink uses a collection (not yet supported in Eleventy)", t => { +test("Permalink uses a collection (not yet supported in Eleventy)", (t) => { let queue = new ComputedDataQueue(); queue.uses("permalink", ["collections.dog", "var2"]); queue.uses("collections.all", ["var2", "var3"]); @@ -58,10 +58,9 @@ test("Permalink uses a collection (not yet supported in Eleventy)", t => { t.deepEqual(queue.getDependsOn("var2"), ["permalink", "collections.all"]); t.deepEqual(queue.getDependsOn("collections.all"), []); t.deepEqual(queue.getDependsOn("hi"), ["permalink", "collections.dog"]); - t.is(queue.isDependsOnStartsWith("hi", "collections."), true); - t.is(queue.isDependsOnStartsWith("collections.all", "collections."), true); - t.is(queue.isDependsOnStartsWith("var2", "collections."), true); - t.is(queue.isDependsOnStartsWith("unrelated", "collections."), false); + t.is(queue.isUsesStartsWith("collections.dog", "hi"), true); + t.is(queue.isUsesStartsWith("permalink", "collections."), true); + t.is(queue.isUsesStartsWith("unrelated", "collections."), false); t.deepEqual(queue.getOrderFor("unrelated"), ["test"]); @@ -74,6 +73,6 @@ test("Permalink uses a collection (not yet supported in Eleventy)", t => { "var3", "collections.all", "test", - "unrelated" + "unrelated", ]); }); diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index 4662687ce..c8ac55a66 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -1,16 +1,16 @@ import test from "ava"; import ComputedData from "../src/ComputedData"; -test("Basic get/set", async t => { +test("Basic get/set", async (t) => { let cd = new ComputedData(); cd.add("keystr", "this is a str"); - cd.add("key1", data => { + cd.add("key1", (data) => { return `this is a test ${data.key2}${data.keystr}`; }); let data = { - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); @@ -19,16 +19,16 @@ test("Basic get/set", async t => { t.is(data.keystr, "this is a str"); }); -test("Basic get/set (reverse order of adds)", async t => { +test("Basic get/set (reverse order of adds)", async (t) => { let cd = new ComputedData(); - cd.add("key1", data => { + cd.add("key1", (data) => { return `this is a test ${data.key2}${data.keystr}`; }); cd.add("keystr", "this is a str"); let data = { - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); @@ -37,19 +37,19 @@ test("Basic get/set (reverse order of adds)", async t => { t.is(data.keystr, "this is a str"); }); -test("Basic get/set (reverse order of adds) nested two deep", async t => { +test("Basic get/set (reverse order of adds) nested two deep", async (t) => { let cd = new ComputedData(); - cd.add("key1.key3", data => { + cd.add("key1.key3", (data) => { return `this is a test ${data.key2}${data.keystr}`; }); - cd.add("key1.key4", data => { + cd.add("key1.key4", (data) => { return `this is a test ${data.key1.key3}`; }); cd.add("keystr", "this is a str"); let data = { - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); @@ -59,69 +59,69 @@ test("Basic get/set (reverse order of adds) nested two deep", async t => { t.is(data.keystr, "this is a str"); }); -test("use a computed value in another computed", async t => { +test("use a computed value in another computed", async (t) => { let cd = new ComputedData(); - cd.add("keyComputed", data => { + cd.add("keyComputed", (data) => { return `this is a test ${data.keyOriginal}`; }); - cd.add("keyComputed2nd", data => { + cd.add("keyComputed2nd", (data) => { return `using computed ${data.keyComputed}`; }); let data = { - keyOriginal: "inject me" + keyOriginal: "inject me", }; await cd.setupData(data); t.is(data.keyComputed2nd, "using computed this is a test inject me"); }); -test("use a computed value in another computed (out of order)", async t => { +test("use a computed value in another computed (out of order)", async (t) => { let cd = new ComputedData(); - cd.add("keyComputed2nd", data => { + cd.add("keyComputed2nd", (data) => { return `using computed ${data.keyComputed}`; }); - cd.add("keyComputed", data => { + cd.add("keyComputed", (data) => { return `this is a test ${data.keyOriginal}`; }); let data = { - keyOriginal: "inject me" + keyOriginal: "inject me", }; await cd.setupData(data); t.is(data.keyComputed2nd, "using computed this is a test inject me"); }); -test("use a computed value in another computed (out of order), async callbacks", async t => { +test("use a computed value in another computed (out of order), async callbacks", async (t) => { let cd = new ComputedData(); - cd.add("keyComputed2nd", async data => { + cd.add("keyComputed2nd", async (data) => { // await in data.keyComputed is optional 👀 return `using computed ${data.keyComputed}`; }); - cd.add("keyComputed", async data => { + cd.add("keyComputed", async (data) => { // await in data.keyOriginal is optional 👀 return `this is a test ${await data.keyOriginal}`; }); let data = { - keyOriginal: "inject me" + keyOriginal: "inject me", }; await cd.setupData(data); t.is(data.keyComputed2nd, "using computed this is a test inject me"); }); -test("Basic get/set nested", async t => { +test("Basic get/set nested", async (t) => { let cd = new ComputedData(); - cd.add("key1.nested", data => { + cd.add("key1.nested", (data) => { return `${data.key2}`; }); - cd.add("key2", data => "hi"); + cd.add("key2", (data) => "hi"); let data = { - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); @@ -130,25 +130,25 @@ test("Basic get/set nested", async t => { t.is(data.key2, "hi"); }); -test("Basic get/set nested deeper", async t => { +test("Basic get/set nested deeper", async (t) => { let cd = new ComputedData(); - cd.add("key1.nested.deeperA", data => { + cd.add("key1.nested.deeperA", (data) => { return `${data.key2}`; }); - cd.add("key1.nested.deeperB", data => { + cd.add("key1.nested.deeperB", (data) => { return `${data.key2}`; }); - cd.add("key1.nested.deeperC.wow", data => { + cd.add("key1.nested.deeperC.wow", (data) => { return `${data.key2}`; }); - cd.add("key2", data => "hi"); + cd.add("key2", (data) => "hi"); let data = { key1: { - nonComputed: "hi" + nonComputed: "hi", }, - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); @@ -158,9 +158,9 @@ test("Basic get/set nested deeper", async t => { deeperA: "hi", deeperB: "hi", deeperC: { - wow: "hi" - } - } + wow: "hi", + }, + }, }); t.is(data.key1.nested.deeperA, "hi"); @@ -170,40 +170,40 @@ test("Basic get/set nested deeper", async t => { t.is(data.key2, "hi"); }); -test("template string versus function types", async t => { +test("template string versus function types", async (t) => { let cd = new ComputedData(); - cd.add("key1.nested.deeperA", data => { + cd.add("key1.nested.deeperA", (data) => { return `${data.key2}`; }); cd.add("key2", () => "hi"); let data = { key1: { - nonComputed: "hi" + nonComputed: "hi", }, - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); t.deepEqual(data.key1, { nonComputed: "hi", nested: { - deeperA: "hi" - } + deeperA: "hi", + }, }); }); -test("Basic get/set with template string", async t => { +test("Basic get/set with template string", async (t) => { let cd = new ComputedData(); cd.addTemplateString("keystr", "this is a str"); - cd.addTemplateString("key1", data => { + cd.addTemplateString("key1", (data) => { return `this is a test ${data.key2}${data.keystr}`; }); let data = { - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); @@ -212,12 +212,12 @@ test("Basic get/set with template string", async t => { t.is(data.keystr, "this is a str"); }); -test("Basic get/set using array data", async t => { +test("Basic get/set using array data", async (t) => { t.plan(5); let cd = new ComputedData(); cd.add("keystr", "this is a str"); - cd.add("key1", data => { + cd.add("key1", (data) => { t.is(Array.isArray(data.arr), true); return `this is a test ${data.arr[0]}${data.keystr}`; }); @@ -226,8 +226,8 @@ test("Basic get/set using array data", async t => { arr: ["inject me"], collections: { first: [], - second: [] - } + second: [], + }, }; await cd.setupData(data); @@ -236,15 +236,15 @@ test("Basic get/set using array data", async t => { t.is(data.keystr, "this is a str"); }); -test("Computed returns deep object", async t => { +test("Computed returns deep object", async (t) => { let cd = new ComputedData(); - cd.add("returnobj", data => { + cd.add("returnobj", (data) => { return { key1: "value1", nest: { - key2: "value2" - } + key2: "value2", + }, }; }); @@ -252,9 +252,9 @@ test("Computed returns deep object", async t => { returnobj: { key1: "bad1", nest: { - key2: "bad2" - } - } + key2: "bad2", + }, + }, }; await cd.setupData(data); @@ -262,13 +262,13 @@ test("Computed returns deep object", async t => { t.is(data.returnobj.nest.key2, "value2"); }); -test("Boolean computed value Issue #1114", async t => { +test("Boolean computed value Issue #1114", async (t) => { let cd = new ComputedData(); cd.add("bool1", true); let data = { - key2: "inject me" + key2: "inject me", }; await cd.setupData(data); @@ -276,11 +276,11 @@ test("Boolean computed value Issue #1114", async t => { t.is(data.key2, "inject me"); }); -test("Expect collections in data callback #1114", async t => { +test("Expect collections in data callback #1114", async (t) => { t.plan(4); let cd = new ComputedData(); - cd.add("key1", data => { + cd.add("key1", (data) => { t.is(data.collections.first[0], 1); t.is(data.collections.second[0], 2); return ``; @@ -289,25 +289,25 @@ test("Expect collections in data callback #1114", async t => { let data = { collections: { first: [1], - second: [2] - } + second: [2], + }, }; await cd.setupData(data); }); -test("Get var order", async t => { +test("Get var order", async (t) => { let cd = new ComputedData(); - cd.add("key1", data => data.collections.all); - cd.add("key2", data => data.collections.dog); - cd.add("key0", data => ""); + cd.add("key1", (data) => data.collections.all); + cd.add("key2", (data) => data.collections.dog); + cd.add("key0", (data) => ""); let data = { key2: "inject me", collections: { all: [1], - dog: [2] - } + dog: [2], + }, }; await cd.resolveVarOrder(data); @@ -316,41 +316,43 @@ test("Get var order", async t => { "key1", "collections.dog", "key2", - "key0" + "key0", ]); }); -test("Get var order and process it in two stages", async t => { +test("Get var order and process it in two stages", async (t) => { let cd = new ComputedData(); - cd.add("page.url", data => data.key2); - cd.add("page.outputPath", data => `${data.key2}${data.collections.dog[0]}`); - cd.add("key0", data => "hi"); - cd.add("collections.processed", data => "hi"); + cd.add("page.url", (data) => data.key2); + cd.add("page.outputPath", (data) => data.key2); + cd.add("key0", (data) => "hi"); + cd.add("key1", (data) => data.collections.dog[0]); + cd.add("collections.processed", (data) => "hi"); let data = { key2: "/my-path/", collections: { - dog: [2] - } + dog: [2], + }, }; // set page.url, page.outputPath, key2, collections.dog[0] - await cd.setupData(data, function(entry) { - return !this.isDependsOnStartsWith(entry, "collections."); + await cd.setupData(data, function (entry) { + return !this.isUsesStartsWith(entry, "collections."); }); t.deepEqual(data, { collections: { dog: [2], - processed: "" + processed: "", }, key0: "hi", + key1: "", key2: "/my-path/", page: { url: "/my-path/", - outputPath: "/my-path/2" - } + outputPath: "/my-path/", + }, }); // set collections.processed @@ -359,14 +361,15 @@ test("Get var order and process it in two stages", async t => { t.deepEqual(data, { collections: { dog: [2], - processed: "hi" + processed: "hi", }, key0: "hi", + key1: 2, key2: "/my-path/", page: { url: "/my-path/", - outputPath: "/my-path/2" - } + outputPath: "/my-path/", + }, }); // t.deepEqual(cd.queue.getOrder(), ["collections.all", "key1", "collections.dog", "key2", "key0"]); From fd4f8a4f8c65e88ca5c95d853d074e5d73b502eb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 6 May 2020 21:44:10 -0500 Subject: [PATCH 210/746] One minor computed note --- src/Template.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Template.js b/src/Template.js index a1a5e7b4d..63180d468 100644 --- a/src/Template.js +++ b/src/Template.js @@ -407,6 +407,12 @@ class Template extends TemplateContent { async addComputedData(data) { // will _not_ consume renderData this.computedData = new ComputedData(); + + // Add permalink (outside of eleventyComputed) to computed graph + // if(data.permalink) { + // this._addComputedEntry(this.computedData, data.permalink, "permalink"); + // } + // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly this.computedData.addTemplateString( "page.url", @@ -430,6 +436,8 @@ class Template extends TemplateContent { // limited run of computed data—save the stuff that relies on collections for later. await this.computedData.setupData(data, function (entry) { return !this.isUsesStartsWith(entry, "collections."); + // TODO possible improvement here is to only process page.url, page.outputPath, permalink + // instead of only punting on things that rely on collections. }); // Deprecated, use eleventyComputed instead. From e3121f911d7f635de6fcf03a4e4e08fd7c37cd5a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 6 May 2020 21:45:23 -0500 Subject: [PATCH 211/746] Better initialization check for Custom engines will wait for init to finish if already running. --- src/Engines/Custom.js | 41 +++++++++++++++++++++++++++++++---- src/Engines/JavaScript.js | 20 ++++------------- src/TemplateEngineManager.js | 4 +++- src/Util/GetJavaScriptData.js | 19 ++++++++++++++++ 4 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 src/Util/GetJavaScriptData.js diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 154521f48..d2d0a9b56 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -1,4 +1,5 @@ const TemplateEngine = require("./TemplateEngine"); +const getJavaScriptData = require("../Util/GetJavaScriptData"); class CustomEngine extends TemplateEngine { constructor(name, includesDir) { @@ -7,6 +8,7 @@ class CustomEngine extends TemplateEngine { this.entry = this.getExtensionMapEntry(); this.needsInit = "init" in this.entry && typeof this.entry.init === "function"; + this.initStarted = false; this.initFinished = false; } @@ -31,11 +33,42 @@ class CustomEngine extends TemplateEngine { return true; } - async compile(str, inputPath) { - if (this.needsInit && !this.initFinished) { - await this.entry.init.bind({ config: this.config })(); - this.initFinished = true; + // If we init from multiple places, wait for the first init to finish + // before continuing on. + async _runningInit() { + if (this.needsInit) { + if (this.initStarted) { + await this.initStarted; + } else if (!this.initFinished) { + this.initStarted = this.entry.init.bind({ config: this.config })(); + await this.initStarted; + this.initFinished = true; + } } + } + + async getExtraDataFromFile(inputPath) { + await this._runningInit(); + + if ("getData" in this.entry) { + if (typeof this.entry.getData === "function") { + return await this.entry.getData(inputPath); + } else { + if (!("getInstanceFromInputPath" in this.entry)) { + return Promise.reject( + new Error( + `getInstanceFromInputPath callback missing from ${this.name} template engine plugin.` + ) + ); + } + let inst = await this.entry.getInstanceFromInputPath(inputPath); + return await getJavaScriptData(inst, inputPath); + } + } + } + + async compile(str, inputPath) { + await this._runningInit(); // TODO generalize this (look at JavaScript.js) return this.entry.compile.bind({ config: this.config })(str, inputPath); diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index b4fa4a8f2..9d913155f 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -2,8 +2,8 @@ const TemplateEngine = require("./TemplateEngine"); const TemplatePath = require("../TemplatePath"); const EleventyBaseError = require("../EleventyBaseError"); const deleteRequireCache = require("../Util/DeleteRequireCache"); +const getJavaScriptData = require("../Util/GetJavaScriptData"); -class JavaScriptTemplateInvalidDataFormatError extends EleventyBaseError {} class JavaScriptTemplateNotDefined extends EleventyBaseError {} class JavaScript extends TemplateEngine { @@ -24,7 +24,7 @@ class JavaScript extends TemplateEngine { // Function, Class // Object _getInstance(mod) { - let noop = function() { + let noop = function () { return ""; }; @@ -91,19 +91,7 @@ class JavaScript extends TemplateEngine { async getExtraDataFromFile(inputPath) { let inst = this.getInstanceFromInputPath(inputPath); - if (inst && "data" in inst) { - // get extra data from `data` method, - // either as a function or getter or object literal - let result = await (typeof inst.data === "function" - ? inst.data() - : inst.data); - if (typeof result !== "object") { - throw new JavaScriptTemplateInvalidDataFormatError( - `Invalid data format returned from ${inputPath}: typeof ${typeof result}` - ); - } - return result; - } + return await getJavaScriptData(inst, inputPath); } getJavaScriptFunctions(inst) { @@ -131,7 +119,7 @@ class JavaScript extends TemplateEngine { inst = this.getInstanceFromInputPath(inputPath); } if (inst && "render" in inst) { - return function(data) { + return function (data) { // only blow away existing inst.page if it has a page.url if (!inst.page || inst.page.url) { inst.page = data.page; diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 42dc91b11..8a24fbfb1 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -29,7 +29,7 @@ class TemplateEngineManager { pug: "Pug", njk: "Nunjucks", liquid: "Liquid", - "11ty.js": "JavaScript" + "11ty.js": "JavaScript", }; if ("extensionMap" in this.config) { @@ -69,6 +69,8 @@ class TemplateEngineManager { instance.config = this.config; instance.engineManager = this; + // Make sure cache key is based on name and not path + // Custom class is used for all plugins, cache once per plugin this.engineCache[name] = instance; return instance; } diff --git a/src/Util/GetJavaScriptData.js b/src/Util/GetJavaScriptData.js new file mode 100644 index 000000000..f1d2289f9 --- /dev/null +++ b/src/Util/GetJavaScriptData.js @@ -0,0 +1,19 @@ +const EleventyBaseError = require("../EleventyBaseError"); + +class JavaScriptInvalidDataFormatError extends EleventyBaseError {} + +module.exports = async function (inst, inputPath, key = "data") { + if (inst && key in inst) { + // get extra data from `data` method, + // either as a function or getter or object literal + let result = await (typeof inst[key] === "function" + ? inst[key]() + : inst[key]); + if (typeof result !== "object") { + throw new JavaScriptInvalidDataFormatError( + `Invalid data format returned from ${inputPath}: typeof ${typeof result}` + ); + } + return result; + } +}; From 8a55defd9f57a1aa6ab1c03b5c25c27143648077 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 9 May 2020 21:55:09 -0500 Subject: [PATCH 212/746] Fixes #1137 --- src/ComputedDataProxy.js | 92 ++++++++++++------- src/Template.js | 10 +- test/ComputedDataTest.js | 27 +++++- test/TemplateMapTest-ComputedData.js | 42 +++++++++ .../collections.njk | 11 +++ .../stubs-computed-collections-filter/dog.njk | 4 + 6 files changed, 149 insertions(+), 37 deletions(-) create mode 100644 test/stubs-computed-collections-filter/collections.njk create mode 100644 test/stubs-computed-collections-filter/dog.njk diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index 75663b693..e32ad91d5 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -27,50 +27,80 @@ class ComputedDataProxy { } } - return this._getProxyData(data, keyRef); + let proxyData = this._getProxyData(data, keyRef); + return proxyData; } - _getProxyData(data, keyRef, parentKey = "") { - if (lodashIsPlainObject(data)) { - return new Proxy( - {}, - { - get: (obj, key) => { - if (typeof key !== "string") { - return obj[key]; - } - let newKey = `${parentKey ? `${parentKey}.` : ""}${key}`; - let newData = this._getProxyData(data[key], keyRef, newKey); - if (!this.isArrayOrPlainObject(newData)) { - keyRef.add(newKey); - } - return newData; - }, - } - ); - } else if (Array.isArray(data)) { - return new Proxy(new Array(data.length), { + _getProxyForObject(dataObj, keyRef, parentKey = "") { + return new Proxy( + {}, + { get: (obj, key) => { - if (Array.prototype.hasOwnProperty(key)) { - // remove `filter`, `constructor`, `map`, etc - keyRef.add(parentKey); + if (typeof key !== "string") { return obj[key]; } - // Hm, this needs to be better - if (key === "then") { - keyRef.add(parentKey); - return; + let newKey = `${parentKey ? `${parentKey}.` : ""}${key}`; + + // Issue #1137 + // Special case for Collections, always return an Array for collection keys + // so they it works fine with Array methods like `filter`, `map`, etc + if (newKey === "collections") { + keyRef.add(newKey); + return new Proxy( + {}, + { + get: (target, key) => { + if (typeof key === "string") { + keyRef.add(`collections.${key}`); + return []; + } + return target[key]; + }, + } + ); } - let newKey = `${parentKey}[${key}]`; - let newData = this._getProxyData(data[key], keyRef, newKey); + let newData = this._getProxyData(dataObj[key], keyRef, newKey); if (!this.isArrayOrPlainObject(newData)) { keyRef.add(newKey); } return newData; }, - }); + } + ); + } + + _getProxyForArray(dataArr, keyRef, parentKey = "") { + return new Proxy(new Array(dataArr.length), { + get: (obj, key) => { + if (Array.prototype.hasOwnProperty(key)) { + // remove `filter`, `constructor`, `map`, etc + keyRef.add(parentKey); + return obj[key]; + } + + // Hm, this needs to be better + if (key === "then") { + keyRef.add(parentKey); + return; + } + + let newKey = `${parentKey}[${key}]`; + let newData = this._getProxyData(dataArr[key], keyRef, newKey); + if (!this.isArrayOrPlainObject(newData)) { + keyRef.add(newKey); + } + return newData; + }, + }); + } + + _getProxyData(data, keyRef, parentKey = "") { + if (lodashIsPlainObject(data)) { + return this._getProxyForObject(data, keyRef, parentKey); + } else if (Array.isArray(data)) { + return this._getProxyForArray(data, keyRef, parentKey); } // everything else! diff --git a/src/Template.js b/src/Template.js index 63180d468..9cbca0864 100644 --- a/src/Template.js +++ b/src/Template.js @@ -413,6 +413,7 @@ class Template extends TemplateContent { // this._addComputedEntry(this.computedData, data.permalink, "permalink"); // } + // Note that `permalink` is only a thing that gets consumed—it does not go directly into generated data // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly this.computedData.addTemplateString( "page.url", @@ -434,10 +435,14 @@ class Template extends TemplateContent { } // limited run of computed data—save the stuff that relies on collections for later. + debug("First round of computed data for %o", this.inputPath); await this.computedData.setupData(data, function (entry) { return !this.isUsesStartsWith(entry, "collections."); + // TODO possible improvement here is to only process page.url, page.outputPath, permalink // instead of only punting on things that rely on collections. + // let firstPhaseComputedData = ["page.url", "page.outputPath", ...this.getOrderFor("page.url"), ...this.getOrderFor("page.outputPath")]; + // return firstPhaseComputedData.indexOf(entry) > -1; }); // Deprecated, use eleventyComputed instead. @@ -450,6 +455,7 @@ class Template extends TemplateContent { } async resolveRemainingComputedData(data) { + debug("Second round of computed data for %o", this.inputPath); await this.computedData.processRemainingData(data); } @@ -492,13 +498,13 @@ class Template extends TemplateContent { for (let page of pageTemplates) { let pageData = Object.assign({}, await page.getData()); + await page.addComputedData(pageData); + // Issue #115 if (data.collections) { pageData.collections = data.collections; } - await page.addComputedData(pageData); - results.push({ template: page, inputPath: this.inputPath, diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index c8ac55a66..26b543f70 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -276,13 +276,31 @@ test("Boolean computed value Issue #1114", async (t) => { t.is(data.key2, "inject me"); }); -test("Expect collections in data callback #1114", async (t) => { - t.plan(4); +test("Expect even missing collections to be arrays in data callback #1114", async (t) => { + t.plan(2); let cd = new ComputedData(); cd.add("key1", (data) => { - t.is(data.collections.first[0], 1); - t.is(data.collections.second[0], 2); + t.is(Array.isArray(data.collections.first), true); + t.is(Array.isArray(data.collections.second), true); + return ``; + }); + + let data = { + collections: {}, + }; + await cd.resolveVarOrder(data); +}); + +test("Expect collections to be arrays in data callback #1114", async (t) => { + t.plan(2); + let cd = new ComputedData(); + + cd.add("key1", (data) => { + if (data.collections.first.length) { + t.is(data.collections.first[0], 1); + t.is(data.collections.second[0], 2); + } return ``; }); @@ -338,6 +356,7 @@ test("Get var order and process it in two stages", async (t) => { // set page.url, page.outputPath, key2, collections.dog[0] await cd.setupData(data, function (entry) { + // TODO see note in Template.js about changing the two pass computed data return !this.isUsesStartsWith(entry, "collections."); }); diff --git a/test/TemplateMapTest-ComputedData.js b/test/TemplateMapTest-ComputedData.js index 131178760..d1566b8bd 100644 --- a/test/TemplateMapTest-ComputedData.js +++ b/test/TemplateMapTest-ComputedData.js @@ -129,3 +129,45 @@ test("Computed data in directory data file consumes data file data, Issue #1137" t.is(map[0]._pages[0].data.webmentions, "first"); t.is(map[1]._pages[0].data.webmentions, "second"); }); + +test("Computed data can filter collections (and other array methods)", async (t) => { + let tm = new TemplateMap(); + + let dataObj = new TemplateData("./test/stubs-computed-collections-filter/"); + let tmpl = getNewTemplate( + "./test/stubs-computed-collections-filter/collections.njk", + "./test/stubs-computed-collections-filter/", + "./dist", + dataObj + ); + + await tm.add(tmpl); + + let dataObj2 = new TemplateData("./test/stubs-computed-collections-filter/"); + let tmpl2 = getNewTemplate( + "./test/stubs-computed-collections-filter/dog.njk", + "./test/stubs-computed-collections-filter/", + "./dist", + dataObj2 + ); + + await tm.add(tmpl2); + + await tm.cache(); + + let map = tm.getMap(); + + t.is(map[0].inputPath.endsWith("collections.njk"), true); + + t.truthy(map[0].data.collections.all); + t.is(map[0].data.collections.all.length, 2); + t.truthy(map[0].data.collections.dog); + t.is(map[0].data.collections.dog.length, 1); + t.truthy(map[0].data.dogCollection); + t.is(map[0].data.dogCollection.length, 1); + t.is(map[0].data.test, "hello"); + + // Deeply equal but not the same per `filter` use. + t.not(map[0].data.dogCollection, map[0].data.collections.dog); + t.deepEqual(map[0].data.dogCollection, map[0].data.collections.dog); +}); diff --git a/test/stubs-computed-collections-filter/collections.njk b/test/stubs-computed-collections-filter/collections.njk new file mode 100644 index 000000000..78eecca74 --- /dev/null +++ b/test/stubs-computed-collections-filter/collections.njk @@ -0,0 +1,11 @@ +---js +{ + eleventyComputed: { + test: "hello", + dogCollection: data => { + return data.collections.dog.filter(entry => true); + } + } +} +--- +Issue #1114 \ No newline at end of file diff --git a/test/stubs-computed-collections-filter/dog.njk b/test/stubs-computed-collections-filter/dog.njk new file mode 100644 index 000000000..a51aa14a0 --- /dev/null +++ b/test/stubs-computed-collections-filter/dog.njk @@ -0,0 +1,4 @@ +--- +tags: dog +--- +Hi from dog \ No newline at end of file From 1ce02f550d881bb117e993ccccc35873d2366fc6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 10 May 2020 13:54:04 -0500 Subject: [PATCH 213/746] v0.11.0 --- docs-src/_data/coverage.json | 13 +++++++------ docs/coverage.md | 13 +++++++------ package.json | 10 +++++----- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 9e2d083db..028ee1f88 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,9 +1,9 @@ -{"total": {"lines":{"total":3428,"covered":3039,"skipped":0,"pct":88.65},"statements":{"total":3450,"covered":3060,"skipped":0,"pct":88.7},"functions":{"total":811,"covered":708,"skipped":0,"pct":87.3},"branches":{"total":1482,"covered":1204,"skipped":0,"pct":81.24}} +{"total": {"lines":{"total":3464,"covered":3062,"skipped":0,"pct":88.39},"statements":{"total":3486,"covered":3083,"skipped":0,"pct":88.44},"functions":{"total":818,"covered":714,"skipped":0,"pct":87.29},"branches":{"total":1503,"covered":1213,"skipped":0,"pct":80.71}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":34,"skipped":0,"pct":73.91},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":46,"covered":34,"skipped":0,"pct":73.91},"branches":{"total":21,"covered":11,"skipped":0,"pct":52.38}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.78},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.78},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} -,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":44,"covered":44,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":44,"covered":44,"skipped":0,"pct":100},"branches":{"total":17,"covered":17,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":38,"covered":38,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":38,"covered":38,"skipped":0,"pct":100},"branches":{"total":24,"covered":24,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":46,"covered":46,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":46,"covered":46,"skipped":0,"pct":100},"branches":{"total":17,"covered":17,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.04},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.04},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.63}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.73}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":24,"covered":24,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -18,7 +18,7 @@ ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":59,"covered":22,"skipped":0,"pct":37.29},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":59,"covered":22,"skipped":0,"pct":37.29},"branches":{"total":36,"covered":10,"skipped":0,"pct":27.78}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":33,"covered":33,"skipped":0,"pct":100},"functions":{"total":16,"covered":16,"skipped":0,"pct":100},"statements":{"total":35,"covered":35,"skipped":0,"pct":100},"branches":{"total":17,"covered":15,"skipped":0,"pct":88.24}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":307,"covered":292,"skipped":0,"pct":95.11},"functions":{"total":55,"covered":54,"skipped":0,"pct":98.18},"statements":{"total":309,"covered":294,"skipped":0,"pct":95.15},"branches":{"total":111,"covered":98,"skipped":0,"pct":88.29}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":309,"covered":294,"skipped":0,"pct":95.15},"functions":{"total":55,"covered":54,"skipped":0,"pct":98.18},"statements":{"total":311,"covered":296,"skipped":0,"pct":95.18},"branches":{"total":115,"covered":102,"skipped":0,"pct":88.7}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":31,"covered":28,"skipped":0,"pct":90.32},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":34,"covered":31,"skipped":0,"pct":91.18},"branches":{"total":10,"covered":7,"skipped":0,"pct":70}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":62,"covered":55,"skipped":0,"pct":88.71},"functions":{"total":10,"covered":6,"skipped":0,"pct":60},"statements":{"total":62,"covered":55,"skipped":0,"pct":88.71},"branches":{"total":26,"covered":24,"skipped":0,"pct":92.31}} @@ -39,12 +39,12 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":112,"covered":88,"skipped":0,"pct":78.57},"functions":{"total":32,"covered":23,"skipped":0,"pct":71.88},"statements":{"total":112,"covered":88,"skipped":0,"pct":78.57},"branches":{"total":28,"covered":14,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":215,"covered":128,"skipped":0,"pct":59.53},"functions":{"total":57,"covered":26,"skipped":0,"pct":45.61},"statements":{"total":216,"covered":129,"skipped":0,"pct":59.72},"branches":{"total":88,"covered":41,"skipped":0,"pct":46.59}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":14,"covered":11,"skipped":0,"pct":78.57},"functions":{"total":4,"covered":1,"skipped":0,"pct":25},"statements":{"total":14,"covered":11,"skipped":0,"pct":78.57},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":19,"covered":12,"skipped":0,"pct":63.16},"functions":{"total":5,"covered":3,"skipped":0,"pct":60},"statements":{"total":19,"covered":12,"skipped":0,"pct":63.16},"branches":{"total":12,"covered":6,"skipped":0,"pct":50}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":34,"covered":15,"skipped":0,"pct":44.12},"functions":{"total":7,"covered":4,"skipped":0,"pct":57.14},"statements":{"total":34,"covered":15,"skipped":0,"pct":44.12},"branches":{"total":20,"covered":5,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.74},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.74},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":61,"covered":59,"skipped":0,"pct":96.72},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":62,"covered":60,"skipped":0,"pct":96.77},"branches":{"total":50,"covered":43,"skipped":0,"pct":86}} +,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":58,"covered":56,"skipped":0,"pct":96.55},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":59,"covered":57,"skipped":0,"pct":96.61},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScriptTemplateLiteral.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":77,"covered":74,"skipped":0,"pct":96.1},"functions":{"total":27,"covered":26,"skipped":0,"pct":96.3},"statements":{"total":77,"covered":74,"skipped":0,"pct":96.1},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.63},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.63},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} @@ -60,6 +60,7 @@ ,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":115,"covered":106,"skipped":0,"pct":92.17},"functions":{"total":18,"covered":17,"skipped":0,"pct":94.44},"statements":{"total":119,"covered":110,"skipped":0,"pct":92.44},"branches":{"total":90,"covered":75,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Util/Capitalize.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":9,"covered":9,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.86},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.86},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/Util/Pluralize.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":44,"covered":42,"skipped":0,"pct":95.45},"functions":{"total":21,"covered":19,"skipped":0,"pct":90.48},"statements":{"total":45,"covered":43,"skipped":0,"pct":95.56},"branches":{"total":18,"covered":18,"skipped":0,"pct":100}} diff --git a/docs/coverage.md b/docs/coverage.md index 46d88a6f5..479a77c07 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,13 +1,13 @@ -# Code Coverage for Eleventy v0.11.0-beta.4 +# Code Coverage for Eleventy v0.11.0 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 88.65% | 88.7% | 87.3% | 81.24% | +| `total` | 88.39% | 88.44% | 87.29% | 80.71% | | `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | | `src/BenchmarkGroup.js` | 73.91% | 73.91% | 66.67% | 52.38% | | `src/BenchmarkManager.js` | 77.78% | 77.78% | 75% | 75% | | `src/ComputedData.js` | 100% | 100% | 100% | 100% | -| `src/ComputedDataProxy.js` | 100% | 100% | 100% | 100% | +| `src/ComputedDataProxy.js` | 98.04% | 98.04% | 100% | 90.63% | | `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.73% | | `src/ComputedDataTemplateString.js` | 100% | 100% | 100% | 83.33% | | `src/Config.js` | 100% | 100% | 100% | 100% | @@ -22,7 +22,7 @@ | `src/EleventyServe.js` | 37.29% | 37.29% | 56.25% | 27.78% | | `src/EleventyWatch.js` | 100% | 100% | 100% | 88.24% | | `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 93.33% | -| `src/Template.js` | 95.11% | 95.15% | 98.18% | 88.29% | +| `src/Template.js` | 95.15% | 95.18% | 98.18% | 88.7% | | `src/TemplateCache.js` | 100% | 100% | 100% | 100% | | `src/TemplateCollection.js` | 90.32% | 91.18% | 93.33% | 70% | | `src/TemplateConfig.js` | 88.71% | 88.71% | 60% | 92.31% | @@ -43,12 +43,12 @@ | `src/TemplateWriter.js` | 78.57% | 78.57% | 71.88% | 50% | | `src/UserConfig.js` | 59.53% | 59.72% | 45.61% | 46.59% | | `src/defaultConfig.js` | 78.57% | 78.57% | 25% | 100% | -| `src/Engines/Custom.js` | 63.16% | 63.16% | 60% | 50% | +| `src/Engines/Custom.js` | 44.12% | 44.12% | 57.14% | 25% | | `src/Engines/Ejs.js` | 94.74% | 94.74% | 85.71% | 88.89% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | -| `src/Engines/JavaScript.js` | 96.72% | 96.77% | 100% | 86% | +| `src/Engines/JavaScript.js` | 96.55% | 96.61% | 100% | 83.33% | | `src/Engines/JavaScriptTemplateLiteral.js` | 94.44% | 94.44% | 100% | 100% | | `src/Engines/Liquid.js` | 96.1% | 96.1% | 96.3% | 85% | | `src/Engines/Markdown.js` | 90.63% | 90.63% | 88.89% | 81.25% | @@ -64,6 +64,7 @@ | `src/Plugins/Pagination.js` | 92.17% | 92.44% | 94.44% | 83.33% | | `src/Util/Capitalize.js` | 100% | 100% | 100% | 100% | | `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | +| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 100% | | `src/Util/Merge.js` | 92.86% | 92.86% | 100% | 87.5% | | `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | | `src/Util/Sortable.js` | 95.45% | 95.56% | 90.48% | 100% | diff --git a/package.json b/package.json index d3d31ac01..0f908df7d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.11.0-beta.4", + "version": "0.11.0", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -76,14 +76,14 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.1", - "ava": "^3.8.1", + "ava": "^3.8.2", "husky": "^4.2.5", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", "jsdoc": "3.6.4", - "lint-staged": "^10.2.0", + "lint-staged": "^10.2.2", "markdown-it-emoji": "^1.4.0", - "node-sass": "^4.14.0", + "node-sass": "^4.14.1", "nyc": "^15.0.1", "prettier": "^2.0.5", "rimraf": "^3.0.2", @@ -108,7 +108,7 @@ "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", "lodash": "^4.17.15", - "luxon": "^1.23.0", + "luxon": "^1.24.1", "markdown-it": "^10.0.0", "minimist": "^1.2.5", "moo": "^0.5.1", From 50d0b5f244efbb3affb2623a22c22f8bd69d69f3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 10 May 2020 14:02:44 -0500 Subject: [PATCH 214/746] Make sure it outputs 0 files when 0 files are written (avoid "in 0.03 seconds (v0.11.0)" bug) --- src/Eleventy.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index d7844e4ce..719fa43ea 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -250,13 +250,12 @@ class Eleventy { ); } - if (writeCount || skippedCount) { - slashRet.push( - `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}${ - skippedCount ? ` (skipped ${skippedCount})` : "" - }` - ); - } + slashRet.push( + `Wrote ${writeCount} ${simplePlural(writeCount, "file", "files")}${ + skippedCount ? ` (skipped ${skippedCount})` : "" + }` + ); + if (slashRet.length) { ret.push(slashRet.join(" / ")); } @@ -500,7 +499,7 @@ Arguments: // Is a CSS input file and is not in the includes folder // TODO check output path file extension of this template (not input path) // TODO add additional API for this, maybe a config callback? - let onlyCssChanges = this.watchManager.hasAllQueueFiles(path => { + let onlyCssChanges = this.watchManager.hasAllQueueFiles((path) => { return ( path.endsWith(".css") && // TODO how to make this work with relative includes? @@ -627,7 +626,7 @@ Arguments: return Object.assign( { ignored: ignores, - ignoreInitial: true + ignoreInitial: true, // also interesting: awaitWriteFinish }, configOptions @@ -684,12 +683,12 @@ Arguments: } } - watcher.on("change", async path => { + watcher.on("change", async (path) => { console.log("File changed:", path); await watchRun.call(this, path); }); - watcher.on("add", async path => { + watcher.on("add", async (path) => { console.log("File added:", path); await watchRun.call(this, path); }); From 36c5022d885d147b5677fc08ef157eb849b8437a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 10 May 2020 14:04:13 -0500 Subject: [PATCH 215/746] Made another commit to 0.11.0 --- docs-src/_data/coverage.json | 6 +++--- docs/coverage.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 028ee1f88..3fdef09ce 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,13 +1,13 @@ -{"total": {"lines":{"total":3464,"covered":3062,"skipped":0,"pct":88.39},"statements":{"total":3486,"covered":3083,"skipped":0,"pct":88.44},"functions":{"total":818,"covered":714,"skipped":0,"pct":87.29},"branches":{"total":1503,"covered":1213,"skipped":0,"pct":80.71}} +{"total": {"lines":{"total":3463,"covered":3064,"skipped":0,"pct":88.48},"statements":{"total":3485,"covered":3085,"skipped":0,"pct":88.52},"functions":{"total":818,"covered":714,"skipped":0,"pct":87.29},"branches":{"total":1499,"covered":1213,"skipped":0,"pct":80.92}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":34,"skipped":0,"pct":73.91},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":46,"covered":34,"skipped":0,"pct":73.91},"branches":{"total":21,"covered":11,"skipped":0,"pct":52.38}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":35,"skipped":0,"pct":76.09},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":46,"covered":35,"skipped":0,"pct":76.09},"branches":{"total":21,"covered":13,"skipped":0,"pct":61.9}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.78},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.78},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} ,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":46,"covered":46,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":46,"covered":46,"skipped":0,"pct":100},"branches":{"total":17,"covered":17,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.04},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.04},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.63}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.73}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":24,"covered":24,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":222,"covered":121,"skipped":0,"pct":54.5},"functions":{"total":40,"covered":20,"skipped":0,"pct":50},"statements":{"total":223,"covered":121,"skipped":0,"pct":54.26},"branches":{"total":74,"covered":32,"skipped":0,"pct":43.24}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":221,"covered":122,"skipped":0,"pct":55.2},"functions":{"total":40,"covered":20,"skipped":0,"pct":50},"statements":{"total":222,"covered":122,"skipped":0,"pct":54.95},"branches":{"total":70,"covered":30,"skipped":0,"pct":42.86}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} diff --git a/docs/coverage.md b/docs/coverage.md index 479a77c07..2316128dd 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -2,16 +2,16 @@ | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 88.39% | 88.44% | 87.29% | 80.71% | +| `total` | 88.48% | 88.52% | 87.29% | 80.92% | | `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | -| `src/BenchmarkGroup.js` | 73.91% | 73.91% | 66.67% | 52.38% | +| `src/BenchmarkGroup.js` | 76.09% | 76.09% | 66.67% | 61.9% | | `src/BenchmarkManager.js` | 77.78% | 77.78% | 75% | 75% | | `src/ComputedData.js` | 100% | 100% | 100% | 100% | | `src/ComputedDataProxy.js` | 98.04% | 98.04% | 100% | 90.63% | | `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.73% | | `src/ComputedDataTemplateString.js` | 100% | 100% | 100% | 83.33% | | `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 54.5% | 54.26% | 50% | 43.24% | +| `src/Eleventy.js` | 55.2% | 54.95% | 50% | 42.86% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | | `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | From 13fc3d88de76d081c5734b09646d6ca6c96ca5fa Mon Sep 17 00:00:00 2001 From: Steven Petryk Date: Wed, 13 May 2020 12:54:49 -0700 Subject: [PATCH 216/746] Fix argument for setTimeout vs new Promise --- src/Eleventy.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index b8fde2445..4c2b23fca 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -658,8 +658,8 @@ Arguments: await new Promise((resolve, reject) => { watchDelay = setTimeout(async () => { this._watch().then(resolve, reject); - }); - }, this.config.watchThrottleWaitTime); + }, this.config.watchThrottleWaitTime); + }); } catch (e) { if (e instanceof EleventyBaseError) { EleventyErrorHandler.error(e, "Eleventy watch error"); From e55a6a899be7c5ffca4ee873ca829fe62a42180b Mon Sep 17 00:00:00 2001 From: Daniel Schildt Date: Fri, 15 May 2020 17:35:29 +0300 Subject: [PATCH 217/746] docs: update license year to 2020 - Update license year to 2020 - Add line break to the end of file - Improves experience when using CLI tools --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index b1726d081..0ad7545c2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Zach Leatherman @zachleat +Copyright (c) 2020 Zach Leatherman @zachleat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. From 7a6d91864f1e89e4d278f21ba6a80931083acd3b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 16 May 2020 20:09:03 -0500 Subject: [PATCH 218/746] Fixes weird bug with zero file copy counts --- src/TemplatePassthroughManager.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 2333d0645..7538f1e1f 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -56,7 +56,7 @@ class TemplatePassthroughManager { inputPath: TemplatePath.addLeadingDotSlash(path), outputPath: outputPath ? TemplatePath.stripLeadingDotSlash(outputPath) - : true + : true, }; } @@ -77,7 +77,7 @@ class TemplatePassthroughManager { } getConfigPathGlobs() { - return this.getConfigPaths().map(path => { + return this.getConfigPaths().map((path) => { return TemplatePath.convertToRecursiveGlobSync(path.inputPath); }); } @@ -113,7 +113,7 @@ class TemplatePassthroughManager { return pass .write() - .then(fileCopyCount => { + .then((fileCopyCount) => { if (pass.isDryRun) { // We don’t count the skipped files as we need to iterate over them debug( @@ -129,10 +129,10 @@ class TemplatePassthroughManager { } else { this.count += fileCopyCount; } - debug("Copied %o (%d files)", path.inputPath, fileCopyCount); + debug("Copied %o (%d files)", path.inputPath, fileCopyCount || 0); } }) - .catch(function(e) { + .catch(function (e) { return Promise.reject( new TemplatePassthroughManagerCopyError( `Having trouble copying '${path.inputPath}'`, From b83c0e27ba3d51010aff2d474494f94e9440c919 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 16 May 2020 20:10:15 -0500 Subject: [PATCH 219/746] Fixes #1152 --- src/TemplateContent.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 77d8be06a..f05a7d0d1 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -14,6 +14,7 @@ const debug = require("debug")("Eleventy:TemplateContent"); const debugDev = require("debug")("Dev:Eleventy:TemplateContent"); const bench = require("./BenchmarkManager").get("Aggregate"); +class TemplateContentFrontMatterError extends EleventyBaseError {} class TemplateContentCompileError extends EleventyBaseError {} class TemplateContentRenderError extends EleventyBaseError {} @@ -79,7 +80,15 @@ class TemplateContent { if (this.inputContent) { let options = this.config.frontMatterParsingOptions || {}; - let fm = matter(this.inputContent, options); + let fm; + try { + fm = matter(this.inputContent, options); + } catch (e) { + throw new TemplateContentFrontMatterError( + `Having trouble reading front matter from template ${this.inputPath}`, + e + ); + } if (options.excerpt && fm.excerpt) { let excerptString = fm.excerpt + (options.excerpt_separator || "---"); if (fm.content.startsWith(excerptString + os.EOL)) { @@ -102,7 +111,7 @@ class TemplateContent { this.frontMatter = { data: {}, content: "", - excerpt: "" + excerpt: "", }; } } From 9a21b9cb49bdbe737995867364fba7ea614bfd3b Mon Sep 17 00:00:00 2001 From: Tierney Cyren Date: Tue, 19 May 2020 16:50:18 -0400 Subject: [PATCH 220/746] chore: update package.json to current minimum Node.js LTS --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f908df7d..c0fab47e5 100755 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "main": "src/Eleventy.js", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "type": "opencollective", From 42650fffc46bb29bc26b4e4d1c2eda8d866a66ba Mon Sep 17 00:00:00 2001 From: vseventer Date: Sun, 24 May 2020 09:17:01 -0400 Subject: [PATCH 221/746] Pass data to pagination before callback. --- src/Plugins/Pagination.js | 2 +- test/PaginationTest.js | 12 ++++++++++++ test/stubs/paged/paged-before-metadata.njk | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 test/stubs/paged/paged-before-metadata.njk diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index d94d4e61a..74470a71f 100644 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -120,7 +120,7 @@ class Pagination { typeof this.data.pagination.before === "function" ) { // we don’t need to make a copy of this because we already .filter() above - result = this.data.pagination.before(result); + result = this.data.pagination.before(result, this.data); } if (this.data.pagination.reverse === true) { diff --git a/test/PaginationTest.js b/test/PaginationTest.js index f0e807cb2..1bd4f967e 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -606,6 +606,18 @@ test("Pagination `before` Callback", async t => { t.deepEqual(templates[0].data.myalias, "item6"); }); +test("Pagination `before` Callback with metadata", async t => { + let tmpl = new Template( + "./test/stubs/paged/paged-before-metadata.njk", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.deepEqual(templates[0].data.pagination.items, ["item3"]); +}); + test("Pagination `before` Callback with a Filter", async t => { let tmpl = new Template( "./test/stubs/paged/paged-before-filter.njk", diff --git a/test/stubs/paged/paged-before-metadata.njk b/test/stubs/paged/paged-before-metadata.njk new file mode 100644 index 000000000..62a857056 --- /dev/null +++ b/test/stubs/paged/paged-before-metadata.njk @@ -0,0 +1,14 @@ +---js +{ + keyword: "item3", + pagination: { + data: "items", + size: 1, + before: function(data, metadata) { + return data.filter(el => el === metadata.keyword); + } + }, + items: ["item1", "item2", "item3", "item4", "item5", "item6"] +} +--- +
    {% for item in pagination.items %}
  1. {{ item }}
  2. {% endfor %}
From c2e0dc506ec476d3b0392b1bf78c66dff90fd751 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Wed, 17 Jun 2020 13:47:30 -0700 Subject: [PATCH 222/746] Initial, cleaned-up cut of performance tuning patches. Benchmark results: https://gist.github.com/slightlyoff/4a2c2709c8a4ef80ef074010b0be6a65 API compatible; all tests pass. --- src/Benchmark.js | 2 ++ src/Engines/Html.js | 5 +++++ src/Engines/Liquid.js | 1 + src/Engines/Markdown.js | 2 ++ src/Engines/Nunjucks.js | 8 +++++++ src/Engines/TemplateEngine.js | 1 + src/Template.js | 14 ++++++++++--- src/TemplateCollection.js | 18 +++++++++++++++- src/TemplateContent.js | 36 +++++++++++++++++++++++++++++++- src/TemplateData.js | 39 ++++++++++++++++++++++++++++++++--- src/TemplateMap.js | 29 +++++++++++++------------- src/TemplateWriter.js | 11 +++++++++- src/Util/Sortable.js | 4 +++- 13 files changed, 146 insertions(+), 24 deletions(-) diff --git a/src/Benchmark.js b/src/Benchmark.js index 5861a8199..0cfcca56f 100644 --- a/src/Benchmark.js +++ b/src/Benchmark.js @@ -18,6 +18,8 @@ class Benchmark { this.beforeTimers = []; } + // TODO(slightlyoff): + // disable all of these hrtime requests when not benchmarking before() { this.timesCalled++; this.beforeTimers.push(this.getNewTimestamp()); diff --git a/src/Engines/Html.js b/src/Engines/Html.js index 223cd45a8..dbe9c56bd 100644 --- a/src/Engines/Html.js +++ b/src/Engines/Html.js @@ -1,6 +1,11 @@ const TemplateEngine = require("./TemplateEngine"); class Html extends TemplateEngine { + constructor(name, includesDir) { + super(name, includesDir); + this.cacheable = true; + } + async compile(str, inputPath, preTemplateEngine) { if (preTemplateEngine) { let engine = this.engineManager.getEngine( diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 5a56dccc8..aeb6f4d5a 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -20,6 +20,7 @@ class Liquid extends TemplateEngine { keyword: /[a-zA-Z0-9\.\-\_]+/, "ignore:whitespace": /[, \t]+/ // includes comma separator }); + this.cacheable = true; } setLibrary(lib) { diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index 9110ceaf4..e89c03997 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -9,6 +9,8 @@ class Markdown extends TemplateEngine { this.markdownOptions = {}; this.setLibrary(this.config.libraryOverrides.md); + + this.cacheable = true; } setLibrary(mdLib) { diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 821d19811..f7f3c198c 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -11,6 +11,8 @@ class Nunjucks extends TemplateEngine { super(name, includesDir); this.setLibrary(this.config.libraryOverrides.njk); + + this.cacheable = true; } setLibrary(env) { @@ -225,6 +227,11 @@ class Nunjucks extends TemplateEngine { } async compile(str, inputPath) { + let needsCompile = (str.indexOf("{{") != -1) || (str.indexOf("{%") != -1); + if (!needsCompile) { + return async function() { return str; }; + } + let tmpl; if (!inputPath || inputPath === "njk" || inputPath === "md") { tmpl = NunjucksLib.compile(str, this.njkEnv); @@ -232,6 +239,7 @@ class Nunjucks extends TemplateEngine { tmpl = NunjucksLib.compile(str, this.njkEnv, inputPath); } return async function(data) { + return new Promise(function(resolve, reject) { tmpl.render(data, function(err, res) { if (err) { diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 7d704c751..c9d88eec9 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -12,6 +12,7 @@ class TemplateEngine { this.partialsHaveBeenCached = false; this.partials = []; this.engineLib = null; + this.cacheable = false; } get config() { diff --git a/src/Template.js b/src/Template.js index 9cbca0864..3193ad28c 100644 --- a/src/Template.js +++ b/src/Template.js @@ -127,7 +127,11 @@ class Template extends TemplateContent { debugDev("Not using dynamicPermalinks, using %o", permalink); permalinkValue = permalink; } else { - permalinkValue = await super.render(permalink, data, true); + // if (this.engine.cacheable && permalink.indexOf("{") == -1) { + // permalinkValue = permalink; + // } else { + permalinkValue = await super.render(permalink, data, true); + // } debug( "Rendering permalink for %o: %s becomes %o", this.inputPath, @@ -459,6 +463,8 @@ class Template extends TemplateContent { await this.computedData.processRemainingData(data); } + _templatesResultsCache = new Map(); + async getTemplates(data) { // TODO cache this let results = []; @@ -664,6 +670,8 @@ class Template extends TemplateContent { } async getMappedDate(data) { + // TODO(slightlyoff): lots of I/O! + // should we use Luxon dates everywhere? Right now using built-in `Date` if ("date" in data && data.date) { debug( @@ -676,7 +684,7 @@ class Template extends TemplateContent { debug("getMappedDate: YAML parsed it: %o", data.date); return data.date; } else { - let stat = await fs.stat(this.inputPath); + let stat = fs.statSync(this.inputPath); // string if (data.date.toLowerCase() === "last modified") { return new Date(stat.ctimeMs); @@ -713,7 +721,7 @@ class Template extends TemplateContent { return dateObj; } - let stat = await fs.stat(this.inputPath); + let stat = fs.statSync(this.inputPath); let createdDate = new Date(stat.birthtimeMs); debug( "getMappedDate: using file created time for %o of %o (from %o)", diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js index b2d3b665d..7e731a675 100644 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -33,16 +33,32 @@ class TemplateCollection extends Sortable { return globs; } + _filteredByGlobsCache = new Map(); + getFilteredByGlob(globs) { globs = this.getGlobs(globs); - return this.getAllSorted().filter(item => { + let key = globs.join("::"); + if (!this._dirty) { + // Try to find a pre-sorted list and clone it. + if (this._filteredByGlobsCache.has(key)) { + return [...(this._filteredByGlobsCache.get(key))]; + } + } else if (this._filteredByGlobsCache.size) { + // Blow away cache + this._filteredByGlobsCache = new Map(); + } + + let filtered = this.getAllSorted().filter(item => { if (multimatch([item.inputPath], globs).length) { return true; } return false; }); + this._dirty = false; + this._filteredByGlobsCache.set(key, [...filtered]); + return filtered; } getFilteredByTag(tagName) { diff --git a/src/TemplateContent.js b/src/TemplateContent.js index f05a7d0d1..3f5e6b978 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -18,6 +18,8 @@ class TemplateContentFrontMatterError extends EleventyBaseError {} class TemplateContentCompileError extends EleventyBaseError {} class TemplateContentRenderError extends EleventyBaseError {} +let inputContentCache = new Map(); + class TemplateContent { constructor(inputPath, inputDir) { this.inputPath = inputPath; @@ -120,10 +122,16 @@ class TemplateContent { if (!this.engine.needsToReadFileContents()) { return ""; } + let content = ""; let templateBenchmark = bench.get("Template Read"); templateBenchmark.before(); - let content = await fs.readFile(this.inputPath, "utf-8"); + if(inputContentCache.has(this.inputPath)){ + content = inputContentCache.get(this.inputPath); + } else { + content = await fs.readFile(this.inputPath, "utf-8"); + inputContentCache.set(this.inputPath, content); + } templateBenchmark.after(); return content; @@ -175,6 +183,20 @@ class TemplateContent { } } + static _compileEngineCache = new Map(); + + _getCompileCache(str, bypassMarkdown) { + let engineName = this.engine.getName() + "::" + (!!bypassMarkdown); + let engineMap = TemplateContent._compileEngineCache.get(engineName); + if (!engineMap) { + engineMap = new Map(); + TemplateContent._compileEngineCache.set(engineName, engineMap); + } + + let cacheable = this.engine.cacheable; + return [ cacheable, str , engineMap ]; + } + async compile(str, bypassMarkdown) { await this.setupTemplateRender(bypassMarkdown); @@ -185,11 +207,23 @@ class TemplateContent { ); try { + let [ cacheable, key, cache ] = + this._getCompileCache(str, bypassMarkdown); + if (cacheable && cache.has(key)) { + return cache.get(key); + } + + // Compilation is async, so we eagerly cache a Promise that eventually + // resolves to the compiled function + let res; + cache.set(key, new Promise((resolve) => { res = resolve; })); + let templateBenchmark = bench.get("Template Compile"); templateBenchmark.before(); let fn = await this.templateRender.getCompiledTemplate(str); templateBenchmark.after(); debugDev("%o getCompiledTemplate function created", this.inputPath); + res(fn); return fn; } catch (e) { debug(`Having trouble compiling template ${this.inputPath}: %O`, str); diff --git a/src/TemplateData.js b/src/TemplateData.js index 1f22aca2e..753ba6835 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -20,6 +20,22 @@ const deleteRequireCache = require("./Util/DeleteRequireCache"); const bench = require("./BenchmarkManager").get("Data"); const aggregateBench = require("./BenchmarkManager").get("Aggregate"); +class FSExistsCache { + _cache = new Map(); + has(path) { return this._cache.has(path); } + exists(path) { + let exists = this._cache.get(path); + if (!this.has(path)) { + exists = fs.pathExistsSync(path); + this._cache.set(path, exists); + } + return exists; + } + markExists(path, value=true) { + this._cache.set(path, !!value); + } +} + class TemplateDataParseError extends EleventyBaseError {} class TemplateData { @@ -104,7 +120,7 @@ class TemplateData { async _checkInputDir() { if (this.inputDirNeedsCheck) { - let globalPathStat = await fs.stat(this.inputDir); + let globalPathStat = fs.statSync(this.inputDir); if (!globalPathStat.isDirectory()) { throw new Error("Could not find data path directory: " + this.inputDir); @@ -180,7 +196,7 @@ class TemplateData { let fsBench = aggregateBench.get("Searching the file system"); fsBench.before(); - let paths = await fastglob(await this.getGlobalDataGlob(), { + let paths = fastglob.sync(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, dot: true }); @@ -261,12 +277,21 @@ class TemplateData { return this.globalData; } + /* Template and Directory data files */ async combineLocalData(localDataPaths) { let localData = {}; if (!Array.isArray(localDataPaths)) { localDataPaths = [localDataPaths]; } + + // Filter out files we know don't exist to avoid overhead for checking + localDataPaths = localDataPaths.filter((path) => { + return this._fsExistsCache.exists(path); + }); + + if (!localDataPaths.length) { return localData; } + for (let path of localDataPaths) { // clean up data for template/directory data files only. let dataForPath = await this.getDataValue(path, null, true); @@ -358,6 +383,10 @@ class TemplateData { } } + // It's common for data files not to exist, so we avoid going to the FS to + // re-check if they do via a quick-and-dirty cache. + _fsExistsCache = new FSExistsCache(); + async getDataValue(path, rawImports, ignoreProcessing) { let extension = TemplatePath.getExtension(path); @@ -370,7 +399,11 @@ class TemplateData { ) { // JS data file or require’d JSON (no preprocessing needed) let localPath = TemplatePath.absolutePath(path); - if (!(await fs.pathExists(localPath))) { + let exists = this._fsExistsCache.exists(localPath); + // Make sure that relative lookups benefit from cache + this._fsExistsCache.markExists(path, exists); + + if (!exists) { return {}; } diff --git a/src/TemplateMap.js b/src/TemplateMap.js index b3e3e90c4..b8d76423a 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -22,6 +22,7 @@ class TemplateMap { this.cached = false; this.configCollections = null; this.verboseOutput = true; + this.collection = new TemplateCollection(); } get tagPrefix() { @@ -38,13 +39,6 @@ class TemplateMap { return this.map; } - get collection() { - if (!this._collection) { - this._collection = new TemplateCollection(); - } - return this._collection; - } - getTagTarget(str) { if (str.startsWith("collections.")) { return str.substr("collections.".length); @@ -107,13 +101,14 @@ class TemplateMap { if (entry.data.tags) { for (let tag of entry.data.tags) { - if (!graph.hasNode(tagPrefix + tag)) { - graph.addNode(tagPrefix + tag); + let tagWithPrefix = tagPrefix + tag; + if (!graph.hasNode(tagWithPrefix)) { + graph.addNode(tagWithPrefix); } // collections.tagName // Dependency from tag to inputPath - graph.addDependency(tagPrefix + tag, entry.inputPath); + graph.addDependency(tagWithPrefix, entry.inputPath); } } } @@ -129,6 +124,7 @@ class TemplateMap { graph.addNode(tagPrefix + "all"); let userConfigCollections = this.getUserConfigCollectionNames(); + // Add tags from named user config collections for (let tag of userConfigCollections) { graph.addNode(tagPrefix + tag); @@ -156,18 +152,20 @@ class TemplateMap { if (entry.data.tags) { for (let tag of entry.data.tags) { - if (!graph.hasNode(tagPrefix + tag)) { - graph.addNode(tagPrefix + tag); + let tagWithPrefix = tagPrefix + tag; + if (!graph.hasNode(tagWithPrefix)) { + graph.addNode(tagWithPrefix); } // collections.tagName // Dependency from tag to inputPath - graph.addDependency(tagPrefix + tag, entry.inputPath); + graph.addDependency(tagWithPrefix, entry.inputPath); } } } } } - return graph.overallOrder(); + let order = graph.overallOrder(); + return order; } getPaginatedOverCollectionsMappedDependencies() { @@ -228,6 +226,7 @@ class TemplateMap { return graph.overallOrder(); } + // TODO(slightlyoff): major bottleneck async initDependencyMap(dependencyMap) { let tagPrefix = this.tagPrefix; for (let depEntry of dependencyMap) { @@ -275,6 +274,7 @@ class TemplateMap { entry.data.collections = this.collectionsData; } + let dependencyMap = this.getMappedDependencies(); await this.initDependencyMap(dependencyMap); @@ -308,6 +308,7 @@ class TemplateMap { this.checkForDuplicatePermalinks(); } + // TODO(slightlyoff): hot inner loop? getMapEntryForInputPath(inputPath) { for (let map of this.map) { if (map.inputPath === inputPath) { diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 88b960ba4..bc131db5c 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -37,6 +37,8 @@ class TemplateWriter { // TODO can we get rid of this? It’s only used for tests in `get eleventyFiles`` this.passthroughAll = isPassthroughAll; + + this._templatePathCache = new Map(); } get templateFormats() { @@ -108,13 +110,17 @@ class TemplateWriter { } _createTemplate(path) { - let tmpl = new Template( + let tmpl = this._templatePathCache.get(path); + if (tmpl) { return tmpl; } + + tmpl = new Template( path, this.inputDir, this.outputDir, this.templateData, this.extensionMap ); + this._templatePathCache.set(path, tmpl); tmpl.setIsVerbose(this.isVerbose); @@ -199,8 +205,10 @@ class TemplateWriter { async writeTemplates(paths) { let promises = []; + // console.time("writeTemplates:_createTemplateMap"); // TODO optimize await here await this._createTemplateMap(paths); + // console.timeEnd("writeTemplates:_createTemplateMap"); debug("Template map created."); let usedTemplateContentTooEarlyMap = []; @@ -235,6 +243,7 @@ class TemplateWriter { }) ); } + promises.push() return promises; } diff --git a/src/Util/Sortable.js b/src/Util/Sortable.js index 8730b244f..242b800c5 100644 --- a/src/Util/Sortable.js +++ b/src/Util/Sortable.js @@ -5,6 +5,7 @@ class Sortable { this.isSortAscending = true; this.isSortNumeric = false; this.items = []; + this._dirty = true; this.sortFunctionStringMap = { "A-Z": "Ascending", @@ -19,6 +20,7 @@ class Sortable { } add(item) { + this._dirty = true; this.items.push(item); } @@ -33,7 +35,7 @@ class Sortable { sortFunction = Sortable["sortFunction" + capitalize(sortFunction)]; } - return this.items.filter(() => true).sort(sortFunction); + return this.items.slice().sort(sortFunction); } sortAscending() { From 8373e2f5d66a1b41a0bc6e5a5a4109ce45108b82 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Fri, 19 Jun 2020 20:24:33 -0700 Subject: [PATCH 223/746] Remove unused comments. --- src/Template.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Template.js b/src/Template.js index 3193ad28c..94b624e7d 100644 --- a/src/Template.js +++ b/src/Template.js @@ -127,11 +127,7 @@ class Template extends TemplateContent { debugDev("Not using dynamicPermalinks, using %o", permalink); permalinkValue = permalink; } else { - // if (this.engine.cacheable && permalink.indexOf("{") == -1) { - // permalinkValue = permalink; - // } else { - permalinkValue = await super.render(permalink, data, true); - // } + permalinkValue = await super.render(permalink, data, true); debug( "Rendering permalink for %o: %s becomes %o", this.inputPath, From a7274b3c1e67d310984523371d0be80d6a51c4d1 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Sat, 20 Jun 2020 15:12:06 -0700 Subject: [PATCH 224/746] Invalidate input caches in watch mode. --- src/Eleventy.js | 2 ++ src/TemplateContent.js | 25 ++++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 64691ab13..8622d425d 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -1,6 +1,7 @@ const pkg = require("../package.json"); const TemplatePath = require("./TemplatePath"); const TemplateData = require("./TemplateData"); +const TemplateContent = require("./TemplateContent"); const TemplateWriter = require("./TemplateWriter"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyErrorHandler = require("./EleventyErrorHandler"); @@ -443,6 +444,7 @@ Arguments: * @param {String} changedFilePath - File that triggered a re-run (added or modified) */ async _addFileToWatchQueue(changedFilePath) { + TemplateContent.deleteCached(changedFilePath); this.watchManager.addToPendingQueue(changedFilePath); } diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 3f5e6b978..2c521022c 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -7,6 +7,7 @@ const lodashSet = require("lodash/set"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const TemplateData = require("./TemplateData"); const TemplateRender = require("./TemplateRender"); +const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const config = require("./Config"); @@ -18,8 +19,6 @@ class TemplateContentFrontMatterError extends EleventyBaseError {} class TemplateContentCompileError extends EleventyBaseError {} class TemplateContentRenderError extends EleventyBaseError {} -let inputContentCache = new Map(); - class TemplateContent { constructor(inputPath, inputDir) { this.inputPath = inputPath; @@ -118,19 +117,31 @@ class TemplateContent { } } + static _inputCache = new Map(); + + static cache(path, content) { + this._inputCache.set(TemplatePath.absolutePath(path), content); + } + + static getCached(path) { + return this._inputCache.get(TemplatePath.absolutePath(path)); + } + + static deleteCached(path) { + this._inputCache.delete(TemplatePath.absolutePath(path)); + } + async getInputContent() { if (!this.engine.needsToReadFileContents()) { return ""; } - let content = ""; let templateBenchmark = bench.get("Template Read"); templateBenchmark.before(); - if(inputContentCache.has(this.inputPath)){ - content = inputContentCache.get(this.inputPath); - } else { + let content = TemplateContent.getCached(this.inputPath); + if(!content) { content = await fs.readFile(this.inputPath, "utf-8"); - inputContentCache.set(this.inputPath, content); + TemplateContent.cache(this.inputPath, content); } templateBenchmark.after(); From d310b3a879ff2cc21a74f302bff8b26a13a109cb Mon Sep 17 00:00:00 2001 From: Oscar Otero Date: Sun, 21 Jun 2020 21:07:25 +0200 Subject: [PATCH 225/746] fix #1247 --- src/Filters/Url.js | 5 +++-- test/UrlTest.js | 41 +++++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/Filters/Url.js b/src/Filters/Url.js index e8824329d..ee2d63e6d 100644 --- a/src/Filters/Url.js +++ b/src/Filters/Url.js @@ -1,14 +1,15 @@ const validUrl = require("valid-url"); const TemplatePath = require("../TemplatePath"); -module.exports = function(url, pathPrefix) { +module.exports = function (url, pathPrefix) { // work with undefined url = url || ""; if ( validUrl.isUri(url) || url.indexOf("http://") === 0 || - url.indexOf("https://") === 0 + url.indexOf("https://") === 0 || + (url.indexOf("//") === 0 && url !== "//") ) { return url; } diff --git a/test/UrlTest.js b/test/UrlTest.js index a81985c9b..5a8eeb597 100644 --- a/test/UrlTest.js +++ b/test/UrlTest.js @@ -1,7 +1,7 @@ import test from "ava"; import url from "../src/Filters/Url.js"; -test("Test url filter without passing in pathPrefix", t => { +test("Test url filter without passing in pathPrefix", (t) => { let projectConfig = require("../src/Config").getConfig(); t.is(projectConfig.pathPrefix, "/"); @@ -9,7 +9,7 @@ test("Test url filter without passing in pathPrefix", t => { t.is(url("/test"), "/test"); }); -test("Test url filter with passthrough urls", t => { +test("Test url filter with passthrough urls", (t) => { // via https://gist.github.com/mxpv/034933deeebb26b62f14 t.is(url("http://foo.com/blah_blah", ""), "http://foo.com/blah_blah"); t.is(url("http://foo.com/blah_blah/", ""), "http://foo.com/blah_blah/"); @@ -102,7 +102,7 @@ test("Test url filter with passthrough urls", t => { t.is(url("http://उदाहरण.परीक्षा", ""), "http://उदाहरण.परीक्षा"); }); -test("Test url filter", t => { +test("Test url filter", (t) => { t.is(url("/", "/"), "/"); t.is(url("//", "/"), "/"); t.is(url(undefined, "/"), "."); @@ -116,18 +116,18 @@ test("Test url filter", t => { t.is(url("test", "/"), "test"); t.is(url("/test", "/"), "/test"); - t.is(url("//test", "/"), "/test"); + t.is(url("//test", "/"), "//test"); t.is(url("./test", "/"), "test"); t.is(url("../test", "/"), "../test"); t.is(url("test/", "/"), "test/"); t.is(url("/test/", "/"), "/test/"); - t.is(url("//test/", "/"), "/test/"); + t.is(url("//test/", "/"), "//test/"); t.is(url("./test/", "/"), "test/"); t.is(url("../test/", "/"), "../test/"); }); -test("Test url filter with custom pathPrefix (empty, gets overwritten by root config `/`)", t => { +test("Test url filter with custom pathPrefix (empty, gets overwritten by root config `/`)", (t) => { t.is(url("/", ""), "/"); t.is(url("//", ""), "/"); t.is(url(undefined, ""), "."); @@ -141,18 +141,18 @@ test("Test url filter with custom pathPrefix (empty, gets overwritten by root co t.is(url("test", ""), "test"); t.is(url("/test", ""), "/test"); - t.is(url("//test", ""), "/test"); + t.is(url("//test", ""), "//test"); t.is(url("./test", ""), "test"); t.is(url("../test", ""), "../test"); t.is(url("test/", ""), "test/"); t.is(url("/test/", ""), "/test/"); - t.is(url("//test/", ""), "/test/"); + t.is(url("//test/", ""), "//test/"); t.is(url("./test/", ""), "test/"); t.is(url("../test/", ""), "../test/"); }); -test("Test url filter with custom pathPrefix (leading slash)", t => { +test("Test url filter with custom pathPrefix (leading slash)", (t) => { t.is(url("/", "/testdir"), "/testdir/"); t.is(url("//", "/testdir"), "/testdir/"); t.is(url(undefined, "/testdir"), "."); @@ -166,18 +166,18 @@ test("Test url filter with custom pathPrefix (leading slash)", t => { t.is(url("test", "/testdir"), "test"); t.is(url("/test", "/testdir"), "/testdir/test"); - t.is(url("//test", "/testdir"), "/testdir/test"); + t.is(url("//test", "/testdir"), "//test"); t.is(url("./test", "/testdir"), "test"); t.is(url("../test", "/testdir"), "../test"); t.is(url("test/", "/testdir"), "test/"); t.is(url("/test/", "/testdir"), "/testdir/test/"); - t.is(url("//test/", "/testdir"), "/testdir/test/"); + t.is(url("//test/", "/testdir"), "//test/"); t.is(url("./test/", "/testdir"), "test/"); t.is(url("../test/", "/testdir"), "../test/"); }); -test("Test url filter with custom pathPrefix (double slash)", t => { +test("Test url filter with custom pathPrefix (double slash)", (t) => { t.is(url("/", "/testdir/"), "/testdir/"); t.is(url("//", "/testdir/"), "/testdir/"); t.is(url(undefined, "/testdir/"), "."); @@ -191,18 +191,18 @@ test("Test url filter with custom pathPrefix (double slash)", t => { t.is(url("test", "/testdir/"), "test"); t.is(url("/test", "/testdir/"), "/testdir/test"); - t.is(url("//test", "/testdir/"), "/testdir/test"); + t.is(url("//test", "/testdir/"), "//test"); t.is(url("./test", "/testdir/"), "test"); t.is(url("../test", "/testdir/"), "../test"); t.is(url("test/", "/testdir/"), "test/"); t.is(url("/test/", "/testdir/"), "/testdir/test/"); - t.is(url("//test/", "/testdir/"), "/testdir/test/"); + t.is(url("//test/", "/testdir/"), "//test/"); t.is(url("./test/", "/testdir/"), "test/"); t.is(url("../test/", "/testdir/"), "../test/"); }); -test("Test url filter with custom pathPrefix (trailing slash)", t => { +test("Test url filter with custom pathPrefix (trailing slash)", (t) => { t.is(url("/", "testdir/"), "/testdir/"); t.is(url("//", "testdir/"), "/testdir/"); t.is(url(undefined, "testdir/"), "."); @@ -216,18 +216,18 @@ test("Test url filter with custom pathPrefix (trailing slash)", t => { t.is(url("test", "testdir/"), "test"); t.is(url("/test", "testdir/"), "/testdir/test"); - t.is(url("//test", "testdir/"), "/testdir/test"); + t.is(url("//test", "testdir/"), "//test"); t.is(url("./test", "testdir/"), "test"); t.is(url("../test", "testdir/"), "../test"); t.is(url("test/", "testdir/"), "test/"); t.is(url("/test/", "testdir/"), "/testdir/test/"); - t.is(url("//test/", "testdir/"), "/testdir/test/"); + t.is(url("//test/", "testdir/"), "//test/"); t.is(url("./test/", "testdir/"), "test/"); t.is(url("../test/", "testdir/"), "../test/"); }); -test("Test url filter with custom pathPrefix (no slash)", t => { +test("Test url filter with custom pathPrefix (no slash)", (t) => { t.is(url("/", "testdir"), "/testdir/"); t.is(url("//", "testdir"), "/testdir/"); t.is(url(undefined, "testdir"), "."); @@ -241,13 +241,14 @@ test("Test url filter with custom pathPrefix (no slash)", t => { t.is(url("test", "testdir"), "test"); t.is(url("/test", "testdir"), "/testdir/test"); - t.is(url("//test", "testdir"), "/testdir/test"); + t.is(url("//test", "testdir"), "//test"); + t.is(url("//foo.com", "testdir"), "//foo.com"); t.is(url("./test", "testdir"), "test"); t.is(url("../test", "testdir"), "../test"); t.is(url("test/", "testdir"), "test/"); t.is(url("/test/", "testdir"), "/testdir/test/"); - t.is(url("//test/", "testdir"), "/testdir/test/"); + t.is(url("//test/", "testdir"), "//test/"); t.is(url("./test/", "testdir"), "test/"); t.is(url("../test/", "testdir"), "../test/"); }); From b7892db1c5ebb00cce3baa860d6f2d3715e6433c Mon Sep 17 00:00:00 2001 From: Tierney Cyren Date: Mon, 22 Jun 2020 19:35:06 -0400 Subject: [PATCH 226/746] chore: update YAML for Travis CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e7614af13..40667e490 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js node_js: - - 8 - 10 - 12 + - 14 before_script: - npm install script: npm run test From ae894e6c3f9cae0a4b06c677aa3e1fbb82a513fe Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 23 Jun 2020 14:17:21 +1000 Subject: [PATCH 227/746] Add global data --- src/TemplateData.js | 25 ++++++++++++++++++++++++- src/UserConfig.js | 7 +++++++ test/TemplateConfigTest.js | 15 ++++++++++++++- test/TemplateDataTest.js | 23 +++++++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 06912f8f5..b28dcea30 100644 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -177,14 +177,37 @@ class TemplateData { return globalData; } + async getInitialGlobalData() { + let globalData = {}; + if (this.config.globalData) { + let keys = Object.keys(this.config.globalData); + for (let j = 0; j < keys.length; j++) { + let returnValue = this.config.globalData[keys[j]]; + + if (typeof returnValue === "function") { + returnValue = await returnValue(); + } + globalData[keys[j]] = returnValue; + } + } + return globalData; + } + async getData() { let rawImports = this.getRawImports(); + let initialGlobalData = await this.getInitialGlobalData(); + if (!this.globalData) { let globalJson = await this.getAllGlobalData(); // OK: Shallow merge when combining rawImports (pkg) with global data files - this.globalData = Object.assign({}, globalJson, rawImports); + this.globalData = Object.assign( + {}, + initialGlobalData, + globalJson, + rawImports + ); } return this.globalData; diff --git a/src/UserConfig.js b/src/UserConfig.js index bf97e89b5..4db255269 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -54,6 +54,7 @@ class UserConfig { // this.templateExtensionAliases = {}; this.watchJavaScriptDependencies = true; this.browserSyncConfig = {}; + this.globalData = {}; } versionCheck(expected) { @@ -208,6 +209,11 @@ class UserConfig { this.nunjucksTags[name] = bench.add(`"${name}" Nunjucks Custom Tag`, tagFn); } + addGlobalData(name, callback) { + name = this.getNamespacedName(name); + this.globalData[name] = callback; + } + addTransform(name, callback) { name = this.getNamespacedName(name); @@ -510,6 +516,7 @@ class UserConfig { templateFormats: this.templateFormats, filters: this.filters, // now called transforms linters: this.linters, + globalData: this.globalData, layoutAliases: this.layoutAliases, passthroughCopies: this.passthroughCopies, liquidOptions: this.liquidOptions, diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 8815233cd..de6c90d59 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -108,7 +108,6 @@ test("Add universal filter", t => { t.not(Object.keys(cfg.handlebarsHelpers).indexOf("myFilterName"), -1); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); - test("Add namespaced universal filter", t => { eleventyConfig.reset(); eleventyConfig.namespace("testNamespace", function() { @@ -311,6 +310,20 @@ test("libraryOverrides", t => { t.deepEqual(mdLib, cfg.libraryOverrides.md); }); +test("addGlobalData", t => { + eleventyConfig.reset(); + eleventyConfig.addGlobalData("buildTime", function() { + return new Date(); + }); + + let templateCfg = new TemplateConfig( + require("../config.js"), + "./test/stubs/config.js" + ); + let cfg = templateCfg.getConfig(); + t.not(Object.keys(cfg.globalData).indexOf("buildTime"), -1); +}); + test("Properly throws error on missing module #182", t => { t.throws(function() { new TemplateConfig( diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 5892367f1..e15728236 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -162,6 +162,29 @@ test("getAllGlobalData() with js function data file", async t => { t.is(data.globalDataFn.datakeyfromjsfn, "howdy"); }); +test("getAllGlobalData() with config globalData", async t => { + let dataObj = new TemplateData("./test/stubs/"); + + dataObj._setConfig({ + ...dataObj.config, + globalData: { + example: () => { + return "one"; + }, + example2: async () => { + return "two"; + }, + example3: "static" + } + }); + + let data = await dataObj.cacheData(true); + + t.is(data.example, "one"); + t.is(data.example2, "two"); + t.is(data.example3, "static"); +}); + test("getDataValue() without a dataTemplateEngine", async t => { let dataObj = new TemplateData("./test/stubs/"); dataObj.setDataTemplateEngine(false); From 1bb0d0caaa20d86b4a4f5b25360fe0547deca27c Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 23 Jun 2020 18:03:24 +1000 Subject: [PATCH 228/746] chore: fix eslint warnings --- src/ComputedDataTemplateString.js | 6 +--- src/Engines/Haml.js | 3 +- src/Engines/Handlebars.js | 7 ++--- src/Engines/Html.js | 4 +-- src/Engines/JavaScriptTemplateLiteral.js | 6 ++-- src/Engines/Liquid.js | 36 ++++++++++++------------ src/Engines/Mustache.js | 4 +-- src/Engines/Nunjucks.js | 24 ++++++++-------- src/Engines/Pug.js | 3 +- src/Engines/TemplateEngine.js | 10 +++---- src/TemplateLayoutPathResolver.js | 3 +- src/TemplateMap.js | 4 +-- src/TemplatePassthroughManager.js | 2 +- 13 files changed, 52 insertions(+), 60 deletions(-) diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js index 90f7cf328..ffa391e6f 100644 --- a/src/ComputedDataTemplateString.js +++ b/src/ComputedDataTemplateString.js @@ -46,19 +46,15 @@ class ComputedDataTemplateString { return Array.from(vars); } - async findVarsUsed(fn, data = {}) { + async findVarsUsed(fn) { let proxyData = this.getProxyData(); let output; - // let savedLog = console.log; - // console.log = () => {}; // Mitigation for #1061, errors with filters in the first pass shouldn’t fail the whole thing. try { output = await fn(proxyData); } catch (e) { debug("Computed Data first pass data resolution error: %o", e); } - // console.log = savedLog; - return this.findVarsInOutput(output); } } diff --git a/src/Engines/Haml.js b/src/Engines/Haml.js index 0728229f3..fa22e6729 100644 --- a/src/Engines/Haml.js +++ b/src/Engines/Haml.js @@ -1,6 +1,5 @@ const HamlLib = require("hamljs"); const TemplateEngine = require("./TemplateEngine"); -const config = require("../Config"); class Haml extends TemplateEngine { constructor(name, includesDir) { @@ -14,7 +13,7 @@ class Haml extends TemplateEngine { this.setEngineLib(lib); } - async compile(str, inputPath) { + async compile(str) { return this.hamlLib.compile(str); } } diff --git a/src/Engines/Handlebars.js b/src/Engines/Handlebars.js index 57a810e9d..3c6ec2e9f 100644 --- a/src/Engines/Handlebars.js +++ b/src/Engines/Handlebars.js @@ -1,6 +1,5 @@ const HandlebarsLib = require("handlebars"); const TemplateEngine = require("./TemplateEngine"); -const config = require("../Config"); class Handlebars extends TemplateEngine { constructor(name, includesDir) { @@ -43,7 +42,7 @@ class Handlebars extends TemplateEngine { addPairedShortcodes(shortcodes) { for (let name in shortcodes) { let callback = shortcodes[name]; - this.addHelper(name, function(...args) { + this.addHelper(name, function (...args) { let options = args[args.length - 1]; let content = ""; if (options && options.fn) { @@ -55,9 +54,9 @@ class Handlebars extends TemplateEngine { } } - async compile(str, inputPath) { + async compile(str) { let fn = this.handlebarsLib.compile(str); - return function(data) { + return function (data) { return fn(data); }; } diff --git a/src/Engines/Html.js b/src/Engines/Html.js index 223cd45a8..8bc7c4a52 100644 --- a/src/Engines/Html.js +++ b/src/Engines/Html.js @@ -10,11 +10,11 @@ class Html extends TemplateEngine { ); let fn = await engine.compile(str, inputPath); - return async function(data) { + return async function (data) { return fn(data); }; } else { - return function(data) { + return function () { // do nothing with data if parseHtmlWith is falsy return str; }; diff --git a/src/Engines/JavaScriptTemplateLiteral.js b/src/Engines/JavaScriptTemplateLiteral.js index 4071593ee..ff9c06bb5 100644 --- a/src/Engines/JavaScriptTemplateLiteral.js +++ b/src/Engines/JavaScriptTemplateLiteral.js @@ -28,8 +28,8 @@ class JavaScriptTemplateLiteral extends TemplateEngine { return str; } - async compile(str, inputPath) { - return function(data) { + async compile(str) { + return function (data) { // avoid `with` let dataStr = ""; for (let j in data) { @@ -38,7 +38,7 @@ class JavaScriptTemplateLiteral extends TemplateEngine { null, null, { - references: true + references: true, } )};\n`; } diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 5a56dccc8..63ac61077 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -17,8 +17,8 @@ class Liquid extends TemplateEngine { number: /[0-9]+\.*[0-9]*/, doubleQuoteString: /"(?:\\["\\]|[^\n"\\])*"/, singleQuoteString: /'(?:\\['\\]|[^\n'\\])*'/, - keyword: /[a-zA-Z0-9\.\-\_]+/, - "ignore:whitespace": /[, \t]+/ // includes comma separator + keyword: /[a-zA-Z0-9.\-_]+/, + "ignore:whitespace": /[, \t]+/, // includes comma separator }); } @@ -48,7 +48,7 @@ class Liquid extends TemplateEngine { root: [super.getIncludesDir()], // overrides in compile with inputPath below extname: ".liquid", dynamicPartials: false, - strict_filters: false + strict_filters: false, }; let options = Object.assign(defaults, this.liquidOptions || {}); @@ -135,13 +135,13 @@ class Liquid extends TemplateEngine { addShortcode(shortcodeName, shortcodeFn) { let _t = this; - this.addTag(shortcodeName, function(liquidEngine) { + this.addTag(shortcodeName, function () { return { - parse: function(tagToken, remainTokens) { + parse: function (tagToken) { this.name = tagToken.name; this.args = tagToken.args; }, - render: function(scope, hash) { + render: function (scope) { let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope); return Promise.resolve( shortcodeFn.call( @@ -149,37 +149,37 @@ class Liquid extends TemplateEngine { ...argArray ) ); - } + }, }; }); } addPairedShortcode(shortcodeName, shortcodeFn) { let _t = this; - this.addTag(shortcodeName, function(liquidEngine) { + this.addTag(shortcodeName, function (liquidEngine) { return { - parse: function(tagToken, remainTokens) { + parse: function (tagToken, remainTokens) { this.name = tagToken.name; this.args = tagToken.args; this.templates = []; var stream = liquidEngine.parser .parseStream(remainTokens) - .on("template", tpl => this.templates.push(tpl)) - .on("tag:end" + shortcodeName, token => stream.stop()) - .on("end", x => { + .on("template", (tpl) => this.templates.push(tpl)) + .on("tag:end" + shortcodeName, () => stream.stop()) + .on("end", () => { throw new Error(`tag ${tagToken.raw} not closed`); }); stream.start(); }, - render: function(scope, hash) { + render: function (scope) { let argArray = Liquid.parseArguments(_t.argLexer, this.args, scope); - return new Promise((resolve, reject) => { + return new Promise((resolve) => { liquidEngine.renderer .renderTemplates(this.templates, scope) - .then(function(html) { + .then(function (html) { resolve( shortcodeFn.call( Liquid._normalizeShortcodeScope(scope), @@ -189,7 +189,7 @@ class Liquid extends TemplateEngine { ); }); }); - } + }, }; }); } @@ -205,10 +205,10 @@ class Liquid extends TemplateEngine { } else { options.root = [ super.getIncludesDir(), - TemplatePath.getDirFromFilePath(inputPath) + TemplatePath.getDirFromFilePath(inputPath), ]; } - return async function(data) { + return async function (data) { return engine.render(tmpl, data, options); }; } diff --git a/src/Engines/Mustache.js b/src/Engines/Mustache.js index 078fb9295..12ca69120 100644 --- a/src/Engines/Mustache.js +++ b/src/Engines/Mustache.js @@ -13,10 +13,10 @@ class Mustache extends TemplateEngine { this.setEngineLib(this.mustacheLib); } - async compile(str, inputPath) { + async compile(str) { let partials = super.getPartials(); - return function(data) { + return function (data) { return this.render(str, data, partials).trim(); }.bind(this.mustacheLib); } diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 821d19811..e91c76578 100644 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -19,7 +19,7 @@ class Nunjucks extends TemplateEngine { new NunjucksLib.Environment( new NunjucksLib.FileSystemLoader([ super.getIncludesDir(), - TemplatePath.getWorkingDir() + TemplatePath.getWorkingDir(), ]) ); this.setEngineLib(this.njkEnv); @@ -87,7 +87,7 @@ class Nunjucks extends TemplateEngine { function ShortcodeFunction() { this.tags = [shortcodeName]; - this.parse = function(parser, nodes, lexer) { + this.parse = function (parser, nodes) { let args; let tok = parser.nextToken(); @@ -107,7 +107,7 @@ class Nunjucks extends TemplateEngine { return new nodes.CallExtension(this, "run", args); }; - this.run = function(...args) { + this.run = function (...args) { let resolve; if (isAsync) { resolve = args.pop(); @@ -118,10 +118,10 @@ class Nunjucks extends TemplateEngine { if (isAsync) { shortcodeFn .call(Nunjucks._normalizeShortcodeContext(context), ...argArray) - .then(function(returnValue) { + .then(function (returnValue) { resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) - .catch(function(e) { + .catch(function (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( @@ -158,7 +158,7 @@ class Nunjucks extends TemplateEngine { function PairedShortcodeFunction() { this.tags = [shortcodeName]; - this.parse = function(parser, nodes, lexer) { + this.parse = function (parser, nodes) { var tok = parser.nextToken(); var args = parser.parseSignature(true, true); @@ -173,7 +173,7 @@ class Nunjucks extends TemplateEngine { return new nodes.CallExtension(this, "run", args, [body]); }; - this.run = function(...args) { + this.run = function (...args) { let resolve; if (isAsync) { resolve = args.pop(); @@ -188,10 +188,10 @@ class Nunjucks extends TemplateEngine { body(), ...argArray ) - .then(function(returnValue) { + .then(function (returnValue) { resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) - .catch(function(e) { + .catch(function (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( @@ -231,9 +231,9 @@ class Nunjucks extends TemplateEngine { } else { tmpl = NunjucksLib.compile(str, this.njkEnv, inputPath); } - return async function(data) { - return new Promise(function(resolve, reject) { - tmpl.render(data, function(err, res) { + return async function (data) { + return new Promise(function (resolve, reject) { + tmpl.render(data, function (err, res) { if (err) { reject(err); } else { diff --git a/src/Engines/Pug.js b/src/Engines/Pug.js index eb620a6d2..1e9e58cf8 100644 --- a/src/Engines/Pug.js +++ b/src/Engines/Pug.js @@ -1,6 +1,5 @@ const PugLib = require("pug"); const TemplateEngine = require("./TemplateEngine"); -const TemplatePath = require("../TemplatePath"); class Pug extends TemplateEngine { constructor(name, includesDir) { @@ -27,7 +26,7 @@ class Pug extends TemplateEngine { return Object.assign( { basedir: includesDir, - filename: includesDir + filename: includesDir, }, this.pugOptions || {} ); diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 7d704c751..3677b5847 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -80,11 +80,11 @@ class TemplateEngine { if (this.includesDir) { let bench = aggregateBench.get("Searching the file system"); bench.before(); - this.extensions.forEach(function(extension) { + this.extensions.forEach(function (extension) { partialFiles = partialFiles.concat( fastglob.sync(prefix + extension, { caseSensitiveMatch: false, - dot: true + dot: true, }) ); }); @@ -99,7 +99,7 @@ class TemplateEngine { this.includesDir ); let partialPathNoExt = partialPath; - this.extensions.forEach(function(extension) { + this.extensions.forEach(function (extension) { partialPathNoExt = TemplatePath.removeExtension( partialPathNoExt, "." + extension @@ -139,11 +139,11 @@ class TemplateEngine { return true; } - getExtraDataFromFile(inputPath) { + getExtraDataFromFile() { return {}; } - initRequireCache(inputPath) { + initRequireCache() { // do nothing } diff --git a/src/TemplateLayoutPathResolver.js b/src/TemplateLayoutPathResolver.js index e5da02ebd..767b20921 100644 --- a/src/TemplateLayoutPathResolver.js +++ b/src/TemplateLayoutPathResolver.js @@ -1,8 +1,7 @@ const fs = require("fs-extra"); const config = require("./Config"); -const EleventyExtensionMap = require("./EleventyExtensionMap"); const TemplatePath = require("./TemplatePath"); -const debug = require("debug")("Eleventy:TemplateLayoutPathResolver"); +// const debug = require("debug")("Eleventy:TemplateLayoutPathResolver"); class TemplateLayoutPathResolver { constructor(path, inputDir, extensionMap) { diff --git a/src/TemplateMap.js b/src/TemplateMap.js index b3e3e90c4..082d1e28d 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -296,7 +296,7 @@ class TemplateMap { secondPaginatedDepMap ); let orderedMap = orderedPaths.map( - function(inputPath) { + function (inputPath) { return this.getMapEntryForInputPath(inputPath); }.bind(this) ); @@ -530,7 +530,7 @@ class TemplateMap { }\`. Use distinct \`permalink\` values to resolve this conflict. 1. ${entry.inputPath} ${permalinks[page.url] - .map(function(inputPath, index) { + .map(function (inputPath, index) { return ` ${index + 2}. ${inputPath}\n`; }) .join("")} diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 7538f1e1f..4b1be9b6a 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -183,7 +183,7 @@ class TemplatePassthroughManager { let promises = []; debug("TemplatePassthrough copy started."); for (let path of this.getConfigPaths()) { - debug(`TemplatePassthrough copying from config: %o`, path); + debug("TemplatePassthrough copying from config: %o", path); promises.push(this.copyPath(path)); } From b709096715eafe9cdffa8ce6cb86298450773e65 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Sun, 28 Jun 2020 18:38:48 -0700 Subject: [PATCH 229/746] Addresses review comments. --- src/EleventyWatch.js | 4 ++-- src/Engines/Nunjucks.js | 40 ++++++++++++++++++++++++--------------- src/Plugins/Pagination.js | 16 ++++++++-------- src/Template.js | 2 -- src/TemplateCollection.js | 16 ++++++++-------- src/TemplateData.js | 21 +++++++++++--------- src/TemplateWriter.js | 13 +++++++------ 7 files changed, 62 insertions(+), 50 deletions(-) mode change 100644 => 100755 src/EleventyWatch.js mode change 100644 => 100755 src/Engines/Nunjucks.js mode change 100644 => 100755 src/Plugins/Pagination.js mode change 100644 => 100755 src/Template.js mode change 100644 => 100755 src/TemplateCollection.js mode change 100644 => 100755 src/TemplateData.js mode change 100644 => 100755 src/TemplateWriter.js diff --git a/src/EleventyWatch.js b/src/EleventyWatch.js old mode 100644 new mode 100755 index b1e073eac..245319ded --- a/src/EleventyWatch.js +++ b/src/EleventyWatch.js @@ -41,7 +41,7 @@ class EleventyWatch { if (typeof file === "function") { filterCallback = file; } else { - filterCallback = path => path === file; + filterCallback = (path) => path === file; } return this.activeQueue.filter(filterCallback); @@ -90,7 +90,7 @@ class EleventyWatch { return this.pendingQueue.length ? [this.pendingQueue.shift()] : []; } - let ret = this.pendingQueue.filter(() => true); + let ret = this.pendingQueue.slice(); this.pendingQueue = []; return ret; } diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js old mode 100644 new mode 100755 index f7f3c198c..f0238a126 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -21,7 +21,7 @@ class Nunjucks extends TemplateEngine { new NunjucksLib.Environment( new NunjucksLib.FileSystemLoader([ super.getIncludesDir(), - TemplatePath.getWorkingDir() + TemplatePath.getWorkingDir(), ]) ); this.setEngineLib(this.njkEnv); @@ -89,7 +89,7 @@ class Nunjucks extends TemplateEngine { function ShortcodeFunction() { this.tags = [shortcodeName]; - this.parse = function(parser, nodes, lexer) { + this.parse = function (parser, nodes, lexer) { let args; let tok = parser.nextToken(); @@ -109,7 +109,7 @@ class Nunjucks extends TemplateEngine { return new nodes.CallExtension(this, "run", args); }; - this.run = function(...args) { + this.run = function (...args) { let resolve; if (isAsync) { resolve = args.pop(); @@ -120,10 +120,10 @@ class Nunjucks extends TemplateEngine { if (isAsync) { shortcodeFn .call(Nunjucks._normalizeShortcodeContext(context), ...argArray) - .then(function(returnValue) { + .then(function (returnValue) { resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) - .catch(function(e) { + .catch(function (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( @@ -160,7 +160,7 @@ class Nunjucks extends TemplateEngine { function PairedShortcodeFunction() { this.tags = [shortcodeName]; - this.parse = function(parser, nodes, lexer) { + this.parse = function (parser, nodes, lexer) { var tok = parser.nextToken(); var args = parser.parseSignature(true, true); @@ -175,7 +175,7 @@ class Nunjucks extends TemplateEngine { return new nodes.CallExtension(this, "run", args, [body]); }; - this.run = function(...args) { + this.run = function (...args) { let resolve; if (isAsync) { resolve = args.pop(); @@ -190,10 +190,10 @@ class Nunjucks extends TemplateEngine { body(), ...argArray ) - .then(function(returnValue) { + .then(function (returnValue) { resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); }) - .catch(function(e) { + .catch(function (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( @@ -227,9 +227,20 @@ class Nunjucks extends TemplateEngine { } async compile(str, inputPath) { - let needsCompile = (str.indexOf("{{") != -1) || (str.indexOf("{%") != -1); + // Defend against syntax customisations: + // https://mozilla.github.io/nunjucks/api.html#customizing-syntax + let optsTags = this.njkEnv.opts.tags || {}; + let blockStart = optsTags.blockStart || "{%"; + let variableStart = optsTags.variableStart || "{{"; + let commentStart = optsTags.variableStart || "{#"; + let needsCompile = + str.indexOf(blockStart) != -1 || + str.indexOf(variableStart) != -1 || + str.indexOf(commentStart) != -1; if (!needsCompile) { - return async function() { return str; }; + return async function () { + return str; + }; } let tmpl; @@ -238,10 +249,9 @@ class Nunjucks extends TemplateEngine { } else { tmpl = NunjucksLib.compile(str, this.njkEnv, inputPath); } - return async function(data) { - - return new Promise(function(resolve, reject) { - tmpl.render(data, function(err, res) { + return async function (data) { + return new Promise(function (resolve, reject) { + tmpl.render(data, function (err, res) { if (err) { reject(err); } else { diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js old mode 100644 new mode 100755 index d94d4e61a..d7619454b --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -113,7 +113,7 @@ class Pagination { keys = Object.keys(fullDataSet); } - let result = keys.filter(() => true); + let result = keys.slice(); if ( this.data.pagination.before && @@ -128,7 +128,7 @@ class Pagination { } if (this.data.pagination.filter) { - result = result.filter(value => !this.isFiltered(value)); + result = result.filter((value) => !this.isFiltered(value)); } return result; @@ -194,7 +194,7 @@ class Pagination { size: this.data.pagination.size, alias: this.alias, - pages: this.size === 1 ? items.map(entry => entry[0]) : items, + pages: this.size === 1 ? items.map((entry) => entry[0]) : items, // See Issue #345 for more examples page: { @@ -219,12 +219,12 @@ class Pagination { ? this.size === 1 ? items[items.length - 1][0] : items[items.length - 1] - : null + : null, }, items: items[pageNumber], - pageNumber: pageNumber - } + pageNumber: pageNumber, + }, }; if (this.alias) { @@ -245,7 +245,7 @@ class Pagination { // we loop twice to pass in the appropriate prev/next links (already full generated now) templates.forEach( - function(cloned, pageNumber) { + function (cloned, pageNumber) { let pageObj = {}; // links are okay but hrefs are better @@ -282,7 +282,7 @@ class Pagination { previous: pageObj.previousPageHref, next: pageObj.nextPageHref, first: pageObj.firstPageHref, - last: pageObj.lastPageHref + last: pageObj.lastPageHref, }; Object.assign(overrides[pageNumber].pagination, pageObj); diff --git a/src/Template.js b/src/Template.js old mode 100644 new mode 100755 index 94b624e7d..e215d21dc --- a/src/Template.js +++ b/src/Template.js @@ -459,8 +459,6 @@ class Template extends TemplateContent { await this.computedData.processRemainingData(data); } - _templatesResultsCache = new Map(); - async getTemplates(data) { // TODO cache this let results = []; diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js old mode 100644 new mode 100755 index 7e731a675..baae0e2c6 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -12,7 +12,7 @@ class TemplateCollection extends Sortable { } getAll() { - return this.items.filter(() => true); + return this.items.slice(); } getAllSorted() { @@ -28,7 +28,7 @@ class TemplateCollection extends Sortable { globs = [globs]; } - globs = globs.map(glob => TemplatePath.addLeadingDotSlash(glob)); + globs = globs.map((glob) => TemplatePath.addLeadingDotSlash(glob)); return globs; } @@ -42,14 +42,14 @@ class TemplateCollection extends Sortable { if (!this._dirty) { // Try to find a pre-sorted list and clone it. if (this._filteredByGlobsCache.has(key)) { - return [...(this._filteredByGlobsCache.get(key))]; + return [...this._filteredByGlobsCache.get(key)]; } } else if (this._filteredByGlobsCache.size) { // Blow away cache this._filteredByGlobsCache = new Map(); } - let filtered = this.getAllSorted().filter(item => { + let filtered = this.getAllSorted().filter((item) => { if (multimatch([item.inputPath], globs).length) { return true; } @@ -62,19 +62,19 @@ class TemplateCollection extends Sortable { } getFilteredByTag(tagName) { - return this.getAllSorted().filter(item => { + return this.getAllSorted().filter((item) => { if (!tagName) { return true; } else if (Array.isArray(item.data.tags)) { - return item.data.tags.some(tag => tag === tagName); + return item.data.tags.some((tag) => tag === tagName); } return false; }); } getFilteredByTags(...tags) { - return this.getAllSorted().filter(item => - tags.every(requiredTag => { + return this.getAllSorted().filter((item) => + tags.every((requiredTag) => { const itemTags = item.data.tags; if (Array.isArray(itemTags)) { return itemTags.includes(requiredTag); diff --git a/src/TemplateData.js b/src/TemplateData.js old mode 100644 new mode 100755 index 753ba6835..7c297f3d0 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -22,7 +22,9 @@ const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class FSExistsCache { _cache = new Map(); - has(path) { return this._cache.has(path); } + has(path) { + return this._cache.has(path); + } exists(path) { let exists = this._cache.get(path); if (!this.has(path)) { @@ -31,7 +33,7 @@ class FSExistsCache { } return exists; } - markExists(path, value=true) { + markExists(path, value = true) { this._cache.set(path, !!value); } } @@ -120,7 +122,7 @@ class TemplateData { async _checkInputDir() { if (this.inputDirNeedsCheck) { - let globalPathStat = fs.statSync(this.inputDir); + let globalPathStat = await fs.stat(this.inputDir); if (!globalPathStat.isDirectory()) { throw new Error("Could not find data path directory: " + this.inputDir); @@ -146,12 +148,12 @@ class TemplateData { let paths = [ `${dir}/**/*.json`, // covers .11tydata.json too `${dir}/**/*${this.config.jsDataFileSuffix}.cjs`, - `${dir}/**/*${this.config.jsDataFileSuffix}.js` + `${dir}/**/*${this.config.jsDataFileSuffix}.js`, ]; if (this.hasUserDataExtensions()) { let userPaths = this.getUserDataExtensions().map( - extension => `${dir}/**/*.${extension}` // covers .11tydata.{extension} too + (extension) => `${dir}/**/*.${extension}` // covers .11tydata.{extension} too ); paths = userPaths.concat(paths); } @@ -162,7 +164,7 @@ class TemplateData { async getTemplateJavaScriptDataFileGlob() { let dir = await this.getInputDir(); return TemplatePath.addLeadingDotSlashArray([ - `${dir}/**/*${this.config.jsDataFileSuffix}.js` + `${dir}/**/*${this.config.jsDataFileSuffix}.js`, ]); } @@ -198,7 +200,7 @@ class TemplateData { fsBench.before(); let paths = fastglob.sync(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, - dot: true + dot: true, }); fsBench.after(); @@ -277,7 +279,6 @@ class TemplateData { return this.globalData; } - /* Template and Directory data files */ async combineLocalData(localDataPaths) { let localData = {}; @@ -290,7 +291,9 @@ class TemplateData { return this._fsExistsCache.exists(path); }); - if (!localDataPaths.length) { return localData; } + if (!localDataPaths.length) { + return localData; + } for (let path of localDataPaths) { // clean up data for template/directory data files only. diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js old mode 100644 new mode 100755 index bc131db5c..cf997b7be --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -111,7 +111,9 @@ class TemplateWriter { _createTemplate(path) { let tmpl = this._templatePathCache.get(path); - if (tmpl) { return tmpl; } + if (tmpl) { + return tmpl; + } tmpl = new Template( path, @@ -194,7 +196,7 @@ class TemplateWriter { passthroughManager.setIncrementalFile(this.incrementalFile); } - return passthroughManager.copyAll(paths).catch(e => { + return passthroughManager.copyAll(paths).catch((e) => { EleventyErrorHandler.warn(e, "Error with passthrough copy"); return Promise.reject( new TemplateWriterWriteError("Having trouble copying", e) @@ -214,7 +216,7 @@ class TemplateWriter { let usedTemplateContentTooEarlyMap = []; for (let mapEntry of this.templateMap.getMap()) { promises.push( - this._writeTemplate(mapEntry).catch(function(e) { + this._writeTemplate(mapEntry).catch(function (e) { // Premature templateContent in layout render, this also happens in // TemplateMap.populateContentDataInMap for non-layout content if (EleventyErrorUtil.isPrematureTemplateContentError(e)) { @@ -233,7 +235,7 @@ class TemplateWriter { for (let mapEntry of usedTemplateContentTooEarlyMap) { promises.push( - this._writeTemplate(mapEntry).catch(function(e) { + this._writeTemplate(mapEntry).catch(function (e) { return Promise.reject( new TemplateWriterWriteError( `Having trouble writing template (second pass): ${mapEntry.outputPath}`, @@ -243,7 +245,6 @@ class TemplateWriter { }) ); } - promises.push() return promises; } @@ -263,7 +264,7 @@ class TemplateWriter { promises.push(...(await this.writeTemplates(paths))); } - return Promise.all(promises).catch(e => { + return Promise.all(promises).catch((e) => { EleventyErrorHandler.error(e, "Error writing templates"); throw e; }); From dc51a114d2c091bf9c22f9c2dc6138287ec3c05e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 10 Jul 2020 21:58:58 -0500 Subject: [PATCH 230/746] Adds tests for #680. --- test/TemplateRenderLiquidTest.js | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index b13169ecb..a56244b91 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -976,3 +976,45 @@ test("Liquid Render a false #1069", async t => { ); t.is(await fn({ falseValue: false }), "false"); }); + +test("Liquid Render Square Brackets dash single quotes", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + "

{{ test['hey-a'] }}

" + ); + t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); +}); + +test.skip("Liquid Render Square Brackets dash single quotes spaces", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + "

{{ test[ 'hey-a' ] }}

" + ); + t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); +}); + +test("Liquid Render Square Brackets dash double quotes", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + '

{{ test["hey-a"] }}

' + ); + t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); +}); + +test.skip("Liquid Render Square Brackets dash double quotes spaces", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + '

{{ test[ "hey-a" ] }}

' + ); + t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); +}); + +test("Liquid Render Square Brackets variable reference", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + "

{{ test[ref] }}

" + ); + t.is(await fn({ test: { "hey-a": 1 }, ref: "hey-a" }), "

1

"); +}); + +test.skip("Liquid Render Square Brackets variable reference array", async t => { + let fn = await new TemplateRender("liquid").getCompiledTemplate( + "

{{ test[ref[0]] }}

" + ); + t.is(await fn({ test: { "hey-a": 1 }, ref: ["hey-a"] }), "

1

"); +}); From 6c8addfa4cf6d0a3f88bff325b1942e494765bd0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 10 Jul 2020 22:02:49 -0500 Subject: [PATCH 231/746] Include reference to issue #680 --- test/TemplateRenderLiquidTest.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index a56244b91..829eb7ac6 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -977,42 +977,42 @@ test("Liquid Render a false #1069", async t => { t.is(await fn({ falseValue: false }), "false"); }); -test("Liquid Render Square Brackets dash single quotes", async t => { +test("Liquid Render Square Brackets #680 dash single quotes", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test['hey-a'] }}

" ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test.skip("Liquid Render Square Brackets dash single quotes spaces", async t => { +test.skip("Liquid Render Square Brackets #680 dash single quotes spaces", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test[ 'hey-a' ] }}

" ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test("Liquid Render Square Brackets dash double quotes", async t => { +test("Liquid Render Square Brackets #680 dash double quotes", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( '

{{ test["hey-a"] }}

' ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test.skip("Liquid Render Square Brackets dash double quotes spaces", async t => { +test.skip("Liquid Render Square Brackets #680 dash double quotes spaces", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( '

{{ test[ "hey-a" ] }}

' ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test("Liquid Render Square Brackets variable reference", async t => { +test("Liquid Render Square Brackets #680 variable reference", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test[ref] }}

" ); t.is(await fn({ test: { "hey-a": 1 }, ref: "hey-a" }), "

1

"); }); -test.skip("Liquid Render Square Brackets variable reference array", async t => { +test.skip("Liquid Render Square Brackets #680 variable reference array", async t => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test[ref[0]] }}

" ); From 95278987c9e4c507051a1fcb9ecf3a06f09473e8 Mon Sep 17 00:00:00 2001 From: Mike Date: Sun, 19 Jul 2020 11:18:01 +1000 Subject: [PATCH 232/746] Change method to take an object --- eleventy | 1 + src/TemplateConfig.js | 4 ++-- src/UserConfig.js | 16 ++++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) create mode 120000 eleventy diff --git a/eleventy b/eleventy new file mode 120000 index 000000000..4c9aba5cb --- /dev/null +++ b/eleventy @@ -0,0 +1 @@ +/eleventy \ No newline at end of file diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 041f92fa1..16a20b2b4 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -104,7 +104,7 @@ class TemplateConfig { throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + (err.message.includes("Cannot find module") - ? chalk.blueBright(" You may need to run `npm install`.") + ? chalk.blue(" You may need to run `npm install`.") : ""), err ); @@ -117,7 +117,7 @@ class TemplateConfig { // remove special merge keys from object let savedForSpecialMerge = { - templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded + templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded, }; delete eleventyConfigApiMergingObject.templateFormatsAdded; diff --git a/src/UserConfig.js b/src/UserConfig.js index 27bac9aa3..0f1151444 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -228,9 +228,11 @@ class UserConfig { this.nunjucksTags[name] = bench.add(`"${name}" Nunjucks Custom Tag`, tagFn); } - addGlobalData(name, callback) { - name = this.getNamespacedName(name); - this.globalData[name] = callback; + addGlobalData(data) { + for (const [key, value] of Object.entries(data)) { + const name = this.getNamespacedName(key); + this.globalData[name] = value; + } } addTransform(name, callback) { @@ -331,7 +333,9 @@ class UserConfig { _normalizeTemplateFormats(templateFormats) { if (typeof templateFormats === "string") { - templateFormats = templateFormats.split(",").map(format => format.trim()); + templateFormats = templateFormats + .split(",") + .map((format) => format.trim()); } return templateFormats; } @@ -635,7 +639,7 @@ class UserConfig { Object.assign( { key: fileExtension, - extension: fileExtension + extension: fileExtension, }, options ) @@ -687,7 +691,7 @@ class UserConfig { dataExtensions: this.dataExtensions, extensionMap: this.extensionMap, quietMode: this.quietMode, - events: this.events + events: this.events, }; } } From e0dbea3092afd32116ae955cb13dfe460f47009b Mon Sep 17 00:00:00 2001 From: Mike Date: Sun, 19 Jul 2020 17:25:46 +1000 Subject: [PATCH 233/746] Pass template dir options to plugins --- src/TemplateConfig.js | 47 ++++++++++++++++++++++++++++++++++++------- src/UserConfig.js | 33 ++++++++---------------------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 041f92fa1..ffee9ab09 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -7,6 +7,7 @@ const EleventyBaseError = require("./EleventyBaseError"); const eleventyConfig = require("./EleventyConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); const deleteRequireCache = require("./Util/DeleteRequireCache"); +const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class EleventyConfigError extends EleventyBaseError {} @@ -22,7 +23,7 @@ class TemplateConfig { this.customRootConfig = null; } this.initializeRootConfig(); - this.config = this.mergeConfig(this.localProjectConfigPath); + this.config = this.mergeConfig(); } getLocalProjectConfigFile() { @@ -40,7 +41,7 @@ class TemplateConfig { reset() { eleventyConfig.reset(); this.initializeRootConfig(); - this.config = this.mergeConfig(this.localProjectConfigPath); + this.config = this.mergeConfig(); } getConfig() { @@ -61,7 +62,6 @@ class TemplateConfig { initializeRootConfig() { this.rootConfig = this.customRootConfig || require("./defaultConfig.js"); - if (typeof this.rootConfig === "function") { this.rootConfig = this.rootConfig(eleventyConfig); // debug( "rootConfig is a function, after calling, eleventyConfig is %o", eleventyConfig ); @@ -69,11 +69,39 @@ class TemplateConfig { debug("rootConfig %o", this.rootConfig); } - mergeConfig(localProjectConfigPath) { + processPlugins(localConfig) { + // eleventyConfig.plugins + eleventyConfig.plugins.forEach(({ plugin, options }) => { + eleventyConfig.dir = localConfig.dir; + // TODO support function.name in plugin config functions + debug("Adding plugin (unknown name: check your config file)."); + let pluginBench = aggregateBench.get("Configuration addPlugin"); + if (typeof plugin === "function") { + pluginBench.before(); + let configFunction = plugin; + configFunction(eleventyConfig, options); + pluginBench.after(); + } else if (plugin && plugin.configFunction) { + pluginBench.before(); + if (options && typeof options.init === "function") { + options.init.call(eleventyConfig, plugin.initArguments || {}); + } + + plugin.configFunction(eleventyConfig, options); + pluginBench.after(); + } else { + throw new UserConfigError( + "Invalid EleventyConfig.addPlugin signature. Should be a function or a valid Eleventy plugin object." + ); + } + }); + } + + mergeConfig() { let localConfig = {}; let path = TemplatePath.join( TemplatePath.getWorkingDir(), - localProjectConfigPath + this.localProjectConfigPath ); debug(`Merging config with ${path}`); @@ -86,7 +114,6 @@ class TemplateConfig { localConfig = require(path); // debug( "localConfig require return value: %o", localConfig ); - if (typeof localConfig === "function") { localConfig = localConfig(eleventyConfig); // debug( "localConfig is a function, after calling, eleventyConfig is %o", eleventyConfig ); @@ -113,11 +140,17 @@ class TemplateConfig { debug("Eleventy local project config file not found, skipping."); } + // Delay processing plugins until after the result of localConfig is returned + // But BEFORE the rest of the config options are merged + // this way we can pass directories and other template information to plugins + this.processPlugins(localConfig); + let eleventyConfigApiMergingObject = eleventyConfig.getMergingConfigObject(); // remove special merge keys from object + let savedForSpecialMerge = { - templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded + templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded, }; delete eleventyConfigApiMergingObject.templateFormatsAdded; diff --git a/src/UserConfig.js b/src/UserConfig.js index 9b9f1259b..e30bf0e9d 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -4,7 +4,6 @@ const semver = require("semver"); const { DateTime } = require("luxon"); const EleventyBaseError = require("./EleventyBaseError"); const bench = require("./BenchmarkManager").get("Configuration"); -const aggregateBench = require("./BenchmarkManager").get("Aggregate"); const debug = require("debug")("Eleventy:UserConfig"); const pkg = require("../package.json"); @@ -64,6 +63,8 @@ class UserConfig { this.dataExtensions = new Map(); this.quietMode = false; + + this.plugins = []; } versionCheck(expected) { @@ -264,27 +265,7 @@ class UserConfig { } addPlugin(plugin, options) { - // TODO support function.name in plugin config functions - debug("Adding plugin (unknown name: check your config file)."); - let pluginBench = aggregateBench.get("Configuration addPlugin"); - if (typeof plugin === "function") { - pluginBench.before(); - let configFunction = plugin; - configFunction(this, options); - pluginBench.after(); - } else if (plugin && plugin.configFunction) { - pluginBench.before(); - if (options && typeof options.init === "function") { - options.init.call(this, plugin.initArguments || {}); - } - - plugin.configFunction(this, options); - pluginBench.after(); - } else { - throw new UserConfigError( - "Invalid EleventyConfig.addPlugin signature. Should be a function or a valid Eleventy plugin object." - ); - } + this.plugins.push({ plugin, options }); } getNamespacedName(name) { @@ -325,7 +306,9 @@ class UserConfig { _normalizeTemplateFormats(templateFormats) { if (typeof templateFormats === "string") { - templateFormats = templateFormats.split(",").map(format => format.trim()); + templateFormats = templateFormats + .split(",") + .map((format) => format.trim()); } return templateFormats; } @@ -629,7 +612,7 @@ class UserConfig { Object.assign( { key: fileExtension, - extension: fileExtension + extension: fileExtension, }, options ) @@ -680,7 +663,7 @@ class UserConfig { dataExtensions: this.dataExtensions, extensionMap: this.extensionMap, quietMode: this.quietMode, - events: this.events + events: this.events, }; } } From cad14d15c721f2b28d47c89327f95b7e5c8ed6ea Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 1 Aug 2020 19:56:26 -0500 Subject: [PATCH 234/746] Fix Node 10 issue with syntax. --- src/TemplateData.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 7c297f3d0..da3f2590b 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -21,7 +21,9 @@ const bench = require("./BenchmarkManager").get("Data"); const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class FSExistsCache { - _cache = new Map(); + constructor() { + this._cache = new Map(); + } has(path) { return this._cache.has(path); } @@ -148,12 +150,12 @@ class TemplateData { let paths = [ `${dir}/**/*.json`, // covers .11tydata.json too `${dir}/**/*${this.config.jsDataFileSuffix}.cjs`, - `${dir}/**/*${this.config.jsDataFileSuffix}.js`, + `${dir}/**/*${this.config.jsDataFileSuffix}.js` ]; if (this.hasUserDataExtensions()) { let userPaths = this.getUserDataExtensions().map( - (extension) => `${dir}/**/*.${extension}` // covers .11tydata.{extension} too + extension => `${dir}/**/*.${extension}` // covers .11tydata.{extension} too ); paths = userPaths.concat(paths); } @@ -164,7 +166,7 @@ class TemplateData { async getTemplateJavaScriptDataFileGlob() { let dir = await this.getInputDir(); return TemplatePath.addLeadingDotSlashArray([ - `${dir}/**/*${this.config.jsDataFileSuffix}.js`, + `${dir}/**/*${this.config.jsDataFileSuffix}.js` ]); } @@ -200,7 +202,7 @@ class TemplateData { fsBench.before(); let paths = fastglob.sync(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, - dot: true, + dot: true }); fsBench.after(); @@ -287,7 +289,7 @@ class TemplateData { } // Filter out files we know don't exist to avoid overhead for checking - localDataPaths = localDataPaths.filter((path) => { + localDataPaths = localDataPaths.filter(path => { return this._fsExistsCache.exists(path); }); From 38002538e010f5d1556f9fccce6e240d6b6fe82f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 1 Aug 2020 20:18:02 -0500 Subject: [PATCH 235/746] =?UTF-8?q?Not=20=5Fquite=5F=20ready=20for=20this?= =?UTF-8?q?=20new=20syntax=20yet=E2=80=94Node=2010=20is=20still=20in=20mai?= =?UTF-8?q?ntenance=20mode.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TemplateCollection.js | 20 ++++++++++++-------- src/TemplateContent.js | 25 ++++++++++++++----------- src/TemplateData.js | 8 ++++---- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js index baae0e2c6..2ed16c6f9 100755 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -3,6 +3,12 @@ const Sortable = require("./Util/Sortable"); const TemplatePath = require("./TemplatePath"); class TemplateCollection extends Sortable { + constructor() { + super(); + + this._filteredByGlobsCache = new Map(); + } + // right now this is only used by the tests async _testAddTemplate(template) { let data = await template.getData(); @@ -28,13 +34,11 @@ class TemplateCollection extends Sortable { globs = [globs]; } - globs = globs.map((glob) => TemplatePath.addLeadingDotSlash(glob)); + globs = globs.map(glob => TemplatePath.addLeadingDotSlash(glob)); return globs; } - _filteredByGlobsCache = new Map(); - getFilteredByGlob(globs) { globs = this.getGlobs(globs); @@ -49,7 +53,7 @@ class TemplateCollection extends Sortable { this._filteredByGlobsCache = new Map(); } - let filtered = this.getAllSorted().filter((item) => { + let filtered = this.getAllSorted().filter(item => { if (multimatch([item.inputPath], globs).length) { return true; } @@ -62,19 +66,19 @@ class TemplateCollection extends Sortable { } getFilteredByTag(tagName) { - return this.getAllSorted().filter((item) => { + return this.getAllSorted().filter(item => { if (!tagName) { return true; } else if (Array.isArray(item.data.tags)) { - return item.data.tags.some((tag) => tag === tagName); + return item.data.tags.some(tag => tag === tagName); } return false; }); } getFilteredByTags(...tags) { - return this.getAllSorted().filter((item) => - tags.every((requiredTag) => { + return this.getAllSorted().filter(item => + tags.every(requiredTag => { const itemTags = item.data.tags; if (Array.isArray(itemTags)) { return itemTags.includes(requiredTag); diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 2c521022c..c14c71b98 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -112,13 +112,11 @@ class TemplateContent { this.frontMatter = { data: {}, content: "", - excerpt: "", + excerpt: "" }; } } - static _inputCache = new Map(); - static cache(path, content) { this._inputCache.set(TemplatePath.absolutePath(path), content); } @@ -139,7 +137,7 @@ class TemplateContent { let templateBenchmark = bench.get("Template Read"); templateBenchmark.before(); let content = TemplateContent.getCached(this.inputPath); - if(!content) { + if (!content) { content = await fs.readFile(this.inputPath, "utf-8"); TemplateContent.cache(this.inputPath, content); } @@ -194,10 +192,8 @@ class TemplateContent { } } - static _compileEngineCache = new Map(); - _getCompileCache(str, bypassMarkdown) { - let engineName = this.engine.getName() + "::" + (!!bypassMarkdown); + let engineName = this.engine.getName() + "::" + !!bypassMarkdown; let engineMap = TemplateContent._compileEngineCache.get(engineName); if (!engineMap) { engineMap = new Map(); @@ -205,7 +201,7 @@ class TemplateContent { } let cacheable = this.engine.cacheable; - return [ cacheable, str , engineMap ]; + return [cacheable, str, engineMap]; } async compile(str, bypassMarkdown) { @@ -218,8 +214,7 @@ class TemplateContent { ); try { - let [ cacheable, key, cache ] = - this._getCompileCache(str, bypassMarkdown); + let [cacheable, key, cache] = this._getCompileCache(str, bypassMarkdown); if (cacheable && cache.has(key)) { return cache.get(key); } @@ -227,7 +222,12 @@ class TemplateContent { // Compilation is async, so we eagerly cache a Promise that eventually // resolves to the compiled function let res; - cache.set(key, new Promise((resolve) => { res = resolve; })); + cache.set( + key, + new Promise(resolve => { + res = resolve; + }) + ); let templateBenchmark = bench.get("Template Compile"); templateBenchmark.before(); @@ -275,4 +275,7 @@ class TemplateContent { } } +TemplateContent._inputCache = new Map(); +TemplateContent._compileEngineCache = new Map(); + module.exports = TemplateContent; diff --git a/src/TemplateData.js b/src/TemplateData.js index da3f2590b..ca68f165c 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -52,6 +52,10 @@ class TemplateData { this.rawImports = {}; this.globalData = null; + + // It's common for data files not to exist, so we avoid going to the FS to + // re-check if they do via a quick-and-dirty cache. + this._fsExistsCache = new FSExistsCache(); } get extensionMap() { @@ -388,10 +392,6 @@ class TemplateData { } } - // It's common for data files not to exist, so we avoid going to the FS to - // re-check if they do via a quick-and-dirty cache. - _fsExistsCache = new FSExistsCache(); - async getDataValue(path, rawImports, ignoreProcessing) { let extension = TemplatePath.getExtension(path); From 79d09607d1c2b4bcf87b2c8297c240a1eb7459a2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 1 Aug 2020 20:18:16 -0500 Subject: [PATCH 236/746] Remove 8 and add 14 to Travis CI --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e7614af13..e1ce39e9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js node_js: - - 8 - 10 - 12 + - 14 before_script: - npm install script: npm run test @@ -15,4 +15,4 @@ os: - osx - windows env: - - YARN_GPG=no + - YARN_GPG=no \ No newline at end of file From 917c0d4e0ae54526e7d8775d623ea0910b2a8b66 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 1 Aug 2020 20:40:26 -0500 Subject: [PATCH 237/746] Use Node 10/12/14 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6303a4cf..6590a7dec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - node: ["8", "10", "12"] + node: ["10", "12", "14"] name: Node.js ${{ matrix.node }} on ${{ matrix.os }} steps: - uses: actions/checkout@v2 @@ -19,4 +19,4 @@ jobs: - run: npm install - run: npm test env: - YARN_GPG: no + YARN_GPG: no \ No newline at end of file From 232cb9b21fed147a1f1660696723fcd5fb060c4d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 1 Aug 2020 20:42:32 -0500 Subject: [PATCH 238/746] Adds GitHub Actions link from Readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index be5c35862..ca328e3df 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ Works with HTML, Markdown, Liquid, Nunjucks, Handlebars, Mustache, EJS, Haml, Pu - Support [11ty on Open Collective](https://opencollective.com/11ty) - [11ty on npm](https://www.npmjs.com/org/11ty) - [11ty on GitHub](https://github.com/11ty) -- [11ty/eleventy on Travis CI](https://travis-ci.org/11ty/eleventy) +- Continuous Integration: + - [Travis CI](https://travis-ci.org/11ty/eleventy) + - [GitHub Actions](https://github.com/11ty/eleventy/actions?query=workflow%3A.github%2Fworkflows%2Fci.yml) [![npm Version](https://img.shields.io/npm/v/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy) [![GitHub issues](https://img.shields.io/github/issues/11ty/eleventy.svg?style=for-the-badge)](https://github.com/11ty/eleventy/issues) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=for-the-badge)](https://github.com/prettier/prettier) [![npm Downloads](https://img.shields.io/npm/dt/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy) From 412d30075d14c1622fcfae6063a592e6ecf6dff2 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 6 Aug 2020 09:26:36 +1000 Subject: [PATCH 239/746] Update test --- test/TemplateConfigTest.js | 112 ++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 3ea61c2d2..61661e691 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -3,7 +3,7 @@ import md from "markdown-it"; import TemplateConfig from "../src/TemplateConfig"; import eleventyConfig from "../src/EleventyConfig"; -test("Template Config local config overrides base config", async t => { +test("Template Config local config overrides base config", async (t) => { let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" @@ -33,9 +33,9 @@ test("Template Config local config overrides base config", async t => { ); }); -test("Add liquid tag", t => { +test("Add liquid tag", (t) => { eleventyConfig.reset(); - eleventyConfig.addLiquidTag("myTagName", function() {}); + eleventyConfig.addLiquidTag("myTagName", function () {}); let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), @@ -45,9 +45,9 @@ test("Add liquid tag", t => { t.not(Object.keys(cfg.liquidTags).indexOf("myTagName"), -1); }); -test("Add nunjucks tag", t => { +test("Add nunjucks tag", (t) => { eleventyConfig.reset(); - eleventyConfig.addNunjucksTag("myNunjucksTag", function() {}); + eleventyConfig.addNunjucksTag("myNunjucksTag", function () {}); let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), @@ -57,9 +57,9 @@ test("Add nunjucks tag", t => { t.not(Object.keys(cfg.nunjucksTags).indexOf("myNunjucksTag"), -1); }); -test("Add liquid filter", t => { +test("Add liquid filter", (t) => { eleventyConfig.reset(); - eleventyConfig.addLiquidFilter("myFilterName", function(liquidEngine) { + eleventyConfig.addLiquidFilter("myFilterName", function (liquidEngine) { return {}; }); @@ -71,9 +71,9 @@ test("Add liquid filter", t => { t.not(Object.keys(cfg.liquidFilters).indexOf("myFilterName"), -1); }); -test("Add handlebars helper", t => { +test("Add handlebars helper", (t) => { eleventyConfig.reset(); - eleventyConfig.addHandlebarsHelper("myHelperName", function() {}); + eleventyConfig.addHandlebarsHelper("myHelperName", function () {}); let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), @@ -83,9 +83,9 @@ test("Add handlebars helper", t => { t.not(Object.keys(cfg.handlebarsHelpers).indexOf("myHelperName"), -1); }); -test("Add nunjucks filter", t => { +test("Add nunjucks filter", (t) => { eleventyConfig.reset(); - eleventyConfig.addNunjucksFilter("myFilterName", function() {}); + eleventyConfig.addNunjucksFilter("myFilterName", function () {}); let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), @@ -95,9 +95,9 @@ test("Add nunjucks filter", t => { t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); -test("Add universal filter", t => { +test("Add universal filter", (t) => { eleventyConfig.reset(); - eleventyConfig.addFilter("myFilterName", function() {}); + eleventyConfig.addFilter("myFilterName", function () {}); let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), @@ -108,10 +108,10 @@ test("Add universal filter", t => { t.not(Object.keys(cfg.handlebarsHelpers).indexOf("myFilterName"), -1); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); -test("Add namespaced universal filter", t => { +test("Add namespaced universal filter", (t) => { eleventyConfig.reset(); - eleventyConfig.namespace("testNamespace", function() { - eleventyConfig.addFilter("MyFilterName", function() {}); + eleventyConfig.namespace("testNamespace", function () { + eleventyConfig.addFilter("MyFilterName", function () {}); }); let templateCfg = new TemplateConfig( @@ -133,10 +133,10 @@ test("Add namespaced universal filter", t => { ); }); -test("Add namespaced universal filter using underscore", t => { +test("Add namespaced universal filter using underscore", (t) => { eleventyConfig.reset(); - eleventyConfig.namespace("testNamespace_", function() { - eleventyConfig.addFilter("myFilterName", function() {}); + eleventyConfig.namespace("testNamespace_", function () { + eleventyConfig.addFilter("myFilterName", function () {}); }); let templateCfg = new TemplateConfig( @@ -158,10 +158,10 @@ test("Add namespaced universal filter using underscore", t => { ); }); -test("Empty namespace", t => { +test("Empty namespace", (t) => { eleventyConfig.reset(); - eleventyConfig.namespace("", function() { - eleventyConfig.addNunjucksFilter("myFilterName", function() {}); + eleventyConfig.namespace("", function () { + eleventyConfig.addNunjucksFilter("myFilterName", function () {}); }); let templateCfg = new TemplateConfig( @@ -172,11 +172,11 @@ test("Empty namespace", t => { t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); -test("Nested Empty Inner namespace", t => { +test("Nested Empty Inner namespace", (t) => { eleventyConfig.reset(); - eleventyConfig.namespace("testNs", function() { - eleventyConfig.namespace("", function() { - eleventyConfig.addNunjucksFilter("myFilterName", function() {}); + eleventyConfig.namespace("testNs", function () { + eleventyConfig.namespace("", function () { + eleventyConfig.addNunjucksFilter("myFilterName", function () {}); }); }); @@ -188,11 +188,11 @@ test("Nested Empty Inner namespace", t => { t.not(Object.keys(cfg.nunjucksFilters).indexOf("testNsmyFilterName"), -1); }); -test("Nested Empty Outer namespace", t => { +test("Nested Empty Outer namespace", (t) => { eleventyConfig.reset(); - eleventyConfig.namespace("", function() { - eleventyConfig.namespace("testNs", function() { - eleventyConfig.addNunjucksFilter("myFilterName", function() {}); + eleventyConfig.namespace("", function () { + eleventyConfig.namespace("testNs", function () { + eleventyConfig.addNunjucksFilter("myFilterName", function () {}); }); }); @@ -207,10 +207,10 @@ test("Nested Empty Outer namespace", t => { // important for backwards compatibility with old // `module.exports = function (eleventyConfig, pluginNamespace) {` // plugin code -test("Non-string namespaces are ignored", t => { +test("Non-string namespaces are ignored", (t) => { eleventyConfig.reset(); - eleventyConfig.namespace(["lkdsjflksd"], function() { - eleventyConfig.addNunjucksFilter("myFilterName", function() {}); + eleventyConfig.namespace(["lkdsjflksd"], function () { + eleventyConfig.addNunjucksFilter("myFilterName", function () {}); }); let templateCfg = new TemplateConfig( @@ -221,11 +221,11 @@ test("Non-string namespaces are ignored", t => { t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); -test(".addPlugin oddity: I don’t think pluginNamespace was ever passed in here, but we don’t want this to break", t => { +test(".addPlugin oddity: I don’t think pluginNamespace was ever passed in here, but we don’t want this to break", (t) => { eleventyConfig.reset(); - eleventyConfig.addPlugin(function(eleventyConfig, pluginNamespace) { + eleventyConfig.addPlugin(function (eleventyConfig, pluginNamespace) { eleventyConfig.namespace(pluginNamespace, () => { - eleventyConfig.addNunjucksFilter("myFilterName", function() {}); + eleventyConfig.addNunjucksFilter("myFilterName", function () {}); }); }); @@ -237,7 +237,7 @@ test(".addPlugin oddity: I don’t think pluginNamespace was ever passed in here t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); -test("Test url universal filter with custom pathPrefix (no slash)", t => { +test("Test url universal filter with custom pathPrefix (no slash)", (t) => { let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" @@ -247,7 +247,7 @@ test("Test url universal filter with custom pathPrefix (no slash)", t => { t.is(cfg.pathPrefix, "/testdirectory/"); }); -test("setTemplateFormats(string)", t => { +test("setTemplateFormats(string)", (t) => { eleventyConfig.reset(); // 0.11.0 removes dupes eleventyConfig.setTemplateFormats("ejs,njk, liquid, njk"); @@ -260,7 +260,7 @@ test("setTemplateFormats(string)", t => { t.deepEqual(cfg.templateFormats, ["ejs", "njk", "liquid"]); }); -test("setTemplateFormats(array)", t => { +test("setTemplateFormats(array)", (t) => { eleventyConfig.reset(); eleventyConfig.setTemplateFormats(["ejs", "njk", "liquid"]); @@ -272,7 +272,7 @@ test("setTemplateFormats(array)", t => { t.deepEqual(cfg.templateFormats, ["ejs", "njk", "liquid"]); }); -test("setTemplateFormats(array, size 1)", t => { +test("setTemplateFormats(array, size 1)", (t) => { eleventyConfig.reset(); eleventyConfig.setTemplateFormats(["liquid"]); @@ -284,7 +284,7 @@ test("setTemplateFormats(array, size 1)", t => { t.deepEqual(cfg.templateFormats, ["liquid"]); }); -test("setTemplateFormats(empty array)", t => { +test("setTemplateFormats(empty array)", (t) => { eleventyConfig.reset(); eleventyConfig.setTemplateFormats([]); @@ -296,7 +296,7 @@ test("setTemplateFormats(empty array)", t => { t.deepEqual(cfg.templateFormats, []); }); -test("setTemplateFormats(null)", t => { +test("setTemplateFormats(null)", (t) => { eleventyConfig.reset(); eleventyConfig.setTemplateFormats(null); @@ -308,7 +308,7 @@ test("setTemplateFormats(null)", t => { t.true(cfg.templateFormats.length > 0); }); -test("multiple setTemplateFormats calls", t => { +test("multiple setTemplateFormats calls", (t) => { eleventyConfig.reset(); eleventyConfig.setTemplateFormats("njk"); eleventyConfig.setTemplateFormats("pug"); @@ -321,7 +321,7 @@ test("multiple setTemplateFormats calls", t => { t.deepEqual(cfg.templateFormats, ["pug"]); }); -test("addTemplateFormats()", t => { +test("addTemplateFormats()", (t) => { eleventyConfig.reset(); eleventyConfig.addTemplateFormats("vue"); @@ -334,7 +334,7 @@ test("addTemplateFormats()", t => { t.deepEqual(cfg.templateFormats, ["md", "njk", "vue"]); }); -test("both setTemplateFormats and addTemplateFormats", t => { +test("both setTemplateFormats and addTemplateFormats", (t) => { // Template Formats can come from three places // defaultConfig.js config API (not used yet) // defaultConfig.js config return object @@ -353,7 +353,7 @@ test("both setTemplateFormats and addTemplateFormats", t => { t.deepEqual(cfg.templateFormats, ["pug", "vue"]); }); -test("libraryOverrides", t => { +test("libraryOverrides", (t) => { let mdLib = md(); eleventyConfig.setLibrary("md", mdLib); @@ -368,22 +368,22 @@ test("libraryOverrides", t => { t.deepEqual(mdLib, cfg.libraryOverrides.md); }); -test("addGlobalData", t => { +test("addGlobalData", (t) => { eleventyConfig.reset(); - eleventyConfig.addGlobalData("buildTime", function() { - return new Date(); + eleventyConfig.addGlobalData({ + function: () => new Date(), }); let templateCfg = new TemplateConfig( - require("../config.js"), + require("../src/defaultConfig.js"), "./test/stubs/config.js" ); let cfg = templateCfg.getConfig(); - t.not(Object.keys(cfg.globalData).indexOf("buildTime"), -1); + t.not(Object.keys(cfg.globalData).indexOf("function"), -1); }); -test("Properly throws error on missing module #182", t => { - t.throws(function() { +test("Properly throws error on missing module #182", (t) => { + t.throws(function () { new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/broken-config.js" @@ -391,8 +391,8 @@ test("Properly throws error on missing module #182", t => { }); }); -test("Properly throws error when config returns a Promise", t => { - t.throws(function() { +test("Properly throws error when config returns a Promise", (t) => { + t.throws(function () { new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config-promise.js" @@ -400,7 +400,7 @@ test("Properly throws error when config returns a Promise", t => { }); }); -test(".addWatchTarget adds a watch target", t => { +test(".addWatchTarget adds a watch target", (t) => { eleventyConfig.reset(); eleventyConfig.addWatchTarget("/testdirectory/"); From c8e628aa79b0cdcd16da1965fc4213769329b1fe Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 6 Aug 2020 12:00:38 +1000 Subject: [PATCH 240/746] Remove Merge master --- eleventy | 1 - src/TemplateConfig.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 120000 eleventy diff --git a/eleventy b/eleventy deleted file mode 120000 index 4c9aba5cb..000000000 --- a/eleventy +++ /dev/null @@ -1 +0,0 @@ -/eleventy \ No newline at end of file diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 16a20b2b4..f8b9776be 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -104,7 +104,7 @@ class TemplateConfig { throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + (err.message.includes("Cannot find module") - ? chalk.blue(" You may need to run `npm install`.") + ? chalk.blueBright(" You may need to run `npm install`.") : ""), err ); From bad56c0260a535cfba9179b40209900beee59fb3 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 6 Aug 2020 12:01:34 +1000 Subject: [PATCH 241/746] Update src/TemplateConfig.js --- src/TemplateConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index f8b9776be..041f92fa1 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -117,7 +117,7 @@ class TemplateConfig { // remove special merge keys from object let savedForSpecialMerge = { - templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded, + templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded }; delete eleventyConfigApiMergingObject.templateFormatsAdded; From cdb1191360a53ba7defc2b93b1ec2895d031c368 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 10 Aug 2020 22:51:06 -0500 Subject: [PATCH 242/746] Update a few dependencies for 1.0 --- package.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 0f908df7d..6512f17f4 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.11.0", + "version": "1.0.0-beta.0", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -8,7 +8,7 @@ "main": "src/Eleventy.js", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "type": "opencollective", @@ -76,15 +76,15 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.1", - "ava": "^3.8.2", + "ava": "^3.11.1", "husky": "^4.2.5", "ink-docstrap": "1.3.2", - "js-yaml": "^3.13.1", - "jsdoc": "3.6.4", - "lint-staged": "^10.2.2", + "js-yaml": "^3.14.0", + "jsdoc": "3.6.5", + "lint-staged": "^10.2.11", "markdown-it-emoji": "^1.4.0", "node-sass": "^4.14.1", - "nyc": "^15.0.1", + "nyc": "^15.1.0", "prettier": "^2.0.5", "rimraf": "^3.0.2", "toml": "^3.0.0", @@ -94,20 +94,20 @@ }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", - "browser-sync": "^2.26.7", + "browser-sync": "^2.26.12", "chalk": "^3.0.0", - "chokidar": "^3.4.0", + "chokidar": "^3.4.2", "debug": "^4.1.1", "dependency-graph": "^0.9.0", "ejs": "^2.7.4", - "fast-glob": "^3.2.2", + "fast-glob": "^3.2.4", "fs-extra": "^8.1.0", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", "handlebars": "^4.7.6", "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "luxon": "^1.24.1", "markdown-it": "^10.0.0", "minimist": "^1.2.5", @@ -115,14 +115,14 @@ "multimatch": "^4.0.0", "mustache": "^2.3.2", "normalize-path": "^3.0.0", - "nunjucks": "^3.2.1", + "nunjucks": "^3.2.2", "parse-filepath": "^1.0.2", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^2.0.4", "recursive-copy": "^2.0.10", "semver": "^7.3.2", - "slugify": "^1.4.0", + "slugify": "^1.4.5", "time-require": "^0.1.2", "valid-url": "^1.0.9" }, From b2db452194a56abd1ea4c31ef3098e09e3da7092 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 10 Aug 2020 22:54:50 -0500 Subject: [PATCH 243/746] Two major dep updates both moving to Node 10+ --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6512f17f4..705ecd0b5 100755 --- a/package.json +++ b/package.json @@ -95,13 +95,13 @@ "dependencies": { "@11ty/dependency-tree": "^1.0.0", "browser-sync": "^2.26.12", - "chalk": "^3.0.0", + "chalk": "^4.1.0", "chokidar": "^3.4.2", "debug": "^4.1.1", "dependency-graph": "^0.9.0", "ejs": "^2.7.4", "fast-glob": "^3.2.4", - "fs-extra": "^8.1.0", + "fs-extra": "^9.0.1", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", "handlebars": "^4.7.6", From 29939d6d89acb04a64d7c24697f4de08737db8f5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 10 Aug 2020 22:56:15 -0500 Subject: [PATCH 244/746] Fixes #669 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 705ecd0b5..3dee24a87 100755 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "liquidjs": "^6.4.3", "lodash": "^4.17.19", "luxon": "^1.24.1", - "markdown-it": "^10.0.0", + "markdown-it": "^11.0.0", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^4.0.0", From ac77a7b8d3ff33e714daf8fcb0af03dcf557c650 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Aug 2020 15:03:00 -0500 Subject: [PATCH 245/746] Generalize the title to fit with Discord chat --- CODE_OF_CONDUCT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b3824062e..010193058 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,4 +1,4 @@ -# Contributor Covenant Code of Conduct +# Eleventy Community Code of Conduct ## Our Pledge @@ -26,7 +26,7 @@ Examples of unacceptable behavior by participants include: Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, chat messages, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope From 8fa5f34b1791b23542eb1552d38f056cb22df19c Mon Sep 17 00:00:00 2001 From: Valtteri Laitinen Date: Wed, 12 Aug 2020 17:50:03 +0300 Subject: [PATCH 246/746] Update links to use 11ty.dev --- README.md | 8 ++++---- docs/collections.md | 2 +- docs/copy.md | 2 +- docs/data.md | 2 +- docs/engines.md | 2 +- docs/engines/ejs.md | 2 +- docs/engines/haml.md | 2 +- docs/engines/handlebars.md | 2 +- docs/engines/html.md | 2 +- docs/engines/jstl.md | 2 +- docs/engines/liquid.md | 2 +- docs/engines/markdown.md | 2 +- docs/engines/mustache.md | 2 +- docs/engines/nunjucks.md | 2 +- docs/engines/pug.md | 2 +- docs/filters.md | 2 +- docs/install-local.md | 2 +- docs/layouts.md | 2 +- docs/pagination.md | 2 +- docs/permalinks.md | 2 +- docs/pitfalls.md | 2 +- docs/plugins.md | 2 +- 22 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index ca328e3df..a693193eb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

eleventy Logo

+

eleventy Logo

# eleventy 🕚⚡️ @@ -6,7 +6,7 @@ A simpler static site generator. An alternative to Jekyll. Written in JavaScript Works with HTML, Markdown, Liquid, Nunjucks, Handlebars, Mustache, EJS, Haml, Pug, and JavaScript Template Literals. -## ➡ [Documentation](https://www.11ty.io/docs/) +## ➡ [Documentation](https://www.11ty.dev/docs/) - Please star [this repo on GitHub](https://github.com/11ty/eleventy/)! - Follow us on Twitter [@eleven_ty](https://twitter.com/eleven_ty) @@ -25,7 +25,7 @@ Works with HTML, Markdown, Liquid, Nunjucks, Handlebars, Mustache, EJS, Haml, Pu npm install @11ty/eleventy --save-dev ``` -Read our [Getting Started guide](https://www.11ty.io/docs/getting-started/). +Read our [Getting Started guide](https://www.11ty.dev/docs/getting-started/). ## Tests @@ -47,4 +47,4 @@ npm run test ## Plugins -See the [official docs on plugins](https://www.11ty.io/docs/plugins/). +See the [official docs on plugins](https://www.11ty.dev/docs/plugins/). diff --git a/docs/collections.md b/docs/collections.md index 586fb702e..3e97b0f37 100644 --- a/docs/collections.md +++ b/docs/collections.md @@ -1,3 +1,3 @@ # Collections (and Tags) -Moved to [https://www.11ty.io/docs/collections/](https://www.11ty.io/docs/collections/). +Moved to [https://www.11ty.dev/docs/collections/](https://www.11ty.dev/docs/collections/). diff --git a/docs/copy.md b/docs/copy.md index 15d456c37..d0f659c5a 100644 --- a/docs/copy.md +++ b/docs/copy.md @@ -1,3 +1,3 @@ # Pass-through File Copy -Moved to [https://www.11ty.io/docs/copy/](https://www.11ty.io/docs/copy/). +Moved to [https://www.11ty.dev/docs/copy/](https://www.11ty.dev/docs/copy/). diff --git a/docs/data.md b/docs/data.md index 3c55b97a6..66cf14b5d 100644 --- a/docs/data.md +++ b/docs/data.md @@ -1,3 +1,3 @@ # Using Data -Moved to [https://www.11ty.io/docs/data/](https://www.11ty.io/docs/data/). +Moved to [https://www.11ty.dev/docs/data/](https://www.11ty.dev/docs/data/). diff --git a/docs/engines.md b/docs/engines.md index 19f1e98bd..c48c0f098 100644 --- a/docs/engines.md +++ b/docs/engines.md @@ -1,3 +1,3 @@ # Changing a Template’s Rendering Engine -Moved to [https://www.11ty.io/docs/languages/](https://www.11ty.io/docs/languages/). +Moved to [https://www.11ty.dev/docs/languages/](https://www.11ty.dev/docs/languages/). diff --git a/docs/engines/ejs.md b/docs/engines/ejs.md index af42d4ec4..17ceae551 100644 --- a/docs/engines/ejs.md +++ b/docs/engines/ejs.md @@ -1,3 +1,3 @@ # EJS -Moved to [https://www.11ty.io/docs/languages/ejs/](https://www.11ty.io/docs/languages/ejs/). +Moved to [https://www.11ty.dev/docs/languages/ejs/](https://www.11ty.dev/docs/languages/ejs/). diff --git a/docs/engines/haml.md b/docs/engines/haml.md index 4a0a189dc..be852296a 100644 --- a/docs/engines/haml.md +++ b/docs/engines/haml.md @@ -1,3 +1,3 @@ # HAML -Moved to [https://www.11ty.io/docs/languages/haml/](https://www.11ty.io/docs/languages/haml/). +Moved to [https://www.11ty.dev/docs/languages/haml/](https://www.11ty.dev/docs/languages/haml/). diff --git a/docs/engines/handlebars.md b/docs/engines/handlebars.md index 4b3c0e1d8..6ff0fde52 100644 --- a/docs/engines/handlebars.md +++ b/docs/engines/handlebars.md @@ -1,3 +1,3 @@ # Handlebars -Moved to [https://www.11ty.io/docs/languages/handlebars/](https://www.11ty.io/docs/languages/handlebars/). +Moved to [https://www.11ty.dev/docs/languages/handlebars/](https://www.11ty.dev/docs/languages/handlebars/). diff --git a/docs/engines/html.md b/docs/engines/html.md index e33147164..82ed03731 100644 --- a/docs/engines/html.md +++ b/docs/engines/html.md @@ -1,3 +1,3 @@ # HTML -Moved to [https://www.11ty.io/docs/languages/html/](https://www.11ty.io/docs/languages/html/). +Moved to [https://www.11ty.dev/docs/languages/html/](https://www.11ty.dev/docs/languages/html/). diff --git a/docs/engines/jstl.md b/docs/engines/jstl.md index 99bc93232..b64912b1e 100644 --- a/docs/engines/jstl.md +++ b/docs/engines/jstl.md @@ -1,3 +1,3 @@ # JavaScript Template Literals -Moved to [https://www.11ty.io/docs/languages/jstl/](https://www.11ty.io/docs/languages/jstl/). +Moved to [https://www.11ty.dev/docs/languages/jstl/](https://www.11ty.dev/docs/languages/jstl/). diff --git a/docs/engines/liquid.md b/docs/engines/liquid.md index 6f58d5c7f..cb7d8ddb4 100644 --- a/docs/engines/liquid.md +++ b/docs/engines/liquid.md @@ -1,3 +1,3 @@ # Liquid -Moved to [https://www.11ty.io/docs/languages/liquid/](https://www.11ty.io/docs/languages/liquid/). +Moved to [https://www.11ty.dev/docs/languages/liquid/](https://www.11ty.dev/docs/languages/liquid/). diff --git a/docs/engines/markdown.md b/docs/engines/markdown.md index cd5ef9677..c92a89a14 100644 --- a/docs/engines/markdown.md +++ b/docs/engines/markdown.md @@ -1,3 +1,3 @@ # Markdown -Moved to [https://www.11ty.io/docs/languages/markdown/](https://www.11ty.io/docs/languages/markdown/). +Moved to [https://www.11ty.dev/docs/languages/markdown/](https://www.11ty.dev/docs/languages/markdown/). diff --git a/docs/engines/mustache.md b/docs/engines/mustache.md index 798bb31b9..7577ec94f 100644 --- a/docs/engines/mustache.md +++ b/docs/engines/mustache.md @@ -1,3 +1,3 @@ # Mustache -Moved to [https://www.11ty.io/docs/languages/mustache/](https://www.11ty.io/docs/languages/mustache/). +Moved to [https://www.11ty.dev/docs/languages/mustache/](https://www.11ty.dev/docs/languages/mustache/). diff --git a/docs/engines/nunjucks.md b/docs/engines/nunjucks.md index 13d0d91cc..d052796d4 100644 --- a/docs/engines/nunjucks.md +++ b/docs/engines/nunjucks.md @@ -1,3 +1,3 @@ # Nunjucks -Moved to [https://www.11ty.io/docs/languages/nunjucks/](https://www.11ty.io/docs/languages/nunjucks/). +Moved to [https://www.11ty.dev/docs/languages/nunjucks/](https://www.11ty.dev/docs/languages/nunjucks/). diff --git a/docs/engines/pug.md b/docs/engines/pug.md index 2b7f95546..6ec9afabe 100644 --- a/docs/engines/pug.md +++ b/docs/engines/pug.md @@ -1,3 +1,3 @@ # Pug (formerly Jade) -Moved to [https://www.11ty.io/docs/languages/pug/](https://www.11ty.io/docs/languages/pug/). +Moved to [https://www.11ty.dev/docs/languages/pug/](https://www.11ty.dev/docs/languages/pug/). diff --git a/docs/filters.md b/docs/filters.md index cff7d91dc..ce4688b2d 100644 --- a/docs/filters.md +++ b/docs/filters.md @@ -1,3 +1,3 @@ # Filters, Tags, etc. -Moved to [https://www.11ty.io/docs/filters/](https://www.11ty.io/docs/filters/). +Moved to [https://www.11ty.dev/docs/filters/](https://www.11ty.dev/docs/filters/). diff --git a/docs/install-local.md b/docs/install-local.md index dbfa1457b..82534b29e 100644 --- a/docs/install-local.md +++ b/docs/install-local.md @@ -1,3 +1,3 @@ # Install locally -Moved to [https://www.11ty.io/docs/local-installation/](https://www.11ty.io/docs/local-installation/). +Moved to [https://www.11ty.dev/docs/local-installation/](https://www.11ty.dev/docs/local-installation/). diff --git a/docs/layouts.md b/docs/layouts.md index 8c9fdf58e..be2fb7c99 100644 --- a/docs/layouts.md +++ b/docs/layouts.md @@ -1,3 +1,3 @@ # Layouts -Moved to [https://www.11ty.io/docs/layouts/](https://www.11ty.io/docs/layouts/). +Moved to [https://www.11ty.dev/docs/layouts/](https://www.11ty.dev/docs/layouts/). diff --git a/docs/pagination.md b/docs/pagination.md index 9be309a55..d3b011d2c 100644 --- a/docs/pagination.md +++ b/docs/pagination.md @@ -1,3 +1,3 @@ # Pagination -Moved to [https://www.11ty.io/docs/pagination/](https://www.11ty.io/docs/pagination/). +Moved to [https://www.11ty.dev/docs/pagination/](https://www.11ty.dev/docs/pagination/). diff --git a/docs/permalinks.md b/docs/permalinks.md index c55076e16..12dadee2f 100644 --- a/docs/permalinks.md +++ b/docs/permalinks.md @@ -1,3 +1,3 @@ # Permalinks -Moved to [https://www.11ty.io/docs/permalinks/](https://www.11ty.io/docs/permalinks/). +Moved to [https://www.11ty.dev/docs/permalinks/](https://www.11ty.dev/docs/permalinks/). diff --git a/docs/pitfalls.md b/docs/pitfalls.md index b39aca287..cac000af1 100644 --- a/docs/pitfalls.md +++ b/docs/pitfalls.md @@ -1,3 +1,3 @@ # Common Eleventy Pitfalls -Moved to [https://www.11ty.io/docs/pitfalls/](https://www.11ty.io/docs/pitfalls/). +Moved to [https://www.11ty.dev/docs/pitfalls/](https://www.11ty.dev/docs/pitfalls/). diff --git a/docs/plugins.md b/docs/plugins.md index 299c6b4ac..34295199b 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -1,3 +1,3 @@ # Plugins -Moved to [https://www.11ty.io/docs/plugins/](https://www.11ty.io/docs/plugins/). +Moved to [https://www.11ty.dev/docs/plugins/](https://www.11ty.dev/docs/plugins/). From 554d7928308d52c128a88e716600cde8ff740d90 Mon Sep 17 00:00:00 2001 From: Gobeli Date: Mon, 17 Aug 2020 16:38:45 +0200 Subject: [PATCH 247/746] add async EventEmitter --- src/Eleventy.js | 6 ++-- src/UserConfig.js | 10 ++++--- src/Util/AsyncEventEmitter.js | 22 +++++++++++++++ test/EleventyConfigTest.js | 52 ++++++++++++++++++++++++----------- 4 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 src/Util/AsyncEventEmitter.js diff --git a/src/Eleventy.js b/src/Eleventy.js index 8622d425d..62ddd6576 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -459,7 +459,7 @@ Arguments: return; } - this.config.events.emit("beforeWatch"); + await this.config.events.emit("beforeWatch"); this.watchManager.setBuildRunning(); @@ -737,13 +737,13 @@ Arguments: EleventyErrorHandler.logger = this.logger; } - this.config.events.emit("beforeBuild"); + await this.config.events.emit("beforeBuild"); try { let promise = this.writer.write(); ret = await promise; - this.config.events.emit("afterBuild"); + await this.config.events.emit("afterBuild"); } catch (e) { EleventyErrorHandler.initialMessage( "Problem writing Eleventy templates", diff --git a/src/UserConfig.js b/src/UserConfig.js index 9b9f1259b..b8d8a8cd5 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -1,7 +1,7 @@ -const EventEmitter = require("events"); const chalk = require("chalk"); const semver = require("semver"); const { DateTime } = require("luxon"); +const EventEmitter = require("./Util/AsyncEventEmitter"); const EleventyBaseError = require("./EleventyBaseError"); const bench = require("./BenchmarkManager").get("Configuration"); const aggregateBench = require("./BenchmarkManager").get("Aggregate"); @@ -325,7 +325,9 @@ class UserConfig { _normalizeTemplateFormats(templateFormats) { if (typeof templateFormats === "string") { - templateFormats = templateFormats.split(",").map(format => format.trim()); + templateFormats = templateFormats + .split(",") + .map((format) => format.trim()); } return templateFormats; } @@ -629,7 +631,7 @@ class UserConfig { Object.assign( { key: fileExtension, - extension: fileExtension + extension: fileExtension, }, options ) @@ -680,7 +682,7 @@ class UserConfig { dataExtensions: this.dataExtensions, extensionMap: this.extensionMap, quietMode: this.quietMode, - events: this.events + events: this.events, }; } } diff --git a/src/Util/AsyncEventEmitter.js b/src/Util/AsyncEventEmitter.js new file mode 100644 index 000000000..f43dd3e8d --- /dev/null +++ b/src/Util/AsyncEventEmitter.js @@ -0,0 +1,22 @@ +const EventEmitter = require("events"); +const lodashGet = require("lodash/get"); +const lodashIsEmpty = require("lodash/isEmpty"); + +class AsyncEventEmitter extends EventEmitter { + async emit(type, ...args) { + const handler = lodashGet(this._events, type); + if (lodashIsEmpty(handler) && typeof handler !== "function") { + return; + } + + if (typeof handler === "function") { + await handler.apply(this, args); + } else { + await Promise.all(handler.map((h) => h.apply(this, args))); + } + + return true; + } +} + +module.exports = AsyncEventEmitter; diff --git a/test/EleventyConfigTest.js b/test/EleventyConfigTest.js index 5b49e6789..64c301ca2 100644 --- a/test/EleventyConfigTest.js +++ b/test/EleventyConfigTest.js @@ -3,8 +3,8 @@ import eleventyConfig from "../src/EleventyConfig"; // more in TemplateConfigTest.js -test.cb("Events", t => { - eleventyConfig.on("testEvent", function(arg1, arg2, arg3) { +test.cb("Events", (t) => { + eleventyConfig.on("testEvent", function (arg1, arg2, arg3) { t.is(arg1, "arg1"); t.is(arg2, "arg2"); t.is(arg3, "arg3"); @@ -14,30 +14,50 @@ test.cb("Events", t => { eleventyConfig.emit("testEvent", "arg1", "arg2", "arg3"); }); -test("Add Collections", t => { - eleventyConfig.addCollection("myCollection", function(collection) {}); +test.cb("Async Events", (t) => { + let arg1; + + eleventyConfig.on( + "asyncTestEvent", + (_arg1) => + new Promise((resolve) => { + setTimeout(() => { + arg1 = _arg1; + resolve(); + }, 10); + }) + ); + + eleventyConfig.emit("asyncTestEvent", "arg1").then(() => { + t.is(arg1, "arg1"); + t.end(); + }); +}); + +test("Add Collections", (t) => { + eleventyConfig.addCollection("myCollection", function (collection) {}); t.deepEqual(Object.keys(eleventyConfig.getCollections()), ["myCollection"]); }); -test("Add Collections throws error on key collision", t => { - eleventyConfig.addCollection("myCollectionCollision", function( +test("Add Collections throws error on key collision", (t) => { + eleventyConfig.addCollection("myCollectionCollision", function ( collection ) {}); t.throws(() => { - eleventyConfig.addCollection("myCollectionCollision", function( + eleventyConfig.addCollection("myCollectionCollision", function ( collection ) {}); }); }); -test("Set manual Pass-through File Copy (single call)", t => { +test("Set manual Pass-through File Copy (single call)", (t) => { eleventyConfig.addPassthroughCopy("img"); t.is(eleventyConfig.passthroughCopies["img"], true); }); -test("Set manual Pass-through File Copy (chained calls)", t => { +test("Set manual Pass-through File Copy (chained calls)", (t) => { eleventyConfig .addPassthroughCopy("css") .addPassthroughCopy("js") @@ -50,10 +70,10 @@ test("Set manual Pass-through File Copy (chained calls)", t => { t.is(eleventyConfig.passthroughCopies["./src/empty"], "./"); }); -test("Set manual Pass-through File Copy (glob patterns)", t => { +test("Set manual Pass-through File Copy (glob patterns)", (t) => { eleventyConfig.addPassthroughCopy({ "./src/static/**/*": "renamed", - "./src/markdown/*.md": "" + "./src/markdown/*.md": "", }); // does not exist @@ -65,27 +85,27 @@ test("Set manual Pass-through File Copy (glob patterns)", t => { t.is(eleventyConfig.passthroughCopies["./src/markdown/*.md"], ""); }); -test("Set Template Formats (string)", t => { +test("Set Template Formats (string)", (t) => { eleventyConfig.setTemplateFormats("ejs, njk, liquid"); t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid"]); }); -test("Set Template Formats (array)", t => { +test("Set Template Formats (array)", (t) => { eleventyConfig.setTemplateFormats(["ejs", "njk", "liquid"]); t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid"]); }); -test("Set Template Formats (js passthrough copy)", t => { +test("Set Template Formats (js passthrough copy)", (t) => { eleventyConfig.setTemplateFormats("ejs, njk, liquid, js"); t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid", "js"]); }); -test("Set Template Formats (11ty.js)", t => { +test("Set Template Formats (11ty.js)", (t) => { eleventyConfig.setTemplateFormats("ejs, njk, liquid, 11ty.js"); t.deepEqual(eleventyConfig.templateFormats, [ "ejs", "njk", "liquid", - "11ty.js" + "11ty.js", ]); }); From 08334a88a87b5a075f2b5cbc9d941083b0c6352d Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 2 Sep 2020 04:04:46 +1000 Subject: [PATCH 248/746] back to orig sig --- src/UserConfig.js | 9 ++++----- test/TemplateConfigTest.js | 4 +--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index 0f1151444..fff80a4e2 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -228,11 +228,10 @@ class UserConfig { this.nunjucksTags[name] = bench.add(`"${name}" Nunjucks Custom Tag`, tagFn); } - addGlobalData(data) { - for (const [key, value] of Object.entries(data)) { - const name = this.getNamespacedName(key); - this.globalData[name] = value; - } + addGlobalData(name, data) { + name = this.getNamespacedName(name); + this.globalData[name] = data; + return this; } addTransform(name, callback) { diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 61661e691..c1633015c 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -370,9 +370,7 @@ test("libraryOverrides", (t) => { test("addGlobalData", (t) => { eleventyConfig.reset(); - eleventyConfig.addGlobalData({ - function: () => new Date(), - }); + eleventyConfig.addGlobalData("function", () => new Date()); let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), From 0bf0581e9a6f8a3a6aecb72ba130dce0bb631faf Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 2 Sep 2020 04:19:26 +1000 Subject: [PATCH 249/746] CI timed out so: empty commit From a37a5c675d97268dab50e83e4692e152be9fbf0d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 4 Sep 2020 13:24:59 -0500 Subject: [PATCH 250/746] As a fast follow to #469, we upgrade the Liquid dependency even more! --- package.json | 18 +- test/TemplateRenderLiquidTest.js | 323 ++++++++++++++++--------------- 2 files changed, 171 insertions(+), 170 deletions(-) diff --git a/package.json b/package.json index 427cdc06d..7a26f03f5 100755 --- a/package.json +++ b/package.json @@ -76,21 +76,21 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", "@ava/babel": "^1.0.1", - "ava": "^3.11.1", + "ava": "^3.12.1", "husky": "^4.2.5", "ink-docstrap": "1.3.2", "js-yaml": "^3.14.0", "jsdoc": "3.6.5", - "lint-staged": "^10.2.11", + "lint-staged": "^10.3.0", "markdown-it-emoji": "^1.4.0", "node-sass": "^4.14.1", "nyc": "^15.1.0", - "prettier": "^2.0.5", + "prettier": "^2.1.1", "rimraf": "^3.0.2", "toml": "^3.0.0", "viperhtml": "^2.17.1", - "vue": "^2.6.11", - "vue-server-renderer": "^2.6.11" + "vue": "^2.6.12", + "vue-server-renderer": "^2.6.12" }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", @@ -106,9 +106,9 @@ "hamljs": "^0.6.2", "handlebars": "^4.7.6", "javascript-stringify": "^2.0.1", - "liquidjs": "^9.11.9", - "lodash": "^4.17.19", - "luxon": "^1.24.1", + "liquidjs": "^9.15.0", + "lodash": "^4.17.20", + "luxon": "^1.25.0", "markdown-it": "^11.0.0", "minimist": "^1.2.5", "moo": "^0.5.1", @@ -120,7 +120,7 @@ "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^2.0.4", - "recursive-copy": "^2.0.10", + "recursive-copy": "^2.0.11", "semver": "^7.3.2", "slugify": "^1.4.5", "time-require": "^0.1.2", diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 32c14080d..8115b0f82 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -9,33 +9,33 @@ function getNewTemplateRender(name, inputDir) { } async function getPromise(resolveTo) { - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(resolveTo); }); }); } // Liquid -test("Liquid", t => { +test("Liquid", (t) => { t.is(getNewTemplateRender("liquid").getEngineName(), "liquid"); }); -test("Liquid Render Addition", async t => { +test("Liquid Render Addition", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ number | plus: 1 }}

" ); t.is(await fn({ number: 1 }), "

2

"); }); -test("Liquid Render Raw", async t => { +test("Liquid Render Raw", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{% raw %}{{name}}{% endraw %}

" ); t.is(await fn({ name: "tim" }), "

{{name}}

"); }); -test("Liquid Render Raw Multiline", async t => { +test("Liquid Render Raw Multiline", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( `

{% raw %} {{name}} @@ -49,14 +49,14 @@ test("Liquid Render Raw Multiline", async t => { ); }); -test("Liquid Render (with Helper)", async t => { +test("Liquid Render (with Helper)", async (t) => { let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{name | capitalize}}

" ); t.is(await fn({ name: "tim" }), "

Tim

"); }); -test("Liquid Render Include", async t => { +test("Liquid Render Include", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" @@ -69,7 +69,7 @@ test("Liquid Render Include", async t => { t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Relative Include", async t => { +test("Liquid Render Relative Include", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" @@ -82,7 +82,7 @@ test("Liquid Render Relative Include", async t => { t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Relative (current dir) Include", async t => { +test("Liquid Render Relative (current dir) Include", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/relative-liquid/does_not_exist_and_thats_ok.liquid", "./test/stubs/" @@ -90,7 +90,7 @@ test("Liquid Render Relative (current dir) Include", async t => { t.is(await fn(), "

TIME IS RELATIVE.

"); }); -test("Liquid Render Relative (parent dir) Include", async t => { +test("Liquid Render Relative (parent dir) Include", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/relative-liquid/dir/does_not_exist_and_thats_ok.liquid", "./test/stubs/" @@ -98,7 +98,7 @@ test("Liquid Render Relative (parent dir) Include", async t => { t.is(await fn(), "

TIME IS RELATIVE.

"); }); -test.skip("Liquid Render Relative (relative include should ignore _includes dir) Include", async t => { +test.skip("Liquid Render Relative (relative include should ignore _includes dir) Include", async (t) => { let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", "./test/stubs/" @@ -111,7 +111,7 @@ test.skip("Liquid Render Relative (relative include should ignore _includes dir) t.is(await fn(), "

This is not in the includes dir.

"); }); -test("Liquid Render Include with Liquid Suffix", async t => { +test("Liquid Render Include with Liquid Suffix", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" @@ -124,7 +124,7 @@ test("Liquid Render Include with Liquid Suffix", async t => { t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include with HTML Suffix", async t => { +test("Liquid Render Include with HTML Suffix", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" @@ -137,7 +137,7 @@ test("Liquid Render Include with HTML Suffix", async t => { t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include with HTML Suffix and Data Pass in", async t => { +test("Liquid Render Include with HTML Suffix and Data Pass in", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" @@ -152,41 +152,41 @@ test("Liquid Render Include with HTML Suffix and Data Pass in", async t => { t.is((await fn()).trim(), "This is an include. myValue"); }); -test("Liquid Custom Filter", async t => { +test("Liquid Custom Filter", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addFilter("prefixWithZach", function(val) { + tr.engine.addFilter("prefixWithZach", function (val) { return "Zach" + val; }); t.is(await tr._testRender("{{ 'test' | prefixWithZach }}", {}), "Zachtest"); }); -test.skip("Liquid Async Filter", async t => { +test.skip("Liquid Async Filter", async (t) => { let tr = new TemplateRender("liquid", "test/stubs"); tr.engine.addFilter({ - myAsyncFilter: function(value) { + myAsyncFilter: function (value) { return new Promise((resolve, reject) => { - setTimeout(function() { + setTimeout(function () { resolve(`HI${value}`); }, 100); }); - } + }, }); let fn = await tr.getCompiledTemplate("{{ 'test' | myAsyncFilter }}"); t.is((await fn()).trim(), "HItest"); }); -test("Liquid Custom Tag prefixWithZach", async t => { +test("Liquid Custom Tag prefixWithZach", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addTag("prefixWithZach", function(liquidEngine) { + tr.engine.addTag("prefixWithZach", function (liquidEngine) { return { - parse: function(tagToken, remainTokens) { + parse: function (tagToken, remainTokens) { this.str = tagToken.args; // name }, - render: function(scope, hash) { + render: function (scope, hash) { var str = liquidEngine.evalValueSync(this.str, scope); // 'alice' return Promise.resolve("Zach" + str); // 'Alice' - } + }, }; }); @@ -196,17 +196,17 @@ test("Liquid Custom Tag prefixWithZach", async t => { ); }); -test("Liquid Custom Tag postfixWithZach", async t => { +test("Liquid Custom Tag postfixWithZach", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addTag("postfixWithZach", function(liquidEngine) { + tr.engine.addTag("postfixWithZach", function (liquidEngine) { return { - parse: function(tagToken, remainTokens) { + parse: function (tagToken, remainTokens) { this.str = tagToken.args; }, - render: async function(scope, hash) { + render: async function (scope, hash) { var str = await liquidEngine.evalValue(this.str, scope); return Promise.resolve(str + "Zach"); - } + }, }; }); @@ -216,16 +216,16 @@ test("Liquid Custom Tag postfixWithZach", async t => { ); }); -test("Liquid Custom Tag Unquoted String", async t => { +test("Liquid Custom Tag Unquoted String", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addTag("testUnquotedStringTag", function(liquidEngine) { + tr.engine.addTag("testUnquotedStringTag", function (liquidEngine) { return { - parse: function(tagToken, remainTokens) { + parse: function (tagToken, remainTokens) { this.str = tagToken.args; }, - render: function(scope, hash) { + render: function (scope, hash) { return Promise.resolve(this.str + "Zach"); - } + }, }; }); @@ -238,27 +238,27 @@ test("Liquid Custom Tag Unquoted String", async t => { ); }); -test("Liquid addTag errors", async t => { +test("Liquid addTag errors", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); t.throws(() => { tr.engine.addTag("badSecondArgument", {}); }); }); -test("Liquid addTags", async t => { +test("Liquid addTags", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addCustomTags({ - postfixWithZach: function(liquidEngine) { + postfixWithZach: function (liquidEngine) { return { - parse: function(tagToken, remainTokens) { + parse: function (tagToken, remainTokens) { this.str = tagToken.args; }, - render: async function(scope, hash) { + render: async function (scope, hash) { var str = await liquidEngine.evalValue(this.str, scope); return Promise.resolve(str + "Zach"); - } + }, }; - } + }, }); t.is( @@ -267,11 +267,11 @@ test("Liquid addTags", async t => { ); }); -test("Liquid Shortcode", async t => { +test("Liquid Shortcode", async (t) => { t.plan(3); let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str) { + tr.engine.addShortcode("postfixWithZach", function (str) { // Data in context t.is(this.page.url, "/hi/"); t.not(this.name, "test"); @@ -283,23 +283,23 @@ test("Liquid Shortcode", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testZach" ); }); -test("Liquid Shortcode returns promise", async t => { +test("Liquid Shortcode returns promise", async (t) => { t.plan(2); let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str) { + tr.engine.addShortcode("postfixWithZach", function (str) { // Data in context t.is(this.page.url, "/hi/"); - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(str + "Zach"); }); }); @@ -309,18 +309,18 @@ test("Liquid Shortcode returns promise", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testZach" ); }); -test("Liquid Shortcode returns promise (await inside)", async t => { +test("Liquid Shortcode returns promise (await inside)", async (t) => { t.plan(2); let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", async function(str) { + tr.engine.addShortcode("postfixWithZach", async function (str) { // Data in context t.is(this.page.url, "/hi/"); @@ -331,18 +331,18 @@ test("Liquid Shortcode returns promise (await inside)", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testZach" ); }); -test("Liquid Shortcode returns promise (no await inside)", async t => { +test("Liquid Shortcode returns promise (no await inside)", async (t) => { t.plan(2); let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", async function(str) { + tr.engine.addShortcode("postfixWithZach", async function (str) { // Data in context t.is(this.page.url, "/hi/"); return getPromise(str + "Zach"); @@ -352,17 +352,17 @@ test("Liquid Shortcode returns promise (no await inside)", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testZach" ); }); -test("Liquid Shortcode Safe Output", async t => { +test("Liquid Shortcode Safe Output", async (t) => { t.plan(2); let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str) { + tr.engine.addShortcode("postfixWithZach", function (str) { // Data in context t.is(this.page.url, "/hi/"); return `${str}`; @@ -372,17 +372,17 @@ test("Liquid Shortcode Safe Output", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "test" ); }); -test("Liquid Paired Shortcode", async t => { +test("Liquid Paired Shortcode", async (t) => { t.plan(2); let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { // Data in context t.is(this.page.url, "/hi/"); return str + content + "Zach"; @@ -394,22 +394,22 @@ test("Liquid Paired Shortcode", async t => { { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, } ), "testContentZach" ); }); -test("Liquid Async Paired Shortcode", async t => { +test("Liquid Async Paired Shortcode", async (t) => { t.plan(2); let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { // Data in context t.is(this.page.url, "/hi/"); - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(str + content + "Zach"); }); }); @@ -421,15 +421,15 @@ test("Liquid Async Paired Shortcode", async t => { { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, } ), "testContentZach" ); }); -test("Liquid Render Include Subfolder", async t => { +test("Liquid Render Include Subfolder", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -437,7 +437,7 @@ test("Liquid Render Include Subfolder", async t => { t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder HTML", async t => { +test("Liquid Render Include Subfolder HTML", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -445,7 +445,7 @@ test("Liquid Render Include Subfolder HTML", async t => { t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder No file extension", async t => { +test("Liquid Render Include Subfolder No file extension", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -456,7 +456,7 @@ test("Liquid Render Include Subfolder No file extension", async t => { // Skipped tests pending https://github.com/harttle/liquidjs/issues/61 // Resolution: we’re going to leave this skipped as LiquidJS will require dynamicPartials // to be on for quoted includes! -test.skip("Liquid Render Include Subfolder Single quotes", async t => { +test.skip("Liquid Render Include Subfolder Single quotes", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -464,7 +464,7 @@ test.skip("Liquid Render Include Subfolder Single quotes", async t => { t.is(await fn(), "

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Double quotes", async t => { +test.skip("Liquid Render Include Subfolder Double quotes", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -472,7 +472,7 @@ test.skip("Liquid Render Include Subfolder Double quotes", async t => { t.is(await fn(), "

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Single quotes HTML", async t => { +test.skip("Liquid Render Include Subfolder Single quotes HTML", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -480,7 +480,7 @@ test.skip("Liquid Render Include Subfolder Single quotes HTML", async t => { t.is(await fn(), "

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Double quotes HTML", async t => { +test.skip("Liquid Render Include Subfolder Double quotes HTML", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -488,7 +488,7 @@ test.skip("Liquid Render Include Subfolder Double quotes HTML", async t => { t.is(await fn(), "

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Single quotes No file extension", async t => { +test.skip("Liquid Render Include Subfolder Single quotes No file extension", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -496,7 +496,7 @@ test.skip("Liquid Render Include Subfolder Single quotes No file extension", asy t.is(await fn(), "

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Double quotes No file extension", async t => { +test.skip("Liquid Render Include Subfolder Double quotes No file extension", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -505,7 +505,7 @@ test.skip("Liquid Render Include Subfolder Double quotes No file extension", asy }); /* End skipped tests */ -test("Liquid Options Overrides", async t => { +test("Liquid Options Overrides", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -513,7 +513,7 @@ test("Liquid Options Overrides", async t => { t.is(options.dynamicPartials, true); }); -test("Liquid Render Include Subfolder Single quotes no extension dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Single quotes no extension dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -523,7 +523,7 @@ test("Liquid Render Include Subfolder Single quotes no extension dynamicPartials t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder Single quotes (relative include current dir) dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Single quotes (relative include current dir) dynamicPartials true", async (t) => { let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", "./test/stubs/" @@ -536,7 +536,7 @@ test("Liquid Render Include Subfolder Single quotes (relative include current di t.is(await fn(), "

TIME IS RELATIVE.

"); }); -test("Liquid Render Include Subfolder Single quotes (relative include parent dir) dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Single quotes (relative include parent dir) dynamicPartials true", async (t) => { let tr = getNewTemplateRender( "./test/stubs/subfolder/does_not_exist_and_thats_ok.liquid", "./test/stubs/" @@ -549,7 +549,7 @@ test("Liquid Render Include Subfolder Single quotes (relative include parent dir t.is(await fn(), "

TIME IS RELATIVE.

"); }); -test("Liquid Render Include Subfolder Double quotes no extension dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Double quotes no extension dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -559,7 +559,7 @@ test("Liquid Render Include Subfolder Double quotes no extension dynamicPartials t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder Single quotes dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Single quotes dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -569,7 +569,7 @@ test("Liquid Render Include Subfolder Single quotes dynamicPartials true", async t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder Double quotes dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Double quotes dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -579,7 +579,7 @@ test("Liquid Render Include Subfolder Double quotes dynamicPartials true", async t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -589,7 +589,7 @@ test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true", t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true", async t => { +test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -599,7 +599,7 @@ test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true", t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true, data passed in", async t => { +test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true, data passed in", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -609,7 +609,7 @@ test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true, d t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true, data passed in", async t => { +test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true, data passed in", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ dynamicPartials: true }); @@ -619,7 +619,7 @@ test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true, d t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render: with Library Override", async t => { +test("Liquid Render: with Library Override", async (t) => { const tr = getNewTemplateRender("liquid"); const { Liquid } = require("liquidjs"); tr.engine.setLibrary(new Liquid()); @@ -628,9 +628,9 @@ test("Liquid Render: with Library Override", async t => { t.is(await fn({ name: "tim" }), "

Tim

"); }); -test("Liquid Paired Shortcode with Tag Inside", async t => { +test("Liquid Paired Shortcode with Tag Inside", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { return str + content + "Zach"; }); @@ -643,9 +643,9 @@ test("Liquid Paired Shortcode with Tag Inside", async t => { ); }); -test("Liquid Nested Paired Shortcode", async t => { +test("Liquid Nested Paired Shortcode", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { return str + content + "Zach"; }); @@ -658,27 +658,28 @@ test("Liquid Nested Paired Shortcode", async t => { ); }); -test("Liquid Shortcode Multiple Args", async t => { +test("Liquid Shortcode Multiple Args", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str, str2) { + tr.engine.addShortcode("postfixWithZach", function (str, str2) { return str + str2 + "Zach"; }); t.is( await tr._testRender("{% postfixWithZach name other %}", { name: "test", - other: "howdy" + other: "howdy", }), "testhowdyZach" ); }); -test.skip("Liquid Include Scope Leak", async t => { +test.skip("Liquid Include Scope Leak", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" ); + // This might be by design? let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -687,7 +688,7 @@ test.skip("Liquid Include Scope Leak", async t => { }); // TODO this will change in 1.0 -test("Liquid Missing Filter Issue #183 (no strictFilters)", async t => { +test("Liquid Missing Filter Issue #183 (no strictFilters)", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); try { @@ -698,7 +699,7 @@ test("Liquid Missing Filter Issue #183 (no strictFilters)", async t => { } }); -test("Liquid Missing Filter Issue #183", async t => { +test("Liquid Missing Filter Issue #183", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.setLiquidOptions({ strictFilters: true }); @@ -710,7 +711,7 @@ test("Liquid Missing Filter Issue #183", async t => { } }); -test("Issue 258: Liquid Render Date", async t => { +test("Issue 258: Liquid Render Date", async (t) => { let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{ myDate }}

" ); @@ -720,33 +721,33 @@ test("Issue 258: Liquid Render Date", async t => { t.not(dateStr.substr(2, 1), '"'); }); -test("Issue 347: Liquid addTags with space in argument", async t => { +test("Issue 347: Liquid addTags with space in argument", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addCustomTags({ - issue347CustomTag: function(liquidEngine) { + issue347CustomTag: function (liquidEngine) { return { - parse: function(tagToken, remainTokens) { + parse: function (tagToken, remainTokens) { this.str = tagToken.args; }, - render: async function(scope, hash) { + render: async function (scope, hash) { var str = await liquidEngine.evalValue(this.str, scope); return Promise.resolve(str + "Zach"); - } + }, }; - } + }, }); t.is( await tr._testRender("{% issue347CustomTag 'te st' %}", { - name: "slkdjflksdjf" + name: "slkdjflksdjf", }), "te stZach" ); }); -test("Issue 347: Liquid Shortcode, string argument", async t => { +test("Issue 347: Liquid Shortcode, string argument", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347", function(str) { + tr.engine.addShortcode("issue347", function (str) { return str + "Zach"; }); @@ -756,23 +757,23 @@ test("Issue 347: Liquid Shortcode, string argument", async t => { ); }); -test("Issue 347: Liquid Shortcode string argument with space, double quotes", async t => { +test("Issue 347: Liquid Shortcode string argument with space, double quotes", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347b", function(str) { + tr.engine.addShortcode("issue347b", function (str) { return str + "Zach"; }); t.is( await tr._testRender('{% issue347b "test 2" "test 3" %}', { - name: "alkdsjfkslja" + name: "alkdsjfkslja", }), "test 2Zach" ); }); -test("Issue 347: Liquid Shortcode string argument with space, single quotes", async t => { +test("Issue 347: Liquid Shortcode string argument with space, single quotes", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347", function(str) { + tr.engine.addShortcode("issue347", function (str) { return str + "Zach"; }); @@ -782,65 +783,65 @@ test("Issue 347: Liquid Shortcode string argument with space, single quotes", as ); }); -test("Issue 347: Liquid Shortcode string argument with space, combination of quotes", async t => { +test("Issue 347: Liquid Shortcode string argument with space, combination of quotes", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347", function(str, str2) { + tr.engine.addShortcode("issue347", function (str, str2) { return str + str2 + "Zach"; }); t.is( await tr._testRender("{% issue347 'test 2' \"test 3\" %}", { - name: "alkdsjfkslja" + name: "alkdsjfkslja", }), "test 2test 3Zach" ); }); -test("Issue 347: Liquid Shortcode multiple arguments, comma separated", async t => { +test("Issue 347: Liquid Shortcode multiple arguments, comma separated", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347", function(str, str2) { + tr.engine.addShortcode("issue347", function (str, str2) { return str + str2 + "Zach"; }); t.is( await tr._testRender("{% issue347 'test 2', \"test 3\" %}", { - name: "alkdsjfkslja" + name: "alkdsjfkslja", }), "test 2test 3Zach" ); }); -test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is an integer", async t => { +test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is an integer", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347", function(str, str2) { + tr.engine.addShortcode("issue347", function (str, str2) { return str + str2 + "Zach"; }); t.is( await tr._testRender("{% issue347 'test 2', 3 %}", { - name: "alkdsjfkslja" + name: "alkdsjfkslja", }), "test 23Zach" ); }); -test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is a float", async t => { +test("Issue 347: Liquid Shortcode multiple arguments, comma separated, one is a float", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347", function(str, str2) { + tr.engine.addShortcode("issue347", function (str, str2) { return str + str2 + "Zach"; }); t.is( await tr._testRender("{% issue347 'test 2', 3.23 %}", { - name: "alkdsjfkslja" + name: "alkdsjfkslja", }), "test 23.23Zach" ); }); -test("Issue 347: Liquid Shortcode boolean argument", async t => { +test("Issue 347: Liquid Shortcode boolean argument", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue347", function(bool) { + tr.engine.addShortcode("issue347", function (bool) { return bool ? "Zach" : "Not Zach"; }); @@ -854,9 +855,9 @@ test("Issue 347: Liquid Shortcode boolean argument", async t => { ); }); -test("Issue 347: Liquid Paired Shortcode with Spaces", async t => { +test("Issue 347: Liquid Paired Shortcode with Spaces", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function( + tr.engine.addPairedShortcode("postfixWithZach", function ( content, str1, num, @@ -874,72 +875,72 @@ test("Issue 347: Liquid Paired Shortcode with Spaces", async t => { ); }); -test("Liquid Render with dash variable Issue #567", async t => { +test("Liquid Render with dash variable Issue #567", async (t) => { let tr = getNewTemplateRender("liquid"); let fn = await tr.getCompiledTemplate("

{{ my-global-name }}

"); t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); -test("Issue 600: Liquid Shortcode argument page.url", async t => { +test("Issue 600: Liquid Shortcode argument page.url", async (t) => { let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue600", function(str) { + tr.engine.addShortcode("issue600", function (str) { return str + "Zach"; }); t.is( await tr._testRender("{% issue600 page.url %}", { - page: { url: "alkdsjfkslja" } + page: { url: "alkdsjfkslja" }, }), "alkdsjfksljaZach" ); }); -test("Issue 600: Liquid Shortcode argument with dashes", async t => { +test("Issue 600: Liquid Shortcode argument with dashes", async (t) => { let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue600b", function(str) { + tr.engine.addShortcode("issue600b", function (str) { return str + "Zach"; }); t.is( await tr._testRender("{% issue600b page-url %}", { - "page-url": "alkdsjfkslja" + "page-url": "alkdsjfkslja", }), "alkdsjfksljaZach" ); }); -test("Issue 600: Liquid Shortcode argument with underscores", async t => { +test("Issue 600: Liquid Shortcode argument with underscores", async (t) => { let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("issue600c", function(str) { + tr.engine.addShortcode("issue600c", function (str) { return str + "Zach"; }); t.is( await tr._testRender("{% issue600c page_url %}", { - page_url: "alkdsjfkslja" + page_url: "alkdsjfkslja", }), "alkdsjfksljaZach" ); }); -test.skip("Issue 611: Run a function", async t => { +test.skip("Issue 611: Run a function", async (t) => { // This works in Nunjucks let tr = new TemplateRender("liquid", "./test/stubs/"); t.is( await tr._testRender("{{ test() }}", { - test: function() { + test: function () { return "alkdsjfksljaZach"; - } + }, }), "alkdsjfksljaZach" ); }); -test("Liquid Shortcode (with sync function, error throwing)", async t => { +test("Liquid Shortcode (with sync function, error throwing)", async (t) => { let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str) { + tr.engine.addShortcode("postfixWithZach", function (str) { throw new Error("Liquid Shortcode (with sync function, error throwing)"); }); @@ -953,9 +954,9 @@ test("Liquid Shortcode (with sync function, error throwing)", async t => { ); }); -test("Liquid Shortcode (with async function, error throwing)", async t => { +test("Liquid Shortcode (with async function, error throwing)", async (t) => { let tr = new TemplateRender("liquid", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", async function(str) { + tr.engine.addShortcode("postfixWithZach", async function (str) { throw new Error("Liquid Shortcode (with async function, error throwing)"); }); @@ -969,49 +970,49 @@ test("Liquid Shortcode (with async function, error throwing)", async t => { ); }); -test("Liquid Render a false #1069", async t => { +test("Liquid Render a false #1069", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "{{ falseValue }}" ); t.is(await fn({ falseValue: false }), "false"); }); -test("Liquid Render Square Brackets #680 dash single quotes", async t => { +test("Liquid Render Square Brackets #680 dash single quotes", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test['hey-a'] }}

" ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test.skip("Liquid Render Square Brackets #680 dash single quotes spaces", async t => { +test("Liquid Render Square Brackets #680 dash single quotes spaces", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test[ 'hey-a' ] }}

" ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test("Liquid Render Square Brackets #680 dash double quotes", async t => { +test("Liquid Render Square Brackets #680 dash double quotes", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( '

{{ test["hey-a"] }}

' ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test.skip("Liquid Render Square Brackets #680 dash double quotes spaces", async t => { +test("Liquid Render Square Brackets #680 dash double quotes spaces", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( '

{{ test[ "hey-a" ] }}

' ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); -test("Liquid Render Square Brackets #680 variable reference", async t => { +test("Liquid Render Square Brackets #680 variable reference", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test[ref] }}

" ); t.is(await fn({ test: { "hey-a": 1 }, ref: "hey-a" }), "

1

"); }); -test.skip("Liquid Render Square Brackets #680 variable reference array", async t => { +test("Liquid Render Square Brackets #680 variable reference array", async (t) => { let fn = await new TemplateRender("liquid").getCompiledTemplate( "

{{ test[ref[0]] }}

" ); From 5ffd6d1d749e2b038cae0907294e8e61288cb3cb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 4 Sep 2020 13:28:15 -0500 Subject: [PATCH 251/746] Fixes #1391. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a26f03f5..0943ec5a0 100755 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "parse-filepath": "^1.0.2", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", - "pug": "^2.0.4", + "pug": "^3.0.0", "recursive-copy": "^2.0.11", "semver": "^7.3.2", "slugify": "^1.4.5", From d64f02a6f3dc053b0b881aadb3cba39f5af03b17 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 4 Sep 2020 13:38:21 -0500 Subject: [PATCH 252/746] Fixes #371 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0943ec5a0..3106fb8f5 100755 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^4.0.0", - "mustache": "^2.3.2", + "mustache": "^4.0.1", "normalize-path": "^3.0.0", "nunjucks": "^3.2.2", "parse-filepath": "^1.0.2", From de8e6e50892440c82dd1fddfbcef08f06a99b508 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 4 Sep 2020 13:58:01 -0500 Subject: [PATCH 253/746] Fixes #1392 --- package.json | 2 +- test/TemplateRenderEJSTest.js | 37 +++++++++++++---------------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 3106fb8f5..58141c28f 100755 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "chokidar": "^3.4.2", "debug": "^4.1.1", "dependency-graph": "^0.9.0", - "ejs": "^2.7.4", + "ejs": "^3.1.5", "fast-glob": "^3.2.4", "fs-extra": "^9.0.1", "gray-matter": "^4.0.2", diff --git a/test/TemplateRenderEJSTest.js b/test/TemplateRenderEJSTest.js index 928cd4db2..534cab77e 100644 --- a/test/TemplateRenderEJSTest.js +++ b/test/TemplateRenderEJSTest.js @@ -9,7 +9,7 @@ function getNewTemplateRender(name, inputDir) { } // EJS -test("EJS", t => { +test("EJS", (t) => { t.is(getNewTemplateRender("ejs").getEngineName(), "ejs"); t.is( getNewTemplateRender("./test/stubs/filename.ejs").getEngineName(), @@ -17,23 +17,14 @@ test("EJS", t => { ); }); -test("EJS Render", async t => { +test("EJS Render", async (t) => { let fn = await getNewTemplateRender("ejs").getCompiledTemplate( "

<%= name %>

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("EJS Render Absolute Include, Preprocessor Directive", async t => { - // includes require a full filename passed in - let fn = await getNewTemplateRender( - "./test/stubs/filename.ejs", - "./test/stubs/" - ).getCompiledTemplate("

<% include /included %>

"); - t.is(await fn(), "

This is an include.

"); -}); - -test("EJS Render Absolute Include, Fxn no Data", async t => { +test("EJS Render Absolute Include, Fxn no Data", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", @@ -42,7 +33,7 @@ test("EJS Render Absolute Include, Fxn no Data", async t => { t.is(await fn(), "

This is an include.

"); }); -test("EJS Render Absolute Include, Fxn with Data", async t => { +test("EJS Render Absolute Include, Fxn with Data", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", @@ -53,34 +44,34 @@ test("EJS Render Absolute Include, Fxn with Data", async t => { t.is(await fn(), "

This is an Bill.

"); }); -test("EJS Render Relative Include (no leading dot-slash for current dir), Preprocessor Directive", async t => { +test("EJS Render Relative Include (no leading dot-slash for current dir)", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/dir/filename.ejs", "./test/stubs/" - ).getCompiledTemplate("

<% include included %>

"); + ).getCompiledTemplate("

<%- include('included') -%>

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

This is an include.

"); }); -test("EJS Render Relative Include Current dir to Subdir, Preprocessor Directive", async t => { +test("EJS Render Relative Include Current dir to Subdir", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/filename.ejs", "./test/stubs/" - ).getCompiledTemplate("

<% include ./dir/included %>

"); + ).getCompiledTemplate("

<%- include('./dir/included') -%>

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

This is an include.

"); }); -test("EJS Render Relative Include Parent dir to Subdir, Preprocessor Directive", async t => { +test("EJS Render Relative Include Parent dir to Subdir", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/dir/filename.ejs", "./test/stubs/" - ).getCompiledTemplate("

<% include ../dir/included %>

"); + ).getCompiledTemplate("

<%- include('../dir/included') -%>

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

This is an include.

"); }); -test("EJS Render Relative Include, Fxn no Data", async t => { +test("EJS Render Relative Include, Fxn no Data", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", @@ -89,7 +80,7 @@ test("EJS Render Relative Include, Fxn no Data", async t => { t.is(await fn(), "

This is an include.

"); }); -test("EJS Render Relative Include current dir to subdir, Fxn no Data", async t => { +test("EJS Render Relative Include current dir to subdir, Fxn no Data", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/relative-ejs/filename.ejs", @@ -98,7 +89,7 @@ test("EJS Render Relative Include current dir to subdir, Fxn no Data", async t = t.is(await fn(), "

This is an include.

"); }); -test("EJS Render Relative Include, Fxn with Data", async t => { +test("EJS Render Relative Include, Fxn with Data", async (t) => { // includes require a full filename passed in let fn = await getNewTemplateRender( "./test/stubs/filename.ejs", @@ -109,7 +100,7 @@ test("EJS Render Relative Include, Fxn with Data", async t => { t.is(await fn(), "

This is an Bill.

"); }); -test("EJS Render: with Library Override", async t => { +test("EJS Render: with Library Override", async (t) => { let tr = getNewTemplateRender("ejs"); let lib = require("ejs"); From f872b6c170f52d2ac277d17a6f32b22626e2edd1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 7 Sep 2020 15:01:02 -0500 Subject: [PATCH 254/746] Fixes #1394 --- package.json | 2 - test/BenchmarkTest.js | 18 +- test/CapitalizeTest.js | 6 +- test/ComputedDataProxyTest.js | 4 +- test/ComputedDataQueueTest.js | 4 +- test/ComputedDataTemplateStringTest.js | 16 +- test/ComputedDataTest.js | 4 +- test/DeleteRequireCacheTest.js | 10 +- test/DependencyGraphTest.js | 10 +- test/EleventyCommandCheckTest.js | 22 +- test/EleventyConfigTest.js | 36 +-- test/EleventyErrorHandlerTest.js | 20 +- test/EleventyErrorUtilTest.js | 22 +- test/EleventyExtensionMapTest.js | 48 ++-- test/EleventyFilesTest.js | 170 +++++------ test/EleventyServeTest.js | 36 +-- test/EleventyTest.js | 40 +-- test/EleventyWatchTargetsTest.js | 38 +-- test/EleventyWatchTest.js | 36 +-- test/GetCollectionItemTest.js | 12 +- test/MergeTest.js | 90 +++--- test/PaginationTest.js | 108 +++---- test/PluralizeTest.js | 6 +- test/SortableTest.js | 36 +-- test/TemplateCacheTest.js | 18 +- test/TemplateCollectionTest.js | 34 +-- test/TemplateConfigTest.js | 8 +- test/TemplateDataTest.js | 116 ++++---- test/TemplateEngineManagerTest.js | 26 +- test/TemplateEngineTest.js | 8 +- test/TemplateFileSlugTest.js | 60 ++-- test/TemplateGlobTest.js | 44 +-- test/TemplateLayoutPathResolverTest.js | 64 ++--- test/TemplateLayoutTest.js | 46 +-- test/TemplateMapTest-ComputedData.js | 10 +- test/TemplateMapTest.js | 178 ++++++------ test/TemplatePassthroughManagerTest.js | 64 ++--- test/TemplatePassthroughTest.js | 58 ++-- test/TemplatePathTest.js | 64 ++--- test/TemplatePermalinkNoWriteTest.js | 6 +- test/TemplatePermalinkTest.js | 20 +- test/TemplateRenderCustomTest.js | 42 +-- test/TemplateRenderEJSTest.js | 6 +- test/TemplateRenderHTMLTest.js | 20 +- test/TemplateRenderHamlTest.js | 12 +- test/TemplateRenderHandlebarsTest.js | 100 +++---- test/TemplateRenderJSTLTest.js | 16 +- test/TemplateRenderJavaScriptTest.js | 124 ++++---- test/TemplateRenderLiquidTest.js | 6 +- test/TemplateRenderMarkdownPluginTest.js | 14 +- test/TemplateRenderMarkdownTest.js | 94 +++--- test/TemplateRenderMustacheTest.js | 26 +- test/TemplateRenderNunjucksTest.js | 236 +++++++-------- test/TemplateRenderPugTest.js | 48 ++-- test/TemplateRenderTest.js | 22 +- test/TemplateTest-ComputedData.js | 32 +-- test/TemplateTest-JavaScript.js | 62 ++-- test/TemplateTest.js | 348 +++++++++++------------ test/TemplateWriterTest.js | 120 ++++---- test/TestUtilityTest.js | 6 +- test/UrlTest.js | 20 +- test/UserConfigTest.js | 8 +- test/UserDataExtensionsTest.js | 20 +- 63 files changed, 1498 insertions(+), 1502 deletions(-) diff --git a/package.json b/package.json index 58141c28f..5416e75ff 100755 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "bugs": "https://github.com/11ty/eleventy/issues", "homepage": "https://www.11ty.dev/", "ava": { - "babel": true, "failFast": false, "files": [ "./test/*.js" @@ -75,7 +74,6 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", - "@ava/babel": "^1.0.1", "ava": "^3.12.1", "husky": "^4.2.5", "ink-docstrap": "1.3.2", diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index 9e62a6a89..97e3e952c 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -1,15 +1,15 @@ -import test from "ava"; -import Benchmark from "../src/Benchmark"; +const test = require("ava"); +const Benchmark = require("../src/Benchmark"); function between(t, value, lowerBound, upperBound) { t.truthy(value >= lowerBound); t.truthy(value <= upperBound); } -test.cb("Standard Benchmark", t => { +test.cb("Standard Benchmark", (t) => { let b = new Benchmark(); b.before(); - setTimeout(function() { + setTimeout(function () { b.after(); t.truthy(b.getTotal() >= 10); t.end(); @@ -18,11 +18,11 @@ test.cb("Standard Benchmark", t => { test.cb( "Nested Benchmark (nested calls are ignored while a parent is measuring)", - t => { + (t) => { let b = new Benchmark(); b.before(); - setTimeout(function() { + setTimeout(function () { b.before(); b.after(); t.truthy(b.getTotal() <= 0.1); @@ -34,17 +34,17 @@ test.cb( } ); -test.cb("Reset Benchmark", t => { +test.cb("Reset Benchmark", (t) => { let b = new Benchmark(); b.before(); b.reset(); - setTimeout(function() { + setTimeout(function () { b.before(); b.after(); t.truthy(b.getTotal() <= 0.1); - t.throws(function() { + t.throws(function () { // throws because we reset b.after(); }); diff --git a/test/CapitalizeTest.js b/test/CapitalizeTest.js index 8c845ec74..9dbad903e 100644 --- a/test/CapitalizeTest.js +++ b/test/CapitalizeTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import capitalize from "../src/Util/Capitalize"; +const test = require("ava"); +const capitalize = require("../src/Util/Capitalize"); -test("capitalize", t => { +test("capitalize", (t) => { t.is(capitalize("hello"), "Hello"); t.is(capitalize("hello world"), "Hello World"); t.is(capitalize("Testing TESTING"), "Testing TESTING"); diff --git a/test/ComputedDataProxyTest.js b/test/ComputedDataProxyTest.js index 0f3eea7f3..673ac5f6c 100644 --- a/test/ComputedDataProxyTest.js +++ b/test/ComputedDataProxyTest.js @@ -1,5 +1,5 @@ -import test from "ava"; -import ComputedDataProxy from "../src/ComputedDataProxy"; +const test = require("ava"); +const ComputedDataProxy = require("../src/ComputedDataProxy"); test("Get vars used by function", async (t) => { let cd = new ComputedDataProxy(["key1"]); diff --git a/test/ComputedDataQueueTest.js b/test/ComputedDataQueueTest.js index fd14a82ae..03281978d 100644 --- a/test/ComputedDataQueueTest.js +++ b/test/ComputedDataQueueTest.js @@ -1,5 +1,5 @@ -import test from "ava"; -import ComputedDataQueue from "../src/ComputedDataQueue"; +const test = require("ava"); +const ComputedDataQueue = require("../src/ComputedDataQueue"); test("Standard uses", (t) => { let queue = new ComputedDataQueue(); diff --git a/test/ComputedDataTemplateStringTest.js b/test/ComputedDataTemplateStringTest.js index dc182799d..5f2c4a531 100644 --- a/test/ComputedDataTemplateStringTest.js +++ b/test/ComputedDataTemplateStringTest.js @@ -1,25 +1,25 @@ -import test from "ava"; -import ComputedDataTemplateString from "../src/ComputedDataTemplateString"; +const test = require("ava"); +const ComputedDataTemplateString = require("../src/ComputedDataTemplateString"); -test("Get fake proxy data", t => { +test("Get fake proxy data", (t) => { let cd = new ComputedDataTemplateString(["key1", "key2"]); t.deepEqual(cd.getProxyData(), { key1: `${cd.prefix}key1${cd.suffix}`, - key2: `${cd.prefix}key2${cd.suffix}` + key2: `${cd.prefix}key2${cd.suffix}`, }); }); -test("Get nested fake proxy data", t => { +test("Get nested fake proxy data", (t) => { let cd = new ComputedDataTemplateString(["key1.nested", "key2"]); t.deepEqual(cd.getProxyData(), { key1: { - nested: `${cd.prefix}key1.nested${cd.suffix}` + nested: `${cd.prefix}key1.nested${cd.suffix}`, }, - key2: `${cd.prefix}key2${cd.suffix}` + key2: `${cd.prefix}key2${cd.suffix}`, }); }); -test("Get vars from output", t => { +test("Get vars from output", (t) => { let cd = new ComputedDataTemplateString(); t.deepEqual(cd.findVarsInOutput(""), []); t.deepEqual(cd.findVarsInOutput("slkdjfkljdsf"), []); diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index 26b543f70..320a33653 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -1,5 +1,5 @@ -import test from "ava"; -import ComputedData from "../src/ComputedData"; +const test = require("ava"); +const ComputedData = require("../src/ComputedData"); test("Basic get/set", async (t) => { let cd = new ComputedData(); diff --git a/test/DeleteRequireCacheTest.js b/test/DeleteRequireCacheTest.js index 4393f5bd1..4cc692b9d 100644 --- a/test/DeleteRequireCacheTest.js +++ b/test/DeleteRequireCacheTest.js @@ -1,9 +1,9 @@ -import test from "ava"; -import path from "path"; -import deleteRequireCache from "../src/Util/DeleteRequireCache"; -import template from "./stubs/function.11ty"; +const test = require("ava"); +const path = require("path"); +const deleteRequireCache = require("../src/Util/DeleteRequireCache"); +const template = require("./stubs/function.11ty"); -test("deleteRequireCache", t => { +test("deleteRequireCache", (t) => { const modulePath = path.normalize( path.join(__dirname, "./stubs/function.11ty.js") ); diff --git a/test/DependencyGraphTest.js b/test/DependencyGraphTest.js index 5c8990883..6bf0c9507 100644 --- a/test/DependencyGraphTest.js +++ b/test/DependencyGraphTest.js @@ -1,6 +1,6 @@ -import test from "ava"; +const test = require("ava"); -test("Dependency graph nodes don’t require dependencies", async t => { +test("Dependency graph nodes don’t require dependencies", async (t) => { const DependencyGraph = require("dependency-graph").DepGraph; let graph = new DependencyGraph(); @@ -19,11 +19,11 @@ test("Dependency graph nodes don’t require dependencies", async t => { "all", "template-a", "template-b", - "template-c" + "template-c", ]); }); -test("Dependency graph assumptions", async t => { +test("Dependency graph assumptions", async (t) => { const DependencyGraph = require("dependency-graph").DepGraph; let graph = new DependencyGraph(); @@ -41,6 +41,6 @@ test("Dependency graph assumptions", async t => { "template-b", "template-c", "all", - "userCollection" + "userCollection", ]); }); diff --git a/test/EleventyCommandCheckTest.js b/test/EleventyCommandCheckTest.js index 1a26e1af5..77ff1d783 100644 --- a/test/EleventyCommandCheckTest.js +++ b/test/EleventyCommandCheckTest.js @@ -1,36 +1,36 @@ -import test from "ava"; -import EleventyCommandCheck from "../src/EleventyCommandCheck"; +const test = require("ava"); +const EleventyCommandCheck = require("../src/EleventyCommandCheck"); -test("Constructor", t => { +test("Constructor", (t) => { let cmdCheck = new EleventyCommandCheck({}); t.is(cmdCheck.toString(), ""); }); -test("Has an argument", t => { +test("Has an argument", (t) => { let cmdCheck = new EleventyCommandCheck({ - input: "src" + input: "src", }); t.is(cmdCheck.toString(), "--input=src"); }); -test("Boolean argument", t => { +test("Boolean argument", (t) => { let cmdCheck = new EleventyCommandCheck({ - version: true + version: true, }); t.is(cmdCheck.toString(), "--version"); }); -test("Multiple arguments", t => { +test("Multiple arguments", (t) => { let cmdCheck = new EleventyCommandCheck({ input: "src", - version: true + version: true, }); // technically invalid but eleventy should quit early on --version t.is(cmdCheck.toString(), "--input=src --version"); }); -test("getArgumentLookupMap", t => { +test("getArgumentLookupMap", (t) => { let cmdCheck = new EleventyCommandCheck({}); t.is(cmdCheck.getArgumentLookupMap()["input"], true); t.is(cmdCheck.getArgumentLookupMap()["version"], true); @@ -43,7 +43,7 @@ test("getArgumentLookupMap", t => { t.is(cmdCheck.isKnownArgument("_"), true); }); -test("throws", t => { +test("throws", (t) => { let cmdCheck = new EleventyCommandCheck({ "unknown-argument": true }); t.throws(() => { cmdCheck.hasUnknownArguments(); diff --git a/test/EleventyConfigTest.js b/test/EleventyConfigTest.js index 5b49e6789..fc21cdc6d 100644 --- a/test/EleventyConfigTest.js +++ b/test/EleventyConfigTest.js @@ -1,10 +1,10 @@ -import test from "ava"; -import eleventyConfig from "../src/EleventyConfig"; +const test = require("ava"); +const eleventyConfig = require("../src/EleventyConfig"); // more in TemplateConfigTest.js -test.cb("Events", t => { - eleventyConfig.on("testEvent", function(arg1, arg2, arg3) { +test.cb("Events", (t) => { + eleventyConfig.on("testEvent", function (arg1, arg2, arg3) { t.is(arg1, "arg1"); t.is(arg2, "arg2"); t.is(arg3, "arg3"); @@ -14,30 +14,30 @@ test.cb("Events", t => { eleventyConfig.emit("testEvent", "arg1", "arg2", "arg3"); }); -test("Add Collections", t => { - eleventyConfig.addCollection("myCollection", function(collection) {}); +test("Add Collections", (t) => { + eleventyConfig.addCollection("myCollection", function (collection) {}); t.deepEqual(Object.keys(eleventyConfig.getCollections()), ["myCollection"]); }); -test("Add Collections throws error on key collision", t => { - eleventyConfig.addCollection("myCollectionCollision", function( +test("Add Collections throws error on key collision", (t) => { + eleventyConfig.addCollection("myCollectionCollision", function ( collection ) {}); t.throws(() => { - eleventyConfig.addCollection("myCollectionCollision", function( + eleventyConfig.addCollection("myCollectionCollision", function ( collection ) {}); }); }); -test("Set manual Pass-through File Copy (single call)", t => { +test("Set manual Pass-through File Copy (single call)", (t) => { eleventyConfig.addPassthroughCopy("img"); t.is(eleventyConfig.passthroughCopies["img"], true); }); -test("Set manual Pass-through File Copy (chained calls)", t => { +test("Set manual Pass-through File Copy (chained calls)", (t) => { eleventyConfig .addPassthroughCopy("css") .addPassthroughCopy("js") @@ -50,10 +50,10 @@ test("Set manual Pass-through File Copy (chained calls)", t => { t.is(eleventyConfig.passthroughCopies["./src/empty"], "./"); }); -test("Set manual Pass-through File Copy (glob patterns)", t => { +test("Set manual Pass-through File Copy (glob patterns)", (t) => { eleventyConfig.addPassthroughCopy({ "./src/static/**/*": "renamed", - "./src/markdown/*.md": "" + "./src/markdown/*.md": "", }); // does not exist @@ -65,27 +65,27 @@ test("Set manual Pass-through File Copy (glob patterns)", t => { t.is(eleventyConfig.passthroughCopies["./src/markdown/*.md"], ""); }); -test("Set Template Formats (string)", t => { +test("Set Template Formats (string)", (t) => { eleventyConfig.setTemplateFormats("ejs, njk, liquid"); t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid"]); }); -test("Set Template Formats (array)", t => { +test("Set Template Formats (array)", (t) => { eleventyConfig.setTemplateFormats(["ejs", "njk", "liquid"]); t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid"]); }); -test("Set Template Formats (js passthrough copy)", t => { +test("Set Template Formats (js passthrough copy)", (t) => { eleventyConfig.setTemplateFormats("ejs, njk, liquid, js"); t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid", "js"]); }); -test("Set Template Formats (11ty.js)", t => { +test("Set Template Formats (11ty.js)", (t) => { eleventyConfig.setTemplateFormats("ejs, njk, liquid, 11ty.js"); t.deepEqual(eleventyConfig.templateFormats, [ "ejs", "njk", "liquid", - "11ty.js" + "11ty.js", ]); }); diff --git a/test/EleventyErrorHandlerTest.js b/test/EleventyErrorHandlerTest.js index 5bc98f80e..b9968740d 100644 --- a/test/EleventyErrorHandlerTest.js +++ b/test/EleventyErrorHandlerTest.js @@ -1,36 +1,36 @@ -import test from "ava"; -import EleventyErrorHandler from "../src/EleventyErrorHandler"; +const test = require("ava"); +const EleventyErrorHandler = require("../src/EleventyErrorHandler"); let output = []; -test.beforeEach(t => { +test.beforeEach((t) => { output = []; EleventyErrorHandler.isChalkEnabled = false; EleventyErrorHandler.logger = { - log: function(str) { + log: function (str) { output.push(str); }, - warn: function(str) { + warn: function (str) { output.push(str); }, - error: function(str) { + error: function (str) { output.push(str); - } + }, }; }); -test.afterEach(t => { +test.afterEach((t) => { EleventyErrorHandler.isChalkEnabled = true; EleventyErrorHandler.logger = null; }); -test("Disable chalk", t => { +test("Disable chalk", (t) => { EleventyErrorHandler.isChalkEnabled = false; t.is(EleventyErrorHandler.isChalkEnabled, false); }); -test("Log a warning, error", t => { +test("Log a warning, error", (t) => { EleventyErrorHandler.warn(new Error("Test warning"), "Hello"); let expected = `Hello: (more in DEBUG output) diff --git a/test/EleventyErrorUtilTest.js b/test/EleventyErrorUtilTest.js index 2ba167fea..a2ffb7fa7 100644 --- a/test/EleventyErrorUtilTest.js +++ b/test/EleventyErrorUtilTest.js @@ -1,5 +1,5 @@ -import test from "ava"; -import EleventyErrorUtil from "../src/EleventyErrorUtil"; +const test = require("ava"); +const EleventyErrorUtil = require("../src/EleventyErrorUtil"); const SAMPLE_ERROR = new Error("Nothing to see here"); @@ -7,15 +7,15 @@ const { cleanMessage, hasEmbeddedError, convertErrorToString, - deconvertErrorToObject + deconvertErrorToObject, } = EleventyErrorUtil; -test("hasEmbeddedError()", t => { +test("hasEmbeddedError()", (t) => { t.false(hasEmbeddedError("")); t.true(hasEmbeddedError(convertErrorToString(SAMPLE_ERROR))); }); -test("cleanMessage()", t => { +test("cleanMessage()", (t) => { t.is(cleanMessage(null), ""); t.is(cleanMessage(undefined), ""); t.is(cleanMessage(false), ""); @@ -26,23 +26,23 @@ test("cleanMessage()", t => { t.is(cleanMessage(text + convertErrorToString(SAMPLE_ERROR)), text); }); -test("deconvertErrorToObject() should throw on invalid inputs", t => { +test("deconvertErrorToObject() should throw on invalid inputs", (t) => { t.throws(() => deconvertErrorToObject(undefined), { - message: "Could not convert error object from: undefined" + message: "Could not convert error object from: undefined", }); t.throws(() => deconvertErrorToObject(""), { - message: "Could not convert error object from: " + message: "Could not convert error object from: ", }); t.throws(() => deconvertErrorToObject("Not an error"), { - message: "Could not convert error object from: Not an error" + message: "Could not convert error object from: Not an error", }); }); -test("deconvertErrorToObject() should return its argument if it does not contain another error", t => { +test("deconvertErrorToObject() should return its argument if it does not contain another error", (t) => { t.is(deconvertErrorToObject(SAMPLE_ERROR), SAMPLE_ERROR); }); -test("deconvertErrorToObject() should get message and stack from convertErrorToString()", t => { +test("deconvertErrorToObject() should get message and stack from convertErrorToString()", (t) => { const nestingError = new Error( "This error contains a sample error: " + convertErrorToString(SAMPLE_ERROR) ); diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index 318dd60ed..d9d8993e4 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -1,82 +1,82 @@ -import test from "ava"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); -test("Empty formats", t => { +test("Empty formats", (t) => { let map = new EleventyExtensionMap([]); t.deepEqual(map.getGlobs("."), []); }); -test("Single format", t => { +test("Single format", (t) => { let map = new EleventyExtensionMap(["pug"]); t.deepEqual(map.getGlobs("."), ["./**/*.pug"]); t.deepEqual(map.getGlobs("src"), ["./src/**/*.pug"]); }); -test("Multiple formats", t => { +test("Multiple formats", (t) => { let map = new EleventyExtensionMap(["njk", "pug"]); t.deepEqual(map.getGlobs("."), ["./**/*.njk", "./**/*.pug"]); t.deepEqual(map.getGlobs("src"), ["./src/**/*.njk", "./src/**/*.pug"]); }); -test("Invalid keys are filtered (no passthrough copy)", t => { +test("Invalid keys are filtered (no passthrough copy)", (t) => { let map = new EleventyExtensionMap(["lksdjfjlsk"]); map.config = { - passthroughFileCopy: false + passthroughFileCopy: false, }; t.deepEqual(map.getGlobs("."), []); }); -test("Invalid keys are filtered (using passthrough copy)", t => { +test("Invalid keys are filtered (using passthrough copy)", (t) => { let map = new EleventyExtensionMap(["lksdjfjlsk"]); map.config = { - passthroughFileCopy: true + passthroughFileCopy: true, }; t.deepEqual(map.getGlobs("."), ["./**/*.lksdjfjlsk"]); }); -test("Keys are mapped to lower case", t => { +test("Keys are mapped to lower case", (t) => { let map = new EleventyExtensionMap(["PUG", "NJK"]); t.deepEqual(map.getGlobs("."), ["./**/*.pug", "./**/*.njk"]); }); -test("Pruned globs", t => { +test("Pruned globs", (t) => { let map = new EleventyExtensionMap(["pug", "njk", "png"]); t.deepEqual(map.getPassthroughCopyGlobs("."), ["./**/*.png"]); }); -test("Empty path for fileList", t => { +test("Empty path for fileList", (t) => { let map = new EleventyExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList(), []); }); -test("fileList", t => { +test("fileList", (t) => { let map = new EleventyExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("filename"), ["filename.njk", "filename.pug"]); }); -test("fileList with dir", t => { +test("fileList with dir", (t) => { let map = new EleventyExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("filename", "_includes"), [ "_includes/filename.njk", - "_includes/filename.pug" + "_includes/filename.pug", ]); }); -test("fileList with dir in path", t => { +test("fileList with dir in path", (t) => { let map = new EleventyExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("layouts/filename"), [ "layouts/filename.njk", - "layouts/filename.pug" + "layouts/filename.pug", ]); }); -test("fileList with dir in path and dir", t => { +test("fileList with dir in path and dir", (t) => { let map = new EleventyExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("layouts/filename", "_includes"), [ "_includes/layouts/filename.njk", - "_includes/layouts/filename.pug" + "_includes/layouts/filename.pug", ]); }); -test("removeTemplateExtension", t => { +test("removeTemplateExtension", (t) => { let map = new EleventyExtensionMap(["njk", "11ty.js"]); t.is(map.removeTemplateExtension("component.njk"), "component"); t.is(map.removeTemplateExtension("component.11ty.js"), "component"); @@ -86,13 +86,13 @@ test("removeTemplateExtension", t => { t.is(map.removeTemplateExtension("component.js"), "component.js"); }); -test("hasEngine", t => { +test("hasEngine", (t) => { let map = new EleventyExtensionMap([ "liquid", "njk", "11ty.js", "ejs", - "pug" + "pug", ]); t.true(map.hasEngine("default.ejs")); t.is(map.getKey("default.ejs"), "ejs"); @@ -110,7 +110,7 @@ test("hasEngine", t => { t.true(map.hasEngine("md")); }); -test("hasEngine no formats passed in", t => { +test("hasEngine no formats passed in", (t) => { let map = new EleventyExtensionMap([]); t.true(map.hasEngine("default.ejs")); t.is(map.getKey("default.ejs"), "ejs"); @@ -129,7 +129,7 @@ test("hasEngine no formats passed in", t => { t.true(map.hasEngine("md")); }); -test("getKey", t => { +test("getKey", (t) => { let map = new EleventyExtensionMap(["njk", "11ty.js", "md"]); t.is(map.getKey("component.njk"), "njk"); t.is(map.getKey("component.11ty.js"), "11ty.js"); diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 96cef0d7a..04026c8d8 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -1,10 +1,10 @@ -import test from "ava"; -import fastglob from "fast-glob"; -import EleventyFiles from "../src/EleventyFiles"; -import TemplatePath from "../src/TemplatePath"; -import TemplatePassthroughManager from "../src/TemplatePassthroughManager"; +const test = require("ava"); +const fastglob = require("fast-glob"); +const EleventyFiles = require("../src/EleventyFiles"); +const TemplatePath = require("../src/TemplatePath"); +const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); -test("getFiles", async t => { +test("getFiles", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTest", "./test/stubs/_writeTestSite", @@ -15,7 +15,7 @@ test("getFiles", async t => { t.deepEqual(await evf.getFiles(), ["./test/stubs/writeTest/test.md"]); }); -test("getFiles (without 11ty.js)", async t => { +test("getFiles (without 11ty.js)", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", @@ -26,7 +26,7 @@ test("getFiles (without 11ty.js)", async t => { t.deepEqual(await evf.getFiles(), []); }); -test("getFiles (with 11ty.js)", async t => { +test("getFiles (with 11ty.js)", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", @@ -37,7 +37,7 @@ test("getFiles (with 11ty.js)", async t => { t.deepEqual(await evf.getFiles(), ["./test/stubs/writeTestJS/test.11ty.js"]); }); -test("getFiles (with js, treated as passthrough copy)", async t => { +test("getFiles (with js, treated as passthrough copy)", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", @@ -50,7 +50,7 @@ test("getFiles (with js, treated as passthrough copy)", async t => { files.sort(), [ "./test/stubs/writeTestJS/sample.js", - "./test/stubs/writeTestJS/test.11ty.js" + "./test/stubs/writeTestJS/test.11ty.js", ].sort() ); @@ -58,7 +58,7 @@ test("getFiles (with js, treated as passthrough copy)", async t => { t.true(evf.extensionMap.hasEngine("./test/stubs/writeTestJS/test.11ty.js")); }); -test("getFiles (with case insensitivity)", async t => { +test("getFiles (with case insensitivity)", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTestJS-casesensitive", "./test/stubs/_writeTestJSCaseSensitiveSite", @@ -70,7 +70,7 @@ test("getFiles (with case insensitivity)", async t => { (await evf.getFiles()).sort(), [ "./test/stubs/writeTestJS-casesensitive/sample.Js", - "./test/stubs/writeTestJS-casesensitive/test.11Ty.js" + "./test/stubs/writeTestJS-casesensitive/test.11Ty.js", ].sort() ); t.false( @@ -85,7 +85,7 @@ test("getFiles (with case insensitivity)", async t => { ); }); -test("Mutually exclusive Input and Output dirs", async t => { +test("Mutually exclusive Input and Output dirs", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTest", "./test/stubs/_writeTestSite", @@ -99,10 +99,10 @@ test("Mutually exclusive Input and Output dirs", async t => { t.is(files[0], "./test/stubs/writeTest/test.md"); }); -test("Single File Input (deep path)", async t => { +test("Single File Input (deep path)", async (t) => { let evf = new EleventyFiles("./test/stubs/index.html", "./test/stubs/_site", [ "ejs", - "md" + "md", ]); evf.init(); @@ -112,18 +112,18 @@ test("Single File Input (deep path)", async t => { t.is(files[0], "./test/stubs/index.html"); }); -test("Single File Input (shallow path)", async t => { +test("Single File Input (shallow path)", async (t) => { let evf = new EleventyFiles("README.md", "./test/stubs/_site", ["md"]); evf.init(); - let globs = evf.getFileGlobs().filter(path => path !== "!./README.md"); + let globs = evf.getFileGlobs().filter((path) => path !== "!./README.md"); let files = await fastglob(globs); t.is(evf.getRawFiles().length, 1); t.is(files.length, 1); t.is(files[0], "./README.md"); }); -test("Glob Input", async t => { +test("Glob Input", async (t) => { let evf = new EleventyFiles( "./test/stubs/glob-pages/!(contact.md)", "./test/stubs/_site", @@ -139,17 +139,17 @@ test("Glob Input", async t => { t.is(files[1], "./test/stubs/glob-pages/home.md"); }); -test(".eleventyignore parsing", t => { +test(".eleventyignore parsing", (t) => { let ignores = EleventyFiles.getFileIgnores("./test/stubs/.eleventyignore"); t.is(ignores.length, 2); t.is(ignores[0], "!./test/stubs/ignoredFolder/**"); t.is(ignores[1], "!./test/stubs/ignoredFolder/ignored.md"); }); -test("Parse multiple .eleventyignores", t => { +test("Parse multiple .eleventyignores", (t) => { let ignores = EleventyFiles.getFileIgnores([ "./test/stubs/multiple-ignores/.eleventyignore", - "./test/stubs/multiple-ignores/subfolder/.eleventyignore" + "./test/stubs/multiple-ignores/subfolder/.eleventyignore", ]); t.is(ignores.length, 4); // Note these folders must exist! @@ -165,7 +165,7 @@ test("Parse multiple .eleventyignores", t => { ); }); -test("defaults if passed file name does not exist", t => { +test("defaults if passed file name does not exist", (t) => { let ignores = EleventyFiles.getFileIgnores( ".thisfiledoesnotexist", "node_modules/**" @@ -174,7 +174,7 @@ test("defaults if passed file name does not exist", t => { t.is(ignores[0], "!./node_modules/**"); }); -test(".eleventyignore files", async t => { +test(".eleventyignore files", async (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["ejs", "md"]); evf.init(); let ignoredFiles = await fastglob("test/stubs/ignoredFolder/*.md"); @@ -185,7 +185,7 @@ test(".eleventyignore files", async t => { t.true(files.length > 0); t.is( - files.filter(file => { + files.filter((file) => { return file.indexOf("./test/stubs/ignoredFolder") > -1; }).length, 0 @@ -193,7 +193,7 @@ test(".eleventyignore files", async t => { }); /* .eleventyignore and .gitignore combos */ -test("Get ignores (no .eleventyignore no .gitignore)", t => { +test("Get ignores (no .eleventyignore no .gitignore)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore1", "test/stubs/ignore1/_site", @@ -208,11 +208,11 @@ test("Get ignores (no .eleventyignore no .gitignore)", t => { "!./test/stubs/ignorelocalroot/node_modules/**", "!./test/stubs/ignore1/node_modules/**", "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore1/_site/**" + "!./test/stubs/ignore1/_site/**", ]); }); -test("Get ignores (no .eleventyignore)", t => { +test("Get ignores (no .eleventyignore)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore2", "test/stubs/ignore2/_site", @@ -224,11 +224,11 @@ test("Get ignores (no .eleventyignore)", t => { t.deepEqual(evf.getIgnores(), [ "!./test/stubs/ignore2/thisshouldnotexist12345", "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore2/_site/**" + "!./test/stubs/ignore2/_site/**", ]); }); -test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", t => { +test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", (t) => { let evf = new EleventyFiles( "test/stubs/ignore2", "test/stubs/ignore2/_site", @@ -239,18 +239,18 @@ test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", t => { evf._setConfig({ useGitIgnore: false, dir: { - includes: "_includes" - } + includes: "_includes", + }, }); evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore2/_site/**" + "!./test/stubs/ignore2/_site/**", ]); }); -test("Get ignores (no .gitignore)", t => { +test("Get ignores (no .gitignore)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore3", "test/stubs/ignore3/_site", @@ -266,11 +266,11 @@ test("Get ignores (no .gitignore)", t => { "!./test/stubs/ignorelocalroot/test.md", "!./test/stubs/ignore3/ignoredFolder/**", "!./test/stubs/ignore3/ignoredFolder/ignored.md", - "!./test/stubs/ignore3/_site/**" + "!./test/stubs/ignore3/_site/**", ]); }); -test("Get ignores (both .eleventyignore and .gitignore)", t => { +test("Get ignores (both .eleventyignore and .gitignore)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore4", "test/stubs/ignore4/_site", @@ -284,11 +284,11 @@ test("Get ignores (both .eleventyignore and .gitignore)", t => { "!./test/stubs/ignorelocalroot/test.md", "!./test/stubs/ignore4/ignoredFolder/**", "!./test/stubs/ignore4/ignoredFolder/ignored.md", - "!./test/stubs/ignore4/_site/**" + "!./test/stubs/ignore4/_site/**", ]); }); -test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(false))", t => { +test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(false))", (t) => { let evf = new EleventyFiles( "test/stubs/ignore4", "test/stubs/ignore4/_site", @@ -299,8 +299,8 @@ test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(fa evf._setConfig({ useGitIgnore: false, dir: { - includes: "_includes" - } + includes: "_includes", + }, }); evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); @@ -308,11 +308,11 @@ test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(fa "!./test/stubs/ignorelocalroot/test.md", "!./test/stubs/ignore4/ignoredFolder/**", "!./test/stubs/ignore4/ignoredFolder/ignored.md", - "!./test/stubs/ignore4/_site/**" + "!./test/stubs/ignore4/_site/**", ]); }); -test("Get ignores (no .eleventyignore .gitignore exists but empty)", t => { +test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore5", "test/stubs/ignore5/_site", @@ -327,11 +327,11 @@ test("Get ignores (no .eleventyignore .gitignore exists but empty)", t => { "!./test/stubs/ignorelocalroot/node_modules/**", "!./test/stubs/ignore5/node_modules/**", "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore5/_site/**" + "!./test/stubs/ignore5/_site/**", ]); }); -test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is empty)", t => { +test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is empty)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore6", "test/stubs/ignore6/_site", @@ -347,11 +347,11 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is "!./test/stubs/ignorelocalroot/test.md", "!./test/stubs/ignore6/ignoredFolder/**", "!./test/stubs/ignore6/ignoredFolder/ignored.md", - "!./test/stubs/ignore6/_site/**" + "!./test/stubs/ignore6/_site/**", ]); }); -test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)", t => { +test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore7", "test/stubs/ignore7/_site", @@ -366,11 +366,11 @@ test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)" "!./test/stubs/ignorelocalroot/node_modules/**", "!./test/stubs/ignore7/node_modules/**", "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore7/_site/**" + "!./test/stubs/ignore7/_site/**", ]); }); -test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore has spaces inside)", t => { +test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore has spaces inside)", (t) => { let evf = new EleventyFiles( "test/stubs/ignore8", "test/stubs/ignore8/_site", @@ -386,12 +386,12 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore ha "!./test/stubs/ignorelocalroot/test.md", "!./test/stubs/ignore8/ignoredFolder/**", "!./test/stubs/ignore8/ignoredFolder/ignored.md", - "!./test/stubs/ignore8/_site/**" + "!./test/stubs/ignore8/_site/**", ]); }); /* End .eleventyignore and .gitignore combos */ -test("getTemplateData caching", t => { +test("getTemplateData caching", (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); let templateDataFirstCall = evf.getTemplateData(); @@ -399,39 +399,39 @@ test("getTemplateData caching", t => { t.is(templateDataFirstCall, templateDataSecondCall); }); -test("getDataDir", t => { +test("getDataDir", (t) => { let evf = new EleventyFiles(".", "_site", []); evf.init(); t.is(evf.getDataDir(), "_data"); }); -test("getDataDir subdir", t => { +test("getDataDir subdir", (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); t.is(evf.getDataDir(), "test/stubs/_data"); }); -test("Include and Data Dirs", t => { +test("Include and Data Dirs", (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); t.deepEqual(evf._getIncludesAndDataDirs(), [ "./test/stubs/_includes/**", - "./test/stubs/_data/**" + "./test/stubs/_data/**", ]); }); -test("Ignore Include and Data Dirs", t => { +test("Ignore Include and Data Dirs", (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); t.deepEqual(evf._getIncludesAndDataDirIgnores(), [ "!./test/stubs/_includes/**", - "!./test/stubs/_data/**" + "!./test/stubs/_data/**", ]); }); -test("Input to 'src' and empty includes dir (issue #403)", t => { +test("Input to 'src' and empty includes dir (issue #403)", (t) => { let evf = new EleventyFiles("src", "src/_site", ["md", "liquid", "html"]); evf._setConfig({ useGitIgnore: false, @@ -440,8 +440,8 @@ test("Input to 'src' and empty includes dir (issue #403)", t => { input: ".", output: "_site", includes: "", - data: "_data" - } + data: "_data", + }, }); evf.init(); @@ -451,13 +451,13 @@ test("Input to 'src' and empty includes dir (issue #403)", t => { "./src/**/*.html", "!./src/_includes/**", "!./src/_site/**", - "!./src/_data/**" + "!./src/_data/**", ]); }); -test("Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async t => { +test("Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { let evf = new EleventyFiles("test/stubs-403", "test/stubs-403/_site", [ - "liquid" + "liquid", ]); evf._setConfig({ useGitIgnore: false, @@ -467,21 +467,21 @@ test("Bad expected output, this indicates a bug upstream in a dependency. Input input: "test/stubs-403", output: "_site", includes: "", - data: false - } + data: false, + }, }); evf.init(); t.deepEqual(await evf.getFiles(), [ "./test/stubs-403/template.liquid", // This is bad, because it uses an absolutePath above. it should be excluded - "./test/stubs-403/_includes/include.liquid" + "./test/stubs-403/_includes/include.liquid", ]); }); -test("Workaround for Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async t => { +test("Workaround for Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { let evf = new EleventyFiles("test/stubs-403", "test/stubs-403/_site", [ - "liquid" + "liquid", ]); evf._setConfig({ useGitIgnore: false, @@ -490,17 +490,17 @@ test("Workaround for Bad expected output, this indicates a bug upstream in a dep input: "test/stubs-403", output: "_site", includes: "", - data: false - } + data: false, + }, }); evf.init(); t.deepEqual(await evf.getFiles(), ["./test/stubs-403/template.liquid"]); }); -test("Issue #403: all .eleventyignores should be relative paths not absolute paths", async t => { +test("Issue #403: all .eleventyignores should be relative paths not absolute paths", async (t) => { let evf = new EleventyFiles("test/stubs-403", "test/stubs-403/_site", [ - "liquid" + "liquid", ]); evf._setConfig({ useGitIgnore: false, @@ -508,32 +508,32 @@ test("Issue #403: all .eleventyignores should be relative paths not absolute pat input: "test/stubs-403", output: "_site", includes: "", - data: false - } + data: false, + }, }); evf.init(); let globs = await evf.getFileGlobs(); t.is( - globs.filter(glob => { + globs.filter((glob) => { return glob.indexOf(TemplatePath.absolutePath()) > -1; }).length, 0 ); }); -test("Glob Watcher Files", async t => { +test("Glob Watcher Files", async (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["njk"]); evf.init(); t.deepEqual(evf.getGlobWatcherFiles(), [ "./test/stubs/**/*.njk", "./test/stubs/_includes/**", - "./test/stubs/_data/**" + "./test/stubs/_data/**", ]); }); -test("Glob Watcher Files with File Extension Passthroughs", async t => { +test("Glob Watcher Files with File Extension Passthroughs", async (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["njk", "png"]); evf.init(); @@ -541,11 +541,11 @@ test("Glob Watcher Files with File Extension Passthroughs", async t => { "./test/stubs/**/*.njk", "./test/stubs/**/*.png", "./test/stubs/_includes/**", - "./test/stubs/_data/**" + "./test/stubs/_data/**", ]); }); -test("Glob Watcher Files with Config Passthroughs (one template format)", async t => { +test("Glob Watcher Files with Config Passthroughs (one template format)", async (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["njk"]); evf.init(); @@ -555,8 +555,8 @@ test("Glob Watcher Files with Config Passthroughs (one template format)", async mgr.setConfig({ passthroughFileCopy: true, passthroughCopies: { - "test/stubs/img/": true - } + "test/stubs/img/": true, + }, }); evf.setPassthroughManager(mgr); @@ -564,29 +564,29 @@ test("Glob Watcher Files with Config Passthroughs (one template format)", async "./test/stubs/**/*.njk", "./test/stubs/img/**", "./test/stubs/_includes/**", - "./test/stubs/_data/**" + "./test/stubs/_data/**", ]); }); -test("Glob Watcher Files with Config Passthroughs (no template formats)", async t => { +test("Glob Watcher Files with Config Passthroughs (no template formats)", async (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); t.deepEqual(await evf.getGlobWatcherTemplateDataFiles(), [ "./test/stubs/**/*.json", "./test/stubs/**/*.11tydata.cjs", - "./test/stubs/**/*.11tydata.js" + "./test/stubs/**/*.11tydata.js", ]); }); -test("Glob Watcher Files with passthroughAll", async t => { +test("Glob Watcher Files with passthroughAll", async (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", [], true); evf.init(); t.is((await evf.getFileGlobs())[0], "./test/stubs/**"); }); -test("Test that negations are ignored (for now) PR#709, will change when #693 is implemented", async t => { +test("Test that negations are ignored (for now) PR#709, will change when #693 is implemented", async (t) => { t.deepEqual( EleventyFiles.normalizeIgnoreContent( "./", diff --git a/test/EleventyServeTest.js b/test/EleventyServeTest.js index 3fedc9002..7a507ac39 100644 --- a/test/EleventyServeTest.js +++ b/test/EleventyServeTest.js @@ -1,22 +1,22 @@ -import test from "ava"; -import EleventyServe from "../src/EleventyServe"; +const test = require("ava"); +const EleventyServe = require("../src/EleventyServe"); -test("Constructor", t => { +test("Constructor", (t) => { let es = new EleventyServe(); t.is(es.getPathPrefix(), "/"); }); -test("Directories", t => { +test("Directories", (t) => { let es = new EleventyServe(); es.setOutputDir("_site"); t.is(es.getRedirectDir("test"), "_site/test"); t.is(es.getRedirectFilename("test"), "_site/test/index.html"); }); -test("Get Options", t => { +test("Get Options", (t) => { let es = new EleventyServe(); es.config = { - pathPrefix: "/" + pathPrefix: "/", }; es.setOutputDir("_site"); @@ -27,16 +27,16 @@ test("Get Options", t => { open: false, port: 8080, server: { - baseDir: "_site" + baseDir: "_site", }, - watch: false + watch: false, }); }); -test("Get Options (with a pathPrefix)", t => { +test("Get Options (with a pathPrefix)", (t) => { let es = new EleventyServe(); es.config = { - pathPrefix: "/web/" + pathPrefix: "/web/", }; es.setOutputDir("_site"); @@ -49,20 +49,20 @@ test("Get Options (with a pathPrefix)", t => { server: { baseDir: "_site/_eleventy_redirect", routes: { - "/web/": "_site" - } + "/web/": "_site", + }, }, - watch: false + watch: false, }); }); -test("Get Options (override in config)", t => { +test("Get Options (override in config)", (t) => { let es = new EleventyServe(); es.config = { pathPrefix: "/", browserSyncConfig: { - notify: true - } + notify: true, + }, }; es.setOutputDir("_site"); @@ -73,8 +73,8 @@ test("Get Options (override in config)", t => { open: false, port: 8080, server: { - baseDir: "_site" + baseDir: "_site", }, - watch: false + watch: false, }); }); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 6d52bc36a..4a7e753aa 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -1,11 +1,11 @@ -import test from "ava"; -import Eleventy from "../src/Eleventy"; -import EleventyWatchTargets from "../src/EleventyWatchTargets"; -import templateConfig from "../src/Config"; +const test = require("ava"); +const Eleventy = require("../src/Eleventy"); +const EleventyWatchTargets = require("../src/EleventyWatchTargets"); +const templateConfig = require("../src/Config"); const config = templateConfig.getConfig(); -test("Eleventy, defaults inherit from config", async t => { +test("Eleventy, defaults inherit from config", async (t) => { let elev = new Eleventy(); t.truthy(elev.input); @@ -14,26 +14,26 @@ test("Eleventy, defaults inherit from config", async t => { t.is(elev.outputDir, config.dir.output); }); -test("Eleventy, get version", t => { +test("Eleventy, get version", (t) => { let elev = new Eleventy(); t.truthy(elev.getVersion()); }); -test("Eleventy, get help", t => { +test("Eleventy, get help", (t) => { let elev = new Eleventy(); t.truthy(elev.getHelp()); }); -test("Eleventy, set is verbose", t => { +test("Eleventy, set is verbose", (t) => { let elev = new Eleventy(); elev.setIsVerbose(true); t.true(elev.isVerbose); }); -test("Eleventy set input/output", async t => { +test("Eleventy set input/output", async (t) => { let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); t.is(elev.input, "./test/stubs"); @@ -44,7 +44,7 @@ test("Eleventy set input/output", async t => { t.truthy(elev.writer); }); -test("Eleventy file watching", async t => { +test("Eleventy file watching", async (t) => { let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); elev.setFormats("njk"); @@ -59,11 +59,11 @@ test("Eleventy file watching", async t => { "./test/stubs/**/*.11tydata.cjs", "./test/stubs/**/*.11tydata.js", "./test/stubs/deps/dep1.js", - "./test/stubs/deps/dep2.js" + "./test/stubs/deps/dep2.js", ]); }); -test("Eleventy file watching (no JS dependencies)", async t => { +test("Eleventy file watching (no JS dependencies)", async (t) => { let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); elev.setFormats("njk"); @@ -80,11 +80,11 @@ test("Eleventy file watching (no JS dependencies)", async t => { "./.eleventy.js", "./test/stubs/**/*.json", "./test/stubs/**/*.11tydata.cjs", - "./test/stubs/**/*.11tydata.js" + "./test/stubs/**/*.11tydata.js", ]); }); -test("Eleventy set input/output, one file input", async t => { +test("Eleventy set input/output, one file input", async (t) => { let elev = new Eleventy("./test/stubs/index.html", "./test/stubs/_site"); t.is(elev.input, "./test/stubs/index.html"); @@ -92,7 +92,7 @@ test("Eleventy set input/output, one file input", async t => { t.is(elev.outputDir, "./test/stubs/_site"); }); -test("Eleventy set input/output, one file input root dir", async t => { +test("Eleventy set input/output, one file input root dir", async (t) => { let elev = new Eleventy("./README.md", "./test/stubs/_site"); t.is(elev.input, "./README.md"); @@ -100,7 +100,7 @@ test("Eleventy set input/output, one file input root dir", async t => { t.is(elev.outputDir, "./test/stubs/_site"); }); -test("Eleventy set input/output, one file input root dir without leading dot/slash", async t => { +test("Eleventy set input/output, one file input root dir without leading dot/slash", async (t) => { let elev = new Eleventy("README.md", "./test/stubs/_site"); t.is(elev.input, "README.md"); @@ -108,7 +108,7 @@ test("Eleventy set input/output, one file input root dir without leading dot/sla t.is(elev.outputDir, "./test/stubs/_site"); }); -test("Eleventy set input/output, one file input exitCode", async t => { +test("Eleventy set input/output, one file input exitCode", async (t) => { let previousExitCode = process.exitCode; let elev = new Eleventy( "./test/stubs/exitCode/failure.njk", @@ -117,9 +117,9 @@ test("Eleventy set input/output, one file input exitCode", async t => { // TODO make this output quieter elev.setLogger({ - log: function() {}, - warn: function() {}, - error: function() {} + log: function () {}, + warn: function () {}, + error: function () {}, }); await elev.init(); diff --git a/test/EleventyWatchTargetsTest.js b/test/EleventyWatchTargetsTest.js index b042a182b..62cabc215 100644 --- a/test/EleventyWatchTargetsTest.js +++ b/test/EleventyWatchTargetsTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import EleventyWatchTargets from "../src/EleventyWatchTargets"; +const test = require("ava"); +const EleventyWatchTargets = require("../src/EleventyWatchTargets"); -test("Basic", t => { +test("Basic", (t) => { let targets = new EleventyWatchTargets(); t.deepEqual(targets.getTargets(), []); @@ -9,7 +9,7 @@ test("Basic", t => { t.deepEqual(targets.getTargets(), ["./.eleventy.js"]); }); -test("Removes duplicates", t => { +test("Removes duplicates", (t) => { let targets = new EleventyWatchTargets(); targets.add(".eleventy.js"); @@ -17,7 +17,7 @@ test("Removes duplicates", t => { t.deepEqual(targets.getTargets(), ["./.eleventy.js"]); }); -test("Add array", t => { +test("Add array", (t) => { let targets = new EleventyWatchTargets(); targets.add([".eleventy.js", "b.js"]); @@ -25,7 +25,7 @@ test("Add array", t => { t.deepEqual(targets.getTargets(), ["./.eleventy.js", "./b.js", "./c.js"]); }); -test("Add and make glob", t => { +test("Add and make glob", (t) => { let targets = new EleventyWatchTargets(); // Note the `test` directory must exist here for this to pass. @@ -33,7 +33,7 @@ test("Add and make glob", t => { t.deepEqual(targets.getTargets(), ["./test/**", "./test/b.js"]); }); -test("JavaScript get dependencies", t => { +test("JavaScript get dependencies", (t) => { let targets = new EleventyWatchTargets(); t.deepEqual( targets.getJavaScriptDependenciesFromList(["./test/stubs/config-deps.js"]), @@ -41,64 +41,64 @@ test("JavaScript get dependencies", t => { ); }); -test("JavaScript addDependencies", t => { +test("JavaScript addDependencies", (t) => { let targets = new EleventyWatchTargets(); targets.addDependencies("./test/stubs/config-deps.js"); t.deepEqual(targets.getTargets(), ["./test/stubs/config-deps-upstream.js"]); }); -test("JavaScript addDependencies (one file has two dependencies)", t => { +test("JavaScript addDependencies (one file has two dependencies)", (t) => { let targets = new EleventyWatchTargets(); targets.addDependencies("./test/stubs/dependencies/two-deps.11ty.js"); t.deepEqual(targets.getTargets(), [ "./test/stubs/dependencies/dep1.js", - "./test/stubs/dependencies/dep2.js" + "./test/stubs/dependencies/dep2.js", ]); }); -test("JavaScript addDependencies (skip JS deps)", t => { +test("JavaScript addDependencies (skip JS deps)", (t) => { let targets = new EleventyWatchTargets(); targets.watchJavaScriptDependencies = false; targets.addDependencies("./test/stubs/dependencies/two-deps.11ty.js"); t.deepEqual(targets.getTargets(), []); }); -test("JavaScript addDependencies with a filter", t => { +test("JavaScript addDependencies with a filter", (t) => { let targets = new EleventyWatchTargets(); - targets.addDependencies("./test/stubs/config-deps.js", function(path) { + targets.addDependencies("./test/stubs/config-deps.js", function (path) { return path.indexOf("./test/stubs/") === -1; }); t.deepEqual(targets.getTargets(), []); }); -test("add, addDependencies falsy values are filtered", t => { +test("add, addDependencies falsy values are filtered", (t) => { let targets = new EleventyWatchTargets(); targets.add(""); targets.addDependencies(""); t.deepEqual(targets.getTargets(), []); }); -test("add, addDependencies file does not exist", t => { +test("add, addDependencies file does not exist", (t) => { let targets = new EleventyWatchTargets(); targets.add("./.eleventy-notfound.js"); // does not exist targets.addDependencies("./.eleventy-notfound.js"); // does not exist t.deepEqual(targets.getTargets(), ["./.eleventy-notfound.js"]); }); -test("getNewTargetsSinceLastReset", t => { +test("getNewTargetsSinceLastReset", (t) => { let targets = new EleventyWatchTargets(); targets.add("./.eleventy-notfound.js"); // does not exist t.deepEqual(targets.getNewTargetsSinceLastReset(), [ - "./.eleventy-notfound.js" + "./.eleventy-notfound.js", ]); t.deepEqual(targets.getNewTargetsSinceLastReset(), [ - "./.eleventy-notfound.js" + "./.eleventy-notfound.js", ]); targets.reset(); targets.add("./.eleventy-notfound2.js"); t.deepEqual(targets.getNewTargetsSinceLastReset(), [ - "./.eleventy-notfound2.js" + "./.eleventy-notfound2.js", ]); targets.reset(); diff --git a/test/EleventyWatchTest.js b/test/EleventyWatchTest.js index e7f26cd7b..8e9797e15 100644 --- a/test/EleventyWatchTest.js +++ b/test/EleventyWatchTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import EleventyWatch from "../src/EleventyWatch"; +const test = require("ava"); +const EleventyWatch = require("../src/EleventyWatch"); -test("Standard", t => { +test("Standard", (t) => { let watch = new EleventyWatch(); t.is(watch.isBuildRunning(), false); @@ -12,7 +12,7 @@ test("Standard", t => { t.is(watch.isBuildRunning(), false); }); -test("Incremental", t => { +test("Incremental", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); @@ -36,7 +36,7 @@ test("Incremental", t => { t.is(watch.getIncrementalFile(), false); }); -test("Incremental queue 2", t => { +test("Incremental queue 2", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); @@ -61,7 +61,7 @@ test("Incremental queue 2", t => { t.is(watch.getIncrementalFile(), false); }); -test("Incremental add while active", t => { +test("Incremental add while active", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); @@ -90,7 +90,7 @@ test("Incremental add while active", t => { t.is(watch.getIncrementalFile(), false); }); -test("Non-incremental", t => { +test("Non-incremental", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); @@ -113,7 +113,7 @@ test("Non-incremental", t => { t.is(watch.getIncrementalFile(), false); }); -test("Non-incremental queue 2", t => { +test("Non-incremental queue 2", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); @@ -137,7 +137,7 @@ test("Non-incremental queue 2", t => { t.is(watch.getIncrementalFile(), false); }); -test("Non-incremental add while active", t => { +test("Non-incremental add while active", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); @@ -165,25 +165,25 @@ test("Non-incremental add while active", t => { t.is(watch.getIncrementalFile(), false); }); -test("Active queue tests", t => { +test("Active queue tests", (t) => { let watch = new EleventyWatch(); watch.addToPendingQueue("test.md"); watch.addToPendingQueue("test2.md"); watch.addToPendingQueue("test.css"); t.is( - watch.hasAllQueueFiles(path => path.startsWith("./test")), + watch.hasAllQueueFiles((path) => path.startsWith("./test")), false ); watch.setBuildRunning(); t.is(watch.hasAllQueueFiles("slkdjflkjsdlkfj"), false); t.is( - watch.hasAllQueueFiles(path => path.startsWith("./test")), + watch.hasAllQueueFiles((path) => path.startsWith("./test")), true ); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), false ); @@ -192,31 +192,31 @@ test("Active queue tests", t => { watch.setBuildFinished(); t.is( - watch.hasAllQueueFiles(path => path.startsWith("./test")), + watch.hasAllQueueFiles((path) => path.startsWith("./test")), false ); }); -test("Active queue tests, all CSS files", t => { +test("Active queue tests, all CSS files", (t) => { let watch = new EleventyWatch(); watch.addToPendingQueue("test.css"); watch.addToPendingQueue("test2.css"); watch.addToPendingQueue("test3.css"); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), false ); watch.setBuildRunning(); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), true ); watch.setBuildFinished(); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), false ); }); diff --git a/test/GetCollectionItemTest.js b/test/GetCollectionItemTest.js index 182ba130b..9f790e36e 100644 --- a/test/GetCollectionItemTest.js +++ b/test/GetCollectionItemTest.js @@ -1,18 +1,18 @@ -import test from "ava"; -import getCollectionItem from "../src/Filters/GetCollectionItem"; +const test = require("ava"); +const getCollectionItem = require("../src/Filters/GetCollectionItem"); -test("getCollectionItem", t => { +test("getCollectionItem", (t) => { let first = { inputPath: "hello.md", - outputPath: "/hello/" + outputPath: "/hello/", }; let second = { inputPath: "hello2.md", - outputPath: "/hello2/" + outputPath: "/hello2/", }; let third = { inputPath: "hello3.md", - outputPath: "/hello3/" + outputPath: "/hello3/", }; let collections = [first, second, third]; diff --git a/test/MergeTest.js b/test/MergeTest.js index ded2bb252..b27f0b7da 100644 --- a/test/MergeTest.js +++ b/test/MergeTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import Merge from "../src/Util/Merge"; +const test = require("ava"); +const Merge = require("../src/Util/Merge"); -test("Shallow Merge", t => { +test("Shallow Merge", (t) => { t.deepEqual(Merge({}, {}), {}); t.deepEqual(Merge({ a: 1 }, { a: 2 }), { a: 2 }); t.deepEqual(Merge({ a: 1 }, { a: 2 }, { a: 3 }), { a: 3 }); @@ -12,55 +12,55 @@ test("Shallow Merge", t => { t.deepEqual(Merge({ a: [1] }, { a: [2] }), { a: [1, 2] }); }); -test("Doesn’t need to return", t => { +test("Doesn’t need to return", (t) => { var b = { a: 2 }; Merge(b, { a: 1 }); t.deepEqual(b, { a: 1 }); }); -test("Invalid", t => { +test("Invalid", (t) => { t.deepEqual(Merge({}, 1), {}); t.deepEqual(Merge({}, [1]), {}); t.deepEqual(Merge({}, "string"), {}); }); -test("Deep", t => { +test("Deep", (t) => { t.deepEqual(Merge({ a: { b: 1 } }, { a: { c: 1 } }), { a: { b: 1, c: 1 } }); }); -test("Deep, override: prefix", t => { +test("Deep, override: prefix", (t) => { t.deepEqual(Merge({ a: { b: [1, 2] } }, { a: { b: [3, 4] } }), { - a: { b: [1, 2, 3, 4] } + a: { b: [1, 2, 3, 4] }, }); t.deepEqual(Merge({ a: [1] }, { a: [2] }), { a: [1, 2] }); t.deepEqual(Merge({ a: [1] }, { "override:a": [2] }), { a: [2] }); t.deepEqual(Merge({ a: { b: [1, 2] } }, { a: { "override:b": [3, 4] } }), { - a: { b: [3, 4] } + a: { b: [3, 4] }, }); }); -test("Deep, override: prefix at root", t => { +test("Deep, override: prefix at root", (t) => { t.deepEqual(Merge({ "override:a": [1] }, { a: [2] }), { a: [1, 2] }); }); -test("Deep, override: prefix at other placements", t => { +test("Deep, override: prefix at other placements", (t) => { t.deepEqual( Merge( { a: { - a: [1] - } + a: [1], + }, }, { a: { - a: [2] - } + a: [2], + }, } ), { a: { - a: [1, 2] - } + a: [1, 2], + }, } ); @@ -68,19 +68,19 @@ test("Deep, override: prefix at other placements", t => { Merge( { a: { - a: [1] - } + a: [1], + }, }, { a: { - "override:a": [2] - } + "override:a": [2], + }, } ), { a: { - a: [2] - } + a: [2], + }, } ); @@ -88,19 +88,19 @@ test("Deep, override: prefix at other placements", t => { Merge( { "override:a": { - a: [1] - } + a: [1], + }, }, { a: { - a: [2] - } + a: [2], + }, } ), { a: { - a: [1, 2] - } + a: [1, 2], + }, } ); @@ -109,19 +109,19 @@ test("Deep, override: prefix at other placements", t => { { a: { a: [1], - b: [1] - } + b: [1], + }, }, { "override:a": { - a: [2] - } + a: [2], + }, } ), { a: { - a: [2] - } + a: [2], + }, } ); @@ -130,29 +130,29 @@ test("Deep, override: prefix at other placements", t => { { a: { a: { - a: [1] - } - } + a: [1], + }, + }, }, { a: { "override:a": { - a: [2] - } - } + a: [2], + }, + }, } ), { a: { a: { - a: [2] - } - } + a: [2], + }, + }, } ); }); -test("Deep, override: empty", t => { +test("Deep, override: empty", (t) => { t.deepEqual(Merge({}, { a: { b: [3, 4] } }), { a: { b: [3, 4] } }); t.deepEqual(Merge({}, { a: [2] }), { a: [2] }); t.deepEqual(Merge({}, { "override:a": [2] }), { a: [2] }); diff --git a/test/PaginationTest.js b/test/PaginationTest.js index f0e807cb2..33a95e08d 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -1,9 +1,9 @@ -import test from "ava"; -import Template from "../src/Template"; -import TemplateData from "../src/TemplateData"; -import Pagination from "../src/Plugins/Pagination"; +const test = require("ava"); +const Template = require("../src/Template"); +const TemplateData = require("../src/TemplateData"); +const Pagination = require("../src/Plugins/Pagination"); -test("No data passed to pagination", async t => { +test("No data passed to pagination", async (t) => { let tmpl = new Template( "./test/stubs/paged/notpaged.njk", "./test/stubs/", @@ -17,7 +17,7 @@ test("No data passed to pagination", async t => { t.is((await paging.getPageTemplates()).length, 0); }); -test("No pagination", async t => { +test("No pagination", async (t) => { let tmpl = new Template( "./test/stubs/paged/notpaged.njk", "./test/stubs/", @@ -34,7 +34,7 @@ test("No pagination", async t => { t.is((await paging.getPageTemplates()).length, 0); }); -test("Pagination enabled in frontmatter", async t => { +test("Pagination enabled in frontmatter", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedresolve.njk", "./test/stubs/", @@ -54,7 +54,7 @@ test("Pagination enabled in frontmatter", async t => { t.is(data.pagination.size, 4); }); -test("Resolve paged data in frontmatter", async t => { +test("Resolve paged data in frontmatter", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedresolve.njk", "./test/stubs/", @@ -69,7 +69,7 @@ test("Resolve paged data in frontmatter", async t => { t.is(paging.getPagedItems().length, 2); }); -test("Paginate data in frontmatter", async t => { +test("Paginate data in frontmatter", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedinlinedata.njk", "./test/stubs/", @@ -93,7 +93,7 @@ test("Paginate data in frontmatter", async t => { ); }); -test("Paginate external data file", async t => { +test("Paginate external data file", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -125,14 +125,14 @@ test("Paginate external data file", async t => { ); }); -test("Slugify test", t => { +test("Slugify test", (t) => { const slugify = require("slugify"); t.is(slugify("This is a test", { lower: true }), "this-is-a-test"); t.is(slugify("This", { lower: true }), "this"); t.is(slugify("ThisLKSDFDS", { lower: true }), "thislksdfds"); }); -test("Permalink with pagination variables", async t => { +test("Permalink with pagination variables", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalink.njk", "./test/stubs/", @@ -146,7 +146,7 @@ test("Permalink with pagination variables", async t => { t.is(pages[1].outputPath, "./dist/paged/another-slug-candidate/index.html"); }); -test("Permalink with pagination variables (numeric)", async t => { +test("Permalink with pagination variables (numeric)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinknumeric.njk", "./test/stubs/", @@ -177,7 +177,7 @@ test("Permalink with pagination variables (numeric)", async t => { t.is(pages[1].data.pagination.hrefs.length, 2); }); -test("Permalink with pagination variables (numeric, one indexed)", async t => { +test("Permalink with pagination variables (numeric, one indexed)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinknumericoneindexed.njk", "./test/stubs/", @@ -204,7 +204,7 @@ test("Permalink with pagination variables (numeric, one indexed)", async t => { t.is(pages[1].data.pagination.hrefs.length, 2); }); -test("Permalink first and last page link with pagination variables (numeric)", async t => { +test("Permalink first and last page link with pagination variables (numeric)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinknumeric.njk", "./test/stubs/", @@ -221,7 +221,7 @@ test("Permalink first and last page link with pagination variables (numeric)", a t.is(pages[1].data.pagination.lastPageLink, "/paged/page-1/index.html"); }); -test("Permalink first and last page link with pagination variables (numeric, one indexed)", async t => { +test("Permalink first and last page link with pagination variables (numeric, one indexed)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinknumericoneindexed.njk", "./test/stubs/", @@ -238,7 +238,7 @@ test("Permalink first and last page link with pagination variables (numeric, one t.is(pages[1].data.pagination.lastPageLink, "/paged/page-2/index.html"); }); -test("Alias to page data", async t => { +test("Alias to page data", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedalias.njk", "./test/stubs/", @@ -255,7 +255,7 @@ test("Alias to page data", async t => { t.is((await pages[1].template.render(pages[1].data)).trim(), "item2"); }); -test("Alias to page data (size 2)", async t => { +test("Alias to page data (size 2)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedaliassize2.njk", "./test/stubs/", @@ -272,7 +272,7 @@ test("Alias to page data (size 2)", async t => { t.is((await pages[1].template.render(pages[1].data)).trim(), "item3"); }); -test("Permalink with pagination variables (and an if statement, nunjucks)", async t => { +test("Permalink with pagination variables (and an if statement, nunjucks)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", @@ -286,7 +286,7 @@ test("Permalink with pagination variables (and an if statement, nunjucks)", asyn t.is(pages[1].outputPath, "./dist/paged/page-1/index.html"); }); -test("Permalink with pagination variables (and an if statement, liquid)", async t => { +test("Permalink with pagination variables (and an if statement, liquid)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinkif.liquid", "./test/stubs/", @@ -300,7 +300,7 @@ test("Permalink with pagination variables (and an if statement, liquid)", async t.is(pages[1].outputPath, "./dist/paged/page-1/index.html"); }); -test("Template with Pagination, getRenderedTemplates", async t => { +test("Template with Pagination, getRenderedTemplates", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", @@ -315,7 +315,7 @@ test("Template with Pagination, getRenderedTemplates", async t => { t.is(templates.length, 2); }); -test("Issue 135", async t => { +test("Issue 135", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -340,7 +340,7 @@ test("Issue 135", async t => { t.is(pages[0].outputPath, "./dist/blog/do-you-even-paginate-bro/index.html"); }); -test("Template with Pagination, getTemplates has page variables set", async t => { +test("Template with Pagination, getTemplates has page variables set", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", @@ -356,7 +356,7 @@ test("Template with Pagination, getTemplates has page variables set", async t => t.is(templates[1].data.page.outputPath, "./dist/paged/page-1/index.html"); }); -test("Template with Pagination, getRenderedTemplates has page variables set", async t => { +test("Template with Pagination, getRenderedTemplates has page variables set", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", @@ -372,7 +372,7 @@ test("Template with Pagination, getRenderedTemplates has page variables set", as t.is(pages[1].data.page.outputPath, "./dist/paged/page-1/index.html"); }); -test("Page over an object (use keys)", async t => { +test("Page over an object (use keys)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedobject.njk", "./test/stubs/", @@ -396,7 +396,7 @@ test("Page over an object (use keys)", async t => { ); }); -test("Page over an object (use values)", async t => { +test("Page over an object (use values)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedobjectvalues.njk", "./test/stubs/", @@ -420,7 +420,7 @@ test("Page over an object (use values)", async t => { ); }); -test("Page over an object (filtered, array)", async t => { +test("Page over an object (filtered, array)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedobjectfilterarray.njk", "./test/stubs/", @@ -441,7 +441,7 @@ test("Page over an object (filtered, array)", async t => { ); }); -test("Page over an object (filtered, string)", async t => { +test("Page over an object (filtered, string)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedobjectfilterstring.njk", "./test/stubs/", @@ -463,7 +463,7 @@ test("Page over an object (filtered, string)", async t => { ); }); -test("Pagination with deep data merge #147", async t => { +test("Pagination with deep data merge #147", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedinlinedata.njk", "./test/stubs/", @@ -471,9 +471,9 @@ test("Pagination with deep data merge #147", async t => { ); tmpl.config = { keys: { - layout: "layout" + layout: "layout", }, - dataDeepMerge: true + dataDeepMerge: true, }; let data = await tmpl.getData(); @@ -493,7 +493,7 @@ test("Pagination with deep data merge #147", async t => { ); }); -test("Pagination with deep data merge with alias #147", async t => { +test("Pagination with deep data merge with alias #147", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedalias.njk", "./test/stubs/", @@ -502,10 +502,10 @@ test("Pagination with deep data merge with alias #147", async t => { tmpl.config = { keys: { layout: "layout", - permalink: "permalink" + permalink: "permalink", }, dynamicPermalinks: true, - dataDeepMerge: true + dataDeepMerge: true, }; let data = await tmpl.getData(); @@ -518,7 +518,7 @@ test("Pagination with deep data merge with alias #147", async t => { t.is((await pages[1].template.render(pages[1].data)).trim(), "item2"); }); -test("Paginate data in frontmatter (reversed)", async t => { +test("Paginate data in frontmatter (reversed)", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedinlinedata-reverse.njk", "./test/stubs/", @@ -545,55 +545,55 @@ test("Paginate data in frontmatter (reversed)", async t => { ); }); -test("No circular dependency (does not throw)", t => { +test("No circular dependency (does not throw)", (t) => { new Pagination({ collections: { - tag1: [] + tag1: [], }, pagination: { data: "collections.tag1", - size: 1 + size: 1, }, - tags: ["tag2"] + tags: ["tag2"], }); t.true(true); }); -test("Circular dependency (pagination iterates over tag1 but also supplies pages to tag1)", t => { +test("Circular dependency (pagination iterates over tag1 but also supplies pages to tag1)", (t) => { t.throws(() => { new Pagination({ collections: { tag1: [], - tag2: [] + tag2: [], }, pagination: { data: "collections.tag1", - size: 1 + size: 1, }, - tags: ["tag1"] + tags: ["tag1"], }); }); }); -test("Circular dependency but should not error because it uses eleventyExcludeFromCollections", t => { +test("Circular dependency but should not error because it uses eleventyExcludeFromCollections", (t) => { new Pagination({ eleventyExcludeFromCollections: true, collections: { tag1: [], - tag2: [] + tag2: [], }, pagination: { data: "collections.tag1", - size: 1 + size: 1, }, - tags: ["tag1"] + tags: ["tag1"], }); t.true(true); }); -test("Pagination `before` Callback", async t => { +test("Pagination `before` Callback", async (t) => { let tmpl = new Template( "./test/stubs/paged/paged-before.njk", "./test/stubs/", @@ -606,7 +606,7 @@ test("Pagination `before` Callback", async t => { t.deepEqual(templates[0].data.myalias, "item6"); }); -test("Pagination `before` Callback with a Filter", async t => { +test("Pagination `before` Callback with a Filter", async (t) => { let tmpl = new Template( "./test/stubs/paged/paged-before-filter.njk", "./test/stubs/", @@ -619,7 +619,7 @@ test("Pagination `before` Callback with a Filter", async t => { t.deepEqual(templates[0].data.myalias, "item2"); }); -test("Pagination `before` Callback with `reverse: true` (test order of operations)", async t => { +test("Pagination `before` Callback with `reverse: true` (test order of operations)", async (t) => { let tmpl = new Template( "./test/stubs/paged/paged-before-and-reverse.njk", "./test/stubs/", @@ -631,7 +631,7 @@ test("Pagination `before` Callback with `reverse: true` (test order of operation t.deepEqual(templates[0].data.pagination.items, ["item2"]); }); -test("Pagination new v0.10.0 href/hrefs", async t => { +test("Pagination new v0.10.0 href/hrefs", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -657,7 +657,7 @@ test("Pagination new v0.10.0 href/hrefs", async t => { t.falsy(templates[1].data.pagination.href.next); }); -test("Pagination new v0.10.0 page/pages", async t => { +test("Pagination new v0.10.0 page/pages", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -688,7 +688,7 @@ test("Pagination new v0.10.0 page/pages", async t => { t.falsy(templates[1].data.pagination.page.next); }); -test("Pagination new v0.10.0 alias", async t => { +test("Pagination new v0.10.0 alias", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedalias.njk", "./test/stubs/", @@ -702,7 +702,7 @@ test("Pagination new v0.10.0 alias", async t => { t.is(templates[1].data.pagination.alias, "font.test"); }); -test("Pagination make sure pageNumber is numeric for {{ pageNumber + 1 }} Issue #760", async t => { +test("Pagination make sure pageNumber is numeric for {{ pageNumber + 1 }} Issue #760", async (t) => { let tmpl = new Template( "./test/stubs/paged/pagedinlinedata.njk", "./test/stubs/", diff --git a/test/PluralizeTest.js b/test/PluralizeTest.js index 17bf9f600..95c34b761 100644 --- a/test/PluralizeTest.js +++ b/test/PluralizeTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import pluralize from "../src/Util/Pluralize"; +const test = require("ava"); +const pluralize = require("../src/Util/Pluralize"); -test("Pluralize", t => { +test("Pluralize", (t) => { t.is(pluralize(0, "test", "tests"), "tests"); t.is(pluralize(1, "test", "tests"), "test"); t.is(pluralize(2, "test", "tests"), "tests"); diff --git a/test/SortableTest.js b/test/SortableTest.js index ef5df7aa7..da6c98cc7 100644 --- a/test/SortableTest.js +++ b/test/SortableTest.js @@ -1,13 +1,13 @@ -import test from "ava"; -import { DateTime } from "luxon"; -import Sortable from "../src/Util/Sortable"; +const test = require("ava"); +const { DateTime } = require("luxon"); +const Sortable = require("../src/Util/Sortable"); -test("get Sort Function", t => { +test("get Sort Function", (t) => { let s = new Sortable(); t.deepEqual(s.getSortFunction(), Sortable.sortFunctionAlphabeticAscending); }); -test("Alphabetic Ascending", t => { +test("Alphabetic Ascending", (t) => { let s = new Sortable(); t.false(s.isSortNumeric); t.true(s.isSortAscending); @@ -18,7 +18,7 @@ test("Alphabetic Ascending", t => { t.deepEqual(s.sort(), ["a", "m", "z"]); }); -test("Alphabetic Ascending (shortcut)", t => { +test("Alphabetic Ascending (shortcut)", (t) => { let s = new Sortable(); s.add("a"); s.add("z"); @@ -26,7 +26,7 @@ test("Alphabetic Ascending (shortcut)", t => { t.deepEqual(s.sortAscending(), ["a", "m", "z"]); }); -test("Alphabetic Descending", t => { +test("Alphabetic Descending", (t) => { let s = new Sortable(); s.setSortDescending(); t.false(s.isSortNumeric); @@ -38,7 +38,7 @@ test("Alphabetic Descending", t => { t.deepEqual(s.sort(), ["z", "m", "a"]); }); -test("Alphabetic Descending (shortcut)", t => { +test("Alphabetic Descending (shortcut)", (t) => { let s = new Sortable(); s.add("a"); s.add("z"); @@ -46,7 +46,7 @@ test("Alphabetic Descending (shortcut)", t => { t.deepEqual(s.sortDescending(), ["z", "m", "a"]); }); -test("Numeric Ascending", t => { +test("Numeric Ascending", (t) => { let s = new Sortable(); s.setSortNumeric(true); t.true(s.isSortNumeric); @@ -58,7 +58,7 @@ test("Numeric Ascending", t => { t.deepEqual(s.sort(), [1, 2, 4]); }); -test("Numeric Descending", t => { +test("Numeric Descending", (t) => { let s = new Sortable(); s.setSortNumeric(true); s.setSortDescending(); @@ -71,13 +71,13 @@ test("Numeric Descending", t => { t.deepEqual(s.sort(), [4, 2, 1]); }); -test("Date Assumptions", t => { +test("Date Assumptions", (t) => { t.is(DateTime.fromISO("2007-10-10") - new Date(2007, 9, 10).getTime(), 0); t.is(DateTime.fromISO("2008-10-10") - new Date(2008, 9, 10).getTime(), 0); t.not(DateTime.fromISO("2008-10-10") - new Date(2007, 9, 10).getTime(), 0); }); -test("Date and Sortable Assumptions", t => { +test("Date and Sortable Assumptions", (t) => { // Sortable works here without extra code because Luxon’s valueOf works in equality comparison (for alphabetic lists) t.is( Sortable.sortFunctionAlphabeticAscending( @@ -139,7 +139,7 @@ test("Date and Sortable Assumptions", t => { ); }); -test("Date Ascending", t => { +test("Date Ascending", (t) => { let s = new Sortable(); let date1 = DateTime.fromISO("2007-10-10"); let date2 = DateTime.fromISO("2008-10-10"); @@ -150,7 +150,7 @@ test("Date Ascending", t => { t.deepEqual(s.sort(), [date1, date2, date3]); }); -test("Date Descending", t => { +test("Date Descending", (t) => { let s = new Sortable(); s.setSortDescending(); let date1 = DateTime.fromISO("2007-10-10"); @@ -162,7 +162,7 @@ test("Date Descending", t => { t.deepEqual(s.sort(), [date3, date2, date1]); }); -test("Alphabetic Ascending (str sort arg)", t => { +test("Alphabetic Ascending (str sort arg)", (t) => { let s = new Sortable(); s.add("a"); s.add("z"); @@ -170,7 +170,7 @@ test("Alphabetic Ascending (str sort arg)", t => { t.deepEqual(s.sort("ascending"), ["a", "m", "z"]); }); -test("Alphabetic Descending (str sort arg)", t => { +test("Alphabetic Descending (str sort arg)", (t) => { let s = new Sortable(); s.add("a"); s.add("z"); @@ -178,7 +178,7 @@ test("Alphabetic Descending (str sort arg)", t => { t.deepEqual(s.sort("descending"), ["z", "m", "a"]); }); -test("Alphabetic Ascending (short str sort arg)", t => { +test("Alphabetic Ascending (short str sort arg)", (t) => { let s = new Sortable(); s.add("a"); s.add("z"); @@ -186,7 +186,7 @@ test("Alphabetic Ascending (short str sort arg)", t => { t.deepEqual(s.sort("A-Z"), ["a", "m", "z"]); }); -test("Alphabetic Descending (short str sort arg)", t => { +test("Alphabetic Descending (short str sort arg)", (t) => { let s = new Sortable(); s.add("a"); s.add("z"); diff --git a/test/TemplateCacheTest.js b/test/TemplateCacheTest.js index 80a0a5adb..5b0e603a8 100644 --- a/test/TemplateCacheTest.js +++ b/test/TemplateCacheTest.js @@ -1,8 +1,8 @@ -import test from "ava"; -import Template from "../src/Template"; -import templateCache from "../src/TemplateCache"; +const test = require("ava"); +const Template = require("../src/Template"); +const templateCache = require("../src/TemplateCache"); -test("Cache can save templates", t => { +test("Cache can save templates", (t) => { templateCache.clear(); let tmpl = new Template( @@ -15,7 +15,7 @@ test("Cache can save templates", t => { t.is(templateCache.size(), 1); }); -test("TemplateCache clear", t => { +test("TemplateCache clear", (t) => { templateCache.clear(); let tmpl = new Template( @@ -30,7 +30,7 @@ test("TemplateCache clear", t => { t.is(templateCache.size(), 0); }); -test("TemplateCache has", t => { +test("TemplateCache has", (t) => { templateCache.clear(); let tmpl = new Template( @@ -43,7 +43,7 @@ test("TemplateCache has", t => { t.is(templateCache.has("./test/stubs/template.ejs"), true); }); -test("TemplateCache get success", t => { +test("TemplateCache get success", (t) => { templateCache.clear(); let tmpl = new Template( @@ -56,7 +56,7 @@ test("TemplateCache get success", t => { t.truthy(templateCache.get("./test/stubs/template.ejs")); }); -test("TemplateCache get fail", t => { +test("TemplateCache get fail", (t) => { templateCache.clear(); let tmpl = new Template( @@ -66,7 +66,7 @@ test("TemplateCache get fail", t => { ); templateCache.add("./test/stubs/template.ejs", tmpl); - t.throws(function() { + t.throws(function () { templateCache.get("./test/stubs/template298374892.ejs"); }); }); diff --git a/test/TemplateCollectionTest.js b/test/TemplateCollectionTest.js index 2d0ee6df5..60f141060 100644 --- a/test/TemplateCollectionTest.js +++ b/test/TemplateCollectionTest.js @@ -1,8 +1,8 @@ -import test from "ava"; -import multimatch from "multimatch"; -import Template from "../src/Template"; -import Collection from "../src/TemplateCollection"; -import Sortable from "../src/Util/Sortable"; +const test = require("ava"); +const multimatch = require("multimatch"); +const Template = require("../src/Template"); +const Collection = require("../src/TemplateCollection"); +const Sortable = require("../src/Util/Sortable"); let tmpl1 = new Template( "./test/stubs/collection/test1.md", @@ -40,7 +40,7 @@ let tmpl7 = new Template( "./test/stubs/_site" ); -test("Basic setup", async t => { +test("Basic setup", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl2); @@ -49,7 +49,7 @@ test("Basic setup", async t => { t.is(c.length, 3); }); -test("sortFunctionDateInputPath", async t => { +test("sortFunctionDateInputPath", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl4); @@ -62,7 +62,7 @@ test("sortFunctionDateInputPath", async t => { t.deepEqual(posts[2].template, tmpl5); }); -test("getFilteredByTag", async t => { +test("getFilteredByTag", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl2); @@ -83,7 +83,7 @@ test("getFilteredByTag", async t => { t.deepEqual(dogs[0].template, tmpl1); }); -test("getFilteredByTag (added out of order, sorted)", async t => { +test("getFilteredByTag (added out of order, sorted)", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl3); await c._testAddTemplate(tmpl2); @@ -105,7 +105,7 @@ test("getFilteredByTag (added out of order, sorted)", async t => { t.deepEqual(dogs[0].template, tmpl1); }); -test("getFilteredByTags", async t => { +test("getFilteredByTags", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl2); @@ -125,7 +125,7 @@ test("getFilteredByTags", async t => { t.deepEqual(dogs[0].template, tmpl1); }); -test("getFilteredByTags (added out of order, sorted)", async t => { +test("getFilteredByTags (added out of order, sorted)", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl3); await c._testAddTemplate(tmpl2); @@ -148,7 +148,7 @@ test("getFilteredByTags (added out of order, sorted)", async t => { t.deepEqual(dogs[0].template, tmpl1); }); -test("getFilteredByGlob", async t => { +test("getFilteredByGlob", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl6); @@ -159,7 +159,7 @@ test("getFilteredByGlob", async t => { t.deepEqual(markdowns[0].template, tmpl1); }); -test("getFilteredByGlob no dash dot", async t => { +test("getFilteredByGlob no dash dot", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl6); @@ -175,7 +175,7 @@ test("getFilteredByGlob no dash dot", async t => { t.deepEqual(htmls[1].template, tmpl7); }); -test("partial match on tag string, issue 95", async t => { +test("partial match on tag string, issue 95", async (t) => { let cat = new Template( "./test/stubs/issue-95/cat.md", "./test/stubs/", @@ -195,7 +195,7 @@ test("partial match on tag string, issue 95", async t => { t.is(posts.length, 1); }); -test("multimatch assumptions, issue #127", async t => { +test("multimatch assumptions, issue #127", async (t) => { t.deepEqual( multimatch( ["src/bookmarks/test.md"], @@ -216,7 +216,7 @@ test("multimatch assumptions, issue #127", async t => { t.deepEqual(globs, ["./**/+(bookmarks|posts|screencasts)/**/!(index)*.md"]); t.deepEqual(multimatch(["./src/bookmarks/test.md"], globs), [ - "./src/bookmarks/test.md" + "./src/bookmarks/test.md", ]); t.deepEqual(multimatch(["./src/bookmarks/index.md"], globs), []); t.deepEqual(multimatch(["./src/bookmarks/index2.md"], globs), []); @@ -226,7 +226,7 @@ test("multimatch assumptions, issue #127", async t => { ); }); -test("Sort in place (issue #352)", async t => { +test("Sort in place (issue #352)", async (t) => { let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl4); diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index c1633015c..326e47baa 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import md from "markdown-it"; -import TemplateConfig from "../src/TemplateConfig"; -import eleventyConfig from "../src/EleventyConfig"; +const test = require("ava"); +const md = require("markdown-it"); +const TemplateConfig = require("../src/TemplateConfig"); +const eleventyConfig = require("../src/EleventyConfig"); test("Template Config local config overrides base config", async (t) => { let templateCfg = new TemplateConfig( diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 8306f27bf..0b3dad33c 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -1,17 +1,17 @@ -import test from "ava"; -import TemplateData from "../src/TemplateData"; -import templateConfig from "../src/Config"; +const test = require("ava"); +const TemplateData = require("../src/TemplateData"); +const templateConfig = require("../src/Config"); const config = templateConfig.getConfig(); -test("Create", async t => { +test("Create", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.getData(); t.true(Object.keys(data[config.keys.package]).length > 0); }); -test("getData()", async t => { +test("getData()", async (t) => { let dataObj = new TemplateData("./test/stubs/"); t.is(dataObj.getData().toString(), "[object Promise]"); @@ -30,14 +30,14 @@ test("getData()", async t => { ); }); -test("Data dir does not exist", async t => { +test("Data dir does not exist", async (t) => { await t.throwsAsync(async () => { let dataObj = new TemplateData("./test/thisdirectorydoesnotexist"); await dataObj.getData(); }); }); -test("Add local data", async t => { +test("Add local data", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.getData(); @@ -58,7 +58,7 @@ test("Add local data", async t => { t.is(withLocalData.localdatakeyfromjs2, "howdy2"); }); -test("Get local data async JS", async t => { +test("Get local data async JS", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let withLocalData = await dataObj.getLocalData( @@ -70,7 +70,7 @@ test("Get local data async JS", async t => { t.is(withLocalData.localdatakeyfromcjs, "common-js-howdydoody"); }); -test("addLocalData() doesn’t exist but doesn’t fail (template file does exist)", async t => { +test("addLocalData() doesn’t exist but doesn’t fail (template file does exist)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.getData(); let beforeDataKeyCount = Object.keys(data); @@ -84,7 +84,7 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does exis t.deepEqual(Object.keys(withLocalData), beforeDataKeyCount); }); -test("addLocalData() doesn’t exist but doesn’t fail (template file does not exist)", async t => { +test("addLocalData() doesn’t exist but doesn’t fail (template file does not exist)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.getData(); let beforeDataKeyCount = Object.keys(data); @@ -97,30 +97,30 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does not t.deepEqual(Object.keys(withLocalData), beforeDataKeyCount); }); -test("Global Dir Directory", async t => { +test("Global Dir Directory", async (t) => { let dataObj = new TemplateData("./"); t.deepEqual(await dataObj.getGlobalDataGlob(), [ - "./_data/**/*.(json|cjs|js)" + "./_data/**/*.(json|cjs|js)", ]); }); -test("Global Dir Directory with Constructor Path Arg", async t => { +test("Global Dir Directory with Constructor Path Arg", async (t) => { let dataObj = new TemplateData("./test/stubs/"); t.deepEqual(await dataObj.getGlobalDataGlob(), [ - "./test/stubs/_data/**/*.(json|cjs|js)" + "./test/stubs/_data/**/*.(json|cjs|js)", ]); }); -test("getAllGlobalData() with other data files", async t => { +test("getAllGlobalData() with other data files", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); t.true(dataFilePaths.length > 0); t.true( - dataFilePaths.filter(path => { + dataFilePaths.filter((path) => { return path.indexOf("./test/stubs/_data/globalData.json") === 0; }).length > 0 ); @@ -130,20 +130,20 @@ test("getAllGlobalData() with other data files", async t => { t.truthy(data.testData); t.deepEqual(data.testData, { - testdatakey1: "testdatavalue1" + testdatakey1: "testdatavalue1", }); t.deepEqual(data.subdir.testDataSubdir, { - subdirkey: "subdirvalue" + subdirkey: "subdirvalue", }); }); -test("getAllGlobalData() with js object data file", async t => { +test("getAllGlobalData() with js object data file", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); t.true( - dataFilePaths.filter(path => { + dataFilePaths.filter((path) => { return path.indexOf("./test/stubs/_data/globalData2.js") === 0; }).length > 0 ); @@ -152,13 +152,13 @@ test("getAllGlobalData() with js object data file", async t => { t.is(data.globalData2.datakeyfromjs, "howdy"); }); -test("getAllGlobalData() with js function data file", async t => { +test("getAllGlobalData() with js function data file", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); t.true( - dataFilePaths.filter(path => { + dataFilePaths.filter((path) => { return path.indexOf("./test/stubs/_data/globalDataFn.js") === 0; }).length > 0 ); @@ -167,7 +167,7 @@ test("getAllGlobalData() with js function data file", async t => { t.is(data.globalDataFn.datakeyfromjsfn, "howdy"); }); -test("getAllGlobalData() with config globalData", async t => { +test("getAllGlobalData() with config globalData", async (t) => { let dataObj = new TemplateData("./test/stubs/"); dataObj._setConfig({ @@ -179,8 +179,8 @@ test("getAllGlobalData() with config globalData", async t => { example2: async () => { return "two"; }, - example3: "static" - } + example3: "static", + }, }); let data = await dataObj.cacheData(true); @@ -190,13 +190,13 @@ test("getAllGlobalData() with config globalData", async t => { t.is(data.example3, "static"); }); -test("getAllGlobalData() with common js function data file", async t => { +test("getAllGlobalData() with common js function data file", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); t.true( - dataFilePaths.filter(path => { + dataFilePaths.filter((path) => { return path.indexOf("./test/stubs/_data/globalDataFnCJS.cjs") === 0; }).length > 0 ); @@ -205,35 +205,35 @@ test("getAllGlobalData() with common js function data file", async t => { t.is(data.globalDataFnCJS.datakeyfromcjsfn, "common-cjs-howdy"); }); -test("getDataValue() without a dataTemplateEngine", async t => { +test("getDataValue() without a dataTemplateEngine", async (t) => { let dataObj = new TemplateData("./test/stubs/"); dataObj.setDataTemplateEngine(false); let data = await dataObj.getDataValue("./test/stubs/_data/testDataEjs.json", { - pkg: { name: "pkgname" } + pkg: { name: "pkgname" }, }); t.deepEqual(data, { datakey1: "datavalue1", - datakey2: "<%= pkg.name %>" + datakey2: "<%= pkg.name %>", }); }); -test("getDataValue() without dataTemplateEngine changed to `ejs`", async t => { +test("getDataValue() without dataTemplateEngine changed to `ejs`", async (t) => { let dataObj = new TemplateData("./test/stubs/"); dataObj.setDataTemplateEngine("ejs"); let data = await dataObj.getDataValue("./test/stubs/_data/testDataEjs.json", { - pkg: { name: "pkgname" } + pkg: { name: "pkgname" }, }); t.deepEqual(data, { datakey1: "datavalue1", - datakey2: "pkgname" + datakey2: "pkgname", }); }); -test("getLocalDataPaths", async t => { +test("getLocalDataPaths", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" @@ -247,11 +247,11 @@ test("getLocalDataPaths", async t => { "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.cjs", - "./test/stubs/component/component.11tydata.js" + "./test/stubs/component/component.11tydata.js", ]); }); -test("Deeper getLocalDataPaths", async t => { +test("Deeper getLocalDataPaths", async (t) => { let dataObj = new TemplateData("./"); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" @@ -269,11 +269,11 @@ test("Deeper getLocalDataPaths", async t => { "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.cjs", - "./test/stubs/component/component.11tydata.js" + "./test/stubs/component/component.11tydata.js", ]); }); -test("getLocalDataPaths with an 11ty js template", async t => { +test("getLocalDataPaths with an 11ty js template", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.11ty.js" @@ -287,11 +287,11 @@ test("getLocalDataPaths with an 11ty js template", async t => { "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.cjs", - "./test/stubs/component/component.11tydata.js" + "./test/stubs/component/component.11tydata.js", ]); }); -test("getLocalDataPaths with inputDir passed in (trailing slash)", async t => { +test("getLocalDataPaths with inputDir passed in (trailing slash)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" @@ -305,11 +305,11 @@ test("getLocalDataPaths with inputDir passed in (trailing slash)", async t => { "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.cjs", - "./test/stubs/component/component.11tydata.js" + "./test/stubs/component/component.11tydata.js", ]); }); -test("getLocalDataPaths with inputDir passed in (no trailing slash)", async t => { +test("getLocalDataPaths with inputDir passed in (no trailing slash)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" @@ -323,11 +323,11 @@ test("getLocalDataPaths with inputDir passed in (no trailing slash)", async t => "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.cjs", - "./test/stubs/component/component.11tydata.js" + "./test/stubs/component/component.11tydata.js", ]); }); -test("getLocalDataPaths with inputDir passed in (no leading slash)", async t => { +test("getLocalDataPaths with inputDir passed in (no leading slash)", async (t) => { let dataObj = new TemplateData("test/stubs"); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" @@ -341,60 +341,60 @@ test("getLocalDataPaths with inputDir passed in (no leading slash)", async t => "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.cjs", - "./test/stubs/component/component.11tydata.js" + "./test/stubs/component/component.11tydata.js", ]); }); -test("getRawImports", async t => { +test("getRawImports", async (t) => { let dataObj = new TemplateData("test/stubs"); let data = dataObj.getRawImports(); t.is(data.pkg.name, "@11ty/eleventy"); }); -test("getTemplateDataFileGlob", async t => { +test("getTemplateDataFileGlob", async (t) => { let tw = new TemplateData("test/stubs"); t.deepEqual(await tw.getTemplateDataFileGlob(), [ "./test/stubs/**/*.json", "./test/stubs/**/*.11tydata.cjs", - "./test/stubs/**/*.11tydata.js" + "./test/stubs/**/*.11tydata.js", ]); }); -test("TemplateData.merge", t => { +test("TemplateData.merge", (t) => { t.deepEqual( TemplateData.merge( { - tags: [1, 2, 3] + tags: [1, 2, 3], }, { - tags: [4, 5, 6] + tags: [4, 5, 6], } ), { tags: [1, 2, 3, 4, 5, 6] } ); }); -test("TemplateData.cleanupData", t => { +test("TemplateData.cleanupData", (t) => { t.deepEqual(TemplateData.cleanupData({}), {}); t.deepEqual(TemplateData.cleanupData({ tags: null }), { tags: [] }); t.deepEqual(TemplateData.cleanupData({ tags: "" }), { tags: [] }); t.deepEqual(TemplateData.cleanupData({ tags: [] }), { tags: [] }); t.deepEqual(TemplateData.cleanupData({ tags: "test" }), { tags: ["test"] }); t.deepEqual(TemplateData.cleanupData({ tags: ["test1", "test2"] }), { - tags: ["test1", "test2"] + tags: ["test1", "test2"], }); }); -test("Parent directory for data (Issue #337)", async t => { +test("Parent directory for data (Issue #337)", async (t) => { let dataObj = new TemplateData("./test/stubs-337/src/"); dataObj._setConfig({ dataTemplateEngine: false, dir: { input: "./test/stubs-337/src/", - data: "../data/" - } + data: "../data/", + }, }); dataObj.setInputDir("./test/stubs-337/src/"); @@ -402,7 +402,7 @@ test("Parent directory for data (Issue #337)", async t => { t.deepEqual(data, { xyz: { - hi: "bye" - } + hi: "bye", + }, }); }); diff --git a/test/TemplateEngineManagerTest.js b/test/TemplateEngineManagerTest.js index a7dc35437..4986eccc0 100644 --- a/test/TemplateEngineManagerTest.js +++ b/test/TemplateEngineManagerTest.js @@ -1,32 +1,32 @@ -import test from "ava"; -import TemplateEngineManager from "../src/TemplateEngineManager"; -import templateConfig from "../src/Config"; +const test = require("ava"); +const TemplateEngineManager = require("../src/TemplateEngineManager"); +const templateConfig = require("../src/Config"); const config = templateConfig.getConfig(); -test("Unsupported engine", async t => { +test("Unsupported engine", async (t) => { t.throws(() => { let tem = new TemplateEngineManager(); tem.getEngine("doesnotexist"); }); }); -test("Supported engine", async t => { +test("Supported engine", async (t) => { let tem = new TemplateEngineManager(); t.truthy(tem.hasEngine("ejs")); }); -test("Supported custom engine", async t => { +test("Supported custom engine", async (t) => { let tem = new TemplateEngineManager(); tem.config = Object.assign({}, config); tem.config.extensionMap.add({ extension: "txt", key: "txt", - compile: function(str, inputPath) { + compile: function (str, inputPath) { // plaintext - return function(data) { + return function (data) { return str; }; - } + }, }); t.truthy(tem.hasEngine("txt")); @@ -35,20 +35,20 @@ test("Supported custom engine", async t => { t.is(await fn({ author: "zach" }), "

This is plaintext

"); }); -test("Handlebars Helpers", async t => { +test("Handlebars Helpers", async (t) => { let tem = new TemplateEngineManager(); let engine = tem.getEngine("hbs"); engine.addHelpers({ - uppercase: function(name) { + uppercase: function (name) { return name.toUpperCase(); - } + }, }); let fn = await engine.compile("

{{uppercase author}}

"); t.is(await fn({ author: "zach" }), "

ZACH

"); }); -test("getEngineLib", async t => { +test("getEngineLib", async (t) => { let tem = new TemplateEngineManager(); t.truthy(tem.getEngine("md").getEngineLib()); }); diff --git a/test/TemplateEngineTest.js b/test/TemplateEngineTest.js index b3e43dbfc..42cce0a08 100644 --- a/test/TemplateEngineTest.js +++ b/test/TemplateEngineTest.js @@ -1,10 +1,10 @@ -import test from "ava"; -import TemplateEngine from "../src/Engines/TemplateEngine"; +const test = require("ava"); +const TemplateEngine = require("../src/Engines/TemplateEngine"); -test("Unsupported engine", async t => { +test("Unsupported engine", async (t) => { t.is(new TemplateEngine("doesnotexist").getName(), "doesnotexist"); }); -test("Supported engine", async t => { +test("Supported engine", async (t) => { t.is(new TemplateEngine("ejs").getName(), "ejs"); }); diff --git a/test/TemplateFileSlugTest.js b/test/TemplateFileSlugTest.js index 36d59d163..0db1dd3da 100644 --- a/test/TemplateFileSlugTest.js +++ b/test/TemplateFileSlugTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateFileSlug from "../src/TemplateFileSlug"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateFileSlug = require("../src/TemplateFileSlug"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewSlugInstance(path, inputDir) { let extensionMap = new EleventyExtensionMap(); @@ -8,43 +8,43 @@ function getNewSlugInstance(path, inputDir) { return fs; } -test("Easy slug", t => { +test("Easy slug", (t) => { let fs = getNewSlugInstance("./file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); -test("Easy slug with dot", t => { +test("Easy slug with dot", (t) => { let fs = getNewSlugInstance("./file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); -test("Easy slug with dot 11ty.js", t => { +test("Easy slug with dot 11ty.js", (t) => { let fs = getNewSlugInstance("./file.test.11ty.js"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); -test("Easy slug with date", t => { +test("Easy slug with date", (t) => { let fs = getNewSlugInstance("./2018-01-01-file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); -test("Easy slug with date and dot in slug", t => { +test("Easy slug with date and dot in slug", (t) => { let fs = getNewSlugInstance("./2018-01-01-file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); -test("Easy slug, index", t => { +test("Easy slug, index", (t) => { let fs = getNewSlugInstance("./index.html"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); -test("Easy slug with date, index", t => { +test("Easy slug with date, index", (t) => { let fs = getNewSlugInstance("./2018-01-01-index.html"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); @@ -52,74 +52,74 @@ test("Easy slug with date, index", t => { /* Directories */ -test("Easy slug with dir", t => { +test("Easy slug with dir", (t) => { let fs = getNewSlugInstance("./test/file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/test/file"); }); -test("Easy slug with dot with dir", t => { +test("Easy slug with dot with dir", (t) => { let fs = getNewSlugInstance("./test/file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/test/file.test"); }); -test("Easy slug with date with dir", t => { +test("Easy slug with date with dir", (t) => { let fs = getNewSlugInstance("./test/2018-01-01-file.html"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/test/file"); }); -test("Easy slug with date and dot in slug with dir", t => { +test("Easy slug with date and dot in slug with dir", (t) => { let fs = getNewSlugInstance("./test/2018-01-01-file.test.html"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/test/file.test"); }); -test("Easy slug, index with dir", t => { +test("Easy slug, index with dir", (t) => { let fs = getNewSlugInstance("./test/index.html"); t.is(fs.getSlug(), "test"); t.is(fs.getFullPathWithoutExtension(), "/test/index"); }); -test("Easy slug with date, index with dir", t => { +test("Easy slug with date, index with dir", (t) => { let fs = getNewSlugInstance("./test/2018-01-01-index.html"); t.is(fs.getSlug(), "test"); t.is(fs.getFullPathWithoutExtension(), "/test/index"); }); /* Pass Input dir */ -test("Easy slug, input dir", t => { +test("Easy slug, input dir", (t) => { let fs = getNewSlugInstance("./file.html", "."); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); -test("Easy slug with dot, input dir", t => { +test("Easy slug with dot, input dir", (t) => { let fs = getNewSlugInstance("./file.test.html", "."); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); -test("Easy slug with date, input dir", t => { +test("Easy slug with date, input dir", (t) => { let fs = getNewSlugInstance("./2018-01-01-file.html", "."); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); -test("Easy slug with date and dot in slug, input dir", t => { +test("Easy slug with date and dot in slug, input dir", (t) => { let fs = getNewSlugInstance("./2018-01-01-file.test.html", "."); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); -test("Easy slug, index, input dir", t => { +test("Easy slug, index, input dir", (t) => { let fs = getNewSlugInstance("./index.html", "."); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); -test("Easy slug with date, index, input dir", t => { +test("Easy slug with date, index, input dir", (t) => { let fs = getNewSlugInstance("./2018-01-01-index.html", "."); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); @@ -127,49 +127,49 @@ test("Easy slug with date, index, input dir", t => { /* Directories and Input Dir */ -test("Easy slug with dir and input dir", t => { +test("Easy slug with dir and input dir", (t) => { let fs = getNewSlugInstance("./test/file.html", "./test"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); -test("Easy slug with dot with dir and input dir", t => { +test("Easy slug with dot with dir and input dir", (t) => { let fs = getNewSlugInstance("./test/file.test.html", "./test"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); -test("Easy slug with date with dir and input dir", t => { +test("Easy slug with date with dir and input dir", (t) => { let fs = getNewSlugInstance("./test/2018-01-01-file.html", "./test"); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/file"); }); -test("Easy slug with date and dot in slug with dir and input dir", t => { +test("Easy slug with date and dot in slug with dir and input dir", (t) => { let fs = getNewSlugInstance("./test/2018-01-01-file.test.html", "./test"); t.is(fs.getSlug(), "file.test"); t.is(fs.getFullPathWithoutExtension(), "/file.test"); }); -test("Easy slug, index with dir and input dir", t => { +test("Easy slug, index with dir and input dir", (t) => { let fs = getNewSlugInstance("./test/index.html", "./test"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); -test("Easy slug with date, index with dir and input dir", t => { +test("Easy slug with date, index with dir and input dir", (t) => { let fs = getNewSlugInstance("./test/2018-01-01-index.html", "./test"); t.is(fs.getSlug(), ""); t.is(fs.getFullPathWithoutExtension(), "/index"); }); -test("Easy slug with multiple dirs", t => { +test("Easy slug with multiple dirs", (t) => { let fs = getNewSlugInstance("./dir1/dir2/dir3/file.html", "."); t.is(fs.getSlug(), "file"); t.is(fs.getFullPathWithoutExtension(), "/dir1/dir2/dir3/file"); }); -test("Easy slug with multiple dirs and an index file", t => { +test("Easy slug with multiple dirs and an index file", (t) => { let fs = getNewSlugInstance("./dir1/dir2/dir3/index.html", "."); t.is(fs.getSlug(), "dir3"); t.is(fs.getFullPathWithoutExtension(), "/dir1/dir2/dir3/index"); diff --git a/test/TemplateGlobTest.js b/test/TemplateGlobTest.js index df69c40be..f496d9f03 100644 --- a/test/TemplateGlobTest.js +++ b/test/TemplateGlobTest.js @@ -1,44 +1,44 @@ -import test from "ava"; -import fastglob from "fast-glob"; -import TemplatePath from "../src/TemplatePath"; -import TemplateGlob from "../src/TemplateGlob"; +const test = require("ava"); +const fastglob = require("fast-glob"); +const TemplatePath = require("../src/TemplatePath"); +const TemplateGlob = require("../src/TemplateGlob"); -test("TemplatePath assumptions", t => { +test("TemplatePath assumptions", (t) => { t.is(TemplatePath.normalize("ignoredFolder"), "ignoredFolder"); t.is(TemplatePath.normalize("./ignoredFolder"), "ignoredFolder"); t.is(TemplatePath.normalize("./ignoredFolder/"), "ignoredFolder"); }); -test("Normalize string argument", t => { +test("Normalize string argument", (t) => { t.deepEqual(TemplateGlob.map("views"), "./views"); t.deepEqual(TemplateGlob.map("views/"), "./views"); t.deepEqual(TemplateGlob.map("./views"), "./views"); t.deepEqual(TemplateGlob.map("./views/"), "./views"); }); -test("Normalize with nots", t => { +test("Normalize with nots", (t) => { t.deepEqual(TemplateGlob.map("!views"), "!./views"); t.deepEqual(TemplateGlob.map("!views/"), "!./views"); t.deepEqual(TemplateGlob.map("!./views"), "!./views"); t.deepEqual(TemplateGlob.map("!./views/"), "!./views"); }); -test("Normalize with globstar", t => { +test("Normalize with globstar", (t) => { t.deepEqual(TemplateGlob.map("!views/**"), "!./views/**"); t.deepEqual(TemplateGlob.map("!./views/**"), "!./views/**"); }); -test("Normalize with globstar and star", t => { +test("Normalize with globstar and star", (t) => { t.deepEqual(TemplateGlob.map("!views/**/*"), "!./views/**/*"); t.deepEqual(TemplateGlob.map("!./views/**/*"), "!./views/**/*"); }); -test("Normalize with globstar and star and file extension", t => { +test("Normalize with globstar and star and file extension", (t) => { t.deepEqual(TemplateGlob.map("!views/**/*.json"), "!./views/**/*.json"); t.deepEqual(TemplateGlob.map("!./views/**/*.json"), "!./views/**/*.json"); }); -test("NormalizePath with globstar and star and file extension", t => { +test("NormalizePath with globstar and star and file extension", (t) => { t.deepEqual( TemplateGlob.normalizePath("views", "/", "**/*.json"), "./views/**/*.json" @@ -49,7 +49,7 @@ test("NormalizePath with globstar and star and file extension", t => { ); }); -test("NormalizePath with globstar and star and file extension (errors)", t => { +test("NormalizePath with globstar and star and file extension (errors)", (t) => { t.throws(() => { TemplateGlob.normalizePath("!views/**/*.json"); }); @@ -67,24 +67,24 @@ test("NormalizePath with globstar and star and file extension (errors)", t => { }); }); -test("Normalize array argument", t => { +test("Normalize array argument", (t) => { t.deepEqual(TemplateGlob.map(["views", "content"]), ["./views", "./content"]); t.deepEqual(TemplateGlob.map("views/"), "./views"); t.deepEqual(TemplateGlob.map("./views"), "./views"); t.deepEqual(TemplateGlob.map("./views/"), "./views"); }); -test("matuzo project issue with fastglob assumptions", async t => { +test("matuzo project issue with fastglob assumptions", async (t) => { let dotslashincludes = await fastglob( TemplateGlob.map([ "./test/stubs/globby/**/*.html", "!./test/stubs/globby/_includes/**/*", - "!./test/stubs/globby/_data/**/*" + "!./test/stubs/globby/_data/**/*", ]) ); t.is( - dotslashincludes.filter(function(file) { + dotslashincludes.filter(function (file) { return file.indexOf("_includes") > -1; }).length, 0 @@ -94,18 +94,18 @@ test("matuzo project issue with fastglob assumptions", async t => { TemplateGlob.map([ "test/stubs/globby/**/*.html", "!./test/stubs/globby/_includes/**/*", - "!./test/stubs/globby/_data/**/*" + "!./test/stubs/globby/_data/**/*", ]) ); t.is( - globincludes.filter(function(file) { + globincludes.filter(function (file) { return file.indexOf("_includes") > -1; }).length, 0 ); }); -test("fastglob assumptions", async t => { +test("fastglob assumptions", async (t) => { let glob = await fastglob("test/stubs/ignoredFolder/**"); t.is(glob.length, 1); @@ -114,19 +114,19 @@ test("fastglob assumptions", async t => { let glob3 = await fastglob([ "./test/stubs/ignoredFolder/**/*.md", - "!./test/stubs/ignoredFolder/**" + "!./test/stubs/ignoredFolder/**", ]); t.is(glob3.length, 0); let glob4 = await fastglob([ "./test/stubs/ignoredFolder/*.md", - "!./test/stubs/ignoredFolder/**" + "!./test/stubs/ignoredFolder/**", ]); t.is(glob4.length, 0); let glob5 = await fastglob([ "./test/stubs/ignoredFolder/ignored.md", - "!./test/stubs/ignoredFolder/**" + "!./test/stubs/ignoredFolder/**", ]); t.is(glob5.length, 0); }); diff --git a/test/TemplateLayoutPathResolverTest.js b/test/TemplateLayoutPathResolverTest.js index 0f33c74d4..984476e63 100644 --- a/test/TemplateLayoutPathResolverTest.js +++ b/test/TemplateLayoutPathResolverTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateLayoutPathResolver from "../src/TemplateLayoutPathResolver"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateLayoutPathResolver = require("../src/TemplateLayoutPathResolver"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getResolverInstance(path, inputDir, map) { if (!map) { @@ -15,115 +15,115 @@ function getResolverInstance(path, inputDir, map) { "njk", "html", "jstl", - "11ty.js" + "11ty.js", ]); } return new TemplateLayoutPathResolver(path, inputDir, map); } -test("Layout", t => { +test("Layout", (t) => { let res = getResolverInstance("default", "./test/stubs"); t.is(res.getFileName(), "default.ejs"); }); -test("Layout already has extension", t => { +test("Layout already has extension", (t) => { let res = getResolverInstance("default.ejs", "./test/stubs"); t.is(res.getFileName(), "default.ejs"); }); -test("Layout (uses empty string includes folder)", t => { +test("Layout (uses empty string includes folder)", (t) => { let res = getResolverInstance("includesemptystring", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { - includes: "" - } + includes: "", + }, }; t.is(res.getFileName(), "includesemptystring.ejs"); }); -test("Layout (uses empty string includes folder) already has extension", t => { +test("Layout (uses empty string includes folder) already has extension", (t) => { let res = getResolverInstance("includesemptystring.ejs", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { - includes: "" - } + includes: "", + }, }; t.is(res.getFileName(), "includesemptystring.ejs"); }); -test("Layout (uses layouts folder)", t => { +test("Layout (uses layouts folder)", (t) => { let res = getResolverInstance("layoutsdefault", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { layouts: "_layouts", - includes: "_includes" - } + includes: "_includes", + }, }; t.is(res.getFileName(), "layoutsdefault.ejs"); }); -test("Layout (uses layouts folder) already has extension", t => { +test("Layout (uses layouts folder) already has extension", (t) => { let res = getResolverInstance("layoutsdefault.ejs", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { layouts: "_layouts", - includes: "_includes" - } + includes: "_includes", + }, }; t.is(res.getFileName(), "layoutsdefault.ejs"); }); -test("Layout (uses empty string layouts folder)", t => { +test("Layout (uses empty string layouts folder)", (t) => { let res = getResolverInstance("layoutsemptystring", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { layouts: "", - includes: "_includes" - } + includes: "_includes", + }, }; t.is(res.getFileName(), "layoutsemptystring.ejs"); }); -test("Layout (uses empty string layouts folder) already has extension", t => { +test("Layout (uses empty string layouts folder) already has extension", (t) => { let res = getResolverInstance("layoutsemptystring.ejs", "./test/stubs"); res.config = { templateFormats: ["ejs"], dir: { layouts: "", - includes: "_includes" - } + includes: "_includes", + }, }; t.is(res.getFileName(), "layoutsemptystring.ejs"); }); -test("Layout subdir", t => { +test("Layout subdir", (t) => { let res = getResolverInstance("layouts/inasubdir", "./test/stubs"); t.is(res.getFileName(), "layouts/inasubdir.njk"); }); -test("Layout subdir already has extension", t => { +test("Layout subdir already has extension", (t) => { let res = getResolverInstance("layouts/inasubdir.njk", "./test/stubs"); t.is(res.getFileName(), "layouts/inasubdir.njk"); }); -test("Multiple layouts exist with the same file base, pick one", t => { +test("Multiple layouts exist with the same file base, pick one", (t) => { let res = getResolverInstance("multiple", "./test/stubs"); // pick the first one if multiple exist. t.is(res.getFileName(), "multiple.ejs"); }); -test("Multiple layouts exist but we are being explicit—layout already has extension", t => { +test("Multiple layouts exist but we are being explicit—layout already has extension", (t) => { let res = getResolverInstance("multiple.ejs", "./test/stubs"); t.is(res.getFileName(), "multiple.ejs"); @@ -131,7 +131,7 @@ test("Multiple layouts exist but we are being explicit—layout already has exte t.is(res2.getFileName(), "multiple.md"); }); -test("Layout is aliased to a new location", t => { +test("Layout is aliased to a new location", (t) => { let tl = getResolverInstance("post", "./test/stubs"); tl.addLayoutAlias("post", "layouts/post.ejs"); tl.init(); @@ -139,7 +139,7 @@ test("Layout is aliased to a new location", t => { t.is(tl.getFileName(), "layouts/post.ejs"); }); -test("Global default with empty string alias", t => { +test("Global default with empty string alias", (t) => { let tl = getResolverInstance("", "./test/stubs"); tl.addLayoutAlias("", "layouts/post.ejs"); tl.init(); @@ -147,7 +147,7 @@ test("Global default with empty string alias", t => { t.is(tl.getFileName(), "layouts/post.ejs"); }); -test("Global default with empty string alias (but no alias exists for this instance)", t => { +test("Global default with empty string alias (but no alias exists for this instance)", (t) => { let tl = getResolverInstance("layout.ejs", "./test/stubs"); tl.addLayoutAlias("", "layouts/post.ejs"); tl.init(); @@ -157,7 +157,7 @@ test("Global default with empty string alias (but no alias exists for this insta }); }); -test("Layout has no alias and does not exist", async t => { +test("Layout has no alias and does not exist", async (t) => { let tl = getResolverInstance("shouldnotexist", "./test/stubs"); tl.addLayoutAlias("post", "layouts/post.ejs"); tl.init(); diff --git a/test/TemplateLayoutTest.js b/test/TemplateLayoutTest.js index 6c67b00c7..e155e389c 100644 --- a/test/TemplateLayoutTest.js +++ b/test/TemplateLayoutTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateLayout from "../src/TemplateLayout"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateLayout = require("../src/TemplateLayout"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getTemplateLayoutInstance(key, inputDir, map) { if (!map) { @@ -15,14 +15,14 @@ function getTemplateLayoutInstance(key, inputDir, map) { "njk", "html", "jstl", - "11ty.js" + "11ty.js", ]); } let layout = new TemplateLayout(key, inputDir, map); return layout; } -test("Creation", t => { +test("Creation", (t) => { t.is( getTemplateLayoutInstance("base", "./test/stubs").getInputPath(), "./test/stubs/_includes/base.njk" @@ -33,7 +33,7 @@ test("Creation", t => { }); }); -test("Get Layout Chain", async t => { +test("Get Layout Chain", async (t) => { let tl = getTemplateLayoutInstance( "layouts/layout-inherit-a.njk", "./test/stubs" @@ -42,11 +42,11 @@ test("Get Layout Chain", async t => { t.deepEqual(await tl.getLayoutChain(), [ "./test/stubs/_includes/layouts/layout-inherit-a.njk", "./test/stubs/_includes/layouts/layout-inherit-b.njk", - "./test/stubs/_includes/layouts/layout-inherit-c.njk" + "./test/stubs/_includes/layouts/layout-inherit-c.njk", ]); }); -test("Get Front Matter Data", async t => { +test("Get Front Matter Data", async (t) => { let tl = getTemplateLayoutInstance( "layouts/layout-inherit-a.njk", "./test/stubs" @@ -61,38 +61,38 @@ test("Get Front Matter Data", async t => { t.deepEqual(data, { inherits: "a", secondinherits: "b", - thirdinherits: "c" + thirdinherits: "c", }); t.deepEqual(await tl.getLayoutChain(), [ "./test/stubs/_includes/layouts/layout-inherit-a.njk", "./test/stubs/_includes/layouts/layout-inherit-b.njk", - "./test/stubs/_includes/layouts/layout-inherit-c.njk" + "./test/stubs/_includes/layouts/layout-inherit-c.njk", ]); t.deepEqual(await tl.getData(), { inherits: "a", secondinherits: "b", - thirdinherits: "c" + thirdinherits: "c", }); }); -test("Augment data with layoutContent", async t => { +test("Augment data with layoutContent", async (t) => { t.deepEqual(TemplateLayout.augmentDataWithContent(null, null), { content: null, layoutContent: null, - _layoutContent: null + _layoutContent: null, }); t.deepEqual(TemplateLayout.augmentDataWithContent(null, "Test"), { content: "Test", layoutContent: "Test", - _layoutContent: "Test" + _layoutContent: "Test", }); t.deepEqual(TemplateLayout.augmentDataWithContent({}, "Test 2"), { content: "Test 2", layoutContent: "Test 2", - _layoutContent: "Test 2" + _layoutContent: "Test 2", }); t.deepEqual( @@ -100,12 +100,12 @@ test("Augment data with layoutContent", async t => { { content: "Test 3", layoutContent: "Test 3", - _layoutContent: "Test 3" + _layoutContent: "Test 3", } ); }); -test("Render Layout", async t => { +test("Render Layout", async (t) => { let tl = getTemplateLayoutInstance( "layouts/layout-inherit-a.njk", "./test/stubs" @@ -115,14 +115,14 @@ test("Render Layout", async t => { await tl.render({ inherits: "a", secondinherits: "b", - thirdinherits: "c" + thirdinherits: "c", }) ).trim(), "a b a c" ); }); -test("Render Layout (Pass in template content)", async t => { +test("Render Layout (Pass in template content)", async (t) => { let tl = getTemplateLayoutInstance( "layouts/layout-inherit-a.njk", "./test/stubs" @@ -138,7 +138,7 @@ test("Render Layout (Pass in template content)", async t => { ); }); -test("Render Layout (Pass in undefined template content)", async t => { +test("Render Layout (Pass in undefined template content)", async (t) => { let tl = getTemplateLayoutInstance( "layouts/layout-contentdump.njk", "./test/stubs" @@ -152,7 +152,7 @@ test("Render Layout (Pass in undefined template content)", async t => { ); }); -test("Render Layout (Pass in null template content)", async t => { +test("Render Layout (Pass in null template content)", async (t) => { let tl = getTemplateLayoutInstance( "layouts/layout-contentdump.njk", "./test/stubs" @@ -166,7 +166,7 @@ test("Render Layout (Pass in null template content)", async t => { ); }); -test("Render Layout (Pass in empty template content)", async t => { +test("Render Layout (Pass in empty template content)", async (t) => { let tl = getTemplateLayoutInstance( "layouts/layout-contentdump.njk", "./test/stubs" @@ -180,7 +180,7 @@ test("Render Layout (Pass in empty template content)", async t => { ); }); -test("Cache Duplicates (use full key for cache)", async t => { +test("Cache Duplicates (use full key for cache)", async (t) => { // if two different layouts used the same filename but had different inputdirs, make sure templatelayout cache is unique let tla = getTemplateLayoutInstance( "layout.njk", diff --git a/test/TemplateMapTest-ComputedData.js b/test/TemplateMapTest-ComputedData.js index d1566b8bd..5635f3aa5 100644 --- a/test/TemplateMapTest-ComputedData.js +++ b/test/TemplateMapTest-ComputedData.js @@ -1,8 +1,8 @@ -import test from "ava"; -import Template from "../src/Template"; -import TemplateData from "../src/TemplateData"; -import TemplateMap from "../src/TemplateMap"; -import getNewTemplate from "./_getNewTemplateForTests"; +const test = require("ava"); +const Template = require("../src/Template"); +const TemplateData = require("../src/TemplateData"); +const TemplateMap = require("../src/TemplateMap"); +const getNewTemplate = require("./_getNewTemplateForTests"); test("Computed data can see tag generated collections", async (t) => { let tm = new TemplateMap(); diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 0285813e9..b5b9f5c62 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -1,9 +1,9 @@ -import test from "ava"; -import Template from "../src/Template"; -import TemplateMap from "../src/TemplateMap"; -import TemplateCollection from "../src/TemplateCollection"; -import UsingCircularTemplateContentReferenceError from "../src/Errors/UsingCircularTemplateContentReferenceError"; -import normalizeNewLines from "./Util/normalizeNewLines"; +const test = require("ava"); +const Template = require("../src/Template"); +const TemplateMap = require("../src/TemplateMap"); +const TemplateCollection = require("../src/TemplateCollection"); +const UsingCircularTemplateContentReferenceError = require("../src/Errors/UsingCircularTemplateContentReferenceError"); +const normalizeNewLines = require("./Util/normalizeNewLines"); let tmpl1 = new Template( "./test/stubs/templateMapCollection/test1.md", @@ -26,7 +26,7 @@ let tmpl5 = new Template( "./test/stubs/_site" ); -test("TemplateMap has collections added", async t => { +test("TemplateMap has collections added", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -36,7 +36,7 @@ test("TemplateMap has collections added", async t => { t.is(tm.collection.getAll().length, 2); }); -test("TemplateMap compared to Collection API", async t => { +test("TemplateMap compared to Collection API", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl4); @@ -58,7 +58,7 @@ test("TemplateMap compared to Collection API", async t => { t.deepEqual(posts[1].template, tmpl4); }); -test("populating the collection twice should clear the previous values (--watch was making it cumulative)", async t => { +test("populating the collection twice should clear the previous values (--watch was making it cumulative)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -69,7 +69,7 @@ test("populating the collection twice should clear the previous values (--watch t.is(tm.getMap().length, 2); }); -test("TemplateMap adds collections data and has templateContent values", async t => { +test("TemplateMap adds collections data and has templateContent values", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -99,7 +99,7 @@ test("TemplateMap adds collections data and has templateContent values", async t ); }); -test("TemplateMap circular references (map without templateContent)", async t => { +test("TemplateMap circular references (map without templateContent)", async (t) => { let tm = new TemplateMap(); await tm.add( new Template( @@ -123,7 +123,7 @@ test("TemplateMap circular references (map without templateContent)", async t => ); }); -test("TemplateMap circular references (map.templateContent)", async t => { +test("TemplateMap circular references (map.templateContent)", async (t) => { let tm = new TemplateMap(); await tm.add( new Template( @@ -141,12 +141,12 @@ test("TemplateMap circular references (map.templateContent)", async t => { await tm.cache(); }, { - instanceOf: UsingCircularTemplateContentReferenceError + instanceOf: UsingCircularTemplateContentReferenceError, } ); }); -test("Issue #115, mixing pagination and collections", async t => { +test("Issue #115, mixing pagination and collections", async (t) => { let tmplFoos = new Template( "./test/stubs/issue-115/template-foos.liquid", "./test/stubs/", @@ -207,7 +207,7 @@ This page is bars ); }); -test("Issue #115 with layout, mixing pagination and collections", async t => { +test("Issue #115 with layout, mixing pagination and collections", async (t) => { let tmplFoos = new Template( "./test/stubs/issue-115/template-foos.liquid", "./test/stubs/", @@ -268,7 +268,7 @@ This page is bars ); }); -test("TemplateMap adds collections data and has page data values using .cache()", async t => { +test("TemplateMap adds collections data and has page data values using .cache()", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -288,7 +288,7 @@ test("TemplateMap adds collections data and has page data values using .cache()" t.truthy(map[0].data.page.date); }); -test("TemplateMap adds collections data and has page data values using ._testGetCollectionsData()", async t => { +test("TemplateMap adds collections data and has page data values using ._testGetCollectionsData()", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -312,15 +312,15 @@ test("TemplateMap adds collections data and has page data values using ._testGet t.is(collections.all[0].data.page.fileSlug, "test1"); }); -test("Url should be available in user config collections API calls", async t => { +test("Url should be available in user config collections API calls", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getAll(); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -342,10 +342,10 @@ test("Url should be available in user config collections API calls", async t => ); }); -test("Url should be available in user config collections API calls (test in callback)", async t => { +test("Url should be available in user config collections API calls (test in callback)", async (t) => { let tm = new TemplateMap(); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getAll(); t.is(all[0].url, "/templateMapCollection/test1/"); t.is( @@ -359,7 +359,7 @@ test("Url should be available in user config collections API calls (test in call ); return all; - } + }, }); await tm.add(tmpl1); @@ -367,7 +367,7 @@ test("Url should be available in user config collections API calls (test in call await tm.cache(); }); -test("Should be able to paginate a tag generated collection", async t => { +test("Should be able to paginate a tag generated collection", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -384,7 +384,7 @@ test("Should be able to paginate a tag generated collection", async t => { t.truthy(collections.dog.length); }); -test("Should be able to paginate a user config collection", async t => { +test("Should be able to paginate a user config collection", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -397,10 +397,10 @@ test("Should be able to paginate a user config collection", async t => { await tm.add(pagedTmpl); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getFilteredByTag("dog"); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -408,7 +408,7 @@ test("Should be able to paginate a user config collection", async t => { t.truthy(collections.userCollection.length); }); -test("Should be able to paginate a user config collection (uses rendered permalink)", async t => { +test("Should be able to paginate a user config collection (uses rendered permalink)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -421,7 +421,7 @@ test("Should be able to paginate a user config collection (uses rendered permali await tm.add(pagedTmpl); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getFilteredByTag("dog"); t.is(all[0].url, "/templateMapCollection/test1/"); t.is( @@ -429,7 +429,7 @@ test("Should be able to paginate a user config collection (uses rendered permali "./test/stubs/_site/templateMapCollection/test1/index.html" ); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -443,7 +443,7 @@ test("Should be able to paginate a user config collection (uses rendered permali t.is(urls.indexOf("/test-title/hello/") > -1, true); }); -test("Should be able to paginate a user config collection (paged template is also tagged)", async t => { +test("Should be able to paginate a user config collection (paged template is also tagged)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag @@ -457,10 +457,10 @@ test("Should be able to paginate a user config collection (paged template is als await tm.add(pagedTmpl); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getFilteredByTag("dog"); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -471,7 +471,7 @@ test("Should be able to paginate a user config collection (paged template is als t.is(collections.haha[0].url, "/templateMapCollection/paged-cfg-tagged/"); }); -test("Should be able to paginate a user config collection (paged template is also tagged, add all pages to collections)", async t => { +test("Should be able to paginate a user config collection (paged template is also tagged, add all pages to collections)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag @@ -485,10 +485,10 @@ test("Should be able to paginate a user config collection (paged template is als await tm.add(pagedTmpl); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getFilteredByTag("dog"); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -506,7 +506,7 @@ test("Should be able to paginate a user config collection (paged template is als ); }); -test("Should be able to paginate a user config collection (paged template is also tagged, uses custom rendered permalink)", async t => { +test("Should be able to paginate a user config collection (paged template is also tagged, uses custom rendered permalink)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag @@ -520,10 +520,10 @@ test("Should be able to paginate a user config collection (paged template is als await tm.add(pagedTmpl); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getFilteredByTag("dog"); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -532,7 +532,7 @@ test("Should be able to paginate a user config collection (paged template is als t.is(collections.haha[0].url, "/test-title/goodbye/"); }); -test("Should be able to paginate a user config collection (paged template is also tagged, uses custom rendered permalink, add all pages to collections)", async t => { +test("Should be able to paginate a user config collection (paged template is also tagged, uses custom rendered permalink, add all pages to collections)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag @@ -546,10 +546,10 @@ test("Should be able to paginate a user config collection (paged template is als await tm.add(pagedTmpl); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getFilteredByTag("dog"); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -559,7 +559,7 @@ test("Should be able to paginate a user config collection (paged template is als t.is(collections.haha[1].url, "/test-title-4/goodbye/"); }); -test("TemplateMap render and templateContent are the same (templateContent doesn’t have layout but makes proper use of layout front matter data)", async t => { +test("TemplateMap render and templateContent are the same (templateContent doesn’t have layout but makes proper use of layout front matter data)", async (t) => { let tm = new TemplateMap(); let tmplLayout = new Template( "./test/stubs/templateMapCollection/testWithLayout.md", @@ -575,7 +575,7 @@ test("TemplateMap render and templateContent are the same (templateContent doesn t.is((await map[0].template.render(map[0].data)).trim(), "

Inherited

"); }); -test("Should be able to paginate a tag generated collection (and it has templateContent)", async t => { +test("Should be able to paginate a tag generated collection (and it has templateContent)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag @@ -615,7 +615,7 @@ test("Should be able to paginate a tag generated collection (and it has template ); }); -test("Should be able to paginate a tag generated collection when aliased (and it has templateContent)", async t => { +test("Should be able to paginate a tag generated collection when aliased (and it has templateContent)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag @@ -649,7 +649,7 @@ test("Should be able to paginate a tag generated collection when aliased (and it ); }); -test("Issue #253: Paginated template with a tag should put multiple pages into a collection", async t => { +test("Issue #253: Paginated template with a tag should put multiple pages into a collection", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl2); @@ -664,10 +664,10 @@ test("Issue #253: Paginated template with a tag should put multiple pages into a // TODO test user config collections (no actual tests against this collection yet) tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { let all = collection.getFilteredByTag("dog"); return all; - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -679,37 +679,37 @@ test("Issue #253: Paginated template with a tag should put multiple pages into a t.is(collections.haha[1].url, "/tagged-pagination-multiples/test/1/"); }); -test("getUserConfigCollectionNames", async t => { +test("getUserConfigCollectionNames", async (t) => { let tm = new TemplateMap(); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { return collection.getAll(); }, - otherUserCollection: function(collection) { + otherUserCollection: function (collection) { return collection.getAll(); - } + }, }); t.deepEqual(tm.getUserConfigCollectionNames(), [ "userCollection", - "otherUserCollection" + "otherUserCollection", ]); }); -test("isUserConfigCollectionName", t => { +test("isUserConfigCollectionName", (t) => { let tm = new TemplateMap(); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { return collection.getAll(); - } + }, }); t.is(tm.isUserConfigCollectionName("userCollection"), true); t.is(tm.isUserConfigCollectionName("userCollection2"), false); }); -test("Dependency Map should have nodes that have no dependencies and no dependents", async t => { +test("Dependency Map should have nodes that have no dependencies and no dependents", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl5); @@ -717,31 +717,31 @@ test("Dependency Map should have nodes that have no dependencies and no dependen await tm.cache(); let deps = await tm.getMappedDependencies(); - t.true(deps.filter(dep => dep.indexOf("test5.md") > -1).length > 0); + t.true(deps.filter((dep) => dep.indexOf("test5.md") > -1).length > 0); let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 2); }); -test("Dependency Map should have include orphan user config collections (in the correct order)", async t => { +test("Dependency Map should have include orphan user config collections (in the correct order)", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); await tm.add(tmpl5); tm.setUserConfigCollections({ - userCollection: function(collection) { + userCollection: function (collection) { return collection.getAll(); - } + }, }); await tm.cache(); let deps = await tm.getMappedDependencies(); - t.true(deps.filter(dep => dep.indexOf("userCollection") > -1).length === 0); + t.true(deps.filter((dep) => dep.indexOf("userCollection") > -1).length === 0); let delayedDeps = await tm.getDelayedMappedDependencies(); t.true( - delayedDeps.filter(dep => dep.indexOf("userCollection") > -1).length > 0 + delayedDeps.filter((dep) => dep.indexOf("userCollection") > -1).length > 0 ); let collections = await tm._testGetCollectionsData(); @@ -749,7 +749,7 @@ test("Dependency Map should have include orphan user config collections (in the t.is(collections.userCollection.length, 2); }); -test("Template pages should not have layouts when added to collections", async t => { +test("Template pages should not have layouts when added to collections", async (t) => { let tm = new TemplateMap(); let tmpl = new Template( "./test/stubs/collection-layout-wrap.njk", @@ -764,7 +764,7 @@ test("Template pages should not have layouts when added to collections", async t t.is(collections.all[0].templateContent, "Layout Test"); }); -test("Paginated template pages should not have layouts when added to collections", async t => { +test("Paginated template pages should not have layouts when added to collections", async (t) => { let tm = new TemplateMap(); let pagedTmpl = new Template( @@ -782,7 +782,7 @@ test("Paginated template pages should not have layouts when added to collections t.is(collections.all[2].templateContent, "three"); }); -test("Tag pages. Allow pagination over all collections a la `data: collections`", async t => { +test("Tag pages. Allow pagination over all collections a la `data: collections`", async (t) => { let tm = new TemplateMap(); let pagedTmpl = new Template( @@ -799,17 +799,17 @@ test("Tag pages. Allow pagination over all collections a la `data: collections`" let collectionTagPagesTemplateContents = new Set( collections.all - .filter(function(entry) { + .filter(function (entry) { return entry.inputPath.endsWith("tagpages.njk"); }) - .map(function(entry) { + .map(function (entry) { return entry.templateContent.trim(); }) ); t.deepEqual(collectionTagPagesTemplateContents, new Set(["post"])); }); -test("Tag pages (all pages added to collections). Allow pagination over all collections a la `data: collections`", async t => { +test("Tag pages (all pages added to collections). Allow pagination over all collections a la `data: collections`", async (t) => { let tm = new TemplateMap(); let pagedTmpl = new Template( @@ -826,10 +826,10 @@ test("Tag pages (all pages added to collections). Allow pagination over all coll let collectionTagPagesTemplateContents = new Set( collections.all - .filter(function(entry) { + .filter(function (entry) { return entry.inputPath.endsWith("tagpagesall.njk"); }) - .map(function(entry) { + .map(function (entry) { return entry.templateContent.trim(); }) ); @@ -839,7 +839,7 @@ test("Tag pages (all pages added to collections). Allow pagination over all coll ); }); -test("eleventyExcludeFromCollections", async t => { +test("eleventyExcludeFromCollections", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); @@ -860,7 +860,7 @@ test("eleventyExcludeFromCollections", async t => { t.is(collections.dog.length, 1); }); -test("Paginate over collections.all", async t => { +test("Paginate over collections.all", async (t) => { let tm = new TemplateMap(); let pagedTmpl = new Template( @@ -875,19 +875,19 @@ test("Paginate over collections.all", async t => { let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 4); t.is( - collections.all.filter(function(entry) { + collections.all.filter(function (entry) { return entry.inputPath.endsWith("test1.md"); }).length, 1 ); t.is( - collections.all.filter(function(entry) { + collections.all.filter(function (entry) { return entry.inputPath.endsWith("test2.md"); }).length, 1 ); t.is( - collections.all.filter(function(entry) { + collections.all.filter(function (entry) { return entry.inputPath.endsWith("paginateall.njk"); }).length, 2 @@ -913,7 +913,7 @@ test("Paginate over collections.all", async t => { t.is(map[2]._pages[0].templateContent.trim(), "

Test 2

"); }); -test("Paginate over collections.all WITH a paginate over collections (tag pages)", async t => { +test("Paginate over collections.all WITH a paginate over collections (tag pages)", async (t) => { let tm = new TemplateMap(); let pagedTmpl = new Template( @@ -936,7 +936,7 @@ test("Paginate over collections.all WITH a paginate over collections (tag pages) t.is(collections.all.length, 10); }); -test("Test a transform with a layout (via templateMap)", async t => { +test("Test a transform with a layout (via templateMap)", async (t) => { t.plan(7); let tm = new TemplateMap(); let tmpl = new Template( @@ -945,14 +945,14 @@ test("Test a transform with a layout (via templateMap)", async t => { "./test/stubs-475/_site" ); - tmpl.addLinter(function(content, inputPath, outputPath) { + tmpl.addLinter(function (content, inputPath, outputPath) { // should be pre-transform content t.is(content, "This is content."); t.true(inputPath.endsWith("transform-layout.njk")); t.true(outputPath.endsWith("transform-layout/index.html")); }); - tmpl.addTransform(function(content, outputPath) { + tmpl.addTransform(function (content, outputPath) { t.is(content, "This is content."); t.true(outputPath.endsWith("transform-layout/index.html")); return "OVERRIDE BY A TRANSFORM"; @@ -973,17 +973,17 @@ test("Test a transform with a layout (via templateMap)", async t => { } }); -test("Async user collection addCollection method", async t => { +test("Async user collection addCollection method", async (t) => { let tm = new TemplateMap(); await tm.add(tmpl1); tm.setUserConfigCollections({ - userCollection: async function(collection) { + userCollection: async function (collection) { return new Promise((resolve, reject) => { - setTimeout(function() { + setTimeout(function () { resolve(collection.getAll()); }, 50); }); - } + }, }); let collections = await tm._testGetCollectionsData(); @@ -992,7 +992,7 @@ test("Async user collection addCollection method", async t => { t.is(collections.userCollection[0].data.collections.userCollection.length, 1); }); -test("Duplicate permalinks in template map", async t => { +test("Duplicate permalinks in template map", async (t) => { let tmpl1 = new Template( "./test/stubs/permalink-conflicts/test1.md", "./test/stubs/", @@ -1012,7 +1012,7 @@ test("Duplicate permalinks in template map", async t => { }); }); -test("No duplicate permalinks in template map, using false", async t => { +test("No duplicate permalinks in template map, using false", async (t) => { let tmpl1 = new Template( "./test/stubs/permalink-conflicts-false/test1.md", "./test/stubs/", @@ -1031,7 +1031,7 @@ test("No duplicate permalinks in template map, using false", async t => { t.true(true); }); -test("Duplicate permalinks in template map, no leading slash", async t => { +test("Duplicate permalinks in template map, no leading slash", async (t) => { let tmpl1 = new Template( "./test/stubs/permalink-conflicts/test1.md", "./test/stubs/", @@ -1052,7 +1052,7 @@ test("Duplicate permalinks in template map, no leading slash", async t => { }); }); -test("TemplateMap circular references (map.templateContent) using eleventyExcludeFromCollections and collections.all", async t => { +test("TemplateMap circular references (map.templateContent) using eleventyExcludeFromCollections and collections.all", async (t) => { let tm = new TemplateMap(); await tm.add( new Template( @@ -1076,7 +1076,7 @@ test("TemplateMap circular references (map.templateContent) using eleventyExclud t.deepEqual(tm.getMappedDependencies(), [ "./test/stubs/issue-522/template.md", "___TAG___all", - "./test/stubs/issue-522/excluded.md" + "./test/stubs/issue-522/excluded.md", ]); await tm.cache(); diff --git a/test/TemplatePassthroughManagerTest.js b/test/TemplatePassthroughManagerTest.js index b648d1daf..da17edf60 100644 --- a/test/TemplatePassthroughManagerTest.js +++ b/test/TemplatePassthroughManagerTest.js @@ -1,27 +1,27 @@ -import test from "ava"; -import fs from "fs-extra"; -import TemplatePassthroughManager from "../src/TemplatePassthroughManager"; +const test = require("ava"); +const fs = require("fs-extra"); +const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); -test("Get paths from Config", async t => { +test("Get paths from Config", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ passthroughFileCopy: true, passthroughCopies: { - img: true - } + img: true, + }, }); t.deepEqual(mgr.getConfigPaths(), [{ inputPath: "./img", outputPath: true }]); }); -test("isPassthroughCopyFile", async t => { +test("isPassthroughCopyFile", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ passthroughFileCopy: true, passthroughCopies: { img: true, - fonts: true - } + fonts: true, + }, }); t.true(mgr.isPassthroughCopyFile([], "./img/test.png")); @@ -36,82 +36,82 @@ test("isPassthroughCopyFile", async t => { ); }); -test("Empty config paths when disabled in config", async t => { +test("Empty config paths when disabled in config", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ passthroughFileCopy: false, passthroughCopies: { - img: true - } + img: true, + }, }); t.deepEqual(mgr.getConfigPaths(), []); }); -test("Get glob paths from config", async t => { +test("Get glob paths from config", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ passthroughFileCopy: true, passthroughCopies: { "test/stubs/img": true, "test/stubs/img/**": "./", - "test/stubs/img/*.js": "./" - } + "test/stubs/img/*.js": "./", + }, }); t.deepEqual(mgr.getConfigPathGlobs(), [ "./test/stubs/img/**", "./test/stubs/img/**", - "./test/stubs/img/*.js" + "./test/stubs/img/*.js", ]); }); -test("Get file paths", async t => { +test("Get file paths", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true + passthroughFileCopy: true, }); t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), ["test.png"]); }); -test("Get file paths (filter out real templates)", async t => { +test("Get file paths (filter out real templates)", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true + passthroughFileCopy: true, }); t.deepEqual(mgr.getNonTemplatePaths(["test.njk"]), []); }); -test("Get file paths (filter out real templates), multiple", async t => { +test("Get file paths (filter out real templates), multiple", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true + passthroughFileCopy: true, }); t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.png"]), ["test.png"]); }); -test("Get file paths with a js file (filter out real templates), multiple", async t => { +test("Get file paths with a js file (filter out real templates), multiple", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true + passthroughFileCopy: true, }); t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.js"]), ["test.js"]); }); -test("Get file paths when disabled in config", async t => { +test("Get file paths when disabled in config", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: false + passthroughFileCopy: false, }); t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), []); }); -test("Naughty paths outside of project dir", async t => { +test("Naughty paths outside of project dir", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ passthroughFileCopy: true, @@ -120,11 +120,11 @@ test("Naughty paths outside of project dir", async t => { "../*": "./", "./test/stubs/template-passthrough2/static/*.css": "./", "./test/stubs/template-passthrough2/static/*.js": "../../", - "./test/stubs/template-passthrough2/img.jpg": "../../" - } + "./test/stubs/template-passthrough2/img.jpg": "../../", + }, }); - await t.throwsAsync(async function() { + await t.throwsAsync(async function () { for (let path of mgr.getConfigPaths()) { await mgr.copyPath(path); } @@ -135,11 +135,11 @@ test("Naughty paths outside of project dir", async t => { "./test/stubs/template-passthrough2/_site/nope.txt", "./test/stubs/template-passthrough2/_site/nope/", "./test/stubs/test.js", - "./test/stubs/img.jpg" + "./test/stubs/img.jpg", ]; let results = await Promise.all( - output.map(function(path) { + output.map(function (path) { return fs.exists(path); }) ); diff --git a/test/TemplatePassthroughTest.js b/test/TemplatePassthroughTest.js index 4b3f37058..f7230c6d8 100644 --- a/test/TemplatePassthroughTest.js +++ b/test/TemplatePassthroughTest.js @@ -1,5 +1,5 @@ -import test from "ava"; -import TemplatePassthrough from "../src/TemplatePassthrough"; +const test = require("ava"); +const TemplatePassthrough = require("../src/TemplatePassthrough"); const getTemplatePassthrough = (path, outputDir, inputDir) => { if (typeof path === "object") { @@ -12,14 +12,14 @@ const getTemplatePassthrough = (path, outputDir, inputDir) => { ); }; -test("Constructor", t => { +test("Constructor", (t) => { let pass = getTemplatePassthrough("avatar.png", "_site", "."); t.truthy(pass); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/avatar.png"); }); -test("Constructor, input directory in inputPath is stripped", t => { +test("Constructor, input directory in inputPath is stripped", (t) => { let pass = getTemplatePassthrough("src/avatar.png", "_site", "src"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/avatar.png"); @@ -33,7 +33,7 @@ test("Constructor, input directory in inputPath is stripped", t => { t.is(pass2.getOutputPath(), "_site/avatar.png"); }); -test("Constructor, input directory in inputPath is stripped, duplicate directory names", t => { +test("Constructor, input directory in inputPath is stripped, duplicate directory names", (t) => { let pass = getTemplatePassthrough("src/src/avatar.png", "_site", "src"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/src/avatar.png"); @@ -47,7 +47,7 @@ test("Constructor, input directory in inputPath is stripped, duplicate directory t.is(pass2.getOutputPath(), "_site/src/avatar.png"); }); -test("Constructor, input directory (object param, directory)", t => { +test("Constructor, input directory (object param, directory)", (t) => { let pass = getTemplatePassthrough( { inputPath: "src/test", outputPath: "test" }, "_site", @@ -57,7 +57,7 @@ test("Constructor, input directory (object param, directory)", t => { t.is(pass.getOutputPath(), "_site/test"); }); -test("Constructor, input directory, path missing input directory", t => { +test("Constructor, input directory, path missing input directory", (t) => { let pass = getTemplatePassthrough("avatar.png", "_site", "src"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/avatar.png"); @@ -71,26 +71,26 @@ test("Constructor, input directory, path missing input directory", t => { t.is(pass2.getOutputPath(), "_site/avatar.png"); }); -test("Constructor Dry Run", t => { +test("Constructor Dry Run", (t) => { let pass = getTemplatePassthrough("avatar.png", "_site", "."); pass.setDryRun(true); t.is(pass.outputPath, true); t.is(pass.isDryRun, true); }); -test("Origin path isn’t included in output when targeting a directory", t => { +test("Origin path isn’t included in output when targeting a directory", (t) => { let pass = getTemplatePassthrough("img", "_site", "_src"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/img"); }); -test("Origin path isn’t included in output when targeting a directory several levels deep", t => { +test("Origin path isn’t included in output when targeting a directory several levels deep", (t) => { let pass = getTemplatePassthrough("img", "_site", "_src/subdir"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/img"); }); -test("Target directory’s subdirectory structure is retained", t => { +test("Target directory’s subdirectory structure is retained", (t) => { let pass = getTemplatePassthrough("subdir/img", "_site", "_src"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/subdir/img"); @@ -103,19 +103,19 @@ test("Target directory’s subdirectory structure is retained", t => { t.is(pass2.getOutputPath(), "_site/subdir/img"); }); -test("Origin path isn’t included in output when targeting a file", t => { +test("Origin path isn’t included in output when targeting a file", (t) => { let pass = getTemplatePassthrough("avatar.png", "_site", "_src"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/avatar.png"); }); -test("Origin path isn’t included in output when targeting a file several levels deep", t => { +test("Origin path isn’t included in output when targeting a file several levels deep", (t) => { let pass = getTemplatePassthrough("avatar.png", "_site", "_src/subdir/img"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/avatar.png"); }); -test("Full input file path and deep input path", t => { +test("Full input file path and deep input path", (t) => { t.is( getTemplatePassthrough( "src/views/avatar.png", @@ -166,19 +166,19 @@ test("Full input file path and deep input path", t => { ); }); -test(".htaccess", t => { +test(".htaccess", (t) => { let pass = getTemplatePassthrough(".htaccess", "_site", "."); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/.htaccess"); }); -test(".htaccess with input dir", t => { +test(".htaccess with input dir", (t) => { let pass = getTemplatePassthrough(".htaccess", "_site", "_src"); t.is(pass.outputPath, true); t.is(pass.getOutputPath(), "_site/.htaccess"); }); -test("getFiles where not glob and file does not exist", async t => { +test("getFiles where not glob and file does not exist", async (t) => { const inputPath = ".htaccess"; let pass = getTemplatePassthrough(inputPath, "_site", "_src"); t.is(pass.outputPath, true); @@ -186,7 +186,7 @@ test("getFiles where not glob and file does not exist", async t => { t.deepEqual(files, []); }); -test("getFiles where not glob and directory does not exist", async t => { +test("getFiles where not glob and directory does not exist", async (t) => { const inputPath = "./test/stubs/template-passthrough/static/not-exists/"; let pass = getTemplatePassthrough(inputPath, "_site", "_src"); t.is(pass.outputPath, true); @@ -194,7 +194,7 @@ test("getFiles where not glob and directory does not exist", async t => { t.deepEqual(files, []); }); -test("getFiles with glob", async t => { +test("getFiles with glob", async (t) => { const inputPath = "./test/stubs/template-passthrough/static/**"; let pass = getTemplatePassthrough(inputPath, "_site", "_src"); t.is(pass.outputPath, true); @@ -205,26 +205,26 @@ test("getFiles with glob", async t => { [ "./test/stubs/template-passthrough/static/test.css", "./test/stubs/template-passthrough/static/test.js", - "./test/stubs/template-passthrough/static/nested/test-nested.css" + "./test/stubs/template-passthrough/static/nested/test-nested.css", ].sort() ); t.is( - pass.getOutputPath(files.filter(entry => entry.endsWith("test.css"))[0]), + pass.getOutputPath(files.filter((entry) => entry.endsWith("test.css"))[0]), "_site/test/stubs/template-passthrough/static/test.css" ); t.is( - pass.getOutputPath(files.filter(entry => entry.endsWith("test.js"))[0]), + pass.getOutputPath(files.filter((entry) => entry.endsWith("test.js"))[0]), "_site/test/stubs/template-passthrough/static/test.js" ); t.is( pass.getOutputPath( - files.filter(entry => entry.endsWith("test-nested.css"))[0] + files.filter((entry) => entry.endsWith("test-nested.css"))[0] ), "_site/test/stubs/template-passthrough/static/nested/test-nested.css" ); }); -test("getFiles with glob 2", async t => { +test("getFiles with glob 2", async (t) => { const inputPath = "./test/stubs/template-passthrough/static/**/*.js"; let pass = getTemplatePassthrough(inputPath, "_site", "_src"); t.is(pass.outputPath, true); @@ -236,7 +236,7 @@ test("getFiles with glob 2", async t => { ); }); -test("Directory where outputPath is true", async t => { +test("Directory where outputPath is true", async (t) => { let pass = getTemplatePassthrough( { inputPath: "./static", outputPath: true }, "_site", @@ -246,7 +246,7 @@ test("Directory where outputPath is true", async t => { t.is(pass.getOutputPath(), "_site/static"); }); -test("Nested directory where outputPath is remapped", async t => { +test("Nested directory where outputPath is remapped", async (t) => { let pass = getTemplatePassthrough( { inputPath: "./static/nested", outputPath: "./test" }, "_site", @@ -256,12 +256,12 @@ test("Nested directory where outputPath is remapped", async t => { t.is(pass.getOutputPath(), "_site/test"); }); -test("Glob pattern", async t => { +test("Glob pattern", async (t) => { const globResolvedPath = "./test/stubs/template-passthrough/static/test.js"; let pass = getTemplatePassthrough( { inputPath: "./test/stubs/template-passthrough/static/*.js", - outputPath: "./directory/" + outputPath: "./directory/", }, "_site", "_src" @@ -270,7 +270,7 @@ test("Glob pattern", async t => { t.is(pass.getOutputPath(globResolvedPath), "_site/directory/test.js"); }); -test("Output paths match with different templatePassthrough methods", async t => { +test("Output paths match with different templatePassthrough methods", async (t) => { let pass1 = getTemplatePassthrough( { inputPath: "./static/nested", outputPath: "./test" }, "_site", diff --git a/test/TemplatePathTest.js b/test/TemplatePathTest.js index 532ae57f8..13b563684 100644 --- a/test/TemplatePathTest.js +++ b/test/TemplatePathTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import TemplatePath from "../src/TemplatePath"; +const test = require("ava"); +const TemplatePath = require("../src/TemplatePath"); -test("getDir", t => { +test("getDir", (t) => { t.is(TemplatePath.getDir("README.md"), "."); t.is(TemplatePath.getDir("test/stubs/config.js"), "test/stubs"); t.is(TemplatePath.getDir("./test/stubs/config.js"), "./test/stubs"); @@ -10,12 +10,12 @@ test("getDir", t => { t.is(TemplatePath.getDir("test/stubs/!(multiple.md)"), "test/stubs"); }); -test("getDirFromFilePath", t => { +test("getDirFromFilePath", (t) => { t.is(TemplatePath.getDirFromFilePath("test/stubs/*.md"), "test/stubs"); t.is(TemplatePath.getDirFromFilePath("test/stubs/!(x.md)"), "test/stubs"); }); -test("getLastPathSegment", t => { +test("getLastPathSegment", (t) => { t.is(TemplatePath.getLastPathSegment("./testing/hello"), "hello"); t.is(TemplatePath.getLastPathSegment("./testing"), "testing"); t.is(TemplatePath.getLastPathSegment("./testing/"), "testing"); @@ -23,7 +23,7 @@ test("getLastPathSegment", t => { t.is(TemplatePath.getLastPathSegment("testing"), "testing"); }); -test("getAllDirs", t => { +test("getAllDirs", (t) => { t.deepEqual(TemplatePath.getAllDirs("."), ["."]); t.deepEqual(TemplatePath.getAllDirs("./"), ["."]); t.deepEqual(TemplatePath.getAllDirs("./testing"), ["./testing"]); @@ -33,13 +33,13 @@ test("getAllDirs", t => { t.deepEqual(TemplatePath.getAllDirs("./testing/hello"), [ "./testing/hello", - "./testing" + "./testing", ]); t.deepEqual(TemplatePath.getAllDirs("./src/collections/posts"), [ "./src/collections/posts", "./src/collections", - "./src" + "./src", ]); t.deepEqual( @@ -50,14 +50,14 @@ test("getAllDirs", t => { "./src/site/content/en", "./src/site/content", "./src/site", - "./src" + "./src", ] ); t.deepEqual(TemplatePath.getAllDirs("./src/_site/src"), [ "./src/_site/src", "./src/_site", - "./src" + "./src", ]); t.deepEqual(TemplatePath.getAllDirs("./src/_site/src/src/src"), [ @@ -65,11 +65,11 @@ test("getAllDirs", t => { "./src/_site/src/src", "./src/_site/src", "./src/_site", - "./src" + "./src", ]); }); -test("normalize", async t => { +test("normalize", async (t) => { t.is(TemplatePath.normalize(""), "."); t.is(TemplatePath.normalize("."), "."); t.is(TemplatePath.normalize("/"), "/"); @@ -90,7 +90,7 @@ test("normalize", async t => { t.is(TemplatePath.normalize(".htaccess"), ".htaccess"); }); -test("join", async t => { +test("join", async (t) => { t.is(TemplatePath.join("src", "_includes"), "src/_includes"); t.is(TemplatePath.join("src", "_includes/"), "src/_includes"); t.is(TemplatePath.join("src", "/_includes"), "src/_includes"); @@ -106,7 +106,7 @@ test("join", async t => { t.is(TemplatePath.join("src", "test", "..", "_includes"), "src/_includes"); }); -test("normalizeUrlPath", t => { +test("normalizeUrlPath", (t) => { t.is(TemplatePath.normalizeUrlPath(""), "."); t.is(TemplatePath.normalizeUrlPath("."), "."); t.is(TemplatePath.normalizeUrlPath("./"), "./"); @@ -123,23 +123,21 @@ test("normalizeUrlPath", t => { t.is(TemplatePath.normalizeUrlPath("/test/../../"), "/"); }); -test("absolutePath", t => { +test("absolutePath", (t) => { t.is( - TemplatePath.absolutePath(".eleventy.js") - .split("/") - .pop(), + TemplatePath.absolutePath(".eleventy.js").split("/").pop(), ".eleventy.js" ); }); -test("absolutePath and relativePath", t => { +test("absolutePath and relativePath", (t) => { t.is( TemplatePath.relativePath(TemplatePath.absolutePath(".eleventy.js")), ".eleventy.js" ); }); -test("addLeadingDotSlash", t => { +test("addLeadingDotSlash", (t) => { t.is(TemplatePath.addLeadingDotSlash("."), "./"); t.is(TemplatePath.addLeadingDotSlash(".."), "../"); t.is(TemplatePath.addLeadingDotSlash("./test/stubs"), "./test/stubs"); @@ -150,22 +148,22 @@ test("addLeadingDotSlash", t => { t.is(TemplatePath.addLeadingDotSlash(".nyc_output"), "./.nyc_output"); }); -test("addLeadingDotSlashArray", t => { +test("addLeadingDotSlashArray", (t) => { t.deepEqual(TemplatePath.addLeadingDotSlashArray(["."]), ["./"]); t.deepEqual(TemplatePath.addLeadingDotSlashArray([".."]), ["../"]); t.deepEqual(TemplatePath.addLeadingDotSlashArray(["./test/stubs"]), [ - "./test/stubs" + "./test/stubs", ]); t.deepEqual(TemplatePath.addLeadingDotSlashArray(["./dist"]), ["./dist"]); t.deepEqual(TemplatePath.addLeadingDotSlashArray(["../dist"]), ["../dist"]); t.deepEqual(TemplatePath.addLeadingDotSlashArray(["/dist"]), ["/dist"]); t.deepEqual(TemplatePath.addLeadingDotSlashArray(["dist"]), ["./dist"]); t.deepEqual(TemplatePath.addLeadingDotSlashArray([".nyc_output"]), [ - "./.nyc_output" + "./.nyc_output", ]); }); -test("stripLeadingDotSlash", t => { +test("stripLeadingDotSlash", (t) => { t.is(TemplatePath.stripLeadingDotSlash("./test/stubs"), "test/stubs"); t.is(TemplatePath.stripLeadingDotSlash("./dist"), "dist"); t.is(TemplatePath.stripLeadingDotSlash("../dist"), "../dist"); @@ -174,7 +172,7 @@ test("stripLeadingDotSlash", t => { t.is(TemplatePath.stripLeadingDotSlash(".htaccess"), ".htaccess"); }); -test("startsWithSubPath", t => { +test("startsWithSubPath", (t) => { t.false(TemplatePath.startsWithSubPath("./testing/hello", "./lskdjklfjz")); t.false(TemplatePath.startsWithSubPath("./testing/hello", "lskdjklfjz")); t.false(TemplatePath.startsWithSubPath("testing/hello", "./lskdjklfjz")); @@ -206,7 +204,7 @@ test("startsWithSubPath", t => { ); }); -test("stripLeadingSubPath", t => { +test("stripLeadingSubPath", (t) => { t.is( TemplatePath.stripLeadingSubPath("./testing/hello", "./lskdjklfjz"), "testing/hello" @@ -225,7 +223,7 @@ test("stripLeadingSubPath", t => { t.is(TemplatePath.stripLeadingSubPath(".htaccess", "."), ".htaccess"); }); -test("convertToRecursiveGlobSync", t => { +test("convertToRecursiveGlobSync", (t) => { t.is(TemplatePath.convertToRecursiveGlobSync(""), "./**"); t.is(TemplatePath.convertToRecursiveGlobSync("."), "./**"); t.is(TemplatePath.convertToRecursiveGlobSync("./"), "./**"); @@ -247,7 +245,7 @@ test("convertToRecursiveGlobSync", t => { ); }); -test("convertToRecursiveGlob", async t => { +test("convertToRecursiveGlob", async (t) => { t.is(await TemplatePath.convertToRecursiveGlob(""), "./**"); t.is(await TemplatePath.convertToRecursiveGlob("."), "./**"); t.is(await TemplatePath.convertToRecursiveGlob("./"), "./**"); @@ -269,14 +267,14 @@ test("convertToRecursiveGlob", async t => { ); }); -test("getExtension", t => { +test("getExtension", (t) => { t.is(TemplatePath.getExtension(""), ""); t.is(TemplatePath.getExtension("test/stubs"), ""); t.is(TemplatePath.getExtension("test/stubs.njk"), "njk"); t.is(TemplatePath.getExtension("test/stubs.hbs"), "hbs"); }); -test("removeExtension", t => { +test("removeExtension", (t) => { t.is(TemplatePath.removeExtension(""), ""); t.is(TemplatePath.removeExtension("", "hbs"), ""); @@ -308,21 +306,21 @@ test("removeExtension", t => { ); }); -test("isDirectorySync", t => { +test("isDirectorySync", (t) => { t.is(TemplatePath.isDirectorySync("asdlkfjklsadjflkja"), false); t.is(TemplatePath.isDirectorySync("test"), true); t.is(TemplatePath.isDirectorySync("test/stubs"), true); t.is(TemplatePath.isDirectorySync("test/stubs/.eleventyignore"), false); }); -test("isDirectory", async t => { +test("isDirectory", async (t) => { t.is(await TemplatePath.isDirectory("asdlkfjklsadjflkja"), false); t.is(await TemplatePath.isDirectory("test"), true); t.is(await TemplatePath.isDirectory("test/stubs"), true); t.is(await TemplatePath.isDirectory("test/stubs/.eleventyignore"), false); }); -test("exists", async t => { +test("exists", async (t) => { t.is(await TemplatePath.exists("asdlkfjklsadjflkja"), false); t.is(await TemplatePath.exists("test"), true); t.is(await TemplatePath.exists("test/stubs"), true); diff --git a/test/TemplatePermalinkNoWriteTest.js b/test/TemplatePermalinkNoWriteTest.js index ad25b4507..99145679d 100644 --- a/test/TemplatePermalinkNoWriteTest.js +++ b/test/TemplatePermalinkNoWriteTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import TemplatePermalinkNoWrite from "../src/TemplatePermalinkNoWrite"; +const test = require("ava"); +const TemplatePermalinkNoWrite = require("../src/TemplatePermalinkNoWrite"); -test("Test standard method signature", t => { +test("Test standard method signature", (t) => { let perm = new TemplatePermalinkNoWrite(); t.is(perm.toHref(), false); t.is(perm.toString(), false); diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index bec272e39..85372887a 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import TemplatePermalink from "../src/TemplatePermalink"; +const test = require("ava"); +const TemplatePermalink = require("../src/TemplatePermalink"); -test("Simple straight permalink", t => { +test("Simple straight permalink", (t) => { t.is( new TemplatePermalink("permalinksubfolder/test.html").toString(), "permalinksubfolder/test.html" @@ -26,7 +26,7 @@ test("Simple straight permalink", t => { ); }); -test("Permalink without filename", t => { +test("Permalink without filename", (t) => { t.is( new TemplatePermalink("permalinksubfolder/").toString(), "permalinksubfolder/index.html" @@ -54,7 +54,7 @@ test("Permalink without filename", t => { ); }); -test("Permalink with pagination subdir", t => { +test("Permalink with pagination subdir", (t) => { t.is( new TemplatePermalink("permalinksubfolder/test.html", "0/").toString(), "permalinksubfolder/0/test.html" @@ -74,7 +74,7 @@ test("Permalink with pagination subdir", t => { ); }); -test("Permalink generate", t => { +test("Permalink generate", (t) => { let gen = TemplatePermalink.generate; t.is(gen("./", "index").toString(), "index.html"); @@ -89,7 +89,7 @@ test("Permalink generate", t => { t.is(gen(".", "test", "1/").toHref(), "/test/1/"); }); -test("Permalink generate with suffix", t => { +test("Permalink generate with suffix", (t) => { let gen = TemplatePermalink.generate; t.is(gen(".", "test", null, "-o").toString(), "test/index-o.html"); @@ -98,7 +98,7 @@ test("Permalink generate with suffix", t => { t.is(gen(".", "test", "1/", "-o").toHref(), "/test/1/index-o.html"); }); -test("Permalink generate with new extension", t => { +test("Permalink generate with new extension", (t) => { let gen = TemplatePermalink.generate; t.is(gen(".", "test", null, null, "css").toString(), "test.css"); @@ -107,7 +107,7 @@ test("Permalink generate with new extension", t => { t.is(gen(".", "test", "1/", null, "css").toHref(), "/1/test.css"); }); -test("Permalink generate with subfolders", t => { +test("Permalink generate with subfolders", (t) => { let gen = TemplatePermalink.generate; t.is( @@ -134,7 +134,7 @@ test("Permalink generate with subfolders", t => { ); }); -test("Permalink matching folder and filename", t => { +test("Permalink matching folder and filename", (t) => { let gen = TemplatePermalink.generate; let hasDupe = TemplatePermalink._hasDuplicateFolder; t.is(hasDupe("subfolder", "component"), false); diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index a829d99b5..a8ddd5dcd 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -1,8 +1,8 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; -import templateConfig from "../src/Config"; -import Vue from "vue"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const templateConfig = require("../src/Config"); +const Vue = require("vue"); const renderer = require("vue-server-renderer").createRenderer(); function getNewTemplateRender(name, inputDir) { @@ -11,7 +11,7 @@ function getNewTemplateRender(name, inputDir) { return tr; } -test("Custom plaintext Render", async t => { +test("Custom plaintext Render", async (t) => { let tr = getNewTemplateRender("txt"); const config = templateConfig.getConfig(); @@ -19,12 +19,12 @@ test("Custom plaintext Render", async t => { tr.config.extensionMap.add({ extension: "txt", key: "txt", - compile: function(str, inputPath) { + compile: function (str, inputPath) { // plaintext - return function(data) { + return function (data) { return str; }; - } + }, }); let fn = await tr.getCompiledTemplate("

Paragraph

"); @@ -32,7 +32,7 @@ test("Custom plaintext Render", async t => { t.is(await fn({}), "

Paragraph

"); }); -test("Custom Vue Render", async t => { +test("Custom Vue Render", async (t) => { let tr = getNewTemplateRender("vue"); const config = templateConfig.getConfig(); @@ -40,23 +40,23 @@ test("Custom Vue Render", async t => { tr.config.extensionMap.add({ extension: "vue", key: "vue", - compile: function(str, inputPath) { - return async function(data) { + compile: function (str, inputPath) { + return async function (data) { const app = new Vue({ template: str, - data: data + data: data, }); return renderer.renderToString(app); }; - } + }, }); let fn = await tr.getCompiledTemplate(`

Paragraph

`); t.is(await fn({ test: "Hello" }), `

Hello

`); }); -test("Custom Sass Render", async t => { +test("Custom Sass Render", async (t) => { const sass = require("node-sass"); let tr = getNewTemplateRender("sass"); @@ -65,10 +65,10 @@ test("Custom Sass Render", async t => { tr.config.extensionMap.add({ extension: "sass", key: "sass", - compile: function(str, inputPath) { + compile: function (str, inputPath) { // TODO declare data variables as SASS variables? - return async function(data) { - return new Promise(function(resolve, reject) { + return async function (data) { + return new Promise(function (resolve, reject) { sass.render( { data: str, @@ -76,9 +76,9 @@ test("Custom Sass Render", async t => { style: "expanded", // TODO // sourcemap: "file", - outFile: "test_this_is_to_not_write_a_file.css" + outFile: "test_this_is_to_not_write_a_file.css", }, - function(error, result) { + function (error, result) { if (error) { reject(error); } else { @@ -88,7 +88,7 @@ test("Custom Sass Render", async t => { ); }); }; - } + }, }); let fn = await tr.getCompiledTemplate(`$color: blue; p { color: $color; }`); diff --git a/test/TemplateRenderEJSTest.js b/test/TemplateRenderEJSTest.js index 534cab77e..7271432b6 100644 --- a/test/TemplateRenderEJSTest.js +++ b/test/TemplateRenderEJSTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); diff --git a/test/TemplateRenderHTMLTest.js b/test/TemplateRenderHTMLTest.js index 7069a178d..dd572370a 100644 --- a/test/TemplateRenderHTMLTest.js +++ b/test/TemplateRenderHTMLTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -9,11 +9,11 @@ function getNewTemplateRender(name, inputDir) { } // HTML -test("HTML", t => { +test("HTML", (t) => { t.is(getNewTemplateRender("html").getEngineName(), "html"); }); -test("HTML Render", async t => { +test("HTML Render", async (t) => { let fn = await getNewTemplateRender("html").getCompiledTemplate( "

Paragraph

" ); @@ -21,35 +21,35 @@ test("HTML Render", async t => { t.is(await fn({}), "

Paragraph

"); }); -test("HTML Render: Parses HTML using liquid engine (default, with data)", async t => { +test("HTML Render: Parses HTML using liquid engine (default, with data)", async (t) => { let fn = await getNewTemplateRender("html").getCompiledTemplate( "

{{title}}

" ); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); -test("HTML Render: Parses HTML using ejs engine", async t => { +test("HTML Render: Parses HTML using ejs engine", async (t) => { let tr = getNewTemplateRender("html"); tr.setHtmlEngine("ejs"); let fn = await tr.getCompiledTemplate("

<%=title %>

"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); -test("HTML Render: Set HTML engine to false, don’t parse", async t => { +test("HTML Render: Set HTML engine to false, don’t parse", async (t) => { let tr = getNewTemplateRender("html"); tr.setHtmlEngine(false); let fn = await tr.getCompiledTemplate("

{{title}}

"); t.is((await fn()).trim(), "

{{title}}

"); }); -test("HTML Render: Pass in an override (ejs)", async t => { +test("HTML Render: Pass in an override (ejs)", async (t) => { let tr = getNewTemplateRender("html"); tr.setHtmlEngine("ejs"); let fn = await tr.getCompiledTemplate("

<%= title %>

"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); -test("HTML Render: Pass in an override (liquid)", async t => { +test("HTML Render: Pass in an override (liquid)", async (t) => { let tr = getNewTemplateRender("html"); tr.setHtmlEngine("liquid"); let fn = await tr.getCompiledTemplate("

{{title}}

"); diff --git a/test/TemplateRenderHamlTest.js b/test/TemplateRenderHamlTest.js index 189bc0787..c32631e7d 100644 --- a/test/TemplateRenderHamlTest.js +++ b/test/TemplateRenderHamlTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -9,16 +9,16 @@ function getNewTemplateRender(name, inputDir) { } // Haml -test("Haml", t => { +test("Haml", (t) => { t.is(getNewTemplateRender("haml").getEngineName(), "haml"); }); -test("Haml Render", async t => { +test("Haml Render", async (t) => { let fn = await getNewTemplateRender("haml").getCompiledTemplate("%p= name"); t.is((await fn({ name: "Zach" })).trim(), "

Zach

"); }); -test("Haml Render: with Library Override", async t => { +test("Haml Render: with Library Override", async (t) => { let tr = getNewTemplateRender("haml"); let lib = require("hamljs"); diff --git a/test/TemplateRenderHandlebarsTest.js b/test/TemplateRenderHandlebarsTest.js index 321b0b403..7c0ec53f8 100644 --- a/test/TemplateRenderHandlebarsTest.js +++ b/test/TemplateRenderHandlebarsTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -9,39 +9,39 @@ function getNewTemplateRender(name, inputDir) { } // Handlebars -test("Handlebars", t => { +test("Handlebars", (t) => { t.is(getNewTemplateRender("hbs").getEngineName(), "hbs"); }); -test("Handlebars Render", async t => { +test("Handlebars Render", async (t) => { let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{name}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Handlebars Render Unescaped Output (no HTML)", async t => { +test("Handlebars Render Unescaped Output (no HTML)", async (t) => { let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{{name}}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Handlebars Render Escaped Output", async t => { +test("Handlebars Render Escaped Output", async (t) => { let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{name}}

" ); t.is(await fn({ name: "Zach" }), "

<b>Zach</b>

"); }); -test("Handlebars Render Unescaped Output (HTML)", async t => { +test("Handlebars Render Unescaped Output (HTML)", async (t) => { let fn = await getNewTemplateRender("hbs").getCompiledTemplate( "

{{{name}}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Handlebars Render Partial", async t => { +test("Handlebars Render Partial", async (t) => { let fn = await getNewTemplateRender( "hbs", "./test/stubs/" @@ -49,7 +49,7 @@ test("Handlebars Render Partial", async t => { t.is(await fn(), "

This is an include.

"); }); -test.skip("Handlebars Render Partial (Relative)", async t => { +test.skip("Handlebars Render Partial (Relative)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.hbs", "./test/stubs/" @@ -59,7 +59,7 @@ test.skip("Handlebars Render Partial (Relative)", async t => { t.is(await fn(), "

This is an includdde.

"); }); -test("Handlebars Render Partial (Subdirectory)", async t => { +test("Handlebars Render Partial (Subdirectory)", async (t) => { let fn = await getNewTemplateRender( "hbs", "./test/stubs/" @@ -67,7 +67,7 @@ test("Handlebars Render Partial (Subdirectory)", async t => { t.is(await fn(), "

This is an include.

"); }); -test("Handlebars Render Partial with variable", async t => { +test("Handlebars Render Partial with variable", async (t) => { let fn = await getNewTemplateRender( "hbs", "./test/stubs/" @@ -75,7 +75,7 @@ test("Handlebars Render Partial with variable", async t => { t.is(await fn({ name: "Zach" }), "

This is a Zach.

"); }); -test("Handlebars Render: with Library Override", async t => { +test("Handlebars Render: with Library Override", async (t) => { let tr = getNewTemplateRender("hbs"); let lib = require("handlebars"); @@ -85,12 +85,12 @@ test("Handlebars Render: with Library Override", async t => { t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Handlebars Render Helper", async t => { +test("Handlebars Render Helper", async (t) => { let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ - helpername: function() { + helpername: function () { return "Zach"; - } + }, }); let fn = await tr.getCompiledTemplate( @@ -99,12 +99,12 @@ test("Handlebars Render Helper", async t => { t.is(await fn({ name: "Zach" }), "

This is a Zach Zach.

"); }); -test("Handlebars Render Helper (uses argument)", async t => { +test("Handlebars Render Helper (uses argument)", async (t) => { let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ - helpername2: function(name) { + helpername2: function (name) { return "Zach"; - } + }, }); let fn = await tr.getCompiledTemplate( @@ -113,18 +113,18 @@ test("Handlebars Render Helper (uses argument)", async t => { t.is(await fn({ name: "Zach" }), "

This is a Zach.

"); }); -test("Handlebars Render Shortcode", async t => { +test("Handlebars Render Shortcode", async (t) => { t.plan(3); let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ - shortcodename: function(name) { + shortcodename: function (name) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); t.is(this.page.url, "/hi/"); return name.toUpperCase(); - } + }, }); let fn = await tr.getCompiledTemplate( @@ -136,17 +136,17 @@ test("Handlebars Render Shortcode", async t => { ); }); -test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { +test("Handlebars Render HTML in Shortcode (Issue #460)", async (t) => { t.plan(2); let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ - shortcodenamehtml: function(name) { + shortcodenamehtml: function (name) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return `${name.toUpperCase()}`; - } + }, }); let fn = await tr.getCompiledTemplate( @@ -155,19 +155,19 @@ test("Handlebars Render HTML in Shortcode (Issue #460)", async t => { t.is(await fn({ name: "Howdy" }), "

This is a HOWDY.

"); }); -test("Handlebars Render Shortcode (Multiple args)", async t => { +test("Handlebars Render Shortcode (Multiple args)", async (t) => { t.plan(3); let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ - shortcodename2: function(name, name2) { + shortcodename2: function (name, name2) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); t.is(this.name2, "Zach"); return name.toUpperCase() + name2.toUpperCase(); - } + }, }); let fn = await tr.getCompiledTemplate( @@ -179,18 +179,18 @@ test("Handlebars Render Shortcode (Multiple args)", async t => { ); }); -test("Handlebars Render Paired Shortcode", async t => { +test("Handlebars Render Paired Shortcode", async (t) => { t.plan(2); let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ - shortcodename3: function(content, name, options) { + shortcodename3: function (content, name, options) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return (content + name).toUpperCase(); - } + }, }); let fn = await tr.getCompiledTemplate( @@ -199,18 +199,18 @@ test("Handlebars Render Paired Shortcode", async t => { t.is(await fn({ name: "Howdy" }), "

This is a TESTINGHOWDY.

"); }); -test("Handlebars Render Paired Shortcode (HTML)", async t => { +test("Handlebars Render Paired Shortcode (HTML)", async (t) => { t.plan(2); let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ - shortcodename3html: function(content, name, options) { + shortcodename3html: function (content, name, options) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return `${(content + name).toUpperCase()}`; - } + }, }); let fn = await tr.getCompiledTemplate( @@ -222,18 +222,18 @@ test("Handlebars Render Paired Shortcode (HTML)", async t => { ); }); -test("Handlebars Render Paired Shortcode (Spaces)", async t => { +test("Handlebars Render Paired Shortcode (Spaces)", async (t) => { t.plan(2); let tr = getNewTemplateRender("hbs"); tr.engine.addPairedShortcodes({ - shortcodename4: function(content, name, options) { + shortcodename4: function (content, name, options) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); return (content + name).toUpperCase(); - } + }, }); let fn = await tr.getCompiledTemplate( @@ -242,30 +242,30 @@ test("Handlebars Render Paired Shortcode (Spaces)", async t => { t.is(await fn({ name: "Howdy" }), "

This is a TESTINGHOWDY.

"); }); -test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async t => { +test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async (t) => { t.plan(5); let tr = getNewTemplateRender("hbs"); tr.engine.addShortcodes({ - shortcodechild: function(txt, options) { + shortcodechild: function (txt, options) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); t.is(this.name2, "Zach"); return txt; - } + }, }); tr.engine.addPairedShortcodes({ - shortcodeparent: function(content, name, name2, options) { + shortcodeparent: function (content, name, name2, options) { // Data in context // Note Handlebars exposes all data while other template languages only expose { page }. See #741 t.is(this.name, "Howdy"); t.is(this.name2, "Zach"); return (content + name + name2).toUpperCase(); - } + }, }); let fn = await tr.getCompiledTemplate( @@ -277,12 +277,12 @@ test("Handlebars Render Paired Shortcode with a Nested Single Shortcode", async ); }); -test("Handlebars Render Raw Output (Issue #436)", async t => { +test("Handlebars Render Raw Output (Issue #436)", async (t) => { let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ - "raw-helper": function(options) { + "raw-helper": function (options) { return options.fn(); - } + }, }); let fn = await tr.getCompiledTemplate( @@ -291,12 +291,12 @@ test("Handlebars Render Raw Output (Issue #436)", async t => { t.is(await fn({ name: "Zach" }), "{{bar}}"); }); -test("Handlebars Render Raw Output (Issue #436 with if statement)", async t => { +test("Handlebars Render Raw Output (Issue #436 with if statement)", async (t) => { let tr = getNewTemplateRender("hbs"); tr.engine.addHelpers({ - "raw-helper": function(options) { + "raw-helper": function (options) { return options.fn(); - } + }, }); let fn = await tr.getCompiledTemplate( @@ -312,7 +312,7 @@ test("Handlebars Render Raw Output (Issue #436 with if statement)", async t => { ); }); -test("Handlebars Render #each with Global Variable (Issue #759)", async t => { +test("Handlebars Render #each with Global Variable (Issue #759)", async (t) => { let fn = await new TemplateRender("hbs", "./test/stubs/").getCompiledTemplate( `` ); @@ -320,7 +320,7 @@ test("Handlebars Render #each with Global Variable (Issue #759)", async t => { ( await fn({ name: "Zach", - navigation: [{ link: "a", text: "text" }] + navigation: [{ link: "a", text: "text" }], }) ).trim(), `` diff --git a/test/TemplateRenderJSTLTest.js b/test/TemplateRenderJSTLTest.js index 3ce85f821..b1ff43930 100644 --- a/test/TemplateRenderJSTLTest.js +++ b/test/TemplateRenderJSTLTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -9,11 +9,11 @@ function getNewTemplateRender(name, inputDir) { } // ES6 -test("ES6 Template Literal", t => { +test("ES6 Template Literal", (t) => { t.is(getNewTemplateRender("jstl").getEngineName(), "jstl"); }); -test("ES6 Template Literal Render (Backticks)", async t => { +test("ES6 Template Literal Render (Backticks)", async (t) => { // pass in a string here, we don’t want to compile the template in the test :O let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "`

${name.toUpperCase()}

`" @@ -21,7 +21,7 @@ test("ES6 Template Literal Render (Backticks)", async t => { t.is(await fn({ name: "Tim" }), "

TIM

"); }); -test("ES6 Template Literal Render (No backticks)", async t => { +test("ES6 Template Literal Render (No backticks)", async (t) => { // pass in a string here, we don’t want to compile the template in the test :O let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "

${name.toUpperCase()}

" @@ -29,7 +29,7 @@ test("ES6 Template Literal Render (No backticks)", async t => { t.is(await fn({ name: "Tim" }), "

TIM

"); }); -test("ES6 Template Literal with newlines", async t => { +test("ES6 Template Literal with newlines", async (t) => { // pass in a string here, we don’t want to compile the template in the test :O let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "Test\n\nMarkdown Syntax ${name}\n" @@ -37,7 +37,7 @@ test("ES6 Template Literal with newlines", async t => { t.is(await fn({ name: "Tim" }), "Test\n\nMarkdown Syntax Tim\n"); }); -test("ES6 Template Literal with markdown", async t => { +test("ES6 Template Literal with markdown", async (t) => { // pass in a string here, we don’t want to compile the template in the test :O let fn = await getNewTemplateRender("jstl").getCompiledTemplate( "Test\n```\nMarkdown Syntax ${name}\n```" diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index f8f88712f..7be793297 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -8,7 +8,7 @@ function getNewTemplateRender(name, inputDir) { return tr; } -test("JS", t => { +test("JS", (t) => { t.is(getNewTemplateRender("11ty.js").getEngineName(), "11ty.js"); t.is( getNewTemplateRender("./test/stubs/filename.11ty.js").getEngineName(), @@ -21,28 +21,28 @@ test("JS", t => { ); }); -test("JS Render a string (no data)", async t => { +test("JS Render a string (no data)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/string.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Bill" }), "

Zach

"); }); -test("JS Render a promise (no data)", async t => { +test("JS Render a promise (no data)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/promise.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Bill" }), "

Zach

"); }); -test("JS Render a buffer (no data)", async t => { +test("JS Render a buffer (no data)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/buffer.11ty.js" ).getCompiledTemplate(); t.is(await fn({ name: "Bill" }), "

tést

"); }); -test("JS Render a function", async t => { +test("JS Render a function", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/function.11ty.js" ).getCompiledTemplate(); @@ -50,7 +50,7 @@ test("JS Render a function", async t => { t.is(await fn({ name: "Bill" }), "

Bill

"); }); -test("JS Render a function (arrow syntax)", async t => { +test("JS Render a function (arrow syntax)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/function-arrow.11ty.js" ).getCompiledTemplate(); @@ -58,7 +58,7 @@ test("JS Render a function (arrow syntax)", async t => { t.is(await fn({ name: "Bill" }), "

Bill

"); }); -test("JS Render a function, returns a Buffer", async t => { +test("JS Render a function, returns a Buffer", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/function-buffer.11ty.js" ).getCompiledTemplate(); @@ -67,7 +67,7 @@ test("JS Render a function, returns a Buffer", async t => { t.is(await fn({ name: "Bill" }), "

Bill

"); }); -test("JS Render a function (Markdown)", async t => { +test("JS Render a function (Markdown)", async (t) => { let tr = getNewTemplateRender("./test/stubs/function-markdown.11ty.js"); tr.setEngineOverride("11ty.js,md"); let fn = await tr.getCompiledTemplate(); @@ -75,7 +75,7 @@ test("JS Render a function (Markdown)", async t => { t.is((await fn({ name: "Bill" })).trim(), "

Bill

"); }); -test("JS Render a function (Collections)", async t => { +test("JS Render a function (Collections)", async (t) => { let tr = getNewTemplateRender("./test/stubs/use-collection.11ty.js"); let fn = await tr.getCompiledTemplate(); t.is( @@ -85,23 +85,23 @@ test("JS Render a function (Collections)", async t => { post: [ { data: { - title: "Testing" - } + title: "Testing", + }, }, { data: { - title: "Testing2" - } - } - ] - } + title: "Testing2", + }, + }, + ], + }, }) ).trim(), `
  • Testing
  • Testing2
` ); }); -test("JS Render an async function", async t => { +test("JS Render an async function", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/function-async.11ty.js" ).getCompiledTemplate(); @@ -109,7 +109,7 @@ test("JS Render an async function", async t => { t.is(await fn({ name: "Bill" }), "

Bill

"); }); -test("JS Render with a Class", async t => { +test("JS Render with a Class", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/class.11ty.js" ).getCompiledTemplate(); @@ -117,7 +117,7 @@ test("JS Render with a Class", async t => { t.is(await fn({ name: "Bill" }), "

BillBillTed

"); }); -test("JS Render with a Class, returns a buffer", async t => { +test("JS Render with a Class, returns a buffer", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/class-buffer.11ty.js" ).getCompiledTemplate(); @@ -126,7 +126,7 @@ test("JS Render with a Class, returns a buffer", async t => { t.is(await fn({ name: "Bill" }), "

BillBillTed

"); }); -test("JS Render with a Class, async render", async t => { +test("JS Render with a Class, async render", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/class-async.11ty.js" ).getCompiledTemplate(); @@ -134,7 +134,7 @@ test("JS Render with a Class, async render", async t => { t.is(await fn({ name: "Bill" }), "

Bill

"); }); -test("JS Render using Vue", async t => { +test("JS Render using Vue", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/vue.11ty.js" ).getCompiledTemplate(); @@ -148,7 +148,7 @@ test("JS Render using Vue", async t => { ); }); -test("JS Render using Vue (with a layout)", async t => { +test("JS Render using Vue (with a layout)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/vue-layout.11ty.js" ).getCompiledTemplate(); @@ -160,7 +160,7 @@ test("JS Render using Vue (with a layout)", async t => { ); }); -test("JS Render using ViperHTML", async t => { +test("JS Render using ViperHTML", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/viperhtml.11ty.js" ).getCompiledTemplate(); @@ -173,20 +173,20 @@ test("JS Render using ViperHTML", async t => { ); }); -test("JS Render with a function", async t => { +test("JS Render with a function", async (t) => { t.plan(8); let tr = getNewTemplateRender("./test/stubs/function-filter.11ty.js"); tr.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { t.is(this.page.url, "/hi/"); // sanity check to make sure data didn’t propagate t.not(this.name, "Zach"); t.not(this.name, "Bill"); return new String(val).toUpperCase(); - } - } + }, + }, }; let fn = await tr.getCompiledTemplate(); @@ -195,14 +195,14 @@ test("JS Render with a function", async t => { }); // This doesn’t work, per arrow functions -test.skip("Issue #934: JS Render with an arrow function and javascript function", async t => { +test.skip("Issue #934: JS Render with an arrow function and javascript function", async (t) => { let tr = new TemplateRender("./test/stubs/function-filter-arrow.11ty.js"); tr.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { return new String(val).toUpperCase(); - } - } + }, + }, }; let fn = await tr.getCompiledTemplate(); @@ -210,19 +210,19 @@ test.skip("Issue #934: JS Render with an arrow function and javascript function" t.is(await fn({ name: "Bill" }), "

BILL

"); }); -test("JS Render with a function and async filter", async t => { +test("JS Render with a function and async filter", async (t) => { t.plan(4); let tr = new TemplateRender("./test/stubs/function-async-filter.11ty.js"); tr.config = { javascriptFunctions: { - upper: function(val) { - return new Promise(resolve => { + upper: function (val) { + return new Promise((resolve) => { t.is(this.page.url, "/hi/"); resolve(new String(val).toUpperCase()); }); - } - } + }, + }, }; let fn = await tr.getCompiledTemplate(); @@ -230,16 +230,16 @@ test("JS Render with a function and async filter", async t => { t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILL

"); }); -test("JS Render with a function prototype", async t => { +test("JS Render with a function prototype", async (t) => { t.plan(4); let tr = getNewTemplateRender("./test/stubs/function-prototype.11ty.js"); tr.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { t.is(this.page.url, "/hi/"); return new String(val).toUpperCase(); - } - } + }, + }, }; let fn = await tr.getCompiledTemplate(); @@ -253,17 +253,17 @@ test("JS Render with a function prototype", async t => { ); }); -test("JS Class Render with a function", async t => { +test("JS Class Render with a function", async (t) => { t.plan(4); let tr = getNewTemplateRender("./test/stubs/class-filter.11ty.js"); tr.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { t.is(this.page.url, "/hi/"); return new String(val).toUpperCase(); - } - } + }, + }, }; let fn = await tr.getCompiledTemplate(); @@ -271,17 +271,17 @@ test("JS Class Render with a function", async t => { t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILLBillTed

"); }); -test("JS Class Async Render with a function", async t => { +test("JS Class Async Render with a function", async (t) => { t.plan(4); let tr = getNewTemplateRender("./test/stubs/class-async-filter.11ty.js"); tr.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { t.is(this.page.url, "/hi/"); return new String(val).toUpperCase(); - } - } + }, + }, }; let fn = await tr.getCompiledTemplate(); @@ -290,16 +290,16 @@ test("JS Class Async Render with a function", async t => { t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILLBillTed

"); }); -test("JS Class Async Render with a function (sync function, throws error)", async t => { +test("JS Class Async Render with a function (sync function, throws error)", async (t) => { let tr = new TemplateRender("./test/stubs/function-throws.11ty.js"); tr.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { throw new Error( "JS Class Async Render with a function (sync function, throws error)" ); - } - } + }, + }, }; let error = await t.throwsAsync(async () => { @@ -313,16 +313,16 @@ test("JS Class Async Render with a function (sync function, throws error)", asyn ); }); -test("JS Class Async Render with a function (async function, throws error)", async t => { +test("JS Class Async Render with a function (async function, throws error)", async (t) => { let tr = new TemplateRender("./test/stubs/function-throws-async.11ty.js"); tr.config = { javascriptFunctions: { - upper: async function(val) { + upper: async function (val) { throw new Error( "JS Class Async Render with a function (async function, throws error)" ); - } - } + }, + }, }; let error = await t.throwsAsync(async () => { @@ -336,7 +336,7 @@ test("JS Class Async Render with a function (async function, throws error)", asy ); }); -test("JS function has access to built in filters", async t => { +test("JS function has access to built in filters", async (t) => { t.plan(6); let tr = getNewTemplateRender("./test/stubs/function-fns.11ty.js"); @@ -344,7 +344,7 @@ test("JS function has access to built in filters", async t => { await fn({ avaTest: t, page: { url: "/hi/" } }); }); -test("Class has access to built in filters", async t => { +test("Class has access to built in filters", async (t) => { t.plan(6); let tr = getNewTemplateRender("./test/stubs/class-fns.11ty.js"); @@ -352,7 +352,7 @@ test("Class has access to built in filters", async t => { await fn({ avaTest: t, page: { url: "/hi/" } }); }); -test("Class has page property already and keeps it", async t => { +test("Class has page property already and keeps it", async (t) => { t.plan(2); let tr = getNewTemplateRender("./test/stubs/class-fns-has-page.11ty.js"); diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 8115b0f82..ea464bb14 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); diff --git a/test/TemplateRenderMarkdownPluginTest.js b/test/TemplateRenderMarkdownPluginTest.js index 74918a3e1..78d1972b7 100644 --- a/test/TemplateRenderMarkdownPluginTest.js +++ b/test/TemplateRenderMarkdownPluginTest.js @@ -1,10 +1,10 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import md from "markdown-it"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const md = require("markdown-it"); const createTestMarkdownPlugin = () => { - const plugin = md => { - md.core.ruler.after("inline", "replace-link", function(state) { + const plugin = (md) => { + md.core.ruler.after("inline", "replace-link", function (state) { plugin.environment = state.env; const link = state.tokens[1].children[0].attrs[0][1]; state.tokens[1].children[0].attrs[0][1] = `${link}?data=${state.env.some}`; @@ -15,7 +15,7 @@ const createTestMarkdownPlugin = () => { return plugin; }; -test("Markdown Render: with HTML prerender, sends context data to the markdown library", async t => { +test("Markdown Render: with HTML prerender, sends context data to the markdown library", async (t) => { let tr = new TemplateRender("md"); const plugin = createTestMarkdownPlugin(); @@ -30,7 +30,7 @@ test("Markdown Render: with HTML prerender, sends context data to the markdown l t.is(result, '

link text

\n'); }); -test("Markdown Render: without HTML prerender, sends context data to the markdown library", async t => { +test("Markdown Render: without HTML prerender, sends context data to the markdown library", async (t) => { let tr = new TemplateRender("md"); const plugin = createTestMarkdownPlugin(); diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js index e70390795..749efdb85 100644 --- a/test/TemplateRenderMarkdownTest.js +++ b/test/TemplateRenderMarkdownTest.js @@ -1,10 +1,10 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; -import md from "markdown-it"; -import mdEmoji from "markdown-it-emoji"; -import UserConfig from "../src/UserConfig"; -import eleventySyntaxHighlightPlugin from "@11ty/eleventy-plugin-syntaxhighlight"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const md = require("markdown-it"); +const mdEmoji = require("markdown-it-emoji"); +const UserConfig = require("../src/UserConfig"); +const eleventySyntaxHighlightPlugin = require("@11ty/eleventy-plugin-syntaxhighlight"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -13,42 +13,42 @@ function getNewTemplateRender(name, inputDir) { } // Markdown -test("Markdown", t => { +test("Markdown", (t) => { t.is(getNewTemplateRender("md").getEngineName(), "md"); }); -test("Markdown Render: Parses base markdown, no data", async t => { +test("Markdown Render: Parses base markdown, no data", async (t) => { let fn = await getNewTemplateRender("md").getCompiledTemplate("# My Title"); t.is((await fn()).trim(), "

My Title

"); }); -test("Markdown Render: Markdown should work with HTML too", async t => { +test("Markdown Render: Markdown should work with HTML too", async (t) => { let fn = await getNewTemplateRender("md").getCompiledTemplate( "

My Title

" ); t.is((await fn()).trim(), "

My Title

"); }); -test("Markdown Render: Parses markdown using liquid engine (default, with data)", async t => { +test("Markdown Render: Parses markdown using liquid engine (default, with data)", async (t) => { let fn = await getNewTemplateRender("md").getCompiledTemplate("# {{title}}"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); -test("Markdown Render: Parses markdown using ejs engine", async t => { +test("Markdown Render: Parses markdown using ejs engine", async (t) => { let tr = getNewTemplateRender("md"); tr.setMarkdownEngine("ejs"); let fn = await tr.getCompiledTemplate("<%=title %>"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); -test("Markdown Render: Ignore markdown, use only preprocess engine (useful for variable resolution in permalinks)", async t => { +test("Markdown Render: Ignore markdown, use only preprocess engine (useful for variable resolution in permalinks)", async (t) => { let tr = getNewTemplateRender("md"); tr.setUseMarkdown(false); let fn = await tr.getCompiledTemplate("{{title}}"); t.is((await fn({ title: "My Title" })).trim(), "My Title"); }); -test("Markdown Render: Skip markdown and preprocess engine (issue #466)", async t => { +test("Markdown Render: Skip markdown and preprocess engine (issue #466)", async (t) => { let tr = getNewTemplateRender("md"); tr.setMarkdownEngine(false); tr.setUseMarkdown(false); @@ -56,14 +56,14 @@ test("Markdown Render: Skip markdown and preprocess engine (issue #466)", async t.is((await fn({ title: "My Title" })).trim(), "404.html"); }); -test("Markdown Render: Set markdown engine to false, don’t parse", async t => { +test("Markdown Render: Set markdown engine to false, don’t parse", async (t) => { let tr = getNewTemplateRender("md"); tr.setMarkdownEngine(false); let fn = await tr.getCompiledTemplate("# {{title}}"); t.is((await fn()).trim(), "

{{title}}

"); }); -test("Markdown Render: Set markdown engine to false, don’t parse (test with HTML input)", async t => { +test("Markdown Render: Set markdown engine to false, don’t parse (test with HTML input)", async (t) => { let tr = getNewTemplateRender("md"); tr.setMarkdownEngine(false); let fn = await tr.getCompiledTemplate("

{{title}}

"); @@ -71,14 +71,14 @@ test("Markdown Render: Set markdown engine to false, don’t parse (test with HT t.is((await fn()).trim(), "

{{title}}

"); }); -test("Markdown Render: Pass in engine override (ejs)", async t => { +test("Markdown Render: Pass in engine override (ejs)", async (t) => { let tr = getNewTemplateRender("md"); tr.setMarkdownEngine("ejs"); let fn = await tr.getCompiledTemplate("# <%= title %>"); t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); -test("Markdown Render: Pass in an override (liquid)", async t => { +test("Markdown Render: Pass in an override (liquid)", async (t) => { let tr = getNewTemplateRender("md"); tr.setMarkdownEngine("liquid"); let fn = await tr.getCompiledTemplate("# {{title}}"); @@ -86,17 +86,17 @@ test("Markdown Render: Pass in an override (liquid)", async t => { t.is((await fn({ title: "My Title" })).trim(), "

My Title

"); }); -test("Markdown Render: Strikethrough", async t => { +test("Markdown Render: Strikethrough", async (t) => { let fn = await getNewTemplateRender("md").getCompiledTemplate("~~No~~"); t.is((await fn()).trim(), "

No

"); }); -test("Markdown Render: Strikethrough in a Header", async t => { +test("Markdown Render: Strikethrough in a Header", async (t) => { let fn = await getNewTemplateRender("md").getCompiledTemplate("# ~~No~~"); t.is((await fn()).trim(), "

No

"); }); -test("Markdown Render: with Library Override", async t => { +test("Markdown Render: with Library Override", async (t) => { let tr = getNewTemplateRender("md"); let mdLib = md(); @@ -107,7 +107,7 @@ test("Markdown Render: with Library Override", async t => { t.is((await fn()).trim(), "

:)

"); }); -test("Markdown Render: with Library Override and a Plugin", async t => { +test("Markdown Render: with Library Override and a Plugin", async (t) => { let tr = getNewTemplateRender("md"); let mdLib = md().use(mdEmoji); @@ -118,14 +118,14 @@ test("Markdown Render: with Library Override and a Plugin", async t => { t.is((await fn()).trim(), "

😃

"); }); -test("Markdown Render: use a custom highlighter", async t => { +test("Markdown Render: use a custom highlighter", async (t) => { let tr = getNewTemplateRender("md"); let mdLib = md(); mdLib.set({ - highlight: function(str, lang) { + highlight: function (str, lang) { return "This is overrrrrrride"; - } + }, }); tr.engine.setLibrary(mdLib); @@ -135,7 +135,7 @@ This is some code. t.is((await fn()).trim(), "
This is overrrrrrride
"); }); -test("Markdown Render: use prism highlighter (no language)", async t => { +test("Markdown Render: use prism highlighter (no language)", async (t) => { let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -145,7 +145,7 @@ test("Markdown Render: use prism highlighter (no language)", async t => { let mdLib = md(); mdLib.set({ - highlight: markdownHighlight + highlight: markdownHighlight, }); tr.engine.setLibrary(mdLib); @@ -159,7 +159,7 @@ This is some code. ); }); -test("Markdown Render: use prism highlighter", async t => { +test("Markdown Render: use prism highlighter", async (t) => { let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -169,7 +169,7 @@ test("Markdown Render: use prism highlighter", async t => { let mdLib = md(); mdLib.set({ - highlight: markdownHighlight + highlight: markdownHighlight, }); tr.engine.setLibrary(mdLib); @@ -182,7 +182,7 @@ var key = "value"; ); }); -test("Markdown Render: use prism highlighter (no space before language)", async t => { +test("Markdown Render: use prism highlighter (no space before language)", async (t) => { let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -192,7 +192,7 @@ test("Markdown Render: use prism highlighter (no space before language)", async let mdLib = md(); mdLib.set({ - highlight: markdownHighlight + highlight: markdownHighlight, }); tr.engine.setLibrary(mdLib); @@ -205,7 +205,7 @@ var key = "value"; ); }); -test("Markdown Render: use prism highlighter, line highlighting", async t => { +test("Markdown Render: use prism highlighter, line highlighting", async (t) => { let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -215,7 +215,7 @@ test("Markdown Render: use prism highlighter, line highlighting", async t => { let mdLib = md(); mdLib.set({ - highlight: markdownHighlight + highlight: markdownHighlight, }); tr.engine.setLibrary(mdLib); @@ -228,7 +228,7 @@ var key = "value"; ); }); -test("Markdown Render: use prism highlighter, line highlighting with fallback `text` language.", async t => { +test("Markdown Render: use prism highlighter, line highlighting with fallback `text` language.", async (t) => { let tr = getNewTemplateRender("md"); let userConfig = new UserConfig(); userConfig.addPlugin(eleventySyntaxHighlightPlugin); @@ -238,7 +238,7 @@ test("Markdown Render: use prism highlighter, line highlighting with fallback `t let mdLib = md(); mdLib.set({ - highlight: markdownHighlight + highlight: markdownHighlight, }); tr.engine.setLibrary(mdLib); @@ -251,12 +251,12 @@ var key = "value"; ); }); -test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", async t => { +test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Liquid"); let liquidEngine = new cls("liquid", tr.getIncludesDir()); - liquidEngine.addShortcode("testShortcode", function() { + liquidEngine.addShortcode("testShortcode", function () { return "## My Other Title"; }); tr.setMarkdownEngine(liquidEngine); @@ -267,7 +267,7 @@ test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", ( await fn({ title: "My Title", - otherTitle: "My Other Title" + otherTitle: "My Other Title", }) ).trim(), `

My Title

@@ -275,12 +275,12 @@ test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", ); }); -test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)", async t => { +test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Nunjucks"); let nunjucksEngine = new cls("njk", tr.getIncludesDir()); - nunjucksEngine.addShortcode("testShortcode", function() { + nunjucksEngine.addShortcode("testShortcode", function () { return "## My Other Title"; }); tr.setMarkdownEngine(nunjucksEngine); @@ -291,7 +291,7 @@ test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)" ( await fn({ title: "My Title", - otherTitle: "My Other Title" + otherTitle: "My Other Title", }) ).trim(), `

My Title

@@ -299,12 +299,12 @@ test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)" ); }); -test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue #536)", async t => { +test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Liquid"); let liquidEngine = new cls("liquid", tr.getIncludesDir()); - liquidEngine.addPairedShortcode("testShortcode", function(content) { + liquidEngine.addPairedShortcode("testShortcode", function (content) { return content; }); tr.setMarkdownEngine(liquidEngine); @@ -315,7 +315,7 @@ test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue # ( await fn({ title: "My Title", - otherTitle: "My Other Title" + otherTitle: "My Other Title", }) ).trim(), `

My Title

@@ -323,12 +323,12 @@ test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue # ); }); -test("Markdown Render: use Markdown inside of a Nunjucks paired shortcode (Issue #536)", async t => { +test("Markdown Render: use Markdown inside of a Nunjucks paired shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); let cls = require("../src/Engines/Nunjucks"); let nunjucksEngine = new cls("njk", tr.getIncludesDir()); - nunjucksEngine.addPairedShortcode("testShortcode", function(content) { + nunjucksEngine.addPairedShortcode("testShortcode", function (content) { return content; }); tr.setMarkdownEngine(nunjucksEngine); @@ -339,7 +339,7 @@ test("Markdown Render: use Markdown inside of a Nunjucks paired shortcode (Issue ( await fn({ title: "My Title", - otherTitle: "My Other Title" + otherTitle: "My Other Title", }) ).trim(), `

My Title

diff --git a/test/TemplateRenderMustacheTest.js b/test/TemplateRenderMustacheTest.js index a9f872506..db5cd4c18 100644 --- a/test/TemplateRenderMustacheTest.js +++ b/test/TemplateRenderMustacheTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -9,18 +9,18 @@ function getNewTemplateRender(name, inputDir) { } // Mustache -test("Mustache", async t => { +test("Mustache", async (t) => { t.is(getNewTemplateRender("mustache").getEngineName(), "mustache"); }); -test("Mustache Render", async t => { +test("Mustache Render", async (t) => { let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{name}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Mustache Render Partial (raw text content)", async t => { +test("Mustache Render Partial (raw text content)", async (t) => { let fn = await getNewTemplateRender( "mustache", "./test/stubs/" @@ -28,7 +28,7 @@ test("Mustache Render Partial (raw text content)", async t => { t.is(await fn(), "

This is an include.

"); }); -test.skip("Mustache Render Partial (relative path, raw text content)", async t => { +test.skip("Mustache Render Partial (relative path, raw text content)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.mustache", "./test/stubs/" @@ -36,7 +36,7 @@ test.skip("Mustache Render Partial (relative path, raw text content)", async t = t.is(await fn(), "

This is an includdde.

"); }); -test("Mustache Render Partial (uses a variable in content)", async t => { +test("Mustache Render Partial (uses a variable in content)", async (t) => { let fn = await getNewTemplateRender( "mustache", "./test/stubs/" @@ -44,7 +44,7 @@ test("Mustache Render Partial (uses a variable in content)", async t => { t.is(await fn({ name: "Zach" }), "

This is a Zach.

"); }); -test("Mustache Render Partial (Subdirectory)", async t => { +test("Mustache Render Partial (Subdirectory)", async (t) => { let fn = await getNewTemplateRender( "mustache", "./test/stubs/" @@ -52,7 +52,7 @@ test("Mustache Render Partial (Subdirectory)", async t => { t.is(await fn({ name: "Zach" }), "

This is an include.

"); }); -test("Mustache Render: with Library Override", async t => { +test("Mustache Render: with Library Override", async (t) => { let tr = getNewTemplateRender("mustache"); let lib = require("mustache"); @@ -62,14 +62,14 @@ test("Mustache Render: with Library Override", async t => { t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Mustache Render Unescaped Output (no HTML)", async t => { +test("Mustache Render Unescaped Output (no HTML)", async (t) => { let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{{name}}}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Mustache Render Escaped Output", async t => { +test("Mustache Render Escaped Output", async (t) => { let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{name}}

" ); @@ -79,7 +79,7 @@ test("Mustache Render Escaped Output", async t => { ); }); -test("Mustache Render Unescaped Output (HTML)", async t => { +test("Mustache Render Unescaped Output (HTML)", async (t) => { let fn = await getNewTemplateRender("mustache").getCompiledTemplate( "

{{{name}}}

" ); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 2f0ab7710..30d804bac 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -11,40 +11,40 @@ function getNewTemplateRender(name, inputDir) { class TestEleventyError extends Error {} async function getPromise(resolveTo) { - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(resolveTo); }); }); } // Nunjucks -test("Nunjucks", t => { +test("Nunjucks", (t) => { t.is(getNewTemplateRender("njk").getEngineName(), "njk"); }); -test("Nunjucks Render", async t => { +test("Nunjucks Render", async (t) => { let fn = await getNewTemplateRender("njk").getCompiledTemplate( "

{{ name }}

" ); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Nunjucks Render Addition", async t => { +test("Nunjucks Render Addition", async (t) => { let fn = await new TemplateRender("njk").getCompiledTemplate( "

{{ number + 1 }}

" ); t.is(await fn({ number: 1 }), "

2

"); }); -test("Nunjucks Render Extends", async t => { +test("Nunjucks Render Extends", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "{% extends 'base.njk' %}{% block content %}This is a child.{% endblock %}" ); t.is(await fn(), "

This is a child.

"); }); -test("Nunjucks Render Relative Extends", async t => { +test("Nunjucks Render Relative Extends", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "test/stubs" @@ -54,28 +54,28 @@ test("Nunjucks Render Relative Extends", async t => { t.is(await fn(), "

This is a child.

"); }); -test("Nunjucks Render Include", async t => { +test("Nunjucks Render Include", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'included.njk' %}

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

This is an include.

"); }); -test("Nunjucks Render Include (different extension)", async t => { +test("Nunjucks Render Include (different extension)", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'included.nunj' %}

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

Nunjabusiness

"); }); -test("Nunjucks Render Include (different extension, subdir)", async t => { +test("Nunjucks Render Include (different extension, subdir)", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'subfolder/included.nunj' %}

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

Nunjabusiness2

"); }); -test("Nunjucks Render Relative Include Issue #190", async t => { +test("Nunjucks Render Relative Include Issue #190", async (t) => { let tr = getNewTemplateRender( "./test/stubs/njk-relative/does_not_exist_and_thats_ok.njk", "./test/stubs" @@ -86,7 +86,7 @@ test("Nunjucks Render Relative Include Issue #190", async t => { t.is(await fn(), "

HELLO FROM THE OTHER SIDE.

"); }); -test("Nunjucks Render Relative Include (using ..) Issue #190", async t => { +test("Nunjucks Render Relative Include (using ..) Issue #190", async (t) => { let tr = getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs" @@ -109,7 +109,7 @@ test("Nunjucks Render Relative Include (using ..) Issue #190", async t => { // t.is(await fn3(), "

akdlsjafkljdskl

"); }); -test("Nunjucks Render Relative Include (using current dir) Issue #190", async t => { +test("Nunjucks Render Relative Include (using current dir) Issue #190", async (t) => { let tr = getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs" @@ -126,7 +126,7 @@ test("Nunjucks Render Relative Include (using current dir) Issue #190", async t // t.is(await fn(), "

akdlsjafkljdskl

"); }); -test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes and in current dir) Issue #190", async t => { +test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes and in current dir) Issue #190", async (t) => { let tr = getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "./test/stubs" @@ -146,16 +146,16 @@ test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes // t.is(await fn2(), "

HELLO FROM THE OTHER SIDE.

"); }); -test("Nunjucks Async Filter", async t => { +test("Nunjucks Async Filter", async (t) => { let tr = new TemplateRender("njk", "test/stubs"); let engine = tr.engine; engine.addFilters( { - myAsyncFilter: function(value, callback) { - setTimeout(function() { + myAsyncFilter: function (value, callback) { + setTimeout(function () { callback(null, `HI${value}`); }, 100); - } + }, }, true ); @@ -163,13 +163,13 @@ test("Nunjucks Async Filter", async t => { t.is((await fn()).trim(), "HItest"); }); -test("Nunjucks Render set with a filter", async t => { +test("Nunjucks Render set with a filter", async (t) => { let tr = new TemplateRender("njk", "test/stubs"); let engine = tr.engine; engine.addFilters({ - uppercase: function(str) { + uppercase: function (str) { return str.toUpperCase(); - } + }, }); let fn = await tr.getCompiledTemplate( `{% set test = "hi" | uppercase %}{{ test }}` @@ -177,13 +177,13 @@ test("Nunjucks Render set with a filter", async t => { t.is((await fn()).trim(), `HI`); }); -test("Nunjucks Render Include a JS file (Issue 398)", async t => { +test("Nunjucks Render Include a JS file (Issue 398)", async (t) => { let tr = getNewTemplateRender("njk", "test/stubs"); let engine = tr.engine; engine.addFilters({ - jsmin: function(str) { + jsmin: function (str) { return str; - } + }, }); let fn = await tr.getCompiledTemplate( "{% set ga %}{% include 'test.js' %}{% endset %}{{ ga | safe | jsmin }}" @@ -191,35 +191,35 @@ test("Nunjucks Render Include a JS file (Issue 398)", async t => { t.is((await fn()).trim(), `/* THIS IS A COMMENT */ alert("Issue #398");`); }); -test("Nunjucks Render Include Subfolder", async t => { +test("Nunjucks Render Include Subfolder", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "

{% include 'subfolder/included.html' %}

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

This is an include.

"); }); -test("Nunjucks Render Include Double Quotes", async t => { +test("Nunjucks Render Include Double Quotes", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( `

{% include "included.njk" %}

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

This is an include.

"); }); -test("Nunjucks Render Include Subfolder Double Quotes", async t => { +test("Nunjucks Render Include Subfolder Double Quotes", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( `

{% include "subfolder/included.html" %}

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

This is an include.

"); }); -test("Nunjucks Render Imports", async t => { +test("Nunjucks Render Imports", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "{% import 'imports.njk' as forms %}
{{ forms.label('Name') }}
" ); t.is(await fn(), "
"); }); -test("Nunjucks Render Relative Imports", async t => { +test("Nunjucks Render Relative Imports", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/njk-relative/dir/does_not_exist_and_thats_ok.njk", "test/stubs" @@ -229,19 +229,19 @@ test("Nunjucks Render Relative Imports", async t => { t.is(await fn(), "
"); }); -test("Nunjucks Render Imports From", async t => { +test("Nunjucks Render Imports From", async (t) => { let fn = await getNewTemplateRender("njk", "test/stubs").getCompiledTemplate( "{% from 'imports.njk' import label %}
{{ label('Name') }}
" ); t.is(await fn(), "
"); }); -test("Nunjucks getEngineLib", async t => { +test("Nunjucks getEngineLib", async (t) => { let tr = getNewTemplateRender("njk", "./test/stubs/"); t.truthy(tr.engine.getEngineLib()); }); -test("Nunjucks Render: with Library Override", async t => { +test("Nunjucks Render: with Library Override", async (t) => { let tr = getNewTemplateRender("njk"); let lib = require("nunjucks"); @@ -254,10 +254,10 @@ test("Nunjucks Render: with Library Override", async t => { t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Nunjucks Render with getGlobals Issue #567", async t => { +test("Nunjucks Render with getGlobals Issue #567", async (t) => { let tr = getNewTemplateRender("njk"); let env = tr.engine.getEngineLib(); - env.addGlobal("getGlobals", function() { + env.addGlobal("getGlobals", function () { return this.getVariables(); }); @@ -267,10 +267,10 @@ test("Nunjucks Render with getGlobals Issue #567", async t => { t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); -test("Nunjucks Render with getVarFromString Filter Issue #567", async t => { +test("Nunjucks Render with getVarFromString Filter Issue #567", async (t) => { let tr = getNewTemplateRender("njk"); let env = tr.engine.getEngineLib(); - env.addFilter("getVarFromString", function(varName) { + env.addFilter("getVarFromString", function (varName) { return this.getVariables()[varName]; }); @@ -280,20 +280,20 @@ test("Nunjucks Render with getVarFromString Filter Issue #567", async t => { t.is(await fn({ "my-global-name": "Zach" }), "

Zach

"); }); -test("Nunjucks Shortcode without args", async t => { +test("Nunjucks Shortcode without args", async (t) => { let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function() { + tr.engine.addShortcode("postfixWithZach", function () { return "Zach"; }); t.is(await tr._testRender("{% postfixWithZach %}", {}), "Zach"); }); -test("Nunjucks Shortcode", async t => { +test("Nunjucks Shortcode", async (t) => { t.plan(3); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str) { + tr.engine.addShortcode("postfixWithZach", function (str) { // Data in context t.is(this.page.url, "/hi/"); // sanity check that all data is not carried forward @@ -306,25 +306,25 @@ test("Nunjucks Shortcode", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testZach" ); }); -test("Nunjucks Async Shortcode", async t => { +test("Nunjucks Async Shortcode", async (t) => { t.plan(2); let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", - function(str) { + function (str) { // Data in context t.is(this.page.url, "/hi/"); - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(str + "Zach"); }); }); @@ -336,20 +336,20 @@ test("Nunjucks Async Shortcode", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testZach" ); }); -test("Nunjucks Async function Shortcode", async t => { +test("Nunjucks Async function Shortcode", async (t) => { t.plan(2); let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", - async function(str) { + async function (str) { // Data in context t.is(this.page.url, "/hi/"); @@ -362,18 +362,18 @@ test("Nunjucks Async function Shortcode", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testZach" ); }); -test("Nunjucks Async function Shortcode (with sync function, error throwing)", async t => { +test("Nunjucks Async function Shortcode (with sync function, error throwing)", async (t) => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", - function(str) { + function (str) { throw new Error( "Nunjucks Async function Shortcode (with sync function, error throwing)" ); @@ -391,11 +391,11 @@ test("Nunjucks Async function Shortcode (with sync function, error throwing)", a ); }); -test("Nunjucks Async function Shortcode (with async function, error throwing)", async t => { +test("Nunjucks Async function Shortcode (with async function, error throwing)", async (t) => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZachError", - async function(str) { + async function (str) { throw new Error( "Nunjucks Async function Shortcode (with async function, error throwing)" ); @@ -413,11 +413,11 @@ test("Nunjucks Async function Shortcode (with async function, error throwing)", ); }); -test("Nunjucks Async function paired Shortcode (with sync function, error throwing)", async t => { +test("Nunjucks Async function paired Shortcode (with sync function, error throwing)", async (t) => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode( "postfixWithZachError", - function(str) { + function (str) { throw new Error( "Nunjucks Async function paired Shortcode (with sync function, error throwing)" ); @@ -438,11 +438,11 @@ test("Nunjucks Async function paired Shortcode (with sync function, error throwi ); }); -test("Nunjucks Async function paired Shortcode (with async function, error throwing)", async t => { +test("Nunjucks Async function paired Shortcode (with async function, error throwing)", async (t) => { let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode( "postfixWithZachError", - async function(str) { + async function (str) { throw new Error( "Nunjucks Async function paired Shortcode (with async function, error throwing)" ); @@ -463,11 +463,11 @@ test("Nunjucks Async function paired Shortcode (with async function, error throw ); }); -test("Nunjucks Shortcode Safe Output", async t => { +test("Nunjucks Shortcode Safe Output", async (t) => { t.plan(2); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str) { + tr.engine.addShortcode("postfixWithZach", function (str) { // Data in context t.is(this.page.url, "/hi/"); @@ -478,18 +478,18 @@ test("Nunjucks Shortcode Safe Output", async t => { await tr._testRender("{% postfixWithZach name %}", { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "test" ); }); -test("Nunjucks Paired Shortcode", async t => { +test("Nunjucks Paired Shortcode", async (t) => { t.plan(2); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { // Data in context t.is(this.page.url, "/hi/"); @@ -502,26 +502,26 @@ test("Nunjucks Paired Shortcode", async t => { { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, } ), "testContentZach" ); }); -test("Nunjucks Async Paired Shortcode", async t => { +test("Nunjucks Async Paired Shortcode", async (t) => { t.plan(2); let tr = new TemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode( "postfixWithZach", - function(content, str) { + function (content, str) { // Data in context t.is(this.page.url, "/hi/"); - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(str + content + "Zach"); }); }); @@ -535,17 +535,17 @@ test("Nunjucks Async Paired Shortcode", async t => { { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, } ), "testContentZach" ); }); -test("Nunjucks Paired Shortcode without args", async t => { +test("Nunjucks Paired Shortcode without args", async (t) => { let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content) { + tr.engine.addPairedShortcode("postfixWithZach", function (content) { // Data in context t.is(this.page.url, "/hi/"); @@ -558,19 +558,19 @@ test("Nunjucks Paired Shortcode without args", async t => { { name: "test", page: { - url: "/hi/" - } + url: "/hi/", + }, } ), "ContentZach" ); }); -test("Nunjucks Paired Shortcode with Tag Inside", async t => { +test("Nunjucks Paired Shortcode with Tag Inside", async (t) => { t.plan(2); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { // Data in context t.is(this.page.url, "/hi/"); @@ -584,19 +584,19 @@ test("Nunjucks Paired Shortcode with Tag Inside", async t => { name: "test", tester: true, page: { - url: "/hi/" - } + url: "/hi/", + }, } ), "testContentIfZach" ); }); -test("Nunjucks Nested Paired Shortcode", async t => { +test("Nunjucks Nested Paired Shortcode", async (t) => { t.plan(3); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function(content, str) { + tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { // Data in context t.is(this.page.url, "/hi/"); @@ -610,19 +610,19 @@ test("Nunjucks Nested Paired Shortcode", async t => { name: "test", name2: "test2", page: { - url: "/hi/" - } + url: "/hi/", + }, } ), "testContenttest2ContentZachZach" ); }); -test("Nunjucks Shortcode Multiple Args", async t => { +test("Nunjucks Shortcode Multiple Args", async (t) => { t.plan(2); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str, str2) { + tr.engine.addShortcode("postfixWithZach", function (str, str2) { // Data in context t.is(this.page.url, "/hi/"); @@ -634,32 +634,32 @@ test("Nunjucks Shortcode Multiple Args", async t => { name: "test", other: "howdy", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testhowdyZach" ); }); -test("Nunjucks Shortcode Multiple Args (Comma is required)", async t => { +test("Nunjucks Shortcode Multiple Args (Comma is required)", async (t) => { let tr = new TemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(str, str2) { + tr.engine.addShortcode("postfixWithZach", function (str, str2) { return str + str2 + "Zach"; }); await t.throwsAsync(async () => { await tr._testRender("{% postfixWithZach name other %}", { name: "test", - other: "howdy" + other: "howdy", }); }); }); -test("Nunjucks Shortcode Named Args", async t => { +test("Nunjucks Shortcode Named Args", async (t) => { t.plan(2); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(arg) { + tr.engine.addShortcode("postfixWithZach", function (arg) { // Data in context t.is(this.page.url, "/hi/"); @@ -671,18 +671,18 @@ test("Nunjucks Shortcode Named Args", async t => { name: "test", other: "howdy", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testhowdyZach" ); }); -test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { +test("Nunjucks Shortcode Named Args (Reverse Order)", async (t) => { t.plan(2); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(arg) { + tr.engine.addShortcode("postfixWithZach", function (arg) { // Data in context t.is(this.page.url, "/hi/"); @@ -694,18 +694,18 @@ test("Nunjucks Shortcode Named Args (Reverse Order)", async t => { name: "test", other: "howdy", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testhowdyZach" ); }); -test("Nunjucks Shortcode Named Args (JS notation)", async t => { +test("Nunjucks Shortcode Named Args (JS notation)", async (t) => { t.plan(2); let tr = getNewTemplateRender("njk", "./test/stubs/"); - tr.engine.addShortcode("postfixWithZach", function(arg) { + tr.engine.addShortcode("postfixWithZach", function (arg) { // Data in context t.is(this.page.url, "/hi/"); @@ -717,19 +717,19 @@ test("Nunjucks Shortcode Named Args (JS notation)", async t => { name: "test", other: "howdy", page: { - url: "/hi/" - } + url: "/hi/", + }, }), "testhowdyZach" ); }); -test("Nunjucks Test if statements on arrays (Issue #524)", async t => { +test("Nunjucks Test if statements on arrays (Issue #524)", async (t) => { let tr = getNewTemplateRender("njk", "./test/stubs/"); t.is( await tr._testRender("{% if 'first' in tags %}Success.{% endif %}", { - tags: ["first", "second"] + tags: ["first", "second"], }), "Success." ); @@ -738,7 +738,7 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { await tr._testRender( "{% if 'sdfsdfs' in tags %}{% else %}Success.{% endif %}", { - tags: ["first", "second"] + tags: ["first", "second"], } ), "Success." @@ -748,7 +748,7 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { await tr._testRender( "{% if false %}{% elseif 'first' in tags %}Success.{% endif %}", { - tags: ["first", "second"] + tags: ["first", "second"], } ), "Success." @@ -756,7 +756,7 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { t.is( await tr._testRender("{% if tags.includes('first') %}Success.{% endif %}", { - tags: ["first", "second"] + tags: ["first", "second"], }), "Success." ); @@ -765,7 +765,7 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { await tr._testRender( "{% if tags.includes('dsds') %}{% else %}Success.{% endif %}", { - tags: ["first", "second"] + tags: ["first", "second"], } ), "Success." @@ -775,22 +775,22 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async t => { await tr._testRender( "{% if false %}{% elseif tags.includes('first') %}Success.{% endif %}", { - tags: ["first", "second"] + tags: ["first", "second"], } ), "Success." ); }); -test("Issue 611: Run a function", async t => { +test("Issue 611: Run a function", async (t) => { // This does not work in Liquid let tr = new TemplateRender("njk", "./test/stubs/"); t.is( await tr._testRender("{{ test() }}", { - test: function() { + test: function () { return "alkdsjfksljaZach"; - } + }, }), "alkdsjfksljaZach" ); diff --git a/test/TemplateRenderPugTest.js b/test/TemplateRenderPugTest.js index 5d83675c1..16f207cd6 100644 --- a/test/TemplateRenderPugTest.js +++ b/test/TemplateRenderPugTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -9,30 +9,30 @@ function getNewTemplateRender(name, inputDir) { } // Pug -test("Pug", t => { +test("Pug", (t) => { t.is(getNewTemplateRender("pug").getEngineName(), "pug"); }); -test("Pug Render", async t => { +test("Pug Render", async (t) => { let fn = await getNewTemplateRender("pug").getCompiledTemplate("p= name"); t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Pug Render Include (Absolute)", async t => { +test("Pug Render Include (Absolute)", async (t) => { let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`p include /included.pug`); t.is(await fn({ name: "Zach" }), "

This is an include.

"); }); -test("Pug Render Include with Data", async t => { +test("Pug Render Include with Data", async (t) => { let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`p include /includedvar.pug`); t.is(await fn({ name: "Zach" }), "

This is Zach.

"); }); -test("Pug Render Include with Data, inline var overrides data", async t => { +test("Pug Render Include with Data, inline var overrides data", async (t) => { let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(` - var name = "Bill"; @@ -41,7 +41,7 @@ p t.is(await fn({ name: "Zach" }), "

This is Bill.

"); }); -test("Pug Render Extends (Layouts)", async t => { +test("Pug Render Extends (Layouts)", async (t) => { let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`extends /layout.pug block content @@ -49,7 +49,7 @@ block content t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Pug Render Extends (Relative, Layouts)", async t => { +test("Pug Render Extends (Relative, Layouts)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.pug", "./test/stubs/" @@ -59,14 +59,14 @@ block content t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Pug Render Include (Relative)", async t => { +test("Pug Render Include (Relative)", async (t) => { let fn = await getNewTemplateRender("pug", "./test/stubs/") .getCompiledTemplate(`p include _includes/included.pug`); t.is(await fn({ name: "Zach" }), "

This is an include.

"); }); -test("Pug Render Include (Relative, again)", async t => { +test("Pug Render Include (Relative, again)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.pug", "./test/stubs/" @@ -78,7 +78,7 @@ test("Pug Render Include (Relative, again)", async t => { ); }); -test("Pug Render Include (Relative, dot slash)", async t => { +test("Pug Render Include (Relative, dot slash)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.pug", "./test/stubs/" @@ -90,7 +90,7 @@ test("Pug Render Include (Relative, dot slash)", async t => { ); }); -test("Pug Render Include (Relative, dot dot slash)", async t => { +test("Pug Render Include (Relative, dot dot slash)", async (t) => { let fn = await getNewTemplateRender( "./test/stubs/dir/does_not_exist_and_thats_ok.pug", "./test/stubs/" @@ -102,7 +102,7 @@ test("Pug Render Include (Relative, dot dot slash)", async t => { ); }); -test("Pug Options Overrides", async t => { +test("Pug Options Overrides", async (t) => { let tr = getNewTemplateRender("pug", "./test/stubs/"); tr.engine.setPugOptions({ testoption: "testoverride" }); @@ -110,12 +110,12 @@ test("Pug Options Overrides", async t => { t.is(options.testoption, "testoverride"); }); -test("Pug getEngineLib", async t => { +test("Pug getEngineLib", async (t) => { let tr = getNewTemplateRender("pug", "./test/stubs/"); t.truthy(tr.engine.getEngineLib()); }); -test("Pug Render: with Library Override", async t => { +test("Pug Render: with Library Override", async (t) => { let tr = getNewTemplateRender("pug"); let lib = require("pug"); @@ -125,14 +125,14 @@ test("Pug Render: with Library Override", async t => { t.is(await fn({ name: "Zach" }), "

Zach

"); }); -test("Pug Filter", async t => { +test("Pug Filter", async (t) => { let tr = getNewTemplateRender("pug", "./test/stubs/"); tr.engine.setPugOptions({ filters: { - makeUppercase: function(text, options) { + makeUppercase: function (text, options) { return text.toUpperCase(); - } - } + }, + }, }); let fn = await tr.getCompiledTemplate(`p @@ -142,13 +142,13 @@ test("Pug Filter", async t => { t.is(await fn({ name: "Test" }), "

ZACH

"); }); -test("Pug Render with Function", async t => { +test("Pug Render with Function", async (t) => { let fn = await getNewTemplateRender("pug").getCompiledTemplate("p= name()"); t.is( await fn({ - name: function() { + name: function () { return "Zach2"; - } + }, }), "

Zach2

" ); diff --git a/test/TemplateRenderTest.js b/test/TemplateRenderTest.js index 8b4957cf8..8447a2520 100644 --- a/test/TemplateRenderTest.js +++ b/test/TemplateRenderTest.js @@ -1,6 +1,6 @@ -import test from "ava"; -import TemplateRender from "../src/TemplateRender"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; +const test = require("ava"); +const TemplateRender = require("../src/TemplateRender"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let tr = new TemplateRender(name, inputDir); @@ -8,35 +8,35 @@ function getNewTemplateRender(name, inputDir) { return tr; } -test("Basic", t => { +test("Basic", (t) => { t.throws(() => { let tr = getNewTemplateRender("sldkjfkldsj"); tr.init("sldkjfkldsj"); }); }); -test("Includes Dir", async t => { +test("Includes Dir", async (t) => { t.is( getNewTemplateRender("ejs", "./test/stubs").getIncludesDir(), "test/stubs/_includes" ); }); -test("Invalid override", async t => { +test("Invalid override", async (t) => { let tr = getNewTemplateRender("ejs", "./test/stubs"); t.throws(() => { tr.setEngineOverride("lslkdjf"); }); }); -test("Valid Override", async t => { +test("Valid Override", async (t) => { let tr = getNewTemplateRender("ejs", "./test/stubs"); tr.setEngineOverride("njk"); t.is(tr.getEngineName(), "njk"); t.truthy(tr.isEngine("njk")); }); -test("Parse Overrides to get Prioritized Engine List", async t => { +test("Parse Overrides to get Prioritized Engine List", async (t) => { t.deepEqual(TemplateRender.parseEngineOverrides(""), []); t.deepEqual(TemplateRender.parseEngineOverrides(null), []); t.deepEqual(TemplateRender.parseEngineOverrides(undefined), []); @@ -50,14 +50,14 @@ test("Parse Overrides to get Prioritized Engine List", async t => { t.deepEqual(TemplateRender.parseEngineOverrides("ejs,html"), ["ejs"]); t.deepEqual(TemplateRender.parseEngineOverrides("ejs,md,html"), [ "md", - "ejs" + "ejs", ]); t.deepEqual(TemplateRender.parseEngineOverrides("njk,njk"), ["njk"]); - t.throws(function() { + t.throws(function () { TemplateRender.parseEngineOverrides("njk,ejs"); }); - t.throws(function() { + t.throws(function () { TemplateRender.parseEngineOverrides("ejs,njk,html"); }); }); diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index acf42c39e..a9a258dd3 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -1,8 +1,8 @@ -import test from "ava"; -import Template from "../src/Template"; -import TemplateData from "../src/TemplateData"; -import { cloneDeep } from "lodash"; -import getNewTemplate from "./_getNewTemplateForTests"; +const test = require("ava"); +const Template = require("../src/Template"); +const TemplateData = require("../src/TemplateData"); +const { cloneDeep } = require("lodash"); +const getNewTemplate = require("./_getNewTemplateForTests"); async function getRenderedData(tmpl, pageNumber = 0) { let data = await tmpl.getData(); @@ -10,7 +10,7 @@ async function getRenderedData(tmpl, pageNumber = 0) { return templates[pageNumber].data; } -test("eleventyComputed", async t => { +test("eleventyComputed", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/first.njk", "./test/stubs/", @@ -20,7 +20,7 @@ test("eleventyComputed", async t => { t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); }); -test("eleventyComputed overrides existing value.", async t => { +test("eleventyComputed overrides existing value.", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/override.njk", "./test/stubs/", @@ -31,7 +31,7 @@ test("eleventyComputed overrides existing value.", async t => { t.is((await tmpl.render(data)).trim(), "hi:override"); }); -test("eleventyComputed overrides existing value and reuses that upstream value", async t => { +test("eleventyComputed overrides existing value and reuses that upstream value", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/override-reuse.njk", "./test/stubs/", @@ -42,7 +42,7 @@ test("eleventyComputed overrides existing value and reuses that upstream value", t.is((await tmpl.render(data)).trim(), "hi:over(value1)ride"); }); -test("eleventyComputed permalink", async t => { +test("eleventyComputed permalink", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/permalink.njk", "./test/stubs/", @@ -58,7 +58,7 @@ test("eleventyComputed permalink", async t => { t.is(data.dependsOnPage, "depends:/haha-value1.html"); }); -test("eleventyComputed simple permalink", async t => { +test("eleventyComputed simple permalink", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/permalink-simple.njk", "./test/stubs/", @@ -71,7 +71,7 @@ test("eleventyComputed simple permalink", async t => { t.is(data.permalink, "haha-value1.html"); }); -test("eleventyComputed permalink using slug", async t => { +test("eleventyComputed permalink using slug", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/permalink-slug.njk", "./test/stubs/", @@ -84,7 +84,7 @@ test("eleventyComputed permalink using slug", async t => { t.is(data.permalink, "haha-this-is-a-string.html"); }); -test("eleventyComputed js front matter (function)", async t => { +test("eleventyComputed js front matter (function)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/second.njk", "./test/stubs/", @@ -95,7 +95,7 @@ test("eleventyComputed js front matter (function)", async t => { t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); }); -test("eleventyComputed js front matter key reuses and overrides", async t => { +test("eleventyComputed js front matter key reuses and overrides", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/third.njk", "./test/stubs/", @@ -106,7 +106,7 @@ test("eleventyComputed js front matter key reuses and overrides", async t => { t.is((await tmpl.render(data)).trim(), "hi:value2-value1"); }); -test("eleventyComputed true primitive", async t => { +test("eleventyComputed true primitive", async (t) => { let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/true.njk", "./test/stubs/", @@ -119,7 +119,7 @@ test("eleventyComputed true primitive", async t => { t.is(data.key4, 324); }); -test("eleventyComputed relies on global data", async t => { +test("eleventyComputed relies on global data", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/use-global-data.njk", @@ -134,7 +134,7 @@ test("eleventyComputed relies on global data", async t => { t.is(data.image, "datavalue1"); }); -test("eleventyComputed intermixes with global data", async t => { +test("eleventyComputed intermixes with global data", async (t) => { let dataObj = new TemplateData("./test/stubs-computed-global/"); let config = cloneDeep(dataObj.config); diff --git a/test/TemplateTest-JavaScript.js b/test/TemplateTest-JavaScript.js index 621b8a8fc..1fd1eb155 100644 --- a/test/TemplateTest-JavaScript.js +++ b/test/TemplateTest-JavaScript.js @@ -1,8 +1,8 @@ -import test from "ava"; -import Template from "../src/Template"; -import semver from "semver"; +const test = require("ava"); +const Template = require("../src/Template"); +const semver = require("semver"); -test("JavaScript template type (function)", async t => { +test("JavaScript template type (function)", async (t) => { let tmpl = new Template( "./test/stubs/function.11ty.js", "./test/stubs/", @@ -17,7 +17,7 @@ test("JavaScript template type (function)", async t => { t.is(pages[0].templateContent.trim(), "

Zach

"); }); -test("JavaScript template type (class with data getter)", async t => { +test("JavaScript template type (class with data getter)", async (t) => { let tmpl = new Template( "./test/stubs/class-data.11ty.js", "./test/stubs/", @@ -31,7 +31,7 @@ test("JavaScript template type (class with data getter)", async t => { t.is(pages[0].templateContent.trim(), "

Ted

"); }); -test("JavaScript template type (class with data method)", async t => { +test("JavaScript template type (class with data method)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-fn.11ty.js", "./test/stubs/", @@ -46,7 +46,7 @@ test("JavaScript template type (class with data method)", async t => { }); if (semver.gte(process.version, "12.4.0")) { - test("JavaScript template type (class fields)", async t => { + test("JavaScript template type (class fields)", async (t) => { let tmpl = new Template( "./test/stubs/classfields-data.11ty.js", "./test/stubs/", @@ -61,7 +61,7 @@ if (semver.gte(process.version, "12.4.0")) { }); } -test("JavaScript template type (class with shorthand data method)", async t => { +test("JavaScript template type (class with shorthand data method)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-fn-shorthand.11ty.js", "./test/stubs/", @@ -75,7 +75,7 @@ test("JavaScript template type (class with shorthand data method)", async t => { t.is(pages[0].templateContent.trim(), "

Ted

"); }); -test("JavaScript template type (class with async data method)", async t => { +test("JavaScript template type (class with async data method)", async (t) => { let tmpl = new Template( "./test/stubs/class-async-data-fn.11ty.js", "./test/stubs/", @@ -89,7 +89,7 @@ test("JavaScript template type (class with async data method)", async t => { t.is(pages[0].templateContent.trim(), "

Ted

"); }); -test("JavaScript template type (class with data getter and a javascriptFunction)", async t => { +test("JavaScript template type (class with data getter and a javascriptFunction)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-filter.11ty.js", "./test/stubs/", @@ -97,10 +97,10 @@ test("JavaScript template type (class with data getter and a javascriptFunction) ); tmpl.templateRender.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { return new String(val).toUpperCase(); - } - } + }, + }, }; t.is(await tmpl.getOutputPath(), "./dist/class-data-filter/index.html"); @@ -109,7 +109,7 @@ test("JavaScript template type (class with data getter and a javascriptFunction) t.is(pages[0].templateContent.trim(), "

TED

"); }); -test("JavaScript template type (class with data method and a javascriptFunction)", async t => { +test("JavaScript template type (class with data method and a javascriptFunction)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-fn-filter.11ty.js", "./test/stubs/", @@ -117,10 +117,10 @@ test("JavaScript template type (class with data method and a javascriptFunction) ); tmpl.templateRender.config = { javascriptFunctions: { - upper: function(val) { + upper: function (val) { return new String(val).toUpperCase(); - } - } + }, + }, }; t.is(await tmpl.getOutputPath(), "./dist/class-data-fn-filter/index.html"); @@ -129,7 +129,7 @@ test("JavaScript template type (class with data method and a javascriptFunction) t.is(pages[0].templateContent.trim(), "

TED

"); }); -test("JavaScript template type (class with data permalink)", async t => { +test("JavaScript template type (class with data permalink)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-permalink.11ty.js", "./test/stubs/", @@ -139,7 +139,7 @@ test("JavaScript template type (class with data permalink)", async t => { t.is(await tmpl.getOutputPath(), "./dist/my-permalink/index.html"); }); -test("JavaScript template type (class with data permalink using a buffer)", async t => { +test("JavaScript template type (class with data permalink using a buffer)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-permalink-buffer.11ty.js", "./test/stubs/", @@ -149,7 +149,7 @@ test("JavaScript template type (class with data permalink using a buffer)", asyn t.is(await tmpl.getOutputPath(), "./dist/my-permalink/index.html"); }); -test("JavaScript template type (class with data permalink function)", async t => { +test("JavaScript template type (class with data permalink function)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-permalink-fn.11ty.js", "./test/stubs/", @@ -159,7 +159,7 @@ test("JavaScript template type (class with data permalink function)", async t => t.is(await tmpl.getOutputPath(), "./dist/my-permalink/value1/index.html"); }); -test("JavaScript template type (class with data permalink function using a buffer)", async t => { +test("JavaScript template type (class with data permalink function using a buffer)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-permalink-fn-buffer.11ty.js", "./test/stubs/", @@ -169,7 +169,7 @@ test("JavaScript template type (class with data permalink function using a buffe t.is(await tmpl.getOutputPath(), "./dist/my-permalink/value1/index.html"); }); -test("JavaScript template type (class with data permalink async function)", async t => { +test("JavaScript template type (class with data permalink async function)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-permalink-async-fn.11ty.js", "./test/stubs/", @@ -179,7 +179,7 @@ test("JavaScript template type (class with data permalink async function)", asyn t.is(await tmpl.getOutputPath(), "./dist/my-permalink/value1/index.html"); }); -test("JavaScript template type (class with data permalink function using a filter)", async t => { +test("JavaScript template type (class with data permalink function using a filter)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-permalink-fn-filter.11ty.js", "./test/stubs/", @@ -192,7 +192,7 @@ test("JavaScript template type (class with data permalink function using a filte ); }); -test("JavaScript template type (class with renderData)", async t => { +test("JavaScript template type (class with renderData)", async (t) => { let tmpl = new Template( "./test/stubs/class-data-renderdata.11ty.js", "./test/stubs/", @@ -207,7 +207,7 @@ test("JavaScript template type (class with renderData)", async t => { ); }); -test("JavaScript template type (should use the same class instance for data and render)", async t => { +test("JavaScript template type (should use the same class instance for data and render)", async (t) => { let tmpl = new Template( "./test/stubs/oneinstance.11ty.js", "./test/stubs/", @@ -222,7 +222,7 @@ test("JavaScript template type (should use the same class instance for data and t.is(pages[0].templateContent.trim(), `

Ted${data.rand}

`); }); -test("JavaScript template type (multiple exports)", async t => { +test("JavaScript template type (multiple exports)", async (t) => { let tmpl = new Template( "./test/stubs/multipleexports.11ty.js", "./test/stubs/", @@ -234,7 +234,7 @@ test("JavaScript template type (multiple exports)", async t => { t.is(pages[0].templateContent.trim(), "

Ted

"); }); -test("JavaScript template type (multiple exports, promises)", async t => { +test("JavaScript template type (multiple exports, promises)", async (t) => { let tmpl = new Template( "./test/stubs/multipleexports-promises.11ty.js", "./test/stubs/", @@ -248,7 +248,7 @@ test("JavaScript template type (multiple exports, promises)", async t => { t.is(pages[0].templateContent.trim(), "

Ted

"); }); -test("JavaScript template type (object)", async t => { +test("JavaScript template type (object)", async (t) => { let tmpl = new Template( "./test/stubs/object.11ty.js", "./test/stubs/", @@ -262,7 +262,7 @@ test("JavaScript template type (object)", async t => { t.is(pages[0].templateContent.trim(), "

Ted

"); }); -test("JavaScript template type (object, no render method)", async t => { +test("JavaScript template type (object, no render method)", async (t) => { let tmpl = new Template( "./test/stubs/object-norender.11ty.js", "./test/stubs/", @@ -276,7 +276,7 @@ test("JavaScript template type (object, no render method)", async t => { t.is(pages[0].templateContent.trim(), ""); }); -test("JavaScript template type (class, no render method)", async t => { +test("JavaScript template type (class, no render method)", async (t) => { let tmpl = new Template( "./test/stubs/class-norender.11ty.js", "./test/stubs/", @@ -289,7 +289,7 @@ test("JavaScript template type (class, no render method)", async t => { let pages = await tmpl.getRenderedTemplates(data); t.is(pages[0].templateContent.trim(), ""); }); -test("JavaScript template type (data returns a string)", async t => { +test("JavaScript template type (data returns a string)", async (t) => { let tmpl = new Template( "./test/stubs/exports-flatdata.11ty.js", "./test/stubs/", diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 548c21b19..f76b7e5f7 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1,17 +1,17 @@ -import test from "ava"; -import fs from "fs-extra"; -import pretty from "pretty"; -import Template from "../src/Template"; -import TemplateData from "../src/TemplateData"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; -import EleventyErrorUtil from "../src/EleventyErrorUtil"; -import TemplateContentPrematureUseError from "../src/Errors/TemplateContentPrematureUseError"; -import normalizeNewLines from "./Util/normalizeNewLines"; - -import templateConfig from "../src/Config"; +const test = require("ava"); +const fs = require("fs-extra"); +const pretty = require("pretty"); +const Template = require("../src/Template"); +const TemplateData = require("../src/TemplateData"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const EleventyErrorUtil = require("../src/EleventyErrorUtil"); +const TemplateContentPrematureUseError = require("../src/Errors/TemplateContentPrematureUseError"); +const normalizeNewLines = require("./Util/normalizeNewLines"); + +const templateConfig = require("../src/Config"); const config = templateConfig.getConfig(); -import getNewTemplate from "./_getNewTemplateForTests"; +const getNewTemplate = require("./_getNewTemplateForTests"); async function getRenderedData(tmpl, pageNumber = 0) { let data = await tmpl.getData(); @@ -23,7 +23,7 @@ function cleanHtml(str) { return pretty(str, { ocd: true }); } -test("getTemplateSubFolder", t => { +test("getTemplateSubFolder", (t) => { let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", @@ -32,7 +32,7 @@ test("getTemplateSubFolder", t => { t.is(tmpl.getTemplateSubfolder(), ""); }); -test("getTemplateSubFolder, output is a subdir of input", t => { +test("getTemplateSubFolder, output is a subdir of input", (t) => { let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", @@ -41,7 +41,7 @@ test("getTemplateSubFolder, output is a subdir of input", t => { t.is(tmpl.getTemplateSubfolder(), ""); }); -test("output path maps to an html file", async t => { +test("output path maps to an html file", async (t) => { let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", @@ -54,7 +54,7 @@ test("output path maps to an html file", async t => { t.is(await tmpl.getOutputPath(), "./dist/template/index.html"); }); -test("subfolder outputs to a subfolder", async t => { +test("subfolder outputs to a subfolder", async (t) => { let tmpl = getNewTemplate( "./test/stubs/subfolder/subfolder.ejs", "./test/stubs/", @@ -65,7 +65,7 @@ test("subfolder outputs to a subfolder", async t => { t.is(await tmpl.getOutputPath(), "./dist/subfolder/index.html"); }); -test("subfolder outputs to double subfolder", async t => { +test("subfolder outputs to double subfolder", async (t) => { let tmpl = getNewTemplate( "./test/stubs/subfolder/subfolder/subfolder.ejs", "./test/stubs/", @@ -76,7 +76,7 @@ test("subfolder outputs to double subfolder", async t => { t.is(await tmpl.getOutputPath(), "./dist/subfolder/subfolder/index.html"); }); -test("HTML files output to the same as the input directory have a file suffix added (only if index, this is not index).", async t => { +test("HTML files output to the same as the input directory have a file suffix added (only if index, this is not index).", async (t) => { let tmpl = getNewTemplate( "./test/stubs/testing.html", "./test/stubs", @@ -85,7 +85,7 @@ test("HTML files output to the same as the input directory have a file suffix ad t.is(await tmpl.getOutputPath(), "./test/stubs/testing/index.html"); }); -test("HTML files output to the same as the input directory have a file suffix added (only if index, this _is_ index).", async t => { +test("HTML files output to the same as the input directory have a file suffix added (only if index, this _is_ index).", async (t) => { let tmpl = getNewTemplate( "./test/stubs/index.html", "./test/stubs", @@ -94,7 +94,7 @@ test("HTML files output to the same as the input directory have a file suffix ad t.is(await tmpl.getOutputPath(), "./test/stubs/index-o.html"); }); -test("HTML files output to the same as the input directory have a file suffix added (only if index, this _is_ index, subfolder).", async t => { +test("HTML files output to the same as the input directory have a file suffix added (only if index, this _is_ index, subfolder).", async (t) => { let tmpl = getNewTemplate( "./test/stubs/subfolder/index.html", "./test/stubs", @@ -103,7 +103,7 @@ test("HTML files output to the same as the input directory have a file suffix ad t.is(await tmpl.getOutputPath(), "./test/stubs/subfolder/index-o.html"); }); -test("Test raw front matter from template (yaml)", async t => { +test("Test raw front matter from template (yaml)", async (t) => { // https://github.com/jonschlinkert/gray-matter/blob/master/examples/yaml.js let tmpl = getNewTemplate( "./test/stubs/templateFrontMatter.ejs", @@ -123,7 +123,7 @@ test("Test raw front matter from template (yaml)", async t => { t.is(pages[0].templateContent.trim(), "c:value1:value2:value3"); }); -test("Test raw front matter from template (json)", async t => { +test("Test raw front matter from template (json)", async (t) => { // https://github.com/jonschlinkert/gray-matter/blob/master/examples/json.js let tmpl = getNewTemplate( "./test/stubs/templateFrontMatterJson.ejs", @@ -142,7 +142,7 @@ test("Test raw front matter from template (json)", async t => { t.is(pages[0].templateContent.trim(), "c:value1:value2:value3"); }); -test("Test raw front matter from template (js)", async t => { +test("Test raw front matter from template (js)", async (t) => { // https://github.com/jonschlinkert/gray-matter/blob/master/examples/javascript.js let tmpl = getNewTemplate( "./test/stubs/templateFrontMatterJs.ejs", @@ -161,7 +161,7 @@ test("Test raw front matter from template (js)", async t => { t.is(pages[0].templateContent.trim(), "c:value1:VALUE2:value3"); }); -test("Test that getData() works", async t => { +test("Test that getData() works", async (t) => { let tmpl = getNewTemplate( "./test/stubs/templateFrontMatter.ejs", "./test/stubs/", @@ -173,7 +173,7 @@ test("Test that getData() works", async t => { t.is(data.key3, "value3"); }); -test("One Layout (using new content var)", async t => { +test("One Layout (using new content var)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/templateWithLayout.ejs", @@ -198,7 +198,7 @@ test("One Layout (using new content var)", async t => { t.is(data.keylayout, "valuelayout"); }); -test("One Layout (using layoutContent)", async t => { +test("One Layout (using layoutContent)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutContent.ejs", @@ -226,7 +226,7 @@ test("One Layout (using layoutContent)", async t => { t.is(data.keylayout, "valuelayout"); }); -test("One Layout (layouts disabled)", async t => { +test("One Layout (layouts disabled)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutContent.ejs", @@ -251,7 +251,7 @@ test("One Layout (layouts disabled)", async t => { t.is(data.keylayout, "valuelayout"); }); -test("One Layout (_layoutContent deprecated but supported)", async t => { +test("One Layout (_layoutContent deprecated but supported)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutBackCompat.ejs", @@ -279,7 +279,7 @@ test("One Layout (_layoutContent deprecated but supported)", async t => { t.is(data.keylayout, "valuelayout"); }); -test("One Layout (liquid test)", async t => { +test("One Layout (liquid test)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/templateWithLayout.liquid", @@ -307,7 +307,7 @@ test("One Layout (liquid test)", async t => { t.is(data.keylayout, "valuelayout"); }); -test("Two Layouts", async t => { +test("Two Layouts", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/templateTwoLayouts.ejs", @@ -334,7 +334,7 @@ test("Two Layouts", async t => { t.is(data.daysPosted, 152); }); -test("Liquid template", async t => { +test("Liquid template", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/formatTest.liquid", @@ -346,7 +346,7 @@ test("Liquid template", async t => { t.is(await tmpl.render(await tmpl.getData()), `

Zach

`); }); -test("Liquid template with include", async t => { +test("Liquid template with include", async (t) => { let tmpl = getNewTemplate( "./test/stubs/includer.liquid", "./test/stubs/", @@ -359,7 +359,7 @@ test("Liquid template with include", async t => { ); }); -test("ES6 Template Literal (No Backticks)", async t => { +test("ES6 Template Literal (No Backticks)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/formatTest.jstl", @@ -371,7 +371,7 @@ test("ES6 Template Literal (No Backticks)", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), `

ZACH

`); }); -test("ES6 Template Literal (with Backticks)", async t => { +test("ES6 Template Literal (with Backticks)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/formatTestBackticks.jstl", @@ -383,7 +383,7 @@ test("ES6 Template Literal (with Backticks)", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), `

ZACH

`); }); -test("Permalink output directory", async t => { +test("Permalink output directory", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalinked.ejs", "./test/stubs/", @@ -392,7 +392,7 @@ test("Permalink output directory", async t => { t.is(await tmpl.getOutputPath(), "./dist/permalinksubfolder/index.html"); }); -test("Permalink output directory from layout", async t => { +test("Permalink output directory from layout", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-in-layout.ejs", "./test/stubs/", @@ -401,7 +401,7 @@ test("Permalink output directory from layout", async t => { t.is(await tmpl.getOutputPath(), "./dist/hello/index.html"); }); -test("Permalink output directory from layout (fileslug)", async t => { +test("Permalink output directory from layout (fileslug)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-in-layout-fileslug.ejs", "./test/stubs/", @@ -413,7 +413,7 @@ test("Permalink output directory from layout (fileslug)", async t => { ); }); -test("Layout from template-data-file that has a permalink (fileslug) Issue #121", async t => { +test("Layout from template-data-file that has a permalink (fileslug) Issue #121", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/permalink-data-layout/test.njk", @@ -428,7 +428,7 @@ test("Layout from template-data-file that has a permalink (fileslug) Issue #121" t.is(await tmpl.getOutputPath(), "./dist/test/index.html"); }); -test("Fileslug in an 11ty.js template Issue #588", async t => { +test("Fileslug in an 11ty.js template Issue #588", async (t) => { let tmpl = getNewTemplate( "./test/stubs/fileslug.11ty.js", "./test/stubs/", @@ -440,7 +440,7 @@ test("Fileslug in an 11ty.js template Issue #588", async t => { t.is(renderedTmpl.templateContent, "

fileslug

"); }); -test("Local template data file import (without a global data json)", async t => { +test("Local template data file import (without a global data json)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -460,13 +460,13 @@ test("Local template data file import (without a global data json)", async t => "./test/stubs/component/component.json", "./test/stubs/component/component.11tydata.json", "./test/stubs/component/component.11tydata.cjs", - "./test/stubs/component/component.11tydata.js" + "./test/stubs/component/component.11tydata.js", ]); t.is(data.localdatakey1, "localdatavalue1"); t.is(await tmpl.render(data), "localdatavalue1"); }); -test("Local template data file import (two subdirectories deep)", async t => { +test("Local template data file import (two subdirectories deep)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -493,11 +493,11 @@ test("Local template data file import (two subdirectories deep)", async t => { "./test/stubs/firstdir/seconddir/component.json", "./test/stubs/firstdir/seconddir/component.11tydata.json", "./test/stubs/firstdir/seconddir/component.11tydata.cjs", - "./test/stubs/firstdir/seconddir/component.11tydata.js" + "./test/stubs/firstdir/seconddir/component.11tydata.js", ]); }); -test("Posts inherits local JSON, layouts", async t => { +test("Posts inherits local JSON, layouts", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -521,7 +521,7 @@ test("Posts inherits local JSON, layouts", async t => { "./test/stubs/posts/post1.json", "./test/stubs/posts/post1.11tydata.json", "./test/stubs/posts/post1.11tydata.cjs", - "./test/stubs/posts/post1.11tydata.js" + "./test/stubs/posts/post1.11tydata.js", ]); let localData = await dataObj.getLocalData(tmpl.getInputPath()); @@ -538,7 +538,7 @@ test("Posts inherits local JSON, layouts", async t => { ); }); -test("Template and folder name are the same, make sure data imports work ok", async t => { +test("Template and folder name are the same, make sure data imports work ok", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -558,7 +558,7 @@ test("Template and folder name are the same, make sure data imports work ok", as "./test/stubs/posts/posts.json", "./test/stubs/posts/posts.11tydata.json", "./test/stubs/posts/posts.11tydata.cjs", - "./test/stubs/posts/posts.11tydata.js" + "./test/stubs/posts/posts.11tydata.js", ]); let localData = await dataObj.getLocalData(tmpl.getInputPath()); @@ -575,7 +575,7 @@ test("Template and folder name are the same, make sure data imports work ok", as ); }); -test("Clone the template", async t => { +test("Clone the template", async (t) => { let tmpl = getNewTemplate( "./test/stubs/default.ejs", "./test/stubs/", @@ -589,7 +589,7 @@ test("Clone the template", async t => { t.is(cloned.extensionMap, tmpl.extensionMap); }); -test("Permalink with variables!", async t => { +test("Permalink with variables!", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalinkdata.njk", "./test/stubs/", @@ -599,7 +599,7 @@ test("Permalink with variables!", async t => { t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-candidate/index.html"); }); -test("Permalink with variables and JS front matter!", async t => { +test("Permalink with variables and JS front matter!", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalinkdata-jsfn.njk", "./test/stubs/", @@ -610,7 +610,7 @@ test("Permalink with variables and JS front matter!", async t => { }); // This is broken right now, permalink must use the same template language as the template -test.skip("Use a JavaScript function for permalink in any template language", async t => { +test.skip("Use a JavaScript function for permalink in any template language", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalinkdata-jspermalinkfn.njk", "./test/stubs/", @@ -620,7 +620,7 @@ test.skip("Use a JavaScript function for permalink in any template language", as t.is(await tmpl.getOutputPath(), "./dist/subdir/slug/index.html"); }); -test("Permalink with dates!", async t => { +test("Permalink with dates!", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalinkdate.liquid", "./test/stubs/", @@ -630,7 +630,7 @@ test("Permalink with dates!", async t => { t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); }); -test("Permalink with dates on file name regex!", async t => { +test("Permalink with dates on file name regex!", async (t) => { let tmpl = getNewTemplate( "./test/stubs/2016-02-01-permalinkdate.liquid", "./test/stubs/", @@ -640,7 +640,7 @@ test("Permalink with dates on file name regex!", async t => { t.is(await tmpl.getOutputPath(), "./dist/2016/02/01/index.html"); }); -test("Reuse permalink in directory specific data file", async t => { +test("Reuse permalink in directory specific data file", async (t) => { let dataObj = new TemplateData("./test/stubs/"); let tmpl = getNewTemplate( "./test/stubs/reuse-permalink/test1.liquid", @@ -652,7 +652,7 @@ test("Reuse permalink in directory specific data file", async t => { t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); }); -test("mapDataAsRenderedTemplates", async t => { +test("mapDataAsRenderedTemplates", async (t) => { let tmpl = getNewTemplate( "./test/stubs/default.ejs", "./test/stubs/", @@ -664,14 +664,14 @@ test("mapDataAsRenderedTemplates", async t => { { key1: "value1", key2: "value2", - key3: "value3" + key3: "value3", }, { parsedKey: "parsedValue" } ), { key1: "value1", key2: "value2", - key3: "value3" + key3: "value3", } ); @@ -679,13 +679,13 @@ test("mapDataAsRenderedTemplates", async t => { await tmpl.mapDataAsRenderedTemplates( { key1: "value1", - key2: "<%= parsedKey %>" + key2: "<%= parsedKey %>", }, { parsedKey: "parsedValue" } ), { key1: "value1", - key2: "parsedValue" + key2: "parsedValue", } ); @@ -693,18 +693,18 @@ test("mapDataAsRenderedTemplates", async t => { await tmpl.mapDataAsRenderedTemplates( { key1: "value1", - key2: ["<%= parsedKey %>", 2] + key2: ["<%= parsedKey %>", 2], }, { parsedKey: "parsedValue" } ), { key1: "value1", - key2: ["parsedValue", 2] + key2: ["parsedValue", 2], } ); }); -test("renderData", async t => { +test("renderData", async (t) => { let tmpl = getNewTemplate( "./test/stubs/renderData/renderData.njk", "./test/stubs/", @@ -714,7 +714,7 @@ test("renderData", async t => { t.is((await tmpl.render(data)).trim(), "hi:value2-value1.css"); }); -test("renderData markdown (issue #40)", async t => { +test("renderData markdown (issue #40)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/renderData/renderData.md", "./test/stubs/", @@ -724,7 +724,7 @@ test("renderData markdown (issue #40)", async t => { t.is((await tmpl.render(data)).trim(), "value2-value1.css"); }); -test("getMappedDate (empty, assume created)", async t => { +test("getMappedDate (empty, assume created)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dates/file1.md", "./test/stubs/", @@ -737,7 +737,7 @@ test("getMappedDate (empty, assume created)", async t => { t.truthy(date.getTime()); }); -test("getMappedDate (explicit date, yaml String)", async t => { +test("getMappedDate (explicit date, yaml String)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dates/file2.md", "./test/stubs/", @@ -750,7 +750,7 @@ test("getMappedDate (explicit date, yaml String)", async t => { t.truthy(date.getTime()); }); -test("getMappedDate (explicit date, yaml Date)", async t => { +test("getMappedDate (explicit date, yaml Date)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dates/file2b.md", "./test/stubs/", @@ -763,7 +763,7 @@ test("getMappedDate (explicit date, yaml Date)", async t => { t.truthy(date.getTime()); }); -test("getMappedDate (explicit date, yaml Date and string should be the same)", async t => { +test("getMappedDate (explicit date, yaml Date and string should be the same)", async (t) => { let tmplA = getNewTemplate( "./test/stubs/dates/file2.md", "./test/stubs/", @@ -785,7 +785,7 @@ test("getMappedDate (explicit date, yaml Date and string should be the same)", a t.deepEqual(stringDate, yamlDate); }); -test("getMappedDate (modified date)", async t => { +test("getMappedDate (modified date)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dates/file3.md", "./test/stubs/", @@ -798,7 +798,7 @@ test("getMappedDate (modified date)", async t => { t.truthy(date.getTime()); }); -test("getMappedDate (created date)", async t => { +test("getMappedDate (created date)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dates/file4.md", "./test/stubs/", @@ -811,7 +811,7 @@ test("getMappedDate (created date)", async t => { t.truthy(date.getTime()); }); -test("getMappedDate (falls back to filename date)", async t => { +test("getMappedDate (falls back to filename date)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dates/2018-01-01-file5.md", "./test/stubs/", @@ -824,7 +824,7 @@ test("getMappedDate (falls back to filename date)", async t => { t.truthy(date.getTime()); }); -test("getRenderedData() has all the page variables", async t => { +test("getRenderedData() has all the page variables", async (t) => { let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", @@ -841,7 +841,7 @@ test("getRenderedData() has all the page variables", async t => { t.is(data.page.outputPath, "./dist/template/index.html"); }); -test("Issue #603: page.date Liquid", async t => { +test("Issue #603: page.date Liquid", async (t) => { let tmpl = getNewTemplate( "./test/stubs/pagedate.liquid", "./test/stubs/", @@ -856,7 +856,7 @@ test("Issue #603: page.date Liquid", async t => { t.is(pages[0].templateContent.trim(), data.page.date.toString()); }); -test("Issue #603: page.date Nunjucks", async t => { +test("Issue #603: page.date Nunjucks", async (t) => { let tmpl = getNewTemplate( "./test/stubs/pagedate.njk", "./test/stubs/", @@ -871,7 +871,7 @@ test("Issue #603: page.date Nunjucks", async t => { t.is(pages[0].templateContent.trim(), data.page.date.toString()); }); -test("Issue #603: page.date.toUTCString() Nunjucks", async t => { +test("Issue #603: page.date.toUTCString() Nunjucks", async (t) => { // Note this is not supported in Liquid let tmpl = getNewTemplate( "./test/stubs/pagedateutc.njk", @@ -887,7 +887,7 @@ test("Issue #603: page.date.toUTCString() Nunjucks", async t => { t.is(pages[0].templateContent.trim(), data.page.date.toUTCString()); }); -test("getTemplates() data has all the root variables", async t => { +test("getTemplates() data has all the root variables", async (t) => { let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", @@ -904,7 +904,7 @@ test("getTemplates() data has all the root variables", async t => { t.is(templates[0].outputPath, "./dist/template/index.html"); }); -test("getTemplates() data has all the page variables", async t => { +test("getTemplates() data has all the page variables", async (t) => { let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", @@ -921,7 +921,7 @@ test("getTemplates() data has all the page variables", async t => { t.is(templates[0].data.page.outputPath, "./dist/template/index.html"); }); -test("getRenderedTemplates() data has all the page variables", async t => { +test("getRenderedTemplates() data has all the page variables", async (t) => { let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", @@ -938,7 +938,7 @@ test("getRenderedTemplates() data has all the page variables", async t => { t.is(templates[0].data.page.outputPath, "./dist/template/index.html"); }); -test("getRenderedData() has good slug (empty, index)", async t => { +test("getRenderedData() has good slug (empty, index)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/index.ejs", "./test/stubs/", @@ -949,7 +949,7 @@ test("getRenderedData() has good slug (empty, index)", async t => { t.is(data.page.filePathStem, "/index"); }); -test("getRenderedData() has good slug", async t => { +test("getRenderedData() has good slug", async (t) => { let tmpl = getNewTemplate( "./test/stubs/includer.liquid", "./test/stubs/", @@ -960,7 +960,7 @@ test("getRenderedData() has good slug", async t => { t.is(data.page.filePathStem, "/includer"); }); -test("Override base templating engine from .liquid to ejs", async t => { +test("Override base templating engine from .liquid to ejs", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-ejs.liquid", "./test/stubs/", @@ -970,7 +970,7 @@ test("Override base templating engine from .liquid to ejs", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "My Title"); }); -test("Override base templating engine from markdown to 11ty.js, then markdown", async t => { +test("Override base templating engine from markdown to 11ty.js, then markdown", async (t) => { let tmpl = getNewTemplate( "./test/stubs/test-override-js-markdown.11ty.js", "./test/stubs/", @@ -983,7 +983,7 @@ test("Override base templating engine from markdown to 11ty.js, then markdown", ); }); -test("Override base templating engine from .liquid to md", async t => { +test("Override base templating engine from .liquid to md", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-md.liquid", "./test/stubs/", @@ -993,7 +993,7 @@ test("Override base templating engine from .liquid to md", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); -test("Override base templating engine from .liquid to ejs,md", async t => { +test("Override base templating engine from .liquid to ejs,md", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-multiple.md", "./test/stubs/", @@ -1003,7 +1003,7 @@ test("Override base templating engine from .liquid to ejs,md", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); -test("Override base templating engine from .njk to ejs,md", async t => { +test("Override base templating engine from .njk to ejs,md", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-multiple2.njk", "./test/stubs/", @@ -1013,7 +1013,7 @@ test("Override base templating engine from .njk to ejs,md", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); -test("Override base templating engine from .html to ejs", async t => { +test("Override base templating engine from .html to ejs", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test.html", "./test/stubs/", @@ -1023,7 +1023,7 @@ test("Override base templating engine from .html to ejs", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "

My Title

"); }); -test("Override base templating engine from .html to (nothing)", async t => { +test("Override base templating engine from .html to (nothing)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-empty.html", "./test/stubs/", @@ -1036,7 +1036,7 @@ test("Override base templating engine from .html to (nothing)", async t => { ); }); -test("Override base templating engine should error with bad string", async t => { +test("Override base templating engine should error with bad string", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-error.njk", "./test/stubs/", @@ -1048,7 +1048,7 @@ test("Override base templating engine should error with bad string", async t => }); }); -test("Override base templating engine (bypasses markdown)", async t => { +test("Override base templating engine (bypasses markdown)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-bypass.md", "./test/stubs/", @@ -1058,7 +1058,7 @@ test("Override base templating engine (bypasses markdown)", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "# My Title"); }); -test("Override base templating engine to (nothing)", async t => { +test("Override base templating engine to (nothing)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test-empty.md", "./test/stubs/", @@ -1069,7 +1069,7 @@ test("Override base templating engine to (nothing)", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "# <%= title %>"); }); -test("Override base templating engine from .ejs to njk", async t => { +test("Override base templating engine from .ejs to njk", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test.ejs", "./test/stubs/", @@ -1079,7 +1079,7 @@ test("Override base templating engine from .ejs to njk", async t => { t.is((await tmpl.render(await tmpl.getData())).trim(), "My Title"); }); -test("Override base templating engine from .njk to ejs (with a layout that uses njk)", async t => { +test("Override base templating engine from .njk to ejs (with a layout that uses njk)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/layout.njk", "./test/stubs/", @@ -1092,7 +1092,7 @@ test("Override base templating engine from .njk to ejs (with a layout that uses ); }); -test("Override base templating engine from .njk to nothing (with a layout that uses njk)", async t => { +test("Override base templating engine from .njk to nothing (with a layout that uses njk)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/layoutfalse.njk", "./test/stubs/", @@ -1105,7 +1105,7 @@ test("Override base templating engine from .njk to nothing (with a layout that u ); }); -test("Using a markdown source file (with a layout that uses njk), markdown shouldn’t render in layout file", async t => { +test("Using a markdown source file (with a layout that uses njk), markdown shouldn’t render in layout file", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test.md", "./test/stubs/", @@ -1121,7 +1121,7 @@ test("Using a markdown source file (with a layout that uses njk), markdown shoul ); }); -test("Override base templating engine from .md to ejs,md (with a layout that uses njk), markdown shouldn’t render in layout file", async t => { +test("Override base templating engine from .md to ejs,md (with a layout that uses njk), markdown shouldn’t render in layout file", async (t) => { let tmpl = getNewTemplate( "./test/stubs/overrides/test2.md", "./test/stubs/", @@ -1137,7 +1137,7 @@ test("Override base templating engine from .md to ejs,md (with a layout that use ); }); -test("renderContent on a markdown file, permalink should not render markdown", async t => { +test("renderContent on a markdown file, permalink should not render markdown", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-markdown.md", "./test/stubs/", @@ -1152,7 +1152,7 @@ test("renderContent on a markdown file, permalink should not render markdown", a t.is(await tmpl.getOutputLink(), "/news/my-test-file/index.html"); }); -test("renderContent on a markdown file, permalink should not render markdown (with variable)", async t => { +test("renderContent on a markdown file, permalink should not render markdown (with variable)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-markdown-var.md", "./test/stubs/", @@ -1171,7 +1171,7 @@ test("renderContent on a markdown file, permalink should not render markdown (wi t.is(await tmpl.getOutputLink(), "/news/my-title/index.html"); }); -test("renderContent on a markdown file, permalink should not render markdown (has override)", async t => { +test("renderContent on a markdown file, permalink should not render markdown (has override)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-markdown-override.md", "./test/stubs/", @@ -1187,7 +1187,7 @@ test("renderContent on a markdown file, permalink should not render markdown (ha }); /* Transforms */ -test("Test a transform", async t => { +test("Test a transform", async (t) => { t.plan(2); let tmpl = getNewTemplate( @@ -1196,7 +1196,7 @@ test("Test a transform", async t => { "./test/stubs/_site" ); - tmpl.addTransform(function(content, outputPath) { + tmpl.addTransform(function (content, outputPath) { t.true(outputPath.endsWith(".html")); return "OVERRIDE BY A TRANSFORM"; }); @@ -1206,7 +1206,7 @@ test("Test a transform", async t => { }); // #789: https://github.com/11ty/eleventy/issues/789 -test.skip("Test a transform (does it have inputPath?)", async t => { +test.skip("Test a transform (does it have inputPath?)", async (t) => { t.plan(3); let tmpl = getNewTemplate( @@ -1215,7 +1215,7 @@ test.skip("Test a transform (does it have inputPath?)", async t => { "./test/stubs/_site" ); - tmpl.addTransform(function(content, outputPath, inputPath) { + tmpl.addTransform(function (content, outputPath, inputPath) { t.true(outputPath.endsWith(".html")); t.true(!!inputPath); return "OVERRIDE BY A TRANSFORM"; @@ -1225,7 +1225,7 @@ test.skip("Test a transform (does it have inputPath?)", async t => { t.is(renders[0], "OVERRIDE BY A TRANSFORM"); }); -test("Test a transform with pages", async t => { +test("Test a transform with pages", async (t) => { t.plan(5); let tmpl = getNewTemplate( @@ -1234,7 +1234,7 @@ test("Test a transform with pages", async t => { "./test/stubs/_site" ); - tmpl.addTransform(function(content, outputPath) { + tmpl.addTransform(function (content, outputPath) { // should run twice, one for each page t.true(content.length > 0); t.true(outputPath.endsWith(".html")); @@ -1245,7 +1245,7 @@ test("Test a transform with pages", async t => { t.is(renders[0], "OVERRIDE BY A TRANSFORM"); }); -test("Test a transform with a layout", async t => { +test("Test a transform with a layout", async (t) => { t.plan(3); let tmpl = getNewTemplate( @@ -1254,7 +1254,7 @@ test("Test a transform with a layout", async t => { "./test/stubs-475/_site" ); - tmpl.addTransform(function(content, outputPath) { + tmpl.addTransform(function (content, outputPath) { t.is(content, "This is content."); t.true(outputPath.endsWith(".html")); return "OVERRIDE BY A TRANSFORM"; @@ -1264,7 +1264,7 @@ test("Test a transform with a layout", async t => { t.is(renders[0], "OVERRIDE BY A TRANSFORM"); }); -test("Test a single asynchronous transform", async t => { +test("Test a single asynchronous transform", async (t) => { t.plan(2); let tmpl = getNewTemplate( @@ -1273,11 +1273,11 @@ test("Test a single asynchronous transform", async t => { "./test/stubs/_site" ); - tmpl.addTransform(async function(content, outputPath) { + tmpl.addTransform(async function (content, outputPath) { t.true(outputPath.endsWith("template/index.html")); return new Promise((resolve, reject) => { - setTimeout(function(str, outputPath) { + setTimeout(function (str, outputPath) { resolve("OVERRIDE BY A TRANSFORM"); }, 50); }); @@ -1287,7 +1287,7 @@ test("Test a single asynchronous transform", async t => { t.is(renders[0], "OVERRIDE BY A TRANSFORM"); }); -test("Test multiple asynchronous transforms", async t => { +test("Test multiple asynchronous transforms", async (t) => { t.plan(3); let tmpl = getNewTemplate( @@ -1296,22 +1296,22 @@ test("Test multiple asynchronous transforms", async t => { "./test/stubs/_site" ); - tmpl.addTransform(async function(content, outputPath) { + tmpl.addTransform(async function (content, outputPath) { t.true(outputPath.endsWith("template/index.html")); return new Promise((resolve, reject) => { - setTimeout(function(str, outputPath) { + setTimeout(function (str, outputPath) { resolve("lowercase transform"); }, 50); }); }); // uppercase - tmpl.addTransform(async function(str, outputPath) { + tmpl.addTransform(async function (str, outputPath) { t.true(outputPath.endsWith("template/index.html")); return new Promise((resolve, reject) => { - setTimeout(function() { + setTimeout(function () { resolve(str.toUpperCase()); }, 50); }); @@ -1321,7 +1321,7 @@ test("Test multiple asynchronous transforms", async t => { t.is(renders[0], "LOWERCASE TRANSFORM"); }); -test("Test a linter", async t => { +test("Test a linter", async (t) => { t.plan(4); let tmpl = getNewTemplate( @@ -1330,7 +1330,7 @@ test("Test a linter", async t => { "./test/stubs/_site" ); - tmpl.addLinter(function(str, inputPath, outputPath) { + tmpl.addLinter(function (str, inputPath, outputPath) { t.true(inputPath.endsWith("template.njk")); t.true(outputPath.endsWith("index.html")); }); @@ -1338,7 +1338,7 @@ test("Test a linter", async t => { await tmpl._testCompleteRender(); }); -test("permalink: false", async t => { +test("permalink: false", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-false/test.md", "./test/stubs/", @@ -1364,7 +1364,7 @@ test("permalink: false", async t => { ); }); -test("Disable dynamic permalinks", async t => { +test("Disable dynamic permalinks", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dynamic-permalink/test.njk", "./test/stubs/", @@ -1375,7 +1375,7 @@ test("Disable dynamic permalinks", async t => { t.is(await tmpl.getOutputHref(), "/{{justastring}}/"); }); -test("Front Matter Tags (Single)", async t => { +test("Front Matter Tags (Single)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/templatetest-frontmatter/single.njk", "./test/stubs/", @@ -1391,7 +1391,7 @@ test("Front Matter Tags (Single)", async t => { t.is(pages[0].templateContent.trim(), "Has single-tag"); }); -test("Front Matter Tags (Multiple)", async t => { +test("Front Matter Tags (Multiple)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/templatetest-frontmatter/multiple.njk", "./test/stubs/", @@ -1407,7 +1407,7 @@ test("Front Matter Tags (Multiple)", async t => { t.is(pages[0].templateContent.trim(), "Has multi-tag-2"); }); -test("Front matter date with quotes (liquid), issue #258", async t => { +test("Front matter date with quotes (liquid), issue #258", async (t) => { let tmpl = getNewTemplate( "./test/stubs/frontmatter-date/test.liquid", "./test/stubs/", @@ -1421,7 +1421,7 @@ test("Front matter date with quotes (liquid), issue #258", async t => { t.is(pages[0].templateContent.trim(), "2009-04-15"); }); -test("Front matter date with quotes (njk), issue #258", async t => { +test("Front matter date with quotes (njk), issue #258", async (t) => { let tmpl = getNewTemplate( "./test/stubs/frontmatter-date/test.njk", "./test/stubs/", @@ -1435,7 +1435,7 @@ test("Front matter date with quotes (njk), issue #258", async t => { t.is(pages[0].templateContent.trim(), "2009-04-15T00:34:34.000Z"); }); -test("Data Cascade (Deep merge)", async t => { +test("Data Cascade (Deep merge)", async (t) => { let newConfig = Object.assign({}, config); newConfig.dataDeepMerge = true; @@ -1458,19 +1458,19 @@ test("Data Cascade (Deep merge)", async t => { "page", "parent", "pkg", - "tags" + "tags", ]); t.deepEqual(Object.keys(data.parent).sort(), [ "child", "datafile", - "frontmatter" + "frontmatter", ]); t.is(data.parent.child, -2); }); -test("Data Cascade (Shallow merge)", async t => { +test("Data Cascade (Shallow merge)", async (t) => { let dataObj = new TemplateData("./test/"); await dataObj.cacheData(); @@ -1488,7 +1488,7 @@ test("Data Cascade (Shallow merge)", async t => { "page", "parent", "pkg", - "tags" + "tags", ]); t.deepEqual(Object.keys(data.parent).sort(), ["child", "frontmatter"]); @@ -1496,7 +1496,7 @@ test("Data Cascade (Shallow merge)", async t => { t.is(data.parent.child, -2); }); -test("Data Cascade Tag Merge (Deep merge)", async t => { +test("Data Cascade Tag Merge (Deep merge)", async (t) => { let newConfig = Object.assign({}, config); newConfig.dataDeepMerge = true; @@ -1516,7 +1516,7 @@ test("Data Cascade Tag Merge (Deep merge)", async t => { t.deepEqual(data.tags.sort(), ["tagA", "tagB", "tagC", "tagD"]); }); -test("Data Cascade Tag Merge (Shallow merge)", async t => { +test("Data Cascade Tag Merge (Shallow merge)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -1531,7 +1531,7 @@ test("Data Cascade Tag Merge (Shallow merge)", async t => { t.deepEqual(data.tags.sort(), ["tagA", "tagB"]); }); -test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async t => { +test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async (t) => { let dataObj = new TemplateData("./test/stubs/"); await dataObj.cacheData(); @@ -1546,7 +1546,7 @@ test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async t t.deepEqual(data.tags.sort(), ["tag1", "tag2"]); }); -test('Local data inherits tags string ([tags] vs "tags") Deep Merge', async t => { +test('Local data inherits tags string ([tags] vs "tags") Deep Merge', async (t) => { let newConfig = Object.assign({}, config); newConfig.dataDeepMerge = true; @@ -1566,7 +1566,7 @@ test('Local data inherits tags string ([tags] vs "tags") Deep Merge', async t => t.deepEqual(data.tags.sort(), ["tag1", "tag2", "tag3"]); }); -test("Throws a Premature Template Content Error (njk)", async t => { +test("Throws a Premature Template Content Error (njk)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.njk", "./test/stubs/", @@ -1581,7 +1581,7 @@ test("Throws a Premature Template Content Error (njk)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error from rendering (njk)", async t => { +test("Throws a Premature Template Content Error from rendering (njk)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.njk", "./test/stubs/", @@ -1596,8 +1596,8 @@ test("Throws a Premature Template Content Error from rendering (njk)", async t = throw new TemplateContentPrematureUseError( "Tried to use templateContent too early (test.njk)" ); - } - } + }, + }, }); let error = await t.throwsAsync(async () => { await tmpl.renderPageEntry(mapEntries[0], pageEntries[0]); @@ -1605,7 +1605,7 @@ test("Throws a Premature Template Content Error from rendering (njk)", async t = t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (liquid)", async t => { +test("Throws a Premature Template Content Error (liquid)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.liquid", "./test/stubs/", @@ -1620,7 +1620,7 @@ test("Throws a Premature Template Content Error (liquid)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (11ty.js)", async t => { +test("Throws a Premature Template Content Error (11ty.js)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.11ty.js", "./test/stubs/", @@ -1635,7 +1635,7 @@ test("Throws a Premature Template Content Error (11ty.js)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (pug)", async t => { +test("Throws a Premature Template Content Error (pug)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.pug", "./test/stubs/", @@ -1650,7 +1650,7 @@ test("Throws a Premature Template Content Error (pug)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error from rendering (pug)", async t => { +test("Throws a Premature Template Content Error from rendering (pug)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.pug", "./test/stubs/", @@ -1665,8 +1665,8 @@ test("Throws a Premature Template Content Error from rendering (pug)", async t = throw new TemplateContentPrematureUseError( "Tried to use templateContent too early (test.pug)" ); - } - } + }, + }, }); let error = await t.throwsAsync(async () => { await tmpl.renderPageEntry(mapEntries[0], pageEntries[0]); @@ -1674,7 +1674,7 @@ test("Throws a Premature Template Content Error from rendering (pug)", async t = t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (md)", async t => { +test("Throws a Premature Template Content Error (md)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.md", "./test/stubs/", @@ -1689,7 +1689,7 @@ test("Throws a Premature Template Content Error (md)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error from rendering (md)", async t => { +test("Throws a Premature Template Content Error from rendering (md)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.md", "./test/stubs/", @@ -1704,8 +1704,8 @@ test("Throws a Premature Template Content Error from rendering (md)", async t => throw new TemplateContentPrematureUseError( "Tried to use templateContent too early (test.md)" ); - } - } + }, + }, }); let error = await t.throwsAsync(async () => { await tmpl.renderPageEntry(mapEntries[0], pageEntries[0]); @@ -1713,7 +1713,7 @@ test("Throws a Premature Template Content Error from rendering (md)", async t => t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (hbs)", async t => { +test("Throws a Premature Template Content Error (hbs)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.hbs", "./test/stubs/", @@ -1728,7 +1728,7 @@ test("Throws a Premature Template Content Error (hbs)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error from rendering (hbs)", async t => { +test("Throws a Premature Template Content Error from rendering (hbs)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.hbs", "./test/stubs/", @@ -1743,8 +1743,8 @@ test("Throws a Premature Template Content Error from rendering (hbs)", async t = throw new TemplateContentPrematureUseError( "Tried to use templateContent too early (test.hbs)" ); - } - } + }, + }, }); let error = await t.throwsAsync(async () => { await tmpl.renderPageEntry(mapEntries[0], pageEntries[0]); @@ -1752,7 +1752,7 @@ test("Throws a Premature Template Content Error from rendering (hbs)", async t = t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (mustache)", async t => { +test("Throws a Premature Template Content Error (mustache)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.mustache", "./test/stubs/", @@ -1767,7 +1767,7 @@ test("Throws a Premature Template Content Error (mustache)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (ejs)", async t => { +test("Throws a Premature Template Content Error (ejs)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.ejs", "./test/stubs/", @@ -1782,7 +1782,7 @@ test("Throws a Premature Template Content Error (ejs)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test("Throws a Premature Template Content Error (haml)", async t => { +test("Throws a Premature Template Content Error (haml)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/prematureTemplateContent/test.haml", "./test/stubs/", @@ -1797,7 +1797,7 @@ test("Throws a Premature Template Content Error (haml)", async t => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test.skip("Issue 413 weird date format", async t => { +test.skip("Issue 413 weird date format", async (t) => { let tmpl = getNewTemplate( "./test/stubs-413/date-frontmatter.md", "./test/stubs-413/", @@ -1808,10 +1808,10 @@ test.skip("Issue 413 weird date format", async t => { t.is(data.page.date, ""); }); -test("Custom Front Matter Parsing Options", async t => { +test("Custom Front Matter Parsing Options", async (t) => { let newConfig = Object.assign({}, config); newConfig.frontMatterParsingOptions = { - excerpt: true + excerpt: true, }; let tmpl = getNewTemplate( @@ -1836,11 +1836,11 @@ This is content.` t.is(fulldata.page.excerpt.trim(), "This is an excerpt."); }); -test("Custom Front Matter Parsing Options (using alias)", async t => { +test("Custom Front Matter Parsing Options (using alias)", async (t) => { let newConfig = Object.assign({}, config); newConfig.frontMatterParsingOptions = { excerpt: true, - excerpt_alias: "my_excerpt" + excerpt_alias: "my_excerpt", }; let tmpl = getNewTemplate( @@ -1863,10 +1863,10 @@ This is content.` t.is(fulldata.my_excerpt.trim(), "This is an excerpt."); }); -test("Custom Front Matter Parsing Options (no newline before excerpt separator)", async t => { +test("Custom Front Matter Parsing Options (no newline before excerpt separator)", async (t) => { let newConfig = Object.assign({}, config); newConfig.frontMatterParsingOptions = { - excerpt: true + excerpt: true, }; let tmpl = getNewTemplate( @@ -1891,10 +1891,10 @@ This is content.` t.is(fulldata.page.excerpt.trim(), "This is an excerpt."); }); -test("Custom Front Matter Parsing Options (no newline after excerpt separator)", async t => { +test("Custom Front Matter Parsing Options (no newline after excerpt separator)", async (t) => { let newConfig = Object.assign({}, config); newConfig.frontMatterParsingOptions = { - excerpt: true + excerpt: true, }; let tmpl = getNewTemplate( @@ -1912,10 +1912,10 @@ This is content.` ); }); -test("Custom Front Matter Parsing Options (no newlines before or after excerpt separator)", async t => { +test("Custom Front Matter Parsing Options (no newlines before or after excerpt separator)", async (t) => { let newConfig = Object.assign({}, config); newConfig.frontMatterParsingOptions = { - excerpt: true + excerpt: true, }; let tmpl = getNewTemplate( @@ -1929,11 +1929,11 @@ test("Custom Front Matter Parsing Options (no newlines before or after excerpt s t.is(frontmatter.content.trim(), "This is an excerpt.This is content."); }); -test("Custom Front Matter Parsing Options (html comment separator)", async t => { +test("Custom Front Matter Parsing Options (html comment separator)", async (t) => { let newConfig = Object.assign({}, config); newConfig.frontMatterParsingOptions = { excerpt: true, - excerpt_separator: "" + excerpt_separator: "", }; let tmpl = getNewTemplate( @@ -1955,15 +1955,15 @@ This is content.` ); }); -test.skip("Custom Front Matter Parsing Options (using TOML)", async t => { +test.skip("Custom Front Matter Parsing Options (using TOML)", async (t) => { // Depends on https://github.com/jonschlinkert/gray-matter/issues/92 for Windows let newConfig = Object.assign({}, config); let toml = require("toml"); newConfig.frontMatterParsingOptions = { engines: { - toml: toml.parse.bind(toml) - } + toml: toml.parse.bind(toml), + }, }; let tmpl = getNewTemplate( @@ -1975,7 +1975,7 @@ test.skip("Custom Front Matter Parsing Options (using TOML)", async t => { let frontmatter = await tmpl.getFrontMatter(); t.deepEqual(frontmatter.data, { - front: "hello" + front: "hello", }); t.is(frontmatter.content.trim(), "This is content."); @@ -1983,7 +1983,7 @@ test.skip("Custom Front Matter Parsing Options (using TOML)", async t => { t.is(fulldata.front, "hello"); }); -test("global variable with dashes Issue #567 (liquid)", async t => { +test("global variable with dashes Issue #567 (liquid)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/global-dash-variable.liquid", "./test/stubs/", @@ -1997,7 +1997,7 @@ test("global variable with dashes Issue #567 (liquid)", async t => { t.is(pages[0].templateContent.trim(), "Yes"); }); -test("Issue #446: Layout has a permalink with a different template language than content", async t => { +test("Issue #446: Layout has a permalink with a different template language than content", async (t) => { let tmpl = getNewTemplate( "./test/stubs/layout-permalink-difflang/test.md", "./test/stubs/layout-permalink-difflang/", @@ -2013,7 +2013,7 @@ test("Issue #446: Layout has a permalink with a different template language than }); // Prior to and including 0.10.0 this mismatched the documentation)! -test("Layout front matter should override template files", async t => { +test("Layout front matter should override template files", async (t) => { let dataObj = new TemplateData( "./test/stubs-data-cascade/layout-data-files/" ); @@ -2028,7 +2028,7 @@ test("Layout front matter should override template files", async t => { t.is(data.shared, "layout"); }); -test("Get Layout Chain", async t => { +test("Get Layout Chain", async (t) => { let tmpl = getNewTemplate( "./test/stubs-incremental/layout-chain/test.njk", "./test/stubs-incremental/layout-chain/", @@ -2038,11 +2038,11 @@ test("Get Layout Chain", async t => { let layoutChain = await tmpl.getLayoutChain(); t.deepEqual(layoutChain, [ "./test/stubs-incremental/layout-chain/_includes/base.njk", - "./test/stubs-incremental/layout-chain/_includes/parent.njk" + "./test/stubs-incremental/layout-chain/_includes/parent.njk", ]); }); -test("Engine Singletons", async t => { +test("Engine Singletons", async (t) => { let map = new EleventyExtensionMap(["njk"]); let tmpl1 = getNewTemplate( "./test/stubs/engine-singletons/first.njk", diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 3b766403e..e6e28bb80 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -1,18 +1,18 @@ -import test from "ava"; -import fs from "fs-extra"; -import rimraf from "rimraf"; -import fastglob from "fast-glob"; -import parsePath from "parse-filepath"; -import EleventyFiles from "../src/EleventyFiles"; -import EleventyExtensionMap from "../src/EleventyExtensionMap"; -import TemplateWriter from "../src/TemplateWriter"; +const test = require("ava"); +const fs = require("fs-extra"); +const rimraf = require("rimraf"); +const fastglob = require("fast-glob"); +const parsePath = require("parse-filepath"); +const EleventyFiles = require("../src/EleventyFiles"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const TemplateWriter = require("../src/TemplateWriter"); // Not sure why but this import up `ava` and _createTemplate 👀 // import Template from "../src/Template"; -import eleventyConfig from "../src/EleventyConfig"; -import normalizeNewLines from "./Util/normalizeNewLines"; +const eleventyConfig = require("../src/EleventyConfig"); +const normalizeNewLines = require("./Util/normalizeNewLines"); // TODO make sure if output is a subdir of input dir that they don’t conflict. -test("Output is a subdir of input", async t => { +test("Output is a subdir of input", async (t) => { let tw = new TemplateWriter( "./test/stubs/writeTest", "./test/stubs/writeTest/_writeTestSite" @@ -36,7 +36,7 @@ test("Output is a subdir of input", async t => { ); }); -test("_createTemplateMap", async t => { +test("_createTemplateMap", async (t) => { let tw = new TemplateWriter( "./test/stubs/writeTest", "./test/stubs/_writeTestSite", @@ -54,7 +54,7 @@ test("_createTemplateMap", async t => { t.truthy(map[0].data); }); -test("_createTemplateMap (no leading dot slash)", async t => { +test("_createTemplateMap (no leading dot slash)", async (t) => { let tw = new TemplateWriter( "test/stubs/writeTest", "test/stubs/_writeTestSite", @@ -66,9 +66,9 @@ test("_createTemplateMap (no leading dot slash)", async t => { t.is(paths[0], "./test/stubs/writeTest/test.md"); }); -test("_testGetCollectionsData", async t => { +test("_testGetCollectionsData", async (t) => { let tw = new TemplateWriter("./test/stubs/collection", "./test/stubs/_site", [ - "md" + "md", ]); let paths = await tw._getAllPaths(); @@ -80,9 +80,9 @@ test("_testGetCollectionsData", async t => { }); // TODO remove this (used by other test things) -test("_testGetAllTags", async t => { +test("_testGetAllTags", async (t) => { let tw = new TemplateWriter("./test/stubs/collection", "./test/stubs/_site", [ - "md" + "md", ]); let paths = await tw._getAllPaths(); @@ -92,9 +92,9 @@ test("_testGetAllTags", async t => { t.deepEqual(tags.sort(), ["cat", "dog", "post"].sort()); }); -test("Collection of files sorted by date", async t => { +test("Collection of files sorted by date", async (t) => { let tw = new TemplateWriter("./test/stubs/dates", "./test/stubs/_site", [ - "md" + "md", ]); let paths = await tw._getAllPaths(); @@ -103,7 +103,7 @@ test("Collection of files sorted by date", async t => { t.is(collectionsData.dateTestTag.length, 6); }); -test("__testGetCollectionsData with custom collection (ascending)", async t => { +test("__testGetCollectionsData with custom collection (ascending)", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -111,8 +111,8 @@ test("__testGetCollectionsData with custom collection (ascending)", async t => { ); /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("customPostsAsc", function(collection) { - return collection.getFilteredByTag("post").sort(function(a, b) { + eleventyConfig.addCollection("customPostsAsc", function (collection) { + return collection.getFilteredByTag("post").sort(function (a, b) { return a.date - b.date; }); }); @@ -125,7 +125,7 @@ test("__testGetCollectionsData with custom collection (ascending)", async t => { t.is(parsePath(collectionsData.customPostsAsc[1].inputPath).base, "test2.md"); }); -test("__testGetCollectionsData with custom collection (descending)", async t => { +test("__testGetCollectionsData with custom collection (descending)", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -133,8 +133,8 @@ test("__testGetCollectionsData with custom collection (descending)", async t => ); /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("customPosts", function(collection) { - return collection.getFilteredByTag("post").sort(function(a, b) { + eleventyConfig.addCollection("customPosts", function (collection) { + return collection.getFilteredByTag("post").sort(function (a, b) { return b.date - a.date; }); }); @@ -147,7 +147,7 @@ test("__testGetCollectionsData with custom collection (descending)", async t => t.is(parsePath(collectionsData.customPosts[1].inputPath).base, "test1.md"); }); -test("__testGetCollectionsData with custom collection (filter only to markdown input)", async t => { +test("__testGetCollectionsData with custom collection (filter only to markdown input)", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -155,8 +155,8 @@ test("__testGetCollectionsData with custom collection (filter only to markdown i ); /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("onlyMarkdown", function(collection) { - return collection.getAllSorted().filter(function(item) { + eleventyConfig.addCollection("onlyMarkdown", function (collection) { + return collection.getAllSorted().filter(function (item) { let extension = item.inputPath.split(".").pop(); return extension === "md"; }); @@ -170,7 +170,7 @@ test("__testGetCollectionsData with custom collection (filter only to markdown i t.is(parsePath(collectionsData.onlyMarkdown[1].inputPath).base, "test2.md"); }); -test("Pagination with a Collection", async t => { +test("Pagination with a Collection", async (t) => { let tw = new TemplateWriter( "./test/stubs/paged/collection", "./test/stubs/_site", @@ -200,7 +200,7 @@ test("Pagination with a Collection", async t => { t.is(mapEntry._pages[1].templateContent.trim(), "
  1. /test3/
"); }); -test("Pagination with a Collection from another Paged Template", async t => { +test("Pagination with a Collection from another Paged Template", async (t) => { let tw = new TemplateWriter( "./test/stubs/paged/cfg-collection-tag-cfg-collection", "./test/stubs/_site", @@ -233,7 +233,7 @@ test("Pagination with a Collection from another Paged Template", async t => { ); }); -test("Pagination with a Collection (apply all pages to collections)", async t => { +test("Pagination with a Collection (apply all pages to collections)", async (t) => { let tw = new TemplateWriter( "./test/stubs/paged/collection-apply-to-all", "./test/stubs/_site", @@ -284,7 +284,7 @@ test("Pagination with a Collection (apply all pages to collections)", async t => t.is(templates[1].templateContent.trim(), "
  1. /test3/
"); }); -test("Use a collection inside of a template", async t => { +test("Use a collection inside of a template", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection-template", "./test/stubs/collection-template/_site", @@ -326,7 +326,7 @@ Template 1 dog` ); }); -test("Use a collection inside of a layout", async t => { +test("Use a collection inside of a layout", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection-layout", "./test/stubs/collection-layout/_site", @@ -365,12 +365,12 @@ Layout 1 dog` ); }); -test("Glob Watcher Files with Passthroughs", t => { +test("Glob Watcher Files with Passthroughs", (t) => { let tw = new TemplateWriter("test/stubs", "test/stubs/_site", ["njk", "png"]); t.deepEqual(tw.eleventyFiles.passthroughGlobs, ["./test/stubs/**/*.png"]); }); -test("Pagination and TemplateContent", async t => { +test("Pagination and TemplateContent", async (t) => { let tw = new TemplateWriter( "./test/stubs/pagination-templatecontent", "./test/stubs/pagination-templatecontent/_site", @@ -393,7 +393,7 @@ test("Pagination and TemplateContent", async t => { rimraf.sync("./test/stubs/pagination-templatecontent/_site/"); }); -test("Custom collection returns array", async t => { +test("Custom collection returns array", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -401,8 +401,8 @@ test("Custom collection returns array", async t => { ); /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("returnAllInputPaths", function(collection) { - return collection.getAllSorted().map(function(item) { + eleventyConfig.addCollection("returnAllInputPaths", function (collection) { + return collection.getAllSorted().map(function (item) { return item.inputPath; }); }); @@ -415,7 +415,7 @@ test("Custom collection returns array", async t => { t.is(parsePath(collectionsData.returnAllInputPaths[1]).base, "test2.md"); }); -test("Custom collection returns a string", async t => { +test("Custom collection returns a string", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -423,7 +423,7 @@ test("Custom collection returns a string", async t => { ); /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("returnATestString", function(collection) { + eleventyConfig.addCollection("returnATestString", function (collection) { return "test"; }); @@ -433,7 +433,7 @@ test("Custom collection returns a string", async t => { t.is(collectionsData.returnATestString, "test"); }); -test("Custom collection returns an object", async t => { +test("Custom collection returns an object", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", @@ -441,7 +441,7 @@ test("Custom collection returns an object", async t => { ); /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("returnATestObject", function() { + eleventyConfig.addCollection("returnATestObject", function () { return { test: "value" }; }); @@ -451,7 +451,7 @@ test("Custom collection returns an object", async t => { t.deepEqual(collectionsData.returnATestObject, { test: "value" }); }); -test("fileSlug should exist in a collection", async t => { +test("fileSlug should exist in a collection", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection-slug", "./test/stubs/collection-slug/_site", @@ -474,7 +474,7 @@ test("fileSlug should exist in a collection", async t => { t.is(templates[0].templateContent.trim(), "fileSlug:/dog1/:dog1"); }); -test("renderData should exist and be resolved in a collection (Issue #289)", async t => { +test("renderData should exist and be resolved in a collection (Issue #289)", async (t) => { let tw = new TemplateWriter( "./test/stubs/collection-renderdata", "./test/stubs/collection-renderdata/_site", @@ -497,7 +497,7 @@ test("renderData should exist and be resolved in a collection (Issue #289)", asy t.is(templates[0].templateContent.trim(), "value2-value1.css"); }); -test("Write Test 11ty.js", async t => { +test("Write Test 11ty.js", async (t) => { let tw = new TemplateWriter( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite" @@ -512,7 +512,7 @@ test("Write Test 11ty.js", async t => { let files = await fastglob(evf.getFileGlobs()); t.deepEqual(evf.getRawFiles(), [ "./test/stubs/writeTestJS/**/*.11ty.js", - "./test/stubs/writeTestJS/**/*.11ty.cjs" + "./test/stubs/writeTestJS/**/*.11ty.cjs", ]); t.deepEqual(files, ["./test/stubs/writeTestJS/test.11ty.js"]); @@ -523,12 +523,12 @@ test("Write Test 11ty.js", async t => { ); }); -test.skip("Markdown with alias", async t => { +test.skip("Markdown with alias", async (t) => { let map = new EleventyExtensionMap(["md"]); map.config = { templateExtensionAliases: { - markdown: "md" - } + markdown: "md", + }, }; let evf = new EleventyFiles( @@ -542,7 +542,7 @@ test.skip("Markdown with alias", async t => { let files = await fastglob(evf.getFileGlobs()); t.deepEqual(evf.getRawFiles(), [ "./test/stubs/writeTestMarkdown/**/*.md", - "./test/stubs/writeTestMarkdown/**/*.markdown" + "./test/stubs/writeTestMarkdown/**/*.markdown", ]); t.true(files.indexOf("./test/stubs/writeTestMarkdown/sample.md") > -1); t.true(files.indexOf("./test/stubs/writeTestMarkdown/sample2.markdown") > -1); @@ -568,12 +568,12 @@ test.skip("Markdown with alias", async t => { ); }); -test.skip("JavaScript with alias", async t => { +test.skip("JavaScript with alias", async (t) => { let map = new EleventyExtensionMap(["11ty.js"]); map.config = { templateExtensionAliases: { - js: "11ty.js" - } + js: "11ty.js", + }, }; let evf = new EleventyFiles( @@ -589,14 +589,14 @@ test.skip("JavaScript with alias", async t => { evf.getRawFiles().sort(), [ "./test/stubs/writeTestJS/**/*.11ty.js", - "./test/stubs/writeTestJS/**/*.js" + "./test/stubs/writeTestJS/**/*.js", ].sort() ); t.deepEqual( files.sort(), [ "./test/stubs/writeTestJS/sample.js", - "./test/stubs/writeTestJS/test.11ty.js" + "./test/stubs/writeTestJS/test.11ty.js", ].sort() ); @@ -613,7 +613,7 @@ test.skip("JavaScript with alias", async t => { ); }); -test("Passthrough file output", async t => { +test("Passthrough file output", async (t) => { let tw = new TemplateWriter( "./test/stubs/template-passthrough/", "./test/stubs/template-passthrough/_site", @@ -627,8 +627,8 @@ test("Passthrough file output", async t => { "./test/stubs/template-passthrough/static": true, "./test/stubs/template-passthrough/static/": "./", "./test/stubs/template-passthrough/static/**/*": "./all/", - "./test/stubs/template-passthrough/static/**/*.js": "./js/" - } + "./test/stubs/template-passthrough/static/**/*.js": "./js/", + }, }); await tw.write(); @@ -643,11 +643,11 @@ test("Passthrough file output", async t => { "./test/stubs/template-passthrough/_site/nested/", "./test/stubs/template-passthrough/_site/nested/test-nested.css", "./test/stubs/template-passthrough/_site/test.css", - "./test/stubs/template-passthrough/_site/test.js" + "./test/stubs/template-passthrough/_site/test.js", ]; let results = await Promise.all( - output.map(function(path) { + output.map(function (path) { return fs.exists(path); }) ); diff --git a/test/TestUtilityTest.js b/test/TestUtilityTest.js index e8c4428cc..c5247bad8 100644 --- a/test/TestUtilityTest.js +++ b/test/TestUtilityTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import normalizeNewLines from "./Util/normalizeNewLines"; +const test = require("ava"); +const normalizeNewLines = require("./Util/normalizeNewLines"); -test("normalizeNewLines", t => { +test("normalizeNewLines", (t) => { t.is(normalizeNewLines("\n"), "\n"); t.is(normalizeNewLines("\r\n"), "\n"); t.is(normalizeNewLines("\r\n\n"), "\n\n"); diff --git a/test/UrlTest.js b/test/UrlTest.js index a81985c9b..b3daf9419 100644 --- a/test/UrlTest.js +++ b/test/UrlTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import url from "../src/Filters/Url.js"; +const test = require("ava"); +const url = require("../src/Filters/Url.js"); -test("Test url filter without passing in pathPrefix", t => { +test("Test url filter without passing in pathPrefix", (t) => { let projectConfig = require("../src/Config").getConfig(); t.is(projectConfig.pathPrefix, "/"); @@ -9,7 +9,7 @@ test("Test url filter without passing in pathPrefix", t => { t.is(url("/test"), "/test"); }); -test("Test url filter with passthrough urls", t => { +test("Test url filter with passthrough urls", (t) => { // via https://gist.github.com/mxpv/034933deeebb26b62f14 t.is(url("http://foo.com/blah_blah", ""), "http://foo.com/blah_blah"); t.is(url("http://foo.com/blah_blah/", ""), "http://foo.com/blah_blah/"); @@ -102,7 +102,7 @@ test("Test url filter with passthrough urls", t => { t.is(url("http://उदाहरण.परीक्षा", ""), "http://उदाहरण.परीक्षा"); }); -test("Test url filter", t => { +test("Test url filter", (t) => { t.is(url("/", "/"), "/"); t.is(url("//", "/"), "/"); t.is(url(undefined, "/"), "."); @@ -127,7 +127,7 @@ test("Test url filter", t => { t.is(url("../test/", "/"), "../test/"); }); -test("Test url filter with custom pathPrefix (empty, gets overwritten by root config `/`)", t => { +test("Test url filter with custom pathPrefix (empty, gets overwritten by root config `/`)", (t) => { t.is(url("/", ""), "/"); t.is(url("//", ""), "/"); t.is(url(undefined, ""), "."); @@ -152,7 +152,7 @@ test("Test url filter with custom pathPrefix (empty, gets overwritten by root co t.is(url("../test/", ""), "../test/"); }); -test("Test url filter with custom pathPrefix (leading slash)", t => { +test("Test url filter with custom pathPrefix (leading slash)", (t) => { t.is(url("/", "/testdir"), "/testdir/"); t.is(url("//", "/testdir"), "/testdir/"); t.is(url(undefined, "/testdir"), "."); @@ -177,7 +177,7 @@ test("Test url filter with custom pathPrefix (leading slash)", t => { t.is(url("../test/", "/testdir"), "../test/"); }); -test("Test url filter with custom pathPrefix (double slash)", t => { +test("Test url filter with custom pathPrefix (double slash)", (t) => { t.is(url("/", "/testdir/"), "/testdir/"); t.is(url("//", "/testdir/"), "/testdir/"); t.is(url(undefined, "/testdir/"), "."); @@ -202,7 +202,7 @@ test("Test url filter with custom pathPrefix (double slash)", t => { t.is(url("../test/", "/testdir/"), "../test/"); }); -test("Test url filter with custom pathPrefix (trailing slash)", t => { +test("Test url filter with custom pathPrefix (trailing slash)", (t) => { t.is(url("/", "testdir/"), "/testdir/"); t.is(url("//", "testdir/"), "/testdir/"); t.is(url(undefined, "testdir/"), "."); @@ -227,7 +227,7 @@ test("Test url filter with custom pathPrefix (trailing slash)", t => { t.is(url("../test/", "testdir/"), "../test/"); }); -test("Test url filter with custom pathPrefix (no slash)", t => { +test("Test url filter with custom pathPrefix (no slash)", (t) => { t.is(url("/", "testdir"), "/testdir/"); t.is(url("//", "testdir"), "/testdir/"); t.is(url(undefined, "testdir"), "."); diff --git a/test/UserConfigTest.js b/test/UserConfigTest.js index efebe6902..41e409626 100644 --- a/test/UserConfigTest.js +++ b/test/UserConfigTest.js @@ -1,7 +1,7 @@ -import test from "ava"; -import UserConfig from "../src/UserConfig"; +const test = require("ava"); +const UserConfig = require("../src/UserConfig"); -test("Template Formats", t => { +test("Template Formats", (t) => { let cfg = new UserConfig(); t.falsy(cfg.getMergingConfigObject().templateFormats); @@ -15,7 +15,7 @@ test("Template Formats", t => { t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); }); -test("Template Formats (Arrays)", t => { +test("Template Formats (Arrays)", (t) => { let cfg = new UserConfig(); t.falsy(cfg.getMergingConfigObject().templateFormats); diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index 0fb25447b..d51f1b699 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -1,15 +1,15 @@ -import test from "ava"; -import TemplateData from "../src/TemplateData"; +const test = require("ava"); +const TemplateData = require("../src/TemplateData"); let yaml = require("js-yaml"); function injectDataExtensions(dataObj) { dataObj.config.dataExtensions = new Map([ - ["yaml", s => yaml.safeLoad(s)], - ["nosj", JSON.parse] + ["yaml", (s) => yaml.safeLoad(s)], + ["nosj", JSON.parse], ]); } -test("Local data", async t => { +test("Local data", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); @@ -37,7 +37,7 @@ test("Local data", async t => { t.is(withLocalData.jsKey1, "js1"); }); -test("Local files", async t => { +test("Local files", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); let files = await dataObj.getLocalDataPaths( @@ -67,17 +67,17 @@ test("Local files", async t => { "./test/stubs-630/component-yaml/component.11tydata.nosj", "./test/stubs-630/component-yaml/component.11tydata.json", "./test/stubs-630/component-yaml/component.11tydata.cjs", - "./test/stubs-630/component-yaml/component.11tydata.js" + "./test/stubs-630/component-yaml/component.11tydata.js", ]); }); -test("Global data", async t => { +test("Global data", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); t.deepEqual(await dataObj.getGlobalDataGlob(), [ - "./test/stubs-630/_data/**/*.(nosj|yaml|json|cjs|js)" + "./test/stubs-630/_data/**/*.(nosj|yaml|json|cjs|js)", ]); let data = await dataObj.getData(); @@ -103,7 +103,7 @@ test("Global data", async t => { t.is(data.subdir.globalDataSubdir.keyyaml, "yaml"); }); -test("Global data merging and priority", async t => { +test("Global data merging and priority", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); From 085c0664566965e798c09d7d91b17dd468d14861 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 7 Sep 2020 15:37:07 -0500 Subject: [PATCH 255/746] Removes JSTL. Fixes #1084 --- package.json | 3 +- src/EleventyExtensionMap.js | 17 +++---- src/Engines/JavaScriptTemplateLiteral.js | 63 ------------------------ src/TemplateEngineManager.js | 1 - src/defaultConfig.js | 11 ++--- test/TemplateLayoutPathResolverTest.js | 1 - test/TemplateLayoutTest.js | 1 - test/TemplateRenderJSTLTest.js | 48 ------------------ test/TemplateTest.js | 24 --------- test/_getNewTemplateForTests.js | 3 +- test/stubs/formatTest.jstl | 4 -- test/stubs/formatTestBackticks.jstl | 4 -- 12 files changed, 15 insertions(+), 165 deletions(-) delete mode 100644 src/Engines/JavaScriptTemplateLiteral.js delete mode 100644 test/TemplateRenderJSTLTest.js delete mode 100644 test/stubs/formatTest.jstl delete mode 100644 test/stubs/formatTestBackticks.jstl diff --git a/package.json b/package.json index 5416e75ff..777701259 100755 --- a/package.json +++ b/package.json @@ -103,7 +103,6 @@ "gray-matter": "^4.0.2", "hamljs": "^0.6.2", "handlebars": "^4.7.6", - "javascript-stringify": "^2.0.1", "liquidjs": "^9.15.0", "lodash": "^4.17.20", "luxon": "^1.25.0", @@ -130,4 +129,4 @@ "pre-push": "npm run test" } } -} +} \ No newline at end of file diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 086f1c2da..d26c0981e 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -9,16 +9,16 @@ class EleventyExtensionMap { } setFormats(formatKeys = []) { - this.unfilteredFormatKeys = formatKeys.map(function(key) { + this.unfilteredFormatKeys = formatKeys.map(function (key) { return key.trim().toLowerCase(); }); - this.validTemplateLanguageKeys = this.unfilteredFormatKeys.filter(key => + this.validTemplateLanguageKeys = this.unfilteredFormatKeys.filter((key) => this.hasExtension(key) ); this.passthroughCopyKeys = this.unfilteredFormatKeys.filter( - key => !this.hasExtension(key) + (key) => !this.hasExtension(key) ); } @@ -46,8 +46,8 @@ class EleventyExtensionMap { let files = []; this.validTemplateLanguageKeys.forEach( - function(key) { - this.getExtensionsFromKey(key).forEach(function(extension) { + function (key) { + this.getExtensionsFromKey(key).forEach(function (extension) { files.push((dir ? dir + "/" : "") + path + "." + extension); }); }.bind(this) @@ -76,9 +76,9 @@ class EleventyExtensionMap { let dir = TemplatePath.convertToRecursiveGlobSync(inputDir); let globs = []; formatKeys.forEach( - function(key) { + function (key) { if (this.hasExtension(key)) { - this.getExtensionsFromKey(key).forEach(function(extension) { + this.getExtensionsFromKey(key).forEach(function (extension) { globs.push(dir + "/*." + extension); }); } else { @@ -141,7 +141,6 @@ class EleventyExtensionMap { this._extensionToKeyMap = { ejs: "ejs", md: "md", - jstl: "jstl", html: "html", hbs: "hbs", mustache: "mustache", @@ -150,7 +149,7 @@ class EleventyExtensionMap { njk: "njk", liquid: "liquid", "11ty.js": "11ty.js", - "11ty.cjs": "11ty.js" + "11ty.cjs": "11ty.js", }; if ("extensionMap" in this.config) { diff --git a/src/Engines/JavaScriptTemplateLiteral.js b/src/Engines/JavaScriptTemplateLiteral.js deleted file mode 100644 index 4071593ee..000000000 --- a/src/Engines/JavaScriptTemplateLiteral.js +++ /dev/null @@ -1,63 +0,0 @@ -const javascriptStringify = require("javascript-stringify"); -const TemplateEngine = require("./TemplateEngine"); -const EleventyBaseError = require("../EleventyBaseError"); - -class JavaScriptTemplateLiteralCompileError extends EleventyBaseError {} - -class JavaScriptTemplateLiteral extends TemplateEngine { - // add ` around template if it doesn’t exist. - static normalizeTicks(str) { - // TODO make this work with tagged templates html`` - let trimmedStr = str.trim(); - if ( - trimmedStr.charAt(0) === "`" && - trimmedStr.charAt(trimmedStr.length - 1) === "`" - ) { - str = - "`" + - trimmedStr.substr(1, trimmedStr.length - 2).replace(/`/g, "\\`") + - "`"; - } else { - str = - "`" + - str.replace(/`/g, "\\`") + - (trimmedStr.charAt(trimmedStr.length - 1) === "`" ? "\n" : "") + - "`"; - } - - return str; - } - - async compile(str, inputPath) { - return function(data) { - // avoid `with` - let dataStr = ""; - for (let j in data) { - dataStr += `let ${j} = ${javascriptStringify.stringify( - data[j], - null, - null, - { - references: true - } - )};\n`; - } - - let evalStr = `${dataStr}\n${JavaScriptTemplateLiteral.normalizeTicks( - str - )};`; - try { - // TODO switch to https://www.npmjs.com/package/es6-template-strings - let val = eval(evalStr); - return val; - } catch (e) { - throw new JavaScriptTemplateLiteralCompileError( - `Broken ES6 template:\n${evalStr}`, - e - ); - } - }; - } -} - -module.exports = JavaScriptTemplateLiteral; diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 8a24fbfb1..5d0949f9f 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -21,7 +21,6 @@ class TemplateEngineManager { this._keyToClassNameMap = { ejs: "Ejs", md: "Markdown", - jstl: "JavaScriptTemplateLiteral", html: "Html", hbs: "Handlebars", mustache: "Mustache", diff --git a/src/defaultConfig.js b/src/defaultConfig.js index fa1b08ca5..0828cd2cb 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -2,7 +2,7 @@ const urlFilter = require("./Filters/Url"); const slugFilter = require("./Filters/Slug"); const getCollectionItem = require("./Filters/GetCollectionItem"); -module.exports = function(config) { +module.exports = function (config) { config.addFilter("slug", slugFilter); config.addFilter("url", urlFilter); config.addFilter("log", console.log); @@ -28,8 +28,7 @@ module.exports = function(config) { "pug", "njk", "html", - "jstl", - "11ty.js" + "11ty.js", ], // if your site lives in a subdirectory, change this pathPrefix: "/", @@ -45,19 +44,19 @@ module.exports = function(config) { permalink: "permalink", permalinkRoot: "permalinkBypassOutputDir", engineOverride: "templateEngineOverride", - computed: "eleventyComputed" + computed: "eleventyComputed", }, dir: { input: ".", includes: "_includes", data: "_data", - output: "_site" + output: "_site", }, // deprecated, use config.addTransform filters: {}, // deprecated, use config.addHandlebarsHelper handlebarsHelpers: {}, // deprecated, use config.addNunjucksFilter - nunjucksFilters: {} + nunjucksFilters: {}, }; }; diff --git a/test/TemplateLayoutPathResolverTest.js b/test/TemplateLayoutPathResolverTest.js index 984476e63..c85937612 100644 --- a/test/TemplateLayoutPathResolverTest.js +++ b/test/TemplateLayoutPathResolverTest.js @@ -14,7 +14,6 @@ function getResolverInstance(path, inputDir, map) { "pug", "njk", "html", - "jstl", "11ty.js", ]); } diff --git a/test/TemplateLayoutTest.js b/test/TemplateLayoutTest.js index e155e389c..1c056fd0e 100644 --- a/test/TemplateLayoutTest.js +++ b/test/TemplateLayoutTest.js @@ -14,7 +14,6 @@ function getTemplateLayoutInstance(key, inputDir, map) { "pug", "njk", "html", - "jstl", "11ty.js", ]); } diff --git a/test/TemplateRenderJSTLTest.js b/test/TemplateRenderJSTLTest.js deleted file mode 100644 index b1ff43930..000000000 --- a/test/TemplateRenderJSTLTest.js +++ /dev/null @@ -1,48 +0,0 @@ -const test = require("ava"); -const TemplateRender = require("../src/TemplateRender"); -const EleventyExtensionMap = require("../src/EleventyExtensionMap"); - -function getNewTemplateRender(name, inputDir) { - let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); - return tr; -} - -// ES6 -test("ES6 Template Literal", (t) => { - t.is(getNewTemplateRender("jstl").getEngineName(), "jstl"); -}); - -test("ES6 Template Literal Render (Backticks)", async (t) => { - // pass in a string here, we don’t want to compile the template in the test :O - let fn = await getNewTemplateRender("jstl").getCompiledTemplate( - "`

${name.toUpperCase()}

`" - ); - t.is(await fn({ name: "Tim" }), "

TIM

"); -}); - -test("ES6 Template Literal Render (No backticks)", async (t) => { - // pass in a string here, we don’t want to compile the template in the test :O - let fn = await getNewTemplateRender("jstl").getCompiledTemplate( - "

${name.toUpperCase()}

" - ); - t.is(await fn({ name: "Tim" }), "

TIM

"); -}); - -test("ES6 Template Literal with newlines", async (t) => { - // pass in a string here, we don’t want to compile the template in the test :O - let fn = await getNewTemplateRender("jstl").getCompiledTemplate( - "Test\n\nMarkdown Syntax ${name}\n" - ); - t.is(await fn({ name: "Tim" }), "Test\n\nMarkdown Syntax Tim\n"); -}); - -test("ES6 Template Literal with markdown", async (t) => { - // pass in a string here, we don’t want to compile the template in the test :O - let fn = await getNewTemplateRender("jstl").getCompiledTemplate( - "Test\n```\nMarkdown Syntax ${name}\n```" - ); - - // TODO this has an extra newline at the end because the input string ends in a `! - t.is(await fn({ name: "Tim" }), "Test\n```\nMarkdown Syntax Tim\n```\n"); -}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index f76b7e5f7..e320c2007 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -359,30 +359,6 @@ test("Liquid template with include", async (t) => { ); }); -test("ES6 Template Literal (No Backticks)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); - let tmpl = getNewTemplate( - "./test/stubs/formatTest.jstl", - "./test/stubs/", - "dist", - dataObj - ); - - t.is((await tmpl.render(await tmpl.getData())).trim(), `

ZACH

`); -}); - -test("ES6 Template Literal (with Backticks)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); - let tmpl = getNewTemplate( - "./test/stubs/formatTestBackticks.jstl", - "./test/stubs/", - "dist", - dataObj - ); - - t.is((await tmpl.render(await tmpl.getData())).trim(), `

ZACH

`); -}); - test("Permalink output directory", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalinked.ejs", diff --git a/test/_getNewTemplateForTests.js b/test/_getNewTemplateForTests.js index 327602624..246b0fda0 100644 --- a/test/_getNewTemplateForTests.js +++ b/test/_getNewTemplateForTests.js @@ -19,8 +19,7 @@ module.exports = function getNewTemplate( "pug", "njk", "html", - "jstl", - "11ty.js" + "11ty.js", ]); } let tmpl = new Template(path, inputDir, outputDir, templateData, map); diff --git a/test/stubs/formatTest.jstl b/test/stubs/formatTest.jstl deleted file mode 100644 index 3a49f1da6..000000000 --- a/test/stubs/formatTest.jstl +++ /dev/null @@ -1,4 +0,0 @@ ---- -name: zach ---- -

${name.toUpperCase()}

diff --git a/test/stubs/formatTestBackticks.jstl b/test/stubs/formatTestBackticks.jstl deleted file mode 100644 index 2a5807b9e..000000000 --- a/test/stubs/formatTestBackticks.jstl +++ /dev/null @@ -1,4 +0,0 @@ ---- -name: zach ---- -`

${name.toUpperCase()}

` From 827f118fd0408a315203bd48467cdad17363780c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 7 Sep 2020 15:44:31 -0500 Subject: [PATCH 256/746] This only runs computed data IF eleventyComputed exists in the data set (performance improvement, probably) --- src/Template.js | 59 ++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/src/Template.js b/src/Template.js index e215d21dc..b81eee44a 100755 --- a/src/Template.js +++ b/src/Template.js @@ -408,42 +408,45 @@ class Template extends TemplateContent { // will _not_ consume renderData this.computedData = new ComputedData(); - // Add permalink (outside of eleventyComputed) to computed graph - // if(data.permalink) { - // this._addComputedEntry(this.computedData, data.permalink, "permalink"); - // } - - // Note that `permalink` is only a thing that gets consumed—it does not go directly into generated data - // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly - this.computedData.addTemplateString( - "page.url", - async (data) => await this.getOutputHref(data), - data.permalink ? ["permalink"] : undefined - ); + if (this.config.keys.computed in data) { + // Note that `permalink` is only a thing that gets consumed—it does not go directly into generated data + // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly + this.computedData.addTemplateString( + "page.url", + async (data) => await this.getOutputHref(data), + data.permalink ? ["permalink"] : undefined + ); - this.computedData.addTemplateString( - "page.outputPath", - async (data) => await this.getOutputPath(data), - data.permalink ? ["permalink"] : undefined - ); + this.computedData.addTemplateString( + "page.outputPath", + async (data) => await this.getOutputPath(data), + data.permalink ? ["permalink"] : undefined + ); - if (this.config.keys.computed in data) { + // actually add the computed data this._addComputedEntry( this.computedData, data[this.config.keys.computed] ); - } - // limited run of computed data—save the stuff that relies on collections for later. - debug("First round of computed data for %o", this.inputPath); - await this.computedData.setupData(data, function (entry) { - return !this.isUsesStartsWith(entry, "collections."); + // limited run of computed data—save the stuff that relies on collections for later. + debug("First round of computed data for %o", this.inputPath); + await this.computedData.setupData(data, function (entry) { + return !this.isUsesStartsWith(entry, "collections."); - // TODO possible improvement here is to only process page.url, page.outputPath, permalink - // instead of only punting on things that rely on collections. - // let firstPhaseComputedData = ["page.url", "page.outputPath", ...this.getOrderFor("page.url"), ...this.getOrderFor("page.outputPath")]; - // return firstPhaseComputedData.indexOf(entry) > -1; - }); + // TODO possible improvement here is to only process page.url, page.outputPath, permalink + // instead of only punting on things that rely on collections. + // let firstPhaseComputedData = ["page.url", "page.outputPath", ...this.getOrderFor("page.url"), ...this.getOrderFor("page.outputPath")]; + // return firstPhaseComputedData.indexOf(entry) > -1; + }); + } else { + if (!("page" in data)) { + data.page = {}; + } + + data.page.url = await this.getOutputHref(data); + data.page.outputPath = await this.getOutputPath(data); + } // Deprecated, use eleventyComputed instead. if ("renderData" in data) { From 00c6ebada318a2c9a293469f24ea729e8bd9588a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 8 Sep 2020 16:27:25 -0500 Subject: [PATCH 257/746] Fixes #222 --- src/Engines/Liquid.js | 2 +- test/TemplateRenderLiquidTest.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index cfb6ed5dd..51363d686 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -49,7 +49,7 @@ class Liquid extends TemplateEngine { root: [super.getIncludesDir()], // overrides in compile with inputPath below extname: ".liquid", dynamicPartials: false, - strictFilters: false, + strictFilters: true, }; let options = Object.assign(defaults, this.liquidOptions || {}); diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index ea464bb14..9d74ece16 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -687,9 +687,10 @@ test.skip("Liquid Include Scope Leak", async (t) => { t.is(await fn({ test: 1 }), "

21

"); }); -// TODO this will change in 1.0 +// Note: this strictFilters default changed in 1.0 from false to true test("Liquid Missing Filter Issue #183 (no strictFilters)", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ strictFilters: false }); try { await tr._testRender("{{ 'test' | prefixWithZach }}", {}); @@ -699,9 +700,9 @@ test("Liquid Missing Filter Issue #183 (no strictFilters)", async (t) => { } }); +// Note: this strictFilters default changed in 1.0 from false to true test("Liquid Missing Filter Issue #183", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ strictFilters: true }); try { await tr._testRender("{{ 'test' | prefixWithZach }}", {}); From 2eca6f3c9dae12bedd25d8828f400e2d0a8c5ece Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Sep 2020 10:08:05 -0500 Subject: [PATCH 258/746] Fixes #1325 --- src/Eleventy.js | 4 ++-- src/EleventyExtensionMap.js | 9 +++++++++ src/EleventyFiles.js | 33 ++++++++++++++++++++------------ test/EleventyExtensionMapTest.js | 19 ++++++++++++++++++ test/EleventyTest.js | 1 + 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 8622d425d..0fccdf91f 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -590,13 +590,13 @@ Arguments: // Config file dependencies this.watchTargets.addDependencies( config.getLocalProjectConfigFile(), - filterOutGlobalDataFiles.bind(this) + filterOutGlobalDataFiles ); // Deps from Global Data (that aren’t in the global data directory, everything is watched there) this.watchTargets.addDependencies( this.templateData.getWatchPathCache(), - filterOutGlobalDataFiles.bind(this) + filterOutGlobalDataFiles ); this.watchTargets.addDependencies( diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index d26c0981e..b62d3c009 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -56,6 +56,15 @@ class EleventyExtensionMap { return files; } + isFullTemplateFilename(path) { + for (let extension of this.validTemplateLanguageKeys) { + if (path.endsWith(`.${extension}`)) { + return true; + } + } + return false; + } + getPassthroughCopyGlobs(inputDir) { return this._getGlobs(this.passthroughCopyKeys, inputDir); } diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 3e6f341fb..32eb43d9e 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -150,7 +150,7 @@ class EleventyFiles { if (this.passthroughAll) { this.templateGlobsWithIgnoresFromFiles = TemplateGlob.map([ - TemplateGlob.normalizePath(this.input, "/**") + TemplateGlob.normalizePath(this.input, "/**"), ]).concat(this.fileIgnores); } else { this.templateGlobsWithIgnoresFromFiles = this.templateGlobs.concat( @@ -201,7 +201,7 @@ class EleventyFiles { } } - ignores.forEach(function(path) { + ignores.forEach(function (path) { debug(`${ignoreFiles} ignoring: ${path}`); }); return ignores; @@ -213,10 +213,10 @@ class EleventyFiles { if (ignoreContent) { ignores = ignoreContent .split("\n") - .map(line => { + .map((line) => { return line.trim(); }) - .filter(line => { + .filter((line) => { if (line.charAt(0) === "!") { debug( ">>> When processing .gitignore/.eleventyignore, Eleventy does not currently support negative patterns but encountered one:" @@ -232,7 +232,7 @@ class EleventyFiles { line.length > 0 && line.charAt(0) !== "#" && line.charAt(0) !== "!" ); }) - .map(line => { + .map((line) => { let path = TemplateGlob.normalizePath(dir, "/", line); path = TemplatePath.addLeadingDotSlash( TemplatePath.relativePath(path) @@ -271,7 +271,7 @@ class EleventyFiles { if (this.config.eleventyignoreOverride !== false) { let eleventyIgnores = [ - TemplatePath.join(rootDirectory, ".eleventyignore") + TemplatePath.join(rootDirectory, ".eleventyignore"), ]; if (rootDirectory !== absoluteInputDir) { eleventyIgnores.push( @@ -307,7 +307,16 @@ class EleventyFiles { } getWatchPathCache() { - return this.pathCache; + // Issue #1325: make sure passthrough copy files are not included here + if (!this.pathCache) { + throw new Error( + "Watching requires `.getFiles()` to be called first in EleventyFiles" + ); + } + + return this.pathCache.filter((path) => + this.extensionMap.isFullTemplateFilename(path) + ); } async getFiles() { @@ -319,14 +328,14 @@ class EleventyFiles { let paths = TemplatePath.addLeadingDotSlashArray( await fastglob(globs, { caseSensitiveMatch: false, - dot: true + dot: true, }) ); bench.after(); if ("extensionMap" in this.config) { let extensions = this.config.extensionMap; - paths = paths.filter(function(path) { + paths = paths.filter(function (path) { for (let entry of extensions) { // TODO `.${extension}` ? if (path.endsWith(entry.extension) && entry.filter) { @@ -365,7 +374,7 @@ class EleventyFiles { await fastglob(globs, { ignore: ["**/node_modules/**"], caseSensitiveMatch: false, - dot: true + dot: true, }) ); bench.after(); @@ -375,7 +384,7 @@ class EleventyFiles { /* Ignored by `eleventy --watch` */ getGlobWatcherIgnores() { // convert to format without ! since they are passed in as a separate argument to glob watcher - return this.fileIgnores.map(ignore => + return this.fileIgnores.map((ignore) => TemplatePath.stripLeadingDotSlash(ignore.substr(1)) ); } @@ -403,7 +412,7 @@ class EleventyFiles { } _getIncludesAndDataDirIgnores() { - return this._getIncludesAndDataDirs().map(function(dir) { + return this._getIncludesAndDataDirs().map(function (dir) { return "!" + dir; }); } diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index d9d8993e4..5d694934a 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -143,3 +143,22 @@ test("getKey", (t) => { t.is(map.getKey("component"), undefined); t.is(map.getKey("component.js"), undefined); }); + +test("isFullTemplateFilename (not a passthrough copy extension)", (t) => { + let map = new EleventyExtensionMap([ + "liquid", + "njk", + "11ty.js", + "ejs", + "pug", + "js", + "css", + ]); + t.true(map.isFullTemplateFilename("template.liquid")); + t.true(map.isFullTemplateFilename("template.njk")); + t.true(map.isFullTemplateFilename("template.11ty.js")); + t.true(map.isFullTemplateFilename("template.ejs")); + t.true(map.isFullTemplateFilename("template.pug")); + t.false(map.isFullTemplateFilename("passthrough.js")); + t.false(map.isFullTemplateFilename("passthrough.css")); +}); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 4a7e753aa..fc4d4eb64 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -49,6 +49,7 @@ test("Eleventy file watching", async (t) => { elev.setFormats("njk"); await elev.init(); + await elev.eleventyFiles.getFiles(); await elev.initWatch(); t.deepEqual(await elev.getWatchedFiles(), [ "./test/stubs/**/*.njk", From a260da3629e0f0cf82a1e1f66c4e083bc6299399 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Sep 2020 10:22:58 -0500 Subject: [PATCH 259/746] Test for #1325 --- test/EleventyTest.js | 13 +++++++++++++ test/stubs-1325/test.11ty.js | 0 test/stubs-1325/test.js | 0 3 files changed, 13 insertions(+) create mode 100644 test/stubs-1325/test.11ty.js create mode 100644 test/stubs-1325/test.js diff --git a/test/EleventyTest.js b/test/EleventyTest.js index fc4d4eb64..69b45a8e3 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -64,6 +64,19 @@ test("Eleventy file watching", async (t) => { ]); }); +test("Eleventy file watching (don’t watch deps of passthrough copy .js files)", async (t) => { + let elev = new Eleventy("./test/stubs-1325", "./test/stubs-1325/_site"); + elev.setFormats("11ty.js,js"); + + await elev.init(); + await elev.eleventyFiles.getFiles(); + await elev.initWatch(); + + t.deepEqual(await elev.eleventyFiles.getWatchPathCache(), [ + "./test/stubs-1325/test.11ty.js", + ]); +}); + test("Eleventy file watching (no JS dependencies)", async (t) => { let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); elev.setFormats("njk"); diff --git a/test/stubs-1325/test.11ty.js b/test/stubs-1325/test.11ty.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/stubs-1325/test.js b/test/stubs-1325/test.js new file mode 100644 index 000000000..e69de29bb From a179b71fb620ed9fb1502659eed47c92de634f5e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 18 Sep 2020 22:49:15 -0500 Subject: [PATCH 260/746] Adds a `changedFiles` argument to the `beforeWatch` event to facilitate some incremental behavior. --- src/Eleventy.js | 4 ++-- src/EleventyWatch.js | 17 +++++++++++++++++ src/UserConfig.js | 2 ++ test/EleventyWatchTest.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 0fccdf91f..f39cda590 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -459,10 +459,10 @@ Arguments: return; } - this.config.events.emit("beforeWatch"); - this.watchManager.setBuildRunning(); + this.config.events.emit("beforeWatch", this.watchManager.getActiveQueue()); + // reset and reload global configuration :O if (this.watchManager.hasQueuedFile(config.getLocalProjectConfigFile())) { this.resetConfig(); diff --git a/src/EleventyWatch.js b/src/EleventyWatch.js index 245319ded..537b360dc 100755 --- a/src/EleventyWatch.js +++ b/src/EleventyWatch.js @@ -36,6 +36,19 @@ class EleventyWatch { return this.activeQueue[0]; } + /* Returns the changed files currently being operated on in the current `watch` build + * Works with or without incremental (though in incremental only one file per time will be processed) + */ + getActiveQueue() { + if (!this.isActive) { + return []; + } else if (this.incremental) { + return [this.activeQueue[0]]; + } + + return this.activeQueue; + } + _queueMatches(file) { let filterCallback; if (typeof file === "function") { @@ -80,6 +93,10 @@ class EleventyWatch { return this.pendingQueue.length; } + getPendingQueue() { + return this.pendingQueue; + } + getActiveQueueSize() { return this.activeQueue.length; } diff --git a/src/UserConfig.js b/src/UserConfig.js index fff80a4e2..5873135c1 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -75,6 +75,8 @@ class UserConfig { } } + // Duplicate event bindings are avoided with the `reset` method above. + // A new EventEmitter instance is created when the config is reset. on(eventName, callback) { return this.events.on(eventName, callback); } diff --git a/test/EleventyWatchTest.js b/test/EleventyWatchTest.js index 8e9797e15..895ba233d 100644 --- a/test/EleventyWatchTest.js +++ b/test/EleventyWatchTest.js @@ -19,21 +19,26 @@ test("Incremental", (t) => { watch.incremental = true; t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); + t.deepEqual(watch.getPendingQueue(), []); }); test("Incremental queue 2", (t) => { @@ -43,22 +48,27 @@ test("Incremental queue 2", (t) => { watch.incremental = true; t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); watch.addToPendingQueue("test2.md"); t.is(watch.getPendingQueueSize(), 2); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), ["./test2.md"]); + t.deepEqual(watch.getActiveQueue(), []); }); test("Incremental add while active", (t) => { @@ -68,26 +78,32 @@ test("Incremental add while active", (t) => { watch.incremental = true; t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.addToPendingQueue("test2.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), ["./test2.md"]); + t.deepEqual(watch.getActiveQueue(), []); }); test("Non-incremental", (t) => { @@ -96,21 +112,25 @@ test("Non-incremental", (t) => { t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); }); test("Non-incremental queue 2", (t) => { @@ -119,22 +139,27 @@ test("Non-incremental queue 2", (t) => { t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); watch.addToPendingQueue("test2.md"); t.is(watch.getPendingQueueSize(), 2); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 2); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md", "./test2.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), []); + t.deepEqual(watch.getActiveQueue(), []); }); test("Non-incremental add while active", (t) => { @@ -148,21 +173,26 @@ test("Non-incremental add while active", (t) => { t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), ["./test.md"]); + t.deepEqual(watch.getActiveQueue(), []); }); test("Active queue tests", (t) => { From 5d763c5aa8b510f3835df9111f5a05a9a31b1f5e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 18 Sep 2020 22:53:04 -0500 Subject: [PATCH 261/746] Test to make sure custom file extensions only init once. --- src/TemplateData.js | 14 ++++++------- src/TemplateRender.js | 5 +++-- test/TemplateEngineManagerTest.js | 33 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 986e63e5a..5e1400169 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -154,12 +154,12 @@ class TemplateData { let paths = [ `${dir}/**/*.json`, // covers .11tydata.json too `${dir}/**/*${this.config.jsDataFileSuffix}.cjs`, - `${dir}/**/*${this.config.jsDataFileSuffix}.js` + `${dir}/**/*${this.config.jsDataFileSuffix}.js`, ]; if (this.hasUserDataExtensions()) { let userPaths = this.getUserDataExtensions().map( - extension => `${dir}/**/*.${extension}` // covers .11tydata.{extension} too + (extension) => `${dir}/**/*.${extension}` // covers .11tydata.{extension} too ); paths = userPaths.concat(paths); } @@ -170,7 +170,7 @@ class TemplateData { async getTemplateJavaScriptDataFileGlob() { let dir = await this.getInputDir(); return TemplatePath.addLeadingDotSlashArray([ - `${dir}/**/*${this.config.jsDataFileSuffix}.js` + `${dir}/**/*${this.config.jsDataFileSuffix}.js`, ]); } @@ -206,7 +206,7 @@ class TemplateData { fsBench.before(); let paths = fastglob.sync(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, - dot: true + dot: true, }); fsBench.after(); @@ -316,7 +316,7 @@ class TemplateData { } // Filter out files we know don't exist to avoid overhead for checking - localDataPaths = localDataPaths.filter(path => { + localDataPaths = localDataPaths.filter((path) => { return this._fsExistsCache.exists(path); }); @@ -415,11 +415,11 @@ class TemplateData { } } + // ignoreProcessing = false for global data files + // ignoreProcessing = true for local data files async getDataValue(path, rawImports, ignoreProcessing) { let extension = TemplatePath.getExtension(path); - // ignoreProcessing = false for global data files - // ignoreProcessing = true for local data files if ( extension === "js" || extension === "cjs" || diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 1f89aa1f1..fc341c820 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -46,6 +46,7 @@ class TemplateRender { return this._extensionMap; } + // Runs once per template init(engineNameOrPath) { this.extensionMap.config = this.config; this._engineName = this.extensionMap.getKey(engineNameOrPath); @@ -89,10 +90,10 @@ class TemplateRender { let usingMarkdown = false; (engineName || "") .split(",") - .map(name => { + .map((name) => { return name.toLowerCase().trim(); }) - .forEach(name => { + .forEach((name) => { // html is assumed (treated as plaintext by the system) if (!name || name === "html") { return; diff --git a/test/TemplateEngineManagerTest.js b/test/TemplateEngineManagerTest.js index 4986eccc0..780fe3c09 100644 --- a/test/TemplateEngineManagerTest.js +++ b/test/TemplateEngineManagerTest.js @@ -35,6 +35,39 @@ test("Supported custom engine", async (t) => { t.is(await fn({ author: "zach" }), "

This is plaintext

"); }); +test("Custom engine with custom init", async (t) => { + let initCount = 0; + let compileCount = 0; + let tem = new TemplateEngineManager(); + tem.config = Object.assign({}, config); + tem.config.extensionMap.add({ + extension: "custom1", + key: "custom1", + init: async function () { + // do custom things, but only once + initCount++; + }, + compile: function (str, inputPath) { + compileCount++; + return () => str; + }, + }); + + t.truthy(tem.hasEngine("custom1")); + let engine = tem.getEngine("custom1"); + let fn = await engine.compile("

This is plaintext

"); + t.is(await fn({}), "

This is plaintext

"); + + let engine2 = tem.getEngine("custom1"); + t.is(engine, engine2); + + let fn2 = await engine2.compile("

This is plaintext

"); + t.is(await fn2({}), "

This is plaintext

"); + + t.is(initCount, 1, "Should have only run the init callback once"); + t.is(compileCount, 2, "Should have only run the compile callback twice"); +}); + test("Handlebars Helpers", async (t) => { let tem = new TemplateEngineManager(); let engine = tem.getEngine("hbs"); From 330191c10b9ab4b93a3abcf6406bbc350a47aa7d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 18 Sep 2020 23:08:58 -0500 Subject: [PATCH 262/746] Fixes https://github.com/11ty/eleventy/issues/174 --- src/defaultConfig.js | 2 +- test/TemplateDataTest.js | 17 +++++++++++++++++ test/UserDataExtensionsTest.js | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/defaultConfig.js b/src/defaultConfig.js index 0828cd2cb..73adf8ad7 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -34,7 +34,7 @@ module.exports = function (config) { pathPrefix: "/", markdownTemplateEngine: "liquid", htmlTemplateEngine: "liquid", - dataTemplateEngine: "liquid", + dataTemplateEngine: false, // change in 1.0 passthroughFileCopy: true, htmlOutputSuffix: "-o", jsDataFileSuffix: ".11tydata", diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 0b3dad33c..bcfc4d4ed 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -13,6 +13,7 @@ test("Create", async (t) => { test("getData()", async (t) => { let dataObj = new TemplateData("./test/stubs/"); + dataObj.setDataTemplateEngine("liquid"); t.is(dataObj.getData().toString(), "[object Promise]"); @@ -30,6 +31,16 @@ test("getData()", async (t) => { ); }); +test("getData() use default processing (false)", async (t) => { + let dataObj = new TemplateData("./test/stubs/"); + let data = await dataObj.getData(); + t.is( + data.globalData.datakey2, + "{{pkg.name}}", + `variables should not resolve` + ); +}); + test("Data dir does not exist", async (t) => { await t.throwsAsync(async () => { let dataObj = new TemplateData("./test/thisdirectorydoesnotexist"); @@ -39,6 +50,8 @@ test("Data dir does not exist", async (t) => { test("Add local data", async (t) => { let dataObj = new TemplateData("./test/stubs/"); + dataObj.setDataTemplateEngine("liquid"); + let data = await dataObj.getData(); t.is(data.globalData.datakey1, "datavalue1"); @@ -72,6 +85,8 @@ test("Get local data async JS", async (t) => { test("addLocalData() doesn’t exist but doesn’t fail (template file does exist)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); + dataObj.setDataTemplateEngine("liquid"); + let data = await dataObj.getData(); let beforeDataKeyCount = Object.keys(data); @@ -86,6 +101,8 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does exis test("addLocalData() doesn’t exist but doesn’t fail (template file does not exist)", async (t) => { let dataObj = new TemplateData("./test/stubs/"); + dataObj.setDataTemplateEngine("liquid"); + let data = await dataObj.getData(); let beforeDataKeyCount = Object.keys(data); diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index d51f1b699..f4e2343a7 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -12,6 +12,7 @@ function injectDataExtensions(dataObj) { test("Local data", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); + dataObj.setDataTemplateEngine("liquid"); let data = await dataObj.getData(); @@ -73,8 +74,8 @@ test("Local files", async (t) => { test("Global data", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); - injectDataExtensions(dataObj); + dataObj.setDataTemplateEngine("liquid"); t.deepEqual(await dataObj.getGlobalDataGlob(), [ "./test/stubs-630/_data/**/*.(nosj|yaml|json|cjs|js)", From a13d53de99cc814b0e2becd82cdedfe076e31168 Mon Sep 17 00:00:00 2001 From: Binyamin Aron Green Date: Tue, 13 Oct 2020 08:44:21 -0400 Subject: [PATCH 263/746] Create config.yml --- .github/ISSUE_TEMPLATE/config.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..c0ad3fe7b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: + - name: Community + url: https://discord.gg/GBkBy9u + about: Ask the community on Discord From a6f78d199467c4819694a1151d3dae8000f90c7f Mon Sep 17 00:00:00 2001 From: Binyamin Aron Green Date: Thu, 15 Oct 2020 15:54:47 -0400 Subject: [PATCH 264/746] Add github discussions link --- .github/ISSUE_TEMPLATE/config.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c0ad3fe7b..2bd8eeb4b 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,7 @@ contact_links: - - name: Community + - name: Discord Community url: https://discord.gg/GBkBy9u about: Ask the community on Discord + - name: GitHub Discussions + url: https://github.com/11ty/eleventy/discussions/ + about: If you've got a question, start a discussion From 878425b035e082e152c0e53963aa6788c3fcb0db Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 16 Oct 2020 14:30:00 -0500 Subject: [PATCH 265/746] Fixes #1454. --- src/EleventyServe.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 94349a98c..9de9a85d2 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -1,4 +1,5 @@ const fs = require("fs-extra"); +const path = require("path"); const TemplatePath = require("./TemplatePath"); const config = require("./Config"); @@ -19,7 +20,12 @@ class EleventyServe { } getPathPrefix() { - return this.config.pathPrefix || "/"; + let cfgPrefix = this.config.pathPrefix; + if (cfgPrefix) { + // add leading / (for browsersync), see #1454 + return path.join("/", cfgPrefix); + } + return "/"; } getRedirectDir(dirName) { @@ -41,7 +47,7 @@ class EleventyServe { // TODO customize this in Configuration API? let serverConfig = { - baseDir: this.outputDir + baseDir: this.outputDir, }; let redirectDirName = this.getRedirectDirOverride(); @@ -68,7 +74,7 @@ class EleventyServe { watch: false, open: false, notify: false, - index: "index.html" + index: "index.html", }, this.config.browserSyncConfig ); @@ -78,7 +84,7 @@ class EleventyServe { if (dirName && dirName !== "/") { let savedPathFilename = this.getRedirectFilename(dirName); - setTimeout(function() { + setTimeout(function () { if (!fs.existsSync(savedPathFilename)) { debug(`Cleanup redirect: Could not find ${savedPathFilename}`); return; @@ -94,7 +100,7 @@ class EleventyServe { return; } - fs.unlink(savedPathFilename, err => { + fs.unlink(savedPathFilename, (err) => { if (!err) { debug(`Cleanup redirect: Deleted ${savedPathFilename}`); } @@ -141,7 +147,9 @@ class EleventyServe { } this.cleanupRedirect(this.savedPathPrefix); - this.server.init(this.getOptions(port)); + + let options = this.getOptions(port); + this.server.init(options); // this needs to happen after `.getOptions` this.savedPathPrefix = pathPrefix; From e9181d3a00995f95e2f9eb0f30e8448f90921fe4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 22 Oct 2020 11:39:34 -0500 Subject: [PATCH 266/746] Adds afterBuild/beforeBuild events, adds argument to beforeWatch event to pass in the files that changed. --- package.json | 2 +- src/Eleventy.js | 7 +++-- src/EleventyWatch.js | 19 +++++++++++- src/UserConfig.js | 10 +++++-- test/EleventyWatchTest.js | 62 +++++++++++++++++++++++++++++---------- 5 files changed, 77 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 0f908df7d..86a657e8c 100755 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", - "browser-sync": "^2.26.7", + "browser-sync": "^2.26.13", "chalk": "^3.0.0", "chokidar": "^3.4.0", "debug": "^4.1.1", diff --git a/src/Eleventy.js b/src/Eleventy.js index 719fa43ea..007d58660 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -457,10 +457,10 @@ Arguments: return; } - this.config.events.emit("beforeWatch"); - this.watchManager.setBuildRunning(); + this.config.events.emit("beforeWatch", this.watchManager.getActiveQueue()); + // reset and reload global configuration :O if (this.watchManager.hasQueuedFile(config.getLocalProjectConfigFile())) { this.resetConfig(); @@ -735,10 +735,13 @@ Arguments: EleventyErrorHandler.logger = this.logger; } + this.config.events.emit("beforeBuild"); + try { let promise = this.writer.write(); ret = await promise; + this.config.events.emit("afterBuild"); } catch (e) { EleventyErrorHandler.initialMessage( "Problem writing Eleventy templates", diff --git a/src/EleventyWatch.js b/src/EleventyWatch.js index b1e073eac..442fa8ba7 100644 --- a/src/EleventyWatch.js +++ b/src/EleventyWatch.js @@ -36,12 +36,25 @@ class EleventyWatch { return this.activeQueue[0]; } + /* Returns the changed files currently being operated on in the current `watch` build + * Works with or without incremental (though in incremental only one file per time will be processed) + */ + getActiveQueue() { + if (!this.isActive) { + return []; + } else if (this.incremental) { + return [this.activeQueue[0]]; + } + + return this.activeQueue; + } + _queueMatches(file) { let filterCallback; if (typeof file === "function") { filterCallback = file; } else { - filterCallback = path => path === file; + filterCallback = (path) => path === file; } return this.activeQueue.filter(filterCallback); @@ -80,6 +93,10 @@ class EleventyWatch { return this.pendingQueue.length; } + getPendingQueue() { + return this.pendingQueue; + } + getActiveQueueSize() { return this.activeQueue.length; } diff --git a/src/UserConfig.js b/src/UserConfig.js index 9b9f1259b..0eb08c1a3 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -74,6 +74,8 @@ class UserConfig { } } + // Duplicate event bindings are avoided with the `reset` method above. + // A new EventEmitter instance is created when the config is reset. on(eventName, callback) { return this.events.on(eventName, callback); } @@ -325,7 +327,9 @@ class UserConfig { _normalizeTemplateFormats(templateFormats) { if (typeof templateFormats === "string") { - templateFormats = templateFormats.split(",").map(format => format.trim()); + templateFormats = templateFormats + .split(",") + .map((format) => format.trim()); } return templateFormats; } @@ -629,7 +633,7 @@ class UserConfig { Object.assign( { key: fileExtension, - extension: fileExtension + extension: fileExtension, }, options ) @@ -680,7 +684,7 @@ class UserConfig { dataExtensions: this.dataExtensions, extensionMap: this.extensionMap, quietMode: this.quietMode, - events: this.events + events: this.events, }; } } diff --git a/test/EleventyWatchTest.js b/test/EleventyWatchTest.js index e7f26cd7b..0b20a5bd6 100644 --- a/test/EleventyWatchTest.js +++ b/test/EleventyWatchTest.js @@ -1,7 +1,7 @@ import test from "ava"; import EleventyWatch from "../src/EleventyWatch"; -test("Standard", t => { +test("Standard", (t) => { let watch = new EleventyWatch(); t.is(watch.isBuildRunning(), false); @@ -12,132 +12,157 @@ test("Standard", t => { t.is(watch.isBuildRunning(), false); }); -test("Incremental", t => { +test("Incremental", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); watch.incremental = true; t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); + t.deepEqual(watch.getPendingQueue(), []); }); -test("Incremental queue 2", t => { +test("Incremental queue 2", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); watch.incremental = true; t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); watch.addToPendingQueue("test2.md"); t.is(watch.getPendingQueueSize(), 2); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), ["./test2.md"]); + t.deepEqual(watch.getActiveQueue(), []); }); -test("Incremental add while active", t => { +test("Incremental add while active", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); watch.incremental = true; t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.addToPendingQueue("test2.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), "./test.md"); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), ["./test2.md"]); + t.deepEqual(watch.getActiveQueue(), []); }); -test("Non-incremental", t => { +test("Non-incremental", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); }); -test("Non-incremental queue 2", t => { +test("Non-incremental queue 2", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.addToPendingQueue("test.md"); watch.addToPendingQueue("test2.md"); t.is(watch.getPendingQueueSize(), 2); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 2); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md", "./test2.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), []); + t.deepEqual(watch.getActiveQueue(), []); }); -test("Non-incremental add while active", t => { +test("Non-incremental add while active", (t) => { let watch = new EleventyWatch(); t.is(watch.getIncrementalFile(), false); @@ -148,42 +173,47 @@ test("Non-incremental add while active", t => { t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), []); watch.setBuildRunning(); t.is(watch.getPendingQueueSize(), 0); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.addToPendingQueue("test.md"); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 1); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getActiveQueue(), ["./test.md"]); watch.setBuildFinished(); t.is(watch.getPendingQueueSize(), 1); t.is(watch.getActiveQueueSize(), 0); t.is(watch.getIncrementalFile(), false); + t.deepEqual(watch.getPendingQueue(), ["./test.md"]); + t.deepEqual(watch.getActiveQueue(), []); }); -test("Active queue tests", t => { +test("Active queue tests", (t) => { let watch = new EleventyWatch(); watch.addToPendingQueue("test.md"); watch.addToPendingQueue("test2.md"); watch.addToPendingQueue("test.css"); t.is( - watch.hasAllQueueFiles(path => path.startsWith("./test")), + watch.hasAllQueueFiles((path) => path.startsWith("./test")), false ); watch.setBuildRunning(); t.is(watch.hasAllQueueFiles("slkdjflkjsdlkfj"), false); t.is( - watch.hasAllQueueFiles(path => path.startsWith("./test")), + watch.hasAllQueueFiles((path) => path.startsWith("./test")), true ); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), false ); @@ -192,31 +222,31 @@ test("Active queue tests", t => { watch.setBuildFinished(); t.is( - watch.hasAllQueueFiles(path => path.startsWith("./test")), + watch.hasAllQueueFiles((path) => path.startsWith("./test")), false ); }); -test("Active queue tests, all CSS files", t => { +test("Active queue tests, all CSS files", (t) => { let watch = new EleventyWatch(); watch.addToPendingQueue("test.css"); watch.addToPendingQueue("test2.css"); watch.addToPendingQueue("test3.css"); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), false ); watch.setBuildRunning(); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), true ); watch.setBuildFinished(); t.is( - watch.hasAllQueueFiles(path => path.endsWith(".css")), + watch.hasAllQueueFiles((path) => path.endsWith(".css")), false ); }); From 094c9851d98d77fdd6723673c71cff32de9a7f0a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 22 Oct 2020 11:40:08 -0500 Subject: [PATCH 267/746] v0.11.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 86a657e8c..0e42b979e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.11.0", + "version": "0.11.1", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 5480a04ea5698d24798373b292c8cd38141417b0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 25 Oct 2020 21:14:47 -0500 Subject: [PATCH 268/746] Nunjucks aggressively cached include content, which is a problem when it might change --- src/Engines/Nunjucks.js | 10 ++-- test/TemplateTest.js | 53 +++++++++++++++++++ test/TemplateWriterTest.js | 4 +- .../_includes/include-script-1.js | 1 + .../_includes/include-script-2.js | 1 + .../_includes/layout.liquid | 1 + test/stubs-layout-cache/_includes/layout.njk | 1 + test/stubs-layout-cache/test.liquid | 4 ++ test/stubs-layout-cache/test.njk | 4 ++ 9 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 test/stubs-layout-cache/_includes/include-script-1.js create mode 100644 test/stubs-layout-cache/_includes/include-script-2.js create mode 100644 test/stubs-layout-cache/_includes/layout.liquid create mode 100644 test/stubs-layout-cache/_includes/layout.njk create mode 100644 test/stubs-layout-cache/test.liquid create mode 100644 test/stubs-layout-cache/test.njk diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 264aad81d..34b685e7b 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -19,10 +19,12 @@ class Nunjucks extends TemplateEngine { this.njkEnv = env || new NunjucksLib.Environment( - new NunjucksLib.FileSystemLoader([ - super.getIncludesDir(), - TemplatePath.getWorkingDir(), - ]) + new NunjucksLib.FileSystemLoader( + [super.getIncludesDir(), TemplatePath.getWorkingDir()], + { + noCache: true, + } + ) ); this.setEngineLib(this.njkEnv); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index e320c2007..a5ee43363 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1,5 +1,6 @@ const test = require("ava"); const fs = require("fs-extra"); +const fsp = require("fs").promises; const pretty = require("pretty"); const Template = require("../src/Template"); const TemplateData = require("../src/TemplateData"); @@ -2037,3 +2038,55 @@ test("Engine Singletons", async (t) => { t.deepEqual(tmpl1.engine, tmpl2.engine); }); + +test("Make sure layout cache takes new changes during watch (nunjucks)", async (t) => { + await fsp.writeFile( + "./test/stubs-layout-cache/_includes/include-script-1.js", + `alert("hi");`, + { encoding: "utf8" } + ); + + let tmpl = getNewTemplate( + "./test/stubs-layout-cache/test.njk", + "./test/stubs-layout-cache/", + "./dist" + ); + + let data = await tmpl.getData(); + + t.is((await tmpl.render(data)).trim(), ''); + + await fsp.writeFile( + "./test/stubs-layout-cache/_includes/include-script-1.js", + `alert("bye");`, + { encoding: "utf8" } + ); + + t.is((await tmpl.render(data)).trim(), ''); +}); + +test("Make sure layout cache takes new changes during watch (liquid)", async (t) => { + await fsp.writeFile( + "./test/stubs-layout-cache/_includes/include-script-2.js", + `alert("hi");`, + { encoding: "utf8" } + ); + + let tmpl = getNewTemplate( + "./test/stubs-layout-cache/test.liquid", + "./test/stubs-layout-cache/", + "./dist" + ); + + let data = await tmpl.getData(); + + t.is((await tmpl.render(data)).trim(), ''); + + await fsp.writeFile( + "./test/stubs-layout-cache/_includes/include-script-2.js", + `alert("bye");`, + { encoding: "utf8" } + ); + + t.is((await tmpl.render(data)).trim(), ''); +}); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index e6e28bb80..8693b913c 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -6,8 +6,8 @@ const parsePath = require("parse-filepath"); const EleventyFiles = require("../src/EleventyFiles"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const TemplateWriter = require("../src/TemplateWriter"); -// Not sure why but this import up `ava` and _createTemplate 👀 -// import Template from "../src/Template"; +// Not sure why but this required `ava` and _createTemplate 👀 +// const Template = require("../src/Template"); const eleventyConfig = require("../src/EleventyConfig"); const normalizeNewLines = require("./Util/normalizeNewLines"); diff --git a/test/stubs-layout-cache/_includes/include-script-1.js b/test/stubs-layout-cache/_includes/include-script-1.js new file mode 100644 index 000000000..f3a5da377 --- /dev/null +++ b/test/stubs-layout-cache/_includes/include-script-1.js @@ -0,0 +1 @@ +alert("bye"); diff --git a/test/stubs-layout-cache/_includes/include-script-2.js b/test/stubs-layout-cache/_includes/include-script-2.js new file mode 100644 index 000000000..f3a5da377 --- /dev/null +++ b/test/stubs-layout-cache/_includes/include-script-2.js @@ -0,0 +1 @@ +alert("bye"); diff --git a/test/stubs-layout-cache/_includes/layout.liquid b/test/stubs-layout-cache/_includes/layout.liquid new file mode 100644 index 000000000..33be0009f --- /dev/null +++ b/test/stubs-layout-cache/_includes/layout.liquid @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/stubs-layout-cache/_includes/layout.njk b/test/stubs-layout-cache/_includes/layout.njk new file mode 100644 index 000000000..fa89095aa --- /dev/null +++ b/test/stubs-layout-cache/_includes/layout.njk @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/stubs-layout-cache/test.liquid b/test/stubs-layout-cache/test.liquid new file mode 100644 index 000000000..03ead8d15 --- /dev/null +++ b/test/stubs-layout-cache/test.liquid @@ -0,0 +1,4 @@ +--- +layout: "layout.liquid" +--- +Content \ No newline at end of file diff --git a/test/stubs-layout-cache/test.njk b/test/stubs-layout-cache/test.njk new file mode 100644 index 000000000..84b369495 --- /dev/null +++ b/test/stubs-layout-cache/test.njk @@ -0,0 +1,4 @@ +--- +layout: "layout.njk" +--- +Content \ No newline at end of file From 2c837470ac95b7c6bc0bcc8568e17b7cd6c2f2a2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 25 Oct 2020 21:15:43 -0500 Subject: [PATCH 269/746] =?UTF-8?q?More=20ignores=20on=20test=20stubs=20fi?= =?UTF-8?q?les=20on=20test=20watcher.=20Also=20don=E2=80=99t=20include=20n?= =?UTF-8?q?ew=20lines=20automatically=20on=20test=20stubs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 5 ++++- docs/meta-release.md | 1 - package.json | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index cd3721ddd..98f9f8d3d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,4 +9,7 @@ trim_trailing_whitespace = true charset = utf-8 [*.js] -insert_final_newline = true \ No newline at end of file +insert_final_newline = true + +[/test/stubs*/**] +insert_final_newline = unset \ No newline at end of file diff --git a/docs/meta-release.md b/docs/meta-release.md index 837224c6f..d60f23d9c 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -26,7 +26,6 @@ ## If branch docs do not exist -1. Make sure `localDev: false` in `config.js` 1. Check in a new `11ty-website` site with updated `package.json` version. 1. Add version to 11ty-website `versions.json` 1. Commit it diff --git a/package.json b/package.json index 777701259..7d60e124a 100755 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "./test/*.js" ], "ignoredByWatcher": [ - "./test/stubs/**/*" + "./test/stubs*/**/*" ] }, "lint-staged": { @@ -129,4 +129,4 @@ "pre-push": "npm run test" } } -} \ No newline at end of file +} From 92bf9ba112637eb50e03c9196bd7c85ead470260 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 25 Oct 2020 22:10:19 -0500 Subject: [PATCH 270/746] Remove generated scripts from stubs --- .gitignore | 2 ++ test/stubs-layout-cache/_includes/include-script-1.js | 1 - test/stubs-layout-cache/_includes/include-script-2.js | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 test/stubs-layout-cache/_includes/include-script-1.js delete mode 100644 test/stubs-layout-cache/_includes/include-script-2.js diff --git a/.gitignore b/.gitignore index 8c3a0ad42..8206118a8 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ api-docs/ _site/ package-lock.json + +test/stubs-layout-cache/_includes/*.js \ No newline at end of file diff --git a/test/stubs-layout-cache/_includes/include-script-1.js b/test/stubs-layout-cache/_includes/include-script-1.js deleted file mode 100644 index f3a5da377..000000000 --- a/test/stubs-layout-cache/_includes/include-script-1.js +++ /dev/null @@ -1 +0,0 @@ -alert("bye"); diff --git a/test/stubs-layout-cache/_includes/include-script-2.js b/test/stubs-layout-cache/_includes/include-script-2.js deleted file mode 100644 index f3a5da377..000000000 --- a/test/stubs-layout-cache/_includes/include-script-2.js +++ /dev/null @@ -1 +0,0 @@ -alert("bye"); From e5cecac6d26205b73f8464d27daf0f32abeebde8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 25 Oct 2020 22:10:47 -0500 Subject: [PATCH 271/746] Update dependencies, fixes #669 again --- package.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 7d60e124a..9b435b477 100755 --- a/package.json +++ b/package.json @@ -73,17 +73,17 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", - "ava": "^3.12.1", - "husky": "^4.2.5", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.4", + "ava": "^3.13.0", + "husky": "^4.3.0", "ink-docstrap": "1.3.2", "js-yaml": "^3.14.0", - "jsdoc": "3.6.5", - "lint-staged": "^10.3.0", - "markdown-it-emoji": "^1.4.0", + "jsdoc": "3.6.6", + "lint-staged": "^10.4.2", + "markdown-it-emoji": "^2.0.0", "node-sass": "^4.14.1", "nyc": "^15.1.0", - "prettier": "^2.1.1", + "prettier": "^2.1.2", "rimraf": "^3.0.2", "toml": "^3.0.0", "viperhtml": "^2.17.1", @@ -92,10 +92,10 @@ }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", - "browser-sync": "^2.26.12", + "browser-sync": "^2.26.13", "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "debug": "^4.1.1", + "chokidar": "^3.4.3", + "debug": "^4.2.0", "dependency-graph": "^0.9.0", "ejs": "^3.1.5", "fast-glob": "^3.2.4", @@ -103,13 +103,13 @@ "gray-matter": "^4.0.2", "hamljs": "^0.6.2", "handlebars": "^4.7.6", - "liquidjs": "^9.15.0", + "liquidjs": "^9.16.1", "lodash": "^4.17.20", "luxon": "^1.25.0", - "markdown-it": "^11.0.0", + "markdown-it": "^12.0.2", "minimist": "^1.2.5", "moo": "^0.5.1", - "multimatch": "^4.0.0", + "multimatch": "^5.0.0", "mustache": "^4.0.1", "normalize-path": "^3.0.0", "nunjucks": "^3.2.2", From 23e451496c46680ed2f229400f84411ef895ee3f Mon Sep 17 00:00:00 2001 From: Valtteri Laitinen Date: Mon, 26 Oct 2020 11:25:43 +0200 Subject: [PATCH 272/746] Add Node 15 to CI --- .github/workflows/ci.yml | 2 +- .travis.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6590a7dec..52e09b40f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - node: ["10", "12", "14"] + node: ["10", "12", "14", "15"] name: Node.js ${{ matrix.node }} on ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index e1ce39e9d..3a49ca63a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ node_js: - 10 - 12 - 14 + - 15 before_script: - npm install script: npm run test From a5ab248c13a82adc611fa556446af50f56b9c49a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 27 Oct 2020 10:51:46 -0500 Subject: [PATCH 273/746] Fixes #1478. --- src/Template.js | 7 ++++++- src/TemplateContent.js | 6 +++--- src/TemplateRender.js | 30 +++++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/Template.js b/src/Template.js index b81eee44a..88ace2b00 100755 --- a/src/Template.js +++ b/src/Template.js @@ -578,8 +578,13 @@ class Template extends TemplateContent { }; } + let engineList = this.templateRender.getReadableEnginesListDifferingFromFileExtension(); if (this.isVerbose) { - console.log(`${lang.start} ${outputPath} from ${this.inputPath}.`); + console.log( + `${lang.start} ${outputPath} from ${this.inputPath}${ + engineList ? ` (${engineList})` : "" + }` + ); } else { debug(`${lang.start} %o from %o.`, outputPath, this.inputPath); } diff --git a/src/TemplateContent.js b/src/TemplateContent.js index c14c71b98..7fefe5810 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -112,7 +112,7 @@ class TemplateContent { this.frontMatter = { data: {}, content: "", - excerpt: "" + excerpt: "", }; } } @@ -224,7 +224,7 @@ class TemplateContent { let res; cache.set( key, - new Promise(resolve => { + new Promise((resolve) => { res = resolve; }) ); @@ -261,7 +261,7 @@ class TemplateContent { if (EleventyErrorUtil.isPrematureTemplateContentError(e)) { throw e; } else { - let engine = this.templateRender.getEnginesStr(); + let engine = this.templateRender.getReadableEnginesList(); debug( `Having trouble rendering ${engine} template ${this.inputPath}: %O`, str diff --git a/src/TemplateRender.js b/src/TemplateRender.js index fc341c820..b49d0b09f 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -127,12 +127,30 @@ class TemplateRender { return engines; } - // used for error logging. - getEnginesStr() { - if (this.engineName === "md" && this.useMarkdown) { - return this.parseMarkdownWith + " (and markdown)"; + // used for error logging and console output. + getReadableEnginesList() { + return ( + this.getReadableEnginesListDifferingFromFileExtension() || this.engineName + ); + } + + getReadableEnginesListDifferingFromFileExtension() { + if ( + this.engineName === "md" && + this.useMarkdown && + this.parseMarkdownWith + ) { + return this.parseMarkdownWith; + } + if (this.engineName === "html" && this.parseHtmlWith) { + return this.parseHtmlWith; + } + + // templateEngineOverride in play and template language differs from file extension + let keyFromFilename = this.extensionMap.getKey(this.engineNameOrPath); + if (keyFromFilename !== this.engineName) { + return this.engineName; } - return this.engineName; } setEngineOverride(engineName, bypassMarkdown) { @@ -182,10 +200,12 @@ class TemplateRender { this.useMarkdown = !!useMarkdown; } + // this is only called for templateEngineOverride setMarkdownEngine(markdownEngine) { this.parseMarkdownWith = markdownEngine; } + // this is only called for templateEngineOverride setHtmlEngine(htmlEngineName) { this.parseHtmlWith = htmlEngineName; } From 897f7152dc7b88f531cf1191a10e84e7f062b8d5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 10:30:56 -0500 Subject: [PATCH 274/746] Fixes #1485 --- src/Eleventy.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index f39cda590..2de5c78c4 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -479,10 +479,14 @@ Arguments: incrementalFile, this.eleventyFiles.getIncludesDir() ); + let isLayout = TemplatePath.startsWithSubPath( + incrementalFile, + this.eleventyFiles.getLayoutsDir() + ); let isJSDependency = this.watchTargets.isJavaScriptDependency( incrementalFile ); - if (!isInclude && !isJSDependency) { + if (!isInclude && !isLayout && !isJSDependency) { this.writer.setIncrementalFile(incrementalFile); } } From e9232847a6b8a02d10a82c9876578ab37b65d53c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 10:52:25 -0500 Subject: [PATCH 275/746] Remove TODO comment from https://github.com/11ty/eleventy/pull/998#issuecomment-719635170 --- src/Template.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Template.js b/src/Template.js index 88ace2b00..6274038bb 100755 --- a/src/Template.js +++ b/src/Template.js @@ -463,7 +463,6 @@ class Template extends TemplateContent { } async getTemplates(data) { - // TODO cache this let results = []; if (!Pagination.hasPagination(data)) { From 71f5943f1fa826a2b6d589cc1f49676d23b88afe Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 14:08:36 -0500 Subject: [PATCH 276/746] Finally remove old `filters` (was renamed to transforms in Eleventy 0.3.3). Adds an error message if the `filters` key still exists in the configuration return object. Use the addTransform method instead. Helps with #1479. Fixes #789. --- src/Template.js | 49 +++++++++++++++++++++++++++++++------- src/TemplateConfig.js | 11 ++++++++- src/TemplateWriter.js | 6 ++--- src/UserConfig.js | 11 ++++----- src/defaultConfig.js | 2 -- test/TemplateConfigTest.js | 4 ++-- test/TemplateMapTest.js | 2 +- test/TemplateTest.js | 14 +++++------ test/stubs/config.js | 16 ++++++------- 9 files changed, 75 insertions(+), 40 deletions(-) diff --git a/src/Template.js b/src/Template.js index 084333ccf..dc9147eb0 100755 --- a/src/Template.js +++ b/src/Template.js @@ -1,4 +1,5 @@ const fs = require("fs-extra"); +const chalk = require("chalk"); const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); const lodashIsObject = require("lodash/isObject"); @@ -354,19 +355,45 @@ class Template extends TemplateContent { } async runLinters(str, inputPath, outputPath) { - this.linters.forEach(function (linter) { + for (let linter of this.linters) { // these can be asynchronous but no guarantee of order when they run - linter.call(this, str, inputPath, outputPath); - }); + linter.call( + { + inputPath, + outputPath, + }, + str, + inputPath, + outputPath + ); + } } - addTransform(callback) { - this.transforms.push(callback); + addTransform(name, callback) { + this.transforms.push({ + name, + callback, + }); } - async runTransforms(str, outputPath, inputPath) { + // Warning: this argument list is the reverse of linters (inputPath then outputPath) + async runTransforms(str, inputPath, outputPath) { for (let transform of this.transforms) { - str = await transform.call(this, str, outputPath, inputPath); + str = await transform.callback.call( + { + inputPath, + outputPath, + }, + str, + outputPath + ); + if (!str && this.isVerbose) { + console.log( + chalk.yellow( + `Warning: Transform \`${transform.name}\` returned empty when writing ${outputPath} from ${inputPath}.` + ) + ); + } } return str; @@ -618,7 +645,11 @@ class Template extends TemplateContent { } await this.runLinters(content, page.inputPath, page.outputPath); - content = await this.runTransforms(content, page.outputPath); // pass in page.inputPath? + content = await this.runTransforms( + content, + page.inputPath, + page.outputPath + ); return content; } @@ -654,7 +685,7 @@ class Template extends TemplateContent { tmpl.config = this.config; for (let transform of this.transforms) { - tmpl.addTransform(transform); + tmpl.addTransform(transform.name, transform.callback); } for (let linter of this.linters) { tmpl.addLinter(linter); diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 041f92fa1..3a60ffaa4 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -100,6 +100,15 @@ class TemplateConfig { ); } } + + if ( + localConfig.filters !== undefined && + Object.keys(localConfig.filters).length + ) { + throw new EleventyConfigError( + `The \`filters\` configuration option was renamed in Eleventy 0.3.3 and removed in Eleventy 1.0. Please use the \`addTransform\` configuration method instead. Read more: https://www.11ty.dev/docs/config/#transforms` + ); + } } catch (err) { throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + @@ -117,7 +126,7 @@ class TemplateConfig { // remove special merge keys from object let savedForSpecialMerge = { - templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded + templateFormatsAdded: eleventyConfigApiMergingObject.templateFormatsAdded, }; delete eleventyConfigApiMergingObject.templateFormatsAdded; diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index cf997b7be..f8e9ed3b3 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -139,10 +139,10 @@ class TemplateWriter { * return pretty(str, { ocd: true }); * } */ - for (let transformName in this.config.filters) { - let transform = this.config.filters[transformName]; + for (let transformName in this.config.transforms) { + let transform = this.config.transforms[transformName]; if (typeof transform === "function") { - tmpl.addTransform(transform); + tmpl.addTransform(transformName, transform); } } diff --git a/src/UserConfig.js b/src/UserConfig.js index 5873135c1..c49e3e936 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -46,8 +46,7 @@ class UserConfig { this.passthroughCopies = {}; this.layoutAliases = {}; this.linters = {}; - // now named `transforms` in API - this.filters = {}; + this.transforms = {}; this.activeNamespace = ""; this.DateTime = DateTime; this.dynamicPermalinks = true; @@ -239,10 +238,7 @@ class UserConfig { addTransform(name, callback) { name = this.getNamespacedName(name); - // these are now called transforms - // this naming is kept here for backwards compatibility - // TODO major version change - this.filters[name] = callback; + this.transforms[name] = callback; } addLinter(name, callback) { @@ -655,7 +651,8 @@ class UserConfig { return { templateFormats: this.templateFormats, templateFormatsAdded: this.templateFormatsAdded, - filters: this.filters, // now called transforms + // filters removed in 1.0 (use addTransform instead) + transforms: this.transforms, linters: this.linters, globalData: this.globalData, layoutAliases: this.layoutAliases, diff --git a/src/defaultConfig.js b/src/defaultConfig.js index 73adf8ad7..baf477dad 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -52,8 +52,6 @@ module.exports = function (config) { data: "_data", output: "_site", }, - // deprecated, use config.addTransform - filters: {}, // deprecated, use config.addHandlebarsHelper handlebarsHelpers: {}, // deprecated, use config.addNunjucksFilter diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 326e47baa..799576ebd 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -18,10 +18,10 @@ test("Template Config local config overrides base config", async (t) => { t.truthy(Object.keys(cfg.handlebarsHelpers).length); t.truthy(Object.keys(cfg.nunjucksFilters).length); - t.is(Object.keys(cfg.filters).length, 1); + t.is(Object.keys(cfg.transforms).length, 1); t.is( - cfg.filters.prettyHtml( + cfg.transforms.prettyHtml( `
`, "test.html" ), diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index b5b9f5c62..762323464 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -952,7 +952,7 @@ test("Test a transform with a layout (via templateMap)", async (t) => { t.true(outputPath.endsWith("transform-layout/index.html")); }); - tmpl.addTransform(function (content, outputPath) { + tmpl.addTransform("transformName", function (content, outputPath) { t.is(content, "This is content."); t.true(outputPath.endsWith("transform-layout/index.html")); return "OVERRIDE BY A TRANSFORM"; diff --git a/test/TemplateTest.js b/test/TemplateTest.js index a5ee43363..e436a2643 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1173,7 +1173,7 @@ test("Test a transform", async (t) => { "./test/stubs/_site" ); - tmpl.addTransform(function (content, outputPath) { + tmpl.addTransform("transformName", function (content, outputPath) { t.true(outputPath.endsWith(".html")); return "OVERRIDE BY A TRANSFORM"; }); @@ -1192,7 +1192,7 @@ test.skip("Test a transform (does it have inputPath?)", async (t) => { "./test/stubs/_site" ); - tmpl.addTransform(function (content, outputPath, inputPath) { + tmpl.addTransform("transformName", function (content, outputPath, inputPath) { t.true(outputPath.endsWith(".html")); t.true(!!inputPath); return "OVERRIDE BY A TRANSFORM"; @@ -1211,7 +1211,7 @@ test("Test a transform with pages", async (t) => { "./test/stubs/_site" ); - tmpl.addTransform(function (content, outputPath) { + tmpl.addTransform("transformName", function (content, outputPath) { // should run twice, one for each page t.true(content.length > 0); t.true(outputPath.endsWith(".html")); @@ -1231,7 +1231,7 @@ test("Test a transform with a layout", async (t) => { "./test/stubs-475/_site" ); - tmpl.addTransform(function (content, outputPath) { + tmpl.addTransform("transformName", function (content, outputPath) { t.is(content, "This is content."); t.true(outputPath.endsWith(".html")); return "OVERRIDE BY A TRANSFORM"; @@ -1250,7 +1250,7 @@ test("Test a single asynchronous transform", async (t) => { "./test/stubs/_site" ); - tmpl.addTransform(async function (content, outputPath) { + tmpl.addTransform("transformName", async function (content, outputPath) { t.true(outputPath.endsWith("template/index.html")); return new Promise((resolve, reject) => { @@ -1273,7 +1273,7 @@ test("Test multiple asynchronous transforms", async (t) => { "./test/stubs/_site" ); - tmpl.addTransform(async function (content, outputPath) { + tmpl.addTransform("transformName", async function (content, outputPath) { t.true(outputPath.endsWith("template/index.html")); return new Promise((resolve, reject) => { @@ -1284,7 +1284,7 @@ test("Test multiple asynchronous transforms", async (t) => { }); // uppercase - tmpl.addTransform(async function (str, outputPath) { + tmpl.addTransform("transformName", async function (str, outputPath) { t.true(outputPath.endsWith("template/index.html")); return new Promise((resolve, reject) => { diff --git a/test/stubs/config.js b/test/stubs/config.js index 142863b40..e4665426b 100644 --- a/test/stubs/config.js +++ b/test/stubs/config.js @@ -1,6 +1,6 @@ const pretty = require("pretty"); -module.exports = function(config) { +module.exports = function (config) { /* { template, inputPath, @@ -17,21 +17,21 @@ module.exports = function(config) { pathPrefix: "/testdir", keys: { - package: "pkg2" + package: "pkg2", }, - filters: { - prettyHtml: function(str, outputPath) { + transforms: { + prettyHtml: function (str, outputPath) { if (outputPath.split(".").pop() === "html") { return pretty(str, { ocd: true }); } else { return str; } - } + }, }, nunjucksFilters: { - testing: str => { + testing: (str) => { return str; - } - } + }, + }, }; }; From 3e4d6bd12d5918486ed2fa0c1616785a3c654a2d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 17:47:04 -0500 Subject: [PATCH 277/746] Fixes #1484 --- cmd.js | 27 ++++++++-------- src/BenchmarkGroup.js | 3 +- src/Eleventy.js | 75 ++++++++++++++++++++++--------------------- test/EleventyTest.js | 2 +- 4 files changed, 55 insertions(+), 52 deletions(-) diff --git a/cmd.js b/cmd.js index d90231c0c..9474961a0 100755 --- a/cmd.js +++ b/cmd.js @@ -2,11 +2,11 @@ const pkg = require("./package.json"); const chalk = require("chalk"); // node 8+ require("please-upgrade-node")(pkg, { - message: function(requiredVersion) { + message: function (requiredVersion) { return chalk.red( `Eleventy requires Node ${requiredVersion}. You’ll need to upgrade to use it!` ); - } + }, }); if (process.env.DEBUG) { @@ -19,8 +19,8 @@ try { const argv = require("minimist")(process.argv.slice(2), { boolean: ["quiet"], default: { - quiet: null - } + quiet: null, + }, }); const Eleventy = require("./src/Eleventy"); const EleventyCommandCheck = require("./src/EleventyCommandCheck"); @@ -31,10 +31,10 @@ try { `Unhandled rejection in promise (${promise})` ); }); - process.on("uncaughtException", error => { + process.on("uncaughtException", (error) => { EleventyErrorHandler.fatal(error, "Uncaught exception"); }); - process.on("rejectionHandled", promise => { + process.on("rejectionHandled", (promise) => { EleventyErrorHandler.warn( promise, "A promise rejection was handled asynchronously" @@ -45,7 +45,11 @@ try { let cmdCheck = new EleventyCommandCheck(argv); cmdCheck.hasUnknownArguments(); - let elev = new Eleventy(argv.input, argv.output); + let elev = new Eleventy(argv.input, argv.output, { + // --quiet and --quiet=true both resolve to true + quietMode: argv.quiet, + }); + elev.setConfigPathOverride(argv.config); elev.setPathPrefix(argv.pathprefix); elev.setDryRun(argv.dryrun); @@ -53,22 +57,17 @@ try { elev.setPassthroughAll(argv.passthroughall); elev.setFormats(argv.formats); - // --quiet and --quiet=true resolves to true - if (argv.quiet === true || argv.quiet === false) { - elev.setIsVerbose(!argv.quiet); - } - // careful, we can’t use async/await here to error properly // with old node versions in `please-upgrade-node` above. elev .init() - .then(function() { + .then(function () { if (argv.version) { console.log(elev.getVersion()); } else if (argv.help) { console.log(elev.getHelp()); } else if (argv.serve) { - elev.watch().then(function() { + elev.watch().then(function () { elev.serve(argv.port); }); } else if (argv.watch) { diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index b1b983f10..e9b82a492 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -6,6 +6,7 @@ const debugBenchmark = require("debug")("Eleventy:Benchmark"); class BenchmarkGroup { constructor() { this.benchmarks = {}; + // Warning: aggregate benchmarks automatically default to false via BenchmarkManager->getBenchmarkGroup this.isVerbose = true; this.minimumThresholdMs = 0; this.minimumThresholdPercent = 8; @@ -25,7 +26,7 @@ class BenchmarkGroup { add(type, callback) { let benchmark = (this.benchmarks[type] = new Benchmark()); - return function(...args) { + return function (...args) { benchmark.before(); let ret = callback.call(this, ...args); benchmark.after(); diff --git a/src/Eleventy.js b/src/Eleventy.js index d78eb1993..d0ef22b2c 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -30,7 +30,7 @@ const debug = require("debug")("Eleventy"); * @returns {undefined} */ class Eleventy { - constructor(input, output) { + constructor(input, output, options = {}) { /** @member {Object} - tbd. */ this.config = config.getConfig(); @@ -41,22 +41,23 @@ class Eleventy { this.configPath = null; /** - * @member {Boolean} - Is Eleventy running in verbose mode? - * @default true - */ - this.isVerbose = process.env.DEBUG ? false : !this.config.quietMode; - - /** - * @member {Boolean} - Was verbose mode overridden manually? + * @member {Boolean} - Was verbose mode overwritten? * @default false */ - this.isVerboseOverride = false; + this.verboseModeSetViaCommandLineParam = false; /** - * @member {Boolean} - Is Eleventy running in debug mode? - * @default false + * @member {Boolean} - Is Eleventy running in verbose mode? + * @default true */ - this.isDebug = false; + if (options.quietMode === true || options.quietMode === false) { + // Set via --quiet + this.setIsVerbose(!options.quietMode); + this.verboseModeSetViaCommandLineParam = true; + } else { + // Fall back to configuration + this.setIsVerbose(!this.config.quietMode); + } /** * @member {Boolean} - Is Eleventy running in dry mode? @@ -325,22 +326,30 @@ Includes: ${this.eleventyFiles.getIncludesDir()} Layouts: ${this.eleventyFiles.getLayoutsDir()} Output: ${this.outputDir} Template Formats: ${formats.join(",")} -Verbose Output: ${this.isVerbose}`); +Verbose Output: ${this.verboseMode}`); - this.writer.setVerboseOutput(this.isVerbose); + this.writer.setVerboseOutput(this.verboseMode); this.writer.setDryRun(this.isDryRun); return this.templateData.cacheData(); } - /** - * Updates the debug mode of Eleventy. - * - * @method - * @param {Boolean} isDebug - Shall Eleventy run in debug mode? - */ - setIsDebug(isDebug) { - this.isDebug = !!isDebug; + /* Setter for verbose mode */ + set verboseMode(value) { + this._isVerboseMode = !!value; + + if (this.writer) { + this.writer.setVerboseOutput(this._isVerboseMode); + } + + if (bench) { + bench.setVerboseOutput(this._isVerboseMode); + } + } + + /* Getter for verbose mode */ + get verboseMode() { + return this._isVerboseMode; } /** @@ -350,18 +359,12 @@ Verbose Output: ${this.isVerbose}`); * @param {Boolean} isVerbose - Shall Eleventy run in verbose mode? */ setIsVerbose(isVerbose) { - this.isVerbose = !!isVerbose; - - // mark that this was changed from the default (probably from --quiet) - // this is used when we reset the config (only applies if not overridden) - this.isVerboseOverride = true; - - if (this.writer) { - this.writer.setVerboseOutput(this.isVerbose); - } - if (bench) { - bench.setVerboseOutput(this.isVerbose); + // Debug mode should always run quiet (all output goes to debug logger) + if (process.env.DEBUG) { + isVerbose = false; } + + this.verboseMode = isVerbose; } /** @@ -431,8 +434,9 @@ Arguments: this.config = config.getConfig(); this.eleventyServe.config = this.config; - if (!this.isVerboseOverride && !process.env.DEBUG) { - this.isVerbose = !this.config.quietMode; + // only use config quietMode if --quiet not set on CLI + if (!this.verboseModeSetViaCommandLineParam) { + this.setIsVerbose(!this.config.quietMode); } } @@ -668,7 +672,6 @@ Arguments: initWatchBench.after(); - this.watcherBench.setIsVerbose(true); this.watcherBench.finish("Watch"); console.log("Watching…"); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 69b45a8e3..8adca1dbf 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -30,7 +30,7 @@ test("Eleventy, set is verbose", (t) => { let elev = new Eleventy(); elev.setIsVerbose(true); - t.true(elev.isVerbose); + t.true(elev.verboseMode); }); test("Eleventy set input/output", async (t) => { From 082b461d0df216664cb7ad611580b55781cbf79e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 20:10:07 -0500 Subject: [PATCH 278/746] Attempt to fix Windows path separator test breakage --- src/EleventyServe.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 9de9a85d2..3cf0883bb 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -23,7 +23,8 @@ class EleventyServe { let cfgPrefix = this.config.pathPrefix; if (cfgPrefix) { // add leading / (for browsersync), see #1454 - return path.join("/", cfgPrefix); + // path.join uses \\ for Windows so we split and rejoin + return path.join("/", cfgPrefix).split(path.sep).join("/"); } return "/"; } From bf8e2dab806e533d5a55768fc0cf601387742368 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 20:24:34 -0500 Subject: [PATCH 279/746] Revert Node 15 after a failure https://github.com/11ty/eleventy/runs/1334797230?check_suite_focus=true --- .github/workflows/ci.yml | 2 +- .travis.yml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52e09b40f..6590a7dec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - node: ["10", "12", "14", "15"] + node: ["10", "12", "14"] name: Node.js ${{ matrix.node }} on ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index 3a49ca63a..e1ce39e9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ node_js: - 10 - 12 - 14 - - 15 before_script: - npm install script: npm run test From 045f666fa6ff9f22a60b3dd6a972d757b0481400 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 20:31:13 -0500 Subject: [PATCH 280/746] Migrating away from Travis. GitHub actions seem to be working better/faster/more reliably here. --- .travis.yml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e1ce39e9d..000000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: node_js -node_js: - - 10 - - 12 - - 14 -before_script: - - npm install -script: npm run test -branches: - except: - - gh-pages -sudo: false -os: - - linux - - osx - - windows -env: - - YARN_GPG=no \ No newline at end of file From b85c60bf983ea926e40485464d459f1b2f33c0b1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Oct 2020 20:32:21 -0500 Subject: [PATCH 281/746] Remove travis reference on readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a693193eb..7ae7a5236 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ Works with HTML, Markdown, Liquid, Nunjucks, Handlebars, Mustache, EJS, Haml, Pu - [11ty on npm](https://www.npmjs.com/org/11ty) - [11ty on GitHub](https://github.com/11ty) - Continuous Integration: - - [Travis CI](https://travis-ci.org/11ty/eleventy) - [GitHub Actions](https://github.com/11ty/eleventy/actions?query=workflow%3A.github%2Fworkflows%2Fci.yml) [![npm Version](https://img.shields.io/npm/v/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy) [![GitHub issues](https://img.shields.io/github/issues/11ty/eleventy.svg?style=for-the-badge)](https://github.com/11ty/eleventy/issues) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=for-the-badge)](https://github.com/prettier/prettier) [![npm Downloads](https://img.shields.io/npm/dt/@11ty/eleventy.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy) From 0ddc71359d9fd1f3a56ff9e67956f8d57fdc3a68 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Sun, 1 Nov 2020 14:39:03 -0800 Subject: [PATCH 282/746] Disgusting hack to prevent NJK from over-compiling --- src/Engines/Nunjucks.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 34b685e7b..451895ae1 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -4,6 +4,34 @@ const TemplatePath = require("../TemplatePath"); const EleventyErrorUtil = require("../EleventyErrorUtil"); const EleventyBaseError = require("../EleventyBaseError"); +/* +// HACKITYHACKHACKHACKHACK +*/ +let pathMap = new Map(); +let tc = NunjucksLib.Template.prototype._compile; +let getKey = (obj) => { + return `${obj.path} :: ${obj.tmplStr.length}`; +}; +NunjucksLib.Template.prototype._compile = function (...args) { + if (!this.tmplProps && pathMap.has(getKey(this))) { + // console.log(`### cached ${getKey(this)}`); + let pathProps = pathMap.get(getKey(this)); + this.blocks = pathProps.blocks; + this.rootRenderFunc = pathProps.rootRenderFunc; + this.compiled = true; + } else { + tc.call(this, ...args); + // console.log(`### caching for ${getKey(this)}`); + pathMap.set(getKey(this), { + blocks: this.blocks, + rootRenderFunc: this.rootRenderFunc, + }); + } +}; +/* +// END HACKITYHACKHACKHACKHACK +*/ + class EleventyShortcodeError extends EleventyBaseError {} class Nunjucks extends TemplateEngine { From babea4443688ee786d9a207f2acb300cf5c4c2b5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 10:06:37 -0600 Subject: [PATCH 283/746] Refactor to use safer `listeners` method instead of this._events (confirmed node 10+) --- src/Util/AsyncEventEmitter.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Util/AsyncEventEmitter.js b/src/Util/AsyncEventEmitter.js index f43dd3e8d..dccddc95c 100644 --- a/src/Util/AsyncEventEmitter.js +++ b/src/Util/AsyncEventEmitter.js @@ -4,18 +4,12 @@ const lodashIsEmpty = require("lodash/isEmpty"); class AsyncEventEmitter extends EventEmitter { async emit(type, ...args) { - const handler = lodashGet(this._events, type); - if (lodashIsEmpty(handler) && typeof handler !== "function") { + let listeners = this.listeners(type); + if (!listeners.length) { return; } - if (typeof handler === "function") { - await handler.apply(this, args); - } else { - await Promise.all(handler.map((h) => h.apply(this, args))); - } - - return true; + return await Promise.all(listeners.map((h) => h.apply(this, args))); } } From a01368797e7ac716abfe469e72973508e8e646f3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 10:08:54 -0600 Subject: [PATCH 284/746] Remove unused requires --- src/Util/AsyncEventEmitter.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Util/AsyncEventEmitter.js b/src/Util/AsyncEventEmitter.js index dccddc95c..acf08e5c5 100644 --- a/src/Util/AsyncEventEmitter.js +++ b/src/Util/AsyncEventEmitter.js @@ -1,6 +1,4 @@ const EventEmitter = require("events"); -const lodashGet = require("lodash/get"); -const lodashIsEmpty = require("lodash/isEmpty"); class AsyncEventEmitter extends EventEmitter { async emit(type, ...args) { From 31ac80b72fbf1f00038f8ba342acf638bb489d5a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 10:37:08 -0600 Subject: [PATCH 285/746] Fix tests --- test/EleventyFilesTest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 04026c8d8..f432f531c 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -394,8 +394,8 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore ha test("getTemplateData caching", (t) => { let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); evf.init(); - let templateDataFirstCall = evf.getTemplateData(); - let templateDataSecondCall = evf.getTemplateData(); + let templateDataFirstCall = evf.templateData; + let templateDataSecondCall = evf.templateData; t.is(templateDataFirstCall, templateDataSecondCall); }); From f873939adcb1b849e54caa9d60c1e245287ff667 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 13:09:41 -0600 Subject: [PATCH 286/746] Remove test file --- test/EleventyCommandCheckTest.js | 51 -------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 test/EleventyCommandCheckTest.js diff --git a/test/EleventyCommandCheckTest.js b/test/EleventyCommandCheckTest.js deleted file mode 100644 index 77ff1d783..000000000 --- a/test/EleventyCommandCheckTest.js +++ /dev/null @@ -1,51 +0,0 @@ -const test = require("ava"); -const EleventyCommandCheck = require("../src/EleventyCommandCheck"); - -test("Constructor", (t) => { - let cmdCheck = new EleventyCommandCheck({}); - t.is(cmdCheck.toString(), ""); -}); - -test("Has an argument", (t) => { - let cmdCheck = new EleventyCommandCheck({ - input: "src", - }); - t.is(cmdCheck.toString(), "--input=src"); -}); - -test("Boolean argument", (t) => { - let cmdCheck = new EleventyCommandCheck({ - version: true, - }); - t.is(cmdCheck.toString(), "--version"); -}); - -test("Multiple arguments", (t) => { - let cmdCheck = new EleventyCommandCheck({ - input: "src", - version: true, - }); - - // technically invalid but eleventy should quit early on --version - t.is(cmdCheck.toString(), "--input=src --version"); -}); - -test("getArgumentLookupMap", (t) => { - let cmdCheck = new EleventyCommandCheck({}); - t.is(cmdCheck.getArgumentLookupMap()["input"], true); - t.is(cmdCheck.getArgumentLookupMap()["version"], true); - t.falsy(cmdCheck.getArgumentLookupMap()["not-an-arg"]); - - t.is(cmdCheck.isKnownArgument("input"), true); - t.is(cmdCheck.isKnownArgument("version"), true); - t.is(cmdCheck.isKnownArgument("unknown-thing"), false); - - t.is(cmdCheck.isKnownArgument("_"), true); -}); - -test("throws", (t) => { - let cmdCheck = new EleventyCommandCheck({ "unknown-argument": true }); - t.throws(() => { - cmdCheck.hasUnknownArguments(); - }); -}); From 678f9bdcd6594bbd93d162d7be8ec10d90e26419 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 13:12:46 -0600 Subject: [PATCH 287/746] =?UTF-8?q?Fix=20for=20filters=20rename=20warning?= =?UTF-8?q?=20(when=20the=20config=20file=20function=20doesn=E2=80=99t=20h?= =?UTF-8?q?ave=20a=20return=20entry)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TemplateConfig.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index ce70910f6..a044628c7 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -183,6 +183,7 @@ class TemplateConfig { } if ( + localConfig && localConfig.filters !== undefined && Object.keys(localConfig.filters).length ) { From b174e57e70c44b5bad4973ed2fc2fd3bcd1f2d40 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 14:05:43 -0600 Subject: [PATCH 288/746] Update deps --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f6b99e65b..b01e7075b 100755 --- a/package.json +++ b/package.json @@ -79,9 +79,9 @@ "ink-docstrap": "1.3.2", "js-yaml": "^3.14.0", "jsdoc": "3.6.6", - "lint-staged": "^10.4.2", + "lint-staged": "^10.5.1", "markdown-it-emoji": "^2.0.0", - "node-sass": "^4.14.1", + "node-sass": "^5.0.0", "nyc": "^15.1.0", "prettier": "^2.1.2", "rimraf": "^3.0.2", @@ -119,7 +119,7 @@ "pug": "^3.0.0", "recursive-copy": "^2.0.11", "semver": "^7.3.2", - "slugify": "^1.4.5", + "slugify": "^1.4.6", "time-require": "^0.1.2", "valid-url": "^1.0.9" }, From 1f827301d0f3fc59da78e2bcadf53de403fcd948 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 14:21:11 -0600 Subject: [PATCH 289/746] Readable file extension output --- src/EleventyExtensionMap.js | 4 ++++ src/TemplateRender.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index b62d3c009..e8804114d 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -170,6 +170,10 @@ class EleventyExtensionMap { return this._extensionToKeyMap; } + + getReadableFileExtensions() { + return Object.keys(this.extensionToKeyMap).join(" "); + } } module.exports = EleventyExtensionMap; diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 758bc9211..86cedd581 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -52,7 +52,7 @@ class TemplateRender { this._engineName = this.extensionMap.getKey(engineNameOrPath); if (!this._engineName) { throw new TemplateRenderUnknownEngineError( - `Unknown engine for ${engineNameOrPath} (supported extensions: ${Object.keys(this.extensionMap.extensionToKeyMap).join(' ')})` + `Unknown engine for ${engineNameOrPath} (supported extensions: ${this.extensionMap.getReadableFileExtensions()})` ); } From 1d7a96737912ff93f7d149a648419b84c9012a7e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Nov 2020 14:48:25 -0600 Subject: [PATCH 290/746] Changes browsersync server instance name to `eleventy-server` --- src/EleventyServe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 8e8bcbec0..2b46fc57e 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -123,7 +123,7 @@ class EleventyServe { serve(port) { // only load on serve—this is pretty expensive const browserSync = require("browser-sync"); - this.server = browserSync.create("eleventyServer"); + this.server = browserSync.create("eleventy-server"); let pathPrefix = this.getPathPrefix(); From 5c5e65aae6edde945e4ec3ba5ccf2b55f434e16d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 22 Nov 2020 13:47:36 -0600 Subject: [PATCH 291/746] Fixes #843 --- src/EleventyServe.js | 1 + test/EleventyServeTest.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 2b46fc57e..c6c14a976 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -75,6 +75,7 @@ class EleventyServe { watch: false, open: false, notify: false, + ui: false, // Default changed in 1.0 index: "index.html", }, this.config.browserSyncConfig diff --git a/test/EleventyServeTest.js b/test/EleventyServeTest.js index 7a507ac39..1fcb8c45e 100644 --- a/test/EleventyServeTest.js +++ b/test/EleventyServeTest.js @@ -30,6 +30,7 @@ test("Get Options", (t) => { baseDir: "_site", }, watch: false, + ui: false, }); }); @@ -53,6 +54,7 @@ test("Get Options (with a pathPrefix)", (t) => { }, }, watch: false, + ui: false, }); }); @@ -76,5 +78,6 @@ test("Get Options (override in config)", (t) => { baseDir: "_site", }, watch: false, + ui: false, }); }); From 7a658a65d89f7829282ed587697d226e635ca83e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 22 Nov 2020 13:52:11 -0600 Subject: [PATCH 292/746] Fixes #841 --- src/EleventyServe.js | 1 + test/EleventyServeTest.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index c6c14a976..6730e33e4 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -76,6 +76,7 @@ class EleventyServe { open: false, notify: false, ui: false, // Default changed in 1.0 + ghostMode: false, // Default changed in 1.0 index: "index.html", }, this.config.browserSyncConfig diff --git a/test/EleventyServeTest.js b/test/EleventyServeTest.js index 1fcb8c45e..c01eed650 100644 --- a/test/EleventyServeTest.js +++ b/test/EleventyServeTest.js @@ -31,6 +31,7 @@ test("Get Options", (t) => { }, watch: false, ui: false, + ghostMode: false, }); }); @@ -55,6 +56,7 @@ test("Get Options (with a pathPrefix)", (t) => { }, watch: false, ui: false, + ghostMode: false, }); }); @@ -79,5 +81,6 @@ test("Get Options (override in config)", (t) => { }, watch: false, ui: false, + ghostMode: false, }); }); From 904234193766aa9d9a7fb1e5037dea8838995a0f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 22 Nov 2020 14:09:43 -0600 Subject: [PATCH 293/746] Fixes #597 --- src/EleventyExtensionMap.js | 6 +--- src/TemplatePassthroughManager.js | 19 ++----------- src/defaultConfig.js | 1 - test/EleventyExtensionMapTest.js | 11 -------- test/EleventyFilesTest.js | 1 - test/TemplatePassthroughManagerTest.js | 38 ++------------------------ test/TemplateWriterTest.js | 1 - 7 files changed, 6 insertions(+), 71 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index e8804114d..521a75247 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -74,11 +74,7 @@ class EleventyExtensionMap { } getGlobs(inputDir) { - if (this.config.passthroughFileCopy) { - return this._getGlobs(this.unfilteredFormatKeys, inputDir); - } - - return this._getGlobs(this.validTemplateLanguageKeys, inputDir); + return this._getGlobs(this.unfilteredFormatKeys, inputDir); } _getGlobs(formatKeys, inputDir) { diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 4b1be9b6a..aa4a52ff5 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -61,18 +61,13 @@ class TemplatePassthroughManager { } getConfigPaths() { - if (!this.config.passthroughFileCopy) { - debug("`passthroughFileCopy` is disabled in config, bypassing."); - return []; - } - let paths = []; let target = this.config.passthroughCopies || {}; - debug("`passthroughFileCopy` config paths: %o", target); + debug("`addPassthroughCopy` config API paths: %o", target); for (let path in target) { paths.push(this._normalizePaths(path, target[path])); } - debug("`passthroughFileCopy` config normalized paths: %o", paths); + debug("`addPassthroughCopy` config API normalized paths: %o", paths); return paths; } @@ -83,11 +78,6 @@ class TemplatePassthroughManager { } getNonTemplatePaths(paths) { - if (!this.config.passthroughFileCopy) { - debug("`passthroughFileCopy` is disabled in config, bypassing."); - return []; - } - let matches = []; for (let path of paths) { if (!this.extensionMap.hasEngine(path)) { @@ -162,11 +152,6 @@ class TemplatePassthroughManager { // bottleneck to eleventy. The copies are performed asynchronously and don’t affect eleventy // write times in a significant way. async copyAll(paths) { - if (!this.config.passthroughFileCopy) { - debug("`passthroughFileCopy` is disabled in config, bypassing."); - return; - } - if ( this.incrementalFile && this.isPassthroughCopyFile(paths, this.incrementalFile) diff --git a/src/defaultConfig.js b/src/defaultConfig.js index baf477dad..c00d7f151 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -35,7 +35,6 @@ module.exports = function (config) { markdownTemplateEngine: "liquid", htmlTemplateEngine: "liquid", dataTemplateEngine: false, // change in 1.0 - passthroughFileCopy: true, htmlOutputSuffix: "-o", jsDataFileSuffix: ".11tydata", keys: { diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index 5d694934a..9640f911b 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -16,19 +16,8 @@ test("Multiple formats", (t) => { t.deepEqual(map.getGlobs("src"), ["./src/**/*.njk", "./src/**/*.pug"]); }); -test("Invalid keys are filtered (no passthrough copy)", (t) => { - let map = new EleventyExtensionMap(["lksdjfjlsk"]); - map.config = { - passthroughFileCopy: false, - }; - t.deepEqual(map.getGlobs("."), []); -}); - test("Invalid keys are filtered (using passthrough copy)", (t) => { let map = new EleventyExtensionMap(["lksdjfjlsk"]); - map.config = { - passthroughFileCopy: true, - }; t.deepEqual(map.getGlobs("."), ["./**/*.lksdjfjlsk"]); }); diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index f432f531c..072a1d371 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -553,7 +553,6 @@ test("Glob Watcher Files with Config Passthroughs (one template format)", async mgr.setInputDir("test/stubs"); mgr.setOutputDir("test/stubs/_site"); mgr.setConfig({ - passthroughFileCopy: true, passthroughCopies: { "test/stubs/img/": true, }, diff --git a/test/TemplatePassthroughManagerTest.js b/test/TemplatePassthroughManagerTest.js index da17edf60..6b4aae5c6 100644 --- a/test/TemplatePassthroughManagerTest.js +++ b/test/TemplatePassthroughManagerTest.js @@ -5,7 +5,6 @@ const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); test("Get paths from Config", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true, passthroughCopies: { img: true, }, @@ -17,7 +16,6 @@ test("Get paths from Config", async (t) => { test("isPassthroughCopyFile", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true, passthroughCopies: { img: true, fonts: true, @@ -36,22 +34,9 @@ test("isPassthroughCopyFile", async (t) => { ); }); -test("Empty config paths when disabled in config", async (t) => { - let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughFileCopy: false, - passthroughCopies: { - img: true, - }, - }); - - t.deepEqual(mgr.getConfigPaths(), []); -}); - test("Get glob paths from config", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true, passthroughCopies: { "test/stubs/img": true, "test/stubs/img/**": "./", @@ -68,53 +53,36 @@ test("Get glob paths from config", async (t) => { test("Get file paths", async (t) => { let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughFileCopy: true, - }); - t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), ["test.png"]); }); test("Get file paths (filter out real templates)", async (t) => { let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughFileCopy: true, - }); t.deepEqual(mgr.getNonTemplatePaths(["test.njk"]), []); }); test("Get file paths (filter out real templates), multiple", async (t) => { let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughFileCopy: true, - }); t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.png"]), ["test.png"]); }); test("Get file paths with a js file (filter out real templates), multiple", async (t) => { let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughFileCopy: true, - }); t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.js"]), ["test.js"]); }); -test("Get file paths when disabled in config", async (t) => { +// This test used to be for passthroughFileCopy: false in config +test("Get file paths (one image path)", async (t) => { let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughFileCopy: false, - }); - - t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), []); + t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), ["test.png"]); }); test("Naughty paths outside of project dir", async (t) => { let mgr = new TemplatePassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true, passthroughCopies: { "../static": true, "../*": "./", diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 8693b913c..0afe98f94 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -622,7 +622,6 @@ test("Passthrough file output", async (t) => { const mgr = tw.eleventyFiles.getPassthroughManager(); mgr.setConfig({ - passthroughFileCopy: true, passthroughCopies: { "./test/stubs/template-passthrough/static": true, "./test/stubs/template-passthrough/static/": "./", From b69f602f6e3bc94ecbf6f7c803706e0ec4b8690c Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Tue, 24 Nov 2020 11:47:26 -0800 Subject: [PATCH 294/746] Correctness fixes on NJK tmpl caching. --- src/Engines/Nunjucks.js | 93 +++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 23 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 451895ae1..c87b98f01 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -5,32 +5,76 @@ const EleventyErrorUtil = require("../EleventyErrorUtil"); const EleventyBaseError = require("../EleventyBaseError"); /* -// HACKITYHACKHACKHACKHACK -*/ + * HACKITYHACKHACKHACKHACK + */ +let inc = ((i) => { + return () => { + return i++; + }; +})(0); let pathMap = new Map(); -let tc = NunjucksLib.Template.prototype._compile; -let getKey = (obj) => { - return `${obj.path} :: ${obj.tmplStr.length}`; -}; -NunjucksLib.Template.prototype._compile = function (...args) { - if (!this.tmplProps && pathMap.has(getKey(this))) { - // console.log(`### cached ${getKey(this)}`); - let pathProps = pathMap.get(getKey(this)); - this.blocks = pathProps.blocks; - this.rootRenderFunc = pathProps.rootRenderFunc; - this.compiled = true; - } else { - tc.call(this, ...args); - // console.log(`### caching for ${getKey(this)}`); - pathMap.set(getKey(this), { - blocks: this.blocks, - rootRenderFunc: this.rootRenderFunc, - }); + +let clearCache = (reason = "") => { + if (pathMap.size > 0) { + pathMap.clear(); } }; + +let clearAndWrap = (name, obj = NunjucksLib.Environment) => { + let orig = obj.prototype[name]; + obj.prototype[name] = function (...args) { + clearCache(name); + return orig.call(this, ...args); + }; +}; + +clearAndWrap("addExtension"); +clearAndWrap("removeExtension"); + +(function () { + // IFFE to prevent temp var leakage + let getKey = (obj) => { + let eids = obj.env.extensionsList.reduce((v, c) => { + return c.__id ? v + " : " + c.__id : v; + }, ""); + let k = + `${obj.path || obj.tmplStr} :: ${obj.tmplStr.length} :: ` + + `${obj.env.asyncFilters.length} :: (${eids})`; /* + + ( + (obj.env.extensionsList.length) ? + `${Object.keys(obj.env.extensions).join("|")} :: (${eids})` : + "" + ); + */ + return k; + }; + let tc = NunjucksLib.Template.prototype._compile; + NunjucksLib.Template.prototype._compile = function (...args) { + // console.log(`NunjucksLib.Template.prototype._compile`); + if (!this.compiled && !this.tmplProps && pathMap.has(getKey(this))) { + let pathProps = pathMap.get(getKey(this)); + this.blocks = pathProps.blocks; + this.rootRenderFunc = pathProps.rootRenderFunc; + this.compiled = true; + } else { + tc.call(this, ...args); + pathMap.set(getKey(this), { + blocks: this.blocks, + rootRenderFunc: this.rootRenderFunc, + }); + } + }; + + let ae = NunjucksLib.Environment.prototype.addExtension; + NunjucksLib.Environment.prototype.addExtension = function (...args) { + let e = args[1]; + e.__id = inc(); + return ae.call(this, ...args); + }; +})(); /* -// END HACKITYHACKHACKHACKHACK -*/ + * END HACKITYHACKHACKHACKHACK + */ class EleventyShortcodeError extends EleventyBaseError {} @@ -92,6 +136,7 @@ class Nunjucks extends TemplateEngine { ); } + clearCache("addTag"); this.njkEnv.addExtension(name, tagObj); } @@ -165,7 +210,6 @@ class Nunjucks extends TemplateEngine { }); } else { try { - // console.log( shortcodeFn.toString() ); return new NunjucksLib.runtime.SafeString( shortcodeFn.call( Nunjucks._normalizeShortcodeContext(context), @@ -183,6 +227,8 @@ class Nunjucks extends TemplateEngine { }; } + // Invalidate the caches. + clearCache("addShortcode"); this.njkEnv.addExtension(shortcodeName, new ShortcodeFunction()); } @@ -253,6 +299,7 @@ class Nunjucks extends TemplateEngine { }; } + clearCache("addPairedShortcode"); this.njkEnv.addExtension(shortcodeName, new PairedShortcodeFunction()); } From bf43bface7c8487783c2d306c4e1be9bb62c2c93 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Sun, 1 Nov 2020 14:39:03 -0800 Subject: [PATCH 295/746] Disgusting hack to prevent NJK from over-compiling --- src/Engines/Nunjucks.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 01e349488..94ead1027 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -4,6 +4,34 @@ const TemplatePath = require("../TemplatePath"); const EleventyErrorUtil = require("../EleventyErrorUtil"); const EleventyBaseError = require("../EleventyBaseError"); +/* +// HACKITYHACKHACKHACKHACK +*/ +let pathMap = new Map(); +let tc = NunjucksLib.Template.prototype._compile; +let getKey = (obj) => { + return `${obj.path} :: ${obj.tmplStr.length}`; +}; +NunjucksLib.Template.prototype._compile = function (...args) { + if (!this.tmplProps && pathMap.has(getKey(this))) { + // console.log(`### cached ${getKey(this)}`); + let pathProps = pathMap.get(getKey(this)); + this.blocks = pathProps.blocks; + this.rootRenderFunc = pathProps.rootRenderFunc; + this.compiled = true; + } else { + tc.call(this, ...args); + // console.log(`### caching for ${getKey(this)}`); + pathMap.set(getKey(this), { + blocks: this.blocks, + rootRenderFunc: this.rootRenderFunc, + }); + } +}; +/* +// END HACKITYHACKHACKHACKHACK +*/ + class EleventyShortcodeError extends EleventyBaseError {} class Nunjucks extends TemplateEngine { From e932b41bf050e7db2abe6d7d3f8e794f80b335f9 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Tue, 24 Nov 2020 11:47:26 -0800 Subject: [PATCH 296/746] Correctness fixes on NJK tmpl caching. --- src/Engines/Nunjucks.js | 93 +++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 23 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 94ead1027..6e46d9dd1 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -5,32 +5,76 @@ const EleventyErrorUtil = require("../EleventyErrorUtil"); const EleventyBaseError = require("../EleventyBaseError"); /* -// HACKITYHACKHACKHACKHACK -*/ + * HACKITYHACKHACKHACKHACK + */ +let inc = ((i) => { + return () => { + return i++; + }; +})(0); let pathMap = new Map(); -let tc = NunjucksLib.Template.prototype._compile; -let getKey = (obj) => { - return `${obj.path} :: ${obj.tmplStr.length}`; -}; -NunjucksLib.Template.prototype._compile = function (...args) { - if (!this.tmplProps && pathMap.has(getKey(this))) { - // console.log(`### cached ${getKey(this)}`); - let pathProps = pathMap.get(getKey(this)); - this.blocks = pathProps.blocks; - this.rootRenderFunc = pathProps.rootRenderFunc; - this.compiled = true; - } else { - tc.call(this, ...args); - // console.log(`### caching for ${getKey(this)}`); - pathMap.set(getKey(this), { - blocks: this.blocks, - rootRenderFunc: this.rootRenderFunc, - }); + +let clearCache = (reason = "") => { + if (pathMap.size > 0) { + pathMap.clear(); } }; + +let clearAndWrap = (name, obj = NunjucksLib.Environment) => { + let orig = obj.prototype[name]; + obj.prototype[name] = function (...args) { + clearCache(name); + return orig.call(this, ...args); + }; +}; + +clearAndWrap("addExtension"); +clearAndWrap("removeExtension"); + +(function () { + // IFFE to prevent temp var leakage + let getKey = (obj) => { + let eids = obj.env.extensionsList.reduce((v, c) => { + return c.__id ? v + " : " + c.__id : v; + }, ""); + let k = + `${obj.path || obj.tmplStr} :: ${obj.tmplStr.length} :: ` + + `${obj.env.asyncFilters.length} :: (${eids})`; /* + + ( + (obj.env.extensionsList.length) ? + `${Object.keys(obj.env.extensions).join("|")} :: (${eids})` : + "" + ); + */ + return k; + }; + let tc = NunjucksLib.Template.prototype._compile; + NunjucksLib.Template.prototype._compile = function (...args) { + // console.log(`NunjucksLib.Template.prototype._compile`); + if (!this.compiled && !this.tmplProps && pathMap.has(getKey(this))) { + let pathProps = pathMap.get(getKey(this)); + this.blocks = pathProps.blocks; + this.rootRenderFunc = pathProps.rootRenderFunc; + this.compiled = true; + } else { + tc.call(this, ...args); + pathMap.set(getKey(this), { + blocks: this.blocks, + rootRenderFunc: this.rootRenderFunc, + }); + } + }; + + let ae = NunjucksLib.Environment.prototype.addExtension; + NunjucksLib.Environment.prototype.addExtension = function (...args) { + let e = args[1]; + e.__id = inc(); + return ae.call(this, ...args); + }; +})(); /* -// END HACKITYHACKHACKHACKHACK -*/ + * END HACKITYHACKHACKHACKHACK + */ class EleventyShortcodeError extends EleventyBaseError {} @@ -93,6 +137,7 @@ class Nunjucks extends TemplateEngine { ); } + clearCache("addTag"); this.njkEnv.addExtension(name, tagObj); } @@ -176,7 +221,6 @@ class Nunjucks extends TemplateEngine { }); } else { try { - // console.log( shortcodeFn.toString() ); return new NunjucksLib.runtime.SafeString( shortcodeFn.call( Nunjucks._normalizeShortcodeContext(context), @@ -194,6 +238,8 @@ class Nunjucks extends TemplateEngine { }; } + // Invalidate the caches. + clearCache("addShortcode"); this.njkEnv.addExtension(shortcodeName, new ShortcodeFunction()); } @@ -264,6 +310,7 @@ class Nunjucks extends TemplateEngine { }; } + clearCache("addPairedShortcode"); this.njkEnv.addExtension(shortcodeName, new PairedShortcodeFunction()); } From 3a005de2124677722643729fb8ea96a44368b5cc Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Tue, 24 Nov 2020 13:35:56 -0800 Subject: [PATCH 297/746] Cleanup variables and scopes per review comments. --- src/Engines/Nunjucks.js | 91 +++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 54 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 6e46d9dd1..2a71ea46d 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -5,76 +5,60 @@ const EleventyErrorUtil = require("../EleventyErrorUtil"); const EleventyBaseError = require("../EleventyBaseError"); /* - * HACKITYHACKHACKHACKHACK + * This IFFE applies a monkey-patch to Nunjucks internals to cache + * compiled templates and re-use them where possible. It's relatively + * pessimistic (conservative) about cache clearing to ensure correctness. */ -let inc = ((i) => { - return () => { - return i++; - }; -})(0); -let pathMap = new Map(); - -let clearCache = (reason = "") => { - if (pathMap.size > 0) { - pathMap.clear(); - } -}; +(function () { + let templateCache = new Map(); -let clearAndWrap = (name, obj = NunjucksLib.Environment) => { - let orig = obj.prototype[name]; - obj.prototype[name] = function (...args) { - clearCache(name); - return orig.call(this, ...args); + let clearAndWrap = (name, obj = NunjucksLib.Environment) => { + let orig = obj.prototype[name]; + obj.prototype[name] = function (...args) { + templateCache.clear(); + return orig.call(this, ...args); + }; }; -}; -clearAndWrap("addExtension"); -clearAndWrap("removeExtension"); + clearAndWrap("addExtension"); + clearAndWrap("removeExtension"); -(function () { - // IFFE to prevent temp var leakage let getKey = (obj) => { - let eids = obj.env.extensionsList.reduce((v, c) => { - return c.__id ? v + " : " + c.__id : v; - }, ""); - let k = - `${obj.path || obj.tmplStr} :: ${obj.tmplStr.length} :: ` + - `${obj.env.asyncFilters.length} :: (${eids})`; /* + - ( - (obj.env.extensionsList.length) ? - `${Object.keys(obj.env.extensions).join("|")} :: (${eids})` : - "" - ); - */ - return k; + return [ + obj.path || obj.tmplStr, + obj.tmplStr.length, + obj.env.asyncFilters.length, + obj.env.extensionsList + .map((e) => { + return e.__id || ""; + }) + .join(":"), + ].join(" :: "); }; - let tc = NunjucksLib.Template.prototype._compile; + + let _compile = NunjucksLib.Template.prototype._compile; NunjucksLib.Template.prototype._compile = function (...args) { - // console.log(`NunjucksLib.Template.prototype._compile`); - if (!this.compiled && !this.tmplProps && pathMap.has(getKey(this))) { - let pathProps = pathMap.get(getKey(this)); + if (!this.compiled && !this.tmplProps && templateCache.has(getKey(this))) { + let pathProps = templateCache.get(getKey(this)); this.blocks = pathProps.blocks; this.rootRenderFunc = pathProps.rootRenderFunc; this.compiled = true; } else { - tc.call(this, ...args); - pathMap.set(getKey(this), { + _compile.call(this, ...args); + templateCache.set(getKey(this), { blocks: this.blocks, rootRenderFunc: this.rootRenderFunc, }); } }; - let ae = NunjucksLib.Environment.prototype.addExtension; - NunjucksLib.Environment.prototype.addExtension = function (...args) { - let e = args[1]; - e.__id = inc(); - return ae.call(this, ...args); + let extensionIdCounter = 0; + let addExtension = NunjucksLib.Environment.prototype.addExtension; + NunjucksLib.Environment.prototype.addExtension = function (name, ext) { + ext.__id = extensionIdCounter++; + return addExtension.call(this, name, ext); }; })(); -/* - * END HACKITYHACKHACKHACKHACK - */ class EleventyShortcodeError extends EleventyBaseError {} @@ -137,7 +121,7 @@ class Nunjucks extends TemplateEngine { ); } - clearCache("addTag"); + // clearCache(); this.njkEnv.addExtension(name, tagObj); } @@ -238,8 +222,7 @@ class Nunjucks extends TemplateEngine { }; } - // Invalidate the caches. - clearCache("addShortcode"); + // clearCache(); this.njkEnv.addExtension(shortcodeName, new ShortcodeFunction()); } @@ -310,7 +293,7 @@ class Nunjucks extends TemplateEngine { }; } - clearCache("addPairedShortcode"); + // clearCache(); this.njkEnv.addExtension(shortcodeName, new PairedShortcodeFunction()); } From acad9bdb475c3b9b8ae2c3e8f71a74ce0cc3a6f9 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Tue, 24 Nov 2020 13:42:14 -0800 Subject: [PATCH 298/746] Further cleanup. --- src/Engines/Nunjucks.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 2a71ea46d..86971c734 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -37,7 +37,7 @@ const EleventyBaseError = require("../EleventyBaseError"); }; let _compile = NunjucksLib.Template.prototype._compile; - NunjucksLib.Template.prototype._compile = function (...args) { + NunjucksLib.Template.prototype._compile = function _wrap_compile(...args) { if (!this.compiled && !this.tmplProps && templateCache.has(getKey(this))) { let pathProps = templateCache.get(getKey(this)); this.blocks = pathProps.blocks; @@ -54,7 +54,10 @@ const EleventyBaseError = require("../EleventyBaseError"); let extensionIdCounter = 0; let addExtension = NunjucksLib.Environment.prototype.addExtension; - NunjucksLib.Environment.prototype.addExtension = function (name, ext) { + NunjucksLib.Environment.prototype.addExtension = function _wrap_addExtension( + name, + ext + ) { ext.__id = extensionIdCounter++; return addExtension.call(this, name, ext); }; @@ -121,7 +124,6 @@ class Nunjucks extends TemplateEngine { ); } - // clearCache(); this.njkEnv.addExtension(name, tagObj); } @@ -222,7 +224,6 @@ class Nunjucks extends TemplateEngine { }; } - // clearCache(); this.njkEnv.addExtension(shortcodeName, new ShortcodeFunction()); } @@ -293,7 +294,6 @@ class Nunjucks extends TemplateEngine { }; } - // clearCache(); this.njkEnv.addExtension(shortcodeName, new PairedShortcodeFunction()); } From e15ae7914c342a87e0b014c7ac32e4183666aa23 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Thu, 26 Nov 2020 11:03:44 -0800 Subject: [PATCH 299/746] Less aggressive cache invalidation for a small speedup. --- src/Engines/Nunjucks.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 86971c734..474f8244e 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -12,17 +12,6 @@ const EleventyBaseError = require("../EleventyBaseError"); (function () { let templateCache = new Map(); - let clearAndWrap = (name, obj = NunjucksLib.Environment) => { - let orig = obj.prototype[name]; - obj.prototype[name] = function (...args) { - templateCache.clear(); - return orig.call(this, ...args); - }; - }; - - clearAndWrap("addExtension"); - clearAndWrap("removeExtension"); - let getKey = (obj) => { return [ obj.path || obj.tmplStr, @@ -58,7 +47,9 @@ const EleventyBaseError = require("../EleventyBaseError"); name, ext ) { - ext.__id = extensionIdCounter++; + if (!("__id" in ext)) { + ext.__id = extensionIdCounter++; + } return addExtension.call(this, name, ext); }; })(); From cce873d6cfde4da12392615705c4bde175dd0dc6 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Thu, 3 Dec 2020 10:35:40 -0800 Subject: [PATCH 300/746] Optmises the hottest loop inside Nunjucks for another 10-20%. --- src/Engines/Nunjucks.js | 47 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 474f8244e..42184f861 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -6,8 +6,7 @@ const EleventyBaseError = require("../EleventyBaseError"); /* * This IFFE applies a monkey-patch to Nunjucks internals to cache - * compiled templates and re-use them where possible. It's relatively - * pessimistic (conservative) about cache clearing to ensure correctness. + * compiled templates and re-use them where possible. */ (function () { let templateCache = new Map(); @@ -52,6 +51,50 @@ const EleventyBaseError = require("../EleventyBaseError"); } return addExtension.call(this, name, ext); }; + + // NunjucksLib.runtime.Frame.prototype.set is the hotest in-template method. + // We replace it with a version that doesn't allocate a `parts` array on + // repeat key use. + let partsCache = new Map(); + let partsFromCache = (name) => { + if (partsCache.has(name)) { + return partsCache.get(name); + } + + let parts = name.split("."); + partsCache.set(name, parts); + return parts; + }; + + let frameSet = NunjucksLib.runtime.Frame.prototype.set; + NunjucksLib.runtime.Frame.prototype.set = function _replacement_set( + name, + val, + resolveUp + ) { + let parts = partsFromCache(name); + let frame = this; + let obj = frame.variables; + + if (resolveUp) { + if ((frame = this.resolve(parts[0], true))) { + frame.set(name, val); + return; + } + } + + // A slightly faster version of the intermediate object allocation loop + let count = parts.length - 1; + let i = 0; + let id = parts[0]; + while (i < count) { + if (!obj.hasOwnProperty(id)) { + obj = obj[id] = {}; + } + id = parts[++i]; + } + obj[id] = val; + }; })(); class EleventyShortcodeError extends EleventyBaseError {} From 8a47a0752fc91c2d76a7dd451e0da8d7b6e3b9de Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Fri, 4 Dec 2020 15:09:03 -0800 Subject: [PATCH 301/746] Re-enables NJK's internal caching by invalidating caches on change. --- src/Eleventy.js | 3 ++- src/Engines/Nunjucks.js | 35 ++++++++++++++++++++++++----------- src/EventBus.js | 17 +++++++++++++++++ src/TemplateContent.js | 4 ++++ test/TemplateTest.js | 28 ++++++++++++++++++---------- 5 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 src/EventBus.js diff --git a/src/Eleventy.js b/src/Eleventy.js index 0e210d5db..40b3d03a7 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -18,6 +18,7 @@ const deleteRequireCache = require("./Util/DeleteRequireCache"); const config = require("./Config"); const bench = require("./BenchmarkManager"); const debug = require("debug")("Eleventy"); +const eventBus = require("./EventBus"); /** * @module 11ty/eleventy/Eleventy @@ -449,7 +450,7 @@ Arguments: * @param {String} changedFilePath - File that triggered a re-run (added or modified) */ async _addFileToWatchQueue(changedFilePath) { - TemplateContent.deleteCached(changedFilePath); + eventBus.emit("resourceModified", changedFilePath); this.watchManager.addToPendingQueue(changedFilePath); } diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 42184f861..dfcc9614f 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -3,9 +3,10 @@ const TemplateEngine = require("./TemplateEngine"); const TemplatePath = require("../TemplatePath"); const EleventyErrorUtil = require("../EleventyErrorUtil"); const EleventyBaseError = require("../EleventyBaseError"); +const eventBus = require("../EventBus"); /* - * This IFFE applies a monkey-patch to Nunjucks internals to cache + * The IFFE below apply a monkey-patch to Nunjucks internals to cache * compiled templates and re-use them where possible. */ (function () { @@ -24,6 +25,17 @@ const EleventyBaseError = require("../EleventyBaseError"); ].join(" :: "); }; + let evictByPath = (path) => { + let keys = templateCache.keys(); + // Likely to be slow; do we care? + for (let k of keys) { + if (k.indexOf(path) >= 0) { + templateCache.delete(k); + } + } + }; + eventBus.on("resourceModified", evictByPath); + let _compile = NunjucksLib.Template.prototype._compile; NunjucksLib.Template.prototype._compile = function _wrap_compile(...args) { if (!this.compiled && !this.tmplProps && templateCache.has(getKey(this))) { @@ -109,16 +121,17 @@ class Nunjucks extends TemplateEngine { } setLibrary(env) { - this.njkEnv = - env || - new NunjucksLib.Environment( - new NunjucksLib.FileSystemLoader( - [super.getIncludesDir(), TemplatePath.getWorkingDir()], - { - noCache: true, - } - ) - ); + let fsLoader = new NunjucksLib.FileSystemLoader([ + super.getIncludesDir(), + TemplatePath.getWorkingDir(), + ]); + this.njkEnv = env || new NunjucksLib.Environment(fsLoader); + // Correct, but overbroad. Better would be to evict more granularly, but + // resolution from paths isn't straightforward. + eventBus.on("resourceModified", (path) => { + this.njkEnv.invalidateCache(); + }); + this.setEngineLib(this.njkEnv); this.addFilters(this.config.nunjucksFilters); diff --git a/src/EventBus.js b/src/EventBus.js new file mode 100644 index 000000000..682b87c3f --- /dev/null +++ b/src/EventBus.js @@ -0,0 +1,17 @@ +const EventEmitter = require("./Util/AsyncEventEmitter"); +const debug = require("debug")("Eleventy:EventBus"); + +/** + * @module 11ty/eleventy/EventBus + */ + +debug("Setting up global EventBus."); +/** + * Provides a global event bus that modules deep down in the stack can + * subscribe to from a global singleton for decoupled pub/sub. + * @type * {module:11ty/eleventy/Util/AsyncEventEmitter~AsyncEventEmitter} + */ +let bus = new EventEmitter(); +bus.setMaxListeners(100); + +module.exports = bus; diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 7fefe5810..7853e77aa 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -14,6 +14,7 @@ const config = require("./Config"); const debug = require("debug")("Eleventy:TemplateContent"); const debugDev = require("debug")("Dev:Eleventy:TemplateContent"); const bench = require("./BenchmarkManager").get("Aggregate"); +const eventBus = require("./EventBus"); class TemplateContentFrontMatterError extends EleventyBaseError {} class TemplateContentCompileError extends EleventyBaseError {} @@ -277,5 +278,8 @@ class TemplateContent { TemplateContent._inputCache = new Map(); TemplateContent._compileEngineCache = new Map(); +eventBus.on("resourceModified", (path) => { + TemplateContent.deleteCached(path); +}); module.exports = TemplateContent; diff --git a/test/TemplateTest.js b/test/TemplateTest.js index cd016bcd3..95cfd99f5 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2049,11 +2049,9 @@ test("Engine Singletons", async (t) => { }); test("Make sure layout cache takes new changes during watch (nunjucks)", async (t) => { - await fsp.writeFile( - "./test/stubs-layout-cache/_includes/include-script-1.js", - `alert("hi");`, - { encoding: "utf8" } - ); + let filePath = "./test/stubs-layout-cache/_includes/include-script-1.js"; + + await fsp.writeFile(filePath, `alert("hi");`, { encoding: "utf8" }); let tmpl = getNewTemplate( "./test/stubs-layout-cache/test.njk", @@ -2065,13 +2063,23 @@ test("Make sure layout cache takes new changes during watch (nunjucks)", async ( t.is((await tmpl.render(data)).trim(), ''); - await fsp.writeFile( - "./test/stubs-layout-cache/_includes/include-script-1.js", - `alert("bye");`, - { encoding: "utf8" } - ); + let eventBus = require("../src/EventBus"); + let chokidar = require("chokidar"); + let watcher = chokidar.watch(filePath, { interval: 10, persistent: true }); + watcher.on("change", (path, stats) => { + eventBus.emit("resourceModified", path); + }); + + await fsp.writeFile(filePath, `alert("bye");`, { encoding: "utf8" }); + + // Give Chokidar time to see the change; + await new Promise((res, rej) => { + setTimeout(res, 200); + }); t.is((await tmpl.render(data)).trim(), ''); + + await watcher.close(); }); test("Make sure layout cache takes new changes during watch (liquid)", async (t) => { From 81f88151f9ccbda771f1c986133c74acedc20ebb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Feb 2021 21:54:09 -0600 Subject: [PATCH 302/746] Adds --to=json command line option. Allows you to do more complex compilaton stuff programmatically without requiring any writes to the file system. --- cmd.js | 24 ++++++++++++++++++++++-- src/Eleventy.js | 43 ++++++++++++++++++++++++++++--------------- src/Template.js | 12 ++++++++++-- src/TemplateWriter.js | 34 ++++++++++++++++++++++++++-------- 4 files changed, 86 insertions(+), 27 deletions(-) diff --git a/cmd.js b/cmd.js index 8aeb5f288..8f8f41020 100755 --- a/cmd.js +++ b/cmd.js @@ -19,7 +19,15 @@ const EleventyErrorHandler = require("./src/EleventyErrorHandler"); try { const EleventyCommandCheckError = require("./src/EleventyCommandCheckError"); const argv = require("minimist")(process.argv.slice(2), { - string: ["input", "output", "formats", "config", "pathprefix", "port"], + string: [ + "input", + "output", + "formats", + "config", + "pathprefix", + "port", + "to", + ], boolean: [ "quiet", "version", @@ -86,7 +94,19 @@ try { } else if (argv.watch) { elev.watch(); } else { - elev.write(); + if (argv.to !== "fs" && argv.to !== "json") { + throw new EleventyCommandCheckError( + `Invalid --to value: ${argv.to}. Supported values: \`fs\` and \`json\`.` + ); + } + + let promise = elev.executeBuild(argv.to); + + if (argv.to === "json") { + promise.then((result) => { + console.log(result); + }); + } } }) .catch(EleventyErrorHandler.fatal); diff --git a/src/Eleventy.js b/src/Eleventy.js index 0e210d5db..8ea338f93 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -214,18 +214,6 @@ class Eleventy { await this.init(); } - /** - * Marks the finish of a run of Eleventy. - * - * @method - */ - finish() { - bench.finish(); - - (this.logger || console).log(this.logFinished()); - debug("Finished writing templates."); - } - /** * Logs some statistics after a complete run of Eleventy. * @@ -743,6 +731,17 @@ Arguments: this.logger = logger; } + /** + * Backwards compatibility method. + * + * @async + * @method + * @returns {Promise<{}>} + */ + async write() { + return this.executeBuild(); + } + /** * tbd. * @@ -750,7 +749,7 @@ Arguments: * @method * @returns {Promise<{}>} ret - tbd. */ - async write() { + async executeBuild(to = "fs") { let ret; if (this.logger) { EleventyErrorHandler.logger = this.logger; @@ -759,7 +758,16 @@ Arguments: await this.config.events.emit("beforeBuild"); try { - let promise = this.writer.write(); + let promise; + if (to === "fs") { + promise = this.writer.write(); + } else if (to === "json") { + promise = this.writer.getJSON(); + } else { + throw new Error( + `Invalid argument for \`Eleventy->executeBuild(${to})\`, expected "json" or "fs".` + ); + } ret = await promise; await this.config.events.emit("afterBuild"); @@ -772,7 +780,12 @@ Arguments: EleventyErrorHandler.fatal(e); } - this.finish(); + bench.finish(); + + if (to !== "json") { + (this.logger || console).log(this.logFinished()); + } + debug("Finished writing templates."); debug(` Getting frustrated? Have a suggestion/feature request/feedback? diff --git a/src/Template.js b/src/Template.js index ab99c3f67..2f102803f 100755 --- a/src/Template.js +++ b/src/Template.js @@ -653,10 +653,18 @@ class Template extends TemplateContent { return content; } - async writeMapEntry(mapEntry) { - await Promise.all( + async generateMapEntry(mapEntry, to) { + return Promise.all( mapEntry._pages.map(async (page) => { let content = await this.renderPageEntry(mapEntry, page); + if (to === "json") { + return { + url: page.url, + inputPath: page.inputPath, + content: content, + }; + } + return this._write(page.outputPath, content); }) ); diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index f8e9ed3b3..3c827b3b7 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -8,6 +8,7 @@ const EleventyErrorHandler = require("./EleventyErrorHandler"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const config = require("./Config"); +const lodashFlatten = require("lodash/flatten"); const debug = require("debug")("Eleventy:TemplateWriter"); const debugDev = require("debug")("Dev:Eleventy:TemplateWriter"); @@ -181,12 +182,13 @@ class TemplateWriter { return this.templateMap; } - async _writeTemplate(mapEntry) { + async _generateTemplate(mapEntry, to) { let tmpl = mapEntry.template; - return tmpl.writeMapEntry(mapEntry).then(() => { + return tmpl.generateMapEntry(mapEntry, to).then((pages) => { this.skippedCount += tmpl.getSkippedCount(); this.writeCount += tmpl.getWriteCount(); + return pages; }); } @@ -204,19 +206,19 @@ class TemplateWriter { }); } - async writeTemplates(paths) { + async generateTemplates(paths, to = "fs") { let promises = []; - // console.time("writeTemplates:_createTemplateMap"); + // console.time("generateTemplates:_createTemplateMap"); // TODO optimize await here await this._createTemplateMap(paths); - // console.timeEnd("writeTemplates:_createTemplateMap"); + // console.timeEnd("generateTemplates:_createTemplateMap"); debug("Template map created."); let usedTemplateContentTooEarlyMap = []; for (let mapEntry of this.templateMap.getMap()) { promises.push( - this._writeTemplate(mapEntry).catch(function (e) { + this._generateTemplate(mapEntry, to).catch(function (e) { // Premature templateContent in layout render, this also happens in // TemplateMap.populateContentDataInMap for non-layout content if (EleventyErrorUtil.isPrematureTemplateContentError(e)) { @@ -235,7 +237,7 @@ class TemplateWriter { for (let mapEntry of usedTemplateContentTooEarlyMap) { promises.push( - this._writeTemplate(mapEntry).catch(function (e) { + this._generateTemplate(mapEntry, to).catch(function (e) { return Promise.reject( new TemplateWriterWriteError( `Having trouble writing template (second pass): ${mapEntry.outputPath}`, @@ -261,7 +263,7 @@ class TemplateWriter { .getPassthroughManager() .isPassthroughCopyFile(paths, this.incrementalFile) ) { - promises.push(...(await this.writeTemplates(paths))); + promises.push(...(await this.generateTemplates(paths))); } return Promise.all(promises).catch((e) => { @@ -270,6 +272,22 @@ class TemplateWriter { }); } + // Passthrough copy not supported in JSON output. + // --incremental not supported in JSON output. + async getJSON() { + let paths = await this._getAllPaths(); + let promises = await this.generateTemplates(paths, "json"); + + return Promise.all(promises) + .then((results) => { + return lodashFlatten(results); // switch to results.flat(1) with Node 12+ + }) + .catch((e) => { + EleventyErrorHandler.error(e, "Error generating templates"); + throw e; + }); + } + setVerboseOutput(isVerbose) { this.isVerbose = isVerbose; } From 8eb901c2abef4a93dbba97e25a7b01305807c125 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Feb 2021 21:58:43 -0600 Subject: [PATCH 303/746] A little cleanup for --to --- cmd.js | 16 +++++++--------- src/Eleventy.js | 13 ++++++++++++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cmd.js b/cmd.js index 8f8f41020..4e673f3a6 100755 --- a/cmd.js +++ b/cmd.js @@ -94,18 +94,16 @@ try { } else if (argv.watch) { elev.watch(); } else { - if (argv.to !== "fs" && argv.to !== "json") { - throw new EleventyCommandCheckError( - `Invalid --to value: ${argv.to}. Supported values: \`fs\` and \`json\`.` - ); - } - - let promise = elev.executeBuild(argv.to); - if (argv.to === "json") { - promise.then((result) => { + elev.toJSON().then((result) => { console.log(result); }); + } else if (!argv.to || argv.to === "fs") { + elev.write(); + } else { + throw new EleventyCommandCheckError( + `Invalid --to value: ${argv.to}. Supported values: \`fs\` and \`json\`.` + ); } } }) diff --git a/src/Eleventy.js b/src/Eleventy.js index 8ea338f93..b52d8a821 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -732,7 +732,7 @@ Arguments: } /** - * Backwards compatibility method. + * Writes templates to the file system. * * @async * @method @@ -742,6 +742,17 @@ Arguments: return this.executeBuild(); } + /** + * Renders templates to a JSON object. + * + * @async + * @method + * @returns {Promise<{}>} + */ + async toJSON() { + return this.executeBuild("json"); + } + /** * tbd. * From 63fdbff9c96670339ebfd733725620f9d0684d37 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 6 Feb 2021 10:11:01 -0600 Subject: [PATCH 304/746] Fix tests. --- src/EleventyErrorUtil.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EleventyErrorUtil.js b/src/EleventyErrorUtil.js index af259838d..2ebcd2cf0 100644 --- a/src/EleventyErrorUtil.js +++ b/src/EleventyErrorUtil.js @@ -63,7 +63,8 @@ class EleventyErrorUtil { return ( e instanceof TemplateContentPrematureUseError || (e.originalError && - e.originalError.name === "RenderError" && + (e.originalError.name === "RenderError" || + e.originalError.name === "UndefinedVariableError") && e.originalError.originalError instanceof TemplateContentPrematureUseError) || // Liquid e.message.indexOf("TemplateContentPrematureUseError") > -1 From 103c117eba41a835c7d298c075f4f8ad9ec82c0b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 6 Feb 2021 15:13:33 -0600 Subject: [PATCH 305/746] Adds `ndjson` output. Makes sure that logged output is JSON compatible so that you can parse it from stdin --- cmd.js | 6 ++++-- src/Eleventy.js | 17 +++++++++++++++-- src/Template.js | 11 +++++++++-- src/TemplateWriter.js | 4 ++-- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/cmd.js b/cmd.js index 4e673f3a6..4639ba158 100755 --- a/cmd.js +++ b/cmd.js @@ -96,13 +96,15 @@ try { } else { if (argv.to === "json") { elev.toJSON().then((result) => { - console.log(result); + console.log(JSON.stringify(result)); }); + } else if (argv.to === "ndjson") { + elev.toNDJSON(); } else if (!argv.to || argv.to === "fs") { elev.write(); } else { throw new EleventyCommandCheckError( - `Invalid --to value: ${argv.to}. Supported values: \`fs\` and \`json\`.` + `Invalid --to value: ${argv.to}. Supported values: \`fs\`, \`json\`, and \`ndjson\`.` ); } } diff --git a/src/Eleventy.js b/src/Eleventy.js index b52d8a821..7c11f95f7 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -753,6 +753,17 @@ Arguments: return this.executeBuild("json"); } + /** + * Renders templates to an NDJSON object (newline delimited). + * + * @async + * @method + * @returns {Promise<{}>} + */ + async toNDJSON() { + return this.executeBuild("ndjson"); + } + /** * tbd. * @@ -773,7 +784,9 @@ Arguments: if (to === "fs") { promise = this.writer.write(); } else if (to === "json") { - promise = this.writer.getJSON(); + promise = this.writer.getJSON("json"); + } else if (to === "ndjson") { + promise = this.writer.getJSON("ndjson"); } else { throw new Error( `Invalid argument for \`Eleventy->executeBuild(${to})\`, expected "json" or "fs".` @@ -793,7 +806,7 @@ Arguments: bench.finish(); - if (to !== "json") { + if (to === "fs") { (this.logger || console).log(this.logFinished()); } debug("Finished writing templates."); diff --git a/src/Template.js b/src/Template.js index 2f102803f..85653b1a1 100755 --- a/src/Template.js +++ b/src/Template.js @@ -657,12 +657,19 @@ class Template extends TemplateContent { return Promise.all( mapEntry._pages.map(async (page) => { let content = await this.renderPageEntry(mapEntry, page); - if (to === "json") { - return { + if (to === "json" || to === "ndjson") { + let obj = { url: page.url, inputPath: page.inputPath, content: content, }; + + if (to === "ndjson") { + console.log(JSON.stringify(obj)); + } + + // json + return obj; } return this._write(page.outputPath, content); diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 3c827b3b7..603a6fe75 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -274,9 +274,9 @@ class TemplateWriter { // Passthrough copy not supported in JSON output. // --incremental not supported in JSON output. - async getJSON() { + async getJSON(to = "json") { let paths = await this._getAllPaths(); - let promises = await this.generateTemplates(paths, "json"); + let promises = await this.generateTemplates(paths, to); return Promise.all(promises) .then((results) => { From 24a13f87b8a3f5555a81e26405f3c458eff8ee5a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 6 Feb 2021 15:14:02 -0600 Subject: [PATCH 306/746] Update dependencies. --- package.json | 30 +++++++++++++++--------------- test/UserDataExtensionsTest.js | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index b01e7075b..66ff3e7e9 100755 --- a/package.json +++ b/package.json @@ -73,17 +73,17 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.4", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.6", "ava": "^3.13.0", - "husky": "^4.3.0", + "husky": "^4.3.8", "ink-docstrap": "1.3.2", - "js-yaml": "^3.14.0", + "js-yaml": "^4.0.0", "jsdoc": "3.6.6", - "lint-staged": "^10.5.1", + "lint-staged": "^10.5.4", "markdown-it-emoji": "^2.0.0", "node-sass": "^5.0.0", "nyc": "^15.1.0", - "prettier": "^2.1.2", + "prettier": "^2.2.1", "rimraf": "^3.0.2", "toml": "^3.0.0", "viperhtml": "^2.17.1", @@ -92,25 +92,25 @@ }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", - "browser-sync": "^2.26.13", + "browser-sync": "^2.26.14", "chalk": "^4.1.0", - "chokidar": "^3.4.3", - "debug": "^4.2.0", - "dependency-graph": "^0.9.0", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "dependency-graph": "^0.10.0", "ejs": "^3.1.5", - "fast-glob": "^3.2.4", - "fs-extra": "^9.0.1", + "fast-glob": "^3.2.5", + "fs-extra": "^9.1.0", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", "handlebars": "^4.7.6", - "liquidjs": "^9.16.1", + "liquidjs": "^9.22.1", "lodash": "^4.17.20", "luxon": "^1.25.0", - "markdown-it": "^12.0.2", + "markdown-it": "^12.0.4", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^5.0.0", - "mustache": "^4.0.1", + "mustache": "^4.1.0", "normalize-path": "^3.0.0", "nunjucks": "^3.2.2", "parse-filepath": "^1.0.2", @@ -118,7 +118,7 @@ "pretty": "^2.0.0", "pug": "^3.0.0", "recursive-copy": "^2.0.11", - "semver": "^7.3.2", + "semver": "^7.3.4", "slugify": "^1.4.6", "time-require": "^0.1.2", "valid-url": "^1.0.9" diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index f4e2343a7..5269c19fe 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -4,7 +4,7 @@ let yaml = require("js-yaml"); function injectDataExtensions(dataObj) { dataObj.config.dataExtensions = new Map([ - ["yaml", (s) => yaml.safeLoad(s)], + ["yaml", (s) => yaml.load(s)], ["nosj", JSON.parse], ]); } From 402ecf13426702f22d0f64a6413dde50d62aa06d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 6 Feb 2021 22:57:16 -0600 Subject: [PATCH 307/746] Resolves https://github.com/11ty/eleventy/pull/1629#pullrequestreview-584931567 --- src/Eleventy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 7c11f95f7..e002be3db 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -789,7 +789,7 @@ Arguments: promise = this.writer.getJSON("ndjson"); } else { throw new Error( - `Invalid argument for \`Eleventy->executeBuild(${to})\`, expected "json" or "fs".` + `Invalid argument for \`Eleventy->executeBuild(${to})\`, expected "json", "ndjson", or "fs".` ); } From cf4342acabed4de9069e314add0328ccae16feb3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 7 Feb 2021 14:29:21 -0600 Subject: [PATCH 308/746] Try to make the benchmarking test a bit more resilient on GitHub actions --- test/BenchmarkTest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index 97e3e952c..f06ffa8a9 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -11,9 +11,9 @@ test.cb("Standard Benchmark", (t) => { b.before(); setTimeout(function () { b.after(); - t.truthy(b.getTotal() >= 10); + t.truthy(b.getTotal() >= 0); t.end(); - }, 10); + }, 100); }); test.cb( From fd37bcae002969d6ba40a342a35c722efb0e5661 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Feb 2021 19:55:59 -0600 Subject: [PATCH 309/746] Use new ConsoleLogger and EleventyErrorHandler classes (not gross static things) to handle output. --- cmd.js | 5 +++ src/BenchmarkGroup.js | 17 ++++---- src/Eleventy.js | 58 +++++++++++++++++++-------- src/EleventyErrorHandler.js | 69 ++++++++++++++++---------------- src/Engines/Nunjucks.js | 1 - src/Template.js | 37 +++++++++-------- src/TemplateWriter.js | 20 +++++++-- src/Util/ConsoleLogger.js | 58 +++++++++++++++++++++++++++ test/ConsoleLoggerTest.js | 7 ++++ test/EleventyErrorHandlerTest.js | 33 +++++---------- test/EleventyTest.js | 66 ++++++++++++++++++++++++++---- test/UserDataExtensionsTest.js | 1 - test/stubs--to/test.md | 1 + test/stubs--to/test2.liquid | 4 ++ 14 files changed, 263 insertions(+), 114 deletions(-) create mode 100644 src/Util/ConsoleLogger.js create mode 100644 test/ConsoleLoggerTest.js create mode 100644 test/stubs--to/test.md create mode 100644 test/stubs--to/test2.liquid diff --git a/cmd.js b/cmd.js index 4639ba158..8bbaf268c 100755 --- a/cmd.js +++ b/cmd.js @@ -71,6 +71,11 @@ try { quietMode: argv.quiet, }); + if (argv.to === "json" || argv.to === "ndjson") { + // override logging output + elev.setIsVerbose(false); + } + elev.setConfigPathOverride(argv.config); elev.setPathPrefix(argv.pathprefix); elev.setDryRun(argv.dryrun); diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index e9b82a492..708b52ec9 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -1,5 +1,4 @@ -const chalk = require("chalk"); - +const ConsoleLogger = require("./Util/ConsoleLogger"); const Benchmark = require("./Benchmark"); const debugBenchmark = require("debug")("Eleventy:Benchmark"); @@ -8,12 +7,14 @@ class BenchmarkGroup { this.benchmarks = {}; // Warning: aggregate benchmarks automatically default to false via BenchmarkManager->getBenchmarkGroup this.isVerbose = true; + this.logger = new ConsoleLogger(this.isVerbose); this.minimumThresholdMs = 0; this.minimumThresholdPercent = 8; } setIsVerbose(isVerbose) { this.isVerbose = isVerbose; + this.logger.isVerbose = isVerbose; } reset() { @@ -91,20 +92,16 @@ class BenchmarkGroup { ); } - let str = chalk.yellow( - `Benchmark (${label}): ${type} took ${totalForBenchmark.toFixed(0)}ms ${ - extraOutput.length ? `(${extraOutput.join(", ")})` : "" - }` - ); + let str = `Benchmark (${label}): ${type} took ${totalForBenchmark.toFixed( + 0 + )}ms ${extraOutput.length ? `(${extraOutput.join(", ")})` : ""}`; if ( (isAbsoluteMinimumComparison && totalForBenchmark >= this.minimumThresholdMs) || percent > this.minimumThresholdPercent ) { - if (this.isVerbose) { - console.log(str); - } + this.logger.warn(str); } if (totalForBenchmark.toFixed(0) > 0) { diff --git a/src/Eleventy.js b/src/Eleventy.js index e002be3db..1a03f9882 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -10,6 +10,7 @@ const EleventyServe = require("./EleventyServe"); const EleventyWatch = require("./EleventyWatch"); const EleventyWatchTargets = require("./EleventyWatchTargets"); const EleventyFiles = require("./EleventyFiles"); +const ConsoleLogger = require("./Util/ConsoleLogger"); const { performance } = require("perf_hooks"); const templateCache = require("./TemplateCache"); @@ -334,6 +335,14 @@ Verbose Output: ${this.verboseMode}`); if (bench) { bench.setVerboseOutput(this._isVerboseMode); } + + if (this.logger) { + this.logger.isVerbose = this._isVerboseMode; + } + + if (this.errorHandler) { + this.errorHandler.isVerbose = this._isVerboseMode; + } } /* Getter for verbose mode */ @@ -341,6 +350,26 @@ Verbose Output: ${this.verboseMode}`); return this._isVerboseMode; } + /* Getter for logger */ + get logger() { + if (!this._logger) { + this._logger = new ConsoleLogger(); + this._logger.isVerbose = this.verboseMode; + } + + return this._logger; + } + + /* Getter for error handler */ + get errorHandler() { + if (!this._errorHandler) { + this._errorHandler = new EleventyErrorHandler(); + this._errorHandler.isVerbose = this.verboseMode; + } + + return this._errorHandler; + } + /** * Updates the verbose mode of Eleventy. * @@ -521,12 +550,12 @@ Arguments: this.watchManager.setBuildFinished(); if (this.watchManager.getPendingQueueSize() > 0) { - console.log( + this.logger.log( `You saved while Eleventy was running, let’s run again. (${this.watchManager.getPendingQueueSize()} remain)` ); await this._watch(); } else { - console.log("Watching…"); + this.logger.log("Watching…"); } } @@ -666,7 +695,7 @@ Arguments: this.watcherBench.finish("Watch"); - console.log("Watching…"); + this.logger.log("Watching…"); this.watcher = watcher; @@ -683,22 +712,22 @@ Arguments: }); } catch (e) { if (e instanceof EleventyBaseError) { - EleventyErrorHandler.error(e, "Eleventy watch error"); + this.errorHandler.error(e, "Eleventy watch error"); this.watchManager.setBuildFinished(); } else { - EleventyErrorHandler.fatal(e, "Eleventy fatal watch error"); + this.errorHandler.fatal(e, "Eleventy fatal watch error"); this.stopWatch(); } } }; watcher.on("change", async (path) => { - console.log("File changed:", path); + this.logger.log(`File changed: ${path}`); await watchRun(path); }); watcher.on("add", async (path) => { - console.log("File added:", path); + this.logger.log(`File added: ${path}`); await watchRun(path); }); @@ -773,9 +802,6 @@ Arguments: */ async executeBuild(to = "fs") { let ret; - if (this.logger) { - EleventyErrorHandler.logger = this.logger; - } await this.config.events.emit("beforeBuild"); @@ -794,20 +820,23 @@ Arguments: } ret = await promise; + if (to === "ndjson") { + ret = ret.join("\n"); + } await this.config.events.emit("afterBuild"); } catch (e) { - EleventyErrorHandler.initialMessage( + this.errorHandler.initialMessage( "Problem writing Eleventy templates", "error", "red" ); - EleventyErrorHandler.fatal(e); + this.errorHandler.fatal(e); } bench.finish(); if (to === "fs") { - (this.logger || console).log(this.logFinished()); + this.logger.log(this.logFinished()); } debug("Finished writing templates."); @@ -815,9 +844,6 @@ Arguments: Getting frustrated? Have a suggestion/feature request/feedback? I want to hear it! Open an issue: https://github.com/11ty/eleventy/issues/new`); - // unset the logger - EleventyErrorHandler.logger = undefined; - return ret; } } diff --git a/src/EleventyErrorHandler.js b/src/EleventyErrorHandler.js index a7fa95d08..0f5b13728 100644 --- a/src/EleventyErrorHandler.js +++ b/src/EleventyErrorHandler.js @@ -1,40 +1,56 @@ const chalk = require("chalk"); +const ConsoleLogger = require("./Util/ConsoleLogger"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const debug = require("debug")("Eleventy:EleventyErrorHandler"); class EleventyErrorHandler { - static get isChalkEnabled() { - if (this._isChalkEnabled !== undefined) { - return this._isChalkEnabled; + constructor() { + this._isVerbose = true; + } + + get isVerbose() { + return this._isVerbose; + } + + set isVerbose(verbose) { + this._isVerbose = !!verbose; + this.logger = !!verbose; + } + + get logger() { + if (!this._logger) { + this._logger = new ConsoleLogger(); + this._logger.isVerbose = this.isVerbose; } - return true; + + return this._logger; } - static set isChalkEnabled(enabled) { - this._isChalkEnabled = !!enabled; + set logger(logger) { + this._logger = logger; } - static warn(e, msg) { + warn(e, msg) { if (msg) { - EleventyErrorHandler.initialMessage(msg, "warn", "yellow"); + this.initialMessage(msg, "warn", "yellow"); } - EleventyErrorHandler.log(e, "warn"); + this.log(e, "warn"); } - static fatal(e, msg) { - EleventyErrorHandler.error(e, msg); + fatal(e, msg) { + this.error(e, msg); process.exitCode = 1; } - static error(e, msg) { + error(e, msg) { if (msg) { - EleventyErrorHandler.initialMessage(msg, "error", "red"); + this.initialMessage(msg, "error", "red"); } - EleventyErrorHandler.log(e, "error"); + this.log(e, "error"); } //https://nodejs.org/api/process.html - static log(e, type = "log", prefix = ">") { + log(e, type = "log", prefix = ">") { let ref = e; while (ref) { let nextRef = ref.originalError; @@ -42,7 +58,7 @@ class EleventyErrorHandler { nextRef = EleventyErrorUtil.deconvertErrorToObject(ref); } - EleventyErrorHandler.message( + this.logger.message( (process.env.DEBUG ? "" : `${prefix} `) + `${( EleventyErrorUtil.cleanMessage(ref.message) || @@ -67,36 +83,21 @@ class EleventyErrorHandler { "(Repeated output has been truncated…)" ); } - EleventyErrorHandler.message( - prefix + stackStr.split("\n").join("\n" + prefix) - ); + this.logger.message(prefix + stackStr.split("\n").join("\n" + prefix)); } ref = nextRef; } } - static initialMessage(message, type = "log", chalkColor = "blue") { + initialMessage(message, type = "log", chalkColor = "blue") { if (message) { - EleventyErrorHandler.message( + this.logger.message( message + ":" + (process.env.DEBUG ? "" : " (more in DEBUG output)"), type, chalkColor ); } } - - static message(message, type = "log", chalkColor) { - if (process.env.DEBUG) { - debug(message); - } else { - let logger = EleventyErrorHandler.logger || console; - if (chalkColor && EleventyErrorHandler.isChalkEnabled) { - logger[type](chalk[chalkColor](message)); - } else { - logger[type](message); - } - } - } } module.exports = EleventyErrorHandler; diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 01e349488..3a3efa500 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -148,7 +148,6 @@ class Nunjucks extends TemplateEngine { }); } else { try { - // console.log( shortcodeFn.toString() ); return new NunjucksLib.runtime.SafeString( shortcodeFn.call( Nunjucks._normalizeShortcodeContext(context), diff --git a/src/Template.js b/src/Template.js index 85653b1a1..560ae77b4 100755 --- a/src/Template.js +++ b/src/Template.js @@ -1,5 +1,4 @@ const fs = require("fs-extra"); -const chalk = require("chalk"); const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); const lodashIsObject = require("lodash/isObject"); @@ -15,6 +14,7 @@ const TemplateFileSlug = require("./TemplateFileSlug"); const ComputedData = require("./ComputedData"); const Pagination = require("./Plugins/Pagination"); const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); +const ConsoleLogger = require("./Util/ConsoleLogger"); const debug = require("debug")("Eleventy:Template"); const debugDev = require("debug")("Dev:Eleventy:Template"); @@ -61,8 +61,17 @@ class Template extends TemplateContent { this.filePathStem = this.fileSlug.getFullPathWithoutExtension(); } + get logger() { + if (!this._logger) { + this._logger = new ConsoleLogger(); + this._logger.isVerbose = this.isVerbose; + } + return this._logger; + } + setIsVerbose(isVerbose) { this.isVerbose = isVerbose; + this.logger.isVerbose = isVerbose; } setDryRun(isDryRun) { @@ -387,11 +396,9 @@ class Template extends TemplateContent { str, outputPath ); - if (!str && this.isVerbose) { - console.log( - chalk.yellow( - `Warning: Transform \`${transform.name}\` returned empty when writing ${outputPath} from ${inputPath}.` - ) + if (!str) { + this.logger.warn( + `Warning: Transform \`${transform.name}\` returned empty when writing ${outputPath} from ${inputPath}.` ); } } @@ -610,15 +617,11 @@ class Template extends TemplateContent { } let engineList = this.templateRender.getReadableEnginesListDifferingFromFileExtension(); - if (this.isVerbose) { - console.log( - `${lang.start} ${outputPath} from ${this.inputPath}${ - engineList ? ` (${engineList})` : "" - }` - ); - } else { - debug(`${lang.start} %o from %o.`, outputPath, this.inputPath); - } + this.logger.log( + `${lang.start} ${outputPath} from ${this.inputPath}${ + engineList ? ` (${engineList})` : "" + }` + ); if (!shouldWriteFile) { this.skippedCount++; @@ -665,7 +668,9 @@ class Template extends TemplateContent { }; if (to === "ndjson") { - console.log(JSON.stringify(obj)); + let jsonString = JSON.stringify(obj); + console.log(jsonString); + return jsonString; } // json diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 603a6fe75..0409adfbb 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -54,6 +54,16 @@ class TemplateWriter { this._templateFormats = value; } + /* Getter for error handler */ + get errorHandler() { + if (!this._errorHandler) { + this._errorHandler = new EleventyErrorHandler(); + this._errorHandler.isVerbose = this.verboseMode; + } + + return this._errorHandler; + } + /* For testing */ overrideConfig(config) { this.config = config; @@ -199,7 +209,7 @@ class TemplateWriter { } return passthroughManager.copyAll(paths).catch((e) => { - EleventyErrorHandler.warn(e, "Error with passthrough copy"); + this.errorHandler.warn(e, "Error with passthrough copy"); return Promise.reject( new TemplateWriterWriteError("Having trouble copying", e) ); @@ -267,7 +277,7 @@ class TemplateWriter { } return Promise.all(promises).catch((e) => { - EleventyErrorHandler.error(e, "Error writing templates"); + this.errorHandler.error(e, "Error writing templates"); throw e; }); } @@ -280,16 +290,18 @@ class TemplateWriter { return Promise.all(promises) .then((results) => { - return lodashFlatten(results); // switch to results.flat(1) with Node 12+ + let flat = lodashFlatten(results); // switch to results.flat(1) with Node 12+ + return flat; }) .catch((e) => { - EleventyErrorHandler.error(e, "Error generating templates"); + this.errorHandler.error(e, "Error generating templates"); throw e; }); } setVerboseOutput(isVerbose) { this.isVerbose = isVerbose; + this.errorHandler.isVerbose = isVerbose; } setDryRun(isDryRun) { diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js new file mode 100644 index 000000000..c5f76366c --- /dev/null +++ b/src/Util/ConsoleLogger.js @@ -0,0 +1,58 @@ +const chalk = require("chalk"); +const debug = require("debug")("Eleventy:Logger"); + +class ConsoleLogger { + constructor() { + this._isVerbose = true; + } + + get isVerbose() { + return this._isVerbose; + } + + set isVerbose(verbose) { + this._isVerbose = !!verbose; + } + + get isChalkEnabled() { + if (this._isChalkEnabled !== undefined) { + return this._isChalkEnabled; + } + return true; + } + + set isChalkEnabled(enabled) { + this._isChalkEnabled = !!enabled; + } + + overrideLogger(logger) { + this._logger = logger; + } + + warn(msg) { + this.message(msg, "warn", "yellow"); + } + + error(msg) { + this.message(msg, "error", "red"); + } + + log(msg) { + this.message(msg); + } + + message(message, type = "log", chalkColor = false) { + if (!this.isVerbose || process.env.DEBUG) { + debug(message); + } else if (this._logger !== false) { + let logger = this._logger || console; + if (chalkColor && this.isChalkEnabled) { + logger[type](chalk[chalkColor](message)); + } else { + logger[type](message); + } + } + } +} + +module.exports = ConsoleLogger; diff --git a/test/ConsoleLoggerTest.js b/test/ConsoleLoggerTest.js new file mode 100644 index 000000000..11fd42cec --- /dev/null +++ b/test/ConsoleLoggerTest.js @@ -0,0 +1,7 @@ +const test = require("ava"); +const ConsoleLogger = require("../src/Util/ConsoleLogger"); + +test("Disable chalk", (t) => { + ConsoleLogger.isChalkEnabled = false; + t.is(ConsoleLogger.isChalkEnabled, false); +}); diff --git a/test/EleventyErrorHandlerTest.js b/test/EleventyErrorHandlerTest.js index b9968740d..cc7922908 100644 --- a/test/EleventyErrorHandlerTest.js +++ b/test/EleventyErrorHandlerTest.js @@ -1,13 +1,10 @@ const test = require("ava"); const EleventyErrorHandler = require("../src/EleventyErrorHandler"); -let output = []; - -test.beforeEach((t) => { - output = []; - - EleventyErrorHandler.isChalkEnabled = false; - EleventyErrorHandler.logger = { +test("Log a warning, error", (t) => { + let errorHandler = new EleventyErrorHandler(); + let output = []; + errorHandler.logger = { log: function (str) { output.push(str); }, @@ -17,21 +14,12 @@ test.beforeEach((t) => { error: function (str) { output.push(str); }, + message: function (str) { + output.push(str); + }, }; -}); - -test.afterEach((t) => { - EleventyErrorHandler.isChalkEnabled = true; - EleventyErrorHandler.logger = null; -}); -test("Disable chalk", (t) => { - EleventyErrorHandler.isChalkEnabled = false; - t.is(EleventyErrorHandler.isChalkEnabled, false); -}); - -test("Log a warning, error", (t) => { - EleventyErrorHandler.warn(new Error("Test warning"), "Hello"); + errorHandler.warn(new Error("Test warning"), "Hello"); let expected = `Hello: (more in DEBUG output) > Test warning @@ -40,12 +28,9 @@ test("Log a warning, error", (t) => { Error: Test warning`; t.is(output.join("\n").substr(0, expected.length), expected); - // normally this would be multiple tests but we do this garbage because - // tests run async and it doesn’t work with the static methods in - // EleventyErrorHandler output = []; - EleventyErrorHandler.error(new Error("Test error"), "It’s me"); + errorHandler.error(new Error("Test error"), "It’s me"); expected = `It’s me: (more in DEBUG output) > Test error diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 8adca1dbf..10658be86 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -128,14 +128,7 @@ test("Eleventy set input/output, one file input exitCode", async (t) => { "./test/stubs/exitCode/failure.njk", "./test/stubs/exitCode/_site" ); - - // TODO make this output quieter - elev.setLogger({ - log: function () {}, - warn: function () {}, - error: function () {}, - }); - + elev.setIsVerbose(false); await elev.init(); await elev.write(); @@ -143,3 +136,60 @@ test("Eleventy set input/output, one file input exitCode", async (t) => { process.exitCode = previousExitCode; }); + +test("Eleventy to json", async (t) => { + let elev = new Eleventy("./test/stubs--to/", "./test/stubs--to/_site"); + await elev.init(); + let result = await elev.toJSON(); + + t.deepEqual( + result.filter((entry) => entry.url === "/test/"), + [ + { + url: "/test/", + inputPath: "./test/stubs--to/test.md", + content: "

hi

\n", + }, + ] + ); + t.deepEqual( + result.filter((entry) => entry.url === "/test2/"), + [ + { + url: "/test2/", + inputPath: "./test/stubs--to/test2.liquid", + content: "hello", + }, + ] + ); +}); + +test("Eleventy to ndjson", async (t) => { + let elev = new Eleventy("./test/stubs--to/", "./test/stubs--to/_site"); + + elev.setIsVerbose(false); + + await elev.init(); + let results = await elev.toNDJSON(); + let parsed = results.split("\n").map((entry) => JSON.parse(entry)); + t.deepEqual( + parsed.filter((entry) => entry.url === "/test/"), + [ + { + url: "/test/", + inputPath: "./test/stubs--to/test.md", + content: "

hi

\n", + }, + ] + ); + t.deepEqual( + parsed.filter((entry) => entry.url === "/test2/"), + [ + { + url: "/test2/", + inputPath: "./test/stubs--to/test2.liquid", + content: "hello", + }, + ] + ); +}); diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index f4e2343a7..753f2010b 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -27,7 +27,6 @@ test("Local data", async (t) => { let withLocalData = await dataObj.getLocalData( "./test/stubs-630/component-yaml/component.njk" ); - // console.log("localdata", withLocalData); t.is(withLocalData.yamlKey1, "yaml1"); t.is(withLocalData.yamlKey2, "yaml2"); diff --git a/test/stubs--to/test.md b/test/stubs--to/test.md new file mode 100644 index 000000000..77ebc6577 --- /dev/null +++ b/test/stubs--to/test.md @@ -0,0 +1 @@ +# hi diff --git a/test/stubs--to/test2.liquid b/test/stubs--to/test2.liquid new file mode 100644 index 000000000..a9a3491c3 --- /dev/null +++ b/test/stubs--to/test2.liquid @@ -0,0 +1,4 @@ +--- +hi: hello +--- +{{ hi }} \ No newline at end of file From a1e6a7551a7bb52556f6ee14935b5ce25e12ba03 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Feb 2021 19:56:26 -0600 Subject: [PATCH 310/746] Removes addExtension warning from console output. --- src/UserConfig.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index 6d5991ea9..45fec0aa5 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -645,12 +645,6 @@ class UserConfig { return; } - console.log( - chalk.yellow( - "Warning: Configuration API `addExtension` is an experimental Eleventy feature with an unstable API. Be careful!" - ) - ); - this.extensionMap.add( Object.assign( { From fbe31abead7641ebde466978337bd6ea941c01a7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Feb 2021 19:58:49 -0600 Subject: [PATCH 311/746] More resilient benchmark tests for GitHub actions failures --- test/BenchmarkTest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index f06ffa8a9..6f57bc990 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -30,7 +30,7 @@ test.cb( b.after(); t.truthy(b.getTotal() >= 10); t.end(); - }, 10); + }, 100); } ); @@ -49,5 +49,5 @@ test.cb("Reset Benchmark", (t) => { b.after(); }); t.end(); - }, 10); + }, 100); }); From a349edd49f3c512d673458089dfdb8005e2b03fa Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Feb 2021 20:13:46 -0600 Subject: [PATCH 312/746] Share the same logger instance, if possible. --- src/Eleventy.js | 20 ++++++++------------ src/Template.js | 8 +++++++- src/TemplateWriter.js | 18 ++++++++++++++++++ src/Util/ConsoleLogger.js | 4 ++++ test/EleventyTest.js | 21 +++++++++++++++++++++ 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 1a03f9882..94ebfd4e6 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -305,7 +305,7 @@ class Eleventy { this.templateData, this.isPassthroughAll ); - + this.writer.logger = this.logger; this.writer.extensionMap = this.extensionMap; this.writer.setEleventyFiles(this.eleventyFiles); @@ -350,7 +350,7 @@ Verbose Output: ${this.verboseMode}`); return this._isVerboseMode; } - /* Getter for logger */ + /* Getter for Logger */ get logger() { if (!this._logger) { this._logger = new ConsoleLogger(); @@ -360,11 +360,17 @@ Verbose Output: ${this.verboseMode}`); return this._logger; } + /* Setter for Logger */ + set logger(logger) { + this._logger = logger; + } + /* Getter for error handler */ get errorHandler() { if (!this._errorHandler) { this._errorHandler = new EleventyErrorHandler(); this._errorHandler.isVerbose = this.verboseMode; + this._errorHandler.logger = this.logger; } return this._errorHandler; @@ -750,16 +756,6 @@ Arguments: this.eleventyServe.serve(port); } - /* For testing */ - /** - * Updates the logger. - * - * @param {} logger - The new logger. - */ - setLogger(logger) { - this.logger = logger; - } - /** * Writes templates to the file system. * diff --git a/src/Template.js b/src/Template.js index 560ae77b4..562825d7c 100755 --- a/src/Template.js +++ b/src/Template.js @@ -69,6 +69,11 @@ class Template extends TemplateContent { return this._logger; } + /* Setter for Logger */ + set logger(logger) { + this._logger = logger; + } + setIsVerbose(isVerbose) { this.isVerbose = isVerbose; this.logger.isVerbose = isVerbose; @@ -669,7 +674,7 @@ class Template extends TemplateContent { if (to === "ndjson") { let jsonString = JSON.stringify(obj); - console.log(jsonString); + this.logger.stdout(jsonString); return jsonString; } @@ -692,6 +697,7 @@ class Template extends TemplateContent { this.extensionMap ); tmpl.config = this.config; + tmpl.logger = this.logger; for (let transform of this.transforms) { tmpl.addTransform(transform.name, transform.callback); diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 0409adfbb..ea83d084b 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -6,6 +6,7 @@ const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyErrorHandler = require("./EleventyErrorHandler"); const EleventyErrorUtil = require("./EleventyErrorUtil"); +const ConsoleLogger = require("./Util/ConsoleLogger"); const config = require("./Config"); const lodashFlatten = require("lodash/flatten"); @@ -59,11 +60,27 @@ class TemplateWriter { if (!this._errorHandler) { this._errorHandler = new EleventyErrorHandler(); this._errorHandler.isVerbose = this.verboseMode; + this._errorHandler.logger = this.logger; } return this._errorHandler; } + /* Getter for Logger */ + get logger() { + if (!this._logger) { + this._logger = new ConsoleLogger(); + this._logger.isVerbose = this.verboseMode; + } + + return this._logger; + } + + /* Setter for Logger */ + set logger(logger) { + this._logger = logger; + } + /* For testing */ overrideConfig(config) { this.config = config; @@ -133,6 +150,7 @@ class TemplateWriter { this.templateData, this.extensionMap ); + tmpl.logger = this.logger; this._templatePathCache.set(path, tmpl); tmpl.setIsVerbose(this.isVerbose); diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index c5f76366c..8876b8f25 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -41,6 +41,10 @@ class ConsoleLogger { this.message(msg); } + stdout(msg) { + console.log(msg); + } + message(message, type = "log", chalkColor = false) { if (!this.isVerbose || process.env.DEBUG) { debug(message); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 10658be86..e13d15df9 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -139,7 +139,10 @@ test("Eleventy set input/output, one file input exitCode", async (t) => { test("Eleventy to json", async (t) => { let elev = new Eleventy("./test/stubs--to/", "./test/stubs--to/_site"); + elev.setIsVerbose(false); + await elev.init(); + let result = await elev.toJSON(); t.deepEqual( @@ -169,8 +172,26 @@ test("Eleventy to ndjson", async (t) => { elev.setIsVerbose(false); + let output = []; + let fn = function (str) { + output.push(str); + }; + elev.logger = { + log: fn, + warn: fn, + error: fn, + message: fn, + stdout: fn, + }; + await elev.init(); + let results = await elev.toNDJSON(); + t.deepEqual(output, [ + `{"url":"/test/","inputPath":"./test/stubs--to/test.md","content":"

hi

\\n"}`, + `{"url":"/test2/","inputPath":"./test/stubs--to/test2.liquid","content":"hello"}`, + ]); + let parsed = results.split("\n").map((entry) => JSON.parse(entry)); t.deepEqual( parsed.filter((entry) => entry.url === "/test/"), From 9c0079d2354d3fcbf5ecdd9c7b3ed653706d53c6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Feb 2021 20:16:37 -0600 Subject: [PATCH 313/746] Cleaner output for --to=json --- cmd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd.js b/cmd.js index 8bbaf268c..85d315188 100755 --- a/cmd.js +++ b/cmd.js @@ -101,7 +101,7 @@ try { } else { if (argv.to === "json") { elev.toJSON().then((result) => { - console.log(JSON.stringify(result)); + console.log(JSON.stringify(result, null, 2)); }); } else if (argv.to === "ndjson") { elev.toNDJSON(); From d840f0ebb9a02ca00e89dea92ec657294f8f12af Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 9 Feb 2021 22:50:40 -0600 Subject: [PATCH 314/746] Returns a readable stream when using .toNDJSON in Eleventy class programmatic API. --- cmd.js | 1 + package.json | 1 + src/Eleventy.js | 19 ++++++-- src/Template.js | 4 +- src/Util/ConsoleLogger.js | 24 +++++++++- test/EleventyTest.js | 92 +++++++++++++++++++++++++++++---------- 6 files changed, 111 insertions(+), 30 deletions(-) diff --git a/cmd.js b/cmd.js index 85d315188..2dab3a76c 100755 --- a/cmd.js +++ b/cmd.js @@ -76,6 +76,7 @@ try { elev.setIsVerbose(false); } + elev.setViaCommandLine(true); elev.setConfigPathOverride(argv.config); elev.setPathPrefix(argv.pathprefix); elev.setDryRun(argv.dryrun); diff --git a/package.json b/package.json index b01e7075b..6b773b3ce 100755 --- a/package.json +++ b/package.json @@ -120,6 +120,7 @@ "recursive-copy": "^2.0.11", "semver": "^7.3.2", "slugify": "^1.4.6", + "split": "^1.0.1", "time-require": "^0.1.2", "valid-url": "^1.0.9" }, diff --git a/src/Eleventy.js b/src/Eleventy.js index 94ebfd4e6..4b95fde4b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -105,6 +105,16 @@ class Eleventy { return new Date().getTime(); } + /** + * Sets the whether or not this instance was created from the command line (via cmd.js) + * + * @method + * @param {Boolean} isViaCommandLine + */ + setViaCommandLine(isViaCommandLine) { + this.isViaCommandLine = isViaCommandLine; + } + /** @type {String} */ get input() { return this.rawInput || this.config.dir.input; @@ -355,6 +365,7 @@ Verbose Output: ${this.verboseMode}`); if (!this._logger) { this._logger = new ConsoleLogger(); this._logger.isVerbose = this.verboseMode; + this._logger.isViaCommandLine = this.isViaCommandLine; } return this._logger; @@ -779,11 +790,11 @@ Arguments: } /** - * Renders templates to an NDJSON object (newline delimited). + * Returns a stream of new line delimited (NDJSON) objects * * @async * @method - * @returns {Promise<{}>} + * @returns {Promise<{ReadableStream}>} */ async toNDJSON() { return this.executeBuild("ndjson"); @@ -816,8 +827,10 @@ Arguments: } ret = await promise; + if (to === "ndjson") { - ret = ret.join("\n"); + // return a stream + ret = this.logger.closeStream(to); } await this.config.events.emit("afterBuild"); } catch (e) { diff --git a/src/Template.js b/src/Template.js index 562825d7c..a6a579db9 100755 --- a/src/Template.js +++ b/src/Template.js @@ -674,8 +674,8 @@ class Template extends TemplateContent { if (to === "ndjson") { let jsonString = JSON.stringify(obj); - this.logger.stdout(jsonString); - return jsonString; + this.logger.toStream(jsonString, "\n"); + return; } // json diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 8876b8f25..cac66aba3 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -1,9 +1,13 @@ const chalk = require("chalk"); const debug = require("debug")("Eleventy:Logger"); +const Readable = require("stream").Readable; +const split = require("split"); class ConsoleLogger { constructor() { this._isVerbose = true; + this.isViaCommandLine = false; + this.outputStream = Readable(); } get isVerbose() { @@ -41,8 +45,24 @@ class ConsoleLogger { this.message(msg); } - stdout(msg) { - console.log(msg); + toStream(msg, suffix = "") { + // only output to stdout/console if we’re running in command line + if (this.isViaCommandLine) { + console.log(msg); + } else { + this.outputStream.push(msg + suffix); + } + } + + closeStream(to = "") { + this.outputStream.push(null); + + if (to === "ndjson") { + return this.outputStream.pipe( + split(JSON.parse, null, { trailing: false }) + ); + } + return this.outputStream; } message(message, type = "log", chalkColor = false) { diff --git a/test/EleventyTest.js b/test/EleventyTest.js index e13d15df9..f3d9fc511 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -138,7 +138,7 @@ test("Eleventy set input/output, one file input exitCode", async (t) => { }); test("Eleventy to json", async (t) => { - let elev = new Eleventy("./test/stubs--to/", "./test/stubs--to/_site"); + let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); await elev.init(); @@ -167,10 +167,11 @@ test("Eleventy to json", async (t) => { ); }); -test("Eleventy to ndjson", async (t) => { - let elev = new Eleventy("./test/stubs--to/", "./test/stubs--to/_site"); +test("Eleventy to ndjson (via command line-ish, to stdout)", async (t) => { + let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); + elev.setViaCommandLine(true); let output = []; let fn = function (str) { @@ -181,36 +182,81 @@ test("Eleventy to ndjson", async (t) => { warn: fn, error: fn, message: fn, - stdout: fn, + toStream: fn, }; await elev.init(); + await elev.toNDJSON(); - let results = await elev.toNDJSON(); - t.deepEqual(output, [ - `{"url":"/test/","inputPath":"./test/stubs--to/test.md","content":"

hi

\\n"}`, - `{"url":"/test2/","inputPath":"./test/stubs--to/test2.liquid","content":"hello"}`, - ]); - - let parsed = results.split("\n").map((entry) => JSON.parse(entry)); t.deepEqual( - parsed.filter((entry) => entry.url === "/test/"), + output.filter((entry) => entry.startsWith(`{"url":"/test/"`)), [ - { - url: "/test/", - inputPath: "./test/stubs--to/test.md", - content: "

hi

\n", - }, + `{"url":"/test/","inputPath":"./test/stubs--to/test.md","content":"

hi

\\n"}`, ] ); t.deepEqual( - parsed.filter((entry) => entry.url === "/test2/"), + output.filter((entry) => entry.startsWith(`{"url":"/test2/"`)), [ - { - url: "/test2/", - inputPath: "./test/stubs--to/test2.liquid", - content: "hello", - }, + `{"url":"/test2/","inputPath":"./test/stubs--to/test2.liquid","content":"hello"}`, ] ); }); + +test("Eleventy to ndjson (no cmd line output when using programmatic API)", async (t) => { + let elev = new Eleventy("./test/stubs--to/"); + + elev.setIsVerbose(false); + elev.setViaCommandLine(false); + + let output = []; + let fn = function (str) { + output.push(str); + }; + elev.logger = { + log: fn, + warn: fn, + error: fn, + message: fn, + stdout: fn, + }; + + await elev.init(); + await elev.toNDJSON(); + + t.deepEqual(output, []); +}); + +test.cb("Eleventy to ndjson (returns stream)", (t) => { + let elev = new Eleventy("./test/stubs--to/"); + + elev.setIsVerbose(false); + elev.setViaCommandLine(false); + + elev.init().then(() => { + elev.toNDJSON().then((stream) => { + let results = []; + stream.on("data", function (jsonObj) { + if (jsonObj.url === "/test/") { + t.deepEqual(jsonObj, { + url: "/test/", + inputPath: "./test/stubs--to/test.md", + content: "

hi

\n", + }); + } + if (jsonObj.url === "/test2/") { + t.deepEqual(jsonObj, { + url: "/test2/", + inputPath: "./test/stubs--to/test2.liquid", + content: "hello", + }); + } + + results.push(jsonObj); + + if (results.length >= 2) { + t.end(); + } + }); + }); + }); +}); From c2e89a0da369da29bdbfa5cf6dac34012e316ba0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 9 Feb 2021 23:41:42 -0600 Subject: [PATCH 315/746] Use EleventyErrorHandler instance, code cleanup to use streams in both CLI and programmatic API --- cmd.js | 32 +++++++++++++++++++++----------- src/Eleventy.js | 11 ----------- src/Util/ConsoleLogger.js | 11 +++-------- test/EleventyTest.js | 3 --- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/cmd.js b/cmd.js index 2dab3a76c..c64b8eaf0 100755 --- a/cmd.js +++ b/cmd.js @@ -50,17 +50,16 @@ try { debug("command: eleventy ", argv.toString()); const Eleventy = require("./src/Eleventy"); + let errorHandler = new EleventyErrorHandler(); + process.on("unhandledRejection", (error, promise) => { - EleventyErrorHandler.error( - error, - `Unhandled rejection in promise (${promise})` - ); + errorHandler.error(error, `Unhandled rejection in promise (${promise})`); }); process.on("uncaughtException", (error) => { - EleventyErrorHandler.fatal(error, "Uncaught exception"); + errorHandler.fatal(error, "Uncaught exception"); }); process.on("rejectionHandled", (promise) => { - EleventyErrorHandler.warn( + errorHandler.warn( promise, "A promise rejection was handled asynchronously" ); @@ -71,12 +70,14 @@ try { quietMode: argv.quiet, }); + // reuse ErrorHandler instance in Eleventy + errorHandler = elev.errorHandler; + if (argv.to === "json" || argv.to === "ndjson") { // override logging output elev.setIsVerbose(false); } - elev.setViaCommandLine(true); elev.setConfigPathOverride(argv.config); elev.setPathPrefix(argv.pathprefix); elev.setDryRun(argv.dryrun); @@ -101,11 +102,20 @@ try { elev.watch(); } else { if (argv.to === "json") { - elev.toJSON().then((result) => { + elev.toJSON().then(function (result) { console.log(JSON.stringify(result, null, 2)); }); } else if (argv.to === "ndjson") { - elev.toNDJSON(); + elev + .toNDJSON() + .then(function (stream) { + stream + .on("data", function (jsonString) { + console.log(jsonString); + }) + .on("error", errorHandler.fatal.bind(errorHandler)); + }) + .catch(errorHandler.fatal.bind(errorHandler)); } else if (!argv.to || argv.to === "fs") { elev.write(); } else { @@ -115,7 +125,7 @@ try { } } }) - .catch(EleventyErrorHandler.fatal); + .catch(errorHandler.fatal.bind(errorHandler)); } catch (e) { - EleventyErrorHandler.fatal(e, "Eleventy fatal error"); + errorHandler.fatal(e, "Eleventy fatal error"); } diff --git a/src/Eleventy.js b/src/Eleventy.js index 4b95fde4b..ea3b2dfbb 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -105,16 +105,6 @@ class Eleventy { return new Date().getTime(); } - /** - * Sets the whether or not this instance was created from the command line (via cmd.js) - * - * @method - * @param {Boolean} isViaCommandLine - */ - setViaCommandLine(isViaCommandLine) { - this.isViaCommandLine = isViaCommandLine; - } - /** @type {String} */ get input() { return this.rawInput || this.config.dir.input; @@ -365,7 +355,6 @@ Verbose Output: ${this.verboseMode}`); if (!this._logger) { this._logger = new ConsoleLogger(); this._logger.isVerbose = this.verboseMode; - this._logger.isViaCommandLine = this.isViaCommandLine; } return this._logger; diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index cac66aba3..ab3283b06 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -6,7 +6,6 @@ const split = require("split"); class ConsoleLogger { constructor() { this._isVerbose = true; - this.isViaCommandLine = false; this.outputStream = Readable(); } @@ -46,12 +45,7 @@ class ConsoleLogger { } toStream(msg, suffix = "") { - // only output to stdout/console if we’re running in command line - if (this.isViaCommandLine) { - console.log(msg); - } else { - this.outputStream.push(msg + suffix); - } + this.outputStream.push(msg + suffix); } closeStream(to = "") { @@ -59,7 +53,8 @@ class ConsoleLogger { if (to === "ndjson") { return this.outputStream.pipe( - split(JSON.parse, null, { trailing: false }) + // split(JSON.parse, null, { trailing: false }) + split(null, null, { trailing: false }) ); } return this.outputStream; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index f3d9fc511..c20972c5f 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -171,7 +171,6 @@ test("Eleventy to ndjson (via command line-ish, to stdout)", async (t) => { let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); - elev.setViaCommandLine(true); let output = []; let fn = function (str) { @@ -206,7 +205,6 @@ test("Eleventy to ndjson (no cmd line output when using programmatic API)", asyn let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); - elev.setViaCommandLine(false); let output = []; let fn = function (str) { @@ -230,7 +228,6 @@ test.cb("Eleventy to ndjson (returns stream)", (t) => { let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); - elev.setViaCommandLine(false); elev.init().then(() => { elev.toNDJSON().then((stream) => { From cc5bf0c7cedc0a059fade92a474029f340f7e972 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 9 Feb 2021 23:51:29 -0600 Subject: [PATCH 316/746] No more raw stdout in the Eleventy object (irrelevant tests) --- test/EleventyTest.js | 59 +------------------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/test/EleventyTest.js b/test/EleventyTest.js index c20972c5f..41ef484a6 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -167,64 +167,7 @@ test("Eleventy to json", async (t) => { ); }); -test("Eleventy to ndjson (via command line-ish, to stdout)", async (t) => { - let elev = new Eleventy("./test/stubs--to/"); - - elev.setIsVerbose(false); - - let output = []; - let fn = function (str) { - output.push(str); - }; - elev.logger = { - log: fn, - warn: fn, - error: fn, - message: fn, - toStream: fn, - }; - - await elev.init(); - await elev.toNDJSON(); - - t.deepEqual( - output.filter((entry) => entry.startsWith(`{"url":"/test/"`)), - [ - `{"url":"/test/","inputPath":"./test/stubs--to/test.md","content":"

hi

\\n"}`, - ] - ); - t.deepEqual( - output.filter((entry) => entry.startsWith(`{"url":"/test2/"`)), - [ - `{"url":"/test2/","inputPath":"./test/stubs--to/test2.liquid","content":"hello"}`, - ] - ); -}); - -test("Eleventy to ndjson (no cmd line output when using programmatic API)", async (t) => { - let elev = new Eleventy("./test/stubs--to/"); - - elev.setIsVerbose(false); - - let output = []; - let fn = function (str) { - output.push(str); - }; - elev.logger = { - log: fn, - warn: fn, - error: fn, - message: fn, - stdout: fn, - }; - - await elev.init(); - await elev.toNDJSON(); - - t.deepEqual(output, []); -}); - -test.cb("Eleventy to ndjson (returns stream)", (t) => { +test.cb("Eleventy to ndjson (returns a stream)", (t) => { let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); From 8f5f9fa93632418dcf3378036457406163aaf5b2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 10 Feb 2021 12:20:37 -0600 Subject: [PATCH 317/746] .on("data") with node streams uses some kind of compatibility mode per https://github.com/substack/stream-handbook#classic-readable-streams Recommend to use pipe --- src/Eleventy.js | 1 + src/Template.js | 2 +- src/Util/ConsoleLogger.js | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index ea3b2dfbb..c5835d348 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -819,6 +819,7 @@ Arguments: if (to === "ndjson") { // return a stream + // TODO this might return only after all the templates have been added to the stream ret = this.logger.closeStream(to); } await this.config.events.emit("afterBuild"); diff --git a/src/Template.js b/src/Template.js index a6a579db9..f6056f80e 100755 --- a/src/Template.js +++ b/src/Template.js @@ -674,7 +674,7 @@ class Template extends TemplateContent { if (to === "ndjson") { let jsonString = JSON.stringify(obj); - this.logger.toStream(jsonString, "\n"); + this.logger.toStream(jsonString + "\n"); return; } diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index ab3283b06..5c9c11742 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -44,8 +44,8 @@ class ConsoleLogger { this.message(msg); } - toStream(msg, suffix = "") { - this.outputStream.push(msg + suffix); + toStream(msg) { + this.outputStream.push(msg); } closeStream(to = "") { From 1894b390d64101a209b5c576de6a095fca04e65e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 10 Feb 2021 12:20:59 -0600 Subject: [PATCH 318/746] Fix error with missing error handler on fatal errors --- cmd.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cmd.js b/cmd.js index c64b8eaf0..9bfc96e00 100755 --- a/cmd.js +++ b/cmd.js @@ -17,6 +17,7 @@ if (process.env.DEBUG) { const EleventyErrorHandler = require("./src/EleventyErrorHandler"); try { + let errorHandler = new EleventyErrorHandler(); const EleventyCommandCheckError = require("./src/EleventyCommandCheckError"); const argv = require("minimist")(process.argv.slice(2), { string: [ @@ -50,8 +51,6 @@ try { debug("command: eleventy ", argv.toString()); const Eleventy = require("./src/Eleventy"); - let errorHandler = new EleventyErrorHandler(); - process.on("unhandledRejection", (error, promise) => { errorHandler.error(error, `Unhandled rejection in promise (${promise})`); }); @@ -109,11 +108,7 @@ try { elev .toNDJSON() .then(function (stream) { - stream - .on("data", function (jsonString) { - console.log(jsonString); - }) - .on("error", errorHandler.fatal.bind(errorHandler)); + stream.pipe(process.stdout); }) .catch(errorHandler.fatal.bind(errorHandler)); } else if (!argv.to || argv.to === "fs") { @@ -127,5 +122,6 @@ try { }) .catch(errorHandler.fatal.bind(errorHandler)); } catch (e) { + let errorHandler = new EleventyErrorHandler(); errorHandler.fatal(e, "Eleventy fatal error"); } From cc9cd890d0705dc2f62c7b77da0a8cd394e50c39 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 10 Feb 2021 12:21:11 -0600 Subject: [PATCH 319/746] Canary release docs --- docs/meta-release.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/meta-release.md b/docs/meta-release.md index d60f23d9c..05b5baba6 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -1,3 +1,11 @@ +# Canary Release Procedure + +1. npmclean aka `rm -rf node_modules && rm -f package-lock.json && npm install` +1. Make sure `npx ava` runs okay +1. Update version in `package.json`, include `-canary.1` suffix +1. Tag new version +1. `npm publish --access=public --tag=canary` + # Beta Release Procedure 1. update minor dependencies in package.json? From 33c623dfbc636cc118670eb7916b21771480ab50 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 10 Feb 2021 12:22:37 -0600 Subject: [PATCH 320/746] v1.0.0-canary.0 --- docs/meta-release.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/meta-release.md b/docs/meta-release.md index 05b5baba6..7988acc69 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -3,6 +3,7 @@ 1. npmclean aka `rm -rf node_modules && rm -f package-lock.json && npm install` 1. Make sure `npx ava` runs okay 1. Update version in `package.json`, include `-canary.1` suffix +1. Check it all in and commit 1. Tag new version 1. `npm publish --access=public --tag=canary` diff --git a/package.json b/package.json index 6b773b3ce..dc84fca48 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.0", + "version": "1.0.0-canary.0", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 95ab1e47e20fa8c4d0a14d337f9eacde3fac0ad6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 10 Feb 2021 12:23:32 -0600 Subject: [PATCH 321/746] Ah, prior art was to use .1 for first off-channel release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc84fca48..01bf549af 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.0", + "version": "1.0.0-canary.1", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 48138fc27a77502cd51e41a8ffb6f9edc177e7ad Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 10 Feb 2021 12:38:32 -0600 Subject: [PATCH 322/746] Oops. --- src/EleventyErrorHandler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EleventyErrorHandler.js b/src/EleventyErrorHandler.js index 0f5b13728..8b613a35b 100644 --- a/src/EleventyErrorHandler.js +++ b/src/EleventyErrorHandler.js @@ -14,7 +14,7 @@ class EleventyErrorHandler { set isVerbose(verbose) { this._isVerbose = !!verbose; - this.logger = !!verbose; + this.logger.isVerbose = !!verbose; } get logger() { From a741537f695ebaa112d61780aee134b714439829 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 10 Feb 2021 12:38:59 -0600 Subject: [PATCH 323/746] v1.0.0-canary.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01bf549af..739da8906 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.1", + "version": "1.0.0-canary.2", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 3dbaab0a3e09988210c03607d9bf46e5748d8f89 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 10:58:29 -0600 Subject: [PATCH 324/746] Adds setter for inputDir when you use a file input and want a different input directory root. Think --input=./src/subdir/index.njk but you want the input directory to be ./src/ --- src/Eleventy.js | 12 ++++++++++++ test/EleventyTest.js | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Eleventy.js b/src/Eleventy.js index 85b2dd21f..89a5777a5 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -113,9 +113,21 @@ class Eleventy { /** @type {String} */ get inputDir() { + if (this._inputDir) { + // set manually via setter + return this._inputDir; + } + return TemplatePath.getDir(this.input); } + /** @type {String} */ + set inputDir(dir) { + if (TemplatePath.isDirectorySync(dir)) { + this._inputDir = dir; + } + } + /** @type {String} */ get outputDir() { let dir = this.rawOutput || this.config.dir.output; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 41ef484a6..3c011f70e 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -106,6 +106,18 @@ test("Eleventy set input/output, one file input", async (t) => { t.is(elev.outputDir, "./test/stubs/_site"); }); +test("Eleventy set input/output, one file input, deeper subdirectory", async (t) => { + let elev = new Eleventy( + "./test/stubs/subdir/index.html", + "./test/stubs/_site" + ); + elev.inputDir = "./test/stubs"; + + t.is(elev.input, "./test/stubs/subdir/index.html"); + t.is(elev.inputDir, "./test/stubs"); + t.is(elev.outputDir, "./test/stubs/_site"); +}); + test("Eleventy set input/output, one file input root dir", async (t) => { let elev = new Eleventy("./README.md", "./test/stubs/_site"); From e2fc0b955eed3e5961c8b485c56f0998ebde429a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 10:59:38 -0600 Subject: [PATCH 325/746] v1.0.0-canary.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c56dccfe..78f029be0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.2", + "version": "1.0.0-canary.3", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 39afa802ac7495102be038e84cb648cc1aa4a22e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 12:19:42 -0600 Subject: [PATCH 326/746] =?UTF-8?q?That=20build=20definitely=20broke=20som?= =?UTF-8?q?ething=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/Eleventy.js | 7 ++----- test/EleventyTest.js | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 78f029be0..7e4a91820 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.3", + "version": "1.0.0-canary.4", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" diff --git a/src/Eleventy.js b/src/Eleventy.js index 89a5777a5..29f71911b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -121,11 +121,8 @@ class Eleventy { return TemplatePath.getDir(this.input); } - /** @type {String} */ - set inputDir(dir) { - if (TemplatePath.isDirectorySync(dir)) { - this._inputDir = dir; - } + setInputDir(dir) { + this._inputDir = dir; } /** @type {String} */ diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 3c011f70e..ce61f4929 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -111,7 +111,7 @@ test("Eleventy set input/output, one file input, deeper subdirectory", async (t) "./test/stubs/subdir/index.html", "./test/stubs/_site" ); - elev.inputDir = "./test/stubs"; + elev.setInputDir("./test/stubs"); t.is(elev.input, "./test/stubs/subdir/index.html"); t.is(elev.inputDir, "./test/stubs"); From 2dee4ed120cb56a66708bef0109977d6ce31a1e2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 14:46:50 -0600 Subject: [PATCH 327/746] Cherry pick from master --- package.json | 2 +- src/Eleventy.js | 9 +++++++++ test/EleventyTest.js | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 739da8906..fca65b5dd 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.2", + "version": "1.0.0-canary.4", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" diff --git a/src/Eleventy.js b/src/Eleventy.js index c5835d348..bedb10780 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -112,9 +112,18 @@ class Eleventy { /** @type {String} */ get inputDir() { + if (this._inputDir) { + // set manually via setter + return this._inputDir; + } + return TemplatePath.getDir(this.input); } + setInputDir(dir) { + this._inputDir = dir; + } + /** @type {String} */ get outputDir() { let dir = this.rawOutput || this.config.dir.output; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 41ef484a6..ce61f4929 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -106,6 +106,18 @@ test("Eleventy set input/output, one file input", async (t) => { t.is(elev.outputDir, "./test/stubs/_site"); }); +test("Eleventy set input/output, one file input, deeper subdirectory", async (t) => { + let elev = new Eleventy( + "./test/stubs/subdir/index.html", + "./test/stubs/_site" + ); + elev.setInputDir("./test/stubs"); + + t.is(elev.input, "./test/stubs/subdir/index.html"); + t.is(elev.inputDir, "./test/stubs"); + t.is(elev.outputDir, "./test/stubs/_site"); +}); + test("Eleventy set input/output, one file input root dir", async (t) => { let elev = new Eleventy("./README.md", "./test/stubs/_site"); From 359a6ae601e491e44958c5b13caf830426d2043e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 14:47:38 -0600 Subject: [PATCH 328/746] v1.0.0-canary.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fca65b5dd..dc740b8c1 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.4", + "version": "1.0.0-canary.5", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From a0ed8a6b517fac190b6ab7f83feb0ea66bb8d323 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 17:51:37 -0600 Subject: [PATCH 329/746] Steps to separate input from input dir. --- src/Eleventy.js | 7 +++++-- src/EleventyFiles.js | 17 +++++++++++++++++ src/TemplateWriter.js | 9 ++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index bedb10780..9e2a40859 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -295,11 +295,13 @@ class Eleventy { this.extensionMap = new EleventyExtensionMap(formats); this.eleventyFiles = new EleventyFiles( - this.input, + this.inputDir, this.outputDir, formats, this.isPassthroughAll ); + + this.eleventyFiles.setInput(this.inputDir, this.input); this.eleventyFiles.extensionMap = this.extensionMap; this.eleventyFiles.init(); @@ -308,12 +310,13 @@ class Eleventy { this.eleventyFiles.templateData = this.templateData; this.writer = new TemplateWriter( - this.input, + this.inputDir, this.outputDir, formats, this.templateData, this.isPassthroughAll ); + this.writer.setInput(this.inputDir, this.input); this.writer.logger = this.logger; this.writer.extensionMap = this.extensionMap; this.writer.setEleventyFiles(this.eleventyFiles); diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 5f2326bdd..3b493a5ea 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -24,6 +24,21 @@ class EleventyFiles { this.passthroughAll = !!passthroughAll; this.formats = formats; + + // init has not yet been called() + this.alreadyInit = false; + } + + /* Overrides this.input and this.inputDir */ + setInput(inputDir, input) { + this.inputDir = inputDir; + this.input = input; + + this.initConfig(); + + if (this.alreadyInit) { + this.init(); + } } initConfig() { @@ -41,6 +56,8 @@ class EleventyFiles { } init() { + this.alreadyInit = true; + // Input was a directory if (this.input === this.inputDir) { this.templateGlobs = this.extensionMap.getGlobs(this.inputDir); diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index ea83d084b..6d31206da 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -43,6 +43,12 @@ class TemplateWriter { this._templatePathCache = new Map(); } + /* Overrides this.input and this.inputDir */ + setInput(inputDir, input) { + this.inputDir = inputDir; + this.input = input; + } + get templateFormats() { return this._templateFormats; } @@ -117,12 +123,13 @@ class TemplateWriter { if (!this._eleventyFiles) { // if not, we can create one (used only by tests) this._eleventyFiles = new EleventyFiles( - this.input, + this.inputDir, this.outputDir, this.templateFormats, this.passthroughAll ); + this._eleventyFiles.setInput(this.inputDir, this.input); this._eleventyFiles.init(); } From ad37becbd26e7507f4f3283abc8c20501c81e928 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 17:52:03 -0600 Subject: [PATCH 330/746] v1.0.0-canary.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc740b8c1..a18226021 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.5", + "version": "1.0.0-canary.6", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 4bddb147217b1f3cb66f7b1744bb2bc634ae779c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Feb 2021 23:32:32 -0600 Subject: [PATCH 331/746] Simplifes the config setup a little bit as a step toward decentralized config object cleanup. Removes EleventyConfig, moves UserConfig into TemplateConfig. Next step is to move another up the chain to Config.js --- src/EleventyConfig.js | 3 - src/TemplateConfig.js | 31 ++++--- src/TemplateMap.js | 24 +++-- src/TemplateWriter.js | 3 + src/UserConfig.js | 2 +- test/EleventyConfigTest.js | 111 ---------------------- test/TemplateConfigTest.js | 185 +++++++++++++++++-------------------- test/TemplateWriterTest.js | 19 ++-- test/UserConfigTest.js | 151 +++++++++++++++++++++++++++--- 9 files changed, 267 insertions(+), 262 deletions(-) delete mode 100644 src/EleventyConfig.js delete mode 100644 test/EleventyConfigTest.js diff --git a/src/EleventyConfig.js b/src/EleventyConfig.js deleted file mode 100644 index ef2e65f8a..000000000 --- a/src/EleventyConfig.js +++ /dev/null @@ -1,3 +0,0 @@ -const UserConfig = require("./UserConfig"); - -module.exports = new UserConfig(); diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index a044628c7..58c79b7af 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -4,7 +4,7 @@ const lodashUniq = require("lodash/uniq"); const lodashMerge = require("lodash/merge"); const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); -const eleventyConfig = require("./EleventyConfig"); +const UserConfig = require("./UserConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); const deleteRequireCache = require("./Util/DeleteRequireCache"); @@ -37,6 +37,8 @@ class EleventyConfigError extends EleventyBaseError {} */ class TemplateConfig { constructor(customRootConfig, localProjectConfigPath) { + this.userConfig = new UserConfig(); + /** @member {module:11ty/eleventy/TemplateConfig~TemplateConfig~override} - tbd. */ this.overrides = {}; @@ -58,10 +60,7 @@ class TemplateConfig { this.initializeRootConfig(); - /** - * @member {module:11ty/eleventy/TemplateConfig~TemplateConfig~config} - tbd. - */ - this.config = this.mergeConfig(this.localProjectConfigPath); + this.hasConfigMerged = false; } /** @@ -86,7 +85,7 @@ class TemplateConfig { * Resets the configuration. */ reset() { - eleventyConfig.reset(); + this.userConfig.reset(); this.initializeRootConfig(); this.config = this.mergeConfig(this.localProjectConfigPath); } @@ -106,6 +105,10 @@ class TemplateConfig { * @returns {{}} - The config object. */ getConfig() { + if (!this.hasConfigMerged) { + this.config = this.mergeConfig(this.localProjectConfigPath); + this.hasConfigMerged = true; + } return this.config; } @@ -128,6 +131,10 @@ class TemplateConfig { setPathPrefix(pathPrefix) { debug("Setting pathPrefix to %o", pathPrefix); this.overrides.pathPrefix = pathPrefix; + + if (!this.hasConfigMerged) { + this.getConfig(); + } this.config.pathPrefix = pathPrefix; } @@ -138,8 +145,8 @@ class TemplateConfig { this.rootConfig = this.customRootConfig || require("./defaultConfig.js"); if (typeof this.rootConfig === "function") { - this.rootConfig = this.rootConfig(eleventyConfig); - // debug( "rootConfig is a function, after calling, eleventyConfig is %o", eleventyConfig ); + this.rootConfig = this.rootConfig(this.userConfig); + // debug( "rootConfig is a function, after calling, this.userConfig is %o", this.userConfig ); } debug("rootConfig %o", this.rootConfig); } @@ -169,8 +176,8 @@ class TemplateConfig { // debug( "localConfig require return value: %o", localConfig ); if (typeof localConfig === "function") { - localConfig = localConfig(eleventyConfig); - // debug( "localConfig is a function, after calling, eleventyConfig is %o", eleventyConfig ); + localConfig = localConfig(this.userConfig); + // debug( "localConfig is a function, after calling, this.userConfig is %o", this.userConfig ); if ( typeof localConfig === "object" && @@ -204,7 +211,7 @@ class TemplateConfig { debug("Eleventy local project config file not found, skipping."); } - let eleventyConfigApiMergingObject = eleventyConfig.getMergingConfigObject(); + let eleventyConfigApiMergingObject = this.userConfig.getMergingConfigObject(); // remove special merge keys from object let savedForSpecialMerge = { @@ -219,7 +226,7 @@ class TemplateConfig { eleventyConfigApiMergingObject.templateFormats || localConfig.templateFormats; - // debug("eleventyConfig.getMergingConfigObject: %o", eleventyConfig.getMergingConfigObject()); + // debug("this.userConfig.getMergingConfigObject: %o", this.userConfig.getMergingConfigObject()); debug("localConfig: %o", localConfig); debug("overrides: %o", this.overrides); diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 6d1b81807..78ef10582 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -3,10 +3,9 @@ const DependencyGraph = require("dependency-graph").DepGraph; const TemplateCollection = require("./TemplateCollection"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const UsingCircularTemplateContentReferenceError = require("./Errors/UsingCircularTemplateContentReferenceError"); -// TODO the config setup here is overly complex. Why aren’t we injecting config instance like everywhere else? -const eleventyConfig = require("./EleventyConfig"); const debug = require("debug")("Eleventy:TemplateMap"); const debugDev = require("debug")("Dev:Eleventy:TemplateMap"); +const config = require("./Config"); const EleventyBaseError = require("./EleventyBaseError"); class DuplicatePermalinkOutputError extends EleventyBaseError { @@ -25,6 +24,18 @@ class TemplateMap { this.collection = new TemplateCollection(); } + set userConfig(config) { + this._userConfig = config; + } + + get userConfig() { + if (!this._userConfig) { + this._userConfig = config.userConfig; + } + + return this._userConfig; + } + get tagPrefix() { return "___TAG___"; } @@ -435,19 +446,20 @@ class TemplateMap { } isUserConfigCollectionName(name) { - let collections = this.configCollections || eleventyConfig.getCollections(); + let collections = + this.configCollections || this.userConfig.getCollections(); return name && !!collections[name]; } getUserConfigCollectionNames() { return Object.keys( - this.configCollections || eleventyConfig.getCollections() + this.configCollections || this.userConfig.getCollections() ); } async getUserConfigCollection(name) { let configCollections = - this.configCollections || eleventyConfig.getCollections(); + this.configCollections || this.userConfig.getCollections(); // This works with async now let result = await configCollections[name](this.collection); @@ -459,7 +471,7 @@ class TemplateMap { async _testGetUserConfigCollectionsData() { let collections = {}; let configCollections = - this.configCollections || eleventyConfig.getCollections(); + this.configCollections || this.userConfig.getCollections(); for (let name in configCollections) { collections[name] = configCollections[name](this.collection); diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 6d31206da..8a9718777 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -24,6 +24,8 @@ class TemplateWriter { isPassthroughAll ) { this.config = config.getConfig(); + this.userConfig = config.userConfig; + this.input = inputPath; this.inputDir = TemplatePath.getDir(inputPath); this.outputDir = outputDir; @@ -209,6 +211,7 @@ class TemplateWriter { async _createTemplateMap(paths) { this.templateMap = new TemplateMap(); + this.templateMap.userConfig = this.userConfig; await this._addToTemplateMap(paths); await this.templateMap.cache(); diff --git a/src/UserConfig.js b/src/UserConfig.js index 45fec0aa5..61ef0c865 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -70,7 +70,7 @@ class UserConfig { versionCheck(expected) { if (!semver.satisfies(pkg.version, expected)) { throw new UserConfigError( - `This project requires the eleventy version to match '${expected}' but found ${pkg.version}. Use \`npm update @11ty/eleventy -g\` to upgrade the eleventy global or \`npm update @11ty/eleventy --save\` to upgrade your local project version.` + `This project requires the Eleventy version to match '${expected}' but found ${pkg.version}. Use \`npm update @11ty/eleventy -g\` to upgrade the eleventy global or \`npm update @11ty/eleventy --save\` to upgrade your local project version.` ); } } diff --git a/test/EleventyConfigTest.js b/test/EleventyConfigTest.js deleted file mode 100644 index 87e5b6781..000000000 --- a/test/EleventyConfigTest.js +++ /dev/null @@ -1,111 +0,0 @@ -const test = require("ava"); -const eleventyConfig = require("../src/EleventyConfig"); - -// more in TemplateConfigTest.js - -test.cb("Events", (t) => { - eleventyConfig.on("testEvent", function (arg1, arg2, arg3) { - t.is(arg1, "arg1"); - t.is(arg2, "arg2"); - t.is(arg3, "arg3"); - t.end(); - }); - - eleventyConfig.emit("testEvent", "arg1", "arg2", "arg3"); -}); - -test.cb("Async Events", (t) => { - let arg1; - - eleventyConfig.on( - "asyncTestEvent", - (_arg1) => - new Promise((resolve) => { - setTimeout(() => { - arg1 = _arg1; - resolve(); - }, 10); - }) - ); - - eleventyConfig.emit("asyncTestEvent", "arg1").then(() => { - t.is(arg1, "arg1"); - t.end(); - }); -}); - -test("Add Collections", (t) => { - eleventyConfig.addCollection("myCollection", function (collection) {}); - t.deepEqual(Object.keys(eleventyConfig.getCollections()), ["myCollection"]); -}); - -test("Add Collections throws error on key collision", (t) => { - eleventyConfig.addCollection("myCollectionCollision", function ( - collection - ) {}); - - t.throws(() => { - eleventyConfig.addCollection("myCollectionCollision", function ( - collection - ) {}); - }); -}); - -test("Set manual Pass-through File Copy (single call)", (t) => { - eleventyConfig.addPassthroughCopy("img"); - - t.is(eleventyConfig.passthroughCopies["img"], true); -}); - -test("Set manual Pass-through File Copy (chained calls)", (t) => { - eleventyConfig - .addPassthroughCopy("css") - .addPassthroughCopy("js") - .addPassthroughCopy({ "./src/static": "static" }) - .addPassthroughCopy({ "./src/empty": "./" }); - - t.is(eleventyConfig.passthroughCopies["css"], true); - t.is(eleventyConfig.passthroughCopies["js"], true); - t.is(eleventyConfig.passthroughCopies["./src/static"], "static"); - t.is(eleventyConfig.passthroughCopies["./src/empty"], "./"); -}); - -test("Set manual Pass-through File Copy (glob patterns)", (t) => { - eleventyConfig.addPassthroughCopy({ - "./src/static/**/*": "renamed", - "./src/markdown/*.md": "", - }); - - // does not exist - t.is(eleventyConfig.passthroughCopies["css/**"], undefined); - t.is(eleventyConfig.passthroughCopies["js/**"], undefined); - - // exists - t.is(eleventyConfig.passthroughCopies["./src/static/**/*"], "renamed"); - t.is(eleventyConfig.passthroughCopies["./src/markdown/*.md"], ""); -}); - -test("Set Template Formats (string)", (t) => { - eleventyConfig.setTemplateFormats("ejs, njk, liquid"); - t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid"]); -}); - -test("Set Template Formats (array)", (t) => { - eleventyConfig.setTemplateFormats(["ejs", "njk", "liquid"]); - t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid"]); -}); - -test("Set Template Formats (js passthrough copy)", (t) => { - eleventyConfig.setTemplateFormats("ejs, njk, liquid, js"); - t.deepEqual(eleventyConfig.templateFormats, ["ejs", "njk", "liquid", "js"]); -}); - -test("Set Template Formats (11ty.js)", (t) => { - eleventyConfig.setTemplateFormats("ejs, njk, liquid, 11ty.js"); - t.deepEqual(eleventyConfig.templateFormats, [ - "ejs", - "njk", - "liquid", - "11ty.js", - ]); -}); diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index fc859108b..0429cc027 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -1,7 +1,6 @@ const test = require("ava"); const md = require("markdown-it"); const TemplateConfig = require("../src/TemplateConfig"); -const eleventyConfig = require("../src/EleventyConfig"); test("Template Config local config overrides base config", async (t) => { let templateCfg = new TemplateConfig( @@ -34,104 +33,97 @@ test("Template Config local config overrides base config", async (t) => { }); test("Add liquid tag", (t) => { - eleventyConfig.reset(); - eleventyConfig.addLiquidTag("myTagName", function () {}); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addLiquidTag("myTagName", function () {}); let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.liquidTags).indexOf("myTagName"), -1); }); test("Add nunjucks tag", (t) => { - eleventyConfig.reset(); - eleventyConfig.addNunjucksTag("myNunjucksTag", function () {}); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addNunjucksTag("myNunjucksTag", function () {}); let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksTags).indexOf("myNunjucksTag"), -1); }); test("Add nunjucks global", (t) => { - eleventyConfig.reset(); - eleventyConfig.addNunjucksGlobal("myNunjucksGlobal1", function () {}); - eleventyConfig.addNunjucksGlobal("myNunjucksGlobal2", 42); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addNunjucksGlobal("myNunjucksGlobal1", function () {}); + templateCfg.userConfig.addNunjucksGlobal("myNunjucksGlobal2", 42); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksGlobals).indexOf("myNunjucksGlobal1"), -1); t.not(Object.keys(cfg.nunjucksGlobals).indexOf("myNunjucksGlobal2"), -1); }); test("Add liquid filter", (t) => { - eleventyConfig.reset(); - eleventyConfig.addLiquidFilter("myFilterName", function (liquidEngine) { - return {}; - }); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addLiquidFilter( + "myFilterName", + function (liquidEngine) { + return {}; + } + ); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.liquidFilters).indexOf("myFilterName"), -1); }); test("Add handlebars helper", (t) => { - eleventyConfig.reset(); - eleventyConfig.addHandlebarsHelper("myHelperName", function () {}); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addHandlebarsHelper("myHelperName", function () {}); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.handlebarsHelpers).indexOf("myHelperName"), -1); }); test("Add nunjucks filter", (t) => { - eleventyConfig.reset(); - eleventyConfig.addNunjucksFilter("myFilterName", function () {}); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addNunjucksFilter("myFilterName", function () {}); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); test("Add universal filter", (t) => { - eleventyConfig.reset(); - eleventyConfig.addFilter("myFilterName", function () {}); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addFilter("myFilterName", function () {}); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.liquidFilters).indexOf("myFilterName"), -1); t.not(Object.keys(cfg.handlebarsHelpers).indexOf("myFilterName"), -1); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); test("Add namespaced universal filter", (t) => { - eleventyConfig.reset(); - eleventyConfig.namespace("testNamespace", function () { - eleventyConfig.addFilter("MyFilterName", function () {}); - }); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.namespace("testNamespace", function () { + templateCfg.userConfig.addFilter("MyFilterName", function () {}); + }); + let cfg = templateCfg.getConfig(); t.not( Object.keys(cfg.liquidFilters).indexOf("testNamespaceMyFilterName"), @@ -148,15 +140,14 @@ test("Add namespaced universal filter", (t) => { }); test("Add namespaced universal filter using underscore", (t) => { - eleventyConfig.reset(); - eleventyConfig.namespace("testNamespace_", function () { - eleventyConfig.addFilter("myFilterName", function () {}); - }); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.namespace("testNamespace_", function () { + templateCfg.userConfig.addFilter("myFilterName", function () {}); + }); + let cfg = templateCfg.getConfig(); t.not( Object.keys(cfg.liquidFilters).indexOf("testNamespace_myFilterName"), @@ -173,47 +164,45 @@ test("Add namespaced universal filter using underscore", (t) => { }); test("Empty namespace", (t) => { - eleventyConfig.reset(); - eleventyConfig.namespace("", function () { - eleventyConfig.addNunjucksFilter("myFilterName", function () {}); - }); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.namespace("", function () { + templateCfg.userConfig.addNunjucksFilter("myFilterName", function () {}); + }); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); test("Nested Empty Inner namespace", (t) => { - eleventyConfig.reset(); - eleventyConfig.namespace("testNs", function () { - eleventyConfig.namespace("", function () { - eleventyConfig.addNunjucksFilter("myFilterName", function () {}); - }); - }); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + + templateCfg.userConfig.namespace("testNs", function () { + templateCfg.userConfig.namespace("", function () { + templateCfg.userConfig.addNunjucksFilter("myFilterName", function () {}); + }); + }); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksFilters).indexOf("testNsmyFilterName"), -1); }); test("Nested Empty Outer namespace", (t) => { - eleventyConfig.reset(); - eleventyConfig.namespace("", function () { - eleventyConfig.namespace("testNs", function () { - eleventyConfig.addNunjucksFilter("myFilterName", function () {}); - }); - }); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.namespace("", function () { + templateCfg.userConfig.namespace("testNs", function () { + templateCfg.userConfig.addNunjucksFilter("myFilterName", function () {}); + }); + }); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksFilters).indexOf("testNsmyFilterName"), -1); }); @@ -222,31 +211,30 @@ test("Nested Empty Outer namespace", (t) => { // `module.exports = function (eleventyConfig, pluginNamespace) {` // plugin code test("Non-string namespaces are ignored", (t) => { - eleventyConfig.reset(); - eleventyConfig.namespace(["lkdsjflksd"], function () { - eleventyConfig.addNunjucksFilter("myFilterName", function () {}); - }); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.namespace(["lkdsjflksd"], function () { + templateCfg.userConfig.addNunjucksFilter("myFilterName", function () {}); + }); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); test(".addPlugin oddity: I don’t think pluginNamespace was ever passed in here, but we don’t want this to break", (t) => { - eleventyConfig.reset(); - eleventyConfig.addPlugin(function (eleventyConfig, pluginNamespace) { + let templateCfg = new TemplateConfig( + require("../src/defaultConfig.js"), + "./test/stubs/config.js" + ); + + templateCfg.userConfig.addPlugin(function (eleventyConfig, pluginNamespace) { eleventyConfig.namespace(pluginNamespace, () => { eleventyConfig.addNunjucksFilter("myFilterName", function () {}); }); }); - let templateCfg = new TemplateConfig( - require("../src/defaultConfig.js"), - "./test/stubs/config.js" - ); let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); @@ -262,87 +250,80 @@ test("Test url universal filter with custom pathPrefix (no slash)", (t) => { }); test("setTemplateFormats(string)", (t) => { - eleventyConfig.reset(); - // 0.11.0 removes dupes - eleventyConfig.setTemplateFormats("ejs,njk, liquid, njk"); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + // 0.11.0 removes dupes + templateCfg.userConfig.setTemplateFormats("ejs,njk, liquid, njk"); + let cfg = templateCfg.getConfig(); t.deepEqual(cfg.templateFormats, ["ejs", "njk", "liquid"]); }); test("setTemplateFormats(array)", (t) => { - eleventyConfig.reset(); - eleventyConfig.setTemplateFormats(["ejs", "njk", "liquid"]); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.setTemplateFormats(["ejs", "njk", "liquid"]); + let cfg = templateCfg.getConfig(); t.deepEqual(cfg.templateFormats, ["ejs", "njk", "liquid"]); }); test("setTemplateFormats(array, size 1)", (t) => { - eleventyConfig.reset(); - eleventyConfig.setTemplateFormats(["liquid"]); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.setTemplateFormats(["liquid"]); + let cfg = templateCfg.getConfig(); t.deepEqual(cfg.templateFormats, ["liquid"]); }); test("setTemplateFormats(empty array)", (t) => { - eleventyConfig.reset(); - eleventyConfig.setTemplateFormats([]); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.setTemplateFormats([]); + let cfg = templateCfg.getConfig(); t.deepEqual(cfg.templateFormats, []); }); test("setTemplateFormats(null)", (t) => { - eleventyConfig.reset(); - eleventyConfig.setTemplateFormats(null); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.setTemplateFormats(null); + let cfg = templateCfg.getConfig(); t.true(cfg.templateFormats.length > 0); }); test("multiple setTemplateFormats calls", (t) => { - eleventyConfig.reset(); - eleventyConfig.setTemplateFormats("njk"); - eleventyConfig.setTemplateFormats("pug"); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.setTemplateFormats("njk"); + templateCfg.userConfig.setTemplateFormats("pug"); + let cfg = templateCfg.getConfig(); t.deepEqual(cfg.templateFormats, ["pug"]); }); test("addTemplateFormats()", (t) => { - eleventyConfig.reset(); - eleventyConfig.addTemplateFormats("vue"); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addTemplateFormats("vue"); + let cfg = templateCfg.getConfig(); // should have ALL of the original defaults t.deepEqual(cfg.templateFormats, ["md", "njk", "vue"]); @@ -355,26 +336,25 @@ test("both setTemplateFormats and addTemplateFormats", (t) => { // project config file config API // project config file config return object - eleventyConfig.reset(); - eleventyConfig.addTemplateFormats("vue"); - eleventyConfig.setTemplateFormats("pug"); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addTemplateFormats("vue"); + templateCfg.userConfig.setTemplateFormats("pug"); + let cfg = templateCfg.getConfig(); t.deepEqual(cfg.templateFormats, ["pug", "vue"]); }); test("libraryOverrides", (t) => { let mdLib = md(); - eleventyConfig.setLibrary("md", mdLib); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.setLibrary("md", mdLib); + let cfg = templateCfg.getConfig(); t.falsy(cfg.libraryOverrides.ldkja); t.falsy(cfg.libraryOverrides.njk); @@ -383,43 +363,44 @@ test("libraryOverrides", (t) => { }); test("addGlobalData", (t) => { - eleventyConfig.reset(); - eleventyConfig.addGlobalData("function", () => new Date()); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addGlobalData("function", () => new Date()); + let cfg = templateCfg.getConfig(); t.not(Object.keys(cfg.globalData).indexOf("function"), -1); }); test("Properly throws error on missing module #182", (t) => { t.throws(function () { - new TemplateConfig( + let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/broken-config.js" ); + + templateCfg.getConfig(); }); }); test("Properly throws error when config returns a Promise", (t) => { t.throws(function () { - new TemplateConfig( + let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config-promise.js" ); + templateCfg.getConfig(); }); }); test(".addWatchTarget adds a watch target", (t) => { - eleventyConfig.reset(); - eleventyConfig.addWatchTarget("/testdirectory/"); - let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), "./test/stubs/config.js" ); + templateCfg.userConfig.addWatchTarget("/testdirectory/"); + let cfg = templateCfg.getConfig(); t.deepEqual(cfg.additionalWatchTargets, ["/testdirectory/"]); }); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 0afe98f94..d439617b3 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -8,7 +8,6 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const TemplateWriter = require("../src/TemplateWriter"); // Not sure why but this required `ava` and _createTemplate 👀 // const Template = require("../src/Template"); -const eleventyConfig = require("../src/EleventyConfig"); const normalizeNewLines = require("./Util/normalizeNewLines"); // TODO make sure if output is a subdir of input dir that they don’t conflict. @@ -110,8 +109,7 @@ test("__testGetCollectionsData with custom collection (ascending)", async (t) => ["md"] ); - /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("customPostsAsc", function (collection) { + tw.userConfig.addCollection("customPostsAsc", function (collection) { return collection.getFilteredByTag("post").sort(function (a, b) { return a.date - b.date; }); @@ -132,8 +130,7 @@ test("__testGetCollectionsData with custom collection (descending)", async (t) = ["md"] ); - /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("customPosts", function (collection) { + tw.userConfig.addCollection("customPosts", function (collection) { return collection.getFilteredByTag("post").sort(function (a, b) { return b.date - a.date; }); @@ -154,8 +151,7 @@ test("__testGetCollectionsData with custom collection (filter only to markdown i ["md"] ); - /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("onlyMarkdown", function (collection) { + tw.userConfig.addCollection("onlyMarkdown", function (collection) { return collection.getAllSorted().filter(function (item) { let extension = item.inputPath.split(".").pop(); return extension === "md"; @@ -400,8 +396,7 @@ test("Custom collection returns array", async (t) => { ["md"] ); - /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("returnAllInputPaths", function (collection) { + tw.userConfig.addCollection("returnAllInputPaths", function (collection) { return collection.getAllSorted().map(function (item) { return item.inputPath; }); @@ -422,8 +417,7 @@ test("Custom collection returns a string", async (t) => { ["md"] ); - /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("returnATestString", function (collection) { + tw.userConfig.addCollection("returnATestString", function (collection) { return "test"; }); @@ -440,8 +434,7 @@ test("Custom collection returns an object", async (t) => { ["md"] ); - /* Careful here, eleventyConfig is a global */ - eleventyConfig.addCollection("returnATestObject", function () { + tw.userConfig.addCollection("returnATestObject", function () { return { test: "value" }; }); diff --git a/test/UserConfigTest.js b/test/UserConfigTest.js index 41e409626..23e389749 100644 --- a/test/UserConfigTest.js +++ b/test/UserConfigTest.js @@ -2,29 +2,152 @@ const test = require("ava"); const UserConfig = require("../src/UserConfig"); test("Template Formats", (t) => { - let cfg = new UserConfig(); + let userCfg = new UserConfig(); - t.falsy(cfg.getMergingConfigObject().templateFormats); + t.falsy(userCfg.getMergingConfigObject().templateFormats); - cfg.setTemplateFormats("njk,liquid"); - t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); + userCfg.setTemplateFormats("njk,liquid"); + t.deepEqual(userCfg.getMergingConfigObject().templateFormats, [ + "njk", + "liquid", + ]); // setting multiple times takes the last one - cfg.setTemplateFormats("njk,liquid,pug"); - cfg.setTemplateFormats("njk,liquid"); - t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); + userCfg.setTemplateFormats("njk,liquid,pug"); + userCfg.setTemplateFormats("njk,liquid"); + t.deepEqual(userCfg.getMergingConfigObject().templateFormats, [ + "njk", + "liquid", + ]); }); test("Template Formats (Arrays)", (t) => { - let cfg = new UserConfig(); + let userCfg = new UserConfig(); - t.falsy(cfg.getMergingConfigObject().templateFormats); + t.falsy(userCfg.getMergingConfigObject().templateFormats); - cfg.setTemplateFormats(["njk", "liquid"]); - t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); + userCfg.setTemplateFormats(["njk", "liquid"]); + t.deepEqual(userCfg.getMergingConfigObject().templateFormats, [ + "njk", + "liquid", + ]); // setting multiple times takes the last one - cfg.setTemplateFormats(["njk", "liquid", "pug"]); - cfg.setTemplateFormats(["njk", "liquid"]); - t.deepEqual(cfg.getMergingConfigObject().templateFormats, ["njk", "liquid"]); + userCfg.setTemplateFormats(["njk", "liquid", "pug"]); + userCfg.setTemplateFormats(["njk", "liquid"]); + t.deepEqual(userCfg.getMergingConfigObject().templateFormats, [ + "njk", + "liquid", + ]); +}); + +// more in TemplateConfigTest.js + +test.cb("Events", (t) => { + let userCfg = new UserConfig(); + userCfg.on("testEvent", function (arg1, arg2, arg3) { + t.is(arg1, "arg1"); + t.is(arg2, "arg2"); + t.is(arg3, "arg3"); + t.end(); + }); + + userCfg.emit("testEvent", "arg1", "arg2", "arg3"); +}); + +test.cb("Async Events", (t) => { + let userCfg = new UserConfig(); + let arg1; + + userCfg.on( + "asyncTestEvent", + (_arg1) => + new Promise((resolve) => { + setTimeout(() => { + arg1 = _arg1; + resolve(); + }, 10); + }) + ); + + userCfg.emit("asyncTestEvent", "arg1").then(() => { + t.is(arg1, "arg1"); + t.end(); + }); +}); + +test("Add Collections", (t) => { + let userCfg = new UserConfig(); + userCfg.addCollection("myCollection", function (collection) {}); + t.deepEqual(Object.keys(userCfg.getCollections()), ["myCollection"]); +}); + +test("Add Collections throws error on key collision", (t) => { + let userCfg = new UserConfig(); + userCfg.addCollection("myCollectionCollision", function (collection) {}); + + t.throws(() => { + userCfg.addCollection("myCollectionCollision", function (collection) {}); + }); +}); + +test("Set manual Pass-through File Copy (single call)", (t) => { + let userCfg = new UserConfig(); + userCfg.addPassthroughCopy("img"); + + t.is(userCfg.passthroughCopies["img"], true); +}); + +test("Set manual Pass-through File Copy (chained calls)", (t) => { + let userCfg = new UserConfig(); + userCfg + .addPassthroughCopy("css") + .addPassthroughCopy("js") + .addPassthroughCopy({ "./src/static": "static" }) + .addPassthroughCopy({ "./src/empty": "./" }); + + t.is(userCfg.passthroughCopies["css"], true); + t.is(userCfg.passthroughCopies["js"], true); + t.is(userCfg.passthroughCopies["./src/static"], "static"); + t.is(userCfg.passthroughCopies["./src/empty"], "./"); +}); + +test("Set manual Pass-through File Copy (glob patterns)", (t) => { + let userCfg = new UserConfig(); + userCfg.addPassthroughCopy({ + "./src/static/**/*": "renamed", + "./src/markdown/*.md": "", + }); + + // does not exist + t.is(userCfg.passthroughCopies["css/**"], undefined); + t.is(userCfg.passthroughCopies["js/**"], undefined); + + // exists + t.is(userCfg.passthroughCopies["./src/static/**/*"], "renamed"); + t.is(userCfg.passthroughCopies["./src/markdown/*.md"], ""); +}); + +test("Set Template Formats (string)", (t) => { + let userCfg = new UserConfig(); + userCfg.setTemplateFormats("ejs, njk, liquid"); + t.deepEqual(userCfg.templateFormats, ["ejs", "njk", "liquid"]); +}); + +test("Set Template Formats (array)", (t) => { + let userCfg = new UserConfig(); + userCfg.setTemplateFormats(["ejs", "njk", "liquid"]); + t.deepEqual(userCfg.templateFormats, ["ejs", "njk", "liquid"]); +}); + +test("Set Template Formats (js passthrough copy)", (t) => { + let userCfg = new UserConfig(); + userCfg.setTemplateFormats("ejs, njk, liquid, js"); + t.deepEqual(userCfg.templateFormats, ["ejs", "njk", "liquid", "js"]); +}); + +test("Set Template Formats (11ty.js)", (t) => { + let userCfg = new UserConfig(); + userCfg.setTemplateFormats("ejs, njk, liquid, 11ty.js"); + t.deepEqual(userCfg.templateFormats, ["ejs", "njk", "liquid", "11ty.js"]); }); From 3326e5e3f613091e1c4de5896d03b05ca54310da Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 18 Feb 2021 18:02:00 -0600 Subject: [PATCH 332/746] These tests are working --- src/Eleventy.js | 44 +++++++++++++++++++++++++++----------------- test/EleventyTest.js | 6 +++--- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 9e2a40859..b9cc73c89 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -11,12 +11,12 @@ const EleventyWatch = require("./EleventyWatch"); const EleventyWatchTargets = require("./EleventyWatchTargets"); const EleventyFiles = require("./EleventyFiles"); const ConsoleLogger = require("./Util/ConsoleLogger"); +const TemplateConfig = require("./TemplateConfig"); const { performance } = require("perf_hooks"); const templateCache = require("./TemplateCache"); const simplePlural = require("./Util/Pluralize"); const deleteRequireCache = require("./Util/DeleteRequireCache"); -const config = require("./Config"); const bench = require("./BenchmarkManager"); const debug = require("debug")("Eleventy"); @@ -32,9 +32,14 @@ const debug = require("debug")("Eleventy"); * @returns {module:11ty/eleventy/Eleventy~Eleventy} */ class Eleventy { - constructor(input, output, options = {}) { - /** @member {module:11ty/eleventy/TemplateConfig~TemplateConfig~config} - TemplateConfig instance */ - this.config = config.getConfig(); + constructor(input, output, options = {}, eleventyConfig = null) { + if (!eleventyConfig) { + this.eleventyConfig = new TemplateConfig(); + } else { + this.eleventyConfig = eleventyConfig; + } + + this.config = this.eleventyConfig.getConfig(); /** * @member {String} - The path to Eleventy's config file. @@ -82,6 +87,7 @@ class Eleventy { /** @member {Object} - tbd. */ this.eleventyServe = new EleventyServe(); + this.eleventyServe.config = this.eleventyConfig; /** @member {String} - Holds the path to the input directory. */ this.rawInput = input; @@ -174,8 +180,8 @@ class Eleventy { */ setPathPrefix(pathPrefix) { if (pathPrefix || pathPrefix === "") { - config.setPathPrefix(pathPrefix); - this.config = config.getConfig(); + this.eleventyConfig.setPathPrefix(pathPrefix); + this.config = this.eleventyConfig.getConfig(); } } @@ -199,8 +205,8 @@ class Eleventy { if (configPath) { this.configPath = configPath; - config.setProjectConfigPath(configPath); - this.config = config.getConfig(); + this.eleventyConfig.setProjectConfigPath(configPath); + this.config = this.eleventyConfig.getConfig(); } } @@ -298,14 +304,14 @@ class Eleventy { this.inputDir, this.outputDir, formats, - this.isPassthroughAll + this.eleventyConfig ); - + this.eleventyFiles.setPassthroughAll(this.isPassthroughAll); this.eleventyFiles.setInput(this.inputDir, this.input); this.eleventyFiles.extensionMap = this.extensionMap; this.eleventyFiles.init(); - this.templateData = new TemplateData(this.inputDir); + this.templateData = new TemplateData(this.inputDir, this.eleventyConfig); this.templateData.extensionMap = this.extensionMap; this.eleventyFiles.templateData = this.templateData; @@ -314,7 +320,7 @@ class Eleventy { this.outputDir, formats, this.templateData, - this.isPassthroughAll + this.eleventyConfig ); this.writer.setInput(this.inputDir, this.input); this.writer.logger = this.logger; @@ -465,9 +471,9 @@ Arguments: * @method */ resetConfig() { - config.reset(); + this.eleventyConfig.reset(); - this.config = config.getConfig(); + this.config = this.eleventyConfig.getConfig(); this.eleventyServe.config = this.config; // only use config quietMode if --quiet not set on CLI @@ -507,7 +513,11 @@ Arguments: ); // reset and reload global configuration :O - if (this.watchManager.hasQueuedFile(config.getLocalProjectConfigFile())) { + if ( + this.watchManager.hasQueuedFile( + this.eleventyConfig.getLocalProjectConfigFile() + ) + ) { this.resetConfig(); } @@ -599,7 +609,7 @@ Arguments: this.watchTargets.add(this.eleventyFiles.getGlobWatcherFiles()); // Watch the local project config file - this.watchTargets.add(config.getLocalProjectConfigFile()); + this.watchTargets.add(this.eleventyConfig.getLocalProjectConfigFile()); // Template and Directory Data Files this.watchTargets.add( @@ -636,7 +646,7 @@ Arguments: // Config file dependencies this.watchTargets.addDependencies( - config.getLocalProjectConfigFile(), + this.eleventyConfig.getLocalProjectConfigFile(), filterOutGlobalDataFiles ); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index ce61f4929..69395dcf6 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -1,13 +1,13 @@ const test = require("ava"); const Eleventy = require("../src/Eleventy"); const EleventyWatchTargets = require("../src/EleventyWatchTargets"); -const templateConfig = require("../src/Config"); - -const config = templateConfig.getConfig(); +const TemplateConfig = require("../src/TemplateConfig"); test("Eleventy, defaults inherit from config", async (t) => { let elev = new Eleventy(); + let config = new TemplateConfig().getConfig(); + t.truthy(elev.input); t.truthy(elev.outputDir); t.is(elev.input, config.dir.input); From 406303322061af91df602f8a113223e54764e347 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 18 Feb 2021 20:13:13 -0600 Subject: [PATCH 333/746] More working tests --- src/EleventyFiles.js | 20 ++-- src/EleventyServe.js | 14 ++- test/EleventyFilesTest.js | 210 ++++++++++++++++++++++++++++++-------- test/EleventyServeTest.js | 28 +++-- 4 files changed, 209 insertions(+), 63 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 3b493a5ea..302b84edb 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -6,22 +6,28 @@ const TemplateData = require("./TemplateData"); const TemplateGlob = require("./TemplateGlob"); const TemplatePath = require("./TemplatePath"); const TemplatePassthroughManager = require("./TemplatePassthroughManager"); +const EleventyBaseError = require("./EleventyBaseError"); + +class EleventyFilesError extends EleventyBaseError {} -const config = require("./Config"); const debug = require("debug")("Eleventy:EleventyFiles"); // const debugDev = require("debug")("Dev:Eleventy:EleventyFiles"); const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class EleventyFiles { - constructor(input, outputDir, formats, passthroughAll) { - this.config = config.getConfig(); + constructor(input, outputDir, formats, eleventyConfig) { + if (!eleventyConfig) { + throw new EleventyFilesError("Missing config argument."); + } + this.eleventyConfig = eleventyConfig; + this.config = eleventyConfig.getConfig(); this.input = input; this.inputDir = TemplatePath.getDir(this.input); this.outputDir = outputDir; this.initConfig(); - this.passthroughAll = !!passthroughAll; + this.passthroughAll = false; this.formats = formats; @@ -29,7 +35,8 @@ class EleventyFiles { this.alreadyInit = false; } - /* Overrides this.input and this.inputDir */ + /* Overrides this.input and this.inputDir, + * Useful when input is a file and inputDir is not its direct parent */ setInput(inputDir, input) { this.inputDir = inputDir; this.input = input; @@ -105,6 +112,7 @@ class EleventyFiles { this.config = config; this.initConfig(); } + /* Set command root for local project paths */ _setLocalPathRoot(dir) { this.localPathRoot = dir; @@ -150,7 +158,7 @@ class EleventyFiles { get templateData() { if (!this._templateData) { - this._templateData = new TemplateData(this.inputDir); + this._templateData = new TemplateData(this.inputDir, this.eleventyConfig); } return this._templateData; } diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 6730e33e4..54b19238a 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -2,17 +2,25 @@ const fs = require("fs-extra"); const path = require("path"); const TemplatePath = require("./TemplatePath"); -const config = require("./Config"); +const EleventyBaseError = require("./EleventyBaseError"); const debug = require("debug")("EleventyServe"); +class EleventyServeConfigError extends EleventyBaseError {} class EleventyServe { constructor() {} get config() { - return this.configOverride || config.getConfig(); + if (!this._config) { + throw new EleventyServeConfigError( + "You need to set the config property on EleventyServe." + ); + } + + return this._config; } + set config(config) { - this.configOverride = config; + this._config = config; } setOutputDir(outputDir) { diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 072a1d371..160765433 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -2,13 +2,16 @@ const test = require("ava"); const fastglob = require("fast-glob"); const EleventyFiles = require("../src/EleventyFiles"); const TemplatePath = require("../src/TemplatePath"); +const TemplateConfig = require("../src/TemplateConfig"); const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); test("getFiles", async (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "./test/stubs/writeTest", "./test/stubs/_writeTestSite", - ["ejs", "md"] + ["ejs", "md"], + eleventyConfig ); evf.init(); @@ -16,10 +19,12 @@ test("getFiles", async (t) => { }); test("getFiles (without 11ty.js)", async (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", - ["ejs", "md"] + ["ejs", "md"], + eleventyConfig ); evf.init(); @@ -27,10 +32,12 @@ test("getFiles (without 11ty.js)", async (t) => { }); test("getFiles (with 11ty.js)", async (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", - ["ejs", "md", "11ty.js"] + ["ejs", "md", "11ty.js"], + eleventyConfig ); evf.init(); @@ -38,10 +45,12 @@ test("getFiles (with 11ty.js)", async (t) => { }); test("getFiles (with js, treated as passthrough copy)", async (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", - ["ejs", "md", "js"] + ["ejs", "md", "js"], + eleventyConfig ); evf.init(); @@ -59,10 +68,12 @@ test("getFiles (with js, treated as passthrough copy)", async (t) => { }); test("getFiles (with case insensitivity)", async (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "./test/stubs/writeTestJS-casesensitive", "./test/stubs/_writeTestJSCaseSensitiveSite", - ["JS"] + ["JS"], + eleventyConfig ); evf.init(); @@ -86,10 +97,12 @@ test("getFiles (with case insensitivity)", async (t) => { }); test("Mutually exclusive Input and Output dirs", async (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "./test/stubs/writeTest", "./test/stubs/_writeTestSite", - ["ejs", "md"] + ["ejs", "md"], + eleventyConfig ); evf.init(); @@ -100,10 +113,13 @@ test("Mutually exclusive Input and Output dirs", async (t) => { }); test("Single File Input (deep path)", async (t) => { - let evf = new EleventyFiles("./test/stubs/index.html", "./test/stubs/_site", [ - "ejs", - "md", - ]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "./test/stubs/index.html", + "./test/stubs/_site", + ["ejs", "md"], + eleventyConfig + ); evf.init(); let files = await fastglob(evf.getFileGlobs()); @@ -113,7 +129,13 @@ test("Single File Input (deep path)", async (t) => { }); test("Single File Input (shallow path)", async (t) => { - let evf = new EleventyFiles("README.md", "./test/stubs/_site", ["md"]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "README.md", + "./test/stubs/_site", + ["md"], + eleventyConfig + ); evf.init(); let globs = evf.getFileGlobs().filter((path) => path !== "!./README.md"); @@ -124,10 +146,12 @@ test("Single File Input (shallow path)", async (t) => { }); test("Glob Input", async (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "./test/stubs/glob-pages/!(contact.md)", "./test/stubs/_site", - ["md"] + ["md"], + eleventyConfig ); evf.init(); @@ -175,7 +199,13 @@ test("defaults if passed file name does not exist", (t) => { }); test(".eleventyignore files", async (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["ejs", "md"]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + ["ejs", "md"], + eleventyConfig + ); evf.init(); let ignoredFiles = await fastglob("test/stubs/ignoredFolder/*.md"); t.is(ignoredFiles.length, 1); @@ -194,10 +224,12 @@ test(".eleventyignore files", async (t) => { /* .eleventyignore and .gitignore combos */ test("Get ignores (no .eleventyignore no .gitignore)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore1", "test/stubs/ignore1/_site", - [] + [], + eleventyConfig ); evf.init(); @@ -213,10 +245,12 @@ test("Get ignores (no .eleventyignore no .gitignore)", (t) => { }); test("Get ignores (no .eleventyignore)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore2", "test/stubs/ignore2/_site", - [] + [], + eleventyConfig ); evf.init(); evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); @@ -229,10 +263,12 @@ test("Get ignores (no .eleventyignore)", (t) => { }); test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore2", "test/stubs/ignore2/_site", - [] + [], + eleventyConfig ); evf.init(); @@ -251,10 +287,12 @@ test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", (t) => { }); test("Get ignores (no .gitignore)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore3", "test/stubs/ignore3/_site", - [] + [], + eleventyConfig ); evf.init(); evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); @@ -271,10 +309,12 @@ test("Get ignores (no .gitignore)", (t) => { }); test("Get ignores (both .eleventyignore and .gitignore)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore4", "test/stubs/ignore4/_site", - [] + [], + eleventyConfig ); evf.init(); evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); @@ -289,10 +329,12 @@ test("Get ignores (both .eleventyignore and .gitignore)", (t) => { }); test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(false))", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore4", "test/stubs/ignore4/_site", - [] + [], + eleventyConfig ); evf.init(); @@ -313,10 +355,12 @@ test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(fa }); test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore5", "test/stubs/ignore5/_site", - [] + [], + eleventyConfig ); evf.init(); @@ -332,10 +376,12 @@ test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { }); test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is empty)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore6", "test/stubs/ignore6/_site", - [] + [], + eleventyConfig ); evf.init(); evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); @@ -352,10 +398,12 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is }); test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore7", "test/stubs/ignore7/_site", - [] + [], + eleventyConfig ); evf.init(); @@ -371,10 +419,12 @@ test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)" }); test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore has spaces inside)", (t) => { + let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore8", "test/stubs/ignore8/_site", - [] + [], + eleventyConfig ); evf.init(); evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); @@ -392,7 +442,13 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore ha /* End .eleventyignore and .gitignore combos */ test("getTemplateData caching", (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + [], + eleventyConfig + ); evf.init(); let templateDataFirstCall = evf.templateData; let templateDataSecondCall = evf.templateData; @@ -400,19 +456,32 @@ test("getTemplateData caching", (t) => { }); test("getDataDir", (t) => { - let evf = new EleventyFiles(".", "_site", []); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles(".", "_site", [], eleventyConfig); evf.init(); t.is(evf.getDataDir(), "_data"); }); test("getDataDir subdir", (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + [], + eleventyConfig + ); evf.init(); t.is(evf.getDataDir(), "test/stubs/_data"); }); test("Include and Data Dirs", (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + [], + eleventyConfig + ); evf.init(); t.deepEqual(evf._getIncludesAndDataDirs(), [ @@ -422,7 +491,13 @@ test("Include and Data Dirs", (t) => { }); test("Ignore Include and Data Dirs", (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + [], + eleventyConfig + ); evf.init(); t.deepEqual(evf._getIncludesAndDataDirIgnores(), [ @@ -432,7 +507,13 @@ test("Ignore Include and Data Dirs", (t) => { }); test("Input to 'src' and empty includes dir (issue #403)", (t) => { - let evf = new EleventyFiles("src", "src/_site", ["md", "liquid", "html"]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "src", + "src/_site", + ["md", "liquid", "html"], + eleventyConfig + ); evf._setConfig({ useGitIgnore: false, eleventyignoreOverride: "!./src/_includes/**", @@ -456,9 +537,13 @@ test("Input to 'src' and empty includes dir (issue #403)", (t) => { }); test("Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { - let evf = new EleventyFiles("test/stubs-403", "test/stubs-403/_site", [ - "liquid", - ]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs-403", + "test/stubs-403/_site", + ["liquid"], + eleventyConfig + ); evf._setConfig({ useGitIgnore: false, eleventyignoreOverride: @@ -480,9 +565,13 @@ test("Bad expected output, this indicates a bug upstream in a dependency. Input }); test("Workaround for Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { - let evf = new EleventyFiles("test/stubs-403", "test/stubs-403/_site", [ - "liquid", - ]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs-403", + "test/stubs-403/_site", + ["liquid"], + eleventyConfig + ); evf._setConfig({ useGitIgnore: false, eleventyignoreOverride: "!./test/stubs-403/_includes/**", @@ -499,9 +588,13 @@ test("Workaround for Bad expected output, this indicates a bug upstream in a dep }); test("Issue #403: all .eleventyignores should be relative paths not absolute paths", async (t) => { - let evf = new EleventyFiles("test/stubs-403", "test/stubs-403/_site", [ - "liquid", - ]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs-403", + "test/stubs-403/_site", + ["liquid"], + eleventyConfig + ); evf._setConfig({ useGitIgnore: false, dir: { @@ -523,7 +616,13 @@ test("Issue #403: all .eleventyignores should be relative paths not absolute pat }); test("Glob Watcher Files", async (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["njk"]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + ["njk"], + eleventyConfig + ); evf.init(); t.deepEqual(evf.getGlobWatcherFiles(), [ @@ -534,7 +633,13 @@ test("Glob Watcher Files", async (t) => { }); test("Glob Watcher Files with File Extension Passthroughs", async (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["njk", "png"]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + ["njk", "png"], + eleventyConfig + ); evf.init(); t.deepEqual(evf.getGlobWatcherFiles(), [ @@ -546,7 +651,13 @@ test("Glob Watcher Files with File Extension Passthroughs", async (t) => { }); test("Glob Watcher Files with Config Passthroughs (one template format)", async (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", ["njk"]); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + ["njk"], + eleventyConfig + ); evf.init(); let mgr = new TemplatePassthroughManager(); @@ -568,7 +679,13 @@ test("Glob Watcher Files with Config Passthroughs (one template format)", async }); test("Glob Watcher Files with Config Passthroughs (no template formats)", async (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", []); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + [], + eleventyConfig + ); evf.init(); t.deepEqual(await evf.getGlobWatcherTemplateDataFiles(), [ @@ -579,7 +696,14 @@ test("Glob Watcher Files with Config Passthroughs (no template formats)", async }); test("Glob Watcher Files with passthroughAll", async (t) => { - let evf = new EleventyFiles("test/stubs", "test/stubs/_site", [], true); + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs", + "test/stubs/_site", + [], + eleventyConfig + ); + evf.setPassthroughAll(true); evf.init(); t.is((await evf.getFileGlobs())[0], "./test/stubs/**"); diff --git a/test/EleventyServeTest.js b/test/EleventyServeTest.js index c01eed650..8a0965431 100644 --- a/test/EleventyServeTest.js +++ b/test/EleventyServeTest.js @@ -1,13 +1,19 @@ const test = require("ava"); const EleventyServe = require("../src/EleventyServe"); +const TemplateConfig = require("../src/TemplateConfig"); test("Constructor", (t) => { let es = new EleventyServe(); + let cfg = new TemplateConfig().getConfig(); + es.config = cfg; t.is(es.getPathPrefix(), "/"); }); test("Directories", (t) => { let es = new EleventyServe(); + let cfg = new TemplateConfig().getConfig(); + es.config = cfg; + es.setOutputDir("_site"); t.is(es.getRedirectDir("test"), "_site/test"); t.is(es.getRedirectFilename("test"), "_site/test/index.html"); @@ -15,9 +21,9 @@ test("Directories", (t) => { test("Get Options", (t) => { let es = new EleventyServe(); - es.config = { - pathPrefix: "/", - }; + let cfg = new TemplateConfig().getConfig(); + cfg.pathPrefix = "/"; + es.config = cfg; es.setOutputDir("_site"); t.deepEqual(es.getOptions(), { @@ -37,9 +43,9 @@ test("Get Options", (t) => { test("Get Options (with a pathPrefix)", (t) => { let es = new EleventyServe(); - es.config = { - pathPrefix: "/web/", - }; + let cfg = new TemplateConfig().getConfig(); + cfg.pathPrefix = "/web/"; + es.config = cfg; es.setOutputDir("_site"); t.deepEqual(es.getOptions(), { @@ -62,12 +68,12 @@ test("Get Options (with a pathPrefix)", (t) => { test("Get Options (override in config)", (t) => { let es = new EleventyServe(); - es.config = { - pathPrefix: "/", - browserSyncConfig: { - notify: true, - }, + let cfg = new TemplateConfig().getConfig(); + cfg.pathPrefix = "/"; + cfg.browserSyncConfig = { + notify: true, }; + es.config = cfg; es.setOutputDir("_site"); t.deepEqual(es.getOptions(), { From fdf87fe2566e02f90376653bc4fc5845e967076c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 18 Feb 2021 22:35:39 -0600 Subject: [PATCH 334/746] All tests pass progress --- src/Eleventy.js | 2 +- src/EleventyExtensionMap.js | 23 +- src/EleventyFiles.js | 7 +- src/Engines/TemplateEngine.js | 3 +- src/Plugins/Pagination.js | 12 +- src/Template.js | 10 +- src/TemplateContent.js | 20 +- src/TemplateData.js | 14 +- src/TemplateLayout.js | 22 +- src/TemplateLayoutPathResolver.js | 10 +- src/TemplateMap.js | 13 +- src/TemplatePassthroughManager.js | 3 +- src/TemplateWriter.js | 33 +- test/EleventyExtensionMapTest.js | 44 +-- test/PaginationTest.js | 215 +++++++---- test/TemplateCacheTest.js | 12 +- test/TemplateCollectionTest.js | 117 ++++-- test/TemplateDataTest.js | 81 ++-- test/TemplateFileSlugTest.js | 4 +- test/TemplateLayoutPathResolverTest.js | 36 +- test/TemplateLayoutTest.js | 36 +- test/TemplateMapTest-ComputedData.js | 86 ++++- test/TemplateMapTest.js | 466 +++++++++++++++-------- test/TemplateRenderCustomTest.js | 12 +- test/TemplateRenderEJSTest.js | 4 +- test/TemplateRenderHTMLTest.js | 4 +- test/TemplateRenderHamlTest.js | 4 +- test/TemplateRenderHandlebarsTest.js | 9 +- test/TemplateRenderJavaScriptTest.js | 14 +- test/TemplateRenderLiquidTest.js | 60 +-- test/TemplateRenderMarkdownPluginTest.js | 13 +- test/TemplateRenderMarkdownTest.js | 4 +- test/TemplateRenderMustacheTest.js | 4 +- test/TemplateRenderNunjucksTest.js | 28 +- test/TemplateRenderPugTest.js | 4 +- test/TemplateRenderTest.js | 4 +- test/TemplateTest-ComputedData.js | 25 +- test/TemplateTest-JavaScript.js | 45 +-- test/TemplateTest.js | 242 ++++++------ test/TemplateWriterTest.js | 168 ++++++-- test/UserDataExtensionsTest.js | 13 +- test/_getNewTemplateForTests.js | 41 +- 42 files changed, 1258 insertions(+), 709 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index b9cc73c89..c16df4c11 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -298,7 +298,7 @@ class Eleventy { this.config.inputDir = this.inputDir; let formats = this.formatsOverride || this.config.templateFormats; - this.extensionMap = new EleventyExtensionMap(formats); + this.extensionMap = new EleventyExtensionMap(formats, this.eleventyConfig); this.eleventyFiles = new EleventyFiles( this.inputDir, diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 521a75247..87fb51078 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -1,8 +1,17 @@ const TemplateEngineManager = require("./TemplateEngineManager"); +const TemplateConfig = require("./TemplateConfig"); const TemplatePath = require("./TemplatePath"); +const EleventyBaseError = require("./EleventyBaseError"); + +class EleventyExtensionMapConfigError extends EleventyBaseError {} class EleventyExtensionMap { - constructor(formatKeys) { + constructor(formatKeys, config) { + if (!config) { + throw new EleventyExtensionMapConfigError("Missing `config` argument."); + } + this.config = config; + this.formatKeys = formatKeys; this.setFormats(formatKeys); @@ -22,11 +31,15 @@ class EleventyExtensionMap { ); } - get config() { - return this.configOverride || require("./Config").getConfig(); - } set config(cfg) { - this.configOverride = cfg; + this._config = cfg; + } + + get config() { + if (this._config instanceof TemplateConfig) { + return this._config.getConfig(); + } + return this._config; } get engineManager() { diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 302b84edb..28c22dc24 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -17,7 +17,7 @@ const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class EleventyFiles { constructor(input, outputDir, formats, eleventyConfig) { if (!eleventyConfig) { - throw new EleventyFilesError("Missing config argument."); + throw new EleventyFilesError("Missing `eleventyConfig`` argument."); } this.eleventyConfig = eleventyConfig; this.config = eleventyConfig.getConfig(); @@ -125,7 +125,10 @@ class EleventyFiles { get extensionMap() { // for tests if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(this.formats); + this._extensionMap = new EleventyExtensionMap( + this.formats, + this.eleventyConfig + ); this._extensionMap.config = this.config; } return this._extensionMap; diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index a6aee2a38..161ca8b25 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -36,8 +36,7 @@ class TemplateEngine { get extensionMap() { if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(); - // this._extensionMap.config = this.config; + this._extensionMap = new EleventyExtensionMap([], this.config); } return this._extensionMap; } diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 6fa062d3b..5815ffcc3 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -2,13 +2,19 @@ const lodashChunk = require("lodash/chunk"); const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); const EleventyBaseError = require("../EleventyBaseError"); -const config = require("../Config"); +class PaginationConfigError extends EleventyBaseError {} class PaginationError extends EleventyBaseError {} class Pagination { - constructor(data) { - this.config = config.getConfig(); + constructor(data, config) { + if (!config) { + throw new PaginationConfigError( + "Expected `config` argument to Pagination class." + ); + } + + this.config = config; this.setData(data); } diff --git a/src/Template.js b/src/Template.js index f6056f80e..bc24b0a2d 100755 --- a/src/Template.js +++ b/src/Template.js @@ -21,9 +21,9 @@ const debugDev = require("debug")("Dev:Eleventy:Template"); const bench = require("./BenchmarkManager").get("Aggregate"); class Template extends TemplateContent { - constructor(path, inputDir, outputDir, templateData, extensionMap) { + constructor(path, inputDir, outputDir, templateData, extensionMap, config) { debugDev("new Template(%o)", path); - super(path, inputDir); + super(path, inputDir, config); this.parsed = parsePath(path); @@ -532,7 +532,7 @@ class Template extends TemplateContent { } else { // needs collections for pagination items // but individual pagination entries won’t be part of a collection - this.paging = new Pagination(data); + this.paging = new Pagination(data, this.config); this.paging.setTemplate(this); let pageTemplates = await this.paging.getPageTemplates(); @@ -694,9 +694,9 @@ class Template extends TemplateContent { this.inputDir, this.outputDir, this.templateData, - this.extensionMap + this.extensionMap, + this.config ); - tmpl.config = this.config; tmpl.logger = this.logger; for (let transform of this.transforms) { diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 7fefe5810..9d6ad6393 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -8,19 +8,27 @@ const EleventyExtensionMap = require("./EleventyExtensionMap"); const TemplateData = require("./TemplateData"); const TemplateRender = require("./TemplateRender"); const TemplatePath = require("./TemplatePath"); +const TemplateConfig = require("./TemplateConfig"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyErrorUtil = require("./EleventyErrorUtil"); -const config = require("./Config"); const debug = require("debug")("Eleventy:TemplateContent"); const debugDev = require("debug")("Dev:Eleventy:TemplateContent"); const bench = require("./BenchmarkManager").get("Aggregate"); +class TemplateContentConfigError extends EleventyBaseError {} class TemplateContentFrontMatterError extends EleventyBaseError {} class TemplateContentCompileError extends EleventyBaseError {} class TemplateContentRenderError extends EleventyBaseError {} class TemplateContent { - constructor(inputPath, inputDir) { + constructor(inputPath, inputDir, config) { + if (!config) { + throw new TemplateContentConfigError( + "Missing `config` argument to TemplateContent" + ); + } + this.config = config; + this.inputPath = inputPath; if (inputDir) { @@ -33,8 +41,7 @@ class TemplateContent { /* Used by tests */ get extensionMap() { if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(); - this._extensionMap.config = this.config; + this._extensionMap = new EleventyExtensionMap([], this.config); } return this._extensionMap; } @@ -48,10 +55,9 @@ class TemplateContent { } get config() { - if (!this._config) { - this._config = config.getConfig(); + if (this._config instanceof TemplateConfig) { + return this._config.getConfig(); } - return this._config; } diff --git a/src/TemplateData.js b/src/TemplateData.js index 5e1400169..794463ab9 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -11,7 +11,6 @@ const TemplateGlob = require("./TemplateGlob"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); -const config = require("./Config"); const debugWarn = require("debug")("Eleventy:Warnings"); const debug = require("debug")("Eleventy:TemplateData"); const debugDev = require("debug")("Dev:Eleventy:TemplateData"); @@ -40,11 +39,17 @@ class FSExistsCache { } } +class TemplateDataConfigError extends EleventyBaseError {} class TemplateDataParseError extends EleventyBaseError {} class TemplateData { - constructor(inputDir) { - this.config = config.getConfig(); + constructor(inputDir, eleventyConfig) { + if (!eleventyConfig) { + throw new TemplateDataConfigError("Missing `config`."); + } + this.eleventyConfig = eleventyConfig; + this.config = this.eleventyConfig.getConfig(); + this.dataTemplateEngine = this.config.dataTemplateEngine; this.inputDirNeedsCheck = false; @@ -60,8 +65,7 @@ class TemplateData { get extensionMap() { if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(); - this._extensionMap.config = this.config; + this._extensionMap = new EleventyExtensionMap([], this.config); } return this._extensionMap; } diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index c90c8599a..2c3d1929d 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -3,22 +3,24 @@ const TemplateContent = require("./TemplateContent"); const TemplateData = require("./TemplateData"); const TemplatePath = require("./TemplatePath"); -// TODO move this into the constructor const templateCache = require("./TemplateCache"); -const config = require("./Config"); // const debug = require("debug")("Eleventy:TemplateLayout"); const debugDev = require("debug")("Dev:Eleventy:TemplateLayout"); class TemplateLayout extends TemplateContent { - constructor(key, inputDir, extensionMap) { - // TODO getConfig() is duplicated in TemplateContent (super) - let cfg = config.getConfig(); + constructor(key, inputDir, extensionMap, config) { + if (!config) { + throw new Error("Expected `config` in TemplateLayout constructor."); + } + let resolvedPath = new TemplateLayoutPathResolver( key, inputDir, - extensionMap + extensionMap, + config ).getFullPath(); - super(resolvedPath, inputDir); + + super(resolvedPath, inputDir, config); if (!extensionMap) { throw new Error("Expected `extensionMap` in TemplateLayout constructor."); @@ -27,7 +29,6 @@ class TemplateLayout extends TemplateContent { this.dataKeyLayoutPath = key; this.inputPath = resolvedPath; this.inputDir = inputDir; - this.config = cfg; } static resolveFullKey(key, inputDir) { @@ -41,8 +42,7 @@ class TemplateLayout extends TemplateContent { return templateCache.get(fullKey); } - let tmpl = new TemplateLayout(key, inputDir, extensionMap); - tmpl.config = config; + let tmpl = new TemplateLayout(key, inputDir, extensionMap, config); templateCache.add(fullKey, tmpl); return tmpl; @@ -52,7 +52,7 @@ class TemplateLayout extends TemplateContent { return { key: this.dataKeyLayoutPath, template: this, - frontMatterData: await this.getFrontMatterData() + frontMatterData: await this.getFrontMatterData(), }; } diff --git a/src/TemplateLayoutPathResolver.js b/src/TemplateLayoutPathResolver.js index 767b20921..2af7e5af6 100644 --- a/src/TemplateLayoutPathResolver.js +++ b/src/TemplateLayoutPathResolver.js @@ -1,11 +1,15 @@ const fs = require("fs-extra"); -const config = require("./Config"); const TemplatePath = require("./TemplatePath"); // const debug = require("debug")("Eleventy:TemplateLayoutPathResolver"); class TemplateLayoutPathResolver { - constructor(path, inputDir, extensionMap) { - this._config = config.getConfig(); + constructor(path, inputDir, extensionMap, config) { + if (!config) { + throw new Error( + "Expected `config` in TemplateLayoutPathResolver constructor" + ); + } + this._config = config; this.inputDir = inputDir; this.originalPath = path; this.path = path; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 78ef10582..8b6f90f88 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -5,9 +5,11 @@ const EleventyErrorUtil = require("./EleventyErrorUtil"); const UsingCircularTemplateContentReferenceError = require("./Errors/UsingCircularTemplateContentReferenceError"); const debug = require("debug")("Eleventy:TemplateMap"); const debugDev = require("debug")("Dev:Eleventy:TemplateMap"); -const config = require("./Config"); const EleventyBaseError = require("./EleventyBaseError"); + +class TemplateMapConfigError extends EleventyBaseError {} + class DuplicatePermalinkOutputError extends EleventyBaseError { get removeDuplicateErrorStringFromOutput() { return true; @@ -15,7 +17,11 @@ class DuplicatePermalinkOutputError extends EleventyBaseError { } class TemplateMap { - constructor() { + constructor(eleventyConfig) { + if (!eleventyConfig) { + throw new TemplateMapConfigError("Missing config argument."); + } + this.eleventyConfig = eleventyConfig; this.map = []; this.collectionsData = null; this.cached = false; @@ -30,7 +36,8 @@ class TemplateMap { get userConfig() { if (!this._userConfig) { - this._userConfig = config.userConfig; + this.config = this.eleventyConfig.getConfig(); + this._userConfig = this.eleventyConfig.userConfig; } return this._userConfig; diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index aa4a52ff5..868387301 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -29,8 +29,7 @@ class TemplatePassthroughManager { get extensionMap() { if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(); - this._extensionMap.config = this.config; + this._extensionMap = new EleventyExtensionMap([], this.config); } return this._extensionMap; } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 8a9718777..607300ae8 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -8,11 +8,11 @@ const EleventyErrorHandler = require("./EleventyErrorHandler"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const ConsoleLogger = require("./Util/ConsoleLogger"); -const config = require("./Config"); const lodashFlatten = require("lodash/flatten"); const debug = require("debug")("Eleventy:TemplateWriter"); const debugDev = require("debug")("Dev:Eleventy:TemplateWriter"); +class TemplateWriterError extends EleventyBaseError {} class TemplateWriterWriteError extends EleventyBaseError {} class TemplateWriter { @@ -21,10 +21,14 @@ class TemplateWriter { outputDir, templateFormats, // TODO remove this, see `get eleventyFiles` first templateData, - isPassthroughAll + eleventyConfig ) { - this.config = config.getConfig(); - this.userConfig = config.userConfig; + if (!eleventyConfig) { + throw new TemplateWriterError("Missing config argument."); + } + this.eleventyConfig = eleventyConfig; + this.config = eleventyConfig.getConfig(); + this.userConfig = eleventyConfig.userConfig; this.input = inputPath; this.inputDir = TemplatePath.getDir(inputPath); @@ -39,13 +43,11 @@ class TemplateWriter { this.writeCount = 0; this.skippedCount = 0; - // TODO can we get rid of this? It’s only used for tests in `get eleventyFiles`` - this.passthroughAll = isPassthroughAll; - this._templatePathCache = new Map(); } - /* Overrides this.input and this.inputDir */ + /* Overrides this.input and this.inputDir + * Useful when input is a file and inputDir is not its direct parent */ setInput(inputDir, input) { this.inputDir = inputDir; this.input = input; @@ -106,8 +108,10 @@ class TemplateWriter { get extensionMap() { if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(this.templateFormats); - this._extensionMap.config = this.config; + this._extensionMap = new EleventyExtensionMap( + this.templateFormats, + this.eleventyConfig + ); } return this._extensionMap; } @@ -128,7 +132,7 @@ class TemplateWriter { this.inputDir, this.outputDir, this.templateFormats, - this.passthroughAll + this.eleventyConfig ); this._eleventyFiles.setInput(this.inputDir, this.input); @@ -157,8 +161,10 @@ class TemplateWriter { this.inputDir, this.outputDir, this.templateData, - this.extensionMap + this.extensionMap, + this.config ); + tmpl.logger = this.logger; this._templatePathCache.set(path, tmpl); @@ -210,8 +216,7 @@ class TemplateWriter { } async _createTemplateMap(paths) { - this.templateMap = new TemplateMap(); - this.templateMap.userConfig = this.userConfig; + this.templateMap = new TemplateMap(this.eleventyConfig); await this._addToTemplateMap(paths); await this.templateMap.cache(); diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index 9640f911b..66236c722 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -1,48 +1,54 @@ const test = require("ava"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const TemplateConfig = require("../src/TemplateConfig"); + +function getExtensionMap(formats, config = new TemplateConfig()) { + let map = new EleventyExtensionMap(formats, config); + return map; +} test("Empty formats", (t) => { - let map = new EleventyExtensionMap([]); + let map = getExtensionMap([]); t.deepEqual(map.getGlobs("."), []); }); test("Single format", (t) => { - let map = new EleventyExtensionMap(["pug"]); + let map = getExtensionMap(["pug"]); t.deepEqual(map.getGlobs("."), ["./**/*.pug"]); t.deepEqual(map.getGlobs("src"), ["./src/**/*.pug"]); }); test("Multiple formats", (t) => { - let map = new EleventyExtensionMap(["njk", "pug"]); + let map = getExtensionMap(["njk", "pug"]); t.deepEqual(map.getGlobs("."), ["./**/*.njk", "./**/*.pug"]); t.deepEqual(map.getGlobs("src"), ["./src/**/*.njk", "./src/**/*.pug"]); }); test("Invalid keys are filtered (using passthrough copy)", (t) => { - let map = new EleventyExtensionMap(["lksdjfjlsk"]); + let map = getExtensionMap(["lksdjfjlsk"]); t.deepEqual(map.getGlobs("."), ["./**/*.lksdjfjlsk"]); }); test("Keys are mapped to lower case", (t) => { - let map = new EleventyExtensionMap(["PUG", "NJK"]); + let map = getExtensionMap(["PUG", "NJK"]); t.deepEqual(map.getGlobs("."), ["./**/*.pug", "./**/*.njk"]); }); test("Pruned globs", (t) => { - let map = new EleventyExtensionMap(["pug", "njk", "png"]); + let map = getExtensionMap(["pug", "njk", "png"]); t.deepEqual(map.getPassthroughCopyGlobs("."), ["./**/*.png"]); }); test("Empty path for fileList", (t) => { - let map = new EleventyExtensionMap(["njk", "pug"]); + let map = getExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList(), []); }); test("fileList", (t) => { - let map = new EleventyExtensionMap(["njk", "pug"]); + let map = getExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("filename"), ["filename.njk", "filename.pug"]); }); test("fileList with dir", (t) => { - let map = new EleventyExtensionMap(["njk", "pug"]); + let map = getExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("filename", "_includes"), [ "_includes/filename.njk", "_includes/filename.pug", @@ -50,7 +56,7 @@ test("fileList with dir", (t) => { }); test("fileList with dir in path", (t) => { - let map = new EleventyExtensionMap(["njk", "pug"]); + let map = getExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("layouts/filename"), [ "layouts/filename.njk", "layouts/filename.pug", @@ -58,7 +64,7 @@ test("fileList with dir in path", (t) => { }); test("fileList with dir in path and dir", (t) => { - let map = new EleventyExtensionMap(["njk", "pug"]); + let map = getExtensionMap(["njk", "pug"]); t.deepEqual(map.getFileList("layouts/filename", "_includes"), [ "_includes/layouts/filename.njk", "_includes/layouts/filename.pug", @@ -66,7 +72,7 @@ test("fileList with dir in path and dir", (t) => { }); test("removeTemplateExtension", (t) => { - let map = new EleventyExtensionMap(["njk", "11ty.js"]); + let map = getExtensionMap(["njk", "11ty.js"]); t.is(map.removeTemplateExtension("component.njk"), "component"); t.is(map.removeTemplateExtension("component.11ty.js"), "component"); @@ -76,13 +82,7 @@ test("removeTemplateExtension", (t) => { }); test("hasEngine", (t) => { - let map = new EleventyExtensionMap([ - "liquid", - "njk", - "11ty.js", - "ejs", - "pug", - ]); + let map = getExtensionMap(["liquid", "njk", "11ty.js", "ejs", "pug"]); t.true(map.hasEngine("default.ejs")); t.is(map.getKey("default.ejs"), "ejs"); t.falsy(map.getKey()); @@ -100,7 +100,7 @@ test("hasEngine", (t) => { }); test("hasEngine no formats passed in", (t) => { - let map = new EleventyExtensionMap([]); + let map = getExtensionMap([]); t.true(map.hasEngine("default.ejs")); t.is(map.getKey("default.ejs"), "ejs"); t.falsy(map.getKey()); @@ -119,7 +119,7 @@ test("hasEngine no formats passed in", (t) => { }); test("getKey", (t) => { - let map = new EleventyExtensionMap(["njk", "11ty.js", "md"]); + let map = getExtensionMap(["njk", "11ty.js", "md"]); t.is(map.getKey("component.njk"), "njk"); t.is(map.getKey("component.11ty.js"), "11ty.js"); t.is(map.getKey("11ty.js"), "11ty.js"); @@ -134,7 +134,7 @@ test("getKey", (t) => { }); test("isFullTemplateFilename (not a passthrough copy extension)", (t) => { - let map = new EleventyExtensionMap([ + let map = getExtensionMap([ "liquid", "njk", "11ty.js", diff --git a/test/PaginationTest.js b/test/PaginationTest.js index 0d36ab94c..bd17093f5 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -1,16 +1,22 @@ const test = require("ava"); -const Template = require("../src/Template"); const TemplateData = require("../src/TemplateData"); const Pagination = require("../src/Plugins/Pagination"); +const TemplateConfig = require("../src/TemplateConfig"); + +const getNewTemplate = require("./_getNewTemplateForTests"); test("No data passed to pagination", async (t) => { - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tmpl = getNewTemplate( "./test/stubs/paged/notpaged.njk", "./test/stubs/", - "./dist" + "./dist", + null, + null, + eleventyConfig ); - let paging = new Pagination(); + let paging = new Pagination({}, tmpl.config); paging.setTemplate(tmpl); t.is(paging.pagedItems.length, 0); @@ -18,14 +24,18 @@ test("No data passed to pagination", async (t) => { }); test("No pagination", async (t) => { - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tmpl = getNewTemplate( "./test/stubs/paged/notpaged.njk", "./test/stubs/", - "./dist" + "./dist", + null, + null, + eleventyConfig ); let data = await tmpl.getData(); - let paging = new Pagination(data); + let paging = new Pagination(data, tmpl.config); paging.setTemplate(tmpl); t.falsy(data.pagination); @@ -35,14 +45,18 @@ test("No pagination", async (t) => { }); test("Pagination enabled in frontmatter", async (t) => { - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tmpl = getNewTemplate( "./test/stubs/paged/pagedresolve.njk", "./test/stubs/", - "./dist" + "./dist", + null, + null, + eleventyConfig ); let data = await tmpl.getData(); - let paging = new Pagination(data); + let paging = new Pagination(data, tmpl.config); paging.setTemplate(tmpl); t.truthy(data.testdata); @@ -55,14 +69,18 @@ test("Pagination enabled in frontmatter", async (t) => { }); test("Resolve paged data in frontmatter", async (t) => { - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tmpl = getNewTemplate( "./test/stubs/paged/pagedresolve.njk", "./test/stubs/", - "./dist" + "./dist", + null, + null, + eleventyConfig ); let data = await tmpl.getData(); - let paging = new Pagination(data); + let paging = new Pagination(data, tmpl.config); paging.setTemplate(tmpl); t.is(paging._resolveItems().length, 8); t.is(paging.getPageCount(), 2); @@ -70,10 +88,14 @@ test("Resolve paged data in frontmatter", async (t) => { }); test("Paginate data in frontmatter", async (t) => { - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tmpl = getNewTemplate( "./test/stubs/paged/pagedinlinedata.njk", "./test/stubs/", - "./dist" + "./dist", + null, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -94,14 +116,17 @@ test("Paginate data in frontmatter", async (t) => { }); test("Paginate external data file", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/paged.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -133,7 +158,7 @@ test("Slugify test", (t) => { }); test("Permalink with pagination variables", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalink.njk", "./test/stubs/", "./dist" @@ -147,7 +172,7 @@ test("Permalink with pagination variables", async (t) => { }); test("Permalink with pagination variables (numeric)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinknumeric.njk", "./test/stubs/", "./dist" @@ -178,7 +203,7 @@ test("Permalink with pagination variables (numeric)", async (t) => { }); test("Permalink with pagination variables (numeric, one indexed)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinknumericoneindexed.njk", "./test/stubs/", "./dist" @@ -205,7 +230,7 @@ test("Permalink with pagination variables (numeric, one indexed)", async (t) => }); test("Permalink first and last page link with pagination variables (numeric)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinknumeric.njk", "./test/stubs/", "./dist" @@ -222,7 +247,7 @@ test("Permalink first and last page link with pagination variables (numeric)", a }); test("Permalink first and last page link with pagination variables (numeric, one indexed)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinknumericoneindexed.njk", "./test/stubs/", "./dist" @@ -239,7 +264,7 @@ test("Permalink first and last page link with pagination variables (numeric, one }); test("Alias to page data", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedalias.njk", "./test/stubs/", "./dist" @@ -256,7 +281,7 @@ test("Alias to page data", async (t) => { }); test("Alias to page data (size 2)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedaliassize2.njk", "./test/stubs/", "./dist" @@ -273,7 +298,7 @@ test("Alias to page data (size 2)", async (t) => { }); test("Permalink with pagination variables (and an if statement, nunjucks)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", "./dist" @@ -287,7 +312,7 @@ test("Permalink with pagination variables (and an if statement, nunjucks)", asyn }); test("Permalink with pagination variables (and an if statement, liquid)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinkif.liquid", "./test/stubs/", "./dist" @@ -301,7 +326,7 @@ test("Permalink with pagination variables (and an if statement, liquid)", async }); test("Template with Pagination, getRenderedTemplates", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", "./dist" @@ -316,14 +341,17 @@ test("Template with Pagination, getRenderedTemplates", async (t) => { }); test("Issue 135", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/issue-135/template.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -341,7 +369,7 @@ test("Issue 135", async (t) => { }); test("Template with Pagination, getTemplates has page variables set", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", "./dist" @@ -357,7 +385,7 @@ test("Template with Pagination, getTemplates has page variables set", async (t) }); test("Template with Pagination, getRenderedTemplates has page variables set", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedpermalinkif.njk", "./test/stubs/", "./dist" @@ -373,7 +401,7 @@ test("Template with Pagination, getRenderedTemplates has page variables set", as }); test("Page over an object (use keys)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedobject.njk", "./test/stubs/", "./dist" @@ -397,7 +425,7 @@ test("Page over an object (use keys)", async (t) => { }); test("Page over an object (use values)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedobjectvalues.njk", "./test/stubs/", "./dist" @@ -421,7 +449,7 @@ test("Page over an object (use values)", async (t) => { }); test("Page over an object (filtered, array)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedobjectfilterarray.njk", "./test/stubs/", "./dist" @@ -442,7 +470,7 @@ test("Page over an object (filtered, array)", async (t) => { }); test("Page over an object (filtered, string)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedobjectfilterstring.njk", "./test/stubs/", "./dist" @@ -464,17 +492,17 @@ test("Page over an object (filtered, string)", async (t) => { }); test("Pagination with deep data merge #147", async (t) => { - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tmpl = getNewTemplate( "./test/stubs/paged/pagedinlinedata.njk", "./test/stubs/", - "./dist" + "./dist", + null, + null, + eleventyConfig ); - tmpl.config = { - keys: { - layout: "layout", - }, - dataDeepMerge: true, - }; + tmpl.config.keys.layout = "layout"; + tmpl.config.deepDataMerge = true; let data = await tmpl.getData(); let pages = await tmpl.getTemplates(data); @@ -494,7 +522,7 @@ test("Pagination with deep data merge #147", async (t) => { }); test("Pagination with deep data merge with alias #147", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedalias.njk", "./test/stubs/", "./dist" @@ -519,7 +547,7 @@ test("Pagination with deep data merge with alias #147", async (t) => { }); test("Paginate data in frontmatter (reversed)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedinlinedata-reverse.njk", "./test/stubs/", "./dist" @@ -546,23 +574,50 @@ test("Paginate data in frontmatter (reversed)", async (t) => { }); test("No circular dependency (does not throw)", (t) => { - new Pagination({ - collections: { - tag1: [], - }, - pagination: { - data: "collections.tag1", - size: 1, + let eleventyConfig = new TemplateConfig(); + + new Pagination( + { + collections: { + tag1: [], + }, + pagination: { + data: "collections.tag1", + size: 1, + }, + tags: ["tag2"], }, - tags: ["tag2"], - }); + eleventyConfig + ); t.true(true); }); test("Circular dependency (pagination iterates over tag1 but also supplies pages to tag1)", (t) => { t.throws(() => { - new Pagination({ + let eleventyConfig = new TemplateConfig(); + new Pagination( + { + collections: { + tag1: [], + tag2: [], + }, + pagination: { + data: "collections.tag1", + size: 1, + }, + tags: ["tag1"], + }, + eleventyConfig + ); + }); +}); + +test("Circular dependency but should not error because it uses eleventyExcludeFromCollections", (t) => { + let eleventyConfig = new TemplateConfig(); + new Pagination( + { + eleventyExcludeFromCollections: true, collections: { tag1: [], tag2: [], @@ -572,29 +627,15 @@ test("Circular dependency (pagination iterates over tag1 but also supplies pages size: 1, }, tags: ["tag1"], - }); - }); -}); - -test("Circular dependency but should not error because it uses eleventyExcludeFromCollections", (t) => { - new Pagination({ - eleventyExcludeFromCollections: true, - collections: { - tag1: [], - tag2: [], - }, - pagination: { - data: "collections.tag1", - size: 1, }, - tags: ["tag1"], - }); + eleventyConfig + ); t.true(true); }); test("Pagination `before` Callback", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/paged-before.njk", "./test/stubs/", "./dist" @@ -607,7 +648,7 @@ test("Pagination `before` Callback", async (t) => { }); test("Pagination `before` Callback with a Filter", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/paged-before-filter.njk", "./test/stubs/", "./dist" @@ -620,7 +661,7 @@ test("Pagination `before` Callback with a Filter", async (t) => { }); test("Pagination `before` Callback with `reverse: true` (test order of operations)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/paged-before-and-reverse.njk", "./test/stubs/", "./dist" @@ -632,14 +673,17 @@ test("Pagination `before` Callback with `reverse: true` (test order of operation }); test("Pagination new v0.10.0 href/hrefs", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/paged.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -658,14 +702,17 @@ test("Pagination new v0.10.0 href/hrefs", async (t) => { }); test("Pagination new v0.10.0 page/pages", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/paged.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -689,7 +736,7 @@ test("Pagination new v0.10.0 page/pages", async (t) => { }); test("Pagination new v0.10.0 alias", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedalias.njk", "./test/stubs/", "./dist" @@ -703,7 +750,7 @@ test("Pagination new v0.10.0 alias", async (t) => { }); test("Pagination make sure pageNumber is numeric for {{ pageNumber + 1 }} Issue #760", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/paged/pagedinlinedata.njk", "./test/stubs/", "./dist" diff --git a/test/TemplateCacheTest.js b/test/TemplateCacheTest.js index 5b0e603a8..61ef30465 100644 --- a/test/TemplateCacheTest.js +++ b/test/TemplateCacheTest.js @@ -2,10 +2,12 @@ const test = require("ava"); const Template = require("../src/Template"); const templateCache = require("../src/TemplateCache"); +const getNewTemplate = require("./_getNewTemplateForTests"); + test("Cache can save templates", (t) => { templateCache.clear(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -18,7 +20,7 @@ test("Cache can save templates", (t) => { test("TemplateCache clear", (t) => { templateCache.clear(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -33,7 +35,7 @@ test("TemplateCache clear", (t) => { test("TemplateCache has", (t) => { templateCache.clear(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -46,7 +48,7 @@ test("TemplateCache has", (t) => { test("TemplateCache get success", (t) => { templateCache.clear(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" @@ -59,7 +61,7 @@ test("TemplateCache get success", (t) => { test("TemplateCache get fail", (t) => { templateCache.clear(); - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/template.ejs", "./test/stubs/", "./dist" diff --git a/test/TemplateCollectionTest.js b/test/TemplateCollectionTest.js index 60f141060..52a5e8efd 100644 --- a/test/TemplateCollectionTest.js +++ b/test/TemplateCollectionTest.js @@ -1,46 +1,41 @@ const test = require("ava"); const multimatch = require("multimatch"); const Template = require("../src/Template"); +const TemplateConfig = require("../src/TemplateConfig"); const Collection = require("../src/TemplateCollection"); const Sortable = require("../src/Util/Sortable"); +const getNewTemplateForTests = require("../test/_getNewTemplateForTests"); + +function getNewTemplate(filename, input, output, eleventyConfig) { + return getNewTemplateForTests( + filename, + input, + output, + null, + null, + eleventyConfig + ); +} + +function getNewTemplateByNumber(num, eleventyConfig) { + let extensions = ["md", "md", "md", "md", "md", "html", "njk"]; -let tmpl1 = new Template( - "./test/stubs/collection/test1.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl2 = new Template( - "./test/stubs/collection/test2.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl3 = new Template( - "./test/stubs/collection/test3.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl4 = new Template( - "./test/stubs/collection/test4.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl5 = new Template( - "./test/stubs/collection/test5.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl6 = new Template( - "./test/stubs/collection/test6.html", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl7 = new Template( - "./test/stubs/collection/test7.njk", - "./test/stubs/", - "./test/stubs/_site" -); + return getNewTemplateForTests( + `./test/stubs/collection/test${num}.${extensions[num - 1]}`, + "./test/stubs/", + "./test/stubs/_site", + null, + null, + eleventyConfig + ); +} test("Basic setup", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl3 = getNewTemplateByNumber(3, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl2); @@ -50,6 +45,11 @@ test("Basic setup", async (t) => { }); test("sortFunctionDateInputPath", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + let tmpl5 = getNewTemplateByNumber(5, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl4); @@ -63,6 +63,11 @@ test("sortFunctionDateInputPath", async (t) => { }); test("getFilteredByTag", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl3 = getNewTemplateByNumber(3, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl2); @@ -84,6 +89,11 @@ test("getFilteredByTag", async (t) => { }); test("getFilteredByTag (added out of order, sorted)", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl3 = getNewTemplateByNumber(3, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl3); await c._testAddTemplate(tmpl2); @@ -106,6 +116,11 @@ test("getFilteredByTag (added out of order, sorted)", async (t) => { }); test("getFilteredByTags", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl3 = getNewTemplateByNumber(3, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl2); @@ -126,6 +141,11 @@ test("getFilteredByTags", async (t) => { }); test("getFilteredByTags (added out of order, sorted)", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl3 = getNewTemplateByNumber(3, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl3); await c._testAddTemplate(tmpl2); @@ -149,6 +169,11 @@ test("getFilteredByTags (added out of order, sorted)", async (t) => { }); test("getFilteredByGlob", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl6 = getNewTemplateByNumber(6, eleventyConfig); + let tmpl7 = getNewTemplateByNumber(7, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl6); @@ -160,6 +185,11 @@ test("getFilteredByGlob", async (t) => { }); test("getFilteredByGlob no dash dot", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl6 = getNewTemplateByNumber(6, eleventyConfig); + let tmpl7 = getNewTemplateByNumber(7, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl6); @@ -176,15 +206,19 @@ test("getFilteredByGlob no dash dot", async (t) => { }); test("partial match on tag string, issue 95", async (t) => { - let cat = new Template( + let eleventyConfig = new TemplateConfig(); + + let cat = getNewTemplate( "./test/stubs/issue-95/cat.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let notacat = new Template( + let notacat = getNewTemplate( "./test/stubs/issue-95/notacat.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); let c = new Collection(); @@ -227,6 +261,11 @@ test("multimatch assumptions, issue #127", async (t) => { }); test("Sort in place (issue #352)", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + let tmpl5 = getNewTemplateByNumber(5, eleventyConfig); + let c = new Collection(); await c._testAddTemplate(tmpl1); await c._testAddTemplate(tmpl4); diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index bcfc4d4ed..671444682 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -1,18 +1,20 @@ const test = require("ava"); const TemplateData = require("../src/TemplateData"); -const templateConfig = require("../src/Config"); - -const config = templateConfig.getConfig(); +const TemplateConfig = require("../src/TemplateConfig"); test("Create", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let config = eleventyConfig.getConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let data = await dataObj.getData(); t.true(Object.keys(data[config.keys.package]).length > 0); }); test("getData()", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let config = eleventyConfig.getConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); dataObj.setDataTemplateEngine("liquid"); t.is(dataObj.getData().toString(), "[object Promise]"); @@ -32,7 +34,8 @@ test("getData()", async (t) => { }); test("getData() use default processing (false)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let data = await dataObj.getData(); t.is( data.globalData.datakey2, @@ -49,7 +52,8 @@ test("Data dir does not exist", async (t) => { }); test("Add local data", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); dataObj.setDataTemplateEngine("liquid"); let data = await dataObj.getData(); @@ -72,7 +76,8 @@ test("Add local data", async (t) => { }); test("Get local data async JS", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let withLocalData = await dataObj.getLocalData( "./test/stubs/component-async/component.njk" @@ -84,7 +89,8 @@ test("Get local data async JS", async (t) => { }); test("addLocalData() doesn’t exist but doesn’t fail (template file does exist)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); dataObj.setDataTemplateEngine("liquid"); let data = await dataObj.getData(); @@ -100,7 +106,8 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does exis }); test("addLocalData() doesn’t exist but doesn’t fail (template file does not exist)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); dataObj.setDataTemplateEngine("liquid"); let data = await dataObj.getData(); @@ -115,7 +122,8 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does not }); test("Global Dir Directory", async (t) => { - let dataObj = new TemplateData("./"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./", eleventyConfig); t.deepEqual(await dataObj.getGlobalDataGlob(), [ "./_data/**/*.(json|cjs|js)", @@ -123,7 +131,8 @@ test("Global Dir Directory", async (t) => { }); test("Global Dir Directory with Constructor Path Arg", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); t.deepEqual(await dataObj.getGlobalDataGlob(), [ "./test/stubs/_data/**/*.(json|cjs|js)", @@ -131,7 +140,8 @@ test("Global Dir Directory with Constructor Path Arg", async (t) => { }); test("getAllGlobalData() with other data files", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); @@ -155,7 +165,8 @@ test("getAllGlobalData() with other data files", async (t) => { }); test("getAllGlobalData() with js object data file", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); @@ -170,7 +181,8 @@ test("getAllGlobalData() with js object data file", async (t) => { }); test("getAllGlobalData() with js function data file", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); @@ -185,7 +197,8 @@ test("getAllGlobalData() with js function data file", async (t) => { }); test("getAllGlobalData() with config globalData", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); dataObj._setConfig({ ...dataObj.config, @@ -208,7 +221,8 @@ test("getAllGlobalData() with config globalData", async (t) => { }); test("getAllGlobalData() with common js function data file", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let data = await dataObj.cacheData(); let dataFilePaths = await dataObj.getGlobalDataFiles(); @@ -223,7 +237,8 @@ test("getAllGlobalData() with common js function data file", async (t) => { }); test("getDataValue() without a dataTemplateEngine", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); dataObj.setDataTemplateEngine(false); let data = await dataObj.getDataValue("./test/stubs/_data/testDataEjs.json", { @@ -237,7 +252,8 @@ test("getDataValue() without a dataTemplateEngine", async (t) => { }); test("getDataValue() without dataTemplateEngine changed to `ejs`", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); dataObj.setDataTemplateEngine("ejs"); let data = await dataObj.getDataValue("./test/stubs/_data/testDataEjs.json", { @@ -251,7 +267,8 @@ test("getDataValue() without dataTemplateEngine changed to `ejs`", async (t) => }); test("getLocalDataPaths", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" ); @@ -269,7 +286,8 @@ test("getLocalDataPaths", async (t) => { }); test("Deeper getLocalDataPaths", async (t) => { - let dataObj = new TemplateData("./"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./", eleventyConfig); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" ); @@ -291,7 +309,8 @@ test("Deeper getLocalDataPaths", async (t) => { }); test("getLocalDataPaths with an 11ty js template", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.11ty.js" ); @@ -309,7 +328,8 @@ test("getLocalDataPaths with an 11ty js template", async (t) => { }); test("getLocalDataPaths with inputDir passed in (trailing slash)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" ); @@ -327,7 +347,8 @@ test("getLocalDataPaths with inputDir passed in (trailing slash)", async (t) => }); test("getLocalDataPaths with inputDir passed in (no trailing slash)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" ); @@ -345,7 +366,8 @@ test("getLocalDataPaths with inputDir passed in (no trailing slash)", async (t) }); test("getLocalDataPaths with inputDir passed in (no leading slash)", async (t) => { - let dataObj = new TemplateData("test/stubs"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("test/stubs", eleventyConfig); let paths = await dataObj.getLocalDataPaths( "./test/stubs/component/component.liquid" ); @@ -363,14 +385,16 @@ test("getLocalDataPaths with inputDir passed in (no leading slash)", async (t) = }); test("getRawImports", async (t) => { - let dataObj = new TemplateData("test/stubs"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("test/stubs", eleventyConfig); let data = dataObj.getRawImports(); t.is(data.pkg.name, "@11ty/eleventy"); }); test("getTemplateDataFileGlob", async (t) => { - let tw = new TemplateData("test/stubs"); + let eleventyConfig = new TemplateConfig(); + let tw = new TemplateData("test/stubs", eleventyConfig); t.deepEqual(await tw.getTemplateDataFileGlob(), [ "./test/stubs/**/*.json", @@ -405,7 +429,8 @@ test("TemplateData.cleanupData", (t) => { }); test("Parent directory for data (Issue #337)", async (t) => { - let dataObj = new TemplateData("./test/stubs-337/src/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs-337/src/", eleventyConfig); dataObj._setConfig({ dataTemplateEngine: false, dir: { diff --git a/test/TemplateFileSlugTest.js b/test/TemplateFileSlugTest.js index 0db1dd3da..e4bdad43f 100644 --- a/test/TemplateFileSlugTest.js +++ b/test/TemplateFileSlugTest.js @@ -1,9 +1,11 @@ const test = require("ava"); const TemplateFileSlug = require("../src/TemplateFileSlug"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const TemplateConfig = require("../src/TemplateConfig"); function getNewSlugInstance(path, inputDir) { - let extensionMap = new EleventyExtensionMap(); + let eleventyConfig = new TemplateConfig(); + let extensionMap = new EleventyExtensionMap([], eleventyConfig); let fs = new TemplateFileSlug(path, inputDir, extensionMap); return fs; } diff --git a/test/TemplateLayoutPathResolverTest.js b/test/TemplateLayoutPathResolverTest.js index c85937612..54e5709a7 100644 --- a/test/TemplateLayoutPathResolverTest.js +++ b/test/TemplateLayoutPathResolverTest.js @@ -1,23 +1,33 @@ const test = require("ava"); +const TemplateConfig = require("../src/TemplateConfig"); const TemplateLayoutPathResolver = require("../src/TemplateLayoutPathResolver"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getResolverInstance(path, inputDir, map) { + let eleventyConfig = new TemplateConfig(); if (!map) { - map = new EleventyExtensionMap([ - "liquid", - "ejs", - "md", - "hbs", - "mustache", - "haml", - "pug", - "njk", - "html", - "11ty.js", - ]); + map = new EleventyExtensionMap( + [ + "liquid", + "ejs", + "md", + "hbs", + "mustache", + "haml", + "pug", + "njk", + "html", + "11ty.js", + ], + eleventyConfig + ); } - return new TemplateLayoutPathResolver(path, inputDir, map); + return new TemplateLayoutPathResolver( + path, + inputDir, + map, + eleventyConfig.getConfig() + ); } test("Layout", (t) => { diff --git a/test/TemplateLayoutTest.js b/test/TemplateLayoutTest.js index 1c056fd0e..0f5bb2887 100644 --- a/test/TemplateLayoutTest.js +++ b/test/TemplateLayoutTest.js @@ -1,23 +1,33 @@ const test = require("ava"); +const TemplateConfig = require("../src/TemplateConfig"); const TemplateLayout = require("../src/TemplateLayout"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getTemplateLayoutInstance(key, inputDir, map) { + let eleventyConfig = new TemplateConfig(); if (!map) { - map = new EleventyExtensionMap([ - "liquid", - "ejs", - "md", - "hbs", - "mustache", - "haml", - "pug", - "njk", - "html", - "11ty.js", - ]); + map = new EleventyExtensionMap( + [ + "liquid", + "ejs", + "md", + "hbs", + "mustache", + "haml", + "pug", + "njk", + "html", + "11ty.js", + ], + eleventyConfig + ); } - let layout = new TemplateLayout(key, inputDir, map); + let layout = new TemplateLayout( + key, + inputDir, + map, + eleventyConfig.getConfig() + ); return layout; } diff --git a/test/TemplateMapTest-ComputedData.js b/test/TemplateMapTest-ComputedData.js index 5635f3aa5..d50cef928 100644 --- a/test/TemplateMapTest-ComputedData.js +++ b/test/TemplateMapTest-ComputedData.js @@ -1,28 +1,39 @@ const test = require("ava"); -const Template = require("../src/Template"); +const TemplateConfig = require("../src/TemplateConfig"); const TemplateData = require("../src/TemplateData"); const TemplateMap = require("../src/TemplateMap"); const getNewTemplate = require("./_getNewTemplateForTests"); test("Computed data can see tag generated collections", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); - let dataObj = new TemplateData("./test/stubs-computed-collections/"); + let dataObj = new TemplateData( + "./test/stubs-computed-collections/", + eleventyConfig + ); let tmpl = getNewTemplate( "./test/stubs-computed-collections/collections.njk", "./test/stubs-computed-collections/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); await tm.add(tmpl); - let dataObj2 = new TemplateData("./test/stubs-computed-collections/"); + let dataObj2 = new TemplateData( + "./test/stubs-computed-collections/", + eleventyConfig + ); let tmpl2 = getNewTemplate( "./test/stubs-computed-collections/dog.njk", "./test/stubs-computed-collections/", "./dist", - dataObj2 + dataObj2, + null, + eleventyConfig ); await tm.add(tmpl2); @@ -46,24 +57,35 @@ test("Computed data can see tag generated collections", async (t) => { }); test("Computed data can see paginated data, Issue #1138", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); - let dataObj = new TemplateData("./test/stubs-computed-pagination/"); + let dataObj = new TemplateData( + "./test/stubs-computed-pagination/", + eleventyConfig + ); let tmpl = getNewTemplate( "./test/stubs-computed-pagination/paginated.njk", "./test/stubs-computed-pagination/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); await tm.add(tmpl); - let dataObj2 = new TemplateData("./test/stubs-computed-pagination/"); + let dataObj2 = new TemplateData( + "./test/stubs-computed-pagination/", + eleventyConfig + ); let tmpl2 = getNewTemplate( "./test/stubs-computed-pagination/child.11ty.js", "./test/stubs-computed-pagination/", "./dist", - dataObj2 + dataObj2, + null, + eleventyConfig ); await tm.add(tmpl2); @@ -99,24 +121,35 @@ test("Computed data can see paginated data, Issue #1138", async (t) => { }); test("Computed data in directory data file consumes data file data, Issue #1137", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); - let dataObj = new TemplateData("./test/stubs-computed-dirdata/"); + let dataObj = new TemplateData( + "./test/stubs-computed-dirdata/", + eleventyConfig + ); let tmpl = getNewTemplate( "./test/stubs-computed-dirdata/dir/first.11ty.js", "./test/stubs-computed-dirdata/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); await tm.add(tmpl); - let dataObj2 = new TemplateData("./test/stubs-computed-dirdata/"); + let dataObj2 = new TemplateData( + "./test/stubs-computed-dirdata/", + eleventyConfig + ); let tmpl2 = getNewTemplate( "./test/stubs-computed-dirdata/dir/second.11ty.js", "./test/stubs-computed-dirdata/", "./dist", - dataObj2 + dataObj2, + null, + eleventyConfig ); await tm.add(tmpl2); @@ -131,24 +164,35 @@ test("Computed data in directory data file consumes data file data, Issue #1137" }); test("Computed data can filter collections (and other array methods)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); - let dataObj = new TemplateData("./test/stubs-computed-collections-filter/"); + let dataObj = new TemplateData( + "./test/stubs-computed-collections-filter/", + eleventyConfig + ); let tmpl = getNewTemplate( "./test/stubs-computed-collections-filter/collections.njk", "./test/stubs-computed-collections-filter/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); await tm.add(tmpl); - let dataObj2 = new TemplateData("./test/stubs-computed-collections-filter/"); + let dataObj2 = new TemplateData( + "./test/stubs-computed-collections-filter/", + eleventyConfig + ); let tmpl2 = getNewTemplate( "./test/stubs-computed-collections-filter/dog.njk", "./test/stubs-computed-collections-filter/", "./dist", - dataObj2 + dataObj2, + null, + eleventyConfig ); await tm.add(tmpl2); diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 762323464..224927499 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -1,33 +1,40 @@ const test = require("ava"); -const Template = require("../src/Template"); const TemplateMap = require("../src/TemplateMap"); const TemplateCollection = require("../src/TemplateCollection"); const UsingCircularTemplateContentReferenceError = require("../src/Errors/UsingCircularTemplateContentReferenceError"); const normalizeNewLines = require("./Util/normalizeNewLines"); +const TemplateConfig = require("../src/TemplateConfig"); -let tmpl1 = new Template( - "./test/stubs/templateMapCollection/test1.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl2 = new Template( - "./test/stubs/templateMapCollection/test2.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl4 = new Template( - "./test/stubs/templateMapCollection/test4.md", - "./test/stubs/", - "./test/stubs/_site" -); -let tmpl5 = new Template( - "./test/stubs/templateMapCollection/test5.md", - "./test/stubs/", - "./test/stubs/_site" -); +const getNewTemplateForTests = require("./_getNewTemplateForTests"); + +function getNewTemplate(filename, input, output, eleventyConfig) { + return getNewTemplateForTests( + filename, + input, + output, + null, + null, + eleventyConfig + ); +} + +function getNewTemplateByNumber(num, eleventyConfig) { + let extensions = ["md", "md", "md", "md", "md", "html", "njk"]; + + return getNewTemplate( + `./test/stubs/templateMapCollection/test${num}.md`, + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); +} test("TemplateMap has collections added", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); await tm.cache(); @@ -37,7 +44,10 @@ test("TemplateMap has collections added", async (t) => { }); test("TemplateMap compared to Collection API", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl4); await tm.cache(); @@ -59,7 +69,11 @@ test("TemplateMap compared to Collection API", async (t) => { }); test("populating the collection twice should clear the previous values (--watch was making it cumulative)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); @@ -70,7 +84,11 @@ test("populating the collection twice should clear the previous values (--watch }); test("TemplateMap adds collections data and has templateContent values", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); @@ -100,14 +118,11 @@ test("TemplateMap adds collections data and has templateContent values", async ( }); test("TemplateMap circular references (map without templateContent)", async (t) => { - let tm = new TemplateMap(); - await tm.add( - new Template( - "./test/stubs/templateMapCollection/test3.md", - "./test/stubs/", - "./test/stubs/_site" - ) - ); + let eleventyConfig = new TemplateConfig(); + let tmpl3 = getNewTemplateByNumber(3, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); + await tm.add(tmpl3); let map = tm.getMap(); t.falsy(map[0].data.collections); @@ -124,14 +139,15 @@ test("TemplateMap circular references (map without templateContent)", async (t) }); test("TemplateMap circular references (map.templateContent)", async (t) => { - let tm = new TemplateMap(); - await tm.add( - new Template( - "./test/stubs/templateMapCollection/templateContent.md", - "./test/stubs/", - "./test/stubs/_site" - ) + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/templateMapCollection/templateContent.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig ); + await tm.add(tmpl); let map = tm.getMap(); t.falsy(map[0].data.collections); @@ -147,23 +163,27 @@ test("TemplateMap circular references (map.templateContent)", async (t) => { }); test("Issue #115, mixing pagination and collections", async (t) => { - let tmplFoos = new Template( + let eleventyConfig = new TemplateConfig(); + let tmplFoos = getNewTemplate( "./test/stubs/issue-115/template-foos.liquid", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tmplBars = new Template( + let tmplBars = getNewTemplate( "./test/stubs/issue-115/template-bars.liquid", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tmplIndex = new Template( + let tmplIndex = getNewTemplate( "./test/stubs/issue-115/index.liquid", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tm = new TemplateMap(); + let tm = new TemplateMap(eleventyConfig); await tm.add(tmplFoos); await tm.add(tmplBars); await tm.add(tmplIndex); @@ -208,23 +228,27 @@ This page is bars }); test("Issue #115 with layout, mixing pagination and collections", async (t) => { - let tmplFoos = new Template( + let eleventyConfig = new TemplateConfig(); + let tmplFoos = getNewTemplate( "./test/stubs/issue-115/template-foos.liquid", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tmplBars = new Template( + let tmplBars = getNewTemplate( "./test/stubs/issue-115/template-bars.liquid", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tmplIndex = new Template( + let tmplIndex = getNewTemplate( "./test/stubs/issue-115/index-with-layout.liquid", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tm = new TemplateMap(); + let tm = new TemplateMap(eleventyConfig); await tm.add(tmplFoos); await tm.add(tmplBars); await tm.add(tmplIndex); @@ -269,7 +293,11 @@ This page is bars }); test("TemplateMap adds collections data and has page data values using .cache()", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); @@ -289,7 +317,11 @@ test("TemplateMap adds collections data and has page data values using .cache()" }); test("TemplateMap adds collections data and has page data values using ._testGetCollectionsData()", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); @@ -313,7 +345,11 @@ test("TemplateMap adds collections data and has page data values using ._testGet }); test("Url should be available in user config collections API calls", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); tm.setUserConfigCollections({ @@ -343,7 +379,8 @@ test("Url should be available in user config collections API calls", async (t) = }); test("Url should be available in user config collections API calls (test in callback)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); tm.setUserConfigCollections({ userCollection: function (collection) { let all = collection.getAll(); @@ -362,20 +399,27 @@ test("Url should be available in user config collections API calls (test in call }, }); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); await tm.cache(); }); test("Should be able to paginate a tag generated collection", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-tag.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -385,14 +429,19 @@ test("Should be able to paginate a tag generated collection", async (t) => { }); test("Should be able to paginate a user config collection", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-cfg.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -409,14 +458,19 @@ test("Should be able to paginate a user config collection", async (t) => { }); test("Should be able to paginate a user config collection (uses rendered permalink)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-cfg-permalink.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -444,15 +498,21 @@ test("Should be able to paginate a user config collection (uses rendered permali }); test("Should be able to paginate a user config collection (paged template is also tagged)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag await tm.add(tmpl4); // has dog tag - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-cfg-tagged.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -472,15 +532,21 @@ test("Should be able to paginate a user config collection (paged template is als }); test("Should be able to paginate a user config collection (paged template is also tagged, add all pages to collections)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag await tm.add(tmpl4); // has dog tag - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-cfg-tagged-apply-to-all.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -507,15 +573,21 @@ test("Should be able to paginate a user config collection (paged template is als }); test("Should be able to paginate a user config collection (paged template is also tagged, uses custom rendered permalink)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag await tm.add(tmpl4); // has dog tag - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-cfg-tagged-permalink.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -533,15 +605,21 @@ test("Should be able to paginate a user config collection (paged template is als }); test("Should be able to paginate a user config collection (paged template is also tagged, uses custom rendered permalink, add all pages to collections)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag await tm.add(tmpl4); // has dog tag - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-cfg-tagged-permalink-apply-to-all.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -560,11 +638,13 @@ test("Should be able to paginate a user config collection (paged template is als }); test("TemplateMap render and templateContent are the same (templateContent doesn’t have layout but makes proper use of layout front matter data)", async (t) => { - let tm = new TemplateMap(); - let tmplLayout = new Template( + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); + let tmplLayout = getNewTemplate( "./test/stubs/templateMapCollection/testWithLayout.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(tmplLayout); @@ -576,15 +656,21 @@ test("TemplateMap render and templateContent are the same (templateContent doesn }); test("Should be able to paginate a tag generated collection (and it has templateContent)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag await tm.add(tmpl4); // has dog tag - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-tag-dogs-templateContent.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -616,15 +702,21 @@ test("Should be able to paginate a tag generated collection (and it has template }); test("Should be able to paginate a tag generated collection when aliased (and it has templateContent)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); // has dog tag await tm.add(tmpl2); // does not have dog tag await tm.add(tmpl4); // has dog tag - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/templateMapCollection/paged-tag-dogs-templateContent-alias.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -650,15 +742,21 @@ test("Should be able to paginate a tag generated collection when aliased (and it }); test("Issue #253: Paginated template with a tag should put multiple pages into a collection", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + let tmpl4 = getNewTemplateByNumber(4, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); await tm.add(tmpl4); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/tagged-pagination-multiples/test.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -680,7 +778,8 @@ test("Issue #253: Paginated template with a tag should put multiple pages into a }); test("getUserConfigCollectionNames", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); tm.setUserConfigCollections({ userCollection: function (collection) { @@ -698,7 +797,8 @@ test("getUserConfigCollectionNames", async (t) => { }); test("isUserConfigCollectionName", (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); tm.setUserConfigCollections({ userCollection: function (collection) { return collection.getAll(); @@ -710,7 +810,11 @@ test("isUserConfigCollectionName", (t) => { }); test("Dependency Map should have nodes that have no dependencies and no dependents", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl5 = getNewTemplateByNumber(5, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl5); @@ -724,7 +828,11 @@ test("Dependency Map should have nodes that have no dependencies and no dependen }); test("Dependency Map should have include orphan user config collections (in the correct order)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl5 = getNewTemplateByNumber(5, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl5); @@ -750,11 +858,13 @@ test("Dependency Map should have include orphan user config collections (in the }); test("Template pages should not have layouts when added to collections", async (t) => { - let tm = new TemplateMap(); - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( "./test/stubs/collection-layout-wrap.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(tmpl); t.is(await tmpl.render(await tmpl.getData()), "
Layout Test
"); @@ -765,12 +875,14 @@ test("Template pages should not have layouts when added to collections", async ( }); test("Paginated template pages should not have layouts when added to collections", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/tagged-pagination-multiples-layout/test.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); await tm.add(pagedTmpl); @@ -783,13 +895,19 @@ test("Paginated template pages should not have layouts when added to collections }); test("Tag pages. Allow pagination over all collections a la `data: collections`", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/page-target-collections/tagpages.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); + await tm.add(pagedTmpl); await tm.add(tmpl1); await tm.add(tmpl2); @@ -810,13 +928,19 @@ test("Tag pages. Allow pagination over all collections a la `data: collections`" }); test("Tag pages (all pages added to collections). Allow pagination over all collections a la `data: collections`", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/page-target-collections/tagpagesall.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); + await tm.add(pagedTmpl); await tm.add(tmpl1); await tm.add(tmpl2); @@ -840,14 +964,19 @@ test("Tag pages (all pages added to collections). Allow pagination over all coll }); test("eleventyExcludeFromCollections", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); - let excludedTmpl = new Template( + let excludedTmpl = getNewTemplate( "./test/stubs/eleventyExcludeFromCollections.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); + await tm.add(excludedTmpl); await tm.cache(); @@ -861,13 +990,19 @@ test("eleventyExcludeFromCollections", async (t) => { }); test("Paginate over collections.all", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/page-target-collections/paginateall.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); + await tm.add(pagedTmpl); await tm.add(tmpl1); await tm.add(tmpl2); @@ -914,18 +1049,25 @@ test("Paginate over collections.all", async (t) => { }); test("Paginate over collections.all WITH a paginate over collections (tag pages)", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + let tmpl2 = getNewTemplateByNumber(2, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); - let pagedTmpl = new Template( + let pagedTmpl = getNewTemplate( "./test/stubs/page-target-collections/paginateall.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tagPagesTmpl = new Template( + let tagPagesTmpl = getNewTemplate( "./test/stubs/page-target-collections/tagpagesall.njk", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); + await tm.add(pagedTmpl); await tm.add(tagPagesTmpl); await tm.add(tmpl1); @@ -938,11 +1080,13 @@ test("Paginate over collections.all WITH a paginate over collections (tag pages) test("Test a transform with a layout (via templateMap)", async (t) => { t.plan(7); - let tm = new TemplateMap(); - let tmpl = new Template( + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( "./test/stubs-475/transform-layout/transform-layout.njk", "./test/stubs-475/", - "./test/stubs-475/_site" + "./test/stubs-475/_site", + eleventyConfig ); tmpl.addLinter(function (content, inputPath, outputPath) { @@ -974,7 +1118,10 @@ test("Test a transform with a layout (via templateMap)", async (t) => { }); test("Async user collection addCollection method", async (t) => { - let tm = new TemplateMap(); + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); tm.setUserConfigCollections({ userCollection: async function (collection) { @@ -993,18 +1140,22 @@ test("Async user collection addCollection method", async (t) => { }); test("Duplicate permalinks in template map", async (t) => { - let tmpl1 = new Template( + let eleventyConfig = new TemplateConfig(); + + let tmpl1 = getNewTemplate( "./test/stubs/permalink-conflicts/test1.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tmpl2 = new Template( + let tmpl2 = getNewTemplate( "./test/stubs/permalink-conflicts/test2.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tm = new TemplateMap(); + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); await t.throwsAsync(async () => { @@ -1013,18 +1164,22 @@ test("Duplicate permalinks in template map", async (t) => { }); test("No duplicate permalinks in template map, using false", async (t) => { - let tmpl1 = new Template( + let eleventyConfig = new TemplateConfig(); + + let tmpl1 = getNewTemplate( "./test/stubs/permalink-conflicts-false/test1.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tmpl2 = new Template( + let tmpl2 = getNewTemplate( "./test/stubs/permalink-conflicts-false/test2.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tm = new TemplateMap(); + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl2); await tm.cache(); @@ -1032,18 +1187,22 @@ test("No duplicate permalinks in template map, using false", async (t) => { }); test("Duplicate permalinks in template map, no leading slash", async (t) => { - let tmpl1 = new Template( + let eleventyConfig = new TemplateConfig(); + + let tmpl1 = getNewTemplate( "./test/stubs/permalink-conflicts/test1.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tmpl3 = new Template( + let tmpl3 = getNewTemplate( "./test/stubs/permalink-conflicts/test3.md", "./test/stubs/", - "./test/stubs/_site" + "./test/stubs/_site", + eleventyConfig ); - let tm = new TemplateMap(); + let tm = new TemplateMap(eleventyConfig); await tm.add(tmpl1); await tm.add(tmpl3); @@ -1053,22 +1212,25 @@ test("Duplicate permalinks in template map, no leading slash", async (t) => { }); test("TemplateMap circular references (map.templateContent) using eleventyExcludeFromCollections and collections.all", async (t) => { - let tm = new TemplateMap(); - await tm.add( - new Template( - "./test/stubs/issue-522/excluded.md", - "./test/stubs/", - "./test/stubs/_site" - ) - ); - - await tm.add( - new Template( - "./test/stubs/issue-522/template.md", - "./test/stubs/", - "./test/stubs/_site" - ) + let eleventyConfig = new TemplateConfig(); + + let tm = new TemplateMap(eleventyConfig); + let tmplExcluded = getNewTemplate( + "./test/stubs/issue-522/excluded.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig ); + await tm.add(tmplExcluded); + + let tmpl = getNewTemplate( + "./test/stubs/issue-522/template.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmpl); let map = tm.getMap(); t.falsy(map[0].data.collections); diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index a8ddd5dcd..43071dae6 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -1,21 +1,19 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); -const templateConfig = require("../src/Config"); +const TemplateConfig = require("../src/TemplateConfig"); const Vue = require("vue"); const renderer = require("vue-server-renderer").createRenderer(); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } test("Custom plaintext Render", async (t) => { let tr = getNewTemplateRender("txt"); - - const config = templateConfig.getConfig(); - tr.config = Object.assign({}, config); tr.config.extensionMap.add({ extension: "txt", key: "txt", @@ -35,8 +33,6 @@ test("Custom plaintext Render", async (t) => { test("Custom Vue Render", async (t) => { let tr = getNewTemplateRender("vue"); - const config = templateConfig.getConfig(); - tr.config = Object.assign({}, config); tr.config.extensionMap.add({ extension: "vue", key: "vue", @@ -60,8 +56,6 @@ test("Custom Sass Render", async (t) => { const sass = require("node-sass"); let tr = getNewTemplateRender("sass"); - const config = templateConfig.getConfig(); - tr.config = Object.assign({}, config); tr.config.extensionMap.add({ extension: "sass", key: "sass", diff --git a/test/TemplateRenderEJSTest.js b/test/TemplateRenderEJSTest.js index 7271432b6..80c3f1f50 100644 --- a/test/TemplateRenderEJSTest.js +++ b/test/TemplateRenderEJSTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderHTMLTest.js b/test/TemplateRenderHTMLTest.js index dd572370a..bb51663c6 100644 --- a/test/TemplateRenderHTMLTest.js +++ b/test/TemplateRenderHTMLTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderHamlTest.js b/test/TemplateRenderHamlTest.js index c32631e7d..2e30f402b 100644 --- a/test/TemplateRenderHamlTest.js +++ b/test/TemplateRenderHamlTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderHandlebarsTest.js b/test/TemplateRenderHandlebarsTest.js index 7c0ec53f8..75565e7fe 100644 --- a/test/TemplateRenderHandlebarsTest.js +++ b/test/TemplateRenderHandlebarsTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } @@ -313,7 +315,10 @@ test("Handlebars Render Raw Output (Issue #436 with if statement)", async (t) => }); test("Handlebars Render #each with Global Variable (Issue #759)", async (t) => { - let fn = await new TemplateRender("hbs", "./test/stubs/").getCompiledTemplate( + let fn = await getNewTemplateRender( + "hbs", + "./test/stubs/" + ).getCompiledTemplate( `` ); t.is( diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 7be793297..bf03de2f7 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } @@ -14,9 +16,9 @@ test("JS", (t) => { getNewTemplateRender("./test/stubs/filename.11ty.js").getEngineName(), "11ty.js" ); - t.is(new TemplateRender("11ty.cjs").getEngineName(), "11ty.js"); + t.is(getNewTemplateRender("11ty.cjs").getEngineName(), "11ty.js"); t.is( - new TemplateRender("./test/stubs/filename.11ty.cjs").getEngineName(), + getNewTemplateRender("./test/stubs/filename.11ty.cjs").getEngineName(), "11ty.js" ); }); @@ -213,7 +215,7 @@ test.skip("Issue #934: JS Render with an arrow function and javascript function" test("JS Render with a function and async filter", async (t) => { t.plan(4); - let tr = new TemplateRender("./test/stubs/function-async-filter.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/function-async-filter.11ty.js"); tr.config = { javascriptFunctions: { upper: function (val) { @@ -291,7 +293,7 @@ test("JS Class Async Render with a function", async (t) => { }); test("JS Class Async Render with a function (sync function, throws error)", async (t) => { - let tr = new TemplateRender("./test/stubs/function-throws.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/function-throws.11ty.js"); tr.config = { javascriptFunctions: { upper: function (val) { @@ -314,7 +316,7 @@ test("JS Class Async Render with a function (sync function, throws error)", asyn }); test("JS Class Async Render with a function (async function, throws error)", async (t) => { - let tr = new TemplateRender("./test/stubs/function-throws-async.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/function-throws-async.11ty.js"); tr.config = { javascriptFunctions: { upper: async function (val) { diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 9d74ece16..f76c3d7ce 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } @@ -22,21 +24,21 @@ test("Liquid", (t) => { }); test("Liquid Render Addition", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{ number | plus: 1 }}

" ); t.is(await fn({ number: 1 }), "

2

"); }); test("Liquid Render Raw", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{% raw %}{{name}}{% endraw %}

" ); t.is(await fn({ name: "tim" }), "

{{name}}

"); }); test("Liquid Render Raw Multiline", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( `

{% raw %} {{name}} {% endraw %}

` @@ -162,7 +164,7 @@ test("Liquid Custom Filter", async (t) => { }); test.skip("Liquid Async Filter", async (t) => { - let tr = new TemplateRender("liquid", "test/stubs"); + let tr = getNewTemplateRender("liquid", "test/stubs"); tr.engine.addFilter({ myAsyncFilter: function (value) { return new Promise((resolve, reject) => { @@ -293,7 +295,7 @@ test("Liquid Shortcode", async (t) => { test("Liquid Shortcode returns promise", async (t) => { t.plan(2); - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function (str) { // Data in context t.is(this.page.url, "/hi/"); @@ -319,7 +321,7 @@ test("Liquid Shortcode returns promise", async (t) => { test("Liquid Shortcode returns promise (await inside)", async (t) => { t.plan(2); - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", async function (str) { // Data in context t.is(this.page.url, "/hi/"); @@ -341,7 +343,7 @@ test("Liquid Shortcode returns promise (await inside)", async (t) => { test("Liquid Shortcode returns promise (no await inside)", async (t) => { t.plan(2); - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", async function (str) { // Data in context t.is(this.page.url, "/hi/"); @@ -404,7 +406,7 @@ test("Liquid Paired Shortcode", async (t) => { test("Liquid Async Paired Shortcode", async (t) => { t.plan(2); - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function (content, str) { // Data in context t.is(this.page.url, "/hi/"); @@ -858,14 +860,12 @@ test("Issue 347: Liquid Shortcode boolean argument", async (t) => { test("Issue 347: Liquid Paired Shortcode with Spaces", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.addPairedShortcode("postfixWithZach", function ( - content, - str1, - num, - str2 - ) { - return str1 + num + str2 + content + "Zach"; - }); + tr.engine.addPairedShortcode( + "postfixWithZach", + function (content, str1, num, str2) { + return str1 + num + str2 + content + "Zach"; + } + ); t.is( await tr._testRender( @@ -884,7 +884,7 @@ test("Liquid Render with dash variable Issue #567", async (t) => { }); test("Issue 600: Liquid Shortcode argument page.url", async (t) => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue600", function (str) { return str + "Zach"; }); @@ -898,7 +898,7 @@ test("Issue 600: Liquid Shortcode argument page.url", async (t) => { }); test("Issue 600: Liquid Shortcode argument with dashes", async (t) => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue600b", function (str) { return str + "Zach"; }); @@ -912,7 +912,7 @@ test("Issue 600: Liquid Shortcode argument with dashes", async (t) => { }); test("Issue 600: Liquid Shortcode argument with underscores", async (t) => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("issue600c", function (str) { return str + "Zach"; }); @@ -927,7 +927,7 @@ test("Issue 600: Liquid Shortcode argument with underscores", async (t) => { test.skip("Issue 611: Run a function", async (t) => { // This works in Nunjucks - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); t.is( await tr._testRender("{{ test() }}", { @@ -940,7 +940,7 @@ test.skip("Issue 611: Run a function", async (t) => { }); test("Liquid Shortcode (with sync function, error throwing)", async (t) => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function (str) { throw new Error("Liquid Shortcode (with sync function, error throwing)"); }); @@ -956,7 +956,7 @@ test("Liquid Shortcode (with sync function, error throwing)", async (t) => { }); test("Liquid Shortcode (with async function, error throwing)", async (t) => { - let tr = new TemplateRender("liquid", "./test/stubs/"); + let tr = getNewTemplateRender("liquid", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", async function (str) { throw new Error("Liquid Shortcode (with async function, error throwing)"); }); @@ -972,49 +972,49 @@ test("Liquid Shortcode (with async function, error throwing)", async (t) => { }); test("Liquid Render a false #1069", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "{{ falseValue }}" ); t.is(await fn({ falseValue: false }), "false"); }); test("Liquid Render Square Brackets #680 dash single quotes", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{ test['hey-a'] }}

" ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); test("Liquid Render Square Brackets #680 dash single quotes spaces", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{ test[ 'hey-a' ] }}

" ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); test("Liquid Render Square Brackets #680 dash double quotes", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( '

{{ test["hey-a"] }}

' ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); test("Liquid Render Square Brackets #680 dash double quotes spaces", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( '

{{ test[ "hey-a" ] }}

' ); t.is(await fn({ test: { "hey-a": 1 } }), "

1

"); }); test("Liquid Render Square Brackets #680 variable reference", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{ test[ref] }}

" ); t.is(await fn({ test: { "hey-a": 1 }, ref: "hey-a" }), "

1

"); }); test("Liquid Render Square Brackets #680 variable reference array", async (t) => { - let fn = await new TemplateRender("liquid").getCompiledTemplate( + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "

{{ test[ref[0]] }}

" ); t.is(await fn({ test: { "hey-a": 1 }, ref: ["hey-a"] }), "

1

"); diff --git a/test/TemplateRenderMarkdownPluginTest.js b/test/TemplateRenderMarkdownPluginTest.js index 78d1972b7..6008f3936 100644 --- a/test/TemplateRenderMarkdownPluginTest.js +++ b/test/TemplateRenderMarkdownPluginTest.js @@ -1,7 +1,16 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const md = require("markdown-it"); +function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); + let tr = new TemplateRender(name, inputDir); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); + return tr; +} + const createTestMarkdownPlugin = () => { const plugin = (md) => { md.core.ruler.after("inline", "replace-link", function (state) { @@ -16,7 +25,7 @@ const createTestMarkdownPlugin = () => { }; test("Markdown Render: with HTML prerender, sends context data to the markdown library", async (t) => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); const plugin = createTestMarkdownPlugin(); let mdLib = md().use(plugin); @@ -31,7 +40,7 @@ test("Markdown Render: with HTML prerender, sends context data to the markdown l }); test("Markdown Render: without HTML prerender, sends context data to the markdown library", async (t) => { - let tr = new TemplateRender("md"); + let tr = getNewTemplateRender("md"); const plugin = createTestMarkdownPlugin(); let mdLib = md().use(plugin); diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js index 749efdb85..5c24b4102 100644 --- a/test/TemplateRenderMarkdownTest.js +++ b/test/TemplateRenderMarkdownTest.js @@ -1,5 +1,6 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const md = require("markdown-it"); const mdEmoji = require("markdown-it-emoji"); @@ -7,8 +8,9 @@ const UserConfig = require("../src/UserConfig"); const eleventySyntaxHighlightPlugin = require("@11ty/eleventy-plugin-syntaxhighlight"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderMustacheTest.js b/test/TemplateRenderMustacheTest.js index db5cd4c18..e8dd3317b 100644 --- a/test/TemplateRenderMustacheTest.js +++ b/test/TemplateRenderMustacheTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 30d804bac..c790c8aec 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } @@ -31,7 +33,7 @@ test("Nunjucks Render", async (t) => { }); test("Nunjucks Render Addition", async (t) => { - let fn = await new TemplateRender("njk").getCompiledTemplate( + let fn = await getNewTemplateRender("njk").getCompiledTemplate( "

{{ number + 1 }}

" ); t.is(await fn({ number: 1 }), "

2

"); @@ -147,7 +149,7 @@ test("Nunjucks Render Relative Include (ambiguous path, file exists in _includes }); test("Nunjucks Async Filter", async (t) => { - let tr = new TemplateRender("njk", "test/stubs"); + let tr = getNewTemplateRender("njk", "test/stubs"); let engine = tr.engine; engine.addFilters( { @@ -164,7 +166,7 @@ test("Nunjucks Async Filter", async (t) => { }); test("Nunjucks Render set with a filter", async (t) => { - let tr = new TemplateRender("njk", "test/stubs"); + let tr = getNewTemplateRender("njk", "test/stubs"); let engine = tr.engine; engine.addFilters({ uppercase: function (str) { @@ -316,7 +318,7 @@ test("Nunjucks Shortcode", async (t) => { test("Nunjucks Async Shortcode", async (t) => { t.plan(2); - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", function (str) { @@ -346,7 +348,7 @@ test("Nunjucks Async Shortcode", async (t) => { test("Nunjucks Async function Shortcode", async (t) => { t.plan(2); - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", async function (str) { @@ -370,7 +372,7 @@ test("Nunjucks Async function Shortcode", async (t) => { }); test("Nunjucks Async function Shortcode (with sync function, error throwing)", async (t) => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZach", function (str) { @@ -392,7 +394,7 @@ test("Nunjucks Async function Shortcode (with sync function, error throwing)", a }); test("Nunjucks Async function Shortcode (with async function, error throwing)", async (t) => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode( "postfixWithZachError", async function (str) { @@ -414,7 +416,7 @@ test("Nunjucks Async function Shortcode (with async function, error throwing)", }); test("Nunjucks Async function paired Shortcode (with sync function, error throwing)", async (t) => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode( "postfixWithZachError", function (str) { @@ -439,7 +441,7 @@ test("Nunjucks Async function paired Shortcode (with sync function, error throwi }); test("Nunjucks Async function paired Shortcode (with async function, error throwing)", async (t) => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode( "postfixWithZachError", async function (str) { @@ -513,7 +515,7 @@ test("Nunjucks Paired Shortcode", async (t) => { test("Nunjucks Async Paired Shortcode", async (t) => { t.plan(2); - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode( "postfixWithZach", function (content, str) { @@ -642,7 +644,7 @@ test("Nunjucks Shortcode Multiple Args", async (t) => { }); test("Nunjucks Shortcode Multiple Args (Comma is required)", async (t) => { - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addShortcode("postfixWithZach", function (str, str2) { return str + str2 + "Zach"; }); @@ -784,7 +786,7 @@ test("Nunjucks Test if statements on arrays (Issue #524)", async (t) => { test("Issue 611: Run a function", async (t) => { // This does not work in Liquid - let tr = new TemplateRender("njk", "./test/stubs/"); + let tr = getNewTemplateRender("njk", "./test/stubs/"); t.is( await tr._testRender("{{ test() }}", { diff --git a/test/TemplateRenderPugTest.js b/test/TemplateRenderPugTest.js index 16f207cd6..977053d87 100644 --- a/test/TemplateRenderPugTest.js +++ b/test/TemplateRenderPugTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderTest.js b/test/TemplateRenderTest.js index 8447a2520..064abdf9a 100644 --- a/test/TemplateRenderTest.js +++ b/test/TemplateRenderTest.js @@ -1,10 +1,12 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); +const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { + let eleventyConfig = new TemplateConfig(); let tr = new TemplateRender(name, inputDir); - tr.extensionMap = new EleventyExtensionMap(); + tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index a9a258dd3..4a5c74b8f 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -1,8 +1,8 @@ const test = require("ava"); const Template = require("../src/Template"); const TemplateData = require("../src/TemplateData"); -const { cloneDeep } = require("lodash"); const getNewTemplate = require("./_getNewTemplateForTests"); +const TemplateConfig = require("../src/TemplateConfig"); async function getRenderedData(tmpl, pageNumber = 0) { let data = await tmpl.getData(); @@ -120,12 +120,15 @@ test("eleventyComputed true primitive", async (t) => { }); test("eleventyComputed relies on global data", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/eleventyComputed/use-global-data.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let fetchedData = await tmpl.getData(); @@ -135,19 +138,21 @@ test("eleventyComputed relies on global data", async (t) => { }); test("eleventyComputed intermixes with global data", async (t) => { - let dataObj = new TemplateData("./test/stubs-computed-global/"); - - let config = cloneDeep(dataObj.config); - config.dataDeepMerge = true; - dataObj._setConfig(config); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.setDataDeepMerge(true); + let dataObj = new TemplateData( + "./test/stubs-computed-global/", + eleventyConfig + ); let tmpl = getNewTemplate( "./test/stubs-computed-global/intermix.njk", "./test/stubs-computed-global/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); - tmpl.config = config; let fetchedData = await tmpl.getData(); t.truthy(fetchedData.eleventyComputed.image); diff --git a/test/TemplateTest-JavaScript.js b/test/TemplateTest-JavaScript.js index 1fd1eb155..9789e1b7d 100644 --- a/test/TemplateTest-JavaScript.js +++ b/test/TemplateTest-JavaScript.js @@ -1,9 +1,10 @@ const test = require("ava"); const Template = require("../src/Template"); const semver = require("semver"); +const getNewTemplate = require("./_getNewTemplateForTests"); test("JavaScript template type (function)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/function.11ty.js", "./test/stubs/", "./dist" @@ -18,7 +19,7 @@ test("JavaScript template type (function)", async (t) => { }); test("JavaScript template type (class with data getter)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data.11ty.js", "./test/stubs/", "./dist" @@ -32,7 +33,7 @@ test("JavaScript template type (class with data getter)", async (t) => { }); test("JavaScript template type (class with data method)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-fn.11ty.js", "./test/stubs/", "./dist" @@ -47,7 +48,7 @@ test("JavaScript template type (class with data method)", async (t) => { if (semver.gte(process.version, "12.4.0")) { test("JavaScript template type (class fields)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/classfields-data.11ty.js", "./test/stubs/", "./dist" @@ -62,7 +63,7 @@ if (semver.gte(process.version, "12.4.0")) { } test("JavaScript template type (class with shorthand data method)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-fn-shorthand.11ty.js", "./test/stubs/", "./dist" @@ -76,7 +77,7 @@ test("JavaScript template type (class with shorthand data method)", async (t) => }); test("JavaScript template type (class with async data method)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-async-data-fn.11ty.js", "./test/stubs/", "./dist" @@ -90,7 +91,7 @@ test("JavaScript template type (class with async data method)", async (t) => { }); test("JavaScript template type (class with data getter and a javascriptFunction)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-filter.11ty.js", "./test/stubs/", "./dist" @@ -110,7 +111,7 @@ test("JavaScript template type (class with data getter and a javascriptFunction) }); test("JavaScript template type (class with data method and a javascriptFunction)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-fn-filter.11ty.js", "./test/stubs/", "./dist" @@ -130,7 +131,7 @@ test("JavaScript template type (class with data method and a javascriptFunction) }); test("JavaScript template type (class with data permalink)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-permalink.11ty.js", "./test/stubs/", "./dist" @@ -140,7 +141,7 @@ test("JavaScript template type (class with data permalink)", async (t) => { }); test("JavaScript template type (class with data permalink using a buffer)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-permalink-buffer.11ty.js", "./test/stubs/", "./dist" @@ -150,7 +151,7 @@ test("JavaScript template type (class with data permalink using a buffer)", asyn }); test("JavaScript template type (class with data permalink function)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-permalink-fn.11ty.js", "./test/stubs/", "./dist" @@ -160,7 +161,7 @@ test("JavaScript template type (class with data permalink function)", async (t) }); test("JavaScript template type (class with data permalink function using a buffer)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-permalink-fn-buffer.11ty.js", "./test/stubs/", "./dist" @@ -170,7 +171,7 @@ test("JavaScript template type (class with data permalink function using a buffe }); test("JavaScript template type (class with data permalink async function)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-permalink-async-fn.11ty.js", "./test/stubs/", "./dist" @@ -180,7 +181,7 @@ test("JavaScript template type (class with data permalink async function)", asyn }); test("JavaScript template type (class with data permalink function using a filter)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-permalink-fn-filter.11ty.js", "./test/stubs/", "./dist" @@ -193,7 +194,7 @@ test("JavaScript template type (class with data permalink function using a filte }); test("JavaScript template type (class with renderData)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-data-renderdata.11ty.js", "./test/stubs/", "./dist" @@ -208,7 +209,7 @@ test("JavaScript template type (class with renderData)", async (t) => { }); test("JavaScript template type (should use the same class instance for data and render)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/oneinstance.11ty.js", "./test/stubs/", "./dist" @@ -223,7 +224,7 @@ test("JavaScript template type (should use the same class instance for data and }); test("JavaScript template type (multiple exports)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/multipleexports.11ty.js", "./test/stubs/", "./dist" @@ -235,7 +236,7 @@ test("JavaScript template type (multiple exports)", async (t) => { }); test("JavaScript template type (multiple exports, promises)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/multipleexports-promises.11ty.js", "./test/stubs/", "./dist" @@ -249,7 +250,7 @@ test("JavaScript template type (multiple exports, promises)", async (t) => { }); test("JavaScript template type (object)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/object.11ty.js", "./test/stubs/", "./dist" @@ -263,7 +264,7 @@ test("JavaScript template type (object)", async (t) => { }); test("JavaScript template type (object, no render method)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/object-norender.11ty.js", "./test/stubs/", "./dist" @@ -277,7 +278,7 @@ test("JavaScript template type (object, no render method)", async (t) => { }); test("JavaScript template type (class, no render method)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/class-norender.11ty.js", "./test/stubs/", "./dist" @@ -290,7 +291,7 @@ test("JavaScript template type (class, no render method)", async (t) => { t.is(pages[0].templateContent.trim(), ""); }); test("JavaScript template type (data returns a string)", async (t) => { - let tmpl = new Template( + let tmpl = getNewTemplate( "./test/stubs/exports-flatdata.11ty.js", "./test/stubs/", "./dist" diff --git a/test/TemplateTest.js b/test/TemplateTest.js index cd016bcd3..e05dc1167 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2,16 +2,14 @@ const test = require("ava"); const fs = require("fs-extra"); const fsp = require("fs").promises; const pretty = require("pretty"); -const Template = require("../src/Template"); + +const TemplateConfig = require("../src/TemplateConfig"); const TemplateData = require("../src/TemplateData"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const EleventyErrorUtil = require("../src/EleventyErrorUtil"); const TemplateContentPrematureUseError = require("../src/Errors/TemplateContentPrematureUseError"); const normalizeNewLines = require("./Util/normalizeNewLines"); -const templateConfig = require("../src/Config"); -const config = templateConfig.getConfig(); - const getNewTemplate = require("./_getNewTemplateForTests"); async function getRenderedData(tmpl, pageNumber = 0) { @@ -184,18 +182,24 @@ test("Test that getData() works", async (t) => { }); test("One Layout (using new content var)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/templateWithLayout.ejs", "./test/stubs/", "dist", - dataObj + dataObj, + null, + eleventyConfig ); - t.is((await tmpl.getFrontMatter()).data[config.keys.layout], "defaultLayout"); + t.is( + (await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], + "defaultLayout" + ); let data = await tmpl.getData(); - t.is(data[config.keys.layout], "defaultLayout"); + t.is(data[tmpl.config.keys.layout], "defaultLayout"); t.is( normalizeNewLines(cleanHtml(await tmpl.renderLayout(tmpl, data))), @@ -209,21 +213,24 @@ test("One Layout (using new content var)", async (t) => { }); test("One Layout (using layoutContent)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutContent.ejs", "./test/stubs/", "dist", - dataObj + dataObj, + null, + eleventyConfig ); t.is( - (await tmpl.getFrontMatter()).data[config.keys.layout], + (await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], "defaultLayoutLayoutContent" ); let data = await tmpl.getData(); - t.is(data[config.keys.layout], "defaultLayoutLayoutContent"); + t.is(data[tmpl.config.keys.layout], "defaultLayoutLayoutContent"); t.is( normalizeNewLines(cleanHtml(await tmpl.renderLayout(tmpl, data))), @@ -237,23 +244,26 @@ test("One Layout (using layoutContent)", async (t) => { }); test("One Layout (layouts disabled)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutContent.ejs", "./test/stubs/", "dist", - dataObj + dataObj, + null, + eleventyConfig ); tmpl.setWrapWithLayouts(false); t.is( - (await tmpl.getFrontMatter()).data[config.keys.layout], + (await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], "defaultLayoutLayoutContent" ); let data = await tmpl.getData(); - t.is(data[config.keys.layout], "defaultLayoutLayoutContent"); + t.is(data[tmpl.config.keys.layout], "defaultLayoutLayoutContent"); t.is(cleanHtml(await tmpl.render(data)), "

Hello.

"); @@ -262,21 +272,24 @@ test("One Layout (layouts disabled)", async (t) => { }); test("One Layout (_layoutContent deprecated but supported)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/templateWithLayoutBackCompat.ejs", "./test/stubs/", "dist", - dataObj + dataObj, + null, + eleventyConfig ); t.is( - (await tmpl.getFrontMatter()).data[config.keys.layout], + (await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], "defaultLayout_layoutContent" ); let data = await tmpl.getData(); - t.is(data[config.keys.layout], "defaultLayout_layoutContent"); + t.is(data[tmpl.config.keys.layout], "defaultLayout_layoutContent"); t.is( normalizeNewLines(cleanHtml(await tmpl.renderLayout(tmpl, data))), @@ -290,21 +303,24 @@ test("One Layout (_layoutContent deprecated but supported)", async (t) => { }); test("One Layout (liquid test)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/templateWithLayout.liquid", "./test/stubs/", "dist", - dataObj + dataObj, + null, + eleventyConfig ); t.is( - (await tmpl.getFrontMatter()).data[config.keys.layout], + (await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], "layoutLiquid.liquid" ); let data = await tmpl.getData(); - t.is(data[config.keys.layout], "layoutLiquid.liquid"); + t.is(data[tmpl.config.keys.layout], "layoutLiquid.liquid"); t.is( normalizeNewLines(cleanHtml(await tmpl.renderLayout(tmpl, data))), @@ -318,18 +334,21 @@ test("One Layout (liquid test)", async (t) => { }); test("Two Layouts", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/templateTwoLayouts.ejs", "./test/stubs/", "dist", - dataObj + dataObj, + null, + eleventyConfig ); - t.is((await tmpl.getFrontMatter()).data[config.keys.layout], "layout-a"); + t.is((await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], "layout-a"); let data = await tmpl.getData(); - t.is(data[config.keys.layout], "layout-a"); + t.is(data[tmpl.config.keys.layout], "layout-a"); t.is(data.key1, "value1"); t.is( @@ -345,12 +364,15 @@ test("Two Layouts", async (t) => { }); test("Liquid template", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/formatTest.liquid", "./test/stubs/", "dist", - dataObj + dataObj, + null, + eleventyConfig ); t.is(await tmpl.render(await tmpl.getData()), `

Zach

`); @@ -400,7 +422,8 @@ test("Permalink output directory from layout (fileslug)", async (t) => { }); test("Layout from template-data-file that has a permalink (fileslug) Issue #121", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/permalink-data-layout/test.njk", "./test/stubs/", @@ -427,7 +450,8 @@ test("Fileslug in an 11ty.js template Issue #588", async (t) => { }); test("Local template data file import (without a global data json)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( @@ -453,7 +477,8 @@ test("Local template data file import (without a global data json)", async (t) = }); test("Local template data file import (two subdirectories deep)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( @@ -484,7 +509,8 @@ test("Local template data file import (two subdirectories deep)", async (t) => { }); test("Posts inherits local JSON, layouts", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( @@ -525,7 +551,8 @@ test("Posts inherits local JSON, layouts", async (t) => { }); test("Template and folder name are the same, make sure data imports work ok", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( @@ -627,7 +654,8 @@ test("Permalink with dates on file name regex!", async (t) => { }); test("Reuse permalink in directory specific data file", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); let tmpl = getNewTemplate( "./test/stubs/reuse-permalink/test1.liquid", "./test/stubs/", @@ -1422,20 +1450,19 @@ test("Front matter date with quotes (njk), issue #258", async (t) => { }); test("Data Cascade (Deep merge)", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.dataDeepMerge = true; - - let dataObj = new TemplateData("./test/"); - dataObj._setConfig(newConfig); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.setDataDeepMerge(true); + let dataObj = new TemplateData("./test/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); - tmpl.config = newConfig; let data = await tmpl.getData(); t.deepEqual(Object.keys(data).sort(), [ @@ -1457,14 +1484,17 @@ test("Data Cascade (Deep merge)", async (t) => { }); test("Data Cascade (Shallow merge)", async (t) => { - let dataObj = new TemplateData("./test/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -1483,34 +1513,36 @@ test("Data Cascade (Shallow merge)", async (t) => { }); test("Data Cascade Tag Merge (Deep merge)", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.dataDeepMerge = true; - - let dataObj = new TemplateData("./test/stubs/"); - dataObj._setConfig(newConfig); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.setDataDeepMerge(true); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); - tmpl.config = newConfig; let data = await tmpl.getData(); t.deepEqual(data.tags.sort(), ["tagA", "tagB", "tagC", "tagD"]); }); test("Data Cascade Tag Merge (Shallow merge)", async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( "./test/stubs/data-cascade/template.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -1518,14 +1550,17 @@ test("Data Cascade Tag Merge (Shallow merge)", async (t) => { }); test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async (t) => { - let dataObj = new TemplateData("./test/stubs/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( "./test/stubs/local-data-tags/component.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -1533,20 +1568,19 @@ test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async ( }); test('Local data inherits tags string ([tags] vs "tags") Deep Merge', async (t) => { - let newConfig = Object.assign({}, config); - newConfig.dataDeepMerge = true; - - let dataObj = new TemplateData("./test/stubs/"); - dataObj._setConfig(newConfig); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.setDataDeepMerge(true); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); let tmpl = getNewTemplate( "./test/stubs/local-data-tags/component.njk", "./test/stubs/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); - tmpl.config = newConfig; let data = await tmpl.getData(); t.deepEqual(data.tags.sort(), ["tag1", "tag2", "tag3"]); @@ -1795,17 +1829,14 @@ test.skip("Issue 413 weird date format", async (t) => { }); test("Custom Front Matter Parsing Options", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.frontMatterParsingOptions = { - excerpt: true, - }; - let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template.njk", "./test/stubs/", "./dist" ); - tmpl.config = newConfig; + tmpl.config.frontMatterParsingOptions = { + excerpt: true, + }; let frontmatter = await tmpl.getFrontMatter(); t.is(frontmatter.data.front, "hello"); @@ -1823,18 +1854,15 @@ This is content.` }); test("Custom Front Matter Parsing Options (using alias)", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.frontMatterParsingOptions = { - excerpt: true, - excerpt_alias: "my_excerpt", - }; - let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template.njk", "./test/stubs/", "./dist" ); - tmpl.config = newConfig; + tmpl.config.frontMatterParsingOptions = { + excerpt: true, + excerpt_alias: "my_excerpt", + }; let frontmatter = await tmpl.getFrontMatter(); t.is(frontmatter.data.front, "hello"); @@ -1850,17 +1878,14 @@ This is content.` }); test("Custom Front Matter Parsing Options (no newline before excerpt separator)", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.frontMatterParsingOptions = { - excerpt: true, - }; - let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-newline1.njk", "./test/stubs/", "./dist" ); - tmpl.config = newConfig; + tmpl.config.frontMatterParsingOptions = { + excerpt: true, + }; let frontmatter = await tmpl.getFrontMatter(); t.is(frontmatter.data.front, "hello"); @@ -1878,17 +1903,14 @@ This is content.` }); test("Custom Front Matter Parsing Options (no newline after excerpt separator)", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.frontMatterParsingOptions = { - excerpt: true, - }; - let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-newline3.njk", "./test/stubs/", "./dist" ); - tmpl.config = newConfig; + tmpl.config.frontMatterParsingOptions = { + excerpt: true, + }; let frontmatter = await tmpl.getFrontMatter(); t.is( @@ -1899,35 +1921,29 @@ This is content.` }); test("Custom Front Matter Parsing Options (no newlines before or after excerpt separator)", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.frontMatterParsingOptions = { - excerpt: true, - }; - let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-newline2.njk", "./test/stubs/", "./dist" ); - tmpl.config = newConfig; + tmpl.config.frontMatterParsingOptions = { + excerpt: true, + }; let frontmatter = await tmpl.getFrontMatter(); t.is(frontmatter.content.trim(), "This is an excerpt.This is content."); }); test("Custom Front Matter Parsing Options (html comment separator)", async (t) => { - let newConfig = Object.assign({}, config); - newConfig.frontMatterParsingOptions = { - excerpt: true, - excerpt_separator: "", - }; - let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-excerpt-comment.njk", "./test/stubs/", "./dist" ); - tmpl.config = newConfig; + tmpl.config.frontMatterParsingOptions = { + excerpt: true, + excerpt_separator: "", + }; let frontmatter = await tmpl.getFrontMatter(); t.is(frontmatter.data.front, "hello"); @@ -1943,20 +1959,18 @@ This is content.` test.skip("Custom Front Matter Parsing Options (using TOML)", async (t) => { // Depends on https://github.com/jonschlinkert/gray-matter/issues/92 for Windows - let newConfig = Object.assign({}, config); let toml = require("toml"); - newConfig.frontMatterParsingOptions = { - engines: { - toml: toml.parse.bind(toml), - }, - }; - let tmpl = getNewTemplate( "./test/stubs/custom-frontmatter/template-toml.njk", "./test/stubs/", "./dist" ); + tmpl.config.frontMatterParsingOptions = { + engines: { + toml: toml.parse.bind(toml), + }, + }; tmpl.config = newConfig; let frontmatter = await tmpl.getFrontMatter(); @@ -2000,14 +2014,19 @@ test("Issue #446: Layout has a permalink with a different template language than // Prior to and including 0.10.0 this mismatched the documentation)! test("Layout front matter should override template files", async (t) => { + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData( - "./test/stubs-data-cascade/layout-data-files/" + "./test/stubs-data-cascade/layout-data-files/", + eleventyConfig ); let tmpl = getNewTemplate( "./test/stubs-data-cascade/layout-data-files/test.njk", "./test/stubs-data-cascade/layout-data-files/", "./dist", - dataObj + dataObj, + null, + eleventyConfig ); let data = await tmpl.getData(); @@ -2029,7 +2048,8 @@ test("Get Layout Chain", async (t) => { }); test("Engine Singletons", async (t) => { - let map = new EleventyExtensionMap(["njk"]); + let eleventyConfig = new TemplateConfig(); + let map = new EleventyExtensionMap(["njk"], eleventyConfig); let tmpl1 = getNewTemplate( "./test/stubs/engine-singletons/first.njk", "./test/stubs/engine-singletons/", diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index d439617b3..5902a4e39 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -6,20 +6,26 @@ const parsePath = require("parse-filepath"); const EleventyFiles = require("../src/EleventyFiles"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const TemplateWriter = require("../src/TemplateWriter"); +const TemplateConfig = require("../src/TemplateConfig"); // Not sure why but this required `ava` and _createTemplate 👀 // const Template = require("../src/Template"); const normalizeNewLines = require("./Util/normalizeNewLines"); // TODO make sure if output is a subdir of input dir that they don’t conflict. test("Output is a subdir of input", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/writeTest", - "./test/stubs/writeTest/_writeTestSite" + "./test/stubs/writeTest/_writeTestSite", + ["ejs", "md"], + null, + eleventyConfig ); let evf = new EleventyFiles( "./test/stubs/writeTest", "./test/stubs/writeTest/_writeTestSite", - ["ejs", "md"] + ["ejs", "md"], + eleventyConfig ); evf.init(); @@ -36,10 +42,13 @@ test("Output is a subdir of input", async (t) => { }); test("_createTemplateMap", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/writeTest", "./test/stubs/_writeTestSite", - ["ejs", "md"] + ["ejs", "md"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -54,10 +63,13 @@ test("_createTemplateMap", async (t) => { }); test("_createTemplateMap (no leading dot slash)", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "test/stubs/writeTest", "test/stubs/_writeTestSite", - ["ejs", "md"] + ["ejs", "md"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -66,9 +78,14 @@ test("_createTemplateMap (no leading dot slash)", async (t) => { }); test("_testGetCollectionsData", async (t) => { - let tw = new TemplateWriter("./test/stubs/collection", "./test/stubs/_site", [ - "md", - ]); + let eleventyConfig = new TemplateConfig(); + let tw = new TemplateWriter( + "./test/stubs/collection", + "./test/stubs/_site", + ["md"], + null, + eleventyConfig + ); let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); @@ -80,9 +97,14 @@ test("_testGetCollectionsData", async (t) => { // TODO remove this (used by other test things) test("_testGetAllTags", async (t) => { - let tw = new TemplateWriter("./test/stubs/collection", "./test/stubs/_site", [ - "md", - ]); + let eleventyConfig = new TemplateConfig(); + let tw = new TemplateWriter( + "./test/stubs/collection", + "./test/stubs/_site", + ["md"], + null, + eleventyConfig + ); let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); @@ -92,9 +114,14 @@ test("_testGetAllTags", async (t) => { }); test("Collection of files sorted by date", async (t) => { - let tw = new TemplateWriter("./test/stubs/dates", "./test/stubs/_site", [ - "md", - ]); + let eleventyConfig = new TemplateConfig(); + let tw = new TemplateWriter( + "./test/stubs/dates", + "./test/stubs/_site", + ["md"], + null, + eleventyConfig + ); let paths = await tw._getAllPaths(); let templateMap = await tw._createTemplateMap(paths); @@ -103,10 +130,13 @@ test("Collection of files sorted by date", async (t) => { }); test("__testGetCollectionsData with custom collection (ascending)", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", - ["md"] + ["md"], + null, + eleventyConfig ); tw.userConfig.addCollection("customPostsAsc", function (collection) { @@ -124,10 +154,13 @@ test("__testGetCollectionsData with custom collection (ascending)", async (t) => }); test("__testGetCollectionsData with custom collection (descending)", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", - ["md"] + ["md"], + null, + eleventyConfig ); tw.userConfig.addCollection("customPosts", function (collection) { @@ -145,10 +178,13 @@ test("__testGetCollectionsData with custom collection (descending)", async (t) = }); test("__testGetCollectionsData with custom collection (filter only to markdown input)", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", - ["md"] + ["md"], + null, + eleventyConfig ); tw.userConfig.addCollection("onlyMarkdown", function (collection) { @@ -167,10 +203,13 @@ test("__testGetCollectionsData with custom collection (filter only to markdown i }); test("Pagination with a Collection", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/paged/collection", "./test/stubs/_site", - ["njk"] + ["njk"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -197,10 +236,13 @@ test("Pagination with a Collection", async (t) => { }); test("Pagination with a Collection from another Paged Template", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/paged/cfg-collection-tag-cfg-collection", "./test/stubs/_site", - ["njk"] + ["njk"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -230,10 +272,13 @@ test("Pagination with a Collection from another Paged Template", async (t) => { }); test("Pagination with a Collection (apply all pages to collections)", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/paged/collection-apply-to-all", "./test/stubs/_site", - ["njk"] + ["njk"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -281,10 +326,13 @@ test("Pagination with a Collection (apply all pages to collections)", async (t) }); test("Use a collection inside of a template", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection-template", "./test/stubs/collection-template/_site", - ["ejs"] + ["ejs"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -323,10 +371,13 @@ Template 1 dog` }); test("Use a collection inside of a layout", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection-layout", "./test/stubs/collection-layout/_site", - ["ejs"] + ["ejs"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -362,15 +413,25 @@ Layout 1 dog` }); test("Glob Watcher Files with Passthroughs", (t) => { - let tw = new TemplateWriter("test/stubs", "test/stubs/_site", ["njk", "png"]); + let eleventyConfig = new TemplateConfig(); + let tw = new TemplateWriter( + "test/stubs", + "test/stubs/_site", + ["njk", "png"], + null, + eleventyConfig + ); t.deepEqual(tw.eleventyFiles.passthroughGlobs, ["./test/stubs/**/*.png"]); }); test("Pagination and TemplateContent", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/pagination-templatecontent", "./test/stubs/pagination-templatecontent/_site", - ["njk", "md"] + ["njk", "md"], + null, + eleventyConfig ); tw.setVerboseOutput(false); @@ -390,10 +451,13 @@ test("Pagination and TemplateContent", async (t) => { }); test("Custom collection returns array", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", - ["md"] + ["md"], + null, + eleventyConfig ); tw.userConfig.addCollection("returnAllInputPaths", function (collection) { @@ -411,10 +475,13 @@ test("Custom collection returns array", async (t) => { }); test("Custom collection returns a string", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", - ["md"] + ["md"], + null, + eleventyConfig ); tw.userConfig.addCollection("returnATestString", function (collection) { @@ -428,10 +495,13 @@ test("Custom collection returns a string", async (t) => { }); test("Custom collection returns an object", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection2", "./test/stubs/_site", - ["md"] + ["md"], + null, + eleventyConfig ); tw.userConfig.addCollection("returnATestObject", function () { @@ -445,10 +515,13 @@ test("Custom collection returns an object", async (t) => { }); test("fileSlug should exist in a collection", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection-slug", "./test/stubs/collection-slug/_site", - ["njk"] + ["njk"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -468,10 +541,13 @@ test("fileSlug should exist in a collection", async (t) => { }); test("renderData should exist and be resolved in a collection (Issue #289)", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/collection-renderdata", "./test/stubs/collection-renderdata/_site", - ["njk"] + ["njk"], + null, + eleventyConfig ); let paths = await tw._getAllPaths(); @@ -491,14 +567,19 @@ test("renderData should exist and be resolved in a collection (Issue #289)", asy }); test("Write Test 11ty.js", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/writeTestJS", - "./test/stubs/_writeTestJSSite" + "./test/stubs/_writeTestJSSite", + ["11ty.js"], + null, + eleventyConfig ); let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", - ["11ty.js"] + ["11ty.js"], + eleventyConfig ); evf.init(); @@ -517,7 +598,8 @@ test("Write Test 11ty.js", async (t) => { }); test.skip("Markdown with alias", async (t) => { - let map = new EleventyExtensionMap(["md"]); + let eleventyConfig = new TemplateConfig(); + let map = new EleventyExtensionMap(["md"], eleventyConfig); map.config = { templateExtensionAliases: { markdown: "md", @@ -527,7 +609,8 @@ test.skip("Markdown with alias", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTestMarkdown", "./test/stubs/_writeTestMarkdownSite", - ["md"] + ["md"], + eleventyConfig ); evf._setExtensionMap(map); evf.init(); @@ -542,7 +625,10 @@ test.skip("Markdown with alias", async (t) => { let tw = new TemplateWriter( "./test/stubs/writeTestMarkdown", - "./test/stubs/_writeTestMarkdownSite" + "./test/stubs/_writeTestMarkdownSite", + ["md"], + null, + eleventyConfig ); tw.setEleventyFiles(evf); @@ -562,7 +648,8 @@ test.skip("Markdown with alias", async (t) => { }); test.skip("JavaScript with alias", async (t) => { - let map = new EleventyExtensionMap(["11ty.js"]); + let eleventyConfig = new TemplateConfig(); + let map = new EleventyExtensionMap(["11ty.js"], eleventyConfig); map.config = { templateExtensionAliases: { js: "11ty.js", @@ -572,7 +659,8 @@ test.skip("JavaScript with alias", async (t) => { let evf = new EleventyFiles( "./test/stubs/writeTestJS", "./test/stubs/_writeTestJSSite", - ["11ty.js"] + ["11ty.js"], + eleventyConfig ); evf._setExtensionMap(map); evf.init(); @@ -595,7 +683,10 @@ test.skip("JavaScript with alias", async (t) => { let tw = new TemplateWriter( "./test/stubs/writeTestJS", - "./test/stubs/_writeTestJSSite" + "./test/stubs/_writeTestJSSite", + ["11ty.js"], + null, + eleventyConfig ); tw.setEleventyFiles(evf); @@ -607,10 +698,13 @@ test.skip("JavaScript with alias", async (t) => { }); test("Passthrough file output", async (t) => { + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/template-passthrough/", "./test/stubs/template-passthrough/_site", - ["njk", "md"] + ["njk", "md"], + null, + eleventyConfig ); const mgr = tw.eleventyFiles.getPassthroughManager(); diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index 753f2010b..4c9a12203 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -1,4 +1,5 @@ const test = require("ava"); +const TemplateConfig = require("../src/TemplateConfig"); const TemplateData = require("../src/TemplateData"); let yaml = require("js-yaml"); @@ -10,7 +11,8 @@ function injectDataExtensions(dataObj) { } test("Local data", async (t) => { - let dataObj = new TemplateData("./test/stubs-630/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs-630/", eleventyConfig); injectDataExtensions(dataObj); dataObj.setDataTemplateEngine("liquid"); @@ -38,7 +40,8 @@ test("Local data", async (t) => { }); test("Local files", async (t) => { - let dataObj = new TemplateData("./test/stubs-630/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs-630/", eleventyConfig); injectDataExtensions(dataObj); let files = await dataObj.getLocalDataPaths( "./test/stubs-630/component-yaml/component.njk" @@ -72,7 +75,8 @@ test("Local files", async (t) => { }); test("Global data", async (t) => { - let dataObj = new TemplateData("./test/stubs-630/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs-630/", eleventyConfig); injectDataExtensions(dataObj); dataObj.setDataTemplateEngine("liquid"); @@ -104,7 +108,8 @@ test("Global data", async (t) => { }); test("Global data merging and priority", async (t) => { - let dataObj = new TemplateData("./test/stubs-630/"); + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs-630/", eleventyConfig); injectDataExtensions(dataObj); let data = await dataObj.getData(); diff --git a/test/_getNewTemplateForTests.js b/test/_getNewTemplateForTests.js index 246b0fda0..471ab6a4e 100644 --- a/test/_getNewTemplateForTests.js +++ b/test/_getNewTemplateForTests.js @@ -1,4 +1,5 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const TemplateConfig = require("../src/TemplateConfig"); const Template = require("../src/Template"); module.exports = function getNewTemplate( @@ -6,22 +7,32 @@ module.exports = function getNewTemplate( inputDir, outputDir, templateData = null, - map = null + map = null, + eleventyConfig = new TemplateConfig() ) { if (!map) { - map = new EleventyExtensionMap([ - "liquid", - "ejs", - "md", - "hbs", - "mustache", - "haml", - "pug", - "njk", - "html", - "11ty.js", - ]); + map = new EleventyExtensionMap( + [ + "liquid", + "ejs", + "md", + "hbs", + "mustache", + "haml", + "pug", + "njk", + "html", + "11ty.js", + ], + eleventyConfig + ); } - let tmpl = new Template(path, inputDir, outputDir, templateData, map); - return tmpl; + return new Template( + path, + inputDir, + outputDir, + templateData, + map, + eleventyConfig + ); }; From f856c525713e1ac1fc26af2c2617e36c76421897 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Feb 2021 20:25:08 -0600 Subject: [PATCH 335/746] Another stopping point, almost there --- src/EleventyExtensionMap.js | 5 ++--- src/Engines/Custom.js | 4 ++-- src/Engines/Ejs.js | 8 ++++---- src/Engines/Haml.js | 4 ++-- src/Engines/Handlebars.js | 4 ++-- src/Engines/Html.js | 4 ++-- src/Engines/JavaScript.js | 4 ++-- src/Engines/Liquid.js | 4 ++-- src/Engines/Markdown.js | 4 ++-- src/Engines/Mustache.js | 4 ++-- src/Engines/Nunjucks.js | 4 ++-- src/Engines/Pug.js | 4 ++-- src/Engines/TemplateEngine.js | 23 ++++++++++++++------- src/TemplateContent.js | 6 +++++- src/TemplateData.js | 2 +- src/TemplateEngineManager.js | 21 +++++++------------ src/TemplateRender.js | 17 ++++++++++++---- test/PaginationTest.js | 10 ++------- test/TemplateEngineManagerTest.js | 26 +++++++++++++++--------- test/TemplateEngineTest.js | 10 +++++++-- test/TemplateRenderCustomTest.js | 22 ++++++++++++-------- test/TemplateRenderEJSTest.js | 2 +- test/TemplateRenderHTMLTest.js | 2 +- test/TemplateRenderHamlTest.js | 2 +- test/TemplateRenderHandlebarsTest.js | 2 +- test/TemplateRenderJavaScriptTest.js | 4 ++-- test/TemplateRenderLiquidTest.js | 2 +- test/TemplateRenderMarkdownPluginTest.js | 2 +- test/TemplateRenderMarkdownTest.js | 17 ++++++++-------- test/TemplateRenderMustacheTest.js | 2 +- test/TemplateRenderNunjucksTest.js | 2 +- test/TemplateRenderPugTest.js | 2 +- test/TemplateRenderTest.js | 2 +- 33 files changed, 128 insertions(+), 103 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 87fb51078..0abc345fd 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -10,7 +10,7 @@ class EleventyExtensionMap { if (!config) { throw new EleventyExtensionMapConfigError("Missing `config` argument."); } - this.config = config; + this._config = config; this.formatKeys = formatKeys; @@ -44,8 +44,7 @@ class EleventyExtensionMap { get engineManager() { if (!this._engineManager) { - this._engineManager = new TemplateEngineManager(); - this._engineManager.config = this.config; + this._engineManager = new TemplateEngineManager(this.config); } return this._engineManager; diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index d2d0a9b56..e2e910639 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -2,8 +2,8 @@ const TemplateEngine = require("./TemplateEngine"); const getJavaScriptData = require("../Util/GetJavaScriptData"); class CustomEngine extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.entry = this.getExtensionMapEntry(); this.needsInit = diff --git a/src/Engines/Ejs.js b/src/Engines/Ejs.js index 00d386034..a05714813 100644 --- a/src/Engines/Ejs.js +++ b/src/Engines/Ejs.js @@ -2,8 +2,8 @@ const ejsLib = require("ejs"); const TemplateEngine = require("./TemplateEngine"); class Ejs extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.ejsOptions = {}; @@ -31,7 +31,7 @@ class Ejs extends TemplateEngine { { root: "./" + includesDir, compileDebug: true, - filename: "./" + includesDir + filename: "./" + includesDir, }, this.ejsOptions || {} ); @@ -46,7 +46,7 @@ class Ejs extends TemplateEngine { let fn = this.ejsLib.compile(str, options); - return function(data) { + return function (data) { return fn(data); }; } diff --git a/src/Engines/Haml.js b/src/Engines/Haml.js index fa22e6729..0dd6ec02c 100644 --- a/src/Engines/Haml.js +++ b/src/Engines/Haml.js @@ -2,8 +2,8 @@ const HamlLib = require("hamljs"); const TemplateEngine = require("./TemplateEngine"); class Haml extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.setLibrary(this.config.libraryOverrides.haml); } diff --git a/src/Engines/Handlebars.js b/src/Engines/Handlebars.js index 3c6ec2e9f..03b05d899 100644 --- a/src/Engines/Handlebars.js +++ b/src/Engines/Handlebars.js @@ -2,8 +2,8 @@ const HandlebarsLib = require("handlebars"); const TemplateEngine = require("./TemplateEngine"); class Handlebars extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.setLibrary(this.config.libraryOverrides.hbs); } diff --git a/src/Engines/Html.js b/src/Engines/Html.js index ba4737469..8415a6c0a 100644 --- a/src/Engines/Html.js +++ b/src/Engines/Html.js @@ -1,8 +1,8 @@ const TemplateEngine = require("./TemplateEngine"); class Html extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.cacheable = true; } diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 9d913155f..6fce05b33 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -7,8 +7,8 @@ const getJavaScriptData = require("../Util/GetJavaScriptData"); class JavaScriptTemplateNotDefined extends EleventyBaseError {} class JavaScript extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.instances = {}; } diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index fb4560fdf..72b4e6996 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -5,8 +5,8 @@ const TemplatePath = require("../TemplatePath"); // const debug = require("debug")("Eleventy:Liquid"); class Liquid extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.liquidOptions = {}; diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index 1685e8ce6..851fc61c3 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -3,8 +3,8 @@ const TemplateEngine = require("./TemplateEngine"); // const debug = require("debug")("Eleventy:Markdown"); class Markdown extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.markdownOptions = {}; diff --git a/src/Engines/Mustache.js b/src/Engines/Mustache.js index 12ca69120..77bdb1244 100644 --- a/src/Engines/Mustache.js +++ b/src/Engines/Mustache.js @@ -2,8 +2,8 @@ const MustacheLib = require("mustache"); const TemplateEngine = require("./TemplateEngine"); class Mustache extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.setLibrary(this.config.libraryOverrides.mustache); } diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 3a3efa500..352763644 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -7,8 +7,8 @@ const EleventyBaseError = require("../EleventyBaseError"); class EleventyShortcodeError extends EleventyBaseError {} class Nunjucks extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.setLibrary(this.config.libraryOverrides.njk); diff --git a/src/Engines/Pug.js b/src/Engines/Pug.js index 1e9e58cf8..de0322b3d 100644 --- a/src/Engines/Pug.js +++ b/src/Engines/Pug.js @@ -2,8 +2,8 @@ const PugLib = require("pug"); const TemplateEngine = require("./TemplateEngine"); class Pug extends TemplateEngine { - constructor(name, includesDir) { - super(name, includesDir); + constructor(name, includesDir, config) { + super(name, includesDir, config); this.pugOptions = {}; diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 161ca8b25..7de46c076 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -1,31 +1,40 @@ const fastglob = require("fast-glob"); const fs = require("fs-extra"); const TemplatePath = require("../TemplatePath"); +const TemplateConfig = require("../TemplateConfig"); const EleventyExtensionMap = require("../EleventyExtensionMap"); +const EleventyBaseError = require("../EleventyBaseError"); const debug = require("debug")("Eleventy:TemplateEngine"); const aggregateBench = require("../BenchmarkManager").get("Aggregate"); +class TemplateEngineConfigError extends EleventyBaseError {} + class TemplateEngine { - constructor(name, includesDir) { + constructor(name, includesDir, config) { this.name = name; this.includesDir = includesDir; this.partialsHaveBeenCached = false; this.partials = []; this.engineLib = null; this.cacheable = false; + + if (!config) { + throw new TemplateEngineConfigError("Missing `config` argument."); + } + this._config = config; + } + + set config(cfg) { + this._config = cfg; } get config() { - if (!this._config) { - this._config = require("../Config").getConfig(); + if (this._config instanceof TemplateConfig) { + return this._config.getConfig(); } return this._config; } - set config(config) { - this._config = config; - } - get engineManager() { return this._engineManager; } diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 9d6ad6393..1b264e7b3 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -67,7 +67,11 @@ class TemplateContent { get templateRender() { if (!this._templateRender) { - this._templateRender = new TemplateRender(this.inputPath, this.inputDir); + this._templateRender = new TemplateRender( + this.inputPath, + this.inputDir, + this.config + ); this._templateRender.extensionMap = this.extensionMap; } diff --git a/src/TemplateData.js b/src/TemplateData.js index 794463ab9..91676d832 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -401,7 +401,7 @@ class TemplateData { ); } } else { - let tr = new TemplateRender(engineName, this.inputDir); + let tr = new TemplateRender(engineName, this.inputDir, this.config); tr.extensionMap = this.extensionMap; let fn = await tr.getCompiledTemplate(rawInput); diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 5d0949f9f..63278fc6b 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -1,19 +1,13 @@ -const config = require("./Config"); - +const EleventyBaseError = require("./EleventyBaseError"); +class TemplateEngineManagerConfigError extends EleventyBaseError {} class TemplateEngineManager { - constructor() { + constructor(config) { this.engineCache = {}; - } - get config() { - if (!this._config) { - this._config = config.getConfig(); + if (!config) { + throw new TemplateEngineManagerConfigError("Missing `config` argument."); } - return this._config; - } - - set config(cfg) { - this._config = cfg; + this.config = config; } get keyToClassNameMap() { @@ -63,9 +57,8 @@ class TemplateEngineManager { let path = "./Engines/" + this.getClassNameFromTemplateKey(name); const cls = require(path); - let instance = new cls(name, includesDir); + let instance = new cls(name, includesDir, this.config); instance.extensionMap = extensionMap; - instance.config = this.config; instance.engineManager = this; // Make sure cache key is based on name and not path diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 86cedd581..789b5fa97 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -1,18 +1,27 @@ const TemplatePath = require("./TemplatePath"); +const TemplateConfig = require("./TemplateConfig"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyExtensionMap = require("./EleventyExtensionMap"); // const debug = require("debug")("Eleventy:TemplateRender"); +class TemplateRenderConfigError extends EleventyBaseError {} class TemplateRenderUnknownEngineError extends EleventyBaseError {} // works with full path names or short engine name class TemplateRender { - constructor(tmplPath, inputDir) { + constructor(tmplPath, inputDir, config) { if (!tmplPath) { throw new Error( `TemplateRender requires a tmplPath argument, instead of ${tmplPath}` ); } + if (!config) { + throw new TemplateRenderConfigError("Missing `config` argument."); + } + if (config instanceof TemplateConfig) { + this.eleventyConfig = config; + } + this.config = config; this.engineNameOrPath = tmplPath; this.inputDir = inputDir; @@ -25,8 +34,8 @@ class TemplateRender { } get config() { - if (!this._config) { - this._config = require("./Config").getConfig(); + if (this._config instanceof TemplateConfig) { + return this._config.getConfig(); } return this._config; } @@ -41,7 +50,7 @@ class TemplateRender { get extensionMap() { if (!this._extensionMap) { - this._extensionMap = new EleventyExtensionMap(); + this._extensionMap = new EleventyExtensionMap([], this.config); } return this._extensionMap; } diff --git a/test/PaginationTest.js b/test/PaginationTest.js index bd17093f5..8f165f6c9 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -527,14 +527,8 @@ test("Pagination with deep data merge with alias #147", async (t) => { "./test/stubs/", "./dist" ); - tmpl.config = { - keys: { - layout: "layout", - permalink: "permalink", - }, - dynamicPermalinks: true, - dataDeepMerge: true, - }; + tmpl.config.dynamicPermalinks = true; + tmpl.config.deepDataMerge = true; let data = await tmpl.getData(); let pages = await tmpl.getTemplates(data); diff --git a/test/TemplateEngineManagerTest.js b/test/TemplateEngineManagerTest.js index 780fe3c09..ab3592217 100644 --- a/test/TemplateEngineManagerTest.js +++ b/test/TemplateEngineManagerTest.js @@ -1,22 +1,24 @@ const test = require("ava"); const TemplateEngineManager = require("../src/TemplateEngineManager"); -const templateConfig = require("../src/Config"); -const config = templateConfig.getConfig(); +const TemplateConfig = require("../src/TemplateConfig"); test("Unsupported engine", async (t) => { t.throws(() => { - let tem = new TemplateEngineManager(); + let config = new TemplateConfig().getConfig(); + let tem = new TemplateEngineManager(config); tem.getEngine("doesnotexist"); }); }); test("Supported engine", async (t) => { - let tem = new TemplateEngineManager(); + let config = new TemplateConfig().getConfig(); + let tem = new TemplateEngineManager(config); t.truthy(tem.hasEngine("ejs")); }); test("Supported custom engine", async (t) => { - let tem = new TemplateEngineManager(); + let config = new TemplateConfig().getConfig(); + let tem = new TemplateEngineManager(config); tem.config = Object.assign({}, config); tem.config.extensionMap.add({ extension: "txt", @@ -38,9 +40,8 @@ test("Supported custom engine", async (t) => { test("Custom engine with custom init", async (t) => { let initCount = 0; let compileCount = 0; - let tem = new TemplateEngineManager(); - tem.config = Object.assign({}, config); - tem.config.extensionMap.add({ + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ extension: "custom1", key: "custom1", init: async function () { @@ -53,6 +54,9 @@ test("Custom engine with custom init", async (t) => { }, }); + let config = eleventyConfig.getConfig(); + let tem = new TemplateEngineManager(config); + t.truthy(tem.hasEngine("custom1")); let engine = tem.getEngine("custom1"); let fn = await engine.compile("

This is plaintext

"); @@ -69,7 +73,8 @@ test("Custom engine with custom init", async (t) => { }); test("Handlebars Helpers", async (t) => { - let tem = new TemplateEngineManager(); + let config = new TemplateConfig().getConfig(); + let tem = new TemplateEngineManager(config); let engine = tem.getEngine("hbs"); engine.addHelpers({ uppercase: function (name) { @@ -82,6 +87,7 @@ test("Handlebars Helpers", async (t) => { }); test("getEngineLib", async (t) => { - let tem = new TemplateEngineManager(); + let config = new TemplateConfig().getConfig(); + let tem = new TemplateEngineManager(config); t.truthy(tem.getEngine("md").getEngineLib()); }); diff --git a/test/TemplateEngineTest.js b/test/TemplateEngineTest.js index 42cce0a08..b11b8f2b0 100644 --- a/test/TemplateEngineTest.js +++ b/test/TemplateEngineTest.js @@ -1,10 +1,16 @@ const test = require("ava"); const TemplateEngine = require("../src/Engines/TemplateEngine"); +const TemplateConfig = require("../src/TemplateConfig"); test("Unsupported engine", async (t) => { - t.is(new TemplateEngine("doesnotexist").getName(), "doesnotexist"); + let eleventyConfig = new TemplateConfig(); + t.is( + new TemplateEngine("doesnotexist", null, eleventyConfig).getName(), + "doesnotexist" + ); }); test("Supported engine", async (t) => { - t.is(new TemplateEngine("ejs").getName(), "ejs"); + let eleventyConfig = new TemplateConfig(); + t.is(new TemplateEngine("ejs", null, eleventyConfig).getName(), "ejs"); }); diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index 43071dae6..91458329d 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -5,16 +5,18 @@ const TemplateConfig = require("../src/TemplateConfig"); const Vue = require("vue"); const renderer = require("vue-server-renderer").createRenderer(); -function getNewTemplateRender(name, inputDir) { - let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); +function getNewTemplateRender(name, inputDir, eleventyConfig) { + if (!eleventyConfig) { + eleventyConfig = new TemplateConfig(); + } + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } test("Custom plaintext Render", async (t) => { - let tr = getNewTemplateRender("txt"); - tr.config.extensionMap.add({ + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ extension: "txt", key: "txt", compile: function (str, inputPath) { @@ -25,6 +27,8 @@ test("Custom plaintext Render", async (t) => { }, }); + let tr = getNewTemplateRender("txt", null, eleventyConfig); + let fn = await tr.getCompiledTemplate("

Paragraph

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

Paragraph

"); t.is(await fn({}), "

Paragraph

"); @@ -33,7 +37,7 @@ test("Custom plaintext Render", async (t) => { test("Custom Vue Render", async (t) => { let tr = getNewTemplateRender("vue"); - tr.config.extensionMap.add({ + tr.eleventyConfig.userConfig.extensionMap.add({ extension: "vue", key: "vue", compile: function (str, inputPath) { @@ -52,11 +56,11 @@ test("Custom Vue Render", async (t) => { t.is(await fn({ test: "Hello" }), `

Hello

`); }); +const sass = require("node-sass"); + test("Custom Sass Render", async (t) => { - const sass = require("node-sass"); let tr = getNewTemplateRender("sass"); - - tr.config.extensionMap.add({ + tr.eleventyConfig.userConfig.extensionMap.add({ extension: "sass", key: "sass", compile: function (str, inputPath) { diff --git a/test/TemplateRenderEJSTest.js b/test/TemplateRenderEJSTest.js index 80c3f1f50..ab0a82323 100644 --- a/test/TemplateRenderEJSTest.js +++ b/test/TemplateRenderEJSTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderHTMLTest.js b/test/TemplateRenderHTMLTest.js index bb51663c6..2027a5a0c 100644 --- a/test/TemplateRenderHTMLTest.js +++ b/test/TemplateRenderHTMLTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderHamlTest.js b/test/TemplateRenderHamlTest.js index 2e30f402b..02159df6f 100644 --- a/test/TemplateRenderHamlTest.js +++ b/test/TemplateRenderHamlTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderHandlebarsTest.js b/test/TemplateRenderHandlebarsTest.js index 75565e7fe..a65c86ff5 100644 --- a/test/TemplateRenderHandlebarsTest.js +++ b/test/TemplateRenderHandlebarsTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index bf03de2f7..49af36358 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } @@ -198,7 +198,7 @@ test("JS Render with a function", async (t) => { // This doesn’t work, per arrow functions test.skip("Issue #934: JS Render with an arrow function and javascript function", async (t) => { - let tr = new TemplateRender("./test/stubs/function-filter-arrow.11ty.js"); + let tr = getNewTemplateRender("./test/stubs/function-filter-arrow.11ty.js"); tr.config = { javascriptFunctions: { upper: function (val) { diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index f76c3d7ce..18154a757 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderMarkdownPluginTest.js b/test/TemplateRenderMarkdownPluginTest.js index 6008f3936..dfd5d345b 100644 --- a/test/TemplateRenderMarkdownPluginTest.js +++ b/test/TemplateRenderMarkdownPluginTest.js @@ -6,7 +6,7 @@ const md = require("markdown-it"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js index 5c24b4102..d88e63a90 100644 --- a/test/TemplateRenderMarkdownTest.js +++ b/test/TemplateRenderMarkdownTest.js @@ -9,7 +9,7 @@ const eleventySyntaxHighlightPlugin = require("@11ty/eleventy-plugin-syntaxhighl function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } @@ -255,9 +255,9 @@ var key = "value"; test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); - + let eleventyConfig = new TemplateConfig(); let cls = require("../src/Engines/Liquid"); - let liquidEngine = new cls("liquid", tr.getIncludesDir()); + let liquidEngine = new cls("liquid", tr.getIncludesDir(), eleventyConfig); liquidEngine.addShortcode("testShortcode", function () { return "## My Other Title"; }); @@ -279,9 +279,9 @@ test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); - + let eleventyConfig = new TemplateConfig(); let cls = require("../src/Engines/Nunjucks"); - let nunjucksEngine = new cls("njk", tr.getIncludesDir()); + let nunjucksEngine = new cls("njk", tr.getIncludesDir(), eleventyConfig); nunjucksEngine.addShortcode("testShortcode", function () { return "## My Other Title"; }); @@ -303,9 +303,9 @@ test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)" test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); - + let eleventyConfig = new TemplateConfig(); let cls = require("../src/Engines/Liquid"); - let liquidEngine = new cls("liquid", tr.getIncludesDir()); + let liquidEngine = new cls("liquid", tr.getIncludesDir(), eleventyConfig); liquidEngine.addPairedShortcode("testShortcode", function (content) { return content; }); @@ -327,9 +327,10 @@ test("Markdown Render: use Markdown inside of a Liquid paired shortcode (Issue # test("Markdown Render: use Markdown inside of a Nunjucks paired shortcode (Issue #536)", async (t) => { let tr = getNewTemplateRender("md"); + let eleventyConfig = new TemplateConfig(); let cls = require("../src/Engines/Nunjucks"); - let nunjucksEngine = new cls("njk", tr.getIncludesDir()); + let nunjucksEngine = new cls("njk", tr.getIncludesDir(), eleventyConfig); nunjucksEngine.addPairedShortcode("testShortcode", function (content) { return content; }); diff --git a/test/TemplateRenderMustacheTest.js b/test/TemplateRenderMustacheTest.js index e8dd3317b..30b2a4146 100644 --- a/test/TemplateRenderMustacheTest.js +++ b/test/TemplateRenderMustacheTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index c790c8aec..7ee7a39e7 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderPugTest.js b/test/TemplateRenderPugTest.js index 977053d87..595978d2a 100644 --- a/test/TemplateRenderPugTest.js +++ b/test/TemplateRenderPugTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } diff --git a/test/TemplateRenderTest.js b/test/TemplateRenderTest.js index 064abdf9a..cf490286b 100644 --- a/test/TemplateRenderTest.js +++ b/test/TemplateRenderTest.js @@ -5,7 +5,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); function getNewTemplateRender(name, inputDir) { let eleventyConfig = new TemplateConfig(); - let tr = new TemplateRender(name, inputDir); + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } From 2df5f88a1de657b0302ca484b419f2358d6f801b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Feb 2021 20:33:18 -0600 Subject: [PATCH 336/746] The last one? --- src/EleventyFiles.js | 2 +- src/TemplatePassthroughManager.js | 16 +++--- test/EleventyFilesTest.js | 2 +- test/TemplatePassthroughManagerTest.js | 77 ++++++++++++++------------ 4 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 28c22dc24..4582878dd 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -139,7 +139,7 @@ class EleventyFiles { } initPassthroughManager() { - let mgr = new TemplatePassthroughManager(); + let mgr = new TemplatePassthroughManager(this.eleventyConfig); mgr.setInputDir(this.inputDir); mgr.setOutputDir(this.outputDir); mgr.extensionMap = this.extensionMap; diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 868387301..92571bbe8 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -1,15 +1,21 @@ -const config = require("./Config"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); const TemplatePassthrough = require("./TemplatePassthrough"); const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthroughManager"); +class TemplatePassthroughManagerConfigError extends EleventyBaseError {} class TemplatePassthroughManagerCopyError extends EleventyBaseError {} class TemplatePassthroughManager { - constructor() { - this.config = config.getConfig(); + constructor(eleventyConfig) { + if (!eleventyConfig) { + throw new TemplatePassthroughManagerConfigError( + "Missing `config` argument." + ); + } + this.eleventyConfig = eleventyConfig; + this.config = eleventyConfig.getConfig(); this.reset(); } @@ -19,10 +25,6 @@ class TemplatePassthroughManager { debug("Resetting counts to 0"); } - setConfig(configOverride) { - this.config = configOverride || {}; - } - set extensionMap(extensionMap) { this._extensionMap = extensionMap; } diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 160765433..0fa5bfcba 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -660,7 +660,7 @@ test("Glob Watcher Files with Config Passthroughs (one template format)", async ); evf.init(); - let mgr = new TemplatePassthroughManager(); + let mgr = new TemplatePassthroughManager(eleventyConfig); mgr.setInputDir("test/stubs"); mgr.setOutputDir("test/stubs/_site"); mgr.setConfig({ diff --git a/test/TemplatePassthroughManagerTest.js b/test/TemplatePassthroughManagerTest.js index 6b4aae5c6..b729f73fe 100644 --- a/test/TemplatePassthroughManagerTest.js +++ b/test/TemplatePassthroughManagerTest.js @@ -1,26 +1,25 @@ const test = require("ava"); const fs = require("fs-extra"); const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); +const TemplateConfig = require("../src/TemplateConfig"); test("Get paths from Config", async (t) => { - let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughCopies: { - img: true, - }, - }); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + img: true, + }; + let mgr = new TemplatePassthroughManager(eleventyConfig); t.deepEqual(mgr.getConfigPaths(), [{ inputPath: "./img", outputPath: true }]); }); test("isPassthroughCopyFile", async (t) => { - let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughCopies: { - img: true, - fonts: true, - }, - }); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + img: true, + fonts: true, + }; + let mgr = new TemplatePassthroughManager(eleventyConfig); t.true(mgr.isPassthroughCopyFile([], "./img/test.png")); t.true(mgr.isPassthroughCopyFile([], "./fonts/Roboto.woff")); @@ -35,14 +34,13 @@ test("isPassthroughCopyFile", async (t) => { }); test("Get glob paths from config", async (t) => { - let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughCopies: { - "test/stubs/img": true, - "test/stubs/img/**": "./", - "test/stubs/img/*.js": "./", - }, - }); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + "test/stubs/img": true, + "test/stubs/img/**": "./", + "test/stubs/img/*.js": "./", + }; + let mgr = new TemplatePassthroughManager(eleventyConfig); t.deepEqual(mgr.getConfigPathGlobs(), [ "./test/stubs/img/**", @@ -52,45 +50,52 @@ test("Get glob paths from config", async (t) => { }); test("Get file paths", async (t) => { - let mgr = new TemplatePassthroughManager(); + let eleventyConfig = new TemplateConfig(); + let mgr = new TemplatePassthroughManager(eleventyConfig); + t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), ["test.png"]); }); test("Get file paths (filter out real templates)", async (t) => { - let mgr = new TemplatePassthroughManager(); + let eleventyConfig = new TemplateConfig(); + let mgr = new TemplatePassthroughManager(eleventyConfig); t.deepEqual(mgr.getNonTemplatePaths(["test.njk"]), []); }); test("Get file paths (filter out real templates), multiple", async (t) => { - let mgr = new TemplatePassthroughManager(); + let eleventyConfig = new TemplateConfig(); + let mgr = new TemplatePassthroughManager(eleventyConfig); t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.png"]), ["test.png"]); }); test("Get file paths with a js file (filter out real templates), multiple", async (t) => { - let mgr = new TemplatePassthroughManager(); + let eleventyConfig = new TemplateConfig(); + let mgr = new TemplatePassthroughManager(eleventyConfig); t.deepEqual(mgr.getNonTemplatePaths(["test.njk", "test.js"]), ["test.js"]); }); // This test used to be for passthroughFileCopy: false in config test("Get file paths (one image path)", async (t) => { - let mgr = new TemplatePassthroughManager(); + let eleventyConfig = new TemplateConfig(); + let mgr = new TemplatePassthroughManager(eleventyConfig); + t.deepEqual(mgr.getNonTemplatePaths(["test.png"]), ["test.png"]); }); test("Naughty paths outside of project dir", async (t) => { - let mgr = new TemplatePassthroughManager(); - mgr.setConfig({ - passthroughCopies: { - "../static": true, - "../*": "./", - "./test/stubs/template-passthrough2/static/*.css": "./", - "./test/stubs/template-passthrough2/static/*.js": "../../", - "./test/stubs/template-passthrough2/img.jpg": "../../", - }, - }); + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + "../static": true, + "../*": "./", + "./test/stubs/template-passthrough2/static/*.css": "./", + "./test/stubs/template-passthrough2/static/*.js": "../../", + "./test/stubs/template-passthrough2/img.jpg": "../../", + }; + + let mgr = new TemplatePassthroughManager(eleventyConfig); await t.throwsAsync(async function () { for (let path of mgr.getConfigPaths()) { From 7dc72109a81e42b49013a3cbba7bfd9a4e3409c2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Feb 2021 21:30:00 -0600 Subject: [PATCH 337/746] Finishes config refactor. --- src/Config.js | 15 --------------- src/Filters/Url.js | 8 +++++--- src/TemplateConfig.js | 2 +- src/defaultConfig.js | 7 ++++++- test/EleventyFilesTest.js | 8 +++----- test/EleventyTest.js | 12 ++++++++++++ test/TemplateWriterTest.js | 14 ++++++-------- test/UrlTest.js | 18 ++++++++++++++---- 8 files changed, 47 insertions(+), 37 deletions(-) delete mode 100644 src/Config.js diff --git a/src/Config.js b/src/Config.js deleted file mode 100644 index 51448f3ac..000000000 --- a/src/Config.js +++ /dev/null @@ -1,15 +0,0 @@ -const TemplateConfig = require("./TemplateConfig"); -const debug = require("debug")("Eleventy:Config"); - -/** - * @module 11ty/eleventy/Config - */ - -debug("Setting up global TemplateConfig."); -/** - * Provides global TemplateConfig. - * @type {module:11ty/eleventy/TemplateConfig~TemplateConfig} - */ -let config = new TemplateConfig(); - -module.exports = config; diff --git a/src/Filters/Url.js b/src/Filters/Url.js index e8824329d..5899a687c 100644 --- a/src/Filters/Url.js +++ b/src/Filters/Url.js @@ -1,7 +1,8 @@ const validUrl = require("valid-url"); const TemplatePath = require("../TemplatePath"); -module.exports = function(url, pathPrefix) { +// This is also used in the Eleventy Navigation plugin +module.exports = function (url, pathPrefix) { // work with undefined url = url || ""; @@ -14,8 +15,9 @@ module.exports = function(url, pathPrefix) { } if (pathPrefix === undefined || typeof pathPrefix !== "string") { - let projectConfig = require("../Config").getConfig(); - pathPrefix = projectConfig.pathPrefix; + // When you retrieve this with config.getFilter("url") it + // grabs the pathPrefix argument from your config for you. + throw new Error("pathPrefix (String) is required in the `url` filter."); } let normUrl = TemplatePath.normalizeUrlPath(url); diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 58c79b7af..dad578c42 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -145,7 +145,7 @@ class TemplateConfig { this.rootConfig = this.customRootConfig || require("./defaultConfig.js"); if (typeof this.rootConfig === "function") { - this.rootConfig = this.rootConfig(this.userConfig); + this.rootConfig = this.rootConfig.call(this, this.userConfig); // debug( "rootConfig is a function, after calling, this.userConfig is %o", this.userConfig ); } debug("rootConfig %o", this.rootConfig); diff --git a/src/defaultConfig.js b/src/defaultConfig.js index c00d7f151..20538b6b0 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -3,8 +3,13 @@ const slugFilter = require("./Filters/Slug"); const getCollectionItem = require("./Filters/GetCollectionItem"); module.exports = function (config) { + let eleventyConfig = this; config.addFilter("slug", slugFilter); - config.addFilter("url", urlFilter); + config.addFilter("url", function (url, pathPrefixOverride) { + let pathPrefix = + pathPrefixOverride || eleventyConfig.getConfig().pathPrefix; + return urlFilter.call(this, url, pathPrefix); + }); config.addFilter("log", console.log); config.addFilter("getCollectionItem", (collection, page) => diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 0fa5bfcba..cb98e9a8c 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -652,6 +652,9 @@ test("Glob Watcher Files with File Extension Passthroughs", async (t) => { test("Glob Watcher Files with Config Passthroughs (one template format)", async (t) => { let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + "test/stubs/img/": true, + }; let evf = new EleventyFiles( "test/stubs", "test/stubs/_site", @@ -663,11 +666,6 @@ test("Glob Watcher Files with Config Passthroughs (one template format)", async let mgr = new TemplatePassthroughManager(eleventyConfig); mgr.setInputDir("test/stubs"); mgr.setOutputDir("test/stubs/_site"); - mgr.setConfig({ - passthroughCopies: { - "test/stubs/img/": true, - }, - }); evf.setPassthroughManager(mgr); t.deepEqual(evf.getGlobWatcherFiles(), [ diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 69395dcf6..fd7fb48f4 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -212,3 +212,15 @@ test.cb("Eleventy to ndjson (returns a stream)", (t) => { }); }); }); + +test("Two Eleventies, two configs!!! (config used to be a global)", async (t) => { + let elev1 = new Eleventy(); + + t.is(elev1.eleventyConfig, elev1.eleventyConfig); + t.is(elev1.config, elev1.config); + t.is(JSON.stringify(elev1.config), JSON.stringify(elev1.config)); + + let elev2 = new Eleventy(); + t.not(elev1.eleventyConfig, elev2.eleventyConfig); + t.is(JSON.stringify(elev1.config), JSON.stringify(elev2.config)); +}); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 5902a4e39..b374b70b7 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -699,6 +699,12 @@ test.skip("JavaScript with alias", async (t) => { test("Passthrough file output", async (t) => { let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + "./test/stubs/template-passthrough/static": true, + "./test/stubs/template-passthrough/static/": "./", + "./test/stubs/template-passthrough/static/**/*": "./all/", + "./test/stubs/template-passthrough/static/**/*.js": "./js/", + }; let tw = new TemplateWriter( "./test/stubs/template-passthrough/", "./test/stubs/template-passthrough/_site", @@ -708,14 +714,6 @@ test("Passthrough file output", async (t) => { ); const mgr = tw.eleventyFiles.getPassthroughManager(); - mgr.setConfig({ - passthroughCopies: { - "./test/stubs/template-passthrough/static": true, - "./test/stubs/template-passthrough/static/": "./", - "./test/stubs/template-passthrough/static/**/*": "./all/", - "./test/stubs/template-passthrough/static/**/*.js": "./js/", - }, - }); await tw.write(); diff --git a/test/UrlTest.js b/test/UrlTest.js index b3daf9419..06e3239f5 100644 --- a/test/UrlTest.js +++ b/test/UrlTest.js @@ -1,12 +1,22 @@ const test = require("ava"); +const TemplateConfig = require("../src/TemplateConfig.js"); const url = require("../src/Filters/Url.js"); +test("Test url filter passing in pathPrefix from config", (t) => { + let eleventyConfig = new TemplateConfig(); + let pp = eleventyConfig.getConfig().pathPrefix; + t.is(pp, "/"); + + t.is(url("test", pp), "test"); + t.is(url("/test", pp), "/test"); +}); + test("Test url filter without passing in pathPrefix", (t) => { - let projectConfig = require("../src/Config").getConfig(); - t.is(projectConfig.pathPrefix, "/"); + let eleventyConfig = new TemplateConfig(); + let urlFilter = eleventyConfig.userConfig.getFilter("url"); - t.is(url("test"), "test"); - t.is(url("/test"), "/test"); + t.is(urlFilter("test"), "test"); + t.is(urlFilter("/test"), "/test"); }); test("Test url filter with passthrough urls", (t) => { From e4bd01fc8db9e36ea01337146d8d7d43e461a507 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Feb 2021 21:42:01 -0600 Subject: [PATCH 338/746] Fixes #1646 --- src/Eleventy.js | 3 +-- src/Util/ConsoleLogger.js | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index c16df4c11..9242cda9d 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -855,9 +855,8 @@ Arguments: } bench.finish(); - if (to === "fs") { - this.logger.log(this.logFinished()); + this.logger.message(this.logFinished(), "info", "green", true); } debug("Finished writing templates."); diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 5c9c11742..c986fee86 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -60,8 +60,8 @@ class ConsoleLogger { return this.outputStream; } - message(message, type = "log", chalkColor = false) { - if (!this.isVerbose || process.env.DEBUG) { + message(message, type = "log", chalkColor = false, forceToConsole = false) { + if (!forceToConsole && (!this.isVerbose || process.env.DEBUG)) { debug(message); } else if (this._logger !== false) { let logger = this._logger || console; From 0013e6b13fb7738a75f0943b41712c042c191052 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Feb 2021 21:42:56 -0600 Subject: [PATCH 339/746] v1.0.0-canary.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a18226021..8a1dfd891 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.6", + "version": "1.0.0-canary.7", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 40bc8c0ba60ff7da805fe56f85c6e2ee05213dbf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 20 Feb 2021 14:52:13 -0600 Subject: [PATCH 340/746] Adds useTemplateCache option to remove all remaining globals. --- src/TemplateContent.js | 45 +++++++++++++++++++++++++++--------------- src/TemplateLayout.js | 22 ++++++++++++--------- src/UserConfig.js | 6 ++++++ 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 1b264e7b3..84e1a46f2 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -146,10 +146,16 @@ class TemplateContent { let templateBenchmark = bench.get("Template Read"); templateBenchmark.before(); - let content = TemplateContent.getCached(this.inputPath); + let content; + if (this.config.useTemplateCache) { + content = TemplateContent.getCached(this.inputPath); + } if (!content) { content = await fs.readFile(this.inputPath, "utf-8"); - TemplateContent.cache(this.inputPath, content); + + if (this.config.useTemplateCache) { + TemplateContent.cache(this.inputPath, content); + } } templateBenchmark.after(); @@ -224,27 +230,34 @@ class TemplateContent { ); try { - let [cacheable, key, cache] = this._getCompileCache(str, bypassMarkdown); - if (cacheable && cache.has(key)) { - return cache.get(key); - } - - // Compilation is async, so we eagerly cache a Promise that eventually - // resolves to the compiled function let res; - cache.set( - key, - new Promise((resolve) => { - res = resolve; - }) - ); + if (this.config.useTemplateCache) { + let [cacheable, key, cache] = this._getCompileCache( + str, + bypassMarkdown + ); + if (cacheable && cache.has(key)) { + return cache.get(key); + } + + // Compilation is async, so we eagerly cache a Promise that eventually + // resolves to the compiled function + cache.set( + key, + new Promise((resolve) => { + res = resolve; + }) + ); + } let templateBenchmark = bench.get("Template Compile"); templateBenchmark.before(); let fn = await this.templateRender.getCompiledTemplate(str); templateBenchmark.after(); debugDev("%o getCompiledTemplate function created", this.inputPath); - res(fn); + if (this.config.useTemplateCache && res) { + res(fn); + } return fn; } catch (e) { debug(`Having trouble compiling template ${this.inputPath}: %O`, str); diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index 2c3d1929d..eaeba7e2f 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -36,16 +36,20 @@ class TemplateLayout extends TemplateContent { } static getTemplate(key, inputDir, config, extensionMap) { - let fullKey = TemplateLayout.resolveFullKey(key, inputDir); - if (templateCache.has(fullKey)) { - debugDev("Found %o in TemplateCache", key); - return templateCache.get(fullKey); + if (config.useTemplateCache) { + let fullKey = TemplateLayout.resolveFullKey(key, inputDir); + if (templateCache.has(fullKey)) { + debugDev("Found %o in TemplateCache", key); + return templateCache.get(fullKey); + } + + let tmpl = new TemplateLayout(key, inputDir, extensionMap, config); + templateCache.add(fullKey, tmpl); + + return tmpl; + } else { + return new TemplateLayout(key, inputDir, extensionMap, config); } - - let tmpl = new TemplateLayout(key, inputDir, extensionMap, config); - templateCache.add(fullKey, tmpl); - - return tmpl; } async getTemplateLayoutMapEntry() { diff --git a/src/UserConfig.js b/src/UserConfig.js index 61ef0c865..083b44d9c 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -65,6 +65,7 @@ class UserConfig { this.dataExtensions = new Map(); this.quietMode = false; + this.useTemplateCache = true; } versionCheck(expected) { @@ -660,6 +661,10 @@ class UserConfig { this.dataExtensions.set(formatExtension, formatParser); } + setUseTemplateCache(bypass) { + this.useTemplateCache = !!bypass; + } + getMergingConfigObject() { return { templateFormats: this.templateFormats, @@ -704,6 +709,7 @@ class UserConfig { extensionMap: this.extensionMap, quietMode: this.quietMode, events: this.events, + useTemplateCache: this.useTemplateCache, }; } } From e7f94fbe4ed35e4aedb92e4e0adc2d67ddf550d9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 20 Feb 2021 14:52:56 -0600 Subject: [PATCH 341/746] v1.0.0-canary.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8a1dfd891..8f229629c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.7", + "version": "1.0.0-canary.8", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 2bc2da2b6a1b8be93bc30f2df1ed5cadc16851a1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 21 Feb 2021 14:32:07 -0600 Subject: [PATCH 342/746] More tests for addGlobalData --- src/TemplateData.js | 7 ++++--- test/TemplateDataTest.js | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 91676d832..20f655c93 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -280,13 +280,14 @@ class TemplateData { let globalData = {}; if (this.config.globalData) { let keys = Object.keys(this.config.globalData); - for (let j = 0; j < keys.length; j++) { - let returnValue = this.config.globalData[keys[j]]; + for (let key of keys) { + let returnValue = this.config.globalData[key]; if (typeof returnValue === "function") { returnValue = await returnValue(); } - globalData[keys[j]] = returnValue; + + globalData[key] = returnValue; } } return globalData; diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 671444682..1fb819699 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -448,3 +448,24 @@ test("Parent directory for data (Issue #337)", async (t) => { }, }); }); + +test("addGlobalData values", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.addGlobalData("myFunction", () => "fn-value"); + eleventyConfig.userConfig.addGlobalData("myPromise", () => + Promise.resolve("promise-value") + ); + eleventyConfig.userConfig.addGlobalData("myAsync", async () => + Promise.resolve("promise-value") + ); + + let dataObj = new TemplateData( + "./test/stubs-global-data-config-api/", + eleventyConfig + ); + let data = await dataObj.getData(); + + t.is(data.myFunction, "fn-value"); + t.is(data.myPromise, "promise-value"); + t.is(data.myAsync, "promise-value"); +}); From eb0699308f3420b264a23c6eef151c806c382235 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 21 Feb 2021 14:33:13 -0600 Subject: [PATCH 343/746] Match to the docs example --- test/TemplateDataTest.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 1fb819699..cdb67b993 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -452,9 +452,11 @@ test("Parent directory for data (Issue #337)", async (t) => { test("addGlobalData values", async (t) => { let eleventyConfig = new TemplateConfig(); eleventyConfig.userConfig.addGlobalData("myFunction", () => "fn-value"); - eleventyConfig.userConfig.addGlobalData("myPromise", () => - Promise.resolve("promise-value") - ); + eleventyConfig.userConfig.addGlobalData("myPromise", () => { + return new Promise((resolve) => { + setTimeout(resolve, 100, "promise-value"); + }); + }); eleventyConfig.userConfig.addGlobalData("myAsync", async () => Promise.resolve("promise-value") ); From b183f8bc3434633427c16c3a23b9f5cdd29e2fb8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 21 Feb 2021 15:29:47 -0600 Subject: [PATCH 344/746] =?UTF-8?q?Fixed=20to=20avoid=20duplicate=20work?= =?UTF-8?q?=20that=20happened=20when=20you=20used=20a=20config=20file=20th?= =?UTF-8?q?at=20wasn=E2=80=99t=20named=20.eleventy.js.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd.js | 2 +- src/Eleventy.js | 26 +++++++------------------- src/TemplateConfig.js | 14 ++++++++++++-- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/cmd.js b/cmd.js index 9bfc96e00..146a81c0c 100755 --- a/cmd.js +++ b/cmd.js @@ -67,6 +67,7 @@ try { let elev = new Eleventy(argv.input, argv.output, { // --quiet and --quiet=true both resolve to true quietMode: argv.quiet, + configPath: argv.config, }); // reuse ErrorHandler instance in Eleventy @@ -77,7 +78,6 @@ try { elev.setIsVerbose(false); } - elev.setConfigPathOverride(argv.config); elev.setPathPrefix(argv.pathprefix); elev.setDryRun(argv.dryrun); elev.setIncrementalBuild(argv.incremental); diff --git a/src/Eleventy.js b/src/Eleventy.js index 9242cda9d..6c40d73bc 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -34,18 +34,21 @@ const debug = require("debug")("Eleventy"); class Eleventy { constructor(input, output, options = {}, eleventyConfig = null) { if (!eleventyConfig) { - this.eleventyConfig = new TemplateConfig(); + this.eleventyConfig = new TemplateConfig(null, options.configPath); } else { this.eleventyConfig = eleventyConfig; + if (options.configPath) { + this.eleventyConfig.setProjectConfigPath(options.configPath); + } } - this.config = this.eleventyConfig.getConfig(); - /** * @member {String} - The path to Eleventy's config file. * @default null */ - this.configPath = null; + this.configPath = options.configPath; + + this.config = this.eleventyConfig.getConfig(); /** * @member {Boolean} - Was verbose mode overwritten? @@ -195,21 +198,6 @@ class Eleventy { this.watchTargets = watchTargets; } - /** - * Updates the config path. - * - * @method - * @param {String} configPath - The new config path. - */ - setConfigPathOverride(configPath) { - if (configPath) { - this.configPath = configPath; - - this.eleventyConfig.setProjectConfigPath(configPath); - this.config = this.eleventyConfig.getConfig(); - } - } - /** * Restarts Eleventy. * diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index dad578c42..8ebe86bf2 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -6,6 +6,7 @@ const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); const UserConfig = require("./UserConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); +const debugDev = require("debug")("Dev:Eleventy:TemplateConfig"); const deleteRequireCache = require("./Util/DeleteRequireCache"); /** @@ -106,6 +107,7 @@ class TemplateConfig { */ getConfig() { if (!this.hasConfigMerged) { + debugDev("Merging via getConfig (first time)"); this.config = this.mergeConfig(this.localProjectConfigPath); this.hasConfigMerged = true; } @@ -120,7 +122,13 @@ class TemplateConfig { setProjectConfigPath(path) { this.localProjectConfigPath = path; - this.config = this.mergeConfig(path); + if (this.hasConfigMerged) { + // merge it again + debugDev( + "Merging in getConfig again after setting the local project config path." + ); + this.config = this.mergeConfig(path); + } } /** @@ -163,6 +171,7 @@ class TemplateConfig { TemplatePath.getWorkingDir(), localProjectConfigPath ); + debug(`Merging config with ${path}`); if (fs.existsSync(path)) { @@ -184,11 +193,12 @@ class TemplateConfig { typeof localConfig.then === "function" ) { throw new EleventyConfigError( - `Error in your Eleventy config file '${path}': Returning a promise is not supported` + `Error in your Eleventy config file '${path}': Returning a promise is not yet supported.` ); } } + // Still using removed `filters`? this was renamed to transforms if ( localConfig && localConfig.filters !== undefined && From a9a7c01aa377af21ed4b0fac824cb953698014cf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 21 Feb 2021 15:30:08 -0600 Subject: [PATCH 345/746] v1.0.0-canary.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f229629c..38c8c1ece 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.8", + "version": "1.0.0-canary.9", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 0603e7159c279dd97ec7fef71cec49f3cbd6fe23 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Feb 2021 11:21:16 -0600 Subject: [PATCH 346/746] Empty dir --- test/stubs-global-data-config-api/empty.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/stubs-global-data-config-api/empty.txt diff --git a/test/stubs-global-data-config-api/empty.txt b/test/stubs-global-data-config-api/empty.txt new file mode 100644 index 000000000..e69de29bb From 1c55ddbd7577cffd9a85ea893fa5ec4c3d3d8ce0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Feb 2021 16:11:46 -0600 Subject: [PATCH 347/746] Adds `config` option to Eleventy constructor. Pass `addGlobalData` results to global data functions. More useTemplateCache forks --- package.json | 2 +- src/Eleventy.js | 5 +++++ src/Engines/Nunjucks.js | 9 +++++++-- src/Template.js | 2 +- src/TemplateConfig.js | 2 ++ src/TemplateContent.js | 9 +++++++++ src/TemplateData.js | 6 +++--- src/TemplateEngineManager.js | 5 +++-- src/TemplateLayout.js | 6 ++++-- src/TemplateMap.js | 1 + src/TemplateWriter.js | 2 +- 11 files changed, 37 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 38c8c1ece..fd72984b0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.9", + "version": "1.0.0-canary.10", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" diff --git a/src/Eleventy.js b/src/Eleventy.js index 6c40d73bc..60c09305f 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -42,6 +42,11 @@ class Eleventy { } } + if (options.config && typeof options.config === "function") { + // TODO use return object here? + options.config(this.eleventyConfig.userConfig); + } + /** * @member {String} - The path to Eleventy's config file. * @default null diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 352763644..1ece968fb 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -26,6 +26,7 @@ class Nunjucks extends TemplateEngine { } ) ); + this.setEngineLib(this.njkEnv); this.addFilters(this.config.nunjucksFilters); @@ -255,11 +256,15 @@ class Nunjucks extends TemplateEngine { }; } + // for(let loader of this.njkEnv.loaders) { + // loader.cache = {}; + // } + let tmpl; if (!inputPath || inputPath === "njk" || inputPath === "md") { - tmpl = NunjucksLib.compile(str, this.njkEnv); + tmpl = new NunjucksLib.Template(str, this.njkEnv, null, true); } else { - tmpl = NunjucksLib.compile(str, this.njkEnv, inputPath); + tmpl = new NunjucksLib.Template(str, this.njkEnv, inputPath, true); } return async function (data) { return new Promise(function (resolve, reject) { diff --git a/src/Template.js b/src/Template.js index bc24b0a2d..40f3f95f0 100755 --- a/src/Template.js +++ b/src/Template.js @@ -695,7 +695,7 @@ class Template extends TemplateContent { this.outputDir, this.templateData, this.extensionMap, - this.config + this.eleventyConfig ); tmpl.logger = this.logger; diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 8ebe86bf2..8456f253d 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -86,6 +86,7 @@ class TemplateConfig { * Resets the configuration. */ reset() { + debugDev("Resetting configuration: TemplateConfig and UserConfig."); this.userConfig.reset(); this.initializeRootConfig(); this.config = this.mergeConfig(this.localProjectConfigPath); @@ -209,6 +210,7 @@ class TemplateConfig { ); } } catch (err) { + // TODO the error message here is bad and I feel bad (needs more accurate info) throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + (err.message.includes("Cannot find module") diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 84e1a46f2..a017f5df7 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -61,6 +61,15 @@ class TemplateContent { return this._config; } + get eleventyConfig() { + if (this._config instanceof TemplateConfig) { + return this._config; + } + throw new TemplateContentConfigError( + "Tried to get an eleventyConfig but none was found." + ); + } + get engine() { return this.templateRender.engine; } diff --git a/src/TemplateData.js b/src/TemplateData.js index 20f655c93..a1a55e2db 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -296,7 +296,7 @@ class TemplateData { async getData() { let rawImports = this.getRawImports(); - let initialGlobalData = await this.getInitialGlobalData(); + this.configApiGlobalData = await this.getInitialGlobalData(); if (!this.globalData) { let globalJson = await this.getAllGlobalData(); @@ -304,7 +304,7 @@ class TemplateData { // OK: Shallow merge when combining rawImports (pkg) with global data files this.globalData = Object.assign( {}, - initialGlobalData, + this.configApiGlobalData, globalJson, rawImports ); @@ -448,7 +448,7 @@ class TemplateData { let returnValue = require(localPath); if (typeof returnValue === "function") { - returnValue = await returnValue(); + returnValue = await returnValue(this.configApiGlobalData || {}); } dataBench.after(); diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 63278fc6b..f77b9cdcf 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -2,12 +2,12 @@ const EleventyBaseError = require("./EleventyBaseError"); class TemplateEngineManagerConfigError extends EleventyBaseError {} class TemplateEngineManager { constructor(config) { - this.engineCache = {}; - if (!config) { throw new TemplateEngineManagerConfigError("Missing `config` argument."); } this.config = config; + + this.engineCache = {}; } get keyToClassNameMap() { @@ -57,6 +57,7 @@ class TemplateEngineManager { let path = "./Engines/" + this.getClassNameFromTemplateKey(name); const cls = require(path); + let instance = new cls(name, includesDir, this.config); instance.extensionMap = extensionMap; instance.engineManager = this; diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index eaeba7e2f..f92184ae6 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -115,7 +115,7 @@ class TemplateLayout extends TemplateContent { } async getCompiledLayoutFunctions() { - if (this.compileCache) { + if (this.config.useTemplateCache && this.compileCache) { return this.compileCache; } @@ -128,7 +128,9 @@ class TemplateLayout extends TemplateContent { ) ); } - this.compileCache = fns; + if (this.config.useTemplateCache) { + this.compileCache = fns; + } return fns; } diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 8b6f90f88..c0aee0b56 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -37,6 +37,7 @@ class TemplateMap { get userConfig() { if (!this._userConfig) { this.config = this.eleventyConfig.getConfig(); + // TODO use this.config for this, need to add collections to mergable props in userconfig this._userConfig = this.eleventyConfig.userConfig; } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 607300ae8..f27f88293 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -162,7 +162,7 @@ class TemplateWriter { this.outputDir, this.templateData, this.extensionMap, - this.config + this.eleventyConfig ); tmpl.logger = this.logger; From f39b93a2c372473f6d8dc4952d3e761b94a65423 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 23 Feb 2021 22:58:25 -0600 Subject: [PATCH 348/746] Delete entries from template cache when there are errors! --- src/TemplateCache.js | 6 ++++++ src/TemplateContent.js | 4 ++++ src/TemplateLayout.js | 36 +++++++++++++++++++----------------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/TemplateCache.js b/src/TemplateCache.js index 163b27b0f..70b155652 100644 --- a/src/TemplateCache.js +++ b/src/TemplateCache.js @@ -29,6 +29,12 @@ class TemplateCache { return this.cache[key]; } + + remove(key) { + if (this.cache[key]) { + delete this.cache[key]; + } + } } // singleton diff --git a/src/TemplateContent.js b/src/TemplateContent.js index a017f5df7..058d90490 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -269,6 +269,10 @@ class TemplateContent { } return fn; } catch (e) { + let [cacheable, key, cache] = this._getCompileCache(str, bypassMarkdown); + if (cacheable) { + cache.delete(key); + } debug(`Having trouble compiling template ${this.inputPath}: %O`, str); throw new TemplateContentCompileError( `Having trouble compiling template ${this.inputPath}`, diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index f92184ae6..99761f777 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -44,6 +44,7 @@ class TemplateLayout extends TemplateContent { } let tmpl = new TemplateLayout(key, inputDir, extensionMap, config); + debugDev("Added %o to TemplateCache", key); templateCache.add(fullKey, tmpl); return tmpl; @@ -55,6 +56,7 @@ class TemplateLayout extends TemplateContent { async getTemplateLayoutMapEntry() { return { key: this.dataKeyLayoutPath, + inputDir: this.inputDir, template: this, frontMatterData: await this.getFrontMatterData(), }; @@ -73,7 +75,7 @@ class TemplateLayout extends TemplateContent { while (mapEntry.frontMatterData && cfgKey in mapEntry.frontMatterData) { let layout = TemplateLayout.getTemplate( mapEntry.frontMatterData[cfgKey], - this.inputDir, + mapEntry.inputDir, this.config, this.extensionMap ); @@ -114,23 +116,22 @@ class TemplateLayout extends TemplateContent { return this.layoutChain; } - async getCompiledLayoutFunctions() { - if (this.config.useTemplateCache && this.compileCache) { - return this.compileCache; - } - - let map = await this.getTemplateLayoutMap(); + async getCompiledLayoutFunctions(layoutMap) { let fns = []; - for (let layoutMap of map) { - fns.push( - await layoutMap.template.compile( - await layoutMap.template.getPreRender() - ) - ); - } - if (this.config.useTemplateCache) { - this.compileCache = fns; + try { + for (let layoutEntry of layoutMap) { + fns.push( + await layoutEntry.template.compile( + await layoutEntry.template.getPreRender() + ) + ); + } + } catch (e) { + debugDev("Clearing TemplateCache after error."); + templateCache.clear(); + return Promise.reject(e); } + return fns; } @@ -153,7 +154,8 @@ class TemplateLayout extends TemplateContent { async render(data, templateContent) { data = TemplateLayout.augmentDataWithContent(data, templateContent); - let fns = await this.getCompiledLayoutFunctions(); + let layoutMap = await this.getTemplateLayoutMap(); + let fns = await this.getCompiledLayoutFunctions(layoutMap); for (let fn of fns) { templateContent = await fn(data); data = TemplateLayout.augmentDataWithContent(data, templateContent); From 199303572c1986ce2c2327da5320359d4c77c336 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 23 Feb 2021 23:00:05 -0600 Subject: [PATCH 349/746] Fixes #1646. --- cmd.js | 48 ++++++++++++++++++----------- src/Eleventy.js | 61 ++++++++++++++++++++++--------------- src/EleventyErrorHandler.js | 27 +++++++++++----- src/TemplateWriter.js | 4 +-- src/Util/ConsoleLogger.js | 13 +++++--- 5 files changed, 96 insertions(+), 57 deletions(-) diff --git a/cmd.js b/cmd.js index 146a81c0c..e3140807d 100755 --- a/cmd.js +++ b/cmd.js @@ -52,7 +52,7 @@ try { const Eleventy = require("./src/Eleventy"); process.on("unhandledRejection", (error, promise) => { - errorHandler.error(error, `Unhandled rejection in promise (${promise})`); + errorHandler.error(error, "Unhandled rejection in promise"); }); process.on("uncaughtException", (error) => { errorHandler.fatal(error, "Uncaught exception"); @@ -86,42 +86,54 @@ try { // careful, we can’t use async/await here to error properly // with old node versions in `please-upgrade-node` above. - elev - .init() - .then(function () { + elev.init().then(function () { + try { if (argv.version) { console.log(elev.getVersion()); } else if (argv.help) { console.log(elev.getHelp()); } else if (argv.serve) { - elev.watch().then(function () { - elev.serve(argv.port); - }); + let startBrowsersync = true; + elev + .watch() + .catch((e) => { + // Build failed but error message already displayed. + startBrowsersync = false; + console.log("Watch catch"); + }) + .then(function () { + if (startBrowsersync) { + elev.serve(argv.port); + } + }); } else if (argv.watch) { - elev.watch(); + elev.watch().catch((e) => { + console.log("watch catch 2"); + }); } else { if (argv.to === "json") { elev.toJSON().then(function (result) { console.log(JSON.stringify(result, null, 2)); }); } else if (argv.to === "ndjson") { - elev - .toNDJSON() - .then(function (stream) { - stream.pipe(process.stdout); - }) - .catch(errorHandler.fatal.bind(errorHandler)); + elev.toNDJSON().then(function (stream) { + stream.pipe(process.stdout); + }); } else if (!argv.to || argv.to === "fs") { elev.write(); } else { throw new EleventyCommandCheckError( - `Invalid --to value: ${argv.to}. Supported values: \`fs\`, \`json\`, and \`ndjson\`.` + `Invalid --to value: ${argv.to}. Supported values: \`fs\` (default), \`json\`, and \`ndjson\`.` ); } } - }) - .catch(errorHandler.fatal.bind(errorHandler)); + } catch (e) { + errorHandler.fatal(e, "Eleventy CLI Error"); + } + }); + // unlikely because we handle a lot of errors internally in Eleventy + // .catch(errorHandler.fatal.bind(errorHandler)); } catch (e) { let errorHandler = new EleventyErrorHandler(); - errorHandler.fatal(e, "Eleventy fatal error"); + errorHandler.fatal(e, "Eleventy CLI Fatal Error"); } diff --git a/src/Eleventy.js b/src/Eleventy.js index 60c09305f..7ee57dc5a 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -537,7 +537,8 @@ Arguments: } } - await this.write(); + let writeResult = await this.write(); + let hasError = !!writeResult.error; this.writer.resetIncrementalFile(); @@ -699,7 +700,11 @@ Arguments: // Note that watching indirectly depends on this for fetching dependencies from JS files // See: TemplateWriter:pathCache and EleventyWatchTargets - await this.write(); + let result = await this.write(); + if (result.error) { + // build failed—quit watch early + return Promise.reject(result.error); + } let initWatchBench = this.watcherBench.get("Start up --watch"); initWatchBench.before(); @@ -716,7 +721,7 @@ Arguments: this.watcherBench.finish("Watch"); - this.logger.log("Watching…"); + this.logger.forceLog("Watching…"); this.watcher = watcher; @@ -743,12 +748,12 @@ Arguments: }; watcher.on("change", async (path) => { - this.logger.log(`File changed: ${path}`); + this.logger.forceLog(`File changed: ${path}`); await watchRun(path); }); watcher.on("add", async (path) => { - this.logger.log(`File added: ${path}`); + this.logger.forceLog(`File added: ${path}`); await watchRun(path); }); @@ -813,10 +818,10 @@ Arguments: */ async executeBuild(to = "fs") { let ret; - - await this.config.events.emit("beforeBuild"); + let hasError = false; try { + await this.config.events.emit("beforeBuild"); let promise; if (to === "fs") { promise = this.writer.write(); @@ -834,30 +839,36 @@ Arguments: if (to === "ndjson") { // return a stream - // TODO this might return only after all the templates have been added to the stream + // TODO this might output the ndjson rows only after all the templates have been written to the stream? ret = this.logger.closeStream(to); } + await this.config.events.emit("afterBuild"); } catch (e) { - this.errorHandler.initialMessage( - "Problem writing Eleventy templates", - "error", - "red" - ); - this.errorHandler.fatal(e); - } - - bench.finish(); - if (to === "fs") { - this.logger.message(this.logFinished(), "info", "green", true); - } - debug("Finished writing templates."); + hasError = true; + ret = { + error: e, + }; + this.errorHandler.fatal(e, "Problem writing Eleventy templates"); + } finally { + // Note, this executes even though we return above in `catch` + bench.finish(); + if (to === "fs") { + this.logger.message( + this.logFinished(), + "info", + hasError ? "red" : "green", + true + ); + } + debug("Finished writing templates."); - debug(` -Getting frustrated? Have a suggestion/feature request/feedback? -I want to hear it! Open an issue: https://github.com/11ty/eleventy/issues/new`); + debug(` + Getting frustrated? Have a suggestion/feature request/feedback? + I want to hear it! Open an issue: https://github.com/11ty/eleventy/issues/new`); - return ret; + return ret; + } } } diff --git a/src/EleventyErrorHandler.js b/src/EleventyErrorHandler.js index 8b613a35b..9ad36e3df 100644 --- a/src/EleventyErrorHandler.js +++ b/src/EleventyErrorHandler.js @@ -44,13 +44,13 @@ class EleventyErrorHandler { error(e, msg) { if (msg) { - this.initialMessage(msg, "error", "red"); + this.initialMessage(msg, "error", "red", true); } - this.log(e, "error"); + this.log(e, "error", undefined, undefined, true); } //https://nodejs.org/api/process.html - log(e, type = "log", prefix = ">") { + log(e, type = "log", prefix = ">", chalkColor = "", forceToConsole = false) { let ref = e; while (ref) { let nextRef = ref.originalError; @@ -66,7 +66,9 @@ class EleventyErrorHandler { ).trim()} \`${ref.name}\` was thrown${!nextRef && ref.stack ? ":" : ""}`, - type + type, + chalkColor, + forceToConsole ); if (process.env.DEBUG) { @@ -83,18 +85,29 @@ class EleventyErrorHandler { "(Repeated output has been truncated…)" ); } - this.logger.message(prefix + stackStr.split("\n").join("\n" + prefix)); + this.logger.message( + prefix + stackStr.split("\n").join("\n" + prefix), + type, + chalkColor, + forceToConsole + ); } ref = nextRef; } } - initialMessage(message, type = "log", chalkColor = "blue") { + initialMessage( + message, + type = "log", + chalkColor = "blue", + forceToConsole = false + ) { if (message) { this.logger.message( message + ":" + (process.env.DEBUG ? "" : " (more in DEBUG output)"), type, - chalkColor + chalkColor, + forceToConsole ); } } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index f27f88293..7da9e3b4f 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -308,10 +308,8 @@ class TemplateWriter { ) { promises.push(...(await this.generateTemplates(paths))); } - return Promise.all(promises).catch((e) => { - this.errorHandler.error(e, "Error writing templates"); - throw e; + return Promise.reject(e); }); } diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index c986fee86..59569a9a7 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -32,18 +32,23 @@ class ConsoleLogger { this._logger = logger; } + log(msg) { + this.message(msg); + } + + forceLog(msg) { + this.message(msg, undefined, undefined, true); + } + warn(msg) { this.message(msg, "warn", "yellow"); } + // Is this used? error(msg) { this.message(msg, "error", "red"); } - log(msg) { - this.message(msg); - } - toStream(msg) { this.outputStream.push(msg); } From c3c9d7bf31b9f6f8c65c9884292b1d5991995313 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Mar 2021 21:54:45 -0600 Subject: [PATCH 350/746] Fixes #1677. --- package.json | 1 + src/Eleventy.js | 21 ++-- src/TemplatePassthrough.js | 119 ++++++++++++------ src/TemplatePassthroughManager.js | 104 +++++++++------ src/TemplatePath.js | 63 ++++------ test/TemplatePassthroughManagerTest.js | 56 ++++++++- test/TemplatePathTest.js | 9 +- .../avatar.png | 0 .../src/views/avatar.png | 0 9 files changed, 247 insertions(+), 126 deletions(-) create mode 100644 test/stubs/template-passthrough-duplicates/avatar.png create mode 100644 test/stubs/template-passthrough-duplicates/src/views/avatar.png diff --git a/package.json b/package.json index fd72984b0..04bf30acd 100755 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "gray-matter": "^4.0.2", "hamljs": "^0.6.2", "handlebars": "^4.7.6", + "is-glob": "^4.0.1", "liquidjs": "^9.16.1", "lodash": "^4.17.20", "luxon": "^1.25.0", diff --git a/src/Eleventy.js b/src/Eleventy.js index 7ee57dc5a..744eb3955 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -525,10 +525,13 @@ Arguments: incrementalFile, this.eleventyFiles.getIncludesDir() ); - let isLayout = TemplatePath.startsWithSubPath( - incrementalFile, - this.eleventyFiles.getLayoutsDir() - ); + + let isLayout = false; + let layoutsDir = this.eleventyFiles.getLayoutsDir(); + if (layoutsDir) { + isLayout = TemplatePath.startsWithSubPath(incrementalFile, layoutsDir); + } + let isJSDependency = this.watchTargets.isJavaScriptDependency( incrementalFile ); @@ -537,8 +540,9 @@ Arguments: } } - let writeResult = await this.write(); - let hasError = !!writeResult.error; + await this.write(); + // let writeResult = await this.write(); + // let hasError = !!writeResult.error; this.writer.resetIncrementalFile(); @@ -680,7 +684,10 @@ Arguments: { ignored: ignores, ignoreInitial: true, - // also interesting: awaitWriteFinish + awaitWriteFinish: { + stabilityThreshold: 150, + pollInterval: 25, + }, }, configOptions ); diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index 0571dd652..e3fa30278 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -1,3 +1,5 @@ +const fs = require("fs"); +const isGlob = require("is-glob"); const copy = require("recursive-copy"); const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthrough"); @@ -9,6 +11,8 @@ class TemplatePassthroughError extends EleventyBaseError {} class TemplatePassthrough { constructor(path, outputDir, inputDir) { + this.rawPath = path; + // inputPath is relative to the root of your project and not your Eleventy input directory. this.inputPath = path.inputPath; // inputDir is only used when stripping from output path in `getOutputPath` @@ -20,6 +24,10 @@ class TemplatePassthrough { this.isDryRun = false; } + getPath() { + return this.rawPath; + } + getOutputPath(inputFileFromGlob) { const { inputDir, outputDir, outputPath, inputPath } = this; @@ -60,73 +68,110 @@ class TemplatePassthrough { const files = TemplatePath.addLeadingDotSlashArray( await fastglob(glob, { caseSensitiveMatch: false, - dot: true + dot: true, }) ); bench.after(); return files; } + /* Types: + * 1. via glob, individual files found + * 2. directory, triggers an event for each file + * 3. individual file + */ async copy(src, dest, copyOptions) { if ( - TemplatePath.stripLeadingDotSlash(dest).includes( + !TemplatePath.stripLeadingDotSlash(dest).includes( TemplatePath.stripLeadingDotSlash(this.outputDir) ) ) { - let fileCopyCount = 0; - // copy() returns a promise - return copy(src, dest, copyOptions) - .on(copy.events.COPY_FILE_START, function(copyOp) { - // Access to individual files at `copyOp.src` - debug("Copying individual file %o", copyOp.src); - aggregateBench.get("Passthrough Copy File").before(); - }) - .on(copy.events.COPY_FILE_COMPLETE, function() { - fileCopyCount++; - aggregateBench.get("Passthrough Copy File").after(); - }) - .then(() => { - return fileCopyCount; - }); + return Promise.reject( + new TemplatePassthroughError( + "Destination is not in the site output directory. Check your passthrough paths." + ) + ); } - return Promise.reject( - new TemplatePassthroughError( - "Destination is not in the site output directory. Check your passthrough paths." - ) - ); + + let fileCopyCount = 0; + let map = {}; + + // returns a promise + return copy(src, dest, copyOptions) + .on(copy.events.COPY_FILE_START, function (copyOp) { + // Access to individual files at `copyOp.src` + debug("Copying individual file %o", copyOp.src); + map[copyOp.src] = copyOp.dest; + aggregateBench.get("Passthrough Copy File").before(); + }) + .on(copy.events.COPY_FILE_COMPLETE, function () { + fileCopyCount++; + aggregateBench.get("Passthrough Copy File").after(); + }) + .then(() => { + return { + count: fileCopyCount, + map, + }; + }); } async write() { + if (this.isDryRun) { + return Promise.resolve({ + count: 0, + map: {}, + }); + } + const copyOptions = { overwrite: true, dot: true, junk: false, - results: false + results: false, }; + let promises = []; - if (!this.isDryRun) { - debug("Copying %o", this.inputPath); - - // If directory or file, recursive copy - if (await TemplatePath.exists(this.inputPath)) { - // IMPORTANT: this returns a promise, does not await for promise to finish - return this.copy(this.inputPath, this.getOutputPath(), copyOptions); - } + debug("Copying %o", this.inputPath); + if (!isGlob(this.inputPath) && fs.existsSync(this.inputPath)) { + // IMPORTANT: this returns a promise, does not await for promise to finish + promises.push( + this.copy(this.inputPath, this.getOutputPath(), copyOptions) + ); + } else { // If not directory or file, attempt to get globs - const files = await this.getFiles(this.inputPath); + let files = await this.getFiles(this.inputPath); - const promises = files.map(inputFile => - this.copy(inputFile, this.getOutputPath(inputFile), copyOptions) - ); + promises = files.map((inputFile) => { + let target = this.getOutputPath(inputFile); + return this.copy(inputFile, target, copyOptions); + }); + } - return Promise.all(promises).catch(err => { + // IMPORTANT: this returns an array of promises, does not await for promise to finish + return Promise.all(promises) + .then((results) => { + // collate the count and input/output map results from the array. + let count = 0; + let map = {}; + + for (let result of results) { + count += result.count; + Object.assign(map, result.map); + } + + return { + count, + map, + }; + }) + .catch((err) => { throw new TemplatePassthroughError( `Error copying passthrough files: ${err.message}`, err ); }); - } } } diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 92571bbe8..d050fbfaa 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -3,6 +3,7 @@ const EleventyBaseError = require("./EleventyBaseError"); const TemplatePassthrough = require("./TemplatePassthrough"); const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthroughManager"); +const debugDev = require("debug")("Dev:Eleventy:TemplatePassthroughManager"); class TemplatePassthroughManagerConfigError extends EleventyBaseError {} class TemplatePassthroughManagerCopyError extends EleventyBaseError {} @@ -21,6 +22,7 @@ class TemplatePassthroughManager { reset() { this.count = 0; + this.conflictMap = {}; this.incrementalFile = null; debug("Resetting counts to 0"); } @@ -93,18 +95,39 @@ class TemplatePassthroughManager { return this.count; } - async copyPath(path) { - let pass = new TemplatePassthrough(path, this.outputDir, this.inputDir); + getTemplatePassthroughForPath(path) { + return new TemplatePassthrough(path, this.outputDir, this.inputDir); + } - if (this.incrementalFile && path.inputPath !== this.incrementalFile) { - pass.setDryRun(true); - } else { - pass.setDryRun(this.isDryRun); + async copyPassthrough(pass) { + if (!(pass instanceof TemplatePassthrough)) { + throw new TemplatePassthroughManagerCopyError( + "copyPassthrough expects an instance of TemplatePassthrough" + ); } + let path = pass.getPath(); + pass.setDryRun(this.isDryRun); + return pass .write() - .then((fileCopyCount) => { + .then(({ count, map }) => { + for (let src in map) { + let dest = map[src]; + if (this.conflictMap[dest]) { + throw new TemplatePassthroughManagerCopyError( + `Multiple passthrough copy files are trying to write to the same output file (${dest}). ${src} and ${this.conflictMap[dest]}` + ); + } + + debugDev( + "Adding %o to passthrough copy conflict map, from %o", + dest, + src + ); + this.conflictMap[dest] = src; + } + if (pass.isDryRun) { // We don’t count the skipped files as we need to iterate over them debug( @@ -112,15 +135,10 @@ class TemplatePassthroughManager { path.inputPath ); } else { - if (Array.isArray(fileCopyCount)) { - // globs - for (let count of fileCopyCount) { - this.count += count; - } - } else { - this.count += fileCopyCount; + if (count) { + this.count += count; } - debug("Copied %o (%d files)", path.inputPath, fileCopyCount || 0); + debug("Copied %o (%d files)", path.inputPath, count || 0); } }) .catch(function (e) { @@ -149,40 +167,50 @@ class TemplatePassthroughManager { return false; } - // Performance note: these can actually take a fair bit of time, but aren’t a - // bottleneck to eleventy. The copies are performed asynchronously and don’t affect eleventy - // write times in a significant way. - async copyAll(paths) { + getAllNormalizedPaths(paths) { if ( this.incrementalFile && this.isPassthroughCopyFile(paths, this.incrementalFile) ) { - return this.copyPath(this._normalizePaths(this.incrementalFile)).then( - () => { - debug( - `TemplatePassthrough --incremental copy finished. Current count: ${this.count}` - ); - } - ); + return [this._normalizePaths(this.incrementalFile)]; } - let promises = []; - debug("TemplatePassthrough copy started."); - for (let path of this.getConfigPaths()) { + let normalizedPaths = []; + + let pathsFromConfigurationFile = this.getConfigPaths(); + for (let path of pathsFromConfigurationFile) { debug("TemplatePassthrough copying from config: %o", path); - promises.push(this.copyPath(path)); + normalizedPaths.push(path); } - let passthroughPaths = this.getNonTemplatePaths(paths); - for (let path of passthroughPaths) { - let normalizedPath = this._normalizePaths(path); - debug( - `TemplatePassthrough copying from non-matching file extension: ${normalizedPath.inputPath}` - ); - promises.push(this.copyPath(normalizedPath)); + if (paths && paths.length) { + let passthroughPaths = this.getNonTemplatePaths(paths); + for (let path of passthroughPaths) { + let normalizedPath = this._normalizePaths(path); + debug( + `TemplatePassthrough copying from non-matching file extension: ${normalizedPath.inputPath}` + ); + normalizedPaths.push(normalizedPath); + } + } + + return normalizedPaths; + } + + // Performance note: these can actually take a fair bit of time, but aren’t a + // bottleneck to eleventy. The copies are performed asynchronously and don’t affect eleventy + // write times in a significant way. + async copyAll(paths) { + debug("TemplatePassthrough copy started."); + let normalizedPaths = this.getAllNormalizedPaths(paths); + let passthroughs = []; + for (let path of normalizedPaths) { + passthroughs.push(this.getTemplatePassthroughForPath(path)); } - return Promise.all(promises).then(() => { + return Promise.all( + passthroughs.map((pass) => this.copyPassthrough(pass)) + ).then(() => { debug(`TemplatePassthrough copy finished. Current count: ${this.count}`); }); } diff --git a/src/TemplatePath.js b/src/TemplatePath.js index f971b7d25..3b06f663c 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -8,7 +8,7 @@ function TemplatePath() {} /** * @returns {String} the absolute path to Eleventy’s project directory. */ -TemplatePath.getWorkingDir = function() { +TemplatePath.getWorkingDir = function () { return TemplatePath.normalize(path.resolve(".")); }; @@ -19,7 +19,7 @@ TemplatePath.getWorkingDir = function() { * @param {String} path A path * @returns {String} the directory portion of a path. */ -TemplatePath.getDir = function(path) { +TemplatePath.getDir = function (path) { if (TemplatePath.isDirectorySync(path)) { return path; } @@ -38,7 +38,7 @@ TemplatePath.getDir = function(path) { * @param {String} path A path * @returns {String} the directory portion of a path. */ -TemplatePath.getDirFromFilePath = function(path) { +TemplatePath.getDirFromFilePath = function (path) { return parsePath(path).dir || "."; }; @@ -52,7 +52,7 @@ TemplatePath.getDirFromFilePath = function(path) { * @param {String} path A path * @returns {String} the last path segment in a path */ -TemplatePath.getLastPathSegment = function(path) { +TemplatePath.getLastPathSegment = function (path) { if (!path.includes("/")) { return path; } @@ -68,7 +68,7 @@ TemplatePath.getLastPathSegment = function(path) { * @returns {String[]} an array of paths pointing to each path segment of the * provided `path`. */ -TemplatePath.getAllDirs = function(path) { +TemplatePath.getAllDirs = function (path) { // Trim a trailing slash if there is one path = path.replace(/\/$/, ""); @@ -79,7 +79,7 @@ TemplatePath.getAllDirs = function(path) { return path .split("/") .map((segment, index, array) => array.slice(0, index + 1).join("/")) - .filter(path => path !== ".") + .filter((path) => path !== ".") .reverse(); }; @@ -93,7 +93,7 @@ TemplatePath.getAllDirs = function(path) { * @param {String} thePath The path that should be normalized. * @returns {String} the normalized path. */ -TemplatePath.normalize = function(thePath) { +TemplatePath.normalize = function (thePath) { return normalize(path.normalize(thePath)); }; @@ -108,7 +108,7 @@ TemplatePath.normalize = function(thePath) { * @param {String[]} paths An arbitrary amount of path segments. * @returns {String} the normalized and joined path. */ -TemplatePath.join = function(...paths) { +TemplatePath.join = function (...paths) { return normalize(path.join(...paths)); }; @@ -120,7 +120,7 @@ TemplatePath.join = function(...paths) { * @param {String[]} urlPaths * @returns {String} a normalized URL path described by the given URL path segments. */ -TemplatePath.normalizeUrlPath = function(...urlPaths) { +TemplatePath.normalizeUrlPath = function (...urlPaths) { const urlPath = path.posix.join(...urlPaths); return urlPath.replace(/\/+$/, "/"); }; @@ -132,7 +132,7 @@ TemplatePath.normalizeUrlPath = function(...urlPaths) { * @param {String[]} paths * @returns {String} the absolute path described by the given path segments. */ -TemplatePath.absolutePath = function(...paths) { +TemplatePath.absolutePath = function (...paths) { return TemplatePath.join(TemplatePath.getWorkingDir(), ...paths); }; @@ -142,7 +142,7 @@ TemplatePath.absolutePath = function(...paths) { * @param {String} absolutePath * @returns {String} the relative path. */ -TemplatePath.relativePath = function(absolutePath) { +TemplatePath.relativePath = function (absolutePath) { return TemplatePath.stripLeadingSubPath( absolutePath, TemplatePath.getWorkingDir() @@ -155,8 +155,8 @@ TemplatePath.relativePath = function(absolutePath) { * @param {String[]} paths * @returns {String[]} */ -TemplatePath.addLeadingDotSlashArray = function(paths) { - return paths.map(path => TemplatePath.addLeadingDotSlash(path)); +TemplatePath.addLeadingDotSlashArray = function (paths) { + return paths.map((path) => TemplatePath.addLeadingDotSlash(path)); }; /** @@ -165,7 +165,7 @@ TemplatePath.addLeadingDotSlashArray = function(paths) { * @param {String} path * @returns {String} */ -TemplatePath.addLeadingDotSlash = function(path) { +TemplatePath.addLeadingDotSlash = function (path) { if (path === "." || path === "..") { return path + "/"; } @@ -183,7 +183,7 @@ TemplatePath.addLeadingDotSlash = function(path) { * @param {String} path * @returns {String} the `path` without a leading dot-slash segment. */ -TemplatePath.stripLeadingDotSlash = function(path) { +TemplatePath.stripLeadingDotSlash = function (path) { return typeof path === "string" ? path.replace(/^\.\//, "") : path; }; @@ -194,7 +194,7 @@ TemplatePath.stripLeadingDotSlash = function(path) { * @param {String} subPath A path * @returns {Boolean} whether `path` starts with `subPath`. */ -TemplatePath.startsWithSubPath = function(path, subPath) { +TemplatePath.startsWithSubPath = function (path, subPath) { path = TemplatePath.normalize(path); subPath = TemplatePath.normalize(subPath); @@ -209,7 +209,7 @@ TemplatePath.startsWithSubPath = function(path, subPath) { * @param {String} subPath A path * @returns {String} the `path` without `subPath` at the start of it. */ -TemplatePath.stripLeadingSubPath = function(path, subPath) { +TemplatePath.stripLeadingSubPath = function (path, subPath) { path = TemplatePath.normalize(path); subPath = TemplatePath.normalize(subPath); @@ -224,7 +224,7 @@ TemplatePath.stripLeadingSubPath = function(path, subPath) { * @param {String} path A path * @returns {Boolean} whether `path` points to an existing directory. */ -TemplatePath.isDirectorySync = function(path) { +TemplatePath.isDirectorySync = function (path) { return fs.existsSync(path) && fs.statSync(path).isDirectory(); }; @@ -232,8 +232,8 @@ TemplatePath.isDirectorySync = function(path) { * @param {String} path A path * @returns {Boolean} whether `path` points to an existing directory. */ -TemplatePath.isDirectory = async function(path) { - return new Promise(resolve => { +TemplatePath.isDirectory = async function (path) { + return new Promise((resolve) => { fs.stat(path, (err, stats) => { if (stats) { resolve(stats.isDirectory()); @@ -243,21 +243,6 @@ TemplatePath.isDirectory = async function(path) { }); }; -/** - * @param {String} path A path - * @returns {Boolean} whether `path` points to a existing directory or file. - */ -TemplatePath.exists = async function(path) { - return new Promise(resolve => { - fs.stat(path, (err, stats) => { - if (stats) { - resolve(true); - } - resolve(false); - }); - }); -}; - /** * Appends a recursive wildcard glob pattern to `path` * unless `path` is not a directory; then, `path` is assumed to be a file path @@ -266,7 +251,7 @@ TemplatePath.exists = async function(path) { * @param {String} path * @returns {String} */ -TemplatePath.convertToRecursiveGlobSync = function(path) { +TemplatePath.convertToRecursiveGlobSync = function (path) { if (path === "") { return "./**"; } @@ -288,7 +273,7 @@ TemplatePath.convertToRecursiveGlobSync = function(path) { * @param {String} path * @returns {String} */ -TemplatePath.convertToRecursiveGlob = async function(path) { +TemplatePath.convertToRecursiveGlob = async function (path) { if (path === "") { return "./**"; } @@ -310,7 +295,7 @@ TemplatePath.convertToRecursiveGlob = async function(path) { * @returns {String} the path’s extension if it exists; * otherwise, the empty string. */ -TemplatePath.getExtension = function(thePath) { +TemplatePath.getExtension = function (thePath) { return path.extname(thePath).replace(/^\./, ""); }; @@ -321,7 +306,7 @@ TemplatePath.getExtension = function(thePath) { * @param {String} extension * @returns {String} */ -TemplatePath.removeExtension = function(path, extension = undefined) { +TemplatePath.removeExtension = function (path, extension = undefined) { if (extension === undefined) { return path; } diff --git a/test/TemplatePassthroughManagerTest.js b/test/TemplatePassthroughManagerTest.js index b729f73fe..23f37ef36 100644 --- a/test/TemplatePassthroughManagerTest.js +++ b/test/TemplatePassthroughManagerTest.js @@ -2,6 +2,8 @@ const test = require("ava"); const fs = require("fs-extra"); const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); const TemplateConfig = require("../src/TemplateConfig"); +const EleventyFiles = require("../src/EleventyFiles"); +const EleventyExtensionMap = require("../src/EleventyExtensionMap"); test("Get paths from Config", async (t) => { let eleventyConfig = new TemplateConfig(); @@ -99,7 +101,8 @@ test("Naughty paths outside of project dir", async (t) => { await t.throwsAsync(async function () { for (let path of mgr.getConfigPaths()) { - await mgr.copyPath(path); + let pass = mgr.getTemplatePassthroughForPath(path); + await mgr.copyPassthrough(pass); } }); @@ -121,3 +124,54 @@ test("Naughty paths outside of project dir", async (t) => { t.false(result); } }); + +test("getAllNormalizedPaths", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + img: true, + }; + + let mgr = new TemplatePassthroughManager(eleventyConfig); + t.deepEqual(mgr.getAllNormalizedPaths(), [ + { inputPath: "./img", outputPath: true }, + ]); +}); + +test("getAllNormalizedPaths with globs", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + img: true, + "img/**": "./", + "img/*.js": "./", + }; + + let mgr = new TemplatePassthroughManager(eleventyConfig); + t.deepEqual(mgr.getAllNormalizedPaths(), [ + { inputPath: "./img", outputPath: true }, + { inputPath: "./img/**", outputPath: "" }, + { inputPath: "./img/*.js", outputPath: "" }, + ]); +}); + +test("Look for uniqueness on template passthrough paths #1677", async (t) => { + let formats = []; + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.passthroughCopies = { + "./test/stubs/template-passthrough-duplicates/**/*.png": "./", + }; + + let files = new EleventyFiles( + "test/stubs/template-passthrough-duplicates", + "test/stubs/template-passthrough-duplicates/_site", + formats, + eleventyConfig + ); + files.init(); + + let mgr = files.getPassthroughManager(); + await t.throwsAsync(async function () { + await mgr.copyAll(); + }); + + fs.unlinkSync("test/stubs/template-passthrough-duplicates/_site/avatar.png"); +}); diff --git a/test/TemplatePathTest.js b/test/TemplatePathTest.js index 13b563684..ed4ad2a48 100644 --- a/test/TemplatePathTest.js +++ b/test/TemplatePathTest.js @@ -1,4 +1,5 @@ const test = require("ava"); +const fs = require("fs"); const TemplatePath = require("../src/TemplatePath"); test("getDir", (t) => { @@ -321,8 +322,8 @@ test("isDirectory", async (t) => { }); test("exists", async (t) => { - t.is(await TemplatePath.exists("asdlkfjklsadjflkja"), false); - t.is(await TemplatePath.exists("test"), true); - t.is(await TemplatePath.exists("test/stubs"), true); - t.is(await TemplatePath.exists("test/stubs/.eleventyignore"), true); + t.is(fs.existsSync("asdlkfjklsadjflkja"), false); + t.is(fs.existsSync("test"), true); + t.is(fs.existsSync("test/stubs"), true); + t.is(fs.existsSync("test/stubs/.eleventyignore"), true); }); diff --git a/test/stubs/template-passthrough-duplicates/avatar.png b/test/stubs/template-passthrough-duplicates/avatar.png new file mode 100644 index 000000000..e69de29bb diff --git a/test/stubs/template-passthrough-duplicates/src/views/avatar.png b/test/stubs/template-passthrough-duplicates/src/views/avatar.png new file mode 100644 index 000000000..e69de29bb From db902d9b75004ddfc5214b9a2361ef78dfa6b70d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Mar 2021 21:55:15 -0600 Subject: [PATCH 351/746] Additional tests for relative dirs paths --- test/EleventyFilesTest.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index cb98e9a8c..29f3058e5 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -5,6 +5,42 @@ const TemplatePath = require("../src/TemplatePath"); const TemplateConfig = require("../src/TemplateConfig"); const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); +test("Dirs paths", async (t) => { + let eleventyConfig = new TemplateConfig({ + dir: { + input: "src", + includes: "includes", + data: "data", + output: "dist", + }, + }); + + let evf = new EleventyFiles("src", "dist", [], eleventyConfig); + + t.deepEqual(evf.inputDir, "src"); + t.deepEqual(evf.includesDir, "src/includes"); + t.deepEqual(evf.getDataDir(), "src/data"); + t.deepEqual(evf.outputDir, "dist"); +}); + +test("Dirs paths (relative)", async (t) => { + let eleventyConfig = new TemplateConfig({ + dir: { + input: "src", + includes: "../includes", + data: "../data", + output: "dist", + }, + }); + + let evf = new EleventyFiles("src", "dist", [], eleventyConfig); + + t.deepEqual(evf.inputDir, "src"); + t.deepEqual(evf.includesDir, "includes"); + t.deepEqual(evf.getDataDir(), "data"); + t.deepEqual(evf.outputDir, "dist"); +}); + test("getFiles", async (t) => { let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( From 8a5162785c58864ef65308c0f0d890cade0b407f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Mar 2021 22:19:11 -0600 Subject: [PATCH 352/746] #1678 --- src/Engines/Nunjucks.js | 198 ++++++++++++++++++++-------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 2829e1db7..53ffbb4d1 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -9,105 +9,105 @@ const eventBus = require("../EventBus"); * The IFFE below apply a monkey-patch to Nunjucks internals to cache * compiled templates and re-use them where possible. */ -(function () { - let templateCache = new Map(); - - let getKey = (obj) => { - return [ - obj.path || obj.tmplStr, - obj.tmplStr.length, - obj.env.asyncFilters.length, - obj.env.extensionsList - .map((e) => { - return e.__id || ""; - }) - .join(":"), - ].join(" :: "); - }; - - let evictByPath = (path) => { - let keys = templateCache.keys(); - // Likely to be slow; do we care? - for (let k of keys) { - if (k.indexOf(path) >= 0) { - templateCache.delete(k); - } - } - }; - eventBus.on("resourceModified", evictByPath); - - let _compile = NunjucksLib.Template.prototype._compile; - NunjucksLib.Template.prototype._compile = function _wrap_compile(...args) { - if (!this.compiled && !this.tmplProps && templateCache.has(getKey(this))) { - let pathProps = templateCache.get(getKey(this)); - this.blocks = pathProps.blocks; - this.rootRenderFunc = pathProps.rootRenderFunc; - this.compiled = true; - } else { - _compile.call(this, ...args); - templateCache.set(getKey(this), { - blocks: this.blocks, - rootRenderFunc: this.rootRenderFunc, - }); - } - }; - - let extensionIdCounter = 0; - let addExtension = NunjucksLib.Environment.prototype.addExtension; - NunjucksLib.Environment.prototype.addExtension = function _wrap_addExtension( - name, - ext - ) { - if (!("__id" in ext)) { - ext.__id = extensionIdCounter++; - } - return addExtension.call(this, name, ext); - }; - - // NunjucksLib.runtime.Frame.prototype.set is the hotest in-template method. - // We replace it with a version that doesn't allocate a `parts` array on - // repeat key use. - let partsCache = new Map(); - let partsFromCache = (name) => { - if (partsCache.has(name)) { - return partsCache.get(name); - } - - let parts = name.split("."); - partsCache.set(name, parts); - return parts; - }; - - let frameSet = NunjucksLib.runtime.Frame.prototype.set; - NunjucksLib.runtime.Frame.prototype.set = function _replacement_set( - name, - val, - resolveUp - ) { - let parts = partsFromCache(name); - let frame = this; - let obj = frame.variables; - - if (resolveUp) { - if ((frame = this.resolve(parts[0], true))) { - frame.set(name, val); - return; - } - } - - // A slightly faster version of the intermediate object allocation loop - let count = parts.length - 1; - let i = 0; - let id = parts[0]; - while (i < count) { - if (!obj.hasOwnProperty(id)) { - obj = obj[id] = {}; - } - id = parts[++i]; - } - obj[id] = val; - }; -})(); +// (function () { +// let templateCache = new Map(); + +// let getKey = (obj) => { +// return [ +// obj.path || obj.tmplStr, +// obj.tmplStr.length, +// obj.env.asyncFilters.length, +// obj.env.extensionsList +// .map((e) => { +// return e.__id || ""; +// }) +// .join(":"), +// ].join(" :: "); +// }; + +// let evictByPath = (path) => { +// let keys = templateCache.keys(); +// // Likely to be slow; do we care? +// for (let k of keys) { +// if (k.indexOf(path) >= 0) { +// templateCache.delete(k); +// } +// } +// }; +// eventBus.on("resourceModified", evictByPath); + +// let _compile = NunjucksLib.Template.prototype._compile; +// NunjucksLib.Template.prototype._compile = function _wrap_compile(...args) { +// if (!this.compiled && !this.tmplProps && templateCache.has(getKey(this))) { +// let pathProps = templateCache.get(getKey(this)); +// this.blocks = pathProps.blocks; +// this.rootRenderFunc = pathProps.rootRenderFunc; +// this.compiled = true; +// } else { +// _compile.call(this, ...args); +// templateCache.set(getKey(this), { +// blocks: this.blocks, +// rootRenderFunc: this.rootRenderFunc, +// }); +// } +// }; + +// let extensionIdCounter = 0; +// let addExtension = NunjucksLib.Environment.prototype.addExtension; +// NunjucksLib.Environment.prototype.addExtension = function _wrap_addExtension( +// name, +// ext +// ) { +// if (!("__id" in ext)) { +// ext.__id = extensionIdCounter++; +// } +// return addExtension.call(this, name, ext); +// }; + +// // NunjucksLib.runtime.Frame.prototype.set is the hotest in-template method. +// // We replace it with a version that doesn't allocate a `parts` array on +// // repeat key use. +// let partsCache = new Map(); +// let partsFromCache = (name) => { +// if (partsCache.has(name)) { +// return partsCache.get(name); +// } + +// let parts = name.split("."); +// partsCache.set(name, parts); +// return parts; +// }; + +// let frameSet = NunjucksLib.runtime.Frame.prototype.set; +// NunjucksLib.runtime.Frame.prototype.set = function _replacement_set( +// name, +// val, +// resolveUp +// ) { +// let parts = partsFromCache(name); +// let frame = this; +// let obj = frame.variables; + +// if (resolveUp) { +// if ((frame = this.resolve(parts[0], true))) { +// frame.set(name, val); +// return; +// } +// } + +// // A slightly faster version of the intermediate object allocation loop +// let count = parts.length - 1; +// let i = 0; +// let id = parts[0]; +// while (i < count) { +// if (!obj.hasOwnProperty(id)) { +// obj = obj[id] = {}; +// } +// id = parts[++i]; +// } +// obj[id] = val; +// }; +// })(); class EleventyShortcodeError extends EleventyBaseError {} From e24427535fdd4b058c9227b42a127d8111b4a7c1 Mon Sep 17 00:00:00 2001 From: milahu Date: Sat, 13 Mar 2021 10:52:23 +0100 Subject: [PATCH 353/746] elev.write: handle missing Eleventy.init --- src/Eleventy.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Eleventy.js b/src/Eleventy.js index 9660b82d6..b5e37371b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -828,6 +828,12 @@ Arguments: let ret; let hasError = false; + if (!this.writer) { + this.errorHandler.fatal(new Error( + "Did you call Eleventy.init to create the TemplateWriter instance? Hint: you probably didn’t." + ), "Problem writing Eleventy templates"); + } + try { await this.config.events.emit("beforeBuild"); let promise; From ed2e00e3fea84863a8a985c379f28544024faed1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Mar 2021 21:51:37 -0500 Subject: [PATCH 354/746] Fixes #1079 --- src/TemplateWriter.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 7da9e3b4f..8e955485d 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -205,11 +205,10 @@ class TemplateWriter { for (let path of paths) { if (this.extensionMap.hasEngine(path)) { promises.push( - this.templateMap.add(this._createTemplate(path)).then(() => { - debug(`${path} added to map.`); - }) + this.templateMap.add(this._createTemplate(path)) ); } + debug(`${path} begun adding to map.`); } return Promise.all(promises); From f4cb6e7d55eaa492fcbebee1fa0ecc6263eb04b6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Mar 2021 21:52:26 -0500 Subject: [PATCH 355/746] Updates a few deps. --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 466087e8b..b87425587 100755 --- a/package.json +++ b/package.json @@ -6,6 +6,9 @@ "access": "public" }, "main": "src/Eleventy.js", + "bin": { + "eleventy": "./cmd.js" + }, "license": "MIT", "engines": { "node": ">=10" @@ -37,9 +40,6 @@ "ejs", "haml" ], - "bin": { - "eleventy": "./cmd.js" - }, "scripts": { "default": "npm run test", "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/", @@ -73,7 +73,7 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.6", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.0", "ava": "^3.15.0", "husky": "^5.1.3", "ink-docstrap": "1.3.2", @@ -96,7 +96,7 @@ "chalk": "^4.1.0", "chokidar": "^3.5.1", "debug": "^4.3.1", - "dependency-graph": "^0.10.0", + "dependency-graph": "^0.11.0", "ejs": "^3.1.6", "fast-glob": "^3.2.5", "fs-extra": "^9.1.0", @@ -104,7 +104,7 @@ "hamljs": "^0.6.2", "handlebars": "^4.7.7", "is-glob": "^4.0.1", - "liquidjs": "^9.23.1", + "liquidjs": "^9.23.2", "lodash": "^4.17.21", "luxon": "^1.26.0", "markdown-it": "^12.0.4", From d6536ba13fb00e4fc2abc9fc32db38f061bff2b6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 12:55:43 -0500 Subject: [PATCH 356/746] Easy deps to upgrade. Includes Pug 2 -> 3 --- package.json | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 0e42b979e..369c8d26c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.11.1", + "version": "0.12.0", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -74,55 +74,55 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.0", "@ava/babel": "^1.0.1", - "ava": "^3.8.2", + "ava": "^3.15.0", "husky": "^4.2.5", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", - "jsdoc": "3.6.4", - "lint-staged": "^10.2.2", + "jsdoc": "3.6.6", + "lint-staged": "^10.5.4", "markdown-it-emoji": "^1.4.0", "node-sass": "^4.14.1", - "nyc": "^15.0.1", - "prettier": "^2.0.5", + "nyc": "^15.1.0", + "prettier": "^2.2.1", "rimraf": "^3.0.2", "toml": "^3.0.0", "viperhtml": "^2.17.1", - "vue": "^2.6.11", - "vue-server-renderer": "^2.6.11" + "vue": "^2.6.12", + "vue-server-renderer": "^2.6.12" }, "dependencies": { "@11ty/dependency-tree": "^1.0.0", - "browser-sync": "^2.26.13", + "browser-sync": "^2.26.14", "chalk": "^3.0.0", - "chokidar": "^3.4.0", - "debug": "^4.1.1", + "chokidar": "^3.5.1", + "debug": "^4.3.1", "dependency-graph": "^0.9.0", "ejs": "^2.7.4", - "fast-glob": "^3.2.2", + "fast-glob": "^3.2.5", "fs-extra": "^8.1.0", "gray-matter": "^4.0.2", "hamljs": "^0.6.2", - "handlebars": "^4.7.6", + "handlebars": "^4.7.7", "javascript-stringify": "^2.0.1", "liquidjs": "^6.4.3", - "lodash": "^4.17.15", - "luxon": "^1.24.1", + "lodash": "^4.17.21", + "luxon": "^1.26.0", "markdown-it": "^10.0.0", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^4.0.0", "mustache": "^2.3.2", "normalize-path": "^3.0.0", - "nunjucks": "^3.2.1", + "nunjucks": "^3.2.3", "parse-filepath": "^1.0.2", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", - "pug": "^2.0.4", - "recursive-copy": "^2.0.10", - "semver": "^7.3.2", - "slugify": "^1.4.0", + "pug": "^3.0.2", + "recursive-copy": "^2.0.11", + "semver": "^7.3.4", + "slugify": "^1.4.7", "time-require": "^0.1.2", "valid-url": "^1.0.9" }, From 2fd65a067d659221604b725d8317a72d9016fcab Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 13:13:56 -0500 Subject: [PATCH 357/746] Upgrades Husky. --- .husky/pre-commit | 1 + .husky/pre-push | 1 + package.json | 8 +------- 3 files changed, 3 insertions(+), 7 deletions(-) create mode 100644 .husky/pre-commit create mode 100644 .husky/pre-push diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 000000000..b28c372e6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npm run lint-staged \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 000000000..aaadc6135 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1 @@ +npm run test \ No newline at end of file diff --git a/package.json b/package.json index 369c8d26c..062a8a5da 100755 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.0", "@ava/babel": "^1.0.1", "ava": "^3.15.0", - "husky": "^4.2.5", + "husky": "^5.1.3", "ink-docstrap": "1.3.2", "js-yaml": "^3.13.1", "jsdoc": "3.6.6", @@ -125,11 +125,5 @@ "slugify": "^1.4.7", "time-require": "^0.1.2", "valid-url": "^1.0.9" - }, - "husky": { - "hooks": { - "pre-commit": "npm run lint-staged", - "pre-push": "npm run test" - } } } From fa9c2875634fefd58d519154ad730de7c199aeca Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 13:14:46 -0500 Subject: [PATCH 358/746] Init husky. --- .husky/.gitignore | 1 + package.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .husky/.gitignore diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 000000000..31354ec13 --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/package.json b/package.json index 062a8a5da..1b8fba787 100755 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/*.js", "test": "npx ava --verbose", "lint-staged": "lint-staged", - "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js" + "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js", + "prepare": "husky install" }, "author": { "name": "Zach Leatherman", From 32e347ab8594eb5d13fb0d38972915bf95d68627 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 13:16:42 -0500 Subject: [PATCH 359/746] Husky tasks. --- .husky/pre-commit | 3 +++ .husky/pre-push | 3 +++ 2 files changed, 6 insertions(+) mode change 100644 => 100755 .husky/pre-commit mode change 100644 => 100755 .husky/pre-push diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 index b28c372e6..fa61cb6ed --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + npm run lint-staged \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push old mode 100644 new mode 100755 index aaadc6135..e8a402fa0 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + npm run test \ No newline at end of file From 509802e5f62c08f1ec305f723310e236f1faea56 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 13:20:47 -0500 Subject: [PATCH 360/746] Cherry pick https://github.com/11ty/eleventy/commit/cf4342acabed4de9069e314add0328ccae16feb3 --- test/BenchmarkTest.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index 9e62a6a89..cdd29521f 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -6,23 +6,23 @@ function between(t, value, lowerBound, upperBound) { t.truthy(value <= upperBound); } -test.cb("Standard Benchmark", t => { +test.cb("Standard Benchmark", (t) => { let b = new Benchmark(); b.before(); - setTimeout(function() { + setTimeout(function () { b.after(); - t.truthy(b.getTotal() >= 10); + t.truthy(b.getTotal() >= 0); t.end(); - }, 10); + }, 100); }); test.cb( "Nested Benchmark (nested calls are ignored while a parent is measuring)", - t => { + (t) => { let b = new Benchmark(); b.before(); - setTimeout(function() { + setTimeout(function () { b.before(); b.after(); t.truthy(b.getTotal() <= 0.1); @@ -34,17 +34,17 @@ test.cb( } ); -test.cb("Reset Benchmark", t => { +test.cb("Reset Benchmark", (t) => { let b = new Benchmark(); b.before(); b.reset(); - setTimeout(function() { + setTimeout(function () { b.before(); b.after(); t.truthy(b.getTotal() <= 0.1); - t.throws(function() { + t.throws(function () { // throws because we reset b.after(); }); From 56f5bd4e1c58e355745867c14163ee296c4a7444 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 13:32:31 -0500 Subject: [PATCH 361/746] Upgrade some of the other deps (not all) --- package.json | 10 +++++----- test/UserDataExtensionsTest.js | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 1b8fba787..7d967b9a6 100755 --- a/package.json +++ b/package.json @@ -80,11 +80,11 @@ "ava": "^3.15.0", "husky": "^5.1.3", "ink-docstrap": "1.3.2", - "js-yaml": "^3.13.1", + "js-yaml": "^4.0.0", "jsdoc": "3.6.6", "lint-staged": "^10.5.4", - "markdown-it-emoji": "^1.4.0", - "node-sass": "^4.14.1", + "markdown-it-emoji": "^2.0.0", + "node-sass": "^5.0.0", "nyc": "^15.1.0", "prettier": "^2.2.1", "rimraf": "^3.0.2", @@ -96,10 +96,10 @@ "dependencies": { "@11ty/dependency-tree": "^1.0.0", "browser-sync": "^2.26.14", - "chalk": "^3.0.0", + "chalk": "^4.1.0", "chokidar": "^3.5.1", "debug": "^4.3.1", - "dependency-graph": "^0.9.0", + "dependency-graph": "^0.11.0", "ejs": "^2.7.4", "fast-glob": "^3.2.5", "fs-extra": "^8.1.0", diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index 0fb25447b..023ae6aec 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -4,12 +4,12 @@ let yaml = require("js-yaml"); function injectDataExtensions(dataObj) { dataObj.config.dataExtensions = new Map([ - ["yaml", s => yaml.safeLoad(s)], - ["nosj", JSON.parse] + ["yaml", (s) => yaml.load(s)], + ["nosj", JSON.parse], ]); } -test("Local data", async t => { +test("Local data", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); @@ -37,7 +37,7 @@ test("Local data", async t => { t.is(withLocalData.jsKey1, "js1"); }); -test("Local files", async t => { +test("Local files", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); let files = await dataObj.getLocalDataPaths( @@ -67,17 +67,17 @@ test("Local files", async t => { "./test/stubs-630/component-yaml/component.11tydata.nosj", "./test/stubs-630/component-yaml/component.11tydata.json", "./test/stubs-630/component-yaml/component.11tydata.cjs", - "./test/stubs-630/component-yaml/component.11tydata.js" + "./test/stubs-630/component-yaml/component.11tydata.js", ]); }); -test("Global data", async t => { +test("Global data", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); t.deepEqual(await dataObj.getGlobalDataGlob(), [ - "./test/stubs-630/_data/**/*.(nosj|yaml|json|cjs|js)" + "./test/stubs-630/_data/**/*.(nosj|yaml|json|cjs|js)", ]); let data = await dataObj.getData(); @@ -103,7 +103,7 @@ test("Global data", async t => { t.is(data.subdir.globalDataSubdir.keyyaml, "yaml"); }); -test("Global data merging and priority", async t => { +test("Global data merging and priority", async (t) => { let dataObj = new TemplateData("./test/stubs-630/"); injectDataExtensions(dataObj); From 785344c535a3c9d88b2aa37f63c31dceb58d8e9e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 14:21:05 -0500 Subject: [PATCH 362/746] Code coverage stats. --- docs-src/_data/coverage.json | 10 +++++----- docs/coverage.md | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 3fdef09ce..2217ab2ff 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,13 +1,13 @@ -{"total": {"lines":{"total":3463,"covered":3064,"skipped":0,"pct":88.48},"statements":{"total":3485,"covered":3085,"skipped":0,"pct":88.52},"functions":{"total":818,"covered":714,"skipped":0,"pct":87.29},"branches":{"total":1499,"covered":1213,"skipped":0,"pct":80.92}} +{"total": {"lines":{"total":3472,"covered":3071,"skipped":0,"pct":88.45},"statements":{"total":3493,"covered":3091,"skipped":0,"pct":88.49},"functions":{"total":820,"covered":716,"skipped":0,"pct":87.32},"branches":{"total":1503,"covered":1215,"skipped":0,"pct":80.84}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":35,"skipped":0,"pct":76.09},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":46,"covered":35,"skipped":0,"pct":76.09},"branches":{"total":21,"covered":13,"skipped":0,"pct":61.9}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":34,"skipped":0,"pct":73.91},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":46,"covered":34,"skipped":0,"pct":73.91},"branches":{"total":21,"covered":11,"skipped":0,"pct":52.38}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.78},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.78},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} ,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":46,"covered":46,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":46,"covered":46,"skipped":0,"pct":100},"branches":{"total":17,"covered":17,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.04},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.04},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.63}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.73}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":24,"covered":24,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":221,"covered":122,"skipped":0,"pct":55.2},"functions":{"total":40,"covered":20,"skipped":0,"pct":50},"statements":{"total":222,"covered":122,"skipped":0,"pct":54.95},"branches":{"total":70,"covered":30,"skipped":0,"pct":42.86}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":223,"covered":123,"skipped":0,"pct":55.16},"functions":{"total":40,"covered":20,"skipped":0,"pct":50},"statements":{"total":224,"covered":123,"skipped":0,"pct":54.91},"branches":{"total":70,"covered":30,"skipped":0,"pct":42.86}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -16,7 +16,7 @@ ,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":64,"covered":64,"skipped":0,"pct":100},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":64,"covered":64,"skipped":0,"pct":100},"branches":{"total":31,"covered":31,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":165,"covered":155,"skipped":0,"pct":93.94},"functions":{"total":40,"covered":36,"skipped":0,"pct":90},"statements":{"total":165,"covered":155,"skipped":0,"pct":93.94},"branches":{"total":61,"covered":51,"skipped":0,"pct":83.61}} ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":59,"covered":22,"skipped":0,"pct":37.29},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":59,"covered":22,"skipped":0,"pct":37.29},"branches":{"total":36,"covered":10,"skipped":0,"pct":27.78}} -,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":33,"covered":33,"skipped":0,"pct":100},"functions":{"total":16,"covered":16,"skipped":0,"pct":100},"statements":{"total":35,"covered":35,"skipped":0,"pct":100},"branches":{"total":17,"covered":15,"skipped":0,"pct":88.24}} +,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":39,"covered":39,"skipped":0,"pct":100},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":41,"covered":41,"skipped":0,"pct":100},"branches":{"total":21,"covered":19,"skipped":0,"pct":90.48}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} ,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":309,"covered":294,"skipped":0,"pct":95.15},"functions":{"total":55,"covered":54,"skipped":0,"pct":98.18},"statements":{"total":311,"covered":296,"skipped":0,"pct":95.18},"branches":{"total":115,"covered":102,"skipped":0,"pct":88.7}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} @@ -37,7 +37,7 @@ ,"/Users/zachleat/Code/eleventy/src/TemplatePermalinkNoWrite.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":80,"covered":79,"skipped":0,"pct":98.75},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":80,"covered":79,"skipped":0,"pct":98.75},"branches":{"total":46,"covered":45,"skipped":0,"pct":97.83}} ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":112,"covered":88,"skipped":0,"pct":78.57},"functions":{"total":32,"covered":23,"skipped":0,"pct":71.88},"statements":{"total":112,"covered":88,"skipped":0,"pct":78.57},"branches":{"total":28,"covered":14,"skipped":0,"pct":50}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":215,"covered":128,"skipped":0,"pct":59.53},"functions":{"total":57,"covered":26,"skipped":0,"pct":45.61},"statements":{"total":216,"covered":129,"skipped":0,"pct":59.72},"branches":{"total":88,"covered":41,"skipped":0,"pct":46.59}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":216,"covered":129,"skipped":0,"pct":59.72},"functions":{"total":57,"covered":26,"skipped":0,"pct":45.61},"statements":{"total":216,"covered":129,"skipped":0,"pct":59.72},"branches":{"total":88,"covered":41,"skipped":0,"pct":46.59}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":14,"covered":11,"skipped":0,"pct":78.57},"functions":{"total":4,"covered":1,"skipped":0,"pct":25},"statements":{"total":14,"covered":11,"skipped":0,"pct":78.57},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":34,"covered":15,"skipped":0,"pct":44.12},"functions":{"total":7,"covered":4,"skipped":0,"pct":57.14},"statements":{"total":34,"covered":15,"skipped":0,"pct":44.12},"branches":{"total":20,"covered":5,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.74},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.74},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} diff --git a/docs/coverage.md b/docs/coverage.md index 2316128dd..07c265669 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,17 +1,17 @@ -# Code Coverage for Eleventy v0.11.0 +# Code Coverage for Eleventy v0.12.0 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 88.48% | 88.52% | 87.29% | 80.92% | +| `total` | 88.45% | 88.49% | 87.32% | 80.84% | | `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | -| `src/BenchmarkGroup.js` | 76.09% | 76.09% | 66.67% | 61.9% | +| `src/BenchmarkGroup.js` | 73.91% | 73.91% | 66.67% | 52.38% | | `src/BenchmarkManager.js` | 77.78% | 77.78% | 75% | 75% | | `src/ComputedData.js` | 100% | 100% | 100% | 100% | | `src/ComputedDataProxy.js` | 98.04% | 98.04% | 100% | 90.63% | | `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.73% | | `src/ComputedDataTemplateString.js` | 100% | 100% | 100% | 83.33% | | `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 55.2% | 54.95% | 50% | 42.86% | +| `src/Eleventy.js` | 55.16% | 54.91% | 50% | 42.86% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | | `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | @@ -20,7 +20,7 @@ | `src/EleventyExtensionMap.js` | 100% | 100% | 100% | 100% | | `src/EleventyFiles.js` | 93.94% | 93.94% | 90% | 83.61% | | `src/EleventyServe.js` | 37.29% | 37.29% | 56.25% | 27.78% | -| `src/EleventyWatch.js` | 100% | 100% | 100% | 88.24% | +| `src/EleventyWatch.js` | 100% | 100% | 100% | 90.48% | | `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 93.33% | | `src/Template.js` | 95.15% | 95.18% | 98.18% | 88.7% | | `src/TemplateCache.js` | 100% | 100% | 100% | 100% | @@ -41,7 +41,7 @@ | `src/TemplatePermalinkNoWrite.js` | 100% | 100% | 100% | 100% | | `src/TemplateRender.js` | 98.75% | 98.75% | 100% | 97.83% | | `src/TemplateWriter.js` | 78.57% | 78.57% | 71.88% | 50% | -| `src/UserConfig.js` | 59.53% | 59.72% | 45.61% | 46.59% | +| `src/UserConfig.js` | 59.72% | 59.72% | 45.61% | 46.59% | | `src/defaultConfig.js` | 78.57% | 78.57% | 25% | 100% | | `src/Engines/Custom.js` | 44.12% | 44.12% | 57.14% | 25% | | `src/Engines/Ejs.js` | 94.74% | 94.74% | 85.71% | 88.89% | From e8ba00356a76087e72a71d59eeafe0cd28719e14 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 14:23:07 -0500 Subject: [PATCH 363/746] Benchmark test failure needs adjustment. --- test/BenchmarkTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index cdd29521f..c22a2fb79 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -30,7 +30,7 @@ test.cb( b.after(); t.truthy(b.getTotal() >= 10); t.end(); - }, 10); + }, 100); } ); From 608c297142b0aab8f5a83052aa14863ab1a0beb0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 14:44:52 -0500 Subject: [PATCH 364/746] Fixes https://github.com/11ty/eleventy/issues/1701 --- cmd.js | 21 +++++++++------------ docs/meta-release.md | 1 - package.json | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/cmd.js b/cmd.js index d90231c0c..54055e82c 100755 --- a/cmd.js +++ b/cmd.js @@ -1,12 +1,9 @@ #!/usr/bin/env node const pkg = require("./package.json"); -const chalk = require("chalk"); // node 8+ require("please-upgrade-node")(pkg, { - message: function(requiredVersion) { - return chalk.red( - `Eleventy requires Node ${requiredVersion}. You’ll need to upgrade to use it!` - ); - } + message: function (requiredVersion) { + return `Eleventy requires Node ${requiredVersion}. You’ll need to upgrade Node to use Eleventy!`; + }, }); if (process.env.DEBUG) { @@ -19,8 +16,8 @@ try { const argv = require("minimist")(process.argv.slice(2), { boolean: ["quiet"], default: { - quiet: null - } + quiet: null, + }, }); const Eleventy = require("./src/Eleventy"); const EleventyCommandCheck = require("./src/EleventyCommandCheck"); @@ -31,10 +28,10 @@ try { `Unhandled rejection in promise (${promise})` ); }); - process.on("uncaughtException", error => { + process.on("uncaughtException", (error) => { EleventyErrorHandler.fatal(error, "Uncaught exception"); }); - process.on("rejectionHandled", promise => { + process.on("rejectionHandled", (promise) => { EleventyErrorHandler.warn( promise, "A promise rejection was handled asynchronously" @@ -62,13 +59,13 @@ try { // with old node versions in `please-upgrade-node` above. elev .init() - .then(function() { + .then(function () { if (argv.version) { console.log(elev.getVersion()); } else if (argv.help) { console.log(elev.getHelp()); } else if (argv.serve) { - elev.watch().then(function() { + elev.watch().then(function () { elev.serve(argv.port); }); } else if (argv.watch) { diff --git a/docs/meta-release.md b/docs/meta-release.md index 837224c6f..d60f23d9c 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -26,7 +26,6 @@ ## If branch docs do not exist -1. Make sure `localDev: false` in `config.js` 1. Check in a new `11ty-website` site with updated `package.json` version. 1. Add version to 11ty-website `versions.json` 1. Commit it diff --git a/package.json b/package.json index 7d967b9a6..ea549b089 100755 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "main": "src/Eleventy.js", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "type": "opencollective", From a596d0a9efa6886aa2027a470f21f30aa6159e0c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 14:48:52 -0500 Subject: [PATCH 365/746] =?UTF-8?q?Per=20note=20on=20https://www.npmjs.com?= =?UTF-8?q?/package/please-upgrade-node#options=20to=20have=20maximum=20co?= =?UTF-8?q?mpatibility=20with=20old=20node,=20switches=20to=20good=20ol?= =?UTF-8?q?=E2=80=99=20concat.=20https://github.com/11ty/eleventy/issues/1?= =?UTF-8?q?701?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd.js b/cmd.js index 54055e82c..c60c3d803 100755 --- a/cmd.js +++ b/cmd.js @@ -2,7 +2,11 @@ const pkg = require("./package.json"); require("please-upgrade-node")(pkg, { message: function (requiredVersion) { - return `Eleventy requires Node ${requiredVersion}. You’ll need to upgrade Node to use Eleventy!`; + return ( + "Eleventy requires Node " + + requiredVersion + + ". You will need to upgrade Node to use Eleventy!" + ); }, }); From 5c840894ff031c1b22f4e9b2005d5294f0b9c6bb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 14:54:08 -0500 Subject: [PATCH 366/746] v0.12.1 --- docs/coverage.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/coverage.md b/docs/coverage.md index 07c265669..b58f71a4c 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,4 +1,4 @@ -# Code Coverage for Eleventy v0.12.0 +# Code Coverage for Eleventy v0.12.1 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | diff --git a/package.json b/package.json index ea549b089..fcb526354 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "0.12.0", + "version": "0.12.1", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 57e28374ff54f325603b0ba2dc5ca97d001f8634 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 17:25:37 -0500 Subject: [PATCH 367/746] =?UTF-8?q?Eleventy=201.0=20is=20Node=2012+=20per?= =?UTF-8?q?=20Node=E2=80=99s=20release=20cycles.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 +- docs/meta-release.md | 3 ++- package.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6590a7dec..8751ddfb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - node: ["10", "12", "14"] + node: ["12", "14"] name: Node.js ${{ matrix.node }} on ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/docs/meta-release.md b/docs/meta-release.md index 7988acc69..b1fe40421 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -23,6 +23,7 @@ 1. update minor dependencies in package.json? `npm outdated` `npm update --save` 1. npmclean aka `rm -rf node_modules && rm -f package-lock.json && npm install` +1. If the minimum Node version changed, make sure you update `package.json` engines property. 1. npm audit 1. Make sure `npx ava` runs okay 1. Update version in `package.json` @@ -33,7 +34,7 @@ 1. Bonus for 0.x branch, make sure it still works in node 8 (see `Temp/eleventy-node-8` sample project) -## If branch docs do not exist +## If Docs branch does not yet exist 1. Check in a new `11ty-website` site with updated `package.json` version. 1. Add version to 11ty-website `versions.json` diff --git a/package.json b/package.json index 946483d1d..ea165c146 100755 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "type": "opencollective", From 0c022f11c9efa0a4a4a5399648149b3330c6a6dc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 21:03:53 -0500 Subject: [PATCH 368/746] =?UTF-8?q?Simplified=20the=20test=20a=20bit,=20we?= =?UTF-8?q?=20don=E2=80=99t=20need=20to=20test=20chokidar=20here=20(and=20?= =?UTF-8?q?it=20was=20failing=20on=20GitHub=20actions)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/TemplateTest.js | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 3914075b0..a6389a52e 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -9,6 +9,7 @@ const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const EleventyErrorUtil = require("../src/EleventyErrorUtil"); const TemplateContentPrematureUseError = require("../src/Errors/TemplateContentPrematureUseError"); const normalizeNewLines = require("./Util/normalizeNewLines"); +const eventBus = require("../src/EventBus"); const getNewTemplate = require("./_getNewTemplateForTests"); @@ -2083,31 +2084,16 @@ test("Make sure layout cache takes new changes during watch (nunjucks)", async ( t.is((await tmpl.render(data)).trim(), ''); - let eventBus = require("../src/EventBus"); - let chokidar = require("chokidar"); - let watcher = chokidar.watch(filePath, { interval: 10, persistent: true }); - watcher.on("change", (path, stats) => { - eventBus.emit("resourceModified", path); - }); - await fsp.writeFile(filePath, `alert("bye");`, { encoding: "utf8" }); - // Give Chokidar time to see the change; - await new Promise((res, rej) => { - setTimeout(res, 200); - }); + eventBus.emit("resourceModified", filePath); t.is((await tmpl.render(data)).trim(), ''); - - await watcher.close(); }); test("Make sure layout cache takes new changes during watch (liquid)", async (t) => { - await fsp.writeFile( - "./test/stubs-layout-cache/_includes/include-script-2.js", - `alert("hi");`, - { encoding: "utf8" } - ); + let filePath = "./test/stubs-layout-cache/_includes/include-script-2.js"; + await fsp.writeFile(filePath, `alert("hi");`, { encoding: "utf8" }); let tmpl = getNewTemplate( "./test/stubs-layout-cache/test.liquid", @@ -2119,11 +2105,9 @@ test("Make sure layout cache takes new changes during watch (liquid)", async (t) t.is((await tmpl.render(data)).trim(), ''); - await fsp.writeFile( - "./test/stubs-layout-cache/_includes/include-script-2.js", - `alert("bye");`, - { encoding: "utf8" } - ); + await fsp.writeFile(filePath, `alert("bye");`, { encoding: "utf8" }); + + eventBus.emit("resourceModified", filePath); t.is((await tmpl.render(data)).trim(), ''); }); From e6c2f2c82b511e8f451ff34f0c7f98c396bb01ef Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 21:21:52 -0500 Subject: [PATCH 369/746] Add Node 15 to GitHub Actions (to be prepared) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8751ddfb6..c65928424 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - node: ["12", "14"] + node: ["12", "14", "15"] name: Node.js ${{ matrix.node }} on ${{ matrix.os }} steps: - uses: actions/checkout@v2 From 78f3be22b5ce20116e352adf4cec510891d9fc5b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 21:33:59 -0500 Subject: [PATCH 370/746] Convert education issues to Discussions instead --- .github/ISSUE_TEMPLATE/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 2bd8eeb4b..07f0e392b 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ contact_links: + - name: I have a question about Eleventy + url: https://github.com/11ty/eleventy/discussions/ + about: General education topics should be filed on our Discussions board e.g. “How do I do this in Eleventy?” or “Can Eleventy do this?” - name: Discord Community url: https://discord.gg/GBkBy9u about: Ask the community on Discord - - name: GitHub Discussions - url: https://github.com/11ty/eleventy/discussions/ - about: If you've got a question, start a discussion From e3729ec26e92889ea0bf0543853cff487291d791 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Mar 2021 21:34:21 -0500 Subject: [PATCH 371/746] Move these to GitHub Discussions instead. --- .github/ISSUE_TEMPLATE/education.md | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/education.md diff --git a/.github/ISSUE_TEMPLATE/education.md b/.github/ISSUE_TEMPLATE/education.md deleted file mode 100644 index 649d96224..000000000 --- a/.github/ISSUE_TEMPLATE/education.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: I have a question about Eleventy -about: General education e.g. “How do I do this in Eleventy?” or “Can Eleventy do this?” -title: "" -labels: education -assignees: "" ---- From 77f7e88476fffd6671f5c644ce9da506695ed3c4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Mar 2021 09:04:26 -0500 Subject: [PATCH 372/746] Test config getting passed around. --- src/EleventyExtensionMap.js | 3 +++ test/EleventyTest.js | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 0abc345fd..5dafa9195 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -10,6 +10,9 @@ class EleventyExtensionMap { if (!config) { throw new EleventyExtensionMapConfigError("Missing `config` argument."); } + if (config instanceof TemplateConfig) { + this.eleventyConfig = config; + } this._config = config; this.formatKeys = formatKeys; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index fd7fb48f4..bbf2157b1 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -224,3 +224,14 @@ test("Two Eleventies, two configs!!! (config used to be a global)", async (t) => t.not(elev1.eleventyConfig, elev2.eleventyConfig); t.is(JSON.stringify(elev1.config), JSON.stringify(elev2.config)); }); + +test("Config propagates to other instances correctly", async (t) => { + let elev = new Eleventy(); + await elev.init(); + + t.is(elev.extensionMap.eleventyConfig, elev.eleventyConfig); + t.is(elev.eleventyServe.config, elev.eleventyConfig); + t.is(elev.eleventyFiles.eleventyConfig, elev.eleventyConfig); + t.is(elev.templateData.eleventyConfig, elev.eleventyConfig); + t.is(elev.writer.eleventyConfig, elev.eleventyConfig); +}); From 6ecbd639c839944b161c4afe205730922b427945 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Mar 2021 09:04:49 -0500 Subject: [PATCH 373/746] Node 10 note. --- docs/meta-release.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/meta-release.md b/docs/meta-release.md index b1fe40421..f93cf5071 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -24,6 +24,7 @@ 1. update minor dependencies in package.json? `npm outdated` `npm update --save` 1. npmclean aka `rm -rf node_modules && rm -f package-lock.json && npm install` 1. If the minimum Node version changed, make sure you update `package.json` engines property. +1. Bonus: make sure the error message works correctly for Node versions less than 10. 0.12.x+ requires Node 10+. 1.x+ requires Node 12+ 1. npm audit 1. Make sure `npx ava` runs okay 1. Update version in `package.json` @@ -32,8 +33,6 @@ 1. Tag new version 1. `npm publish --access=public` -1. Bonus for 0.x branch, make sure it still works in node 8 (see `Temp/eleventy-node-8` sample project) - ## If Docs branch does not yet exist 1. Check in a new `11ty-website` site with updated `package.json` version. From 7b62af88610b49290e5b92aeea0d4976a8ede686 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Mar 2021 09:05:11 -0500 Subject: [PATCH 374/746] Make the tests a bit more resilient when creating files. --- test/TemplateWriterTest.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index b374b70b7..33eef68c0 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -425,6 +425,8 @@ test("Glob Watcher Files with Passthroughs", (t) => { }); test("Pagination and TemplateContent", async (t) => { + rimraf.sync("./test/stubs/pagination-templatecontent/_site/"); + let eleventyConfig = new TemplateConfig(); let tw = new TemplateWriter( "./test/stubs/pagination-templatecontent", @@ -698,6 +700,8 @@ test.skip("JavaScript with alias", async (t) => { }); test("Passthrough file output", async (t) => { + rimraf.sync("./test/stubs/template-passthrough/_site/"); + let eleventyConfig = new TemplateConfig(); eleventyConfig.userConfig.passthroughCopies = { "./test/stubs/template-passthrough/static": true, From 4249f48e6b20748f172a7f12b7c00ca0a565fece Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Mar 2021 17:28:24 -0500 Subject: [PATCH 375/746] Moves incremental checks around to allow `isIncrementalMatch` checks to be passed in to custom template engines. --- src/Eleventy.js | 19 +---- src/EleventyExtensionMap.js | 17 ++++- src/EleventyFiles.js | 58 ++++++++++----- src/Engines/TemplateEngine.js | 9 +++ src/TemplateContent.js | 44 ++++++++++++ src/TemplatePassthroughManager.js | 14 ++-- src/TemplateWriter.js | 113 ++++++++++++++++-------------- test/EleventyExtensionMapTest.js | 16 ++--- test/TemplateTest.js | 42 ++++++++++- test/stubs/add-extension/test.njk | 0 test/stubs/add-extension/test.txt | 0 11 files changed, 230 insertions(+), 102 deletions(-) create mode 100644 test/stubs/add-extension/test.njk create mode 100644 test/stubs/add-extension/test.txt diff --git a/src/Eleventy.js b/src/Eleventy.js index 9660b82d6..ff53faa8b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -521,24 +521,7 @@ Arguments: let incrementalFile = this.watchManager.getIncrementalFile(); if (incrementalFile) { - // TODO remove these and delegate to the template dependency graph - let isInclude = TemplatePath.startsWithSubPath( - incrementalFile, - this.eleventyFiles.getIncludesDir() - ); - - let isLayout = false; - let layoutsDir = this.eleventyFiles.getLayoutsDir(); - if (layoutsDir) { - isLayout = TemplatePath.startsWithSubPath(incrementalFile, layoutsDir); - } - - let isJSDependency = this.watchTargets.isJavaScriptDependency( - incrementalFile - ); - if (!isInclude && !isLayout && !isJSDependency) { - this.writer.setIncrementalFile(incrementalFile); - } + this.writer.setIncrementalFile(incrementalFile); } await this.write(); diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 5dafa9195..1947fc19b 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -71,7 +71,10 @@ class EleventyExtensionMap { return files; } - isFullTemplateFilename(path) { + // Warning: this would false positive on an include, but is only used + // on paths found from the file system glob search. + // TODO: Method name might just need to be renamed to something more accurate. + isFullTemplateFilePath(path) { for (let extension of this.validTemplateLanguageKeys) { if (path.endsWith(`.${extension}`)) { return true; @@ -128,6 +131,18 @@ class EleventyExtensionMap { return extensions; } + getExtensionEntriesFromKey(key) { + let entries = []; + if ("extensionMap" in this.config) { + for (let entry of this.config.extensionMap) { + if (entry.key === key) { + entries.push(entry); + } + } + } + return entries; + } + hasEngine(pathOrKey) { return !!this.getKey(pathOrKey); } diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 4582878dd..975e6cbf1 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -105,6 +105,7 @@ class EleventyFiles { restart() { this.passthroughManager.reset(); this.setupGlobs(); + this._glob = null; } /* For testing */ @@ -344,42 +345,67 @@ class EleventyFiles { ); } + // Filter out the passthrough copy paths. return this.pathCache.filter((path) => - this.extensionMap.isFullTemplateFilename(path) + this.extensionMap.isFullTemplateFilePath(path) ); } - async getFiles() { + _globSearch() { + if (this._glob) { + return this._glob; + } + let globs = this.getFileGlobs(); + // returns a promise debug("Searching for: %o", globs); + this._glob = fastglob(globs, { + caseSensitiveMatch: false, + dot: true, + }); + + return this._glob; + } + + async getFiles() { let bench = aggregateBench.get("Searching the file system"); bench.before(); - let paths = TemplatePath.addLeadingDotSlashArray( - await fastglob(globs, { - caseSensitiveMatch: false, - dot: true, - }) - ); + let globResults = await this._globSearch(); + let paths = TemplatePath.addLeadingDotSlashArray(globResults); bench.after(); + // filter individual paths in the new config-specified extension + // where is this used? if ("extensionMap" in this.config) { let extensions = this.config.extensionMap; - paths = paths.filter(function (path) { - for (let entry of extensions) { - // TODO `.${extension}` ? - if (path.endsWith(entry.extension) && entry.filter) { - return entry.filter(path); + if (Array.from(extensions).filter((entry) => !!entry.filter).length) { + paths = paths.filter(function (path) { + for (let entry of extensions) { + if (entry.filter && path.endsWith(`.${entry.extension}`)) { + return entry.filter(path); + } } - } - return true; - }); + return true; + }); + } } this.pathCache = paths; return paths; } + // Assumption here that filePath is not a passthrough copy file + isFullTemplateFile(paths, filePath) { + for (let path of paths) { + if (path === filePath) { + return true; + } + } + + return false; + } + /* For `eleventy --watch` */ getGlobWatcherFiles() { // TODO is it better to tie the includes and data to specific file extensions or keep the **? diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 7de46c076..502974d4c 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -61,6 +61,15 @@ class TemplateEngine { return this._extensions; } + get extensionEntries() { + if (!this._extensionEntries) { + this._extensionEntries = this.extensionMap.getExtensionEntriesFromKey( + this.name + ); + } + return this._extensionEntries; + } + getName() { return this.name; } diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 58085e9eb..78feb9c5d 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -310,6 +310,50 @@ class TemplateContent { } } } + + getExtensionEntries() { + let extensions = this.templateRender.engine.extensionEntries; + return extensions; + } + + isFileRelevantToThisTemplate(incrementalFile, metadata = {}) { + // always relevant if incremental file not set (build everything) + if (!incrementalFile) { + return true; + } + + let incrementalFileIsFullTemplate = metadata.incrementalFileIsFullTemplate; + let extensionEntries = this.getExtensionEntries().filter( + (entry) => !!entry.isIncrementalMatch + ); + if (extensionEntries.length) { + for (let entry of extensionEntries) { + if ( + entry.isIncrementalMatch.call( + { + inputPath: this.inputPath, + }, + incrementalFile + ) + ) { + return true; + } + } + } else { + // Not great way of building all templates if this is a layout, include, JS dependency. + // TODO improve this for default langs + if (!incrementalFileIsFullTemplate) { + return true; + } + + // only build if this input path is the same as the file that was changed + if (this.inputPath === incrementalFile) { + return true; + } + } + + return false; + } } TemplateContent._inputCache = new Map(); diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index d050fbfaa..bbb4e29fd 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -51,7 +51,9 @@ class TemplatePassthroughManager { } setIncrementalFile(path) { - this.incrementalFile = path; + if (path) { + this.incrementalFile = path; + } } _normalizePaths(path, outputPath) { @@ -168,11 +170,11 @@ class TemplatePassthroughManager { } getAllNormalizedPaths(paths) { - if ( - this.incrementalFile && - this.isPassthroughCopyFile(paths, this.incrementalFile) - ) { - return [this._normalizePaths(this.incrementalFile)]; + if (this.incrementalFile) { + if (this.isPassthroughCopyFile(paths, this.incrementalFile)) { + return [this._normalizePaths(this.incrementalFile)]; + } + return []; } let normalizedPaths = []; diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 8e955485d..020170953 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -150,53 +150,74 @@ class TemplateWriter { return this.allPaths; } - _createTemplate(path) { + _isIncrementalFileAPassthroughCopy(paths) { + let passthroughManager = this.eleventyFiles.getPassthroughManager(); + return passthroughManager.isPassthroughCopyFile( + paths, + this.incrementalFile + ); + } + + _createTemplate(path, allPaths) { let tmpl = this._templatePathCache.get(path); - if (tmpl) { - return tmpl; - } + if (!tmpl) { + tmpl = new Template( + path, + this.inputDir, + this.outputDir, + this.templateData, + this.extensionMap, + this.eleventyConfig + ); - tmpl = new Template( - path, - this.inputDir, - this.outputDir, - this.templateData, - this.extensionMap, - this.eleventyConfig - ); + tmpl.logger = this.logger; + this._templatePathCache.set(path, tmpl); + + /* + * Sample filter: arg str, return pretty HTML string + * function(str) { + * return pretty(str, { ocd: true }); + * } + */ + for (let transformName in this.config.transforms) { + let transform = this.config.transforms[transformName]; + if (typeof transform === "function") { + tmpl.addTransform(transformName, transform); + } + } - tmpl.logger = this.logger; - this._templatePathCache.set(path, tmpl); + for (let linterName in this.config.linters) { + let linter = this.config.linters[linterName]; + if (typeof linter === "function") { + tmpl.addLinter(linter); + } + } + } tmpl.setIsVerbose(this.isVerbose); // --incremental only writes files that trigger a build during --watch - if (this.incrementalFile && path !== this.incrementalFile) { - tmpl.setDryRun(true); + if (this.incrementalFile) { + // incremental file is a passthrough copy (not a template) + if (this._isIncrementalFileAPassthroughCopy(allPaths)) { + tmpl.setDryRun(true); + // Passthrough copy check is above this (order is important) + } else if ( + tmpl.isFileRelevantToThisTemplate(this.incrementalFile, { + incrementalFileIsFullTemplate: this.eleventyFiles.isFullTemplateFile( + allPaths, + this.incrementalFile + ), + }) + ) { + tmpl.setDryRun(this.isDryRun); + } else { + tmpl.setDryRun(true); + } } else { tmpl.setDryRun(this.isDryRun); } - /* - * Sample filter: arg str, return pretty HTML string - * function(str) { - * return pretty(str, { ocd: true }); - * } - */ - for (let transformName in this.config.transforms) { - let transform = this.config.transforms[transformName]; - if (typeof transform === "function") { - tmpl.addTransform(transformName, transform); - } - } - - for (let linterName in this.config.linters) { - let linter = this.config.linters[linterName]; - if (typeof linter === "function") { - tmpl.addLinter(linter); - } - } - return tmpl; } @@ -204,9 +225,7 @@ class TemplateWriter { let promises = []; for (let path of paths) { if (this.extensionMap.hasEngine(path)) { - promises.push( - this.templateMap.add(this._createTemplate(path)) - ); + promises.push(this.templateMap.add(this._createTemplate(path, paths))); } debug(`${path} begun adding to map.`); } @@ -236,9 +255,7 @@ class TemplateWriter { async writePassthroughCopy(paths) { let passthroughManager = this.eleventyFiles.getPassthroughManager(); - if (this.incrementalFile) { - passthroughManager.setIncrementalFile(this.incrementalFile); - } + passthroughManager.setIncrementalFile(this.incrementalFile); return passthroughManager.copyAll(paths).catch((e) => { this.errorHandler.warn(e, "Error with passthrough copy"); @@ -296,17 +313,11 @@ class TemplateWriter { async write() { let paths = await this._getAllPaths(); let promises = []; + promises.push(this.writePassthroughCopy(paths)); - // Only write templates if not using incremental OR if incremental file was *not* a passthrough copy - if ( - !this.incrementalFile || - !this.eleventyFiles - .getPassthroughManager() - .isPassthroughCopyFile(paths, this.incrementalFile) - ) { - promises.push(...(await this.generateTemplates(paths))); - } + promises.push(...(await this.generateTemplates(paths))); + return Promise.all(promises).catch((e) => { return Promise.reject(e); }); diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index 66236c722..bdf5fab72 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -133,7 +133,7 @@ test("getKey", (t) => { t.is(map.getKey("component.js"), undefined); }); -test("isFullTemplateFilename (not a passthrough copy extension)", (t) => { +test("isFullTemplateFilePath (not a passthrough copy extension)", (t) => { let map = getExtensionMap([ "liquid", "njk", @@ -143,11 +143,11 @@ test("isFullTemplateFilename (not a passthrough copy extension)", (t) => { "js", "css", ]); - t.true(map.isFullTemplateFilename("template.liquid")); - t.true(map.isFullTemplateFilename("template.njk")); - t.true(map.isFullTemplateFilename("template.11ty.js")); - t.true(map.isFullTemplateFilename("template.ejs")); - t.true(map.isFullTemplateFilename("template.pug")); - t.false(map.isFullTemplateFilename("passthrough.js")); - t.false(map.isFullTemplateFilename("passthrough.css")); + t.true(map.isFullTemplateFilePath("template.liquid")); + t.true(map.isFullTemplateFilePath("template.njk")); + t.true(map.isFullTemplateFilePath("template.11ty.js")); + t.true(map.isFullTemplateFilePath("template.ejs")); + t.true(map.isFullTemplateFilePath("template.pug")); + t.false(map.isFullTemplateFilePath("passthrough.js")); + t.false(map.isFullTemplateFilePath("passthrough.css")); }); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index a6389a52e..1e87d244a 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2056,14 +2056,16 @@ test("Engine Singletons", async (t) => { "./test/stubs/engine-singletons/", "./dist", null, - map + map, + eleventyConfig ); let tmpl2 = getNewTemplate( "./test/stubs/engine-singletons/second.njk", "./test/stubs/engine-singletons/", "./dist", null, - map + map, + eleventyConfig ); t.deepEqual(tmpl1.engine, tmpl2.engine); @@ -2111,3 +2113,39 @@ test("Make sure layout cache takes new changes during watch (liquid)", async (t) t.is((await tmpl.render(data)).trim(), ''); }); + +test("Add Extension via Configuration (txt file)", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + isIncrementalMatch: function (incrementalFilePath) { + // do some kind of check + return this.inputPath === incrementalFilePath; + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let map = new EleventyExtensionMap([], eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default.txt", + "./test/stubs/", + "./dist", + null, + map, + eleventyConfig + ); + + let extensions = tmpl.getExtensionEntries(); + t.deepEqual(extensions[0].key, "txt"); + t.deepEqual(extensions[0].extension, "txt"); + + t.truthy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default.txt")); + t.falsy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default2.txt")); + t.falsy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default.njk")); +}); diff --git a/test/stubs/add-extension/test.njk b/test/stubs/add-extension/test.njk new file mode 100644 index 000000000..e69de29bb diff --git a/test/stubs/add-extension/test.txt b/test/stubs/add-extension/test.txt new file mode 100644 index 000000000..e69de29bb From a56eae493450d6e0594a9eb6e109345a2c8e3c0d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Mar 2021 21:46:01 -0500 Subject: [PATCH 376/746] Refactor away from forEach (eww) --- src/EleventyExtensionMap.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 1947fc19b..6a76b7a36 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -98,17 +98,15 @@ class EleventyExtensionMap { _getGlobs(formatKeys, inputDir) { let dir = TemplatePath.convertToRecursiveGlobSync(inputDir); let globs = []; - formatKeys.forEach( - function (key) { - if (this.hasExtension(key)) { - this.getExtensionsFromKey(key).forEach(function (extension) { - globs.push(dir + "/*." + extension); - }); - } else { - globs.push(dir + "/*." + key); + for (let key of formatKeys) { + if (this.hasExtension(key)) { + for (let extension of this.getExtensionsFromKey(key)) { + globs.push(dir + "/*." + extension); } - }.bind(this) - ); + } else { + globs.push(dir + "/*." + key); + } + } return globs; } From 7f86629bf18baf73bcbac947fc762b482e627c5c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Mar 2021 21:47:08 -0500 Subject: [PATCH 377/746] Move to use fastglob ignore option instead of negated strings (for speeeed) --- src/EleventyFiles.js | 48 ++++++------ test/EleventyFilesTest.js | 151 +++++++++++++++++--------------------- 2 files changed, 93 insertions(+), 106 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 975e6cbf1..1c5d12e25 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -65,7 +65,7 @@ class EleventyFiles { init() { this.alreadyInit = true; - // Input was a directory + // Input is a directory if (this.input === this.inputDir) { this.templateGlobs = this.extensionMap.getGlobs(this.inputDir); } else { @@ -79,6 +79,7 @@ class EleventyFiles { get validTemplateGlobs() { if (!this._validTemplateGlobs) { let globs; + // Input is a directory if (this.input === this.inputDir) { globs = this.extensionMap.getValidGlobs(this.inputDir); } else { @@ -175,20 +176,26 @@ class EleventyFiles { setupGlobs() { this.fileIgnores = this.getIgnores(); + this.extraIgnores = this._getIncludesAndDataDirs(); if (this.passthroughAll) { - this.templateGlobsWithIgnoresFromFiles = TemplateGlob.map([ + this.normalizedTemplateGlobs = TemplateGlob.map([ TemplateGlob.normalizePath(this.input, "/**"), - ]).concat(this.fileIgnores); + ]); } else { - this.templateGlobsWithIgnoresFromFiles = this.templateGlobs.concat( - this.fileIgnores - ); + this.normalizedTemplateGlobs = this.templateGlobs; } + } - this.templateGlobsWithAllIgnores = this.templateGlobsWithIgnoresFromFiles.concat( - this._getIncludesAndDataDirIgnores() - ); + getIgnoreGlobs() { + let uniqueIgnores = new Set(); + for (let ignore of this.fileIgnores) { + uniqueIgnores.add(ignore); + } + for (let ignore of this.extraIgnores) { + uniqueIgnores.add(ignore); + } + return Array.from(uniqueIgnores); } static getFileIgnores(ignoreFiles, defaultIfFileDoesNotExist) { @@ -221,10 +228,10 @@ class EleventyFiles { } if (!fileFound && defaultIfFileDoesNotExist) { - ignores.push("!" + TemplateGlob.normalizePath(defaultIfFileDoesNotExist)); + ignores.push(TemplateGlob.normalizePath(defaultIfFileDoesNotExist)); for (let dir of dirs) { ignores.push( - "!" + TemplateGlob.normalizePath(dir, defaultIfFileDoesNotExist) + TemplateGlob.normalizePath(dir, defaultIfFileDoesNotExist) ); } } @@ -270,11 +277,11 @@ class EleventyFiles { // Note these folders must exist to get /** suffix let stat = fs.statSync(path); if (stat.isDirectory()) { - return "!" + path + "/**"; + return path + "/**"; } - return "!" + path; + return path; } catch (e) { - return "!" + path; + return path; } }); } @@ -315,7 +322,7 @@ class EleventyFiles { // ignore output dir unless that would occlude all input if (!TemplatePath.startsWithSubPath(this.inputDir, this.outputDir)) { - files = files.concat(TemplateGlob.map("!" + this.outputDir + "/**")); + files = files.concat(TemplateGlob.map(this.outputDir + "/**")); } return files; @@ -330,7 +337,7 @@ class EleventyFiles { } getFileGlobs() { - return this.templateGlobsWithAllIgnores; + return this.normalizedTemplateGlobs; } getRawFiles() { @@ -363,6 +370,7 @@ class EleventyFiles { this._glob = fastglob(globs, { caseSensitiveMatch: false, dot: true, + ignore: this.getIgnoreGlobs(), }); return this._glob; @@ -441,7 +449,7 @@ class EleventyFiles { getGlobWatcherIgnores() { // convert to format without ! since they are passed in as a separate argument to glob watcher return this.fileIgnores.map((ignore) => - TemplatePath.stripLeadingDotSlash(ignore.substr(1)) + TemplatePath.stripLeadingDotSlash(ignore) ); } @@ -466,12 +474,6 @@ class EleventyFiles { return files; } - - _getIncludesAndDataDirIgnores() { - return this._getIncludesAndDataDirs().map(function (dir) { - return "!" + dir; - }); - } } module.exports = EleventyFiles; diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index 29f3058e5..f7b0400e1 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -174,8 +174,10 @@ test("Single File Input (shallow path)", async (t) => { ); evf.init(); - let globs = evf.getFileGlobs().filter((path) => path !== "!./README.md"); - let files = await fastglob(globs); + let globs = evf.getFileGlobs(); //.filter((path) => path !== "./README.md"); + let files = await fastglob(globs, { + ignore: evf.getIgnoreGlobs(), + }); t.is(evf.getRawFiles().length, 1); t.is(files.length, 1); t.is(files[0], "./README.md"); @@ -202,8 +204,8 @@ test("Glob Input", async (t) => { test(".eleventyignore parsing", (t) => { let ignores = EleventyFiles.getFileIgnores("./test/stubs/.eleventyignore"); t.is(ignores.length, 2); - t.is(ignores[0], "!./test/stubs/ignoredFolder/**"); - t.is(ignores[1], "!./test/stubs/ignoredFolder/ignored.md"); + t.is(ignores[0], "./test/stubs/ignoredFolder/**"); + t.is(ignores[1], "./test/stubs/ignoredFolder/ignored.md"); }); test("Parse multiple .eleventyignores", (t) => { @@ -213,15 +215,12 @@ test("Parse multiple .eleventyignores", (t) => { ]); t.is(ignores.length, 4); // Note these folders must exist! - t.is(ignores[0], "!./test/stubs/multiple-ignores/ignoredFolder/**"); - t.is(ignores[1], "!./test/stubs/multiple-ignores/ignoredFolder/ignored.md"); - t.is( - ignores[2], - "!./test/stubs/multiple-ignores/subfolder/ignoredFolder2/**" - ); + t.is(ignores[0], "./test/stubs/multiple-ignores/ignoredFolder/**"); + t.is(ignores[1], "./test/stubs/multiple-ignores/ignoredFolder/ignored.md"); + t.is(ignores[2], "./test/stubs/multiple-ignores/subfolder/ignoredFolder2/**"); t.is( ignores[3], - "!./test/stubs/multiple-ignores/subfolder/ignoredFolder2/ignored2.md" + "./test/stubs/multiple-ignores/subfolder/ignoredFolder2/ignored2.md" ); }); @@ -231,7 +230,7 @@ test("defaults if passed file name does not exist", (t) => { "node_modules/**" ); t.truthy(ignores.length); - t.is(ignores[0], "!./node_modules/**"); + t.is(ignores[0], "./node_modules/**"); }); test(".eleventyignore files", async (t) => { @@ -246,7 +245,9 @@ test(".eleventyignore files", async (t) => { let ignoredFiles = await fastglob("test/stubs/ignoredFolder/*.md"); t.is(ignoredFiles.length, 1); - let files = await fastglob(evf.getFileGlobs()); + let files = await fastglob(evf.getFileGlobs(), { + ignore: evf.getIgnoreGlobs(), + }); t.true(files.length > 0); @@ -272,11 +273,11 @@ test("Get ignores (no .eleventyignore no .gitignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./node_modules/**", - "!./test/stubs/ignorelocalroot/node_modules/**", - "!./test/stubs/ignore1/node_modules/**", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore1/_site/**", + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignore1/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore1/_site/**", ]); }); @@ -292,9 +293,9 @@ test("Get ignores (no .eleventyignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./test/stubs/ignore2/thisshouldnotexist12345", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore2/_site/**", + "./test/stubs/ignore2/thisshouldnotexist12345", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore2/_site/**", ]); }); @@ -317,8 +318,8 @@ test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore2/_site/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore2/_site/**", ]); }); @@ -334,13 +335,13 @@ test("Get ignores (no .gitignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./node_modules/**", - "!./test/stubs/ignorelocalroot/node_modules/**", - "!./test/stubs/ignore3/node_modules/**", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore3/ignoredFolder/**", - "!./test/stubs/ignore3/ignoredFolder/ignored.md", - "!./test/stubs/ignore3/_site/**", + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignore3/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore3/ignoredFolder/**", + "./test/stubs/ignore3/ignoredFolder/ignored.md", + "./test/stubs/ignore3/_site/**", ]); }); @@ -356,11 +357,11 @@ test("Get ignores (both .eleventyignore and .gitignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./test/stubs/ignore4/thisshouldnotexist12345", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore4/ignoredFolder/**", - "!./test/stubs/ignore4/ignoredFolder/ignored.md", - "!./test/stubs/ignore4/_site/**", + "./test/stubs/ignore4/thisshouldnotexist12345", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore4/ignoredFolder/**", + "./test/stubs/ignore4/ignoredFolder/ignored.md", + "./test/stubs/ignore4/_site/**", ]); }); @@ -383,10 +384,10 @@ test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(fa evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore4/ignoredFolder/**", - "!./test/stubs/ignore4/ignoredFolder/ignored.md", - "!./test/stubs/ignore4/_site/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore4/ignoredFolder/**", + "./test/stubs/ignore4/ignoredFolder/ignored.md", + "./test/stubs/ignore4/_site/**", ]); }); @@ -403,11 +404,11 @@ test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./node_modules/**", - "!./test/stubs/ignorelocalroot/node_modules/**", - "!./test/stubs/ignore5/node_modules/**", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore5/_site/**", + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignore5/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore5/_site/**", ]); }); @@ -423,13 +424,13 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./node_modules/**", - "!./test/stubs/ignorelocalroot/node_modules/**", - "!./test/stubs/ignore6/node_modules/**", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore6/ignoredFolder/**", - "!./test/stubs/ignore6/ignoredFolder/ignored.md", - "!./test/stubs/ignore6/_site/**", + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignore6/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore6/ignoredFolder/**", + "./test/stubs/ignore6/ignoredFolder/ignored.md", + "./test/stubs/ignore6/_site/**", ]); }); @@ -446,11 +447,11 @@ test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)" evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./node_modules/**", - "!./test/stubs/ignorelocalroot/node_modules/**", - "!./test/stubs/ignore7/node_modules/**", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore7/_site/**", + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignore7/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore7/_site/**", ]); }); @@ -466,13 +467,13 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore ha evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "!./node_modules/**", - "!./test/stubs/ignorelocalroot/node_modules/**", - "!./test/stubs/ignore8/node_modules/**", - "!./test/stubs/ignorelocalroot/test.md", - "!./test/stubs/ignore8/ignoredFolder/**", - "!./test/stubs/ignore8/ignoredFolder/ignored.md", - "!./test/stubs/ignore8/_site/**", + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignore8/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore8/ignoredFolder/**", + "./test/stubs/ignore8/ignoredFolder/ignored.md", + "./test/stubs/ignore8/_site/**", ]); }); /* End .eleventyignore and .gitignore combos */ @@ -526,22 +527,6 @@ test("Include and Data Dirs", (t) => { ]); }); -test("Ignore Include and Data Dirs", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs", - "test/stubs/_site", - [], - eleventyConfig - ); - evf.init(); - - t.deepEqual(evf._getIncludesAndDataDirIgnores(), [ - "!./test/stubs/_includes/**", - "!./test/stubs/_data/**", - ]); -}); - test("Input to 'src' and empty includes dir (issue #403)", (t) => { let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( @@ -566,9 +551,9 @@ test("Input to 'src' and empty includes dir (issue #403)", (t) => { "./src/**/*.md", "./src/**/*.liquid", "./src/**/*.html", - "!./src/_includes/**", - "!./src/_site/**", - "!./src/_data/**", + // "!./src/_includes/**", + // "!./src/_site/**", + // "!./src/_data/**", ]); }); @@ -750,6 +735,6 @@ test("Test that negations are ignored (for now) PR#709, will change when #693 is `hello !testing` ), - ["!./hello"] + ["./hello"] ); }); From 8b49da00524c661da27862f5645c302a810e4e87 Mon Sep 17 00:00:00 2001 From: Binyamin Aron Green Date: Wed, 31 Mar 2021 18:12:40 +0000 Subject: [PATCH 378/746] update nvmrc see commit 57e28374ff54f325603b0ba2dc5ca97d001f8634 --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 9a037142a..3cacc0b93 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -10 \ No newline at end of file +12 \ No newline at end of file From c9ca422a049f34551048579bfdd30f8768ba44c3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 3 Apr 2021 15:20:49 -0500 Subject: [PATCH 379/746] Fix issue where passing an absolute path into TemplatePath.absolutePath would concat two absolute paths together. Exhibited itself with missing global data on Eleventy Cloud when you use an absolute path to an input directory. --- src/TemplatePath.js | 13 +++++++++++++ test/TemplatePathTest.js | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/src/TemplatePath.js b/src/TemplatePath.js index 3b06f663c..f63a76d3e 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -133,6 +133,19 @@ TemplatePath.normalizeUrlPath = function (...urlPaths) { * @returns {String} the absolute path described by the given path segments. */ TemplatePath.absolutePath = function (...paths) { + let i = 0; + for (let path of paths) { + if (path.startsWith("/")) { + if (i === 0) { + return path; + } + throw new Error( + `Only the first parameter to Template.absolutePath can be an absolute path. Received: ${path} from ${paths}` + ); + } + i++; + } + return TemplatePath.join(TemplatePath.getWorkingDir(), ...paths); }; diff --git a/test/TemplatePathTest.js b/test/TemplatePathTest.js index ed4ad2a48..e8cda9faf 100644 --- a/test/TemplatePathTest.js +++ b/test/TemplatePathTest.js @@ -129,6 +129,11 @@ test("absolutePath", (t) => { TemplatePath.absolutePath(".eleventy.js").split("/").pop(), ".eleventy.js" ); + t.is(TemplatePath.absolutePath("/tmp/.eleventy.js"), "/tmp/.eleventy.js"); + + t.throws(() => { + TemplatePath.absolutePath("file1.js", "test/file2.js", "/tmp/.eleventy.js"); + }); }); test("absolutePath and relativePath", (t) => { From 659633c05f6aff016ea02e66213509c24e44d589 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 4 Apr 2021 14:42:02 -0500 Subject: [PATCH 380/746] Test to solidify https://github.com/11ty/11ty-website/pull/499 --- test/TemplateFileSlugTest.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/TemplateFileSlugTest.js b/test/TemplateFileSlugTest.js index e4bdad43f..972cab52a 100644 --- a/test/TemplateFileSlugTest.js +++ b/test/TemplateFileSlugTest.js @@ -52,6 +52,12 @@ test("Easy slug with date, index", (t) => { t.is(fs.getFullPathWithoutExtension(), "/index"); }); +test("Easy slug with only a date and no suffix", (t) => { + let fs = getNewSlugInstance("./2018-01-01.html"); + t.is(fs.getSlug(), "2018-01-01"); + t.is(fs.getFullPathWithoutExtension(), "/2018-01-01"); +}); + /* Directories */ test("Easy slug with dir", (t) => { From afb017a7d0371adb059baa2d87c53e5f2b2910ba Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 6 Apr 2021 22:26:32 -0500 Subject: [PATCH 381/746] Start to support objects in `permalink` for more complex aliasing. --- src/Plugins/Pagination.js | 9 +- src/Template.js | 130 +++++++---- src/TemplateCollection.js | 14 +- src/TemplateMap.js | 3 +- src/TemplatePermalink.js | 204 ++++++++++++------ src/TemplatePermalinkNoWrite.js | 11 - test/TemplatePermalinkNoWriteTest.js | 8 - test/TemplatePermalinkTest.js | 77 +++++-- test/TemplateTest.js | 19 +- test/stubs/permalink-build/permalink-build.md | 6 + test/stubs/permalink-true/permalink-true.md | 5 + 11 files changed, 326 insertions(+), 160 deletions(-) delete mode 100644 src/TemplatePermalinkNoWrite.js delete mode 100644 test/TemplatePermalinkNoWriteTest.js create mode 100644 test/stubs/permalink-build/permalink-build.md create mode 100644 test/stubs/permalink-true/permalink-true.md diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 5815ffcc3..a213c6006 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -244,12 +244,9 @@ class Pagination { cloned.setPaginationData(override); // TO DO subdirectory to links if the site doesn’t live at / - let [outputLink, outputHref] = await Promise.all([ - cloned.getOutputLink(), - cloned.getOutputHref(), - ]); - links.push("/" + outputLink); - hrefs.push(outputHref); + let { link, href } = await cloned.getOutputLocations(); + links.push("/" + link); + hrefs.push(href); } // we loop twice to pass in the appropriate prev/next links (already full generated now) diff --git a/src/Template.js b/src/Template.js index 40f3f95f0..588980838 100755 --- a/src/Template.js +++ b/src/Template.js @@ -1,14 +1,13 @@ const fs = require("fs-extra"); const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); -const lodashIsObject = require("lodash/isObject"); +const isPlainObject = require("lodash/isPlainObject"); const { DateTime } = require("luxon"); const TemplateData = require("./TemplateData"); const TemplateContent = require("./TemplateContent"); const TemplatePath = require("./TemplatePath"); const TemplatePermalink = require("./TemplatePermalink"); -const TemplatePermalinkNoWrite = require("./TemplatePermalinkNoWrite"); const TemplateLayout = require("./TemplateLayout"); const TemplateFileSlug = require("./TemplateFileSlug"); const ComputedData = require("./ComputedData"); @@ -135,33 +134,62 @@ class Template extends TemplateContent { } let permalink = data[this.config.keys.permalink]; - if (permalink) { - // render variables inside permalink front matter, bypass markdown - let permalinkValue; - if (!this.config.dynamicPermalinks || data.dynamicPermalink === false) { - debugDev("Not using dynamicPermalinks, using %o", permalink); - permalinkValue = permalink; - } else { - permalinkValue = await super.render(permalink, data, true); + 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) + if (typeof permalink === "boolean") { + debugDev("Using boolean permalink %o", permalink); + permalinkValue = permalink; + } else if ( + permalink && + (!this.config.dynamicPermalinks || data.dynamicPermalink === false) + ) { + debugDev("Not using dynamic permalinks, using %o", permalink); + permalinkValue = permalink; + } else if (isPlainObject(permalink)) { + let promises = []; + let order = []; + for (let key in permalink) { + order.push(key); + promises.push(super.render(permalink[key], data, true)); + } + let results = await Promise.all(promises); + + permalinkValue = {}; + for (let j = 0, k = order.length; j < k; j++) { + permalinkValue[order[j]] = results[j]; debug( - "Rendering permalink for %o: %s becomes %o", + "Rendering permalink.%o for %o: %s becomes %o", + order[j], this.inputPath, permalink, - permalinkValue + results[j] ); debugDev("Permalink rendered with data: %o", data); } + } else if (permalink) { + // render variables inside permalink front matter, bypass markdown + permalinkValue = await super.render(permalink, data, true); + debug( + "Rendering permalink for %o: %s becomes %o", + this.inputPath, + permalink, + permalinkValue + ); + debugDev("Permalink rendered with data: %o", data); + } + if (permalinkValue !== undefined) { let perm = new TemplatePermalink( permalinkValue, this.extraOutputSubdirectory ); - return perm; - } else if (permalink === false) { - return new TemplatePermalinkNoWrite(); } + // No `permalink` specified in data cascade, do the default return TemplatePermalink.generate( this.getTemplateSubfolder(), this.baseFile, @@ -171,30 +199,54 @@ class Template extends TemplateContent { ); } + async usePermalinkRoot() { + if (this._usePermalinkRoot === undefined) { + // TODO this only works with immediate front matter and not data files + this._usePermalinkRoot = (await this.getFrontMatterData())[ + this.config.keys.permalinkRoot + ]; + } + + return this._usePermalinkRoot; + } + // TODO instead of htmlIOException, do a global search to check if output path = input path and then add extra suffix + async getOutputLocations(data) { + let link = await this._getLink(data); + + let path; + if (await this.usePermalinkRoot()) { + path = link.toPathFromRoot(); + } else { + path = link.toPath(this.outputDir); + } + + return { + link: link.toLink(), + href: link.toHref(), + path: path, + }; + } + + // Preferred to use the singular `getOutputLocations` above. async getOutputLink(data) { let link = await this._getLink(data); - return link.toString(); + return link.toLink(); } + // Preferred to use the singular `getOutputLocations` above. async getOutputHref(data) { let link = await this._getLink(data); return link.toHref(); } + // Preferred to use the singular `getOutputLocations` above. async getOutputPath(data) { - let uri = await this.getOutputLink(data); - - if (uri === false) { - return false; - } else if ( - (await this.getFrontMatterData())[this.config.keys.permalinkRoot] - ) { - // TODO this only works with immediate front matter and not data files - return normalize(uri); - } else { - return normalize(this.outputDir + "/" + uri); + let link = await this._getLink(data); + if (await this.usePermalinkRoot()) { + return link.toPathFromRoot(); } + return link.toPath(this.outputDir); } setPaginationData(paginationData) { @@ -212,7 +264,7 @@ class Template extends TemplateContent { return Promise.all( data.map((item) => this.mapDataAsRenderedTemplates(item, templateData)) ); - } else if (lodashIsObject(data)) { + } else if (isPlainObject(data)) { let obj = {}; await Promise.all( Object.keys(data).map(async (value) => { @@ -412,10 +464,10 @@ class Template extends TemplateContent { } _addComputedEntry(computedData, obj, parentKey, declaredDependencies) { - // this check must come before lodashIsObject + // this check must come before isPlainObject if (typeof obj === "function") { computedData.add(parentKey, obj, declaredDependencies); - } else if (lodashIsObject(obj)) { + } else if (isPlainObject(obj)) { for (let key in obj) { let keys = []; if (parentKey) { @@ -483,8 +535,9 @@ class Template extends TemplateContent { data.page = {}; } - data.page.url = await this.getOutputHref(data); - data.page.outputPath = await this.getOutputPath(data); + let { href, path } = await this.getOutputLocations(data); + data.page.url = href; + data.page.outputPath = path; } // Deprecated, use eleventyComputed instead. @@ -574,14 +627,12 @@ class Template extends TemplateContent { } } + // TODO move this into tests (this is only used by tests) async getRenderedTemplates(data) { let pages = await this.getTemplates(data); await Promise.all( pages.map(async (page) => { - let content = await page.template._getContent( - page.outputPath, - page.data - ); + let content = await page.template._getContent(page.data); page.templateContent = content; }) @@ -589,7 +640,7 @@ class Template extends TemplateContent { return pages; } - async _getContent(outputPath, data) { + async _getContent(data) { return await this.render(data); } @@ -787,10 +838,7 @@ class Template extends TemplateContent { async getTemplateMapContent(pageMapEntry) { pageMapEntry.template.setWrapWithLayouts(false); - let content = await pageMapEntry.template._getContent( - pageMapEntry.outputPath, - pageMapEntry.data - ); + let content = await pageMapEntry.template._getContent(pageMapEntry.data); pageMapEntry.template.setWrapWithLayouts(true); return content; diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js index 2ed16c6f9..f3026ef02 100755 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -9,7 +9,7 @@ class TemplateCollection extends Sortable { this._filteredByGlobsCache = new Map(); } - // right now this is only used by the tests + // TODO move this into tests (this is only used by tests) async _testAddTemplate(template) { let data = await template.getData(); for (let map of await template.getTemplates(data)) { @@ -34,7 +34,7 @@ class TemplateCollection extends Sortable { globs = [globs]; } - globs = globs.map(glob => TemplatePath.addLeadingDotSlash(glob)); + globs = globs.map((glob) => TemplatePath.addLeadingDotSlash(glob)); return globs; } @@ -53,7 +53,7 @@ class TemplateCollection extends Sortable { this._filteredByGlobsCache = new Map(); } - let filtered = this.getAllSorted().filter(item => { + let filtered = this.getAllSorted().filter((item) => { if (multimatch([item.inputPath], globs).length) { return true; } @@ -66,19 +66,19 @@ class TemplateCollection extends Sortable { } getFilteredByTag(tagName) { - return this.getAllSorted().filter(item => { + return this.getAllSorted().filter((item) => { if (!tagName) { return true; } else if (Array.isArray(item.data.tags)) { - return item.data.tags.some(tag => tag === tagName); + return item.data.tags.some((tag) => tag === tagName); } return false; }); } getFilteredByTags(...tags) { - return this.getAllSorted().filter(item => - tags.every(requiredTag => { + return this.getAllSorted().filter((item) => + tags.every((requiredTag) => { const itemTags = item.data.tags; if (Array.isArray(itemTags)) { return itemTags.includes(requiredTag); diff --git a/src/TemplateMap.js b/src/TemplateMap.js index c0aee0b56..8ad1208d5 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -265,10 +265,11 @@ class TemplateMap { let counter = 0; for (let page of map._pages) { - // TODO do we need this in map entries? + // Copy outputPath to map entry if (!map.outputPath) { map.outputPath = page.outputPath; } + if ( counter === 0 || (map.data.pagination && diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 59433e16d..8851b7d4b 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -1,74 +1,152 @@ const parsePath = require("parse-filepath"); const TemplatePath = require("./TemplatePath"); +const normalize = require("normalize-path"); +const isPlainObject = require("lodash/isPlainObject"); -function TemplatePermalink(link, extraSubdir) { - this.link = this._cleanLink(link); - this.extraSubdir = extraSubdir || ""; -} +class TemplatePermalink { + // `link` with template syntax should have already been rendered in Template.js + constructor(link, extraSubdir) { + // these defaults may get overriden below + this.isProcessible = true; + this.outputToFileSystem = true; + + if (link === true) { + throw new Error( + "`permalink: true` is not a supported feature in Eleventy. Did you mean `permalink: false`?" + ); + } + if (link === false) { + // permalink: false // doesn’t match `permalink: build: false` only for backwards compat + this.outputToFileSystem = false; + return; + } + + let rawLink; + if (isPlainObject(link)) { + if ("build" in link) { + rawLink = link.build; + // permalink: build: true + // permalink: build: false + if (typeof rawLink === "boolean") { + this.outputToFileSystem = false; + this.isProcessible = rawLink; + } + } else { + // opt out of build + this.outputToFileSystem = false; + this.isProcessible = false; + } + } else { + rawLink = link; + } + + this.rawLink = rawLink; + this.extraPaginationSubdir = extraSubdir || ""; + } + + _cleanLink(link) { + return link + (link.substr(-1) === "/" ? "index.html" : ""); + } + + toLink() { + if (!this.outputToFileSystem) { + return false; + } + + let cleanLink = this._cleanLink(this.rawLink); + let parsed = parsePath(cleanLink); + + return TemplatePath.join( + parsed.dir, + this.extraPaginationSubdir, + parsed.base + ); + } + + // remove all index.html’s from links + // index.html becomes / + // test/index.html becomes test/ + toHref() { + if (!this.outputToFileSystem) { + return false; + } -TemplatePermalink.prototype._cleanLink = function(link) { - return link + (link.substr(-1) === "/" ? "index.html" : ""); -}; - -TemplatePermalink.prototype.resolve = function() { - let parsed = parsePath(this.link); - - return TemplatePath.join(parsed.dir, this.extraSubdir, parsed.base); -}; - -TemplatePermalink.prototype.toString = function() { - return this.resolve(); -}; - -// remove all index.html’s from links -// index.html becomes / -// test/index.html becomes test/ -TemplatePermalink.prototype.toHref = function() { - let str = this.toString(); - let original = (str.charAt(0) !== "/" ? "/" : "") + this.toString(); - let needle = "/index.html"; - if (original === needle) { - return "/"; - } else if (original.substr(-1 * needle.length) === needle) { - return original.substr(0, original.length - needle.length) + "/"; + let transformedLink = this.toLink(); + let original = + (transformedLink.charAt(0) !== "/" ? "/" : "") + transformedLink; + let needle = "/index.html"; + if (original === needle) { + return "/"; + } else if (original.substr(-1 * needle.length) === needle) { + return original.substr(0, original.length - needle.length) + "/"; + } + return original; } - return original; -}; -TemplatePermalink._hasDuplicateFolder = function(dir, base) { - let folders = dir.split("/"); - if (!folders[folders.length - 1]) { - folders.pop(); + toPath(outputDir) { + let uri = this.toLink(); + + if (uri === false) { + return false; + } + + return normalize(outputDir + "/" + uri); + } + + toPathFromRoot() { + let uri = this.toLink(); + + if (uri === false) { + return false; + } + + return normalize(uri); } - return folders[folders.length - 1] === base; -}; - -TemplatePermalink.generate = function( - dir, - filenameNoExt, - extraSubdir, - suffix, - fileExtension = "html" -) { - let hasDupeFolder = TemplatePermalink._hasDuplicateFolder(dir, filenameNoExt); - let path; - if (fileExtension === "html") { - path = - (dir ? dir + "/" : "") + - (filenameNoExt !== "index" && !hasDupeFolder ? filenameNoExt + "/" : "") + - "index" + - (suffix || "") + - ".html"; - } else { - path = - (dir ? dir + "/" : "") + - filenameNoExt + - (suffix || "") + - "." + - fileExtension; + + isTemplateProcessable() { + return this.isProcessible; + } + + static _hasDuplicateFolder(dir, base) { + let folders = dir.split("/"); + if (!folders[folders.length - 1]) { + folders.pop(); + } + return folders[folders.length - 1] === base; } - return new TemplatePermalink(path, extraSubdir); -}; + static generate( + dir, + filenameNoExt, + extraSubdir, + suffix, + fileExtension = "html" + ) { + let hasDupeFolder = TemplatePermalink._hasDuplicateFolder( + dir, + filenameNoExt + ); + let path; + if (fileExtension === "html") { + path = + (dir ? dir + "/" : "") + + (filenameNoExt !== "index" && !hasDupeFolder + ? filenameNoExt + "/" + : "") + + "index" + + (suffix || "") + + ".html"; + } else { + path = + (dir ? dir + "/" : "") + + filenameNoExt + + (suffix || "") + + "." + + fileExtension; + } + + return new TemplatePermalink(path, extraSubdir); + } +} module.exports = TemplatePermalink; diff --git a/src/TemplatePermalinkNoWrite.js b/src/TemplatePermalinkNoWrite.js deleted file mode 100644 index 02174a228..000000000 --- a/src/TemplatePermalinkNoWrite.js +++ /dev/null @@ -1,11 +0,0 @@ -class TemplatePermalinkNoWrite { - toString() { - return false; - } - - toHref() { - return false; - } -} - -module.exports = TemplatePermalinkNoWrite; diff --git a/test/TemplatePermalinkNoWriteTest.js b/test/TemplatePermalinkNoWriteTest.js deleted file mode 100644 index 99145679d..000000000 --- a/test/TemplatePermalinkNoWriteTest.js +++ /dev/null @@ -1,8 +0,0 @@ -const test = require("ava"); -const TemplatePermalinkNoWrite = require("../src/TemplatePermalinkNoWrite"); - -test("Test standard method signature", (t) => { - let perm = new TemplatePermalinkNoWrite(); - t.is(perm.toHref(), false); - t.is(perm.toString(), false); -}); diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index 85372887a..b2c9021cf 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -3,11 +3,11 @@ const TemplatePermalink = require("../src/TemplatePermalink"); test("Simple straight permalink", (t) => { t.is( - new TemplatePermalink("permalinksubfolder/test.html").toString(), + new TemplatePermalink("permalinksubfolder/test.html").toLink(), "permalinksubfolder/test.html" ); t.is( - new TemplatePermalink("./permalinksubfolder/test.html").toString(), + new TemplatePermalink("./permalinksubfolder/test.html").toLink(), "permalinksubfolder/test.html" ); @@ -28,15 +28,15 @@ test("Simple straight permalink", (t) => { test("Permalink without filename", (t) => { t.is( - new TemplatePermalink("permalinksubfolder/").toString(), + new TemplatePermalink("permalinksubfolder/").toLink(), "permalinksubfolder/index.html" ); t.is( - new TemplatePermalink("./permalinksubfolder/").toString(), + new TemplatePermalink("./permalinksubfolder/").toLink(), "permalinksubfolder/index.html" ); t.is( - new TemplatePermalink("/permalinksubfolder/").toString(), + new TemplatePermalink("/permalinksubfolder/").toLink(), "/permalinksubfolder/index.html" ); @@ -56,11 +56,11 @@ test("Permalink without filename", (t) => { test("Permalink with pagination subdir", (t) => { t.is( - new TemplatePermalink("permalinksubfolder/test.html", "0/").toString(), + new TemplatePermalink("permalinksubfolder/test.html", "0/").toLink(), "permalinksubfolder/0/test.html" ); t.is( - new TemplatePermalink("permalinksubfolder/test.html", "1/").toString(), + new TemplatePermalink("permalinksubfolder/test.html", "1/").toLink(), "permalinksubfolder/1/test.html" ); @@ -77,33 +77,33 @@ test("Permalink with pagination subdir", (t) => { test("Permalink generate", (t) => { let gen = TemplatePermalink.generate; - t.is(gen("./", "index").toString(), "index.html"); + t.is(gen("./", "index").toLink(), "index.html"); t.is(gen("./", "index").toHref(), "/"); - t.is(gen(".", "index").toString(), "index.html"); + t.is(gen(".", "index").toLink(), "index.html"); t.is(gen(".", "index").toHref(), "/"); - t.is(gen(".", "test").toString(), "test/index.html"); + t.is(gen(".", "test").toLink(), "test/index.html"); t.is(gen(".", "test").toHref(), "/test/"); - t.is(gen(".", "test", "0/").toString(), "test/0/index.html"); + t.is(gen(".", "test", "0/").toLink(), "test/0/index.html"); t.is(gen(".", "test", "0/").toHref(), "/test/0/"); - t.is(gen(".", "test", "1/").toString(), "test/1/index.html"); + t.is(gen(".", "test", "1/").toLink(), "test/1/index.html"); t.is(gen(".", "test", "1/").toHref(), "/test/1/"); }); test("Permalink generate with suffix", (t) => { let gen = TemplatePermalink.generate; - t.is(gen(".", "test", null, "-o").toString(), "test/index-o.html"); + t.is(gen(".", "test", null, "-o").toLink(), "test/index-o.html"); t.is(gen(".", "test", null, "-o").toHref(), "/test/index-o.html"); - t.is(gen(".", "test", "1/", "-o").toString(), "test/1/index-o.html"); + t.is(gen(".", "test", "1/", "-o").toLink(), "test/1/index-o.html"); t.is(gen(".", "test", "1/", "-o").toHref(), "/test/1/index-o.html"); }); test("Permalink generate with new extension", (t) => { let gen = TemplatePermalink.generate; - t.is(gen(".", "test", null, null, "css").toString(), "test.css"); + t.is(gen(".", "test", null, null, "css").toLink(), "test.css"); t.is(gen(".", "test", null, null, "css").toHref(), "/test.css"); - t.is(gen(".", "test", "1/", null, "css").toString(), "1/test.css"); + t.is(gen(".", "test", "1/", null, "css").toLink(), "1/test.css"); t.is(gen(".", "test", "1/", null, "css").toHref(), "/1/test.css"); }); @@ -111,15 +111,15 @@ test("Permalink generate with subfolders", (t) => { let gen = TemplatePermalink.generate; t.is( - gen("permalinksubfolder/", "index").toString(), + gen("permalinksubfolder/", "index").toLink(), "permalinksubfolder/index.html" ); t.is( - gen("permalinksubfolder/", "test").toString(), + gen("permalinksubfolder/", "test").toLink(), "permalinksubfolder/test/index.html" ); t.is( - gen("permalinksubfolder/", "test", "1/", "-o").toString(), + gen("permalinksubfolder/", "test", "1/", "-o").toLink(), "permalinksubfolder/test/1/index-o.html" ); @@ -144,6 +144,43 @@ test("Permalink matching folder and filename", (t) => { t.is(hasDupe("component", "component"), true); t.is(hasDupe("component/", "component"), true); - t.is(gen("component/", "component").toString(), "component/index.html"); + t.is(gen("component/", "component").toLink(), "component/index.html"); t.is(gen("component/", "component").toHref(), "/component/"); }); + +test("Permalink Object, just build", (t) => { + t.is( + new TemplatePermalink({ + build: "permalinksubfolder/test.html", + }).toLink(), + "permalinksubfolder/test.html" + ); + + t.is( + new TemplatePermalink({ + build: false, + }).toLink(), + false + ); + + t.is( + new TemplatePermalink({ + build: true, + }).toLink(), + false + ); + + t.is( + new TemplatePermalink({ + request: "/url/", + }).toLink(), + false + ); + + t.is( + new TemplatePermalink({ + rando: "/url/", + }).toLink(), + false + ); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 1e87d244a..224b3edc2 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1360,10 +1360,10 @@ test("permalink: false", async (t) => { "./test/stubs/_site" ); - t.is(await tmpl.getOutputLink(), false); - t.is(await tmpl.getOutputHref(), false); - let data = await tmpl.getData(); + t.is(await tmpl.getOutputLink(data), false); + t.is(await tmpl.getOutputHref(data), false); + await write(tmpl, data); // Input file exists (sanity check for paths) @@ -1379,6 +1379,19 @@ test("permalink: false", async (t) => { ); }); +test("permalink: true", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-true/permalink-true.md", + "./test/stubs/", + "./test/stubs/_site" + ); + + let data = await tmpl.getData(); + await t.throwsAsync(async () => { + await tmpl.getOutputLink(data); + }); +}); + test("Disable dynamic permalinks", async (t) => { let tmpl = getNewTemplate( "./test/stubs/dynamic-permalink/test.njk", diff --git a/test/stubs/permalink-build/permalink-build.md b/test/stubs/permalink-build/permalink-build.md new file mode 100644 index 000000000..bb3c5148a --- /dev/null +++ b/test/stubs/permalink-build/permalink-build.md @@ -0,0 +1,6 @@ +--- +permalink: + build: /url/ +--- + +This shouldn’t write diff --git a/test/stubs/permalink-true/permalink-true.md b/test/stubs/permalink-true/permalink-true.md new file mode 100644 index 000000000..b4b85d57c --- /dev/null +++ b/test/stubs/permalink-true/permalink-true.md @@ -0,0 +1,5 @@ +--- +permalink: true +--- + +This shouldn’t write From 41b055a712de4ac520668e5c1b2f73fdcdaf6514 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 7 Apr 2021 17:47:58 -0500 Subject: [PATCH 382/746] =?UTF-8?q?permalink=20objects=20without=20build?= =?UTF-8?q?=20shouldn=E2=80=99t=20process=20or=20write=20to=20file=20syste?= =?UTF-8?q?m.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Plugins/Pagination.js | 1 + src/Template.js | 25 +++++++++--- src/TemplateMap.js | 39 +++++++++++-------- test/TemplateMapTest.js | 38 +++++++++++++++++- test/TemplateTest.js | 22 +++++++++++ test/stubs/permalink-build/permalink-build.md | 2 +- .../permalink-nobuild/permalink-nobuild.md | 6 +++ 7 files changed, 108 insertions(+), 25 deletions(-) create mode 100644 test/stubs/permalink-nobuild/permalink-nobuild.md diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index a213c6006..665b7c838 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -244,6 +244,7 @@ class Pagination { cloned.setPaginationData(override); // TO DO subdirectory to links if the site doesn’t live at / + // TODO missing data argument means Template.getData is regenerated, maybe doesn’t matter because of data cache? let { link, href } = await cloned.getOutputLocations(); links.push("/" + link); hrefs.push(href); diff --git a/src/Template.js b/src/Template.js index 588980838..85d108523 100755 --- a/src/Template.js +++ b/src/Template.js @@ -128,6 +128,15 @@ class Template extends TemplateContent { ); } + _getRawPermalinkInstance(permalinkValue) { + // unrendered! + let perm = new TemplatePermalink( + permalinkValue, + this.extraOutputSubdirectory + ); + return perm; + } + async _getLink(data) { if (!data) { data = await this.getData(); @@ -182,11 +191,7 @@ class Template extends TemplateContent { } if (permalinkValue !== undefined) { - let perm = new TemplatePermalink( - permalinkValue, - this.extraOutputSubdirectory - ); - return perm; + return this._getRawPermalinkInstance(permalinkValue); } // No `permalink` specified in data cascade, do the default @@ -210,6 +215,12 @@ class Template extends TemplateContent { return this._usePermalinkRoot; } + isProcessible(data) { + let rawPermalinkValue = data[this.config.keys.permalink]; + let link = this._getRawPermalinkInstance(rawPermalinkValue); + return link.isProcessible; + } + // TODO instead of htmlIOException, do a global search to check if output path = input path and then add extra suffix async getOutputLocations(data) { let link = await this._getLink(data); @@ -847,13 +858,15 @@ class Template extends TemplateContent { async getTemplateMapEntries() { debugDev("%o getMapped()", this.inputPath); + // Important reminder: This is where the template data is first generated via TemplateMap let data = await this.getData(); + let entries = []; // does not return outputPath or url, we don’t want to render permalinks yet entries.push({ template: this, inputPath: this.inputPath, - data: data, + data, }); return entries; } diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 8ad1208d5..cd02ffd24 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -49,6 +49,7 @@ class TemplateMap { } async add(template) { + // getTemplateMapEntries is where the Template.getData is first generated for (let map of await template.getTemplateMapEntries()) { this.map.push(map); } @@ -250,6 +251,7 @@ class TemplateMap { let tagPrefix = this.tagPrefix; for (let depEntry of dependencyMap) { if (depEntry.startsWith(tagPrefix)) { + // is a tag (collection) entry let tagName = depEntry.substr(tagPrefix.length); if (this.isUserConfigCollectionName(tagName)) { // async @@ -260,27 +262,32 @@ class TemplateMap { this.collectionsData[tagName] = this.getTaggedCollection(tagName); } } else { + // is a template entry let map = this.getMapEntryForInputPath(depEntry); - map._pages = await map.template.getTemplates(map.data); + if (!map.template.isProcessible(map.data)) { + map._pages = []; + } else { + 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 (!map.data.eleventyExcludeFromCollections) { - // TODO do we need .template in collection entries? - this.collection.add(page); + if ( + counter === 0 || + (map.data.pagination && + map.data.pagination.addAllPagesToCollections) + ) { + if (!map.data.eleventyExcludeFromCollections) { + // TODO do we need .template in collection entries? + this.collection.add(page); + } } + counter++; } - counter++; } } } diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 224927499..78946e906 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -19,8 +19,6 @@ function getNewTemplate(filename, input, output, eleventyConfig) { } function getNewTemplateByNumber(num, eleventyConfig) { - let extensions = ["md", "md", "md", "md", "md", "html", "njk"]; - return getNewTemplate( `./test/stubs/templateMapCollection/test${num}.md`, "./test/stubs/", @@ -1247,3 +1245,39 @@ test("TemplateMap circular references (map.templateContent) using eleventyExclud let collections = await tm._testGetCollectionsData(); t.is(collections.all.length, 1); }); + +test("permalink object with build", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); + let tmplLayout = getNewTemplate( + "./test/stubs/permalink-build/permalink-build.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmplLayout); + + let map = tm.getMap(); + await tm.cache(); + + t.is(map[0]._pages.length, 1); +}); + +test("permalink object without build", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tm = new TemplateMap(eleventyConfig); + let tmplLayout = getNewTemplate( + "./test/stubs/permalink-nobuild/permalink-nobuild.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmplLayout); + + let map = tm.getMap(); + await tm.cache(); + + t.is(map[0]._pages.length, 0); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 224b3edc2..e254cc1f5 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2162,3 +2162,25 @@ test("Add Extension via Configuration (txt file)", async (t) => { t.falsy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default2.txt")); t.falsy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default.njk")); }); + +test("permalink object with build", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-build/permalink-build.md", + "./test/stubs/", + "./test/stubs/_site" + ); + + t.is(await tmpl.getOutputLink(), "/url/index.html"); + t.is(await tmpl.getOutputHref(), "/url/"); +}); + +test("permalink object without build", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-nobuild/permalink-nobuild.md", + "./test/stubs/", + "./test/stubs/_site" + ); + + t.is(await tmpl.getOutputLink(), false); + t.is(await tmpl.getOutputHref(), false); +}); diff --git a/test/stubs/permalink-build/permalink-build.md b/test/stubs/permalink-build/permalink-build.md index bb3c5148a..43800686f 100644 --- a/test/stubs/permalink-build/permalink-build.md +++ b/test/stubs/permalink-build/permalink-build.md @@ -3,4 +3,4 @@ permalink: build: /url/ --- -This shouldn’t write +This should be the same as `permalink: /url/` diff --git a/test/stubs/permalink-nobuild/permalink-nobuild.md b/test/stubs/permalink-nobuild/permalink-nobuild.md new file mode 100644 index 000000000..a1ee11397 --- /dev/null +++ b/test/stubs/permalink-nobuild/permalink-nobuild.md @@ -0,0 +1,6 @@ +--- +permalink: + request: /url/ +--- + +This shouldn’t write to the file system and in fact not be processed at all. From bbc461688f0babf1cbfafd5fac56ab68f569cef7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 7 Apr 2021 17:48:54 -0500 Subject: [PATCH 383/746] Adds Needs Compilation checks to Liquid too (was already in Nunjucks) --- src/Engines/Liquid.js | 17 +++++++++++++++++ src/Engines/Nunjucks.js | 16 ++++++++++------ src/Engines/TemplateEngine.js | 5 +++++ test/TemplateRenderLiquidTest.js | 11 +++++++++++ test/TemplateRenderNunjucksTest.js | 8 ++++++++ 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 72b4e6996..536d0f699 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -50,6 +50,8 @@ class Liquid extends TemplateEngine { extname: ".liquid", dynamicPartials: false, strictFilters: true, + // TODO? + // cache: true, }; let options = Object.assign(defaults, this.liquidOptions || {}); @@ -201,7 +203,22 @@ class Liquid extends TemplateEngine { }); } + needsCompilation(str) { + let options = this.liquidLib.options; + + return ( + str.indexOf(options.tagDelimiterLeft) !== -1 || + str.indexOf(options.outputDelimiterLeft) !== -1 + ); + } + async compile(str, inputPath) { + if (!this.needsCompilation(str)) { + return async function (data) { + return str; + }; + } + let engine = this.liquidLib; let tmplReady = engine.parse(str, inputPath); diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 53ffbb4d1..6b0388bdb 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -344,18 +344,22 @@ class Nunjucks extends TemplateEngine { this.njkEnv.addExtension(shortcodeName, new PairedShortcodeFunction()); } - async compile(str, inputPath) { + needsCompilation(str) { // Defend against syntax customisations: // https://mozilla.github.io/nunjucks/api.html#customizing-syntax let optsTags = this.njkEnv.opts.tags || {}; let blockStart = optsTags.blockStart || "{%"; let variableStart = optsTags.variableStart || "{{"; let commentStart = optsTags.variableStart || "{#"; - let needsCompile = - str.indexOf(blockStart) != -1 || - str.indexOf(variableStart) != -1 || - str.indexOf(commentStart) != -1; - if (!needsCompile) { + return ( + str.indexOf(blockStart) !== -1 || + str.indexOf(variableStart) !== -1 || + str.indexOf(commentStart) !== -1 + ); + } + + async compile(str, inputPath) { + if (!this.needsCompilation(str)) { return async function () { return str; }; diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 502974d4c..0d949e071 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -168,6 +168,11 @@ class TemplateEngine { get defaultTemplateFileExtension() { return "html"; } + + // whether or not compile is needed or can we return the plaintext? + needsCompilation(str) { + return true; + } } module.exports = TemplateEngine; diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 18154a757..758d93a12 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1019,3 +1019,14 @@ test("Liquid Render Square Brackets #680 variable reference array", async (t) => ); t.is(await fn({ test: { "hey-a": 1 }, ref: ["hey-a"] }), "

1

"); }); + +test("Liquid bypass compilation", async (t) => { + let tr = getNewTemplateRender("liquid"); + + t.is(tr.engine.needsCompilation("

{{ me }}

"), true); + t.is( + tr.engine.needsCompilation("

{% comment %}{% endcomment %}

"), + true + ); + t.is(tr.engine.needsCompilation("

test

"), false); +}); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 7ee7a39e7..5738268b8 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -797,3 +797,11 @@ test("Issue 611: Run a function", async (t) => { "alkdsjfksljaZach" ); }); + +test("Nunjucks bypass compilation", async (t) => { + let tr = getNewTemplateRender("njk"); + + t.is(tr.engine.needsCompilation("

{{ me }}

"), true); + t.is(tr.engine.needsCompilation("

{% tag %}{% endtag %}

"), true); + t.is(tr.engine.needsCompilation("

test

"), false); +}); From b078b2df28afaa2ec60de182b535b099639519f3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 7 Apr 2021 17:49:36 -0500 Subject: [PATCH 384/746] More clarify on template language console output --- src/Template.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Template.js b/src/Template.js index 85d108523..81bc197ef 100755 --- a/src/Template.js +++ b/src/Template.js @@ -686,7 +686,7 @@ class Template extends TemplateContent { let engineList = this.templateRender.getReadableEnginesListDifferingFromFileExtension(); this.logger.log( `${lang.start} ${outputPath} from ${this.inputPath}${ - engineList ? ` (${engineList})` : "" + engineList ? ` (using ${engineList})` : "" }` ); From 1e47d66bdbcc6ff0c03318e750545f565ce1cb8c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 8 Apr 2021 21:29:40 -0500 Subject: [PATCH 385/746] =?UTF-8?q?Adds=20support=20for=20`dependencyMap`?= =?UTF-8?q?=20event.=20Working=20example=20of=20automatic=20SSR=20?= =?UTF-8?q?=F0=9F=8F=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TemplateContentUnrenderedTemplateError.js | 5 + src/Template.js | 123 +++++++++++------- src/TemplateConfig.js | 2 +- src/TemplateMap.js | 37 +++++- src/TemplatePermalink.js | 86 +++++++----- src/TemplateWriter.js | 13 +- test/TemplateMapTest.js | 16 ++- test/TemplatePermalinkTest.js | 7 +- test/TemplateTest.js | 33 ++++- test/TemplateWriterTest.js | 5 +- test/stubs/permalink-true/permalink-true.md | 2 +- 11 files changed, 226 insertions(+), 103 deletions(-) create mode 100644 src/Errors/TemplateContentUnrenderedTemplateError.js diff --git a/src/Errors/TemplateContentUnrenderedTemplateError.js b/src/Errors/TemplateContentUnrenderedTemplateError.js new file mode 100644 index 000000000..35ea957b7 --- /dev/null +++ b/src/Errors/TemplateContentUnrenderedTemplateError.js @@ -0,0 +1,5 @@ +const EleventyBaseError = require("../EleventyBaseError"); + +class TemplateContentUnrenderedTemplateError extends EleventyBaseError {} + +module.exports = TemplateContentUnrenderedTemplateError; diff --git a/src/Template.js b/src/Template.js index 81bc197ef..b017243f2 100755 --- a/src/Template.js +++ b/src/Template.js @@ -13,6 +13,7 @@ const TemplateFileSlug = require("./TemplateFileSlug"); const ComputedData = require("./ComputedData"); const Pagination = require("./Plugins/Pagination"); const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); +const TemplateContentUnrenderedTemplateError = require("./Errors/TemplateContentUnrenderedTemplateError"); const ConsoleLogger = require("./Util/ConsoleLogger"); const debug = require("debug")("Eleventy:Template"); @@ -58,6 +59,8 @@ class Template extends TemplateContent { ); this.fileSlugStr = this.fileSlug.getSlug(); this.filePathStem = this.fileSlug.getFullPathWithoutExtension(); + + this.outputFormat = "fs"; } get logger() { @@ -73,6 +76,10 @@ class Template extends TemplateContent { this._logger = logger; } + setOutputFormat(to) { + this.outputFormat = to; + } + setIsVerbose(isVerbose) { this.isVerbose = isVerbose; this.logger.isVerbose = isVerbose; @@ -159,24 +166,29 @@ class Template extends TemplateContent { permalinkValue = permalink; } else if (isPlainObject(permalink)) { let promises = []; - let order = []; - for (let key in permalink) { - order.push(key); - promises.push(super.render(permalink[key], data, true)); + let keys = []; + if(permalink.build) { + keys.push("build"); + promises.push(super.render(permalink.build, data, true)); } + if(permalink.external) { + keys.push("external"); + promises.push(super.render(permalink.external, data, true)); + } + let results = await Promise.all(promises); - permalinkValue = {}; - for (let j = 0, k = order.length; j < k; j++) { - permalinkValue[order[j]] = results[j]; + permalinkValue = Object.assign({}, permalink); + for (let j = 0, k = keys.length; j < k; j++) { + let key = keys[j]; + permalinkValue[key] = results[j]; debug( "Rendering permalink.%o for %o: %s becomes %o", - order[j], + key, this.inputPath, - permalink, + permalink[key], results[j] ); - debugDev("Permalink rendered with data: %o", data); } } else if (permalink) { // render variables inside permalink front matter, bypass markdown @@ -204,6 +216,7 @@ class Template extends TemplateContent { ); } + // TODO add support for a key inside the `permalink` object for this async usePermalinkRoot() { if (this._usePermalinkRoot === undefined) { // TODO this only works with immediate front matter and not data files @@ -215,12 +228,6 @@ class Template extends TemplateContent { return this._usePermalinkRoot; } - isProcessible(data) { - let rawPermalinkValue = data[this.config.keys.permalink]; - let link = this._getRawPermalinkInstance(rawPermalinkValue); - return link.isProcessible; - } - // TODO instead of htmlIOException, do a global search to check if output path = input path and then add extra suffix async getOutputLocations(data) { let link = await this._getLink(data); @@ -565,7 +572,7 @@ class Template extends TemplateContent { await this.computedData.processRemainingData(data); } - async getTemplates(data) { + async getTemplates(data, shouldRender = true) { if (!Pagination.hasPagination(data)) { await this.addComputedData(data); @@ -583,11 +590,15 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if (this._templateContent === undefined) { - // should at least warn here - throw new TemplateContentPrematureUseError( - `Tried to use templateContent too early (${this.inputPath})` - ); + if(shouldRender) { + if (this._templateContent === undefined) { + // should at least warn here + throw new TemplateContentPrematureUseError( + `Tried to use templateContent too early (${this.inputPath})` + ); + } + } else { + throw new TemplateContentUnrenderedTemplateError(`Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath}`); } return this._templateContent; }, @@ -625,10 +636,14 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if (this._templateContent === undefined) { - throw new TemplateContentPrematureUseError( - `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` - ); + if(shouldRender) { + if (this._templateContent === undefined) { + throw new TemplateContentPrematureUseError( + `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` + ); + } + } else { + throw new TemplateContentUnrenderedTemplateError(`Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath} page ${this.pageNumber}`); } return this._templateContent; }, @@ -643,7 +658,7 @@ class Template extends TemplateContent { let pages = await this.getTemplates(data); await Promise.all( pages.map(async (page) => { - let content = await page.template._getContent(page.data); + let content = await page.template.render(page.data); page.templateContent = content; }) @@ -651,10 +666,6 @@ class Template extends TemplateContent { return pages; } - async _getContent(data) { - return await this.render(data); - } - async _write(outputPath, finalContent) { let shouldWriteFile = true; @@ -662,15 +673,6 @@ class Template extends TemplateContent { shouldWriteFile = false; } - if (outputPath === false) { - debug( - "Ignored %o from %o (permalink: false).", - outputPath, - this.inputPath - ); - return; - } - let lang = { start: "Writing", finished: "written.", @@ -726,7 +728,14 @@ class Template extends TemplateContent { async generateMapEntry(mapEntry, to) { return Promise.all( mapEntry._pages.map(async (page) => { - let content = await this.renderPageEntry(mapEntry, page); + let content; + + // Note that behavior.rendered is overridden when using json or ndjson output + if(mapEntry.behavior.rendered) { + // this reuses page.templateContent, it doesn’t render it + content = await this.renderPageEntry(mapEntry, page); + } + if (to === "json" || to === "ndjson") { let obj = { url: page.url, @@ -744,6 +753,24 @@ class Template extends TemplateContent { return obj; } + if(!mapEntry.behavior.rendered) { + debug( + "Template not written %o from %o (via permalink.behavior).", + page.outputPath, + mapEntry.template.inputPath + ); + return; + } + + if (!mapEntry.behavior.writeable) { + debug( + "Template not written %o from %o (via permalink: false, permalink.build: false, or a permalink object without a build property).", + page.outputPath, + mapEntry.template.inputPath + ); + return; + } + return this._write(page.outputPath, content); }) ); @@ -849,17 +876,20 @@ class Template extends TemplateContent { async getTemplateMapContent(pageMapEntry) { pageMapEntry.template.setWrapWithLayouts(false); - let content = await pageMapEntry.template._getContent(pageMapEntry.data); + let content = await pageMapEntry.template.render(pageMapEntry.data); pageMapEntry.template.setWrapWithLayouts(true); return content; } - async getTemplateMapEntries() { + async getTemplateMapEntries(dataOverride) { debugDev("%o getMapped()", this.inputPath); // Important reminder: This is where the template data is first generated via TemplateMap - let data = await this.getData(); + let data = dataOverride || await this.getData(); + + let rawPermalinkValue = data[this.config.keys.permalink]; + let link = this._getRawPermalinkInstance(rawPermalinkValue); let entries = []; // does not return outputPath or url, we don’t want to render permalinks yet @@ -867,6 +897,11 @@ class Template extends TemplateContent { template: this, inputPath: this.inputPath, data, + behavior: { + ignored: link.isTemplateIgnored(), + rendered: this.outputFormat === "json" || this.outputFormat === "ndjson" || link.isTemplateRendered(), + writeable: link.isTemplateWriteable(), + } }); return entries; } diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 8456f253d..f18edb917 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -206,7 +206,7 @@ class TemplateConfig { Object.keys(localConfig.filters).length ) { throw new EleventyConfigError( - `The \`filters\` configuration option was renamed in Eleventy 0.3.3 and removed in Eleventy 1.0. Please use the \`addTransform\` configuration method instead. Read more: https://www.11ty.dev/docs/config/#transforms` + "The `filters` configuration option was renamed in Eleventy 0.3.3 and removed in Eleventy 1.0. Please use the `addTransform` configuration method instead. Read more: https://www.11ty.dev/docs/config/#transforms" ); } } catch (err) { diff --git a/src/TemplateMap.js b/src/TemplateMap.js index cd02ffd24..2c30e1493 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -36,7 +36,6 @@ class TemplateMap { get userConfig() { if (!this._userConfig) { - this.config = this.eleventyConfig.getConfig(); // TODO use this.config for this, need to add collections to mergable props in userconfig this._userConfig = this.eleventyConfig.userConfig; } @@ -44,6 +43,13 @@ class TemplateMap { return this._userConfig; } + get config() { + if(!this._config) { + this._config = this.eleventyConfig.getConfig(); + } + return this._config; + } + get tagPrefix() { return "___TAG___"; } @@ -264,10 +270,10 @@ class TemplateMap { } else { // is a template entry let map = this.getMapEntryForInputPath(depEntry); - if (!map.template.isProcessible(map.data)) { + if (map.behavior.ignored) { map._pages = []; } else { - map._pages = await map.template.getTemplates(map.data); + map._pages = await map.template.getTemplates(map.data, map.behavior.rendered); let counter = 0; for (let page of map._pages) { @@ -326,12 +332,34 @@ class TemplateMap { return this.getMapEntryForInputPath(inputPath); }.bind(this) ); + await this.populateContentDataInMap(orderedMap); this.populateCollectionsWithContent(); this.cached = true; this.checkForDuplicatePermalinks(); + + await this.config.events.emit("dependencyMap", this.generateDependencyMapEventObject(orderedMap)); + } + + generateDependencyMapEventObject(orderedMap) { + let entries = []; + for(let entry of orderedMap) { + let ret = { + inputPath: entry.inputPath, + isExternal: !!(entry.data.permalink && entry.data.permalink.external) + }; + + // TODO `needs: []` array of inputPath or glob? this template uses + + for(let page of entry._pages) { + entries.push(Object.assign({}, ret, { + url: page.url + })); + } + } + return entries; } // TODO(slightlyoff): hot inner loop? @@ -381,6 +409,9 @@ class TemplateMap { if (!map._pages) { throw new Error(`Content pages not found for ${map.inputPath}`); } + if(!map.behavior.rendered) { + continue; + } try { for (let pageEntry of map._pages) { pageEntry.templateContent = await map.template.getTemplateMapContent( diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 8851b7d4b..b0a8626c6 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -6,41 +6,56 @@ const isPlainObject = require("lodash/isPlainObject"); class TemplatePermalink { // `link` with template syntax should have already been rendered in Template.js constructor(link, extraSubdir) { - // these defaults may get overriden below - this.isProcessible = true; - this.outputToFileSystem = true; - - if (link === true) { - throw new Error( - "`permalink: true` is not a supported feature in Eleventy. Did you mean `permalink: false`?" - ); - } - if (link === false) { - // permalink: false // doesn’t match `permalink: build: false` only for backwards compat - this.outputToFileSystem = false; - return; - } + let isLinkAnObject = isPlainObject(link); + + this._isIgnoredTemplate = false; + this._isRendered = true; + this._outputToFileSystem = true; let rawLink; - if (isPlainObject(link)) { + if (isLinkAnObject) { if ("build" in link) { rawLink = link.build; - // permalink: build: true - // permalink: build: false - if (typeof rawLink === "boolean") { - this.outputToFileSystem = false; - this.isProcessible = rawLink; - } - } else { - // opt out of build - this.outputToFileSystem = false; - this.isProcessible = false; } } else { rawLink = link; } - this.rawLink = rawLink; + // permalink: false and permalink: build: false + if (typeof rawLink === "boolean") { + if(rawLink === false) { + this._outputToFileSystem = false; + } else { + throw new Error( + `\`permalink: ${isLinkAnObject ? "build: " : ""}true\` is not a supported feature in Eleventy. Did you mean \`permalink: ${isLinkAnObject ? "build: " : ""}false\`?` + ); + } + } else if(rawLink) { + this.rawLink = rawLink; + } + + if(isLinkAnObject) { + if("external" in link) { + this.externalLink = link.external; + } + + // default for permalink objects without a build URL + if(!("behavior" in link) && !("build" in link)) { + link.behavior = "skip-render"; + } + + if(link.behavior === "skip-write") { // same as permalink: false and permalink: build: false + this._outputToFileSystem = false; + } else if(link.behavior === "skip-render") { + this._outputToFileSystem = false; + this._isRendered = false; + } else if(link.behavior === "skip") { + this._outputToFileSystem = false; + this._isRendered = false; + this._isIgnoredTemplate = true; + } + } + this.extraPaginationSubdir = extraSubdir || ""; } @@ -49,7 +64,7 @@ class TemplatePermalink { } toLink() { - if (!this.outputToFileSystem) { + if (!this.rawLink) { // empty or false return false; } @@ -67,7 +82,10 @@ class TemplatePermalink { // index.html becomes / // test/index.html becomes test/ toHref() { - if (!this.outputToFileSystem) { + if(this.externalLink) { + return this.externalLink; + } + if (!this.rawLink) { // empty or false return false; } @@ -103,8 +121,16 @@ class TemplatePermalink { return normalize(uri); } - isTemplateProcessable() { - return this.isProcessible; + isTemplateIgnored() { + return this._isIgnoredTemplate; + } + + isTemplateRendered() { + return this._isRendered; + } + + isTemplateWriteable() { + return this._outputToFileSystem; } static _hasDuplicateFolder(dir, base) { diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 020170953..975290515 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -158,7 +158,7 @@ class TemplateWriter { ); } - _createTemplate(path, allPaths) { + _createTemplate(path, allPaths, to = "fs") { let tmpl = this._templatePathCache.get(path); if (!tmpl) { tmpl = new Template( @@ -169,6 +169,7 @@ class TemplateWriter { this.extensionMap, this.eleventyConfig ); + tmpl.setOutputFormat(to); tmpl.logger = this.logger; this._templatePathCache.set(path, tmpl); @@ -221,11 +222,11 @@ class TemplateWriter { return tmpl; } - async _addToTemplateMap(paths) { + async _addToTemplateMap(paths, to = "fs") { let promises = []; for (let path of paths) { if (this.extensionMap.hasEngine(path)) { - promises.push(this.templateMap.add(this._createTemplate(path, paths))); + promises.push(this.templateMap.add(this._createTemplate(path, paths, to))); } debug(`${path} begun adding to map.`); } @@ -233,10 +234,10 @@ class TemplateWriter { return Promise.all(promises); } - async _createTemplateMap(paths) { + async _createTemplateMap(paths, to) { this.templateMap = new TemplateMap(this.eleventyConfig); - await this._addToTemplateMap(paths); + await this._addToTemplateMap(paths, to); await this.templateMap.cache(); debugDev("TemplateMap cache complete."); @@ -270,7 +271,7 @@ class TemplateWriter { // console.time("generateTemplates:_createTemplateMap"); // TODO optimize await here - await this._createTemplateMap(paths); + await this._createTemplateMap(paths, to); // console.timeEnd("generateTemplates:_createTemplateMap"); debug("Template map created."); diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 78946e906..3af39f9aa 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -2,6 +2,7 @@ const test = require("ava"); const TemplateMap = require("../src/TemplateMap"); const TemplateCollection = require("../src/TemplateCollection"); const UsingCircularTemplateContentReferenceError = require("../src/Errors/UsingCircularTemplateContentReferenceError"); +const TemplateContentUnrenderedTemplateError = require("../src/Errors/TemplateContentUnrenderedTemplateError"); const normalizeNewLines = require("./Util/normalizeNewLines"); const TemplateConfig = require("../src/TemplateConfig"); @@ -1123,7 +1124,7 @@ test("Async user collection addCollection method", async (t) => { await tm.add(tmpl1); tm.setUserConfigCollections({ userCollection: async function (collection) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { setTimeout(function () { resolve(collection.getAll()); }, 50); @@ -1264,20 +1265,25 @@ test("permalink object with build", async (t) => { t.is(map[0]._pages.length, 1); }); -test("permalink object without build", async (t) => { +test("permalink object without build (defaults to no-render mode)", async (t) => { let eleventyConfig = new TemplateConfig(); let tm = new TemplateMap(eleventyConfig); - let tmplLayout = getNewTemplate( + let tmpl = getNewTemplate( "./test/stubs/permalink-nobuild/permalink-nobuild.md", "./test/stubs/", "./test/stubs/_site", eleventyConfig ); - await tm.add(tmplLayout); + await tm.add(tmpl); let map = tm.getMap(); await tm.cache(); - t.is(map[0]._pages.length, 0); + t.is(map[0]._pages.length, 1); + t.throws(() => { + map[0]._pages[0].templateContent; + }, { + instanceOf: TemplateContentUnrenderedTemplateError + }); }); diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index b2c9021cf..f1f4ff6f5 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -163,12 +163,11 @@ test("Permalink Object, just build", (t) => { false ); - t.is( + t.throws(() => { new TemplatePermalink({ build: true, - }).toLink(), - false - ); + }).toLink(); + }); t.is( new TemplatePermalink({ diff --git a/test/TemplateTest.js b/test/TemplateTest.js index e254cc1f5..2db15a0e2 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -19,11 +19,32 @@ async function getRenderedData(tmpl, pageNumber = 0) { return templates[pageNumber].data; } +async function getTemplateMapEntriesWithContent(template, data) { + let entries = await template.getTemplateMapEntries(data); + + return Promise.all( + entries.map(async (entry) => { + entry._pages = await entry.template.getTemplates(entry.data); + await Promise.all( + entry._pages.map(async (page) => { + page.templateContent = await entry.template.getTemplateMapContent( + page + ); + return page; + }) + ); + return entry; + }) + ); +} + async function write(tmpl, data) { - let templates = await tmpl.getRenderedTemplates(data); + let mapEntries = await getTemplateMapEntriesWithContent(tmpl, data); let promises = []; - for (let template of templates) { - promises.push(tmpl._write(template.outputPath, template.templateContent)); + for (let entry of mapEntries) { + if(entry.behavior.writeable) { + promises.push(tmpl._write(entry.outputPath, entry.templateContent)); + } } return Promise.all(promises); } @@ -376,7 +397,7 @@ test("Liquid template", async (t) => { eleventyConfig ); - t.is(await tmpl.render(await tmpl.getData()), `

Zach

`); + t.is(await tmpl.render(await tmpl.getData()), "

Zach

"); }); test("Liquid template with include", async (t) => { @@ -1103,7 +1124,7 @@ test("Override base templating engine from .njk to ejs (with a layout that uses t.is( (await tmpl.render(await tmpl.getData())).trim(), - '

My Title

' + `

My Title

` ); }); @@ -1291,7 +1312,7 @@ test("Test a single asynchronous transform", async (t) => { tmpl.addTransform("transformName", async function (content, outputPath) { t.true(outputPath.endsWith("template/index.html")); - return new Promise((resolve, reject) => { + return new Promise((resolve) => { setTimeout(function (str, outputPath) { resolve("OVERRIDE BY A TRANSFORM"); }, 50); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 33eef68c0..c8f9d4526 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -486,7 +486,7 @@ test("Custom collection returns a string", async (t) => { eleventyConfig ); - tw.userConfig.addCollection("returnATestString", function (collection) { + tw.userConfig.addCollection("returnATestString", function () { return "test"; }); @@ -709,6 +709,7 @@ test("Passthrough file output", async (t) => { "./test/stubs/template-passthrough/static/**/*": "./all/", "./test/stubs/template-passthrough/static/**/*.js": "./js/", }; + let tw = new TemplateWriter( "./test/stubs/template-passthrough/", "./test/stubs/template-passthrough/_site", @@ -717,8 +718,6 @@ test("Passthrough file output", async (t) => { eleventyConfig ); - const mgr = tw.eleventyFiles.getPassthroughManager(); - await tw.write(); const output = [ diff --git a/test/stubs/permalink-true/permalink-true.md b/test/stubs/permalink-true/permalink-true.md index b4b85d57c..e836beb7a 100644 --- a/test/stubs/permalink-true/permalink-true.md +++ b/test/stubs/permalink-true/permalink-true.md @@ -2,4 +2,4 @@ permalink: true --- -This shouldn’t write +This should throw an error. From 4786d718940f66ebca6b664138a75f1a5656413e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 9 Apr 2021 14:51:58 -0500 Subject: [PATCH 386/746] Add a TODO --- cmd.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd.js b/cmd.js index 00bea702e..df0c9e591 100755 --- a/cmd.js +++ b/cmd.js @@ -49,6 +49,8 @@ try { ); }, }); + + // TODO fix debug output: `Eleventy:cmd command: eleventy [object Object] +0ms` debug("command: eleventy ", argv.toString()); const Eleventy = require("./src/Eleventy"); From 5fe9968eecf2f86e2117209cec8201c12b888b33 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 9 Apr 2021 14:57:03 -0500 Subject: [PATCH 387/746] Rename `permalink.external` to `permalink.cloud` --- src/Template.js | 33 ++++++++++++++++++++------------- src/TemplateMap.js | 28 ++++++++++++++++++---------- src/TemplatePermalink.js | 33 ++++++++++++++++++++------------- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/Template.js b/src/Template.js index b017243f2..30f39d760 100755 --- a/src/Template.js +++ b/src/Template.js @@ -167,13 +167,13 @@ class Template extends TemplateContent { } else if (isPlainObject(permalink)) { let promises = []; let keys = []; - if(permalink.build) { + if (permalink.build) { keys.push("build"); promises.push(super.render(permalink.build, data, true)); } - if(permalink.external) { - keys.push("external"); - promises.push(super.render(permalink.external, data, true)); + if (permalink.cloud) { + keys.push("cloud"); + promises.push(super.render(permalink.cloud, data, true)); } let results = await Promise.all(promises); @@ -590,7 +590,7 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if(shouldRender) { + if (shouldRender) { if (this._templateContent === undefined) { // should at least warn here throw new TemplateContentPrematureUseError( @@ -598,7 +598,9 @@ class Template extends TemplateContent { ); } } else { - throw new TemplateContentUnrenderedTemplateError(`Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath}`); + throw new TemplateContentUnrenderedTemplateError( + `Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath}` + ); } return this._templateContent; }, @@ -636,14 +638,16 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if(shouldRender) { + if (shouldRender) { if (this._templateContent === undefined) { throw new TemplateContentPrematureUseError( `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` ); } } else { - throw new TemplateContentUnrenderedTemplateError(`Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath} page ${this.pageNumber}`); + throw new TemplateContentUnrenderedTemplateError( + `Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath} page ${this.pageNumber}` + ); } return this._templateContent; }, @@ -731,7 +735,7 @@ class Template extends TemplateContent { let content; // Note that behavior.rendered is overridden when using json or ndjson output - if(mapEntry.behavior.rendered) { + if (mapEntry.behavior.rendered) { // this reuses page.templateContent, it doesn’t render it content = await this.renderPageEntry(mapEntry, page); } @@ -753,7 +757,7 @@ class Template extends TemplateContent { return obj; } - if(!mapEntry.behavior.rendered) { + if (!mapEntry.behavior.rendered) { debug( "Template not written %o from %o (via permalink.behavior).", page.outputPath, @@ -886,7 +890,7 @@ class Template extends TemplateContent { debugDev("%o getMapped()", this.inputPath); // Important reminder: This is where the template data is first generated via TemplateMap - let data = dataOverride || await this.getData(); + let data = dataOverride || (await this.getData()); let rawPermalinkValue = data[this.config.keys.permalink]; let link = this._getRawPermalinkInstance(rawPermalinkValue); @@ -899,9 +903,12 @@ class Template extends TemplateContent { data, behavior: { ignored: link.isTemplateIgnored(), - rendered: this.outputFormat === "json" || this.outputFormat === "ndjson" || link.isTemplateRendered(), + rendered: + this.outputFormat === "json" || + this.outputFormat === "ndjson" || + link.isTemplateRendered(), writeable: link.isTemplateWriteable(), - } + }, }); return entries; } diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 2c30e1493..d325fb543 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -44,7 +44,7 @@ class TemplateMap { } get config() { - if(!this._config) { + if (!this._config) { this._config = this.eleventyConfig.getConfig(); } return this._config; @@ -273,7 +273,10 @@ class TemplateMap { if (map.behavior.ignored) { map._pages = []; } else { - map._pages = await map.template.getTemplates(map.data, map.behavior.rendered); + map._pages = await map.template.getTemplates( + map.data, + map.behavior.rendered + ); let counter = 0; for (let page of map._pages) { @@ -340,23 +343,28 @@ class TemplateMap { this.checkForDuplicatePermalinks(); - await this.config.events.emit("dependencyMap", this.generateDependencyMapEventObject(orderedMap)); + await this.config.events.emit( + "dependencyMap", + this.generateDependencyMapEventObject(orderedMap) + ); } generateDependencyMapEventObject(orderedMap) { let entries = []; - for(let entry of orderedMap) { + for (let entry of orderedMap) { let ret = { inputPath: entry.inputPath, - isExternal: !!(entry.data.permalink && entry.data.permalink.external) + isExternal: !!(entry.data.permalink && entry.data.permalink.cloud), }; // TODO `needs: []` array of inputPath or glob? this template uses - for(let page of entry._pages) { - entries.push(Object.assign({}, ret, { - url: page.url - })); + for (let page of entry._pages) { + entries.push( + Object.assign({}, ret, { + url: page.url, + }) + ); } } return entries; @@ -409,7 +417,7 @@ class TemplateMap { if (!map._pages) { throw new Error(`Content pages not found for ${map.inputPath}`); } - if(!map.behavior.rendered) { + if (!map.behavior.rendered) { continue; } try { diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index b0a8626c6..da03cbbec 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -23,33 +23,38 @@ class TemplatePermalink { // permalink: false and permalink: build: false if (typeof rawLink === "boolean") { - if(rawLink === false) { + if (rawLink === false) { this._outputToFileSystem = false; } else { throw new Error( - `\`permalink: ${isLinkAnObject ? "build: " : ""}true\` is not a supported feature in Eleventy. Did you mean \`permalink: ${isLinkAnObject ? "build: " : ""}false\`?` + `\`permalink: ${ + isLinkAnObject ? "build: " : "" + }true\` is not a supported feature in Eleventy. Did you mean \`permalink: ${ + isLinkAnObject ? "build: " : "" + }false\`?` ); } - } else if(rawLink) { + } else if (rawLink) { this.rawLink = rawLink; } - if(isLinkAnObject) { - if("external" in link) { - this.externalLink = link.external; + if (isLinkAnObject) { + if ("external" in link) { + this.externalLink = link.cloud; } // default for permalink objects without a build URL - if(!("behavior" in link) && !("build" in link)) { + if (!("behavior" in link) && !("build" in link)) { link.behavior = "skip-render"; } - if(link.behavior === "skip-write") { // same as permalink: false and permalink: build: false + if (link.behavior === "skip-write") { + // same as permalink: false and permalink: build: false this._outputToFileSystem = false; - } else if(link.behavior === "skip-render") { + } else if (link.behavior === "skip-render") { this._outputToFileSystem = false; this._isRendered = false; - } else if(link.behavior === "skip") { + } else if (link.behavior === "skip") { this._outputToFileSystem = false; this._isRendered = false; this._isIgnoredTemplate = true; @@ -64,7 +69,8 @@ class TemplatePermalink { } toLink() { - if (!this.rawLink) { // empty or false + if (!this.rawLink) { + // empty or false return false; } @@ -82,10 +88,11 @@ class TemplatePermalink { // index.html becomes / // test/index.html becomes test/ toHref() { - if(this.externalLink) { + if (this.externalLink) { return this.externalLink; } - if (!this.rawLink) { // empty or false + if (!this.rawLink) { + // empty or false return false; } From eeab196389d6d4bcfe995393fe32c6b3954142d5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 9 Apr 2021 14:57:29 -0500 Subject: [PATCH 388/746] v1.0.0-canary.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea165c146..ab741a035 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.10", + "version": "1.0.0-canary.11", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 2968d37ab6023636e6a83e1a9eff7f2823cbd82f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 9 Apr 2021 17:07:27 -0500 Subject: [PATCH 389/746] Wrong property. --- src/TemplatePermalink.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index da03cbbec..0791f644b 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -39,7 +39,7 @@ class TemplatePermalink { } if (isLinkAnObject) { - if ("external" in link) { + if ("cloud" in link) { this.externalLink = link.cloud; } From 2cc06c646e762b6a9adf1077546c7893cdaafe27 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 9 Apr 2021 17:08:08 -0500 Subject: [PATCH 390/746] v1.0.0-canary.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab741a035..b72ceac8b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.11", + "version": "1.0.0-canary.12", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 749e5c1683e0c49aeb581b0d5781f955472aa536 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 10 Apr 2021 09:57:21 -0500 Subject: [PATCH 391/746] Add option to use absolute path for config file path. --- src/TemplateConfig.js | 23 ++++++++++------------- src/TemplatePath.js | 14 ++++++++++---- test/TemplatePathTest.js | 8 ++++++++ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index f18edb917..075d119db 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -34,10 +34,10 @@ class EleventyConfigError extends EleventyBaseError {} * Config for a template. * * @param {{}} customRootConfig - tbd. - * @param {String} localProjectConfigPath - Path to local project config. + * @param {String} projectConfigPath - Path to local project config. */ class TemplateConfig { - constructor(customRootConfig, localProjectConfigPath) { + constructor(customRootConfig, projectConfigPath) { this.userConfig = new UserConfig(); /** @member {module:11ty/eleventy/TemplateConfig~TemplateConfig~override} - tbd. */ @@ -47,7 +47,7 @@ class TemplateConfig { * @member {String} - Path to local project config. * @default .eleventy.js */ - this.localProjectConfigPath = localProjectConfigPath || ".eleventy.js"; + this.projectConfigPath = projectConfigPath || ".eleventy.js"; if (customRootConfig) { /** @@ -71,7 +71,7 @@ class TemplateConfig { * @returns {String} - The normalised local project config file path. */ getLocalProjectConfigFile() { - return TemplatePath.addLeadingDotSlash(this.localProjectConfigPath); + return TemplatePath.addLeadingDotSlash(this.projectConfigPath); } get inputDir() { @@ -89,7 +89,7 @@ class TemplateConfig { debugDev("Resetting configuration: TemplateConfig and UserConfig."); this.userConfig.reset(); this.initializeRootConfig(); - this.config = this.mergeConfig(this.localProjectConfigPath); + this.config = this.mergeConfig(this.projectConfigPath); } /** @@ -109,7 +109,7 @@ class TemplateConfig { getConfig() { if (!this.hasConfigMerged) { debugDev("Merging via getConfig (first time)"); - this.config = this.mergeConfig(this.localProjectConfigPath); + this.config = this.mergeConfig(this.projectConfigPath); this.hasConfigMerged = true; } return this.config; @@ -121,7 +121,7 @@ class TemplateConfig { * @param {String} path - The new config path. */ setProjectConfigPath(path) { - this.localProjectConfigPath = path; + this.projectConfigPath = path; if (this.hasConfigMerged) { // merge it again @@ -163,15 +163,12 @@ class TemplateConfig { /** * Merges different config files together. * - * @param {String} localProjectConfigPath - Path to local project config. + * @param {String} projectConfigPath - Path to project config. * @returns {{}} merged - The merged config file. */ - mergeConfig(localProjectConfigPath) { + mergeConfig(projectConfigPath) { let localConfig = {}; - let path = TemplatePath.join( - TemplatePath.getWorkingDir(), - localProjectConfigPath - ); + let path = TemplatePath.absolutePath(projectConfigPath); debug(`Merging config with ${path}`); diff --git a/src/TemplatePath.js b/src/TemplatePath.js index f63a76d3e..a4c94d31a 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -134,11 +134,9 @@ TemplatePath.normalizeUrlPath = function (...urlPaths) { */ TemplatePath.absolutePath = function (...paths) { let i = 0; + // check all the paths before we short circuit from the first index for (let path of paths) { - if (path.startsWith("/")) { - if (i === 0) { - return path; - } + if (path.startsWith("/") && i > 0) { throw new Error( `Only the first parameter to Template.absolutePath can be an absolute path. Received: ${path} from ${paths}` ); @@ -146,6 +144,14 @@ TemplatePath.absolutePath = function (...paths) { i++; } + let j = 0; + for (let path of paths) { + if (j === 0 && path.startsWith("/")) { + return TemplatePath.join(...paths); + } + j++; + } + return TemplatePath.join(TemplatePath.getWorkingDir(), ...paths); }; diff --git a/test/TemplatePathTest.js b/test/TemplatePathTest.js index e8cda9faf..6c7600a2e 100644 --- a/test/TemplatePathTest.js +++ b/test/TemplatePathTest.js @@ -130,6 +130,14 @@ test("absolutePath", (t) => { ".eleventy.js" ); t.is(TemplatePath.absolutePath("/tmp/.eleventy.js"), "/tmp/.eleventy.js"); + t.is( + TemplatePath.absolutePath("/var/task/", ".eleventy.js"), + "/var/task/.eleventy.js" + ); + + t.throws(() => { + TemplatePath.absolutePath("/var/task/", "/var/task/.eleventy.js"); + }); t.throws(() => { TemplatePath.absolutePath("file1.js", "test/file2.js", "/tmp/.eleventy.js"); From 3fbde5803906d042a34b7212d3bc4716ac462562 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 10 Apr 2021 13:53:10 -0500 Subject: [PATCH 392/746] Add a few comments. --- src/BenchmarkGroup.js | 1 + src/EleventyFiles.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index 708b52ec9..d986dcefb 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -92,6 +92,7 @@ class BenchmarkGroup { ); } + // TODO move the % to the beginning of the string for easier comparison let str = `Benchmark (${label}): ${type} took ${totalForBenchmark.toFixed( 0 )}ms ${extraOutput.length ? `(${extraOutput.join(", ")})` : ""}`; diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 1c5d12e25..860047bec 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -116,6 +116,7 @@ class EleventyFiles { } /* Set command root for local project paths */ + // This is only used by tests _setLocalPathRoot(dir) { this.localPathRoot = dir; } From e05e629acf7c46a3185afc89ad967751980d3c15 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 10 Apr 2021 13:54:44 -0500 Subject: [PATCH 393/746] v1.0.0-canary.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b72ceac8b..1eccc98e8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.12", + "version": "1.0.0-canary.13", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 47a8f42cd025099d0147eb68e714a2c408328196 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 11 Apr 2021 21:09:30 -0500 Subject: [PATCH 394/746] Updates to dependency tree v2, adds `globalDataFiles` event --- package.json | 2 +- src/TemplateData.js | 2 ++ test/TemplateDataTest.js | 5 ++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1eccc98e8..e3e230047 100755 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "vue-server-renderer": "^2.6.12" }, "dependencies": { - "@11ty/dependency-tree": "^1.0.0", + "@11ty/dependency-tree": "^2.0.0", "browser-sync": "^2.26.14", "chalk": "^4.1.0", "chokidar": "^3.5.1", diff --git a/src/TemplateData.js b/src/TemplateData.js index a1a55e2db..ef51782d8 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -249,6 +249,8 @@ class TemplateData { await this.getGlobalDataFiles() ); + this.config.events.emit("globalDataFiles", files); + let dataFileConflicts = {}; for (let j = 0, k = files.length; j < k; j++) { diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index cdb67b993..90a6ee0a0 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -429,15 +429,14 @@ test("TemplateData.cleanupData", (t) => { }); test("Parent directory for data (Issue #337)", async (t) => { - let eleventyConfig = new TemplateConfig(); - let dataObj = new TemplateData("./test/stubs-337/src/", eleventyConfig); - dataObj._setConfig({ + let eleventyConfig = new TemplateConfig({ dataTemplateEngine: false, dir: { input: "./test/stubs-337/src/", data: "../data/", }, }); + let dataObj = new TemplateData("./test/stubs-337/src/", eleventyConfig); dataObj.setInputDir("./test/stubs-337/src/"); let data = await dataObj.getData(); From 6a982db8da6f9db16eb906af3f087bf27a66b4bf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 11 Apr 2021 21:09:53 -0500 Subject: [PATCH 395/746] v1.0.0-canary.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3e230047..b338e508b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.13", + "version": "1.0.0-canary.14", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 2be4ac0956bdc9ede96123fdedf9c2cc4effd5d5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 15 Apr 2021 17:50:07 -0500 Subject: [PATCH 396/746] Option to use inject precompiled collections via a config option. --- src/TemplateMap.js | 38 ++++++++++++++++++++++++++++---------- src/UserConfig.js | 6 ++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/TemplateMap.js b/src/TemplateMap.js index d325fb543..7241f36a7 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -252,6 +252,28 @@ class TemplateMap { return graph.overallOrder(); } + async setCollectionByTagName(tagName) { + if (this.isUserConfigCollectionName(tagName)) { + // async + this.collectionsData[tagName] = await this.getUserConfigCollection( + tagName + ); + } else { + this.collectionsData[tagName] = this.getTaggedCollection(tagName); + } + + let precompiled = this.config.precompiledCollections; + if (precompiled && precompiled[tagName]) { + if ( + tagName === "all" || + !Array.isArray(this.collectionsData[tagName]) || + this.collectionsData[tagName].length === 0 + ) { + this.collectionsData[tagName] = precompiled[tagName]; + } + } + } + // TODO(slightlyoff): major bottleneck async initDependencyMap(dependencyMap) { let tagPrefix = this.tagPrefix; @@ -259,14 +281,7 @@ class TemplateMap { if (depEntry.startsWith(tagPrefix)) { // is a tag (collection) entry let tagName = depEntry.substr(tagPrefix.length); - if (this.isUserConfigCollectionName(tagName)) { - // async - this.collectionsData[tagName] = await this.getUserConfigCollection( - tagName - ); - } else { - this.collectionsData[tagName] = this.getTaggedCollection(tagName); - } + await this.setCollectionByTagName(tagName); } else { // is a template entry let map = this.getMapEntryForInputPath(depEntry); @@ -564,8 +579,11 @@ class TemplateMap { } let entry = this.getMapEntryForInputPath(item.inputPath); - let index = item.pageNumber || 0; - item.templateContent = entry._pages[index]._templateContent; + // This check skips precompiled collections + if (entry) { + let index = item.pageNumber || 0; + item.templateContent = entry._pages[index]._templateContent; + } } } } diff --git a/src/UserConfig.js b/src/UserConfig.js index 083b44d9c..2b2089e1e 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -20,6 +20,7 @@ class UserConfig { debug("Resetting EleventyConfig to initial values."); this.events = new EventEmitter(); this.collections = {}; + this.precompiledCollections = {}; this.templateFormats = undefined; this.liquidOptions = {}; @@ -665,6 +666,10 @@ class UserConfig { this.useTemplateCache = !!bypass; } + setPrecompiledCollections(collections) { + this.precompiledCollections = collections; + } + getMergingConfigObject() { return { templateFormats: this.templateFormats, @@ -710,6 +715,7 @@ class UserConfig { quietMode: this.quietMode, events: this.events, useTemplateCache: this.useTemplateCache, + precompiledCollections: this.precompiledCollections, }; } } From 4fdd4f525a02f19e48b90fb626c8de246c41f78b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 15 Apr 2021 17:54:58 -0500 Subject: [PATCH 397/746] v1.0.0-canary.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b338e508b..22455b2c5 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.14", + "version": "1.0.0-canary.15", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From f727959188c0dedcdd6ad42182ad2793191a90ff Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 18 Apr 2021 14:53:29 -0500 Subject: [PATCH 398/746] Tests for https://github.com/11ty/11ty-website/pull/1001 --- test/TemplateRenderLiquidTest.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 758d93a12..01d88667f 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1030,3 +1030,19 @@ test("Liquid bypass compilation", async (t) => { ); t.is(tr.engine.needsCompilation("

test

"), false); }); + +test("Liquid reverse filter in {{ }}", async (t) => { + // https://liquidjs.com/filters/reverse.html + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( + "{{ test | reverse }}" + ); + t.is(await fn({ test: [1, 2, 3] }), "[3,2,1]"); +}); + +test("Liquid reverse filter in {% for %}", async (t) => { + // https://liquidjs.com/tags/for.html#reversed + let fn = await getNewTemplateRender("liquid").getCompiledTemplate( + "{% for num in test reversed %}{{ num }}{% endfor %}" + ); + t.is(await fn({ test: [1, 2, 3] }), "321"); +}); From 2a85ed655ba2dfae8fed0e9d69ac59af65edd87e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 18 Apr 2021 14:53:53 -0500 Subject: [PATCH 399/746] Tests for https://github.com/11ty/11ty-website/pull/1001 --- test/TemplateRenderLiquidTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 01d88667f..ec99a850c 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1036,7 +1036,7 @@ test("Liquid reverse filter in {{ }}", async (t) => { let fn = await getNewTemplateRender("liquid").getCompiledTemplate( "{{ test | reverse }}" ); - t.is(await fn({ test: [1, 2, 3] }), "[3,2,1]"); + t.is(await fn({ test: [1, 2, 3] }), "3,2,1"); }); test("Liquid reverse filter in {% for %}", async (t) => { From cea3c94256c62c9e0fe9fffccfab2663b30465fb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 19 Apr 2021 10:08:47 -0500 Subject: [PATCH 400/746] Fixes #1684 --- src/Eleventy.js | 3 +-- test/EleventyTest.js | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index ff53faa8b..47a9bbaab 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -1,7 +1,6 @@ const pkg = require("../package.json"); const TemplatePath = require("./TemplatePath"); const TemplateData = require("./TemplateData"); -const TemplateContent = require("./TemplateContent"); const TemplateWriter = require("./TemplateWriter"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyErrorHandler = require("./EleventyErrorHandler"); @@ -96,7 +95,7 @@ class Eleventy { /** @member {Object} - tbd. */ this.eleventyServe = new EleventyServe(); - this.eleventyServe.config = this.eleventyConfig; + this.eleventyServe.config = this.config; /** @member {String} - Holds the path to the input directory. */ this.rawInput = input; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index bbf2157b1..3b4d6d7a5 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -229,8 +229,9 @@ test("Config propagates to other instances correctly", async (t) => { let elev = new Eleventy(); await elev.init(); + t.is(elev.eleventyServe.config, elev.config); + t.is(elev.extensionMap.eleventyConfig, elev.eleventyConfig); - t.is(elev.eleventyServe.config, elev.eleventyConfig); t.is(elev.eleventyFiles.eleventyConfig, elev.eleventyConfig); t.is(elev.templateData.eleventyConfig, elev.eleventyConfig); t.is(elev.writer.eleventyConfig, elev.eleventyConfig); From f60b5b7430195b9f38328f3d0241af9ca2053383 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 20 Apr 2021 11:52:20 -0500 Subject: [PATCH 401/746] Switch SASS from node-sass to sass package for Node 16 compat --- package.json | 2 +- test/TemplateRenderCustomTest.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 22455b2c5..eaaeb68c9 100755 --- a/package.json +++ b/package.json @@ -82,10 +82,10 @@ "jsdoc": "3.6.6", "lint-staged": "^10.5.4", "markdown-it-emoji": "^2.0.0", - "node-sass": "^5.0.0", "nyc": "^15.1.0", "prettier": "^2.2.1", "rimraf": "^3.0.2", + "sass": "^1.32.11", "toml": "^3.0.0", "viperhtml": "^2.17.1", "vue": "^2.6.12", diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index 91458329d..b0fc3a5d5 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -56,7 +56,7 @@ test("Custom Vue Render", async (t) => { t.is(await fn({ test: "Hello" }), `

Hello

`); }); -const sass = require("node-sass"); +const sass = require("sass"); test("Custom Sass Render", async (t) => { let tr = getNewTemplateRender("sass"); @@ -72,6 +72,7 @@ test("Custom Sass Render", async (t) => { data: str, includePaths: [tr.inputDir, tr.includesDir], style: "expanded", + indentType: "space", // TODO // sourcemap: "file", outFile: "test_this_is_to_not_write_a_file.css", @@ -93,6 +94,7 @@ test("Custom Sass Render", async (t) => { t.is( (await fn({})).trim(), `p { - color: blue; }` + color: blue; +}` ); }); From 046fbf6320047c61317ddc3c4c1c54ca5ad9824a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 20 Apr 2021 11:52:44 -0500 Subject: [PATCH 402/746] Move from Node 15 to Node 16 for GitHub Actions tests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c65928424..8ed6b98d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - node: ["12", "14", "15"] + node: ["12", "14", "16"] name: Node.js ${{ matrix.node }} on ${{ matrix.os }} steps: - uses: actions/checkout@v2 From 8b2adca1ff07566147a083e2c87a692a38f1d973 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 20 Apr 2021 12:11:33 -0500 Subject: [PATCH 403/746] Unreliable timing based test on CI --- test/BenchmarkTest.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index 6f57bc990..e6f5e633e 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -42,7 +42,6 @@ test.cb("Reset Benchmark", (t) => { setTimeout(function () { b.before(); b.after(); - t.truthy(b.getTotal() <= 0.1); t.throws(function () { // throws because we reset From f72751f0e812fef7887c1a8bad033129eac26d28 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 25 Apr 2021 14:52:48 -0500 Subject: [PATCH 404/746] Allow complex keys in `addGlobalData`, minor tweak to data cascade (addGlobalData will override global data files). Also changed to do a deep merge between the two. --- src/TemplateData.js | 10 +++------- test/TemplateDataTest.js | 16 ++++++++++++++++ .../_data/deep.js | 3 +++ 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 test/stubs-global-data-config-api-nested/_data/deep.js diff --git a/src/TemplateData.js b/src/TemplateData.js index ef51782d8..26fe6c05a 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -289,7 +289,7 @@ class TemplateData { returnValue = await returnValue(); } - globalData[key] = returnValue; + lodashset(globalData, key, returnValue); } } return globalData; @@ -302,14 +302,10 @@ class TemplateData { if (!this.globalData) { let globalJson = await this.getAllGlobalData(); + let mergedGlobalData = merge(globalJson, this.configApiGlobalData); // OK: Shallow merge when combining rawImports (pkg) with global data files - this.globalData = Object.assign( - {}, - this.configApiGlobalData, - globalJson, - rawImports - ); + this.globalData = Object.assign({}, mergedGlobalData, rawImports); } return this.globalData; diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 90a6ee0a0..408589bb0 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -470,3 +470,19 @@ test("addGlobalData values", async (t) => { t.is(data.myPromise, "promise-value"); t.is(data.myAsync, "promise-value"); }); + +test("addGlobalData complex key", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.addGlobalData("deep.nested.one", () => "first"); + eleventyConfig.userConfig.addGlobalData("deep.nested.two", () => "second"); + + let dataObj = new TemplateData( + "./test/stubs-global-data-config-api-nested/", + eleventyConfig + ); + let data = await dataObj.getData(); + + t.is(data.deep.existing, true); + t.is(data.deep.nested.one, "first"); + t.is(data.deep.nested.two, "second"); +}); diff --git a/test/stubs-global-data-config-api-nested/_data/deep.js b/test/stubs-global-data-config-api-nested/_data/deep.js new file mode 100644 index 000000000..15a00dfd6 --- /dev/null +++ b/test/stubs-global-data-config-api-nested/_data/deep.js @@ -0,0 +1,3 @@ +module.exports = { + existing: true, +}; From 35c3c2effa98ec45677071eeaf8ca03f3eefb246 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 27 Apr 2021 10:08:31 -0500 Subject: [PATCH 405/746] Shortcut for single page renders on pagination in cloud render. --- src/Plugins/Pagination.js | 241 ++++++++++++++++++++++---------------- src/Template.js | 63 ++++++---- src/TemplateMap.js | 34 ++++-- src/TemplatePermalink.js | 39 +++--- test/TemplateMapTest.js | 15 ++- 5 files changed, 233 insertions(+), 159 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 665b7c838..bd7b28d36 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -69,7 +69,7 @@ class Pagination { this.alias = data.pagination.alias; this.target = this._resolveItems(); - this.items = this.pagedItems; + this.chunkedItems = this.pagedItems; } setTemplate(tmpl) { @@ -80,7 +80,7 @@ class Pagination { return this.data.pagination.data; } - doResolveToObjectValues() { + resolveDataToObjectValues() { if ("resolve" in this.data.pagination) { return this.data.pagination.resolve === "values"; } @@ -100,32 +100,39 @@ class Pagination { return false; } - _resolveItems() { + _get(target, key) { let notFoundValue = "__NOT_FOUND_ERROR__"; - let key = this._getDataKey(); - let fullDataSet = lodashGet(this.data, key, notFoundValue); - if (fullDataSet === notFoundValue) { + let data = lodashGet(target, key, notFoundValue); + if (data === notFoundValue) { throw new Error( - `Could not resolve pagination key in template data: ${key}` + `Could not find pagination data, went looking for: ${key}` ); } + return data; + } + + _resolveItems() { + let fullDataSet = this._get(this.data, this._getDataKey()); + + // TODO maybe don’t operate on the full data set for a cloud render let keys; if (Array.isArray(fullDataSet)) { keys = fullDataSet; - } else if (this.doResolveToObjectValues()) { + } else if (this.resolveDataToObjectValues()) { keys = Object.values(fullDataSet); } else { keys = Object.keys(fullDataSet); } + // keys must be an array let result = keys.slice(); if ( this.data.pagination.before && typeof this.data.pagination.before === "function" ) { - // we don’t need to make a copy of this because we already .filter() above + // we don’t need to make a copy of this because we .slice() above to create a new copy result = this.data.pagination.before(result); } @@ -159,7 +166,98 @@ class Pagination { return 0; } - return this.items.length; + return this.chunkedItems.length; + } + + getNormalizedItems(pageItems) { + return this.size === 1 ? pageItems[0] : pageItems; + } + + getOverrideData(pageItems) { + let override = { + pagination: { + data: this.data.pagination.data, + size: this.data.pagination.size, + alias: this.alias, + items: pageItems, + }, + }; + + if (this.alias) { + lodashSet(override, this.alias, this.getNormalizedItems(pageItems)); + } + + return override; + } + + getOverrideDataPages(items, pageNumber) { + let obj = { + pages: this.size === 1 ? items.map((entry) => entry[0]) : items, + + // See Issue #345 for more examples + page: { + previous: + pageNumber > 0 + ? this.getNormalizedItems(items[pageNumber - 1]) + : null, + next: + pageNumber < items.length - 1 + ? this.getNormalizedItems(items[pageNumber + 1]) + : null, + first: items.length ? this.getNormalizedItems(items[0]) : null, + last: items.length + ? this.getNormalizedItems(items[items.length - 1]) + : null, + }, + + pageNumber, + }; + + return obj; + } + + getOverrideDataLinks(pageNumber, templates, links) { + let obj = {}; + + // links are okay but hrefs are better + obj.previousPageLink = pageNumber > 0 ? links[pageNumber - 1] : null; + obj.previous = obj.previousPageLink; + + obj.nextPageLink = + pageNumber < templates.length - 1 ? links[pageNumber + 1] : null; + obj.next = obj.nextPageLink; + + obj.firstPageLink = links.length > 0 ? links[0] : null; + obj.lastPageLink = links.length > 0 ? links[links.length - 1] : null; + + obj.links = links; + // todo deprecated, consistency with collections and use links instead + obj.pageLinks = links; + return obj; + } + + getOverrideDataHrefs(pageNumber, templates, hrefs) { + let obj = {}; + + // hrefs are better than links + obj.previousPageHref = pageNumber > 0 ? hrefs[pageNumber - 1] : null; + obj.nextPageHref = + pageNumber < templates.length - 1 ? hrefs[pageNumber + 1] : null; + + obj.firstPageHref = hrefs.length > 0 ? hrefs[0] : null; + obj.lastPageHref = hrefs.length > 0 ? hrefs[hrefs.length - 1] : null; + + obj.hrefs = hrefs; + + // better names + obj.href = { + previous: obj.previousPageHref, + next: obj.nextPageHref, + first: obj.firstPageHref, + last: obj.lastPageHref, + }; + + return obj; } async getPageTemplates() { @@ -175,8 +273,8 @@ class Pagination { return this.pagesCache; } - let pages = []; - let items = this.items; + let pagesCache = []; + let items = this.chunkedItems; let tmpl = this.template; let templates = []; let links = []; @@ -193,52 +291,11 @@ class Pagination { templates.push(cloned); - let override = { - pagination: { - data: this.data.pagination.data, - size: this.data.pagination.size, - alias: this.alias, - - pages: this.size === 1 ? items.map((entry) => entry[0]) : items, - - // See Issue #345 for more examples - page: { - previous: - pageNumber > 0 - ? this.size === 1 - ? items[pageNumber - 1][0] - : items[pageNumber - 1] - : null, - next: - pageNumber < items.length - 1 - ? this.size === 1 - ? items[pageNumber + 1][0] - : items[pageNumber + 1] - : null, - first: items.length - ? this.size === 1 - ? items[0][0] - : items[0] - : null, - last: items.length - ? this.size === 1 - ? items[items.length - 1][0] - : items[items.length - 1] - : null, - }, - - items: items[pageNumber], - pageNumber: pageNumber, - }, - }; - - if (this.alias) { - lodashSet( - override, - this.alias, - this.size === 1 ? items[pageNumber][0] : items[pageNumber] - ); - } + let override = this.getOverrideData(items[pageNumber]); + Object.assign( + override.pagination, + this.getOverrideDataPages(items, pageNumber) + ); overrides.push(override); cloned.setPaginationData(override); @@ -251,58 +308,34 @@ class Pagination { } // we loop twice to pass in the appropriate prev/next links (already full generated now) - templates.forEach( - function (cloned, pageNumber) { - let pageObj = {}; - - // links are okay but hrefs are better - pageObj.previousPageLink = - pageNumber > 0 ? links[pageNumber - 1] : null; - pageObj.previous = pageObj.previousPageLink; - - pageObj.nextPageLink = - pageNumber < templates.length - 1 ? links[pageNumber + 1] : null; - pageObj.next = pageObj.nextPageLink; + for (let pageNumber = 0; pageNumber < templates.length; pageNumber++) { + let linksObj = this.getOverrideDataLinks(pageNumber, templates, links); + Object.assign(overrides[pageNumber].pagination, linksObj); - pageObj.firstPageLink = links.length > 0 ? links[0] : null; - pageObj.lastPageLink = - links.length > 0 ? links[links.length - 1] : null; + let hrefsObj = this.getOverrideDataHrefs(pageNumber, templates, hrefs); + Object.assign(overrides[pageNumber].pagination, hrefsObj); - pageObj.links = links; - // todo deprecated, consistency with collections and use links instead - pageObj.pageLinks = links; + let cloned = templates[pageNumber]; + cloned.setPaginationData(overrides[pageNumber]); - // hrefs are better than links - pageObj.previousPageHref = - pageNumber > 0 ? hrefs[pageNumber - 1] : null; - pageObj.nextPageHref = - pageNumber < templates.length - 1 ? hrefs[pageNumber + 1] : null; - - pageObj.firstPageHref = hrefs.length > 0 ? hrefs[0] : null; - pageObj.lastPageHref = - hrefs.length > 0 ? hrefs[hrefs.length - 1] : null; - - pageObj.hrefs = hrefs; - - // better names - pageObj.href = { - previous: pageObj.previousPageHref, - next: pageObj.nextPageHref, - first: pageObj.firstPageHref, - last: pageObj.lastPageHref, - }; - - Object.assign(overrides[pageNumber].pagination, pageObj); - - cloned.setPaginationData(overrides[pageNumber]); + pagesCache.push(cloned); + } - pages.push(cloned); - }.bind(this) - ); + this.pagesCache = pagesCache; - this.pagesCache = pages; + return pagesCache; + } - return pages; + getTruncatedCloudData(data) { + let cloudKey = data.pagination.cloud; + if (!cloudKey) { + throw new Error( + "Missing `cloud` key in `pagination` object to point to pagination data." + ); + } + let resolvedKey = this._get(data, cloudKey); + let fullDataSet = this._get(data, this._getDataKey()); + return [this._get(fullDataSet, resolvedKey)]; } } diff --git a/src/Template.js b/src/Template.js index 30f39d760..3a5f56011 100755 --- a/src/Template.js +++ b/src/Template.js @@ -2,6 +2,7 @@ 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"); @@ -572,8 +573,33 @@ class Template extends TemplateContent { await this.computedData.processRemainingData(data); } - async getTemplates(data, shouldRender = true) { - if (!Pagination.hasPagination(data)) { + async getTemplates(data, behavior) { + if (!behavior) { + behavior = { + read: true, + render: true, + write: true, + }; + } + + // no pagination on permalink.cloud for local builds + let hasPagination = Pagination.hasPagination(data); + let isCloudRenderOnBuild = !behavior.render; + let isCloudRenderOnCloud = behavior.render === "override"; + + if (!hasPagination || isCloudRenderOnBuild || isCloudRenderOnCloud) { + // inject pagination page data for just this one entry for cloud render + if (isCloudRenderOnCloud && hasPagination) { + let pagination = new Pagination(data, this.config); + let paginationItems = pagination.getTruncatedCloudData(data); + let override = pagination.getOverrideData(paginationItems); + // TODO errors or warnings when trying to access `pagination.pages`, pageNumber, links, hrefs, etc + this.setPaginationData(override); + + // TODO: better? + Object.assign(data, override); + } + await this.addComputedData(data); return [ @@ -590,17 +616,17 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if (shouldRender) { - if (this._templateContent === undefined) { + if (this._templateContent === undefined) { + if (behavior.render) { // should at least warn here throw new TemplateContentPrematureUseError( `Tried to use templateContent too early (${this.inputPath})` ); + } else { + throw new TemplateContentUnrenderedTemplateError( + `Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath}` + ); } - } else { - throw new TemplateContentUnrenderedTemplateError( - `Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath}` - ); } return this._templateContent; }, @@ -615,6 +641,7 @@ class Template extends TemplateContent { return await Promise.all( pageTemplates.map(async (page, pageNumber) => { + // TODO get smarter with something like Object.assign(data, override); let pageData = Object.assign({}, await page.getData()); await page.addComputedData(pageData); @@ -638,7 +665,7 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if (shouldRender) { + if (behavior.render) { if (this._templateContent === undefined) { throw new TemplateContentPrematureUseError( `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` @@ -734,8 +761,8 @@ class Template extends TemplateContent { mapEntry._pages.map(async (page) => { let content; - // Note that behavior.rendered is overridden when using json or ndjson output - if (mapEntry.behavior.rendered) { + // Note that behavior.render is overridden when using json or ndjson output + if (mapEntry.behavior.render) { // this reuses page.templateContent, it doesn’t render it content = await this.renderPageEntry(mapEntry, page); } @@ -757,7 +784,7 @@ class Template extends TemplateContent { return obj; } - if (!mapEntry.behavior.rendered) { + if (!mapEntry.behavior.render) { debug( "Template not written %o from %o (via permalink.behavior).", page.outputPath, @@ -766,7 +793,7 @@ class Template extends TemplateContent { return; } - if (!mapEntry.behavior.writeable) { + if (!mapEntry.behavior.write) { debug( "Template not written %o from %o (via permalink: false, permalink.build: false, or a permalink object without a build property).", page.outputPath, @@ -895,20 +922,14 @@ class Template extends TemplateContent { 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: { - ignored: link.isTemplateIgnored(), - rendered: - this.outputFormat === "json" || - this.outputFormat === "ndjson" || - link.isTemplateRendered(), - writeable: link.isTemplateWriteable(), - }, + behavior, }); return entries; } diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 7241f36a7..4bfc004ed 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -121,7 +121,10 @@ class TemplateMap { graph.addNode(entry.inputPath); } - if (!entry.data.eleventyExcludeFromCollections) { + if ( + !entry.data.eleventyExcludeFromCollections && + entry.behavior.includeInCollections + ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -172,7 +175,10 @@ class TemplateMap { } graph.addDependency(entry.inputPath, tagPrefix + paginationTagTarget); - if (!entry.data.eleventyExcludeFromCollections) { + if ( + !entry.data.eleventyExcludeFromCollections && + entry.behavior.includeInCollections + ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -213,7 +219,10 @@ class TemplateMap { graph.addNode(entry.inputPath); } - if (!entry.data.eleventyExcludeFromCollections) { + if ( + !entry.data.eleventyExcludeFromCollections && + entry.behavior.includeInCollections + ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); } @@ -242,7 +251,10 @@ class TemplateMap { graph.addNode(entry.inputPath); } - if (!entry.data.eleventyExcludeFromCollections) { + if ( + !entry.data.eleventyExcludeFromCollections && + entry.behavior.includeInCollections + ) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); } @@ -285,13 +297,10 @@ class TemplateMap { } else { // is a template entry let map = this.getMapEntryForInputPath(depEntry); - if (map.behavior.ignored) { + if (!map.behavior.read) { map._pages = []; } else { - map._pages = await map.template.getTemplates( - map.data, - map.behavior.rendered - ); + map._pages = await map.template.getTemplates(map.data, map.behavior); let counter = 0; for (let page of map._pages) { @@ -305,7 +314,10 @@ class TemplateMap { (map.data.pagination && map.data.pagination.addAllPagesToCollections) ) { - if (!map.data.eleventyExcludeFromCollections) { + if ( + !map.data.eleventyExcludeFromCollections && + map.behavior.includeInCollections + ) { // TODO do we need .template in collection entries? this.collection.add(page); } @@ -432,7 +444,7 @@ class TemplateMap { if (!map._pages) { throw new Error(`Content pages not found for ${map.inputPath}`); } - if (!map.behavior.rendered) { + if (!map.behavior.render) { continue; } try { diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 0791f644b..069d7784b 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -10,7 +10,7 @@ class TemplatePermalink { this._isIgnoredTemplate = false; this._isRendered = true; - this._outputToFileSystem = true; + this._writeToFileSystem = true; let rawLink; if (isLinkAnObject) { @@ -24,7 +24,7 @@ class TemplatePermalink { // permalink: false and permalink: build: false if (typeof rawLink === "boolean") { if (rawLink === false) { - this._outputToFileSystem = false; + this._writeToFileSystem = false; } else { throw new Error( `\`permalink: ${ @@ -43,19 +43,19 @@ class TemplatePermalink { this.externalLink = link.cloud; } - // default for permalink objects without a build URL + // default if permalink is an Object but does not have a `build` prop if (!("behavior" in link) && !("build" in link)) { - link.behavior = "skip-render"; + link.behavior = "read"; } - if (link.behavior === "skip-write") { + if (link.behavior === "render") { // same as permalink: false and permalink: build: false - this._outputToFileSystem = false; - } else if (link.behavior === "skip-render") { - this._outputToFileSystem = false; + this._writeToFileSystem = false; + } else if (link.behavior === "read") { + this._writeToFileSystem = false; this._isRendered = false; } else if (link.behavior === "skip") { - this._outputToFileSystem = false; + this._writeToFileSystem = false; this._isRendered = false; this._isIgnoredTemplate = true; } @@ -128,16 +128,21 @@ class TemplatePermalink { return normalize(uri); } - isTemplateIgnored() { - return this._isIgnoredTemplate; - } + getBehavior(outputFormat = "fs") { + let obj = { + read: !this._isIgnoredTemplate, + render: this._isRendered, + write: this._writeToFileSystem, + }; - isTemplateRendered() { - return this._isRendered; - } + // override render behavior for --json or --ndjson + if (outputFormat !== "fs") { + obj.render = "override"; + } + + obj.includeInCollections = obj.read && obj.render; - isTemplateWriteable() { - return this._outputToFileSystem; + return obj; } static _hasDuplicateFolder(dir, base) { diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 3af39f9aa..f51f04d36 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -1265,7 +1265,7 @@ test("permalink object with build", async (t) => { t.is(map[0]._pages.length, 1); }); -test("permalink object without build (defaults to no-render mode)", async (t) => { +test("permalink object without build (defaults to `read` mode)", async (t) => { let eleventyConfig = new TemplateConfig(); let tm = new TemplateMap(eleventyConfig); let tmpl = getNewTemplate( @@ -1281,9 +1281,12 @@ test("permalink object without build (defaults to no-render mode)", async (t) => await tm.cache(); t.is(map[0]._pages.length, 1); - t.throws(() => { - map[0]._pages[0].templateContent; - }, { - instanceOf: TemplateContentUnrenderedTemplateError - }); + t.throws( + () => { + map[0]._pages[0].templateContent; + }, + { + instanceOf: TemplateContentUnrenderedTemplateError, + } + ); }); From 2aa7ffb7f8eacd0b46ffb425ad608c57c1a55993 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 27 Apr 2021 10:18:59 -0500 Subject: [PATCH 406/746] v1.0.0-canary.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eaaeb68c9..a3f084b02 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.15", + "version": "1.0.0-canary.16", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 9cf519725e92af7024dff2fad0cf5e2ede09175a Mon Sep 17 00:00:00 2001 From: Luke Bonaccorsi Date: Tue, 27 Apr 2021 17:16:40 +0100 Subject: [PATCH 407/746] Add failing test for nunjucks nested async paired shortcodes --- test/TemplateRenderNunjucksTest.js | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 5738268b8..f8884487a 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -545,6 +545,40 @@ test("Nunjucks Async Paired Shortcode", async (t) => { ); }); +test("Nunjucks Nested Async Paired Shortcode", async (t) => { + t.plan(3); + + let tr = getNewTemplateRender("njk", "./test/stubs/"); + tr.engine.addPairedShortcode( + "postfixWithZach", + function (content, str) { + // Data in context + t.is(this.page.url, "/hi/"); + + return new Promise(function (resolve) { + setTimeout(function () { + resolve(str + content + "Zach"); + }); + }); + }, + true + ); + + t.is( + await tr._testRender( + "{% postfixWithZach name %}Content{% postfixWithZach name2 %}Content{% endpostfixWithZach %}{% endpostfixWithZach %}", + { + name: "test", + name2: "test2", + page: { + url: "/hi/", + }, + } + ), + "testContenttest2ContentZachZach" + ); +}); + test("Nunjucks Paired Shortcode without args", async (t) => { let tr = getNewTemplateRender("njk", "./test/stubs/"); tr.engine.addPairedShortcode("postfixWithZach", function (content) { From 5b5a45554403808ff5e4626933dc745bd72ff56d Mon Sep 17 00:00:00 2001 From: Luke Bonaccorsi Date: Tue, 27 Apr 2021 17:19:48 +0100 Subject: [PATCH 408/746] Fix for nunjucks nested async paired shortcodes --- src/Engines/Nunjucks.js | 87 +++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 6b0388bdb..3d0262d9b 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -287,57 +287,68 @@ class Nunjucks extends TemplateEngine { var body = parser.parseUntilBlocks("end" + shortcodeName); parser.advanceAfterBlockEnd(); - if (isAsync) { - return new nodes.CallExtensionAsync(this, "run", args, [body]); - } - return new nodes.CallExtension(this, "run", args, [body]); + return new nodes.CallExtensionAsync(this, "run", args, [body]); }; this.run = function (...args) { - let resolve; - if (isAsync) { - resolve = args.pop(); - } + let resolve = args.pop(); let body = args.pop(); let [context, ...argArray] = args; - if (isAsync) { - shortcodeFn - .call( - Nunjucks._normalizeShortcodeContext(context), - body(), - ...argArray - ) - .then(function (returnValue) { - resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); - }) - .catch(function (e) { + body(function (err, bodyContent) { + if (err) { + resolve( + new EleventyShortcodeError( + `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ) + ); + } + + if (isAsync) { + shortcodeFn + .call( + Nunjucks._normalizeShortcodeContext(context), + bodyContent, + ...argArray + ) + .then(function (returnValue) { + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function (e) { + resolve( + new EleventyShortcodeError( + `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ), + null + ); + }); + } else { + try { + resolve( + null, + new NunjucksLib.runtime.SafeString( + shortcodeFn.call( + Nunjucks._normalizeShortcodeContext(context), + bodyContent, + ...argArray + ) + ) + ); + } catch (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( e )}` - ), - null + ) ); - }); - } else { - try { - return new NunjucksLib.runtime.SafeString( - shortcodeFn.call( - Nunjucks._normalizeShortcodeContext(context), - body(), - ...argArray - ) - ); - } catch (e) { - throw new EleventyShortcodeError( - `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( - e - )}` - ); + } } - } + }); }; } From a4bb516ca669f2f99081552ef3c07e4752102e8e Mon Sep 17 00:00:00 2001 From: Luke Bonaccorsi Date: Wed, 28 Apr 2021 02:51:39 +0100 Subject: [PATCH 409/746] Fix incorrect variable reference --- src/Engines/Nunjucks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 3d0262d9b..a1be3fa1c 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -295,8 +295,8 @@ class Nunjucks extends TemplateEngine { let body = args.pop(); let [context, ...argArray] = args; - body(function (err, bodyContent) { - if (err) { + body(function (e, bodyContent) { + if (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( From cf08d2dbce3e1b22216e3fc9f3932bc9ae742011 Mon Sep 17 00:00:00 2001 From: Kimiaki Kuno Date: Fri, 30 Apr 2021 22:58:24 +0900 Subject: [PATCH 410/746] Fix no use local timezone when parse date from filename --- src/Template.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Template.js b/src/Template.js index 3a5f56011..bedb59ffc 100755 --- a/src/Template.js +++ b/src/Template.js @@ -881,7 +881,7 @@ class Template extends TemplateContent { } else { let filenameRegex = this.inputPath.match(/(\d{4}-\d{2}-\d{2})/); if (filenameRegex !== null) { - let dateObj = DateTime.fromISO(filenameRegex[1]).toJSDate(); + let dateObj = DateTime.fromISO(filenameRegex[1], { zone: 'utc' }).toJSDate(); debug( "getMappedDate: using filename regex time for %o of %o: %o", this.inputPath, From b469b3eeecda067ed7f911770a43971689e3a85b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 30 Apr 2021 11:52:08 -0500 Subject: [PATCH 411/746] Changed Data Deep merge default to true for 1.0 --- src/UserConfig.js | 2 +- test/TemplateTest.js | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index 2b2089e1e..e3f2e5b6b 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -53,7 +53,7 @@ class UserConfig { this.DateTime = DateTime; this.dynamicPermalinks = true; this.useGitIgnore = true; - this.dataDeepMerge = false; + this.dataDeepMerge = true; this.extensionMap = new Set(); this.watchJavaScriptDependencies = true; this.additionalWatchTargets = []; diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 2db15a0e2..9445e9168 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -42,7 +42,7 @@ async function write(tmpl, data) { let mapEntries = await getTemplateMapEntriesWithContent(tmpl, data); let promises = []; for (let entry of mapEntries) { - if(entry.behavior.writeable) { + if (entry.behavior.writeable) { promises.push(tmpl._write(entry.outputPath, entry.templateContent)); } } @@ -1486,7 +1486,8 @@ test("Front matter date with quotes (njk), issue #258", async (t) => { test("Data Cascade (Deep merge)", async (t) => { let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.setDataDeepMerge(true); + // Default changed in 1.0 + // eleventyConfig.userConfig.setDataDeepMerge(true); let dataObj = new TemplateData("./test/", eleventyConfig); await dataObj.cacheData(); @@ -1520,6 +1521,8 @@ test("Data Cascade (Deep merge)", async (t) => { test("Data Cascade (Shallow merge)", async (t) => { let eleventyConfig = new TemplateConfig(); + // Default changed in 1.0 + eleventyConfig.userConfig.setDataDeepMerge(false); let dataObj = new TemplateData("./test/", eleventyConfig); await dataObj.cacheData(); @@ -1549,7 +1552,8 @@ test("Data Cascade (Shallow merge)", async (t) => { test("Data Cascade Tag Merge (Deep merge)", async (t) => { let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.setDataDeepMerge(true); + // Default changed in 1.0 + // eleventyConfig.userConfig.setDataDeepMerge(true); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); @@ -1568,6 +1572,8 @@ test("Data Cascade Tag Merge (Deep merge)", async (t) => { test("Data Cascade Tag Merge (Shallow merge)", async (t) => { let eleventyConfig = new TemplateConfig(); + // Default changed in 1.0 + eleventyConfig.userConfig.setDataDeepMerge(false); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); @@ -1586,6 +1592,8 @@ test("Data Cascade Tag Merge (Shallow merge)", async (t) => { test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async (t) => { let eleventyConfig = new TemplateConfig(); + // Default changed in 1.0 + eleventyConfig.userConfig.setDataDeepMerge(false); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); @@ -1604,7 +1612,8 @@ test('Local data inherits tags string ([tags] vs "tags") Shallow Merge', async ( test('Local data inherits tags string ([tags] vs "tags") Deep Merge', async (t) => { let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.setDataDeepMerge(true); + // Default changed in 1.0 + // eleventyConfig.userConfig.setDataDeepMerge(true); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); await dataObj.cacheData(); From 4ee394b76880e95e214d1ca9ea377d63b6d0ff55 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 2 May 2021 15:17:05 -0500 Subject: [PATCH 412/746] Renaming `cloud` to `serverless` for clarity after feedback from a few folks --- src/Plugins/Pagination.js | 12 ++++++------ src/Template.js | 26 +++++++++++++++----------- src/TemplateMap.js | 2 +- src/TemplatePermalink.js | 4 ++-- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index bd7b28d36..f02afe732 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -114,7 +114,7 @@ class Pagination { _resolveItems() { let fullDataSet = this._get(this.data, this._getDataKey()); - // TODO maybe don’t operate on the full data set for a cloud render + // TODO maybe don’t operate on the full data set for a serverless render let keys; if (Array.isArray(fullDataSet)) { @@ -326,14 +326,14 @@ class Pagination { return pagesCache; } - getTruncatedCloudData(data) { - let cloudKey = data.pagination.cloud; - if (!cloudKey) { + getTruncatedServerlessData(data) { + let serverlessKey = data.pagination.serverless; + if (!serverlessKey) { throw new Error( - "Missing `cloud` key in `pagination` object to point to pagination data." + "Missing `serverless` key in `pagination` object to point to pagination data." ); } - let resolvedKey = this._get(data, cloudKey); + let resolvedKey = this._get(data, serverlessKey); let fullDataSet = this._get(data, this._getDataKey()); return [this._get(fullDataSet, resolvedKey)]; } diff --git a/src/Template.js b/src/Template.js index 3a5f56011..4bc142713 100755 --- a/src/Template.js +++ b/src/Template.js @@ -172,9 +172,9 @@ class Template extends TemplateContent { keys.push("build"); promises.push(super.render(permalink.build, data, true)); } - if (permalink.cloud) { - keys.push("cloud"); - promises.push(super.render(permalink.cloud, data, true)); + if (permalink.serverless) { + keys.push("serverless"); + promises.push(super.render(permalink.serverless, data, true)); } let results = await Promise.all(promises); @@ -582,16 +582,20 @@ class Template extends TemplateContent { }; } - // no pagination on permalink.cloud for local builds + // no pagination on permalink.serverless for local builds let hasPagination = Pagination.hasPagination(data); - let isCloudRenderOnBuild = !behavior.render; - let isCloudRenderOnCloud = behavior.render === "override"; + let isServerlessRenderOnBuild = !behavior.render; + let isServerlessRenderOnServerless = behavior.render === "override"; - if (!hasPagination || isCloudRenderOnBuild || isCloudRenderOnCloud) { - // inject pagination page data for just this one entry for cloud render - if (isCloudRenderOnCloud && hasPagination) { + if ( + !hasPagination || + isServerlessRenderOnBuild || + isServerlessRenderOnServerless + ) { + // inject pagination page data for just this one entry for serverless render + if (isServerlessRenderOnServerless && hasPagination) { let pagination = new Pagination(data, this.config); - let paginationItems = pagination.getTruncatedCloudData(data); + let paginationItems = pagination.getTruncatedServerlessData(data); let override = pagination.getOverrideData(paginationItems); // TODO errors or warnings when trying to access `pagination.pages`, pageNumber, links, hrefs, etc this.setPaginationData(override); @@ -719,7 +723,7 @@ class Template extends TemplateContent { let engineList = this.templateRender.getReadableEnginesListDifferingFromFileExtension(); this.logger.log( `${lang.start} ${outputPath} from ${this.inputPath}${ - engineList ? ` (using ${engineList})` : "" + engineList ? ` (${engineList})` : "" }` ); diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 4bfc004ed..016ffe71c 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -381,7 +381,7 @@ class TemplateMap { for (let entry of orderedMap) { let ret = { inputPath: entry.inputPath, - isExternal: !!(entry.data.permalink && entry.data.permalink.cloud), + isExternal: !!(entry.data.permalink && entry.data.permalink.serverless), }; // TODO `needs: []` array of inputPath or glob? this template uses diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 069d7784b..896a92409 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -39,8 +39,8 @@ class TemplatePermalink { } if (isLinkAnObject) { - if ("cloud" in link) { - this.externalLink = link.cloud; + if ("serverless" in link) { + this.externalLink = link.serverless; } // default if permalink is an Object but does not have a `build` prop From 4c8e2125383edcbeeebfbf485a813a1c8e507db5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 May 2021 17:11:52 -0500 Subject: [PATCH 413/746] Set a few default environment variables useful in serverless mode. --- src/Eleventy.js | 42 +++++++++++++++++++++++++++++++++++++++--- src/TemplateData.js | 17 +++++++++++++++++ test/EleventyTest.js | 13 +++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index d2d14cc3a..9a82290e5 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -110,6 +110,9 @@ class Eleventy { this.watchTargets = new EleventyWatchTargets(); this.watchTargets.addAndMakeGlob(this.config.additionalWatchTargets); this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; + + this.env = this.getEnvironmentVariableValues(); + this.initializeEnvironmentVariables(this.env); } getNewTimestamp() { @@ -306,6 +309,9 @@ class Eleventy { this.templateData = new TemplateData(this.inputDir, this.eleventyConfig); this.templateData.extensionMap = this.extensionMap; + if (this.env) { + this.templateData.environmentVariables = this.env; + } this.eleventyFiles.templateData = this.templateData; this.writer = new TemplateWriter( @@ -335,6 +341,33 @@ Verbose Output: ${this.verboseMode}`); return this.templateData.cacheData(); } + getEnvironmentVariableValues() { + let absolutePathToConfig = TemplatePath.absolutePath( + this.eleventyConfig.getLocalProjectConfigFile() + ); + let root = TemplatePath.getDirFromFilePath(absolutePathToConfig); + + return { + root, + }; + } + + /** + * Set process.ENV variables for use in Eleventy projects + * + * @method + */ + initializeEnvironmentVariables(env) { + process.env.ELEVENTY_ROOT = env.root; + debug("Setting process.env.ELEVENTY_ROOT: %o", env.root); + + // careful here, setting to false will cast to string "false" which is truthy + if (process.env.AWS_LAMBDA_FUNCTION_NAME) { + process.env.ELEVENTY_SERVERLESS = true; + debug("Setting process.env.ELEVENTY_SERVERLESS: %o", true); + } + } + /* Setter for verbose mode */ set verboseMode(value) { this._isVerboseMode = !!value; @@ -811,9 +844,12 @@ Arguments: let hasError = false; if (!this.writer) { - this.errorHandler.fatal(new Error( - "Did you call Eleventy.init to create the TemplateWriter instance? Hint: you probably didn’t." - ), "Problem writing Eleventy templates"); + this.errorHandler.fatal( + new Error( + "Did you call Eleventy.init to create the TemplateWriter instance? Hint: you probably didn’t." + ), + "Problem writing Eleventy templates" + ); } try { diff --git a/src/TemplateData.js b/src/TemplateData.js index 26fe6c05a..f2efa03c9 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -74,6 +74,14 @@ class TemplateData { this._extensionMap = map; } + get environmentVariables() { + return this._env; + } + + set environmentVariables(env) { + this._env = env; + } + /* Used by tests */ _setConfig(config) { this.config = config; @@ -292,6 +300,15 @@ class TemplateData { lodashset(globalData, key, returnValue); } } + if (this.environmentVariables) { + if (!("eleventy" in globalData)) { + globalData.eleventy = {}; + } + if (!("env" in globalData.eleventy)) { + globalData.eleventy.env = {}; + } + Object.assign(globalData.eleventy.env, this.environmentVariables); + } return globalData; } diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 3b4d6d7a5..ee90de111 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -44,6 +44,19 @@ test("Eleventy set input/output", async (t) => { t.truthy(elev.writer); }); +test("Eleventy process.ENV", async (t) => { + let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); + + process.env.ELEVENTY_ROOT = ""; + t.falsy(process.env.ELEVENTY_ROOT); + await elev.init(); + t.truthy(process.env.ELEVENTY_ROOT); + + // all ELEVENTY_ env variables are also available on eleventy.env + let globals = await elev.templateData.getInitialGlobalData(); + t.truthy(globals.eleventy.env.root); +}); + test("Eleventy file watching", async (t) => { let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); elev.setFormats("njk"); From 6d80f2cd0fdd04dee0502d9a062932503129f491 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 May 2021 17:18:01 -0500 Subject: [PATCH 414/746] v1.0.0-canary.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3f084b02..b603f93d0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.16", + "version": "1.0.0-canary.17", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 1ed58c28650cc7d4a651df5fff5dbab49852ac23 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 May 2021 18:00:19 -0500 Subject: [PATCH 415/746] We need to do that sooner so that devs can use the ENV variables inside of their user config. --- src/Eleventy.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 9a82290e5..a6a70b971 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -53,6 +53,16 @@ class Eleventy { */ this.configPath = options.configPath; + /** + * @member {Object} - Initialize Eleventy environment variables + * @default null + */ + this.env = this.getEnvironmentVariableValues(); + this.initializeEnvironmentVariables(this.env); + + /** + * @member {Object} - Initialize Eleventy’s configuration, including the user config file + */ this.config = this.eleventyConfig.getConfig(); /** @@ -110,9 +120,6 @@ class Eleventy { this.watchTargets = new EleventyWatchTargets(); this.watchTargets.addAndMakeGlob(this.config.additionalWatchTargets); this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; - - this.env = this.getEnvironmentVariableValues(); - this.initializeEnvironmentVariables(this.env); } getNewTimestamp() { From 94d57fb1c6f7ff45f7620cf3d1d2e580357b33aa Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 May 2021 18:00:29 -0500 Subject: [PATCH 416/746] v1.0.0-canary.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b603f93d0..4ebee6a15 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.17", + "version": "1.0.0-canary.18", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From ae1f6a85c2699adc3b0fd00550d199776b529abd Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 May 2021 10:23:04 -0500 Subject: [PATCH 417/746] Adds `eleventy.env` event, prefixes a few other eleventy event names. --- src/Eleventy.js | 11 ++++++++--- src/TemplateData.js | 2 +- src/TemplateMap.js | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index a6a70b971..97d161caf 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -298,6 +298,10 @@ class Eleventy { * @returns {} - tbd. */ async init() { + if (this.env) { + await this.config.events.emit("eleventy.env", this.env); + } + this.config.inputDir = this.inputDir; let formats = this.formatsOverride || this.config.templateFormats; @@ -348,13 +352,14 @@ Verbose Output: ${this.verboseMode}`); return this.templateData.cacheData(); } + // These are all set as initial global data under eleventy.env.* (see TemplateData->environmentVariables) getEnvironmentVariableValues() { - let absolutePathToConfig = TemplatePath.absolutePath( - this.eleventyConfig.getLocalProjectConfigFile() - ); + let configPath = this.eleventyConfig.getLocalProjectConfigFile(); + let absolutePathToConfig = TemplatePath.absolutePath(configPath); let root = TemplatePath.getDirFromFilePath(absolutePathToConfig); return { + config: absolutePathToConfig, root, }; } diff --git a/src/TemplateData.js b/src/TemplateData.js index f2efa03c9..1af9a0506 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -257,7 +257,7 @@ class TemplateData { await this.getGlobalDataFiles() ); - this.config.events.emit("globalDataFiles", files); + this.config.events.emit("eleventy.globalDataFiles", files); let dataFileConflicts = {}; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 016ffe71c..9eadf9f89 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -371,7 +371,7 @@ class TemplateMap { this.checkForDuplicatePermalinks(); await this.config.events.emit( - "dependencyMap", + "eleventy.dependencyMap", this.generateDependencyMapEventObject(orderedMap) ); } From b92fdc6fed890aed3e853801578d1b2d17da112c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 May 2021 10:26:20 -0500 Subject: [PATCH 418/746] v1.0.0-canary.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4ebee6a15..406201ae4 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.18", + "version": "1.0.0-canary.19", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 8c5428f9e721c2b3f19781100b69d7a84deb50b5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 May 2021 12:53:05 -0500 Subject: [PATCH 419/746] Fixes https://github.com/11ty/eleventy/issues/1760 regression --- cmd.js | 89 ++++++++++---------- test/cmdTest.js | 32 +++++++ test/stubs/exitCode_globalData/_data/test.js | 3 + test/stubs/exitCode_success/success.njk | 1 + 4 files changed, 81 insertions(+), 44 deletions(-) create mode 100644 test/cmdTest.js create mode 100644 test/stubs/exitCode_globalData/_data/test.js create mode 100644 test/stubs/exitCode_success/success.njk diff --git a/cmd.js b/cmd.js index df0c9e591..46d8b0c11 100755 --- a/cmd.js +++ b/cmd.js @@ -55,7 +55,7 @@ try { const Eleventy = require("./src/Eleventy"); process.on("unhandledRejection", (error, promise) => { - errorHandler.error(error, "Unhandled rejection in promise"); + errorHandler.fatal(error, "Unhandled rejection in promise"); }); process.on("uncaughtException", (error) => { errorHandler.fatal(error, "Uncaught exception"); @@ -89,53 +89,54 @@ try { // careful, we can’t use async/await here to error properly // with old node versions in `please-upgrade-node` above. - elev.init().then(function () { - try { - if (argv.version) { - console.log(elev.getVersion()); - } else if (argv.help) { - console.log(elev.getHelp()); - } else if (argv.serve) { - let startBrowsersync = true; - elev - .watch() - .catch((e) => { - // Build failed but error message already displayed. - startBrowsersync = false; - console.log("Watch catch"); - }) - .then(function () { - if (startBrowsersync) { - elev.serve(argv.port); - } + elev + .init() + .then(function () { + try { + if (argv.version) { + console.log(elev.getVersion()); + } else if (argv.help) { + console.log(elev.getHelp()); + } else if (argv.serve) { + let startBrowsersync = true; + elev + .watch() + .catch((e) => { + // Build failed but error message already displayed. + startBrowsersync = false; + console.log("Watch catch"); + }) + .then(function () { + if (startBrowsersync) { + elev.serve(argv.port); + } + }); + } else if (argv.watch) { + elev.watch().catch((e) => { + console.log("watch catch 2"); }); - } else if (argv.watch) { - elev.watch().catch((e) => { - console.log("watch catch 2"); - }); - } else { - if (argv.to === "json") { - elev.toJSON().then(function (result) { - console.log(JSON.stringify(result, null, 2)); - }); - } else if (argv.to === "ndjson") { - elev.toNDJSON().then(function (stream) { - stream.pipe(process.stdout); - }); - } else if (!argv.to || argv.to === "fs") { - elev.write(); } else { - throw new EleventyCommandCheckError( - `Invalid --to value: ${argv.to}. Supported values: \`fs\` (default), \`json\`, and \`ndjson\`.` - ); + if (argv.to === "json") { + elev.toJSON().then(function (result) { + console.log(JSON.stringify(result, null, 2)); + }); + } else if (argv.to === "ndjson") { + elev.toNDJSON().then(function (stream) { + stream.pipe(process.stdout); + }); + } else if (!argv.to || argv.to === "fs") { + elev.write(); + } else { + throw new EleventyCommandCheckError( + `Invalid --to value: ${argv.to}. Supported values: \`fs\` (default), \`json\`, and \`ndjson\`.` + ); + } } + } catch (e) { + errorHandler.fatal(e, "Eleventy CLI Error"); } - } catch (e) { - errorHandler.fatal(e, "Eleventy CLI Error"); - } - }); - // unlikely because we handle a lot of errors internally in Eleventy - // .catch(errorHandler.fatal.bind(errorHandler)); + }) + .catch(errorHandler.fatal.bind(errorHandler)); } catch (e) { let errorHandler = new EleventyErrorHandler(); errorHandler.fatal(e, "Eleventy CLI Fatal Error"); diff --git a/test/cmdTest.js b/test/cmdTest.js new file mode 100644 index 000000000..778fcb65a --- /dev/null +++ b/test/cmdTest.js @@ -0,0 +1,32 @@ +const test = require("ava"); +const { exec } = require("child_process"); + +test.cb("Test command line exit code success", (t) => { + exec( + "node ./cmd.js --input=test/stubs/exitCode_success --dryrun", + (error, stdout, stderr) => { + t.falsy(error); + t.end(); + } + ); +}); + +test.cb("Test command line exit code for template error", (t) => { + exec( + "node ./cmd.js --input=test/stubs/exitCode --dryrun", + (error, stdout, stderr) => { + t.is(error.code, 1); + t.end(); + } + ); +}); + +test.cb("Test command line exit code for global data error", (t) => { + exec( + "node ./cmd.js --input=test/stubs/exitCode_globalData --dryrun", + (error, stdout, stderr) => { + t.is(error.code, 1); + t.end(); + } + ); +}); diff --git a/test/stubs/exitCode_globalData/_data/test.js b/test/stubs/exitCode_globalData/_data/test.js new file mode 100644 index 000000000..bf7385fac --- /dev/null +++ b/test/stubs/exitCode_globalData/_data/test.js @@ -0,0 +1,3 @@ +module.exports = async function () { + throw new Error("Testing"); +}; diff --git a/test/stubs/exitCode_success/success.njk b/test/stubs/exitCode_success/success.njk new file mode 100644 index 000000000..c498e3e04 --- /dev/null +++ b/test/stubs/exitCode_success/success.njk @@ -0,0 +1 @@ +{{ "hi" }} \ No newline at end of file From f746238ef136ae275dc3c172f7f64553c1509b7c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 May 2021 12:56:40 -0500 Subject: [PATCH 420/746] v1.0.0-canary.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 406201ae4..7ec27518b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.19", + "version": "1.0.0-canary.20", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From dca2e7fdb9b6dd81a723776dcf90c52d931eb678 Mon Sep 17 00:00:00 2001 From: milahu Date: Fri, 7 May 2021 19:28:31 +0200 Subject: [PATCH 421/746] TemplateConfig.js: make err.message optional --- src/TemplateConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 075d119db..2d0be4c45 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -210,7 +210,7 @@ class TemplateConfig { // TODO the error message here is bad and I feel bad (needs more accurate info) throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + - (err.message.includes("Cannot find module") + (err.message?.includes("Cannot find module") ? chalk.blueBright(" You may need to run `npm install`.") : ""), err From 81dfb98d72e5b428eb4f22fb2418bdd2b82460df Mon Sep 17 00:00:00 2001 From: Marius Schulz Date: Tue, 22 Dec 2020 13:33:19 +0000 Subject: [PATCH 422/746] Add .prettierrc.json file WIP --- .prettierrc.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .prettierrc.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..d68aa739e --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,3 @@ +{ + "arrowParens": "avoid" +} From 9db0aa36f71229640540847d1ad47feadccc3074 Mon Sep 17 00:00:00 2001 From: Marius Schulz Date: Tue, 22 Dec 2020 13:33:31 +0000 Subject: [PATCH 423/746] Add npm format script to run Prettier --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 7ec27518b..2f2693ba5 100755 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "scripts": { "default": "npm run test", "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/", + "format": "prettier src/ --write", "test": "npx ava --verbose", "lint-staged": "lint-staged", "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js", From 8c1f61c710bab43542ea8781a127f9dc837dfa9b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 14 May 2021 14:21:04 -0500 Subject: [PATCH 424/746] Require `pagination.serverless` key to truncate data in serverless pagination --- src/Plugins/Pagination.js | 6 +++--- src/Template.js | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index f02afe732..a324de540 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -327,13 +327,13 @@ class Pagination { } getTruncatedServerlessData(data) { - let serverlessKey = data.pagination.serverless; - if (!serverlessKey) { + if (!("serverless" in data.pagination)) { throw new Error( "Missing `serverless` key in `pagination` object to point to pagination data." ); } - let resolvedKey = this._get(data, serverlessKey); + + let resolvedKey = this._get(data, data.pagination.serverless); let fullDataSet = this._get(data, this._getDataKey()); return [this._get(fullDataSet, resolvedKey)]; } diff --git a/src/Template.js b/src/Template.js index 4bc142713..966348d5d 100755 --- a/src/Template.js +++ b/src/Template.js @@ -585,7 +585,10 @@ class Template extends TemplateContent { // no pagination on permalink.serverless for local builds let hasPagination = Pagination.hasPagination(data); let isServerlessRenderOnBuild = !behavior.render; - let isServerlessRenderOnServerless = behavior.render === "override"; + let isServerlessRenderOnServerless = + behavior.render === "override" && + hasPagination && + "serverless" in data.pagination; if ( !hasPagination || From 6f9310aa48073c243240ab54235431ec2fa08035 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 14 May 2021 14:21:37 -0500 Subject: [PATCH 425/746] Starter --- package.json | 2 + src/Eleventy.js | 2 + src/Plugins/ServerlessPlugin.js | 181 ++++++++++++++++++++++++++++++++ src/Serverless.js | 140 ++++++++++++++++++++++++ 4 files changed, 325 insertions(+) create mode 100644 src/Plugins/ServerlessPlugin.js create mode 100644 src/Serverless.js diff --git a/package.json b/package.json index 7ec27518b..1467c8980 100755 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", + "@iarna/toml": "^2.2.5", "browser-sync": "^2.26.14", "chalk": "^4.1.0", "chokidar": "^3.5.1", @@ -124,6 +125,7 @@ "slugify": "^1.4.7", "split": "^1.0.1", "time-require": "^0.1.2", + "url-pattern": "^1.0.3", "valid-url": "^1.0.9" } } diff --git a/src/Eleventy.js b/src/Eleventy.js index 97d161caf..1b67583b7 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -917,3 +917,5 @@ Arguments: } module.exports = Eleventy; +module.exports.Serverless = require("./Serverless"); +module.exports.ServerlessPlugin = require("./Plugins/ServerlessPlugin"); diff --git a/src/Plugins/ServerlessPlugin.js b/src/Plugins/ServerlessPlugin.js new file mode 100644 index 000000000..5a29d1f6c --- /dev/null +++ b/src/Plugins/ServerlessPlugin.js @@ -0,0 +1,181 @@ +const fs = require("fs"); +const path = require("path"); +const TOML = require("@iarna/toml"); +const dependencyTree = require("@11ty/dependency-tree"); +const TemplatePath = require("../TemplatePath"); +const { default: copy } = require("recursive-copy"); +const debug = require("debug")("Eleventy:Serverless"); + +function getNodeModulesList(files) { + let pkgs = new Set(); + + let jsFiles = files.filter((entry) => entry.endsWith(".js")); + + for (let filepath of jsFiles) { + let modules = dependencyTree(filepath, { + nodeModuleNamesOnly: true, + allowNotFound: true, // TODO is this okay? + }); + + for (let name of modules) { + pkgs.add(name); + } + } + + return Array.from(pkgs).sort(); +} + +function addRedirectsWithoutDuplicates(config, redirects) { + if (!config.redirects) { + config.redirects = []; + } + + for (let r of redirects) { + let found = false; + for (let entry of config.redirects) { + if (r.from === entry.from && r.to === entry.to) { + found = true; + } + } + if (!found) { + config.redirects.push(r); + } + } + return config; +} + +class BundlerHelper { + constructor(name, options) { + this.name = name; + this.options = options; + this.dir = path.join(options.functionsDir, name); + } + + getOutputFilename(filename) { + return TemplatePath.addLeadingDotSlash(path.join(this.dir, filename)); + } + + copyFile(fullPath, outputFilename) { + fs.copyFileSync(fullPath, this.getOutputFilename(outputFilename)); + } + + writeBundlerDependenciesFile(filename, deps = []) { + let modules = deps.map((name) => `require("${name}");`); + if (modules.length) { + let fullPath = this.getOutputFilename(filename); + fs.writeFileSync(fullPath, modules.join("\n")); + debug( + `Writing a file to make it very obvious to the serverless bundler which extra \`require\`s are needed from the config file (×${modules.length}): ${fullPath}` + ); + } + } + + writeDependencyEntryFile() { + let modulesFilename = this.getOutputFilename("eleventy-bundler-modules.js"); + if (!fs.existsSync(modulesFilename)) { + this.writeBundlerDependenciesFile("eleventy-bundler-modules.js", [ + "./eleventy-app-config-modules.js", + "./eleventy-app-globaldata-modules.js", + ]); + } + } + + writeDependencyConfigFile(configPath) { + let modules = getNodeModulesList([configPath]); + this.writeBundlerDependenciesFile( + "eleventy-app-config-modules.js", + modules + ); + } + + writeDependencyGlobalDataFile(globalDataFileList) { + let modules = getNodeModulesList(globalDataFileList); + this.writeBundlerDependenciesFile( + "eleventy-app-globalData-modules.js", + modules + ); + } +} + +module.exports = function (eleventyConfig, options = {}) { + options = Object.assign( + { + name: "", + functionsDir: "./functions/", + // Add automated redirects to netlify.toml (appends or creates, avoids duplicate entries) + redirects: function (outputMap) { + let redirects = []; + for (let url in outputMap) { + redirects.push({ + from: url, + to: `/.netlify/functions/${options.name}`, + status: 200, + force: true, + }); + } + + let configFilename = "./netlify.toml"; + let cfg = {}; + // parse existing netlify.toml + if (fs.existsSync(configFilename)) { + cfg = TOML.parse(fs.readFileSync(configFilename)); + } + + let newCfg = addRedirectsWithoutDuplicates(cfg, redirects); + fs.writeFileSync(configFilename, TOML.stringify(newCfg)); + console.log( + `Eleventy Serverless (${options.name}), writing (×${redirects.length}): ${configFilename}` + ); + }, + }, + options + ); + + if (!options.name) { + throw new Error( + "Serverless addPlugin second argument options object must have a name." + ); + } + + let dir = path.join(options.functionsDir, options.name); + + if (!process.env.ELEVENTY_SERVERLESS) { + let helper = new BundlerHelper(options.name, options); + helper.writeDependencyEntryFile(); + + // TODO is this necessary or can we just use require("eleventy.config.js") in the `eleventy-bundler-modules.js` file + eleventyConfig.on("eleventy.env", (env) => { + helper.copyFile(env.config, "eleventy.config.js"); + helper.writeDependencyConfigFile(env.config); + }); + + eleventyConfig.on("eleventy.globalDataFiles", (fileList) => { + helper.writeDependencyGlobalDataFile(fileList); + }); + + eleventyConfig.on("eleventy.dependencyMap", (templateMap) => { + let outputMap = {}; + + for (let entry of templateMap) { + if (entry.isExternal) { + outputMap[entry.url] = entry.inputPath; + } + } + + // Maps input files to output paths + let mapEntryCount = Object.keys(outputMap).length; + if (mapEntryCount > 0) { + let filename = TemplatePath.addLeadingDotSlash( + path.join(dir, "eleventy-serverless-map.json") + ); + fs.writeFileSync(filename, JSON.stringify(outputMap, null, 2)); + console.log( + `Eleventy Serverless (${options.name}), writing (×${mapEntryCount}): ${filename}` + ); + + // Write redirects into netlify.toml + options.redirects(outputMap); + } + }); + } +}; diff --git a/src/Serverless.js b/src/Serverless.js new file mode 100644 index 000000000..74552b233 --- /dev/null +++ b/src/Serverless.js @@ -0,0 +1,140 @@ +const path = require("path"); +const fs = require("fs"); + +const Eleventy = require("./Eleventy"); +const TemplatePath = require("./TemplatePath"); +const UrlPattern = require("url-pattern"); +const debug = require("debug")("Eleventy:Serverless"); + +class Serverless { + constructor(name, event, options = {}) { + this.name = name; + this.event = event; + + this.options = Object.assign( + { + inputDir: "src", + functionsDir: "functions/", + mapFilename: "eleventy-serverless-map.json", + // The bundle script sets the bundled config file name + configFilename: "eleventy.config.js", + matchUrlPattern: function (path, url) { + let pattern = new UrlPattern(url); + return pattern.match(path); + }, + }, + options + ); + + this.dir = this.getProjectDir(); + } + + getProjectDir() { + // TODO? improve with process.env.LAMBDA_TASK_ROOT—was `/var/task/` on lambda (not local) + let dir = path.join(this.options.functionsDir, this.name); + let paths = [ + path.join(TemplatePath.getWorkingDir(), dir), // netlify dev + path.join("/var/task/src/", dir), // AWS Lambda absolute path + ]; + + for (let path of paths) { + if (fs.existsSync(path)) { + return path; + } + } + + throw new Error( + `Couldn’t find the "${dir}" directory. Looked in: ${paths}` + ); + } + + getContentMap() { + let fullPath = TemplatePath.absolutePath( + this.dir, + this.options.mapFilename + ); + debug( + `Including content map (maps output URLs to input files) from ${fullPath}` + ); + return require(fullPath); + } + + matchUrlPattern(contentMap) { + for (let url in contentMap) { + let result = this.options.matchUrlPattern(this.event.path, url); + if (result) { + return { + pathParams: result, + inputPath: contentMap[url], + }; + } + } + + throw new Error( + `No matching URL found for ${this.event.path} in ${JSON.stringify( + contentMap + )}` + ); + } + + async render(options = {}) { + // TODO is this necessary? + if (this.dir.startsWith("/var/task/")) { + process.chdir(this.dir); + } + + let inputDir = path.join(this.dir, this.options.inputDir); + let configPath = path.join(this.dir, this.options.configFilename); + let { pathParams, inputPath } = this.matchUrlPattern(this.getContentMap()); + + debug(`Current dir: ${process.cwd()}`); + debug(`Project dir: ${this.dir}`); + debug(`Config path: ${configPath}`); + + debug(`Input dir: ${inputDir}`); + debug(`Requested URL: ${this.event.path}`); + debug(`Path params: ${pathParams}`); + debug(`Input path: ${inputPath}`); + + let elev = new Eleventy(inputPath, null, { + configPath, + config: (eleventyConfig) => { + if (options.precompiledCollections) { + eleventyConfig.setPrecompiledCollections( + options.precompiledCollections + ); + } + + // Add the params to Global Data + eleventyConfig.addGlobalData("eleventy.serverless", { + query: this.event.queryStringParameters, + path: pathParams, + }); + }, + }); + + elev.setInputDir(inputDir); + await elev.init(); + + let json = await elev.toJSON(); + if (!json.length) { + throw new Error("Couldn’t find any generated output from Eleventy."); + } + + debug(`Eleventy generated ${json.length} templates.`); + + for (let entry of json) { + if (entry.inputPath === inputPath) { + return entry.content; + } + } + + // Log to Serverless Function output + console.log(json); + throw new Error( + `Couldn’t find any matching output from Eleventy for ${inputPath}` + ); + } +} + +module.exports = Serverless; From 5765284030ff60077a65b99524bfcaa8ddc68cf4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 14 May 2021 14:23:13 -0500 Subject: [PATCH 426/746] v1.0.0-canary.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ec27518b..99e7822fb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.20", + "version": "1.0.0-canary.21", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From f79b2b4c3ce2ea56d1bccf09e52b8fa900168409 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 14 May 2021 23:48:49 -0500 Subject: [PATCH 427/746] Got rid of the separate bundler script! --- src/Eleventy.js | 24 +++++++++--- src/Plugins/ServerlessPlugin.js | 65 ++++++++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 1b67583b7..6c970bcf1 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -119,7 +119,8 @@ class Eleventy { /** @member {Object} - tbd. */ this.watchTargets = new EleventyWatchTargets(); this.watchTargets.addAndMakeGlob(this.config.additionalWatchTargets); - this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; + this.watchTargets.watchJavaScriptDependencies = + this.config.watchJavaScriptDependencies; } getNewTimestamp() { @@ -337,18 +338,29 @@ class Eleventy { this.writer.extensionMap = this.extensionMap; this.writer.setEleventyFiles(this.eleventyFiles); + let dirs = { + input: this.inputDir, + data: this.templateData.getDataDir(), + includes: this.eleventyFiles.getIncludesDir(), + layouts: this.eleventyFiles.getLayoutsDir(), + output: this.outputDir, + }; + debug(`Directories: -Input: ${this.inputDir} -Data: ${this.templateData.getDataDir()} -Includes: ${this.eleventyFiles.getIncludesDir()} -Layouts: ${this.eleventyFiles.getLayoutsDir()} -Output: ${this.outputDir} +Input: ${dirs.input} +Data: ${dirs.data} +Includes: ${dirs.includes} +Layouts: ${dirs.layouts} +Output: ${dirs.output} Template Formats: ${formats.join(",")} Verbose Output: ${this.verboseMode}`); this.writer.setVerboseOutput(this.verboseMode); this.writer.setDryRun(this.isDryRun); + this.config.events.emit("eleventy.directories", dirs); + + // …why does this return this return this.templateData.cacheData(); } diff --git a/src/Plugins/ServerlessPlugin.js b/src/Plugins/ServerlessPlugin.js index 5a29d1f6c..befae6b50 100644 --- a/src/Plugins/ServerlessPlugin.js +++ b/src/Plugins/ServerlessPlugin.js @@ -1,9 +1,10 @@ const fs = require("fs"); +const fsp = fs.promises; const path = require("path"); const TOML = require("@iarna/toml"); +const copy = require("recursive-copy"); const dependencyTree = require("@11ty/dependency-tree"); const TemplatePath = require("../TemplatePath"); -const { default: copy } = require("recursive-copy"); const debug = require("debug")("Eleventy:Serverless"); function getNodeModulesList(files) { @@ -51,18 +52,30 @@ class BundlerHelper { this.dir = path.join(options.functionsDir, name); } - getOutputFilename(filename) { - return TemplatePath.addLeadingDotSlash(path.join(this.dir, filename)); + getOutputPath(filepath) { + return TemplatePath.addLeadingDotSlash(path.join(this.dir, filepath)); } copyFile(fullPath, outputFilename) { - fs.copyFileSync(fullPath, this.getOutputFilename(outputFilename)); + console.log(`Copying ${fullPath} to ${this.getOutputPath(outputFilename)}`); + fs.copyFileSync(fullPath, this.getOutputPath(outputFilename)); + } + + recursiveCopy(src, dest) { + let finalDest = this.getOutputPath(dest || src); + + return copy(src, finalDest, { + overwrite: true, + dot: true, + junk: false, + results: false, + }); } writeBundlerDependenciesFile(filename, deps = []) { let modules = deps.map((name) => `require("${name}");`); if (modules.length) { - let fullPath = this.getOutputFilename(filename); + let fullPath = this.getOutputPath(filename); fs.writeFileSync(fullPath, modules.join("\n")); debug( `Writing a file to make it very obvious to the serverless bundler which extra \`require\`s are needed from the config file (×${modules.length}): ${fullPath}` @@ -71,7 +84,7 @@ class BundlerHelper { } writeDependencyEntryFile() { - let modulesFilename = this.getOutputFilename("eleventy-bundler-modules.js"); + let modulesFilename = this.getOutputPath("eleventy-bundler-modules.js"); if (!fs.existsSync(modulesFilename)) { this.writeBundlerDependenciesFile("eleventy-bundler-modules.js", [ "./eleventy-app-config-modules.js", @@ -102,6 +115,7 @@ module.exports = function (eleventyConfig, options = {}) { { name: "", functionsDir: "./functions/", + copy: [], // Add automated redirects to netlify.toml (appends or creates, avoids duplicate entries) redirects: function (outputMap) { let redirects = []; @@ -143,6 +157,26 @@ module.exports = function (eleventyConfig, options = {}) { let helper = new BundlerHelper(options.name, options); helper.writeDependencyEntryFile(); + // extra copy targets + (async function () { + if (options.copy && Array.isArray(options.copy)) { + let promises = []; + for (let cp of options.copy) { + if (typeof cp === "string") { + promises.push(helper.recursiveCopy(cp)); + } else if (cp.from && cp.to) { + promises.push(helper.recursiveCopy(cp.from, cp.to)); + } else { + debug( + "Ignored extra copy %o (needs to be a string or a {from: '', to: ''})", + cp + ); + } + } + await Promise.all(promises); + } + })(); + // TODO is this necessary or can we just use require("eleventy.config.js") in the `eleventy-bundler-modules.js` file eleventyConfig.on("eleventy.env", (env) => { helper.copyFile(env.config, "eleventy.config.js"); @@ -153,6 +187,16 @@ module.exports = function (eleventyConfig, options = {}) { helper.writeDependencyGlobalDataFile(fileList); }); + eleventyConfig.on("eleventy.directories", async (dirs) => { + let promises = []; + promises.push(copy(dirs.data, helper.getOutputPath(dirs.data))); + promises.push(copy(dirs.includes, helper.getOutputPath(dirs.includes))); + if (dirs.layouts) { + promises.push(copy(dirs.layouts, helper.getOutputPath(dirs.layouts))); + } + await Promise.all(promises); + }); + eleventyConfig.on("eleventy.dependencyMap", (templateMap) => { let outputMap = {}; @@ -165,9 +209,7 @@ module.exports = function (eleventyConfig, options = {}) { // Maps input files to output paths let mapEntryCount = Object.keys(outputMap).length; if (mapEntryCount > 0) { - let filename = TemplatePath.addLeadingDotSlash( - path.join(dir, "eleventy-serverless-map.json") - ); + let filename = helper.getOutputPath("eleventy-serverless-map.json"); fs.writeFileSync(filename, JSON.stringify(outputMap, null, 2)); console.log( `Eleventy Serverless (${options.name}), writing (×${mapEntryCount}): ${filename}` @@ -175,6 +217,11 @@ module.exports = function (eleventyConfig, options = {}) { // Write redirects into netlify.toml options.redirects(outputMap); + + // Copy templates to bundle folder + for (let url in outputMap) { + helper.recursiveCopy(outputMap[url]); + } } }); } From be865cff0907dd2a0ada3383554be24ddf475837 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 16 May 2021 20:31:00 -0500 Subject: [PATCH 428/746] Adds source to ENV variables. Prefixes existing event names with `eleventy.` (make dupes for backwards compat). Adds some code to prepare for browsersync middleware --- cmd.js | 1 + src/Eleventy.js | 23 +++++++--- src/Engines/Nunjucks.js | 4 +- ...ssPlugin.js => ServerlessBundlerPlugin.js} | 40 +++++++++++------- src/Serverless.js | 42 +++++++++++++------ src/TemplateContent.js | 2 +- test/TemplateTest.js | 4 +- 7 files changed, 79 insertions(+), 37 deletions(-) rename src/Plugins/{ServerlessPlugin.js => ServerlessBundlerPlugin.js} (87%) diff --git a/cmd.js b/cmd.js index 46d8b0c11..75ebd21ef 100755 --- a/cmd.js +++ b/cmd.js @@ -71,6 +71,7 @@ try { // --quiet and --quiet=true both resolve to true quietMode: argv.quiet, configPath: argv.config, + source: "cli", }); // reuse ErrorHandler instance in Eleventy diff --git a/src/Eleventy.js b/src/Eleventy.js index 6c970bcf1..50525ac2c 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -53,6 +53,12 @@ class Eleventy { */ this.configPath = options.configPath; + /** + * @member {String} - Called via CLI (`cli`) or Programmatically (`script`) + * @default "script" + */ + this.source = options.source || "script"; + /** * @member {Object} - Initialize Eleventy environment variables * @default null @@ -373,6 +379,7 @@ Verbose Output: ${this.verboseMode}`); return { config: absolutePathToConfig, root, + source: this.source, }; } @@ -385,6 +392,8 @@ Verbose Output: ${this.verboseMode}`); process.env.ELEVENTY_ROOT = env.root; debug("Setting process.env.ELEVENTY_ROOT: %o", env.root); + process.env.ELEVENTY_SOURCE = this.source; + // careful here, setting to false will cast to string "false" which is truthy if (process.env.AWS_LAMBDA_FUNCTION_NAME) { process.env.ELEVENTY_SERVERLESS = true; @@ -540,7 +549,7 @@ Arguments: * @param {String} changedFilePath - File that triggered a re-run (added or modified) */ async _addFileToWatchQueue(changedFilePath) { - eventBus.emit("resourceModified", changedFilePath); + eventBus.emit("eleventy.resourceModified", changedFilePath); this.watchManager.addToPendingQueue(changedFilePath); } @@ -557,10 +566,9 @@ Arguments: this.watchManager.setBuildRunning(); - await this.config.events.emit( - "beforeWatch", - this.watchManager.getActiveQueue() - ); + let queue = this.watchManager.getActiveQueue(); + await this.config.events.emit("beforeWatch", queue); + await this.config.events.emit("eleventy.beforeWatch", queue); // reset and reload global configuration :O if ( @@ -878,6 +886,8 @@ Arguments: try { await this.config.events.emit("beforeBuild"); + await this.config.events.emit("eleventy.before"); + let promise; if (to === "fs") { promise = this.writer.write(); @@ -900,6 +910,7 @@ Arguments: } await this.config.events.emit("afterBuild"); + await this.config.events.emit("eleventy.after"); } catch (e) { hasError = true; ret = { @@ -930,4 +941,4 @@ Arguments: module.exports = Eleventy; module.exports.Serverless = require("./Serverless"); -module.exports.ServerlessPlugin = require("./Plugins/ServerlessPlugin"); +module.exports.ServerlessBundlerPlugin = require("./Plugins/ServerlessBundlerPlugin"); diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 6b0388bdb..1c6fe5be9 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -34,7 +34,7 @@ const eventBus = require("../EventBus"); // } // } // }; -// eventBus.on("resourceModified", evictByPath); +// eventBus.on("eleventy.resourceModified", evictByPath); // let _compile = NunjucksLib.Template.prototype._compile; // NunjucksLib.Template.prototype._compile = function _wrap_compile(...args) { @@ -128,7 +128,7 @@ class Nunjucks extends TemplateEngine { this.njkEnv = env || new NunjucksLib.Environment(fsLoader); // Correct, but overbroad. Better would be to evict more granularly, but // resolution from paths isn't straightforward. - eventBus.on("resourceModified", (path) => { + eventBus.on("eleventy.resourceModified", (path) => { this.njkEnv.invalidateCache(); }); diff --git a/src/Plugins/ServerlessPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js similarity index 87% rename from src/Plugins/ServerlessPlugin.js rename to src/Plugins/ServerlessBundlerPlugin.js index befae6b50..f5a3da4fb 100644 --- a/src/Plugins/ServerlessPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -1,5 +1,4 @@ const fs = require("fs"); -const fsp = fs.promises; const path = require("path"); const TOML = require("@iarna/toml"); const copy = require("recursive-copy"); @@ -50,6 +49,7 @@ class BundlerHelper { this.name = name; this.options = options; this.dir = path.join(options.functionsDir, name); + this.copyCount = 0; } getOutputPath(filepath) { @@ -57,18 +57,24 @@ class BundlerHelper { } copyFile(fullPath, outputFilename) { - console.log(`Copying ${fullPath} to ${this.getOutputPath(outputFilename)}`); + debug( + `Eleventy Serverless: Copying ${fullPath} to ${this.getOutputPath( + outputFilename + )}` + ); fs.copyFileSync(fullPath, this.getOutputPath(outputFilename)); + this.copyCount++; } recursiveCopy(src, dest) { let finalDest = this.getOutputPath(dest || src); - return copy(src, finalDest, { overwrite: true, dot: true, junk: false, results: false, + }).on(copy.events.COPY_FILE_COMPLETE, () => { + this.copyCount++; }); } @@ -137,7 +143,7 @@ module.exports = function (eleventyConfig, options = {}) { let newCfg = addRedirectsWithoutDuplicates(cfg, redirects); fs.writeFileSync(configFilename, TOML.stringify(newCfg)); - console.log( + debug( `Eleventy Serverless (${options.name}), writing (×${redirects.length}): ${configFilename}` ); }, @@ -151,14 +157,13 @@ module.exports = function (eleventyConfig, options = {}) { ); } - let dir = path.join(options.functionsDir, options.name); - - if (!process.env.ELEVENTY_SERVERLESS) { + if (process.env.ELEVENTY_SOURCE === "cli") { let helper = new BundlerHelper(options.name, options); helper.writeDependencyEntryFile(); - // extra copy targets - (async function () { + eleventyConfig.on("eleventy.after", async () => { + // extra copy targets + // we put these in after a build so that we can grab files generated _by_ the build too if (options.copy && Array.isArray(options.copy)) { let promises = []; for (let cp of options.copy) { @@ -175,7 +180,13 @@ module.exports = function (eleventyConfig, options = {}) { } await Promise.all(promises); } - })(); + + console.log( + `Eleventy Serverless: ${ + helper.copyCount + } files bundled with ${helper.getOutputPath("")}.` + ); + }); // TODO is this necessary or can we just use require("eleventy.config.js") in the `eleventy-bundler-modules.js` file eleventyConfig.on("eleventy.env", (env) => { @@ -189,10 +200,10 @@ module.exports = function (eleventyConfig, options = {}) { eleventyConfig.on("eleventy.directories", async (dirs) => { let promises = []; - promises.push(copy(dirs.data, helper.getOutputPath(dirs.data))); - promises.push(copy(dirs.includes, helper.getOutputPath(dirs.includes))); + promises.push(helper.recursiveCopy(dirs.data)); + promises.push(helper.recursiveCopy(dirs.includes)); if (dirs.layouts) { - promises.push(copy(dirs.layouts, helper.getOutputPath(dirs.layouts))); + promises.push(helper.recursiveCopy(dirs.layouts)); } await Promise.all(promises); }); @@ -211,9 +222,10 @@ module.exports = function (eleventyConfig, options = {}) { if (mapEntryCount > 0) { let filename = helper.getOutputPath("eleventy-serverless-map.json"); fs.writeFileSync(filename, JSON.stringify(outputMap, null, 2)); - console.log( + debug( `Eleventy Serverless (${options.name}), writing (×${mapEntryCount}): ${filename}` ); + this.copyCount++; // Write redirects into netlify.toml options.redirects(outputMap); diff --git a/src/Serverless.js b/src/Serverless.js index 74552b233..507fcdc3a 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -7,9 +7,9 @@ const UrlPattern = require("url-pattern"); const debug = require("debug")("Eleventy:Serverless"); class Serverless { - constructor(name, event, options = {}) { + constructor(name, path, options = {}) { this.name = name; - this.event = event; + this.path = path; this.options = Object.assign( { @@ -22,6 +22,7 @@ class Serverless { let pattern = new UrlPattern(url); return pattern.match(path); }, + query: {}, }, options ); @@ -59,9 +60,22 @@ class Serverless { return require(fullPath); } - matchUrlPattern(contentMap) { + isServerlessUrl(urlPath) { + let contentMap = this.getContentMap(); + + for (let url in contentMap) { + if (this.options.matchUrlPattern(urlPath, url)) { + return true; + } + } + return false; + } + + matchUrlPattern(urlPath) { + let contentMap = this.getContentMap(); + for (let url in contentMap) { - let result = this.options.matchUrlPattern(this.event.path, url); + let result = this.options.matchUrlPattern(urlPath, url); if (result) { return { pathParams: result, @@ -70,11 +84,7 @@ class Serverless { } } - throw new Error( - `No matching URL found for ${this.event.path} in ${JSON.stringify( - contentMap - )}` - ); + return {}; } async render(options = {}) { @@ -85,14 +95,22 @@ class Serverless { let inputDir = path.join(this.dir, this.options.inputDir); let configPath = path.join(this.dir, this.options.configFilename); - let { pathParams, inputPath } = this.matchUrlPattern(this.getContentMap()); + let { pathParams, inputPath } = this.matchUrlPattern(this.path); + + if (!pathParams || !inputPath) { + throw new Error( + `No matching URL found for ${this.path} in ${JSON.stringify( + this.getContentMap() + )}` + ); + } debug(`Current dir: ${process.cwd()}`); debug(`Project dir: ${this.dir}`); debug(`Config path: ${configPath}`); debug(`Input dir: ${inputDir}`); - debug(`Requested URL: ${this.event.path}`); + debug(`Requested URL: ${this.path}`); debug(`Path params: ${pathParams}`); debug(`Input path: ${inputPath}`); @@ -107,7 +125,7 @@ class Serverless { // Add the params to Global Data eleventyConfig.addGlobalData("eleventy.serverless", { - query: this.event.queryStringParameters, + query: this.options.query, path: pathParams, }); }, diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 78feb9c5d..813e43756 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -358,7 +358,7 @@ class TemplateContent { TemplateContent._inputCache = new Map(); TemplateContent._compileEngineCache = new Map(); -eventBus.on("resourceModified", (path) => { +eventBus.on("eleventy.resourceModified", (path) => { TemplateContent.deleteCached(path); }); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 9445e9168..ff64a8d29 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2131,7 +2131,7 @@ test("Make sure layout cache takes new changes during watch (nunjucks)", async ( await fsp.writeFile(filePath, `alert("bye");`, { encoding: "utf8" }); - eventBus.emit("resourceModified", filePath); + eventBus.emit("eleventy.resourceModified", filePath); t.is((await tmpl.render(data)).trim(), ''); }); @@ -2152,7 +2152,7 @@ test("Make sure layout cache takes new changes during watch (liquid)", async (t) await fsp.writeFile(filePath, `alert("bye");`, { encoding: "utf8" }); - eventBus.emit("resourceModified", filePath); + eventBus.emit("eleventy.resourceModified", filePath); t.is((await tmpl.render(data)).trim(), ''); }); From 1c4baf22a0dcb8f4a430795a820255dbacfa7b24 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 17 May 2021 14:36:12 -0500 Subject: [PATCH 429/746] All options moved into constuctor --- src/Serverless.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Serverless.js b/src/Serverless.js index 507fcdc3a..142766cc2 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -23,6 +23,7 @@ class Serverless { return pattern.match(path); }, query: {}, + precompiledCollections: {}, }, options ); @@ -87,7 +88,7 @@ class Serverless { return {}; } - async render(options = {}) { + async render() { // TODO is this necessary? if (this.dir.startsWith("/var/task/")) { process.chdir(this.dir); @@ -117,9 +118,9 @@ class Serverless { let elev = new Eleventy(inputPath, null, { configPath, config: (eleventyConfig) => { - if (options.precompiledCollections) { + if (Object.keys(this.options.precompiledCollections).length > 0) { eleventyConfig.setPrecompiledCollections( - options.precompiledCollections + this.options.precompiledCollections ); } From fb8e453c1a3a79e02ddaaea5e463d89ce8b29f2e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 17 May 2021 17:15:24 -0500 Subject: [PATCH 430/746] Hide the browser-sync module name from the serverless bundler. --- src/EleventyServe.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 54b19238a..26b98b4be 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -131,9 +131,10 @@ class EleventyServe { } serve(port) { - // only load on serve—this is pretty expensive - const browserSync = require("browser-sync"); - this.server = browserSync.create("eleventy-server"); + // Only load on serve—this is pretty expensive + // We use a module name here to hide this from the serverless bundler. + let moduleName = "browser-sync"; + this.server = require(moduleName).create("eleventy-server"); let pathPrefix = this.getPathPrefix(); From 4210697f215992db4925a6f7b34d222baef54461 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 17 May 2021 17:22:44 -0500 Subject: [PATCH 431/746] v1.0.0-canary.22 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 99e7822fb..6a7ff88c8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.21", + "version": "1.0.0-canary.22", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -79,7 +79,7 @@ "husky": "^5.1.3", "ink-docstrap": "1.3.2", "js-yaml": "^4.0.0", - "jsdoc": "3.6.6", + "jsdoc": "3.6.7", "lint-staged": "^10.5.4", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", From ed1d1898632ae38c11aa63c0bd472936d84c0e75 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 19 May 2021 20:50:10 -0500 Subject: [PATCH 432/746] =?UTF-8?q?More=20serverless=20bundler=20workaroun?= =?UTF-8?q?ds=20=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Eleventy.js | 13 +++++++++++-- src/EleventyServe.js | 14 +++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 97d161caf..cb7a1a1a3 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -119,7 +119,8 @@ class Eleventy { /** @member {Object} - tbd. */ this.watchTargets = new EleventyWatchTargets(); this.watchTargets.addAndMakeGlob(this.config.additionalWatchTargets); - this.watchTargets.watchJavaScriptDependencies = this.config.watchJavaScriptDependencies; + this.watchTargets.watchJavaScriptDependencies = + this.config.watchJavaScriptDependencies; } getNewTimestamp() { @@ -731,7 +732,15 @@ Arguments: this.watcherBench.setMinimumThresholdMs(500); this.watcherBench.reset(); - const chokidar = require("chokidar"); + // We use a string module name and try/catch here to hide this from the zisi and esbuild serverless bundlers + let chokidar; + // eslint-disable-next-line no-useless-catch + try { + let moduleName = "chokidar"; + chokidar = require(moduleName); + } catch (e) { + throw e; + } // Note that watching indirectly depends on this for fetching dependencies from JS files // See: TemplateWriter:pathCache and EleventyWatchTargets diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 26b98b4be..2051c3835 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -132,9 +132,17 @@ class EleventyServe { serve(port) { // Only load on serve—this is pretty expensive - // We use a module name here to hide this from the serverless bundler. - let moduleName = "browser-sync"; - this.server = require(moduleName).create("eleventy-server"); + // We use a string module name and try/catch here to hide this from the zisi and esbuild serverless bundlers + let server; + // eslint-disable-next-line no-useless-catch + try { + let moduleName = "browser-sync"; + server = require(moduleName); + } catch (e) { + throw e; + } + + this.server = server.create("eleventy-server"); let pathPrefix = this.getPathPrefix(); From e94b8be9116c5228261c910b9b07361338096722 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 19 May 2021 20:50:43 -0500 Subject: [PATCH 433/746] v1.0.0-canary.23 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a7ff88c8..1c367342d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.22", + "version": "1.0.0-canary.23", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 84ce976fddbe94eee78d77e23192339b9f741a6f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 20 May 2021 16:38:49 -0500 Subject: [PATCH 434/746] Expose more requires to esbuild to make Eleventy more bundleable. --- .npmignore | 1 + src/TemplateEngineManager.js | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.npmignore b/.npmignore index eb693a273..e341d01e4 100644 --- a/.npmignore +++ b/.npmignore @@ -1,4 +1,5 @@ docs docs-src test +coverage .* diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index f77b9cdcf..0540e2412 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -1,5 +1,6 @@ const EleventyBaseError = require("./EleventyBaseError"); class TemplateEngineManagerConfigError extends EleventyBaseError {} + class TemplateEngineManager { constructor(config) { if (!config) { @@ -55,8 +56,31 @@ class TemplateEngineManager { return this.engineCache[name]; } - let path = "./Engines/" + this.getClassNameFromTemplateKey(name); - const cls = require(path); + let cls; + // We include these as raw strings (and not more readable variables) so they’re parsed by the bundler. + if (name === "ejs") { + cls = require("./Engines/Ejs"); + } else if (name === "md") { + cls = require("./Engines/Markdown"); + } else if (name === "html") { + cls = require("./Engines/Html"); + } else if (name === "hbs") { + cls = require("./Engines/Handlebars"); + } else if (name === "mustache") { + cls = require("./Engines/Mustache"); + } else if (name === "haml") { + cls = require("./Engines/Haml"); + } else if (name === "pug") { + cls = require("./Engines/Pug"); + } else if (name === "njk") { + cls = require("./Engines/Nunjucks"); + } else if (name === "liquid") { + cls = require("./Engines/Liquid"); + } else if (name === "11ty.js") { + cls = require("./Engines/JavaScript"); + } else { + cls = require("./Engines/Custom"); + } let instance = new cls(name, includesDir, this.config); instance.extensionMap = extensionMap; From 741d914f7744b8c74c0622882a97c2752a871218 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 26 May 2021 09:44:37 -0500 Subject: [PATCH 435/746] Multiple setBrowserSyncConfig calls will deep merge the options together (for plugin friendliness) --- src/UserConfig.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index e3f2e5b6b..1cea64648 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -3,6 +3,7 @@ const semver = require("semver"); const { DateTime } = require("luxon"); const EventEmitter = require("./Util/AsyncEventEmitter"); const EleventyBaseError = require("./EleventyBaseError"); +const merge = require("./Util/Merge"); const bench = require("./BenchmarkManager").get("Configuration"); const aggregateBench = require("./BenchmarkManager").get("Aggregate"); const debug = require("debug")("Eleventy:UserConfig"); @@ -622,8 +623,12 @@ class UserConfig { this.watchJavaScriptDependencies = !!watchEnabled; } - setBrowserSyncConfig(options = {}) { - this.browserSyncConfig = options; + setBrowserSyncConfig(options = {}, mergeOptions = true) { + if (mergeOptions) { + this.browserSyncConfig = merge(this.browserSyncConfig, options); + } else { + this.browserSyncConfig = options; + } } setChokidarConfig(options = {}) { From 9850a2cba7a39581f84a3f3c45d28b5e60c8d106 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 26 May 2021 09:45:23 -0500 Subject: [PATCH 436/746] BrowserSync will fake-run the serverless functions locally! --- src/Eleventy.js | 4 +-- src/Plugins/ServerlessBundlerPlugin.js | 34 +++++++++++++++++++++++++- src/Serverless.js | 22 +++++++++++------ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 50525ac2c..bdfab9218 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -940,5 +940,5 @@ Arguments: } module.exports = Eleventy; -module.exports.Serverless = require("./Serverless"); -module.exports.ServerlessBundlerPlugin = require("./Plugins/ServerlessBundlerPlugin"); +module.exports.EleventyServerless = require("./Serverless"); +module.exports.EleventyServerlessBundlerPlugin = require("./Plugins/ServerlessBundlerPlugin"); diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index f5a3da4fb..f60a3c176 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -114,6 +114,35 @@ class BundlerHelper { modules ); } + + browserSyncMiddleware() { + let serverlessFilepath = TemplatePath.addLeadingDotSlash( + path.join(TemplatePath.getWorkingDir(), this.dir, "index") + ); + + return async (req, res, next) => { + let serverlessFunction = require(serverlessFilepath); + let url = new URL(req.url, "http://localhost/"); // any domain will do here, we just want the searchParams + + let start = new Date(); + let result = await serverlessFunction.handler({ + httpMethod: "GET", + path: req.url, + queryStringParameters: Object.fromEntries(url.searchParams), + }); + + if (result.statusCode === 404) { + // return static file + return next(); + } + + res.writeHead(result.statusCode, result.headers || {}); + res.write(result.body); + res.end(); + + console.log(`Dynamic Render: ${req.url} (${Date.now() - start}ms)`); + }; + } } module.exports = function (eleventyConfig, options = {}) { @@ -161,6 +190,10 @@ module.exports = function (eleventyConfig, options = {}) { let helper = new BundlerHelper(options.name, options); helper.writeDependencyEntryFile(); + eleventyConfig.setBrowserSyncConfig({ + middleware: [helper.browserSyncMiddleware()], + }); + eleventyConfig.on("eleventy.after", async () => { // extra copy targets // we put these in after a build so that we can grab files generated _by_ the build too @@ -188,7 +221,6 @@ module.exports = function (eleventyConfig, options = {}) { ); }); - // TODO is this necessary or can we just use require("eleventy.config.js") in the `eleventy-bundler-modules.js` file eleventyConfig.on("eleventy.env", (env) => { helper.copyFile(env.config, "eleventy.config.js"); helper.writeDependencyConfigFile(env.config); diff --git a/src/Serverless.js b/src/Serverless.js index 142766cc2..5273f8f4e 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -13,16 +13,18 @@ class Serverless { this.options = Object.assign( { - inputDir: "src", + inputDir: ".", functionsDir: "functions/", mapFilename: "eleventy-serverless-map.json", - // The bundle script sets the bundled config file name + // The ServerlessBundlerPlugin hard-codes to this (even if you used a different file name) configFilename: "eleventy.config.js", matchUrlPattern: function (path, url) { let pattern = new UrlPattern(url); return pattern.match(path); }, + // Query String Parameters query: {}, + // Inject shared collections precompiledCollections: {}, }, options @@ -99,11 +101,13 @@ class Serverless { let { pathParams, inputPath } = this.matchUrlPattern(this.path); if (!pathParams || !inputPath) { - throw new Error( + let err = new Error( `No matching URL found for ${this.path} in ${JSON.stringify( this.getContentMap() )}` ); + err.httpStatusCode = 404; + throw err; } debug(`Current dir: ${process.cwd()}`); @@ -137,11 +141,15 @@ class Serverless { let json = await elev.toJSON(); if (!json.length) { - throw new Error("Couldn’t find any generated output from Eleventy."); + let err = new Error( + `Couldn’t find any generated output from Eleventy (URL path parameters: ${JSON.stringify( + pathParams + )}).` + ); + err.httpStatusCode = 404; + throw err; } - debug(`Eleventy generated ${json.length} templates.`); - for (let entry of json) { if (entry.inputPath === inputPath) { return entry.content; @@ -151,7 +159,7 @@ class Serverless { // Log to Serverless Function output console.log(json); throw new Error( - `Couldn’t find any matching output from Eleventy for ${inputPath}` + `Couldn’t find any matching output from Eleventy for ${inputPath} (${json.length} pages rendered).` ); } } From 7fb4314a9d0b8a3515b512c3d518189c4182ae59 Mon Sep 17 00:00:00 2001 From: milahu Date: Wed, 26 May 2021 17:57:24 +0200 Subject: [PATCH 437/746] compat node 12 --- src/TemplateConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 2d0be4c45..f0d9e77d9 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -210,7 +210,7 @@ class TemplateConfig { // TODO the error message here is bad and I feel bad (needs more accurate info) throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + - (err.message?.includes("Cannot find module") + (err.message && err.message.includes("Cannot find module") ? chalk.blueBright(" You may need to run `npm install`.") : ""), err From 6be2a098a2fc2263d6e2052bfa1fcc4009f80a2a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 26 May 2021 20:42:18 -0500 Subject: [PATCH 438/746] =?UTF-8?q?Add=20a=20test=20to=20make=20sure=20glo?= =?UTF-8?q?bal=20data=20wasn=E2=80=99t=20changing=20from=20a=20deep=20merg?= =?UTF-8?q?e=20somewhere=20(it=20wasn=E2=80=99t,=20but=20let=E2=80=99s=20k?= =?UTF-8?q?eep=20the=20test=20around=20anyway)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/PaginationTest.js | 38 +++++++++++++++++++ .../_data/testdata.js | 14 +++++++ .../paged-differing-data-set.njk | 12 ++++++ 3 files changed, 64 insertions(+) create mode 100644 test/stubs/paged-global-data-mutable/_data/testdata.js create mode 100644 test/stubs/paged-global-data-mutable/paged-differing-data-set.njk diff --git a/test/PaginationTest.js b/test/PaginationTest.js index 8f165f6c9..270ed6146 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -755,3 +755,41 @@ test("Pagination make sure pageNumber is numeric for {{ pageNumber + 1 }} Issue t.is(templates[0].data.pagination.pageNumber, 0); t.not(templates[0].data.pagination.pageNumber, "0"); }); + +test("Pagination mutable global data", async (t) => { + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData( + "./test/stubs/paged-global-data-mutable/", + eleventyConfig + ); + await dataObj.cacheData(); + + let tmpl = getNewTemplate( + "./test/stubs/paged-global-data-mutable/paged-differing-data-set.njk", + "./test/stubs/", + "./dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.is(templates.length, 3); + t.deepEqual(templates[0].data.pagination.items[0], { + key1: "item1", + key2: "item2", + }); + t.deepEqual(templates[1].data.pagination.items[0], { + key3: "item3", + key4: "item4", + }); + t.deepEqual(templates[2].data.pagination.items[0], { + key5: "item5", + key6: "item6", + }); + + t.deepEqual(templates[0].data.item, { key1: "item1", key2: "item2" }); + t.deepEqual(templates[1].data.item, { key3: "item3", key4: "item4" }); + t.deepEqual(templates[2].data.item, { key5: "item5", key6: "item6" }); +}); diff --git a/test/stubs/paged-global-data-mutable/_data/testdata.js b/test/stubs/paged-global-data-mutable/_data/testdata.js new file mode 100644 index 000000000..97bd7a1e4 --- /dev/null +++ b/test/stubs/paged-global-data-mutable/_data/testdata.js @@ -0,0 +1,14 @@ +module.exports = [ + { + key1: "item1", + key2: "item2", + }, + { + key3: "item3", + key4: "item4", + }, + { + key5: "item5", + key6: "item6", + }, +]; diff --git a/test/stubs/paged-global-data-mutable/paged-differing-data-set.njk b/test/stubs/paged-global-data-mutable/paged-differing-data-set.njk new file mode 100644 index 000000000..be59f0db9 --- /dev/null +++ b/test/stubs/paged-global-data-mutable/paged-differing-data-set.njk @@ -0,0 +1,12 @@ +--- +pagination: + data: testdata + size: 1 + alias: item +--- +1:{{ item.key1 }} +2:{{ item.key2 }} +3:{{ item.key3 }} +4:{{ item.key4 }} +5:{{ item.key5 }} +6:{{ item.key6 }} \ No newline at end of file From f061d8488eb10211a5f0bf206dbcf08a4f05429c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 1 Jun 2021 23:20:33 -0500 Subject: [PATCH 439/746] 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 From 5ffb3b14229138c9de133108c2b0e8f61f5f5649 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 2 Jun 2021 10:58:30 -0500 Subject: [PATCH 440/746] Test for eleventyExcludeFromCollections: true and permalink:false https://github.com/11ty/eleventy/issues/1754#issuecomment-852865233 --- src/TemplatePermalink.js | 1 + test/TemplateMapTest.js | 26 +++++++++++++++++++ ...tyExcludeFromCollectionsPermalinkFalse.njk | 9 +++++++ 3 files changed, 36 insertions(+) create mode 100644 test/stubs/eleventyExcludeFromCollectionsPermalinkFalse.njk diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 539b100e4..e9c66d488 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -43,6 +43,7 @@ class TemplatePermalink { } // default if permalink is an Object but does not have a `build` prop + // note that `read` will opt-out this template from collections. See TemplateBehavior->isIncludedInCollections if (!("behavior" in link) && !("build" in link)) { link.behavior = "read"; } diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index f51f04d36..5f40bbe82 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -988,6 +988,32 @@ test("eleventyExcludeFromCollections", async (t) => { t.is(collections.dog.length, 1); }); +test("eleventyExcludeFromCollections and permalink: false", async (t) => { + let eleventyConfig = new TemplateConfig(); + let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); + + let tm = new TemplateMap(eleventyConfig); + await tm.add(tmpl1); + + let excludedTmpl = getNewTemplate( + "./test/stubs/eleventyExcludeFromCollectionsPermalinkFalse.njk", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(excludedTmpl); + + await tm.cache(); + + t.is(tm.getMap().length, 2); + + let collections = await tm._testGetCollectionsData(); + t.is(collections.all.length, 1); + t.is(collections.post.length, 1); + t.is(collections.dog.length, 1); +}); + test("Paginate over collections.all", async (t) => { let eleventyConfig = new TemplateConfig(); let tmpl1 = getNewTemplateByNumber(1, eleventyConfig); diff --git a/test/stubs/eleventyExcludeFromCollectionsPermalinkFalse.njk b/test/stubs/eleventyExcludeFromCollectionsPermalinkFalse.njk new file mode 100644 index 000000000..db6b592ed --- /dev/null +++ b/test/stubs/eleventyExcludeFromCollectionsPermalinkFalse.njk @@ -0,0 +1,9 @@ +--- +title: Paged Test +eleventyExcludeFromCollections: true +permalink: false +tags: + - post + - dog +--- +{{ title }} \ No newline at end of file From 50b18bdd18c4be57e2fb66a466b5b235389292c5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 6 Jun 2021 15:24:00 -0500 Subject: [PATCH 441/746] Serverless templates were being included in collections incorrectly (due to bug in of behavior calcs in Eleventy order of operations) --- src/Template.js | 15 +++++++++------ src/TemplateBehavior.js | 28 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/Template.js b/src/Template.js index 162240a06..47c9571b4 100755 --- a/src/Template.js +++ b/src/Template.js @@ -63,7 +63,7 @@ class Template extends TemplateContent { this.outputFormat = "fs"; - this.behavior = new TemplateBehavior(); + this.behavior = new TemplateBehavior(this.config); this.behavior.setOutputFormat(this.outputFormat); } @@ -582,19 +582,19 @@ class Template extends TemplateContent { async getTemplates(data) { // no pagination on permalink.serverless for local builds let hasPagination = Pagination.hasPagination(data); - let isServerlessRenderOnBuild = !this.behavior.isRenderable(); - let isServerlessRenderOnServerless = + let isServerlessTemplateRenderingViaBuild = !this.behavior.isRenderable(); + let isServerlessTemplateRenderingViaServerless = this.behavior.isRenderForced() && hasPagination && "serverless" in data.pagination; if ( !hasPagination || - isServerlessRenderOnBuild || - isServerlessRenderOnServerless + isServerlessTemplateRenderingViaBuild || + isServerlessTemplateRenderingViaServerless ) { // inject pagination page data for just this one entry for serverless render - if (isServerlessRenderOnServerless && hasPagination) { + if (isServerlessTemplateRenderingViaServerless && hasPagination) { let pagination = new Pagination(data, this.config); let paginationItems = pagination.getTruncatedServerlessData(data); let override = pagination.getOverrideData(paginationItems); @@ -925,6 +925,8 @@ class Template extends TemplateContent { // Important reminder: This is where the template data is first generated via TemplateMap let data = dataOverride || (await this.getData()); + this.behavior.setRenderViaDataCascade(data); + let entries = []; // does not return outputPath or url, we don’t want to render permalinks yet entries.push({ @@ -932,6 +934,7 @@ class Template extends TemplateContent { inputPath: this.inputPath, data, }); + return entries; } diff --git a/src/TemplateBehavior.js b/src/TemplateBehavior.js index 9767f1e0e..afa20c9ca 100644 --- a/src/TemplateBehavior.js +++ b/src/TemplateBehavior.js @@ -1,8 +1,15 @@ +const isPlainObject = require("lodash/isPlainObject"); + class TemplateBehavior { - constructor() { + constructor(config) { this.render = true; this.write = true; this.outputFormat = null; + + if (!config) { + throw new Error("Missing config argument in TemplateBehavior"); + } + this.config = config; } isRenderable() { @@ -25,6 +32,25 @@ class TemplateBehavior { return this.isRenderable(); } + setRenderViaDataCascade(data) { + // render is false *only* if `build` key does not exist in permalink objects (both in data and eleventyComputed) + // (note that permalink: false means it won’t write but will still render) + + let keys = new Set(); + if (isPlainObject(data.permalink)) { + keys.add(...Object.keys(data.permalink)); + } + + let computedKey = this.config.keys.computed; + if (computedKey in data && isPlainObject(data[computedKey].permalink)) { + keys.add(...Object.keys(data[computedKey].permalink)); + } + + if (keys.size) { + this.render = keys.has("build"); + } + } + setFromPermalink(templatePermalink) { this.render = templatePermalink._isRendered; this.write = templatePermalink._writeToFileSystem; From e9b385fefde18fabfcae167a527a3c55095ffbcc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 7 Jun 2021 09:07:51 -0500 Subject: [PATCH 442/746] Fix for error messaging when two serverless permalinks match exactly --- cmd.js | 4 ++-- src/Plugins/ServerlessBundlerPlugin.js | 6 +++-- src/Serverless.js | 31 +++++++++++++++++++------- src/TemplateMap.js | 13 +++++++---- src/TemplatePermalink.js | 14 +++++------- test/TemplatePermalinkTest.js | 16 +++++++++++++ 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/cmd.js b/cmd.js index 75ebd21ef..718c79758 100755 --- a/cmd.js +++ b/cmd.js @@ -105,7 +105,7 @@ try { .catch((e) => { // Build failed but error message already displayed. startBrowsersync = false; - console.log("Watch catch"); + // A build error occurred and we aren’t going to --serve }) .then(function () { if (startBrowsersync) { @@ -114,7 +114,7 @@ try { }); } else if (argv.watch) { elev.watch().catch((e) => { - console.log("watch catch 2"); + // A build error occurred and we aren’t going to --watch }); } else { if (argv.to === "json") { diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index f60a3c176..89c4da422 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -145,7 +145,7 @@ class BundlerHelper { } } -module.exports = function (eleventyConfig, options = {}) { +function EleventyPlugin(eleventyConfig, options = {}) { options = Object.assign( { name: "", @@ -269,4 +269,6 @@ module.exports = function (eleventyConfig, options = {}) { } }); } -}; +} + +module.exports = EleventyPlugin; diff --git a/src/Serverless.js b/src/Serverless.js index 5273f8f4e..d84f87eac 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -16,13 +16,13 @@ class Serverless { inputDir: ".", functionsDir: "functions/", mapFilename: "eleventy-serverless-map.json", - // The ServerlessBundlerPlugin hard-codes to this (even if you used a different file name) + // ServerlessBundlerPlugin hard-codes to this (even if you used a different file name) configFilename: "eleventy.config.js", - matchUrlPattern: function (path, url) { - let pattern = new UrlPattern(url); + // Query String Parameters + matchUrlToPattern(path, urlToCompare) { + let pattern = new UrlPattern(urlToCompare); return pattern.match(path); }, - // Query String Parameters query: {}, // Inject shared collections precompiledCollections: {}, @@ -67,7 +67,7 @@ class Serverless { let contentMap = this.getContentMap(); for (let url in contentMap) { - if (this.options.matchUrlPattern(urlPath, url)) { + if (this.options.matchUrlToPattern(urlPath, url)) { return true; } } @@ -76,15 +76,30 @@ class Serverless { matchUrlPattern(urlPath) { let contentMap = this.getContentMap(); + let matches = []; for (let url in contentMap) { - let result = this.options.matchUrlPattern(urlPath, url); + let result = this.options.matchUrlToPattern(urlPath, url); if (result) { - return { + matches.push({ + compareTo: url, pathParams: result, inputPath: contentMap[url], - }; + }); + } + } + + if (matches.length) { + if (matches.length > 1) { + console.log( + `Eleventy Serverless conflict: there are multiple serverless paths that match the current URL (${urlPath}): ${JSON.stringify( + matches, + null, + 2 + )}` + ); } + return matches[0]; } return {}; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 90777117f..8787b8605 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -614,15 +614,20 @@ class TemplateMap { for (let entry of this.map) { for (let page of entry._pages) { if (page.url === false) { - // do nothing + // do nothing, note that url exists in serverless mode } else if (!permalinks[page.url]) { permalinks[page.url] = [entry.inputPath]; } else { + // in serverless mode, page.outputPath is `false` + let isServerlessTemplate = !page.outputPath; + warnings[ page.outputPath - ] = `Output conflict: multiple input files are writing to \`${ - page.outputPath - }\`. Use distinct \`permalink\` values to resolve this conflict. + ] = `Output conflict: multiple input files are ${ + isServerlessTemplate + ? "using the same serverless path" + : `writing to \`${page.outputPath}\`` + }. Use distinct \`permalink\` values to resolve this conflict. 1. ${entry.inputPath} ${permalinks[page.url] .map(function (inputPath, index) { diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index e9c66d488..eabcc08f5 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -43,15 +43,8 @@ class TemplatePermalink { } // default if permalink is an Object but does not have a `build` prop - // note that `read` will opt-out this template from collections. See TemplateBehavior->isIncludedInCollections - if (!("behavior" in link) && !("build" in link)) { - link.behavior = "read"; - } - - if (link.behavior === "render") { - // same as permalink: false and permalink: build: false - this._writeToFileSystem = false; - } else if (link.behavior === "read") { + // note that this will opt-out this template from collections. See TemplateBehavior->isIncludedInCollections + if (!("build" in link)) { this._writeToFileSystem = false; this._isRendered = false; } @@ -80,6 +73,9 @@ class TemplatePermalink { ); } + // This method is used to generate the `page.url` variable. + // Note that in serverless mode this should still exist to generate the content map + // remove all index.html’s from links // index.html becomes / // test/index.html becomes test/ diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index f1f4ff6f5..9f10d5612 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -168,6 +168,22 @@ test("Permalink Object, just build", (t) => { build: true, }).toLink(); }); +}); + +test("Permalink Object, serverless URLs", (t) => { + t.is( + new TemplatePermalink({ + serverless: "permalinksubfolder/test.html", + }).toLink(), + false + ); + + t.is( + new TemplatePermalink({ + serverless: "permalinksubfolder/test.html", + }).toHref(), + "permalinksubfolder/test.html" + ); t.is( new TemplatePermalink({ From f8f65b089ed3023f09269ca285978cd1a71fa36d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 7 Jun 2021 13:05:32 -0500 Subject: [PATCH 443/746] =?UTF-8?q?Generalize=20permalink=20serverless=20k?= =?UTF-8?q?eys=20to=20any=20name=20passed=20to=20the=20Serverless=20Bundle?= =?UTF-8?q?r=20Plugin=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Plugins/ServerlessBundlerPlugin.js | 16 ++- src/Serverless.js | 16 +-- src/Template.js | 25 ++-- src/TemplateMap.js | 40 +++---- src/TemplatePermalink.js | 14 ++- test/TemplateMapTest.js | 112 ++++++++++++++++++ test/TemplatePermalinkTest.js | 16 ++- test/TemplateTest.js | 47 ++++++++ .../permalink-build-serverless-rendered.md | 9 ++ .../permalink-build-serverless.md | 7 ++ .../permalink-nobuild/permalink-nobuild.md | 4 +- 11 files changed, 254 insertions(+), 52 deletions(-) create mode 100644 test/stubs/permalink-build-serverless-rendered/permalink-build-serverless-rendered.md create mode 100644 test/stubs/permalink-build-serverless/permalink-build-serverless.md diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 89c4da422..12045679d 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -240,12 +240,22 @@ function EleventyPlugin(eleventyConfig, options = {}) { await Promise.all(promises); }); - eleventyConfig.on("eleventy.dependencyMap", (templateMap) => { + eleventyConfig.on("eleventy.serverlessUrlMap", (templateMap) => { let outputMap = {}; for (let entry of templateMap) { - if (entry.isExternal) { - outputMap[entry.url] = entry.inputPath; + for (let key in entry.serverless) { + if (key === options.name) { + if (outputMap[entry.serverless[key]]) { + throw new Error( + `Serverless URL conflict: multiple input files are using the same URL path (in \`permalink\`): ${ + outputMap[entry.serverless[key]] + } and ${entry.inputPath}` + ); + } + + outputMap[entry.serverless[key]] = entry.inputPath; + } } } diff --git a/src/Serverless.js b/src/Serverless.js index d84f87eac..32f151fd0 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -11,13 +11,16 @@ class Serverless { this.name = name; this.path = path; + // ServerlessBundlerPlugin hard-codes to this (even if you used a different file name) + this.configFilename = "eleventy.config.js"; + + // Maps input files to eligible serverless URLs + this.mapFilename = "eleventy-serverless-map.json"; + this.options = Object.assign( { inputDir: ".", functionsDir: "functions/", - mapFilename: "eleventy-serverless-map.json", - // ServerlessBundlerPlugin hard-codes to this (even if you used a different file name) - configFilename: "eleventy.config.js", // Query String Parameters matchUrlToPattern(path, urlToCompare) { let pattern = new UrlPattern(urlToCompare); @@ -53,10 +56,7 @@ class Serverless { } getContentMap() { - let fullPath = TemplatePath.absolutePath( - this.dir, - this.options.mapFilename - ); + let fullPath = TemplatePath.absolutePath(this.dir, this.mapFilename); debug( `Including content map (maps output URLs to input files) from ${fullPath}` ); @@ -112,7 +112,7 @@ class Serverless { } let inputDir = path.join(this.dir, this.options.inputDir); - let configPath = path.join(this.dir, this.options.configFilename); + let configPath = path.join(this.dir, this.configFilename); let { pathParams, inputPath } = this.matchUrlPattern(this.path); if (!pathParams || !inputPath) { diff --git a/src/Template.js b/src/Template.js index 47c9571b4..d24ab2364 100755 --- a/src/Template.js +++ b/src/Template.js @@ -65,6 +65,8 @@ class Template extends TemplateContent { this.behavior = new TemplateBehavior(this.config); this.behavior.setOutputFormat(this.outputFormat); + + this.serverlessUrls = null; } get logger() { @@ -140,14 +142,23 @@ class Template extends TemplateContent { ); } + getServerlessUrls() { + if (!this.serverlessUrls) { + throw new Error( + "Permalink has not yet processed. Calls to Template->getServerlessUrls not yet allowed." + ); + } + return this.serverlessUrls; + } + _getRawPermalinkInstance(permalinkValue) { - // unrendered! let perm = new TemplatePermalink( permalinkValue, this.extraOutputSubdirectory ); this.behavior.setFromPermalink(perm); + this.serverlessUrls = perm.getServerlessUrls(); return perm; } @@ -174,18 +185,14 @@ class Template extends TemplateContent { } else if (isPlainObject(permalink)) { let promises = []; let keys = []; - if (permalink.build) { - keys.push("build"); - promises.push(super.render(permalink.build, data, true)); - } - if (permalink.serverless) { - keys.push("serverless"); - promises.push(super.render(permalink.serverless, data, true)); + for (let key in permalink) { + keys.push(key); + promises.push(super.render(permalink[key], data, true)); } let results = await Promise.all(promises); - permalinkValue = Object.assign({}, permalink); + permalinkValue = {}; for (let j = 0, k = keys.length; j < k; j++) { let key = keys[j]; permalinkValue[key] = results[j]; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 8787b8605..0f0d80287 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -369,27 +369,26 @@ class TemplateMap { this.checkForDuplicatePermalinks(); await this.config.events.emit( - "eleventy.dependencyMap", - this.generateDependencyMapEventObject(orderedMap) + "eleventy.serverlessUrlMap", + this.generateServerlessUrlMap(orderedMap) ); } - generateDependencyMapEventObject(orderedMap) { + generateServerlessUrlMap(orderedMap) { let entries = []; for (let entry of orderedMap) { - let ret = { - inputPath: entry.inputPath, - isExternal: !!(entry.data.permalink && entry.data.permalink.serverless), - }; - - // TODO `needs: []` array of inputPath or glob? this template uses - for (let page of entry._pages) { - entries.push( - Object.assign({}, ret, { + let serverless = {}; + if (isPlainObject(page.data.permalink)) { + // These are rendered in the template language! + Object.assign(serverless, page.template.getServerlessUrls()); + + entries.push({ + inputPath: entry.inputPath, url: page.url, - }) - ); + serverless, + }); + } } } return entries; @@ -614,20 +613,15 @@ class TemplateMap { for (let entry of this.map) { for (let page of entry._pages) { if (page.url === false) { - // do nothing, note that url exists in serverless mode + // do nothing (also serverless) } else if (!permalinks[page.url]) { permalinks[page.url] = [entry.inputPath]; } else { - // in serverless mode, page.outputPath is `false` - let isServerlessTemplate = !page.outputPath; - warnings[ page.outputPath - ] = `Output conflict: multiple input files are ${ - isServerlessTemplate - ? "using the same serverless path" - : `writing to \`${page.outputPath}\`` - }. Use distinct \`permalink\` values to resolve this conflict. + ] = `Output conflict: multiple input files are writing to \`${ + page.outputPath + }\`. Use distinct \`permalink\` values to resolve this conflict. 1. ${entry.inputPath} ${permalinks[page.url] .map(function (inputPath, index) { diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index eabcc08f5..d4ec7a040 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -37,10 +37,11 @@ class TemplatePermalink { this.rawLink = rawLink; } + this.serverlessUrls = {}; + if (isLinkAnObject) { - if ("serverless" in link) { - this.externalLink = link.serverless; - } + Object.assign(this.serverlessUrls, link); + delete this.serverlessUrls.build; // default if permalink is an Object but does not have a `build` prop // note that this will opt-out this template from collections. See TemplateBehavior->isIncludedInCollections @@ -53,6 +54,10 @@ class TemplatePermalink { this.extraPaginationSubdir = extraSubdir || ""; } + getServerlessUrls() { + return this.serverlessUrls; + } + _cleanLink(link) { return link + (link.substr(-1) === "/" ? "index.html" : ""); } @@ -80,9 +85,6 @@ class TemplatePermalink { // index.html becomes / // test/index.html becomes test/ toHref() { - if (this.externalLink) { - return this.externalLink; - } if (!this.rawLink) { // empty or false return false; diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 5f40bbe82..38adda02a 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -1316,3 +1316,115 @@ test("permalink object without build (defaults to `read` mode)", async (t) => { } ); }); + +test("serverlessUrlMap Event (without `build`, only `serverless`)", async (t) => { + t.plan(1); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.on("eleventy.serverlessUrlMap", (templateMap) => { + t.deepEqual(templateMap, [ + { + inputPath: "./test/stubs/permalink-nobuild/permalink-nobuild.md", + url: false, + serverless: { + serverless: "/url/", + }, + }, + ]); + }); + + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/permalink-nobuild/permalink-nobuild.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmpl); + await tm.cache(); +}); + +test("serverlessUrlMap Event (with `build`)", async (t) => { + t.plan(1); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.on("eleventy.serverlessUrlMap", (templateMap) => { + t.deepEqual(templateMap, [ + { + inputPath: "./test/stubs/permalink-build/permalink-build.md", + url: "/url/", + serverless: {}, + }, + ]); + }); + + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/permalink-build/permalink-build.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmpl); + await tm.cache(); +}); + +test("serverlessUrlMap Event (with `build` and `serverless`)", async (t) => { + t.plan(1); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.on("eleventy.serverlessUrlMap", (templateMap) => { + t.deepEqual(templateMap, [ + { + inputPath: + "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", + url: "/url/", + serverless: { + serverless: "/some-other-url/", + }, + }, + ]); + }); + + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmpl); + await tm.cache(); +}); + +test("serverlessUrlMap Event (with templating on both `build` and `serverless`)", async (t) => { + t.plan(1); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.on("eleventy.serverlessUrlMap", (templateMap) => { + t.deepEqual(templateMap, [ + { + inputPath: + "./test/stubs/permalink-build-serverless-rendered/permalink-build-serverless-rendered.md", + url: "/url/", + serverless: { + serverless: "/some-other-url/", + }, + }, + ]); + }); + + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/permalink-build-serverless-rendered/permalink-build-serverless-rendered.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmpl); + await tm.cache(); +}); diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index 9f10d5612..146a188fe 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -182,7 +182,7 @@ test("Permalink Object, serverless URLs", (t) => { new TemplatePermalink({ serverless: "permalinksubfolder/test.html", }).toHref(), - "permalinksubfolder/test.html" + false ); t.is( @@ -192,10 +192,24 @@ test("Permalink Object, serverless URLs", (t) => { false ); + t.is( + new TemplatePermalink({ + request: "/url/", + }).toHref(), + false + ); + t.is( new TemplatePermalink({ rando: "/url/", }).toLink(), false ); + + t.is( + new TemplatePermalink({ + rando: "/url/", + }).toHref(), + false + ); }); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 484c6247a..891432f68 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2254,3 +2254,50 @@ test("permalink object without build", async (t) => { t.is(await tmpl.getOutputLink(), false); t.is(await tmpl.getOutputHref(), false); }); + +test("permalink object _getLink", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-nobuild/permalink-nobuild.md", + "./test/stubs/", + "./test/stubs/_site" + ); + + let link = await tmpl._getLink({ + permalink: { + serverless: "/serverless/", + }, + }); + t.is(await link.toLink(), false); + t.is(await link.toHref(), false); + t.deepEqual(link.getServerlessUrls(), { + serverless: "/serverless/", + }); + t.deepEqual(tmpl.getServerlessUrls(), { + serverless: "/serverless/", + }); + + let link2 = await tmpl._getLink({ + permalink: { + build: "/build/", + }, + }); + t.is(await link2.toLink(), "/build/index.html"); + t.is(await link2.toHref(), "/build/"); + t.deepEqual(link2.getServerlessUrls(), {}); + t.deepEqual(tmpl.getServerlessUrls(), {}); + + let link3 = await tmpl._getLink({ + permalink: { + build: "/build/", + serverless: "/serverless/", + }, + }); + t.is(await link3.toLink(), "/build/index.html"); + t.is(await link3.toHref(), "/build/"); + t.deepEqual(link3.getServerlessUrls(), { + serverless: "/serverless/", + }); + t.deepEqual(tmpl.getServerlessUrls(), { + serverless: "/serverless/", + }); +}); diff --git a/test/stubs/permalink-build-serverless-rendered/permalink-build-serverless-rendered.md b/test/stubs/permalink-build-serverless-rendered/permalink-build-serverless-rendered.md new file mode 100644 index 000000000..051ab7ff3 --- /dev/null +++ b/test/stubs/permalink-build-serverless-rendered/permalink-build-serverless-rendered.md @@ -0,0 +1,9 @@ +--- +slug1: "url" +slug2: "some-other-url" +permalink: + build: "/{{ slug1 }}/" + serverless: "/{{ slug2 }}/" +--- + +This should be the same as `permalink: /url/` diff --git a/test/stubs/permalink-build-serverless/permalink-build-serverless.md b/test/stubs/permalink-build-serverless/permalink-build-serverless.md new file mode 100644 index 000000000..49eb09c82 --- /dev/null +++ b/test/stubs/permalink-build-serverless/permalink-build-serverless.md @@ -0,0 +1,7 @@ +--- +permalink: + build: "/url/" + serverless: "/some-other-url/" +--- + +This should be the same as `permalink: /url/` diff --git a/test/stubs/permalink-nobuild/permalink-nobuild.md b/test/stubs/permalink-nobuild/permalink-nobuild.md index a1ee11397..390e4be65 100644 --- a/test/stubs/permalink-nobuild/permalink-nobuild.md +++ b/test/stubs/permalink-nobuild/permalink-nobuild.md @@ -1,6 +1,6 @@ --- permalink: - request: /url/ + serverless: /url/ --- -This shouldn’t write to the file system and in fact not be processed at all. +This shouldn’t write to the file system or be rendered by a template engine. From d3cd329d83ec31414dfecc23b30b22c876e9d238 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 7 Jun 2021 20:45:26 -0500 Subject: [PATCH 444/746] Reset the copy count during watch --- src/Plugins/ServerlessBundlerPlugin.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 12045679d..7c00681ec 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -52,6 +52,10 @@ class BundlerHelper { this.copyCount = 0; } + reset() { + this.copyCount = 0; + } + getOutputPath(filepath) { return TemplatePath.addLeadingDotSlash(path.join(this.dir, filepath)); } @@ -194,6 +198,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { middleware: [helper.browserSyncMiddleware()], }); + eleventyConfig.on("eleventy.before", async () => { + helper.reset(); + }); + eleventyConfig.on("eleventy.after", async () => { // extra copy targets // we put these in after a build so that we can grab files generated _by_ the build too From 6845142354127ddf93e8d02efe02ad47903445ac Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 8 Jun 2021 07:53:35 -0500 Subject: [PATCH 445/746] Adds `excludeDependencies` option. --- src/Plugins/ServerlessBundlerPlugin.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 7c00681ec..65546db12 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -107,7 +107,9 @@ class BundlerHelper { let modules = getNodeModulesList([configPath]); this.writeBundlerDependenciesFile( "eleventy-app-config-modules.js", - modules + modules.filter( + (name) => this.options.excludeDependencies.indexOf(name) === -1 + ) ); } @@ -115,7 +117,9 @@ class BundlerHelper { let modules = getNodeModulesList(globalDataFileList); this.writeBundlerDependenciesFile( "eleventy-app-globalData-modules.js", - modules + modules.filter( + (name) => this.options.excludeDependencies.indexOf(name) === -1 + ) ); } @@ -155,6 +159,11 @@ function EleventyPlugin(eleventyConfig, options = {}) { name: "", functionsDir: "./functions/", copy: [], + + // Dependencies explicitly declared from configuration and global data can be excluded and hidden from bundler. + // Excluded from: `eleventy-app-config-modules.js` and `eleventy-app-globalData-modules.js` + excludeDependencies: [], + // Add automated redirects to netlify.toml (appends or creates, avoids duplicate entries) redirects: function (outputMap) { let redirects = []; @@ -173,9 +182,9 @@ function EleventyPlugin(eleventyConfig, options = {}) { if (fs.existsSync(configFilename)) { cfg = TOML.parse(fs.readFileSync(configFilename)); } + let cfgWithRedirects = addRedirectsWithoutDuplicates(cfg, redirects); - let newCfg = addRedirectsWithoutDuplicates(cfg, redirects); - fs.writeFileSync(configFilename, TOML.stringify(newCfg)); + fs.writeFileSync(configFilename, TOML.stringify(cfgWithRedirects)); debug( `Eleventy Serverless (${options.name}), writing (×${redirects.length}): ${configFilename}` ); @@ -225,7 +234,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { console.log( `Eleventy Serverless: ${ helper.copyCount - } files bundled with ${helper.getOutputPath("")}.` + } files bundled to ${helper.getOutputPath("")}.` ); }); From 7748576dcbcb30cbf817188c980d33bde7f75d89 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 8 Jun 2021 11:01:39 -0500 Subject: [PATCH 446/746] Original serverless templates are now included in collections (but only one entry for now) --- src/Template.js | 11 +++++------ src/TemplateBehavior.js | 4 ---- src/TemplateMap.js | 25 +++++-------------------- src/TemplatePermalink.js | 1 - 4 files changed, 10 insertions(+), 31 deletions(-) diff --git a/src/Template.js b/src/Template.js index d24ab2364..e4df0d091 100755 --- a/src/Template.js +++ b/src/Template.js @@ -587,21 +587,20 @@ class Template extends TemplateContent { } async getTemplates(data) { - // no pagination on permalink.serverless for local builds + // no pagination with permalink.serverless let hasPagination = Pagination.hasPagination(data); - let isServerlessTemplateRenderingViaBuild = !this.behavior.isRenderable(); - let isServerlessTemplateRenderingViaServerless = + let isPaginatedServerlessTemplateRenderingViaServerless = this.behavior.isRenderForced() && hasPagination && "serverless" in data.pagination; if ( !hasPagination || - isServerlessTemplateRenderingViaBuild || - isServerlessTemplateRenderingViaServerless + !this.behavior.isRenderable() || + isPaginatedServerlessTemplateRenderingViaServerless ) { // inject pagination page data for just this one entry for serverless render - if (isServerlessTemplateRenderingViaServerless && hasPagination) { + if (isPaginatedServerlessTemplateRenderingViaServerless) { let pagination = new Pagination(data, this.config); let paginationItems = pagination.getTruncatedServerlessData(data); let override = pagination.getOverrideData(paginationItems); diff --git a/src/TemplateBehavior.js b/src/TemplateBehavior.js index afa20c9ca..b1e8e3f15 100644 --- a/src/TemplateBehavior.js +++ b/src/TemplateBehavior.js @@ -28,10 +28,6 @@ class TemplateBehavior { return this.write; } - isIncludedInCollections() { - return this.isRenderable(); - } - setRenderViaDataCascade(data) { // render is false *only* if `build` key does not exist in permalink objects (both in data and eleventyComputed) // (note that permalink: false means it won’t write but will still render) diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 0f0d80287..6f871c6bb 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -121,10 +121,7 @@ class TemplateMap { graph.addNode(entry.inputPath); } - if ( - !entry.data.eleventyExcludeFromCollections && - entry.template.behavior.isIncludedInCollections() - ) { + if (!entry.data.eleventyExcludeFromCollections) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -175,10 +172,7 @@ class TemplateMap { } graph.addDependency(entry.inputPath, tagPrefix + paginationTagTarget); - if ( - !entry.data.eleventyExcludeFromCollections && - entry.template.behavior.isIncludedInCollections() - ) { + if (!entry.data.eleventyExcludeFromCollections) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); @@ -219,10 +213,7 @@ class TemplateMap { graph.addNode(entry.inputPath); } - if ( - !entry.data.eleventyExcludeFromCollections && - entry.template.behavior.isIncludedInCollections() - ) { + if (!entry.data.eleventyExcludeFromCollections) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); } @@ -251,10 +242,7 @@ class TemplateMap { graph.addNode(entry.inputPath); } - if ( - !entry.data.eleventyExcludeFromCollections && - entry.template.behavior.isIncludedInCollections() - ) { + if (!entry.data.eleventyExcludeFromCollections) { // collections.all graph.addDependency(tagPrefix + "all", entry.inputPath); } @@ -311,10 +299,7 @@ class TemplateMap { (map.data.pagination && map.data.pagination.addAllPagesToCollections) ) { - if ( - !map.data.eleventyExcludeFromCollections && - map.template.behavior.isIncludedInCollections() - ) { + if (!map.data.eleventyExcludeFromCollections) { // TODO do we need .template in collection entries? this.collection.add(page); } diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index d4ec7a040..d70563a6d 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -44,7 +44,6 @@ class TemplatePermalink { delete this.serverlessUrls.build; // default if permalink is an Object but does not have a `build` prop - // note that this will opt-out this template from collections. See TemplateBehavior->isIncludedInCollections if (!("build" in link)) { this._writeToFileSystem = false; this._isRendered = false; From 217b4e3030404406637fd5cb550231ec4d107e0c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 8 Jun 2021 13:02:01 -0500 Subject: [PATCH 447/746] More straightforward pagination template code for serverless. --- src/Plugins/Pagination.js | 73 +++++++++++++++----------- src/Plugins/ServerlessBundlerPlugin.js | 4 ++ src/Template.js | 37 ++++--------- src/TemplateBehavior.js | 4 ++ 4 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index a324de540..8bec4c8e5 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -67,9 +67,36 @@ class Pagination { this.size = data.pagination.size; this.alias = data.pagination.alias; + // TODO do we need the full data set for serverless? + this.fullDataSet = this._get(this.data, this._getDataKey()); - this.target = this._resolveItems(); - this.chunkedItems = this.pagedItems; + // truncate pagination data to one entry for serverless render + if ( + data.pagination.serverless && + this._has(data, data.pagination.serverless) + ) { + // Warn: this doesn’t run filter/before/pagination transformations + // Warn: `pagination.pages`, pageNumber, links, hrefs, etc + let serverlessPaginationKey = this._get(data, data.pagination.serverless); + this.chunkedItems = [ + [this._get(this.fullDataSet, serverlessPaginationKey)], + ]; + } else { + // this returns an array + this.target = this._resolveItems(); + + // Serverless Shortcut when key is not found in data set (probably running local build and expected a :path param in data) + // Only collections are relevant for templates that don’t have a permalink.build, they don’t have a templateContent and aren’t written to disk + if ( + data.pagination.serverless && + !data.pagination.addAllPagesToCollections + ) { + // use the first page only + this.chunkedItems = [this.pagedItems[0]]; + } else { + this.chunkedItems = this.pagedItems; + } + } } setTemplate(tmpl) { @@ -100,6 +127,12 @@ class Pagination { return false; } + _has(target, key) { + let notFoundValue = "__NOT_FOUND_ERROR__"; + let data = lodashGet(target, key, notFoundValue); + return data !== notFoundValue; + } + _get(target, key) { let notFoundValue = "__NOT_FOUND_ERROR__"; let data = lodashGet(target, key, notFoundValue); @@ -112,17 +145,13 @@ class Pagination { } _resolveItems() { - let fullDataSet = this._get(this.data, this._getDataKey()); - - // TODO maybe don’t operate on the full data set for a serverless render - let keys; - if (Array.isArray(fullDataSet)) { - keys = fullDataSet; + if (Array.isArray(this.fullDataSet)) { + keys = this.fullDataSet; } else if (this.resolveDataToObjectValues()) { - keys = Object.values(fullDataSet); + keys = Object.values(this.fullDataSet); } else { - keys = Object.keys(fullDataSet); + keys = Object.keys(this.fullDataSet); } // keys must be an array @@ -269,11 +298,7 @@ class Pagination { return []; } - if (this.pagesCache) { - return this.pagesCache; - } - - let pagesCache = []; + let pages = []; let items = this.chunkedItems; let tmpl = this.template; let templates = []; @@ -318,24 +343,10 @@ class Pagination { let cloned = templates[pageNumber]; cloned.setPaginationData(overrides[pageNumber]); - pagesCache.push(cloned); - } - - this.pagesCache = pagesCache; - - return pagesCache; - } - - getTruncatedServerlessData(data) { - if (!("serverless" in data.pagination)) { - throw new Error( - "Missing `serverless` key in `pagination` object to point to pagination data." - ); + pages.push(cloned); } - let resolvedKey = this._get(data, data.pagination.serverless); - let fullDataSet = this._get(data, this._getDataKey()); - return [this._get(fullDataSet, resolvedKey)]; + return pages; } } diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 65546db12..ad617ce13 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -263,6 +263,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { for (let entry of templateMap) { for (let key in entry.serverless) { if (key === options.name) { + if (outputMap[entry.serverless[key]] === entry.inputPath) { + continue; + } + if (outputMap[entry.serverless[key]]) { throw new Error( `Serverless URL conflict: multiple input files are using the same URL path (in \`permalink\`): ${ diff --git a/src/Template.js b/src/Template.js index e4df0d091..6e8dd5da1 100755 --- a/src/Template.js +++ b/src/Template.js @@ -589,28 +589,8 @@ class Template extends TemplateContent { async getTemplates(data) { // no pagination with permalink.serverless let hasPagination = Pagination.hasPagination(data); - let isPaginatedServerlessTemplateRenderingViaServerless = - this.behavior.isRenderForced() && - hasPagination && - "serverless" in data.pagination; - - if ( - !hasPagination || - !this.behavior.isRenderable() || - isPaginatedServerlessTemplateRenderingViaServerless - ) { - // inject pagination page data for just this one entry for serverless render - if (isPaginatedServerlessTemplateRenderingViaServerless) { - let pagination = new Pagination(data, this.config); - let paginationItems = pagination.getTruncatedServerlessData(data); - let override = pagination.getOverrideData(paginationItems); - // TODO errors or warnings when trying to access `pagination.pages`, pageNumber, links, hrefs, etc - this.setPaginationData(override); - - // TODO: better? - Object.assign(data, override); - } + if (!hasPagination) { await this.addComputedData(data); return [ @@ -648,6 +628,7 @@ class Template extends TemplateContent { // but individual pagination entries won’t be part of a collection this.paging = new Pagination(data, this.config); this.paging.setTemplate(this); + let pageTemplates = await this.paging.getPageTemplates(); return await Promise.all( @@ -676,16 +657,16 @@ class Template extends TemplateContent { this._templateContent = content; }, get templateContent() { - if (this.template.behavior.isRenderable()) { - if (this._templateContent === undefined) { + if (this._templateContent === undefined) { + if (this.template.behavior.isRenderable()) { throw new TemplateContentPrematureUseError( `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` ); + } else { + throw new TemplateContentUnrenderedTemplateError( + `Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath} page ${this.pageNumber}` + ); } - } else { - throw new TemplateContentUnrenderedTemplateError( - `Tried to use templateContent on unrendered template. You need a valid permalink (or permalink object) to use templateContent on ${this.inputPath} page ${this.pageNumber}` - ); } return this._templateContent; }, @@ -798,7 +779,7 @@ class Template extends TemplateContent { if (!mapEntry.template.behavior.isRenderable()) { debug( - "Template not written %o from %o (via permalink.behavior).", + "Template not written %o from %o (via serverless permalink).", page.outputPath, mapEntry.template.inputPath ); diff --git a/src/TemplateBehavior.js b/src/TemplateBehavior.js index b1e8e3f15..22626ad32 100644 --- a/src/TemplateBehavior.js +++ b/src/TemplateBehavior.js @@ -12,6 +12,7 @@ class TemplateBehavior { this.config = config; } + // permalink *has* a build key or output is json/ndjson isRenderable() { return this.render || this.isRenderForced(); } @@ -28,6 +29,7 @@ class TemplateBehavior { return this.write; } + // Duplicate logic with TemplatePermalink constructor setRenderViaDataCascade(data) { // render is false *only* if `build` key does not exist in permalink objects (both in data and eleventyComputed) // (note that permalink: false means it won’t write but will still render) @@ -48,7 +50,9 @@ class TemplateBehavior { } setFromPermalink(templatePermalink) { + // this.render is duplicated between TemplatePermalink and `setRenderViaDataCascade` above this.render = templatePermalink._isRendered; + this.write = templatePermalink._writeToFileSystem; } } From 51917a4b832c2a0b685660a14e7a08fcc5e27042 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 07:12:37 -0500 Subject: [PATCH 448/746] Support array of eliglble URL paths in a single template: permalink: serverless: - "/creators/:name/" - "/authors/:name/" --- src/Plugins/ServerlessBundlerPlugin.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index ad617ce13..0060e9117 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -262,20 +262,26 @@ function EleventyPlugin(eleventyConfig, options = {}) { for (let entry of templateMap) { for (let key in entry.serverless) { - if (key === options.name) { - if (outputMap[entry.serverless[key]] === entry.inputPath) { + if (key !== options.name) { + continue; + } + let urls = entry.serverless[key]; + if (!Array.isArray(urls)) { + urls = [entry.serverless[key]]; + } + for (let eligibleUrl of urls) { + // ignore duplicates that have the same input file, via Pagination. + if (outputMap[eligibleUrl] === entry.inputPath) { continue; } - if (outputMap[entry.serverless[key]]) { + if (outputMap[eligibleUrl]) { throw new Error( - `Serverless URL conflict: multiple input files are using the same URL path (in \`permalink\`): ${ - outputMap[entry.serverless[key]] - } and ${entry.inputPath}` + `Serverless URL conflict: multiple input files are using the same URL path (in \`permalink\`): ${outputMap[eligibleUrl]} and ${entry.inputPath}` ); } - outputMap[entry.serverless[key]] = entry.inputPath; + outputMap[eligibleUrl] = entry.inputPath; } } } From cda7376d45058b8f965820bcf8f5812198c0e14a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 07:31:54 -0500 Subject: [PATCH 449/746] v1.0.0-canary.24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10bb1ea50..8a19df785 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.23", + "version": "1.0.0-canary.24", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 86be192faeafe5fe96681c431a449a78c9b9887c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 07:44:53 -0500 Subject: [PATCH 450/746] Casing on file name --- src/Plugins/ServerlessBundlerPlugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 0060e9117..e30a5cf2c 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -116,7 +116,7 @@ class BundlerHelper { writeDependencyGlobalDataFile(globalDataFileList) { let modules = getNodeModulesList(globalDataFileList); this.writeBundlerDependenciesFile( - "eleventy-app-globalData-modules.js", + "eleventy-app-globaldata-modules.js", modules.filter( (name) => this.options.excludeDependencies.indexOf(name) === -1 ) @@ -161,7 +161,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { copy: [], // Dependencies explicitly declared from configuration and global data can be excluded and hidden from bundler. - // Excluded from: `eleventy-app-config-modules.js` and `eleventy-app-globalData-modules.js` + // Excluded from: `eleventy-app-config-modules.js` and `eleventy-app-globaldata-modules.js` excludeDependencies: [], // Add automated redirects to netlify.toml (appends or creates, avoids duplicate entries) From 547b482743973c5e952a796d39d550172a621595 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 07:45:19 -0500 Subject: [PATCH 451/746] v1.0.0-canary.25 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8a19df785..f63ea7b6a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.24", + "version": "1.0.0-canary.25", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 6c9e32ff2765c9dfe3e2df056d5e2ac85eea5b2d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 07:54:52 -0500 Subject: [PATCH 452/746] Removes bad chdir --- src/Serverless.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Serverless.js b/src/Serverless.js index 32f151fd0..4eb01d147 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -106,11 +106,6 @@ class Serverless { } async render() { - // TODO is this necessary? - if (this.dir.startsWith("/var/task/")) { - process.chdir(this.dir); - } - let inputDir = path.join(this.dir, this.options.inputDir); let configPath = path.join(this.dir, this.configFilename); let { pathParams, inputPath } = this.matchUrlPattern(this.path); From 78fbcc7bcddd1186bf62706a7f1c369984cc450e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 07:55:32 -0500 Subject: [PATCH 453/746] v1.0.0-canary.26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f63ea7b6a..ec8cc9bc4 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.25", + "version": "1.0.0-canary.26", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From b7f895c929fd7a9817f79fcecfc344526c36ff29 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 08:02:55 -0500 Subject: [PATCH 454/746] Work with chdir --- src/Serverless.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Serverless.js b/src/Serverless.js index 4eb01d147..e7bc7fcfd 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -42,6 +42,7 @@ class Serverless { let paths = [ path.join(TemplatePath.getWorkingDir(), dir), // netlify dev path.join("/var/task/src/", dir), // AWS Lambda absolute path + path.join(TemplatePath.getWorkingDir()), // after the chdir below ]; for (let path of paths) { @@ -106,6 +107,10 @@ class Serverless { } async render() { + if (this.dir.startsWith("/var/task/")) { + process.chdir(this.dir); + } + let inputDir = path.join(this.dir, this.options.inputDir); let configPath = path.join(this.dir, this.configFilename); let { pathParams, inputPath } = this.matchUrlPattern(this.path); From 34e3837bef09a9ecf025abcdf37c5b4660e7847c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 08:03:19 -0500 Subject: [PATCH 455/746] v1.0.0-canary.27 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec8cc9bc4..71af3f96c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.26", + "version": "1.0.0-canary.27", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 2e4ff5e8e0684f25a8a257ab724082fa7df0a2e6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 09:04:20 -0500 Subject: [PATCH 456/746] =?UTF-8?q?Write=20these=20files=20even=20if=20the?= =?UTF-8?q?y=E2=80=99re=20empty=20or=20require=20will=20fail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Plugins/ServerlessBundlerPlugin.js | 27 +++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index e30a5cf2c..efe24ab7d 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -84,13 +84,11 @@ class BundlerHelper { writeBundlerDependenciesFile(filename, deps = []) { let modules = deps.map((name) => `require("${name}");`); - if (modules.length) { - let fullPath = this.getOutputPath(filename); - fs.writeFileSync(fullPath, modules.join("\n")); - debug( - `Writing a file to make it very obvious to the serverless bundler which extra \`require\`s are needed from the config file (×${modules.length}): ${fullPath}` - ); - } + let fullPath = this.getOutputPath(filename); + fs.writeFileSync(fullPath, modules.join("\n")); + debug( + `Writing a file to make it very obvious to the serverless bundler which extra \`require\`s are needed from the config file (×${modules.length}): ${fullPath}` + ); } writeDependencyEntryFile() { @@ -288,14 +286,15 @@ function EleventyPlugin(eleventyConfig, options = {}) { // Maps input files to output paths let mapEntryCount = Object.keys(outputMap).length; - if (mapEntryCount > 0) { - let filename = helper.getOutputPath("eleventy-serverless-map.json"); - fs.writeFileSync(filename, JSON.stringify(outputMap, null, 2)); - debug( - `Eleventy Serverless (${options.name}), writing (×${mapEntryCount}): ${filename}` - ); - this.copyCount++; + // This is expected to exist even if empty + let filename = helper.getOutputPath("eleventy-serverless-map.json"); + fs.writeFileSync(filename, JSON.stringify(outputMap, null, 2)); + debug( + `Eleventy Serverless (${options.name}), writing (×${mapEntryCount}): ${filename}` + ); + this.copyCount++; + if (mapEntryCount > 0) { // Write redirects into netlify.toml options.redirects(outputMap); From b92bede8eabcbc8c30fd254f2df0131cc4149d02 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 09:04:49 -0500 Subject: [PATCH 457/746] v1.0.0-canary.28 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 71af3f96c..a68ab62e9 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.27", + "version": "1.0.0-canary.28", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 2f9317b95f05f4eeb422b8a1af3f77e58014c661 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 09:14:45 -0500 Subject: [PATCH 458/746] Always write bundler helper file --- src/Plugins/ServerlessBundlerPlugin.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index efe24ab7d..262491820 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -86,19 +86,17 @@ class BundlerHelper { let modules = deps.map((name) => `require("${name}");`); let fullPath = this.getOutputPath(filename); fs.writeFileSync(fullPath, modules.join("\n")); + this.copyCount++; debug( `Writing a file to make it very obvious to the serverless bundler which extra \`require\`s are needed from the config file (×${modules.length}): ${fullPath}` ); } writeDependencyEntryFile() { - let modulesFilename = this.getOutputPath("eleventy-bundler-modules.js"); - if (!fs.existsSync(modulesFilename)) { - this.writeBundlerDependenciesFile("eleventy-bundler-modules.js", [ - "./eleventy-app-config-modules.js", - "./eleventy-app-globaldata-modules.js", - ]); - } + this.writeBundlerDependenciesFile("eleventy-bundler-modules.js", [ + "./eleventy-app-config-modules.js", + "./eleventy-app-globaldata-modules.js", + ]); } writeDependencyConfigFile(configPath) { @@ -199,7 +197,6 @@ function EleventyPlugin(eleventyConfig, options = {}) { if (process.env.ELEVENTY_SOURCE === "cli") { let helper = new BundlerHelper(options.name, options); - helper.writeDependencyEntryFile(); eleventyConfig.setBrowserSyncConfig({ middleware: [helper.browserSyncMiddleware()], @@ -207,6 +204,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { eleventyConfig.on("eleventy.before", async () => { helper.reset(); + helper.writeDependencyEntryFile(); }); eleventyConfig.on("eleventy.after", async () => { From 9824d452e7734d96e92b02ce9c10f7a434f62985 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 9 Jun 2021 09:15:06 -0500 Subject: [PATCH 459/746] v1.0.0-canary.29 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a68ab62e9..529203761 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.28", + "version": "1.0.0-canary.29", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 9264b181227282df1d2a2b566b4de7543d3732b0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 10 Jun 2021 08:28:15 -0500 Subject: [PATCH 460/746] Fix for URLs with query parameters on localhost --- src/Plugins/ServerlessBundlerPlugin.js | 15 ++++++++++----- src/Serverless.js | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 262491820..ca24097f0 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -4,6 +4,7 @@ const TOML = require("@iarna/toml"); const copy = require("recursive-copy"); const dependencyTree = require("@11ty/dependency-tree"); const TemplatePath = require("../TemplatePath"); +const deleteRequireCache = require("../Util/DeleteRequireCache"); const debug = require("debug")("Eleventy:Serverless"); function getNodeModulesList(files) { @@ -123,16 +124,20 @@ class BundlerHelper { let serverlessFilepath = TemplatePath.addLeadingDotSlash( path.join(TemplatePath.getWorkingDir(), this.dir, "index") ); + deleteRequireCache(TemplatePath.absolutePath(serverlessFilepath)); return async (req, res, next) => { let serverlessFunction = require(serverlessFilepath); let url = new URL(req.url, "http://localhost/"); // any domain will do here, we just want the searchParams + let queryParams = Object.fromEntries(url.searchParams); let start = new Date(); let result = await serverlessFunction.handler({ httpMethod: "GET", - path: req.url, - queryStringParameters: Object.fromEntries(url.searchParams), + path: url.pathname, + // @netlify/functions builder overwrites these to {} intentionally + // See https://github.com/netlify/functions/issues/38 + queryStringParameters: queryParams, }); if (result.statusCode === 404) { @@ -228,9 +233,9 @@ function EleventyPlugin(eleventyConfig, options = {}) { } console.log( - `Eleventy Serverless: ${ - helper.copyCount - } files bundled to ${helper.getOutputPath("")}.` + `Eleventy Serverless: ${helper.copyCount} file${ + helper.copyCount !== 1 ? "s" : "" + } bundled to ${helper.getOutputPath("")}.` ); }); diff --git a/src/Serverless.js b/src/Serverless.js index e7bc7fcfd..9bab08017 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -21,11 +21,11 @@ class Serverless { { inputDir: ".", functionsDir: "functions/", - // Query String Parameters matchUrlToPattern(path, urlToCompare) { let pattern = new UrlPattern(urlToCompare); return pattern.match(path); }, + // Query String Parameters query: {}, // Inject shared collections precompiledCollections: {}, From 3482dac153505b624187015f86ba92912b24f6d1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 10 Jun 2021 08:47:15 -0500 Subject: [PATCH 461/746] Cache fs.stat calls for dates --- src/Template.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Template.js b/src/Template.js index 6e8dd5da1..6302c268e 100755 --- a/src/Template.js +++ b/src/Template.js @@ -832,6 +832,24 @@ class Template extends TemplateContent { return this.skippedCount; } + async getInputFileStat() { + if (this._stats) { + return this._stats; + } + + this._stats = new Promise((resolve, reject) => { + fs.stat(this.inputPath, (err, stats) => { + if (err) { + reject(err); + } else { + resolve(stats); + } + }); + }); + + return this._stats; + } + async getMappedDate(data) { // TODO(slightlyoff): lots of I/O! @@ -847,11 +865,12 @@ class Template extends TemplateContent { debug("getMappedDate: YAML parsed it: %o", data.date); return data.date; } else { - let stat = fs.statSync(this.inputPath); // string if (data.date.toLowerCase() === "last modified") { + let stat = await this.getInputFileStat(); return new Date(stat.ctimeMs); } else if (data.date.toLowerCase() === "created") { + let stat = await this.getInputFileStat(); return new Date(stat.birthtimeMs); } else { // try to parse with Luxon @@ -884,7 +903,7 @@ class Template extends TemplateContent { return dateObj; } - let stat = fs.statSync(this.inputPath); + let stat = await this.getInputFileStat(); let createdDate = new Date(stat.birthtimeMs); debug( "getMappedDate: using file created time for %o of %o (from %o)", From dac4bb54f0f7a043f56b37d89d2905b371795835 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 10 Jun 2021 10:03:08 -0500 Subject: [PATCH 462/746] Prevent netlify.toml redirects from adding up, handle modifications and deletes. --- src/Plugins/ServerlessBundlerPlugin.js | 44 ++++++++++++++++++-------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index ca24097f0..8cc99c83a 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -26,22 +26,33 @@ function getNodeModulesList(files) { return Array.from(pkgs).sort(); } -function addRedirectsWithoutDuplicates(config, redirects) { - if (!config.redirects) { - config.redirects = []; - } +function addRedirectsWithoutDuplicates(name, config, newRedirects) { + // keep non-generated redirects or those generated by a different function + let redirects = (config.redirects || []).filter((entry) => { + return ( + !entry._generated_by_eleventy_serverless || + entry._generated_by_eleventy_serverless !== name + ); + }); - for (let r of redirects) { + for (let r of newRedirects) { let found = false; - for (let entry of config.redirects) { + for (let entry of redirects) { if (r.from === entry.from && r.to === entry.to) { found = true; } } if (!found) { - config.redirects.push(r); + redirects.push(r); } } + + if (redirects.length) { + config.redirects = redirects; + } else { + delete config.redirects; + } + return config; } @@ -167,13 +178,14 @@ function EleventyPlugin(eleventyConfig, options = {}) { // Add automated redirects to netlify.toml (appends or creates, avoids duplicate entries) redirects: function (outputMap) { - let redirects = []; + let newRedirects = []; for (let url in outputMap) { - redirects.push({ + newRedirects.push({ from: url, to: `/.netlify/functions/${options.name}`, status: 200, force: true, + _generated_by_eleventy_serverless: options.name, }); } @@ -183,11 +195,15 @@ function EleventyPlugin(eleventyConfig, options = {}) { if (fs.existsSync(configFilename)) { cfg = TOML.parse(fs.readFileSync(configFilename)); } - let cfgWithRedirects = addRedirectsWithoutDuplicates(cfg, redirects); + let cfgWithRedirects = addRedirectsWithoutDuplicates( + options.name, + cfg, + newRedirects + ); fs.writeFileSync(configFilename, TOML.stringify(cfgWithRedirects)); debug( - `Eleventy Serverless (${options.name}), writing (×${redirects.length}): ${configFilename}` + `Eleventy Serverless (${options.name}), writing (×${newRedirects.length}): ${configFilename}` ); }, }, @@ -297,10 +313,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { ); this.copyCount++; - if (mapEntryCount > 0) { - // Write redirects into netlify.toml - options.redirects(outputMap); + // Write redirects into netlify.toml (even if no redirects exist for this function to handle deletes) + options.redirects(outputMap); + if (mapEntryCount > 0) { // Copy templates to bundle folder for (let url in outputMap) { helper.recursiveCopy(outputMap[url]); From 7c3e630024e9c7a65dc801a3fea369b49250a169 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 10 Jun 2021 10:08:54 -0500 Subject: [PATCH 463/746] v1.0.0-canary.30 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 529203761..947c1f1b2 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.29", + "version": "1.0.0-canary.30", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From d16a556b32282f50bba25bfdadf7106d17474ebb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 10 Jun 2021 20:21:30 -0500 Subject: [PATCH 464/746] Add global copyOptions to serverless bundler plugin options and an `options` prop in the copy object `{ from: "", to: "", options: {} }` --- src/Plugins/ServerlessBundlerPlugin.js | 27 ++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 8cc99c83a..b9da9cfe0 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -82,14 +82,22 @@ class BundlerHelper { this.copyCount++; } - recursiveCopy(src, dest) { + recursiveCopy(src, dest, options = {}) { let finalDest = this.getOutputPath(dest || src); - return copy(src, finalDest, { - overwrite: true, - dot: true, - junk: false, - results: false, - }).on(copy.events.COPY_FILE_COMPLETE, () => { + return copy( + src, + finalDest, + Object.assign( + { + overwrite: true, + dot: true, + junk: false, + results: false, + }, + this.options.copyOptions, + options + ) + ).on(copy.events.COPY_FILE_COMPLETE, () => { this.copyCount++; }); } @@ -172,6 +180,9 @@ function EleventyPlugin(eleventyConfig, options = {}) { functionsDir: "./functions/", copy: [], + // https://www.npmjs.com/package/recursive-copy#usage + copyOptions: {}, + // Dependencies explicitly declared from configuration and global data can be excluded and hidden from bundler. // Excluded from: `eleventy-app-config-modules.js` and `eleventy-app-globaldata-modules.js` excludeDependencies: [], @@ -237,7 +248,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { if (typeof cp === "string") { promises.push(helper.recursiveCopy(cp)); } else if (cp.from && cp.to) { - promises.push(helper.recursiveCopy(cp.from, cp.to)); + promises.push(helper.recursiveCopy(cp.from, cp.to, cp.options)); } else { debug( "Ignored extra copy %o (needs to be a string or a {from: '', to: ''})", From 40c49d5c78169166dabe613c6fc63a752f7493ce Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 10 Jun 2021 20:21:57 -0500 Subject: [PATCH 465/746] v1.0.0-canary.31 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 947c1f1b2..c2ca43849 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.30", + "version": "1.0.0-canary.31", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 6f9732368a67ed4a9be1a396c9137dcb0fa76a52 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 11 Jun 2021 13:22:40 -0500 Subject: [PATCH 466/746] Pass `pathname` in with global data. --- src/Serverless.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Serverless.js b/src/Serverless.js index 9bab08017..b0a77443b 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -145,6 +145,7 @@ class Serverless { // Add the params to Global Data eleventyConfig.addGlobalData("eleventy.serverless", { + pathname: this.path, query: this.options.query, path: pathParams, }); From fcb6f5036e626943523bb3b6da21618029029f38 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 11 Jun 2021 13:23:02 -0500 Subject: [PATCH 467/746] v1.0.0-canary.32 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c2ca43849..523e04ffb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.31", + "version": "1.0.0-canary.32", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From d19257350887c9f670f8652039555d9460f69f79 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 11 Jun 2021 22:02:16 -0500 Subject: [PATCH 468/746] Fix for missing serverless URLs in serverlessUrlMap event on pagination templates with empty data (and no pages) --- src/Template.js | 11 ++++ src/TemplateMap.js | 65 +++++++++++++------ test/TemplateMapTest.js | 32 +++++++-- .../permalink-serverless-empty-pagination.md | 8 +++ 4 files changed, 92 insertions(+), 24 deletions(-) create mode 100644 test/stubs/permalink-serverless-empty-pagination/permalink-serverless-empty-pagination.md diff --git a/src/Template.js b/src/Template.js index 6302c268e..60f804d62 100755 --- a/src/Template.js +++ b/src/Template.js @@ -151,6 +151,17 @@ class Template extends TemplateContent { return this.serverlessUrls; } + initServerlessUrlsForEmptyPaginationTemplates(permalinkValue) { + if (isPlainObject(permalinkValue)) { + let buildlessPermalink = Object.assign({}, permalinkValue); + delete buildlessPermalink.build; + + if (Object.keys(buildlessPermalink).length) { + return this._getRawPermalinkInstance(buildlessPermalink); + } + } + } + _getRawPermalinkInstance(permalinkValue) { let perm = new TemplatePermalink( permalinkValue, diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 6f871c6bb..13f3e45e9 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -287,24 +287,35 @@ class TemplateMap { let map = this.getMapEntryForInputPath(depEntry); 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; - } + if (map._pages.length === 0) { + // Setup serverlessUrls even if data set is 0 pages. This fixes 404 issue + // with full build not including Sanity drafts but serverless render does + // include Sanity drafts. + + // We want these empty-data pagination templates to show up in the serverlessUrlMap. + map.template.initServerlessUrlsForEmptyPaginationTemplates( + map.data.permalink + ); + } else { + 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 (!map.data.eleventyExcludeFromCollections) { - // TODO do we need .template in collection entries? - this.collection.add(page); + if ( + counter === 0 || + (map.data.pagination && + map.data.pagination.addAllPagesToCollections) + ) { + if (!map.data.eleventyExcludeFromCollections) { + // TODO do we need .template in collection entries? + this.collection.add(page); + } } + counter++; } - counter++; } } } @@ -362,18 +373,32 @@ class TemplateMap { generateServerlessUrlMap(orderedMap) { let entries = []; for (let entry of orderedMap) { - for (let page of entry._pages) { + // Pagination templates with 0 pages should still populate + // serverlessUrls into this event. We want these to still show up + // in the inputPath to URL map and in the redirects. + if (entry._pages.length === 0) { let serverless = {}; - if (isPlainObject(page.data.permalink)) { + if (isPlainObject(entry.data.permalink)) { // These are rendered in the template language! - Object.assign(serverless, page.template.getServerlessUrls()); - + Object.assign(serverless, entry.template.getServerlessUrls()); entries.push({ inputPath: entry.inputPath, - url: page.url, serverless, }); } + } else { + for (let page of entry._pages) { + let serverless = {}; + if (isPlainObject(page.data.permalink)) { + // These are rendered in the template language! + Object.assign(serverless, page.template.getServerlessUrls()); + + entries.push({ + inputPath: entry.inputPath, + serverless, + }); + } + } } } return entries; diff --git a/test/TemplateMapTest.js b/test/TemplateMapTest.js index 38adda02a..069834267 100644 --- a/test/TemplateMapTest.js +++ b/test/TemplateMapTest.js @@ -1325,7 +1325,6 @@ test("serverlessUrlMap Event (without `build`, only `serverless`)", async (t) => t.deepEqual(templateMap, [ { inputPath: "./test/stubs/permalink-nobuild/permalink-nobuild.md", - url: false, serverless: { serverless: "/url/", }, @@ -1353,7 +1352,6 @@ test("serverlessUrlMap Event (with `build`)", async (t) => { t.deepEqual(templateMap, [ { inputPath: "./test/stubs/permalink-build/permalink-build.md", - url: "/url/", serverless: {}, }, ]); @@ -1380,7 +1378,6 @@ test("serverlessUrlMap Event (with `build` and `serverless`)", async (t) => { { inputPath: "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", - url: "/url/", serverless: { serverless: "/some-other-url/", }, @@ -1409,7 +1406,6 @@ test("serverlessUrlMap Event (with templating on both `build` and `serverless`)" { inputPath: "./test/stubs/permalink-build-serverless-rendered/permalink-build-serverless-rendered.md", - url: "/url/", serverless: { serverless: "/some-other-url/", }, @@ -1428,3 +1424,31 @@ test("serverlessUrlMap Event (with templating on both `build` and `serverless`)" await tm.add(tmpl); await tm.cache(); }); + +test("serverlessUrlMap Event (empty pagination template with `serverless` should still show up)", async (t) => { + t.plan(1); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.on("eleventy.serverlessUrlMap", (templateMap) => { + t.deepEqual(templateMap, [ + { + inputPath: + "./test/stubs/permalink-serverless-empty-pagination/permalink-serverless-empty-pagination.md", + serverless: { + serverless: "/url/", + }, + }, + ]); + }); + + let tm = new TemplateMap(eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/permalink-serverless-empty-pagination/permalink-serverless-empty-pagination.md", + "./test/stubs/", + "./test/stubs/_site", + eleventyConfig + ); + + await tm.add(tmpl); + await tm.cache(); +}); diff --git a/test/stubs/permalink-serverless-empty-pagination/permalink-serverless-empty-pagination.md b/test/stubs/permalink-serverless-empty-pagination/permalink-serverless-empty-pagination.md new file mode 100644 index 000000000..20bfaf844 --- /dev/null +++ b/test/stubs/permalink-serverless-empty-pagination/permalink-serverless-empty-pagination.md @@ -0,0 +1,8 @@ +--- +sampledata: [] +pagination: + data: sampledata + size: 1 +permalink: + serverless: /url/ +--- From fde78920bed4d5b128f7e854b245a8916d9057b2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 13 Jun 2021 15:00:56 -0500 Subject: [PATCH 469/746] Fixes #364 --- src/EleventyFiles.js | 29 ++++++++------- test/EleventyFilesTest.js | 35 ++++++++----------- .../ignorelocalrootgitignore/.eleventyignore | 1 + .../.gitignore | 0 4 files changed, 32 insertions(+), 33 deletions(-) create mode 100644 test/stubs/ignorelocalrootgitignore/.eleventyignore rename test/stubs/{ignore4 => ignorelocalrootgitignore}/.gitignore (100%) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 860047bec..dfd0c4e0c 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -30,6 +30,7 @@ class EleventyFiles { this.passthroughAll = false; this.formats = formats; + this.eleventyIgnoreContent = false; // init has not yet been called() this.alreadyInit = false; @@ -290,22 +291,27 @@ class EleventyFiles { return ignores; } + setEleventyIgnoreContent(content) { + this.eleventyIgnoreContent = content; + } + getIgnores() { let files = []; let rootDirectory = this.localPathRoot || TemplatePath.getWorkingDir(); - let absoluteInputDir = TemplatePath.absolutePath(this.inputDir); - if (this.config.useGitIgnore) { - let gitIgnores = [TemplatePath.join(rootDirectory, ".gitignore")]; - if (rootDirectory !== absoluteInputDir) { - gitIgnores.push(TemplatePath.join(this.inputDir, ".gitignore")); - } + if (this.config.useGitIgnore) { files = files.concat( - EleventyFiles.getFileIgnores(gitIgnores, "node_modules/**") + EleventyFiles.getFileIgnores( + [TemplatePath.join(rootDirectory, ".gitignore")], + "node_modules/**" + ) ); } - if (this.config.eleventyignoreOverride !== false) { + if (this.eleventyIgnoreContent !== false) { + files = files.concat(this.eleventyIgnoreContent); + } else { + let absoluteInputDir = TemplatePath.absolutePath(this.inputDir); let eleventyIgnores = [ TemplatePath.join(rootDirectory, ".eleventyignore"), ]; @@ -315,13 +321,10 @@ class EleventyFiles { ); } - files = files.concat( - this.config.eleventyignoreOverride || - EleventyFiles.getFileIgnores(eleventyIgnores) - ); + files = files.concat(EleventyFiles.getFileIgnores(eleventyIgnores)); } - // ignore output dir unless that would occlude all input + // ignore output dir unless that would exclude all input if (!TemplatePath.startsWithSubPath(this.inputDir, this.outputDir)) { files = files.concat(TemplateGlob.map(this.outputDir + "/**")); } diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index f7b0400e1..e607d2d54 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -275,7 +275,6 @@ test("Get ignores (no .eleventyignore no .gitignore)", (t) => { t.deepEqual(evf.getIgnores(), [ "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignore1/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore1/_site/**", ]); @@ -290,11 +289,11 @@ test("Get ignores (no .eleventyignore)", (t) => { eleventyConfig ); evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); t.deepEqual(evf.getIgnores(), [ - "./test/stubs/ignore2/thisshouldnotexist12345", - "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", + "./test/stubs/ignorelocalrootgitignore/test.md", "./test/stubs/ignore2/_site/**", ]); }); @@ -337,7 +336,6 @@ test("Get ignores (no .gitignore)", (t) => { t.deepEqual(evf.getIgnores(), [ "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignore3/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore3/ignoredFolder/**", "./test/stubs/ignore3/ignoredFolder/ignored.md", @@ -345,7 +343,7 @@ test("Get ignores (no .gitignore)", (t) => { ]); }); -test("Get ignores (both .eleventyignore and .gitignore)", (t) => { +test("Get ignores (project .eleventyignore and root .gitignore)", (t) => { let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore4", @@ -354,18 +352,18 @@ test("Get ignores (both .eleventyignore and .gitignore)", (t) => { eleventyConfig ); evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); t.deepEqual(evf.getIgnores(), [ - "./test/stubs/ignore4/thisshouldnotexist12345", - "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", + "./test/stubs/ignorelocalrootgitignore/test.md", "./test/stubs/ignore4/ignoredFolder/**", "./test/stubs/ignore4/ignoredFolder/ignored.md", "./test/stubs/ignore4/_site/**", ]); }); -test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(false))", (t) => { +test("Get ignores (project .eleventyignore and root .gitignore, using setUseGitIgnore(false))", (t) => { let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( "test/stubs/ignore4", @@ -381,10 +379,10 @@ test("Get ignores (both .eleventyignore and .gitignore, using setUseGitIgnore(fa includes: "_includes", }, }); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); t.deepEqual(evf.getIgnores(), [ - "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignorelocalrootgitignore/test.md", "./test/stubs/ignore4/ignoredFolder/**", "./test/stubs/ignore4/ignoredFolder/ignored.md", "./test/stubs/ignore4/_site/**", @@ -406,7 +404,6 @@ test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { t.deepEqual(evf.getIgnores(), [ "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignore5/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore5/_site/**", ]); @@ -426,7 +423,6 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is t.deepEqual(evf.getIgnores(), [ "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignore6/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore6/ignoredFolder/**", "./test/stubs/ignore6/ignoredFolder/ignored.md", @@ -449,7 +445,6 @@ test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)" t.deepEqual(evf.getIgnores(), [ "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignore7/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore7/_site/**", ]); @@ -469,7 +464,6 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore ha t.deepEqual(evf.getIgnores(), [ "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignore8/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore8/ignoredFolder/**", "./test/stubs/ignore8/ignoredFolder/ignored.md", @@ -535,9 +529,9 @@ test("Input to 'src' and empty includes dir (issue #403)", (t) => { ["md", "liquid", "html"], eleventyConfig ); + evf.setEleventyIgnoreContent("!./src/_includes/**"); evf._setConfig({ useGitIgnore: false, - eleventyignoreOverride: "!./src/_includes/**", dir: { input: ".", output: "_site", @@ -565,10 +559,11 @@ test("Bad expected output, this indicates a bug upstream in a dependency. Input ["liquid"], eleventyConfig ); + evf.setEleventyIgnoreContent( + "!" + TemplatePath.absolutePath("test/stubs-403/_includes") + "/**" + ); evf._setConfig({ useGitIgnore: false, - eleventyignoreOverride: - "!" + TemplatePath.absolutePath("test/stubs-403/_includes") + "/**", dir: { input: "test/stubs-403", output: "_site", @@ -593,9 +588,9 @@ test("Workaround for Bad expected output, this indicates a bug upstream in a dep ["liquid"], eleventyConfig ); + evf.setEleventyIgnoreContent("!./test/stubs-403/_includes/**"); evf._setConfig({ useGitIgnore: false, - eleventyignoreOverride: "!./test/stubs-403/_includes/**", dir: { input: "test/stubs-403", output: "_site", diff --git a/test/stubs/ignorelocalrootgitignore/.eleventyignore b/test/stubs/ignorelocalrootgitignore/.eleventyignore new file mode 100644 index 000000000..7545a50d7 --- /dev/null +++ b/test/stubs/ignorelocalrootgitignore/.eleventyignore @@ -0,0 +1 @@ +test.md \ No newline at end of file diff --git a/test/stubs/ignore4/.gitignore b/test/stubs/ignorelocalrootgitignore/.gitignore similarity index 100% rename from test/stubs/ignore4/.gitignore rename to test/stubs/ignorelocalrootgitignore/.gitignore From 7dcbdd13b1167af94d6512b7fc1f0041e1ba969a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 13 Jun 2021 15:11:11 -0500 Subject: [PATCH 470/746] Separate gitignore and eleventyignore tests into new file --- ...leventyFilesGitIgnoreEleventyIgnoreTest.js | 297 ++++++++++++++++++ test/EleventyFilesTest.js | 293 ----------------- 2 files changed, 297 insertions(+), 293 deletions(-) create mode 100644 test/EleventyFilesGitIgnoreEleventyIgnoreTest.js diff --git a/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js new file mode 100644 index 000000000..e6d085ae8 --- /dev/null +++ b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js @@ -0,0 +1,297 @@ +const test = require("ava"); +const EleventyFiles = require("../src/EleventyFiles"); +const TemplatePath = require("../src/TemplatePath"); +const TemplateConfig = require("../src/TemplateConfig"); + +/* .eleventyignore and .gitignore combos */ + +test("Get ignores (no .eleventyignore no .gitignore)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore1", + "test/stubs/ignore1/_site", + [], + eleventyConfig + ); + evf.init(); + + evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + + t.deepEqual(evf.getIgnores(), [ + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore1/_site/**", + ]); +}); + +test("Get ignores (no .eleventyignore)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore2", + "test/stubs/ignore2/_site", + [], + eleventyConfig + ); + evf.init(); + evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); + + t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", + "./test/stubs/ignorelocalrootgitignore/test.md", + "./test/stubs/ignore2/_site/**", + ]); +}); + +test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore2", + "test/stubs/ignore2/_site", + [], + eleventyConfig + ); + evf.init(); + + evf._setConfig({ + useGitIgnore: false, + dir: { + includes: "_includes", + }, + }); + evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + + t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore2/_site/**", + ]); +}); + +test("Get ignores (no .gitignore)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore3", + "test/stubs/ignore3/_site", + [], + eleventyConfig + ); + evf.init(); + evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + + t.deepEqual(evf.getIgnores(), [ + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore3/ignoredFolder/**", + "./test/stubs/ignore3/ignoredFolder/ignored.md", + "./test/stubs/ignore3/_site/**", + ]); +}); + +test("Get ignores (project .eleventyignore and root .gitignore)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore4", + "test/stubs/ignore4/_site", + [], + eleventyConfig + ); + evf.init(); + evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); + + t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", + "./test/stubs/ignorelocalrootgitignore/test.md", + "./test/stubs/ignore4/ignoredFolder/**", + "./test/stubs/ignore4/ignoredFolder/ignored.md", + "./test/stubs/ignore4/_site/**", + ]); +}); + +test("Get ignores (project .eleventyignore and root .gitignore, using setUseGitIgnore(false))", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore4", + "test/stubs/ignore4/_site", + [], + eleventyConfig + ); + evf.init(); + + evf._setConfig({ + useGitIgnore: false, + dir: { + includes: "_includes", + }, + }); + evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); + + t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalrootgitignore/test.md", + "./test/stubs/ignore4/ignoredFolder/**", + "./test/stubs/ignore4/ignoredFolder/ignored.md", + "./test/stubs/ignore4/_site/**", + ]); +}); + +test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore5", + "test/stubs/ignore5/_site", + [], + eleventyConfig + ); + evf.init(); + + evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + + t.deepEqual(evf.getIgnores(), [ + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore5/_site/**", + ]); +}); + +test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is empty)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore6", + "test/stubs/ignore6/_site", + [], + eleventyConfig + ); + evf.init(); + evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + + t.deepEqual(evf.getIgnores(), [ + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore6/ignoredFolder/**", + "./test/stubs/ignore6/ignoredFolder/ignored.md", + "./test/stubs/ignore6/_site/**", + ]); +}); + +test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore7", + "test/stubs/ignore7/_site", + [], + eleventyConfig + ); + evf.init(); + + evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + + t.deepEqual(evf.getIgnores(), [ + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore7/_site/**", + ]); +}); + +test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore has spaces inside)", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/ignore8", + "test/stubs/ignore8/_site", + [], + eleventyConfig + ); + evf.init(); + evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); + + t.deepEqual(evf.getIgnores(), [ + "./node_modules/**", + "./test/stubs/ignorelocalroot/node_modules/**", + "./test/stubs/ignorelocalroot/test.md", + "./test/stubs/ignore8/ignoredFolder/**", + "./test/stubs/ignore8/ignoredFolder/ignored.md", + "./test/stubs/ignore8/_site/**", + ]); +}); + +test("Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs-403", + "test/stubs-403/_site", + ["liquid"], + eleventyConfig + ); + evf.setEleventyIgnoreContent( + "!" + TemplatePath.absolutePath("test/stubs-403/_includes") + "/**" + ); + evf._setConfig({ + useGitIgnore: false, + dir: { + input: "test/stubs-403", + output: "_site", + includes: "", + data: false, + }, + }); + evf.init(); + + t.deepEqual(await evf.getFiles(), [ + "./test/stubs-403/template.liquid", + // This is bad, because it uses an absolutePath above. it should be excluded + "./test/stubs-403/_includes/include.liquid", + ]); +}); + +test("Workaround for Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs-403", + "test/stubs-403/_site", + ["liquid"], + eleventyConfig + ); + evf.setEleventyIgnoreContent("!./test/stubs-403/_includes/**"); + evf._setConfig({ + useGitIgnore: false, + dir: { + input: "test/stubs-403", + output: "_site", + includes: "", + data: false, + }, + }); + evf.init(); + + t.deepEqual(await evf.getFiles(), ["./test/stubs-403/template.liquid"]); +}); + +test("Issue #403: all .eleventyignores should be relative paths not absolute paths", async (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs-403", + "test/stubs-403/_site", + ["liquid"], + eleventyConfig + ); + evf._setConfig({ + useGitIgnore: false, + dir: { + input: "test/stubs-403", + output: "_site", + includes: "", + data: false, + }, + }); + evf.init(); + + let globs = await evf.getFileGlobs(); + t.is( + globs.filter((glob) => { + return glob.indexOf(TemplatePath.absolutePath()) > -1; + }).length, + 0 + ); +}); diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index e607d2d54..c35ca09d6 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -259,219 +259,6 @@ test(".eleventyignore files", async (t) => { ); }); -/* .eleventyignore and .gitignore combos */ -test("Get ignores (no .eleventyignore no .gitignore)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore1", - "test/stubs/ignore1/_site", - [], - eleventyConfig - ); - evf.init(); - - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore1/_site/**", - ]); -}); - -test("Get ignores (no .eleventyignore)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore2", - "test/stubs/ignore2/_site", - [], - eleventyConfig - ); - evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); - - t.deepEqual(evf.getIgnores(), [ - "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", - "./test/stubs/ignorelocalrootgitignore/test.md", - "./test/stubs/ignore2/_site/**", - ]); -}); - -test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore2", - "test/stubs/ignore2/_site", - [], - eleventyConfig - ); - evf.init(); - - evf._setConfig({ - useGitIgnore: false, - dir: { - includes: "_includes", - }, - }); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore2/_site/**", - ]); -}); - -test("Get ignores (no .gitignore)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore3", - "test/stubs/ignore3/_site", - [], - eleventyConfig - ); - evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore3/ignoredFolder/**", - "./test/stubs/ignore3/ignoredFolder/ignored.md", - "./test/stubs/ignore3/_site/**", - ]); -}); - -test("Get ignores (project .eleventyignore and root .gitignore)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore4", - "test/stubs/ignore4/_site", - [], - eleventyConfig - ); - evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); - - t.deepEqual(evf.getIgnores(), [ - "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", - "./test/stubs/ignorelocalrootgitignore/test.md", - "./test/stubs/ignore4/ignoredFolder/**", - "./test/stubs/ignore4/ignoredFolder/ignored.md", - "./test/stubs/ignore4/_site/**", - ]); -}); - -test("Get ignores (project .eleventyignore and root .gitignore, using setUseGitIgnore(false))", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore4", - "test/stubs/ignore4/_site", - [], - eleventyConfig - ); - evf.init(); - - evf._setConfig({ - useGitIgnore: false, - dir: { - includes: "_includes", - }, - }); - evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); - - t.deepEqual(evf.getIgnores(), [ - "./test/stubs/ignorelocalrootgitignore/test.md", - "./test/stubs/ignore4/ignoredFolder/**", - "./test/stubs/ignore4/ignoredFolder/ignored.md", - "./test/stubs/ignore4/_site/**", - ]); -}); - -test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore5", - "test/stubs/ignore5/_site", - [], - eleventyConfig - ); - evf.init(); - - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore5/_site/**", - ]); -}); - -test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is empty)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore6", - "test/stubs/ignore6/_site", - [], - eleventyConfig - ); - evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore6/ignoredFolder/**", - "./test/stubs/ignore6/ignoredFolder/ignored.md", - "./test/stubs/ignore6/_site/**", - ]); -}); - -test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore7", - "test/stubs/ignore7/_site", - [], - eleventyConfig - ); - evf.init(); - - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore7/_site/**", - ]); -}); - -test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore has spaces inside)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore8", - "test/stubs/ignore8/_site", - [], - eleventyConfig - ); - evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore8/ignoredFolder/**", - "./test/stubs/ignore8/ignoredFolder/ignored.md", - "./test/stubs/ignore8/_site/**", - ]); -}); -/* End .eleventyignore and .gitignore combos */ - test("getTemplateData caching", (t) => { let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( @@ -551,86 +338,6 @@ test("Input to 'src' and empty includes dir (issue #403)", (t) => { ]); }); -test("Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs-403", - "test/stubs-403/_site", - ["liquid"], - eleventyConfig - ); - evf.setEleventyIgnoreContent( - "!" + TemplatePath.absolutePath("test/stubs-403/_includes") + "/**" - ); - evf._setConfig({ - useGitIgnore: false, - dir: { - input: "test/stubs-403", - output: "_site", - includes: "", - data: false, - }, - }); - evf.init(); - - t.deepEqual(await evf.getFiles(), [ - "./test/stubs-403/template.liquid", - // This is bad, because it uses an absolutePath above. it should be excluded - "./test/stubs-403/_includes/include.liquid", - ]); -}); - -test("Workaround for Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs-403", - "test/stubs-403/_site", - ["liquid"], - eleventyConfig - ); - evf.setEleventyIgnoreContent("!./test/stubs-403/_includes/**"); - evf._setConfig({ - useGitIgnore: false, - dir: { - input: "test/stubs-403", - output: "_site", - includes: "", - data: false, - }, - }); - evf.init(); - - t.deepEqual(await evf.getFiles(), ["./test/stubs-403/template.liquid"]); -}); - -test("Issue #403: all .eleventyignores should be relative paths not absolute paths", async (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs-403", - "test/stubs-403/_site", - ["liquid"], - eleventyConfig - ); - evf._setConfig({ - useGitIgnore: false, - dir: { - input: "test/stubs-403", - output: "_site", - includes: "", - data: false, - }, - }); - evf.init(); - - let globs = await evf.getFileGlobs(); - t.is( - globs.filter((glob) => { - return glob.indexOf(TemplatePath.absolutePath()) > -1; - }).length, - 0 - ); -}); - test("Glob Watcher Files", async (t) => { let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( From 8c3377c01cd70b71b719924227b8f869f1b34400 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 13 Jun 2021 15:14:47 -0500 Subject: [PATCH 471/746] Tests for #1129 and #186 --- ...leventyFilesGitIgnoreEleventyIgnoreTest.js | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js index e6d085ae8..59c1f386c 100644 --- a/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js +++ b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js @@ -295,3 +295,45 @@ test("Issue #403: all .eleventyignores should be relative paths not absolute pat 0 ); }); + +test("Same input and output directories, issues #186 and #1129", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles("test/stubs/", "test/stubs/", [], eleventyConfig); + evf._setConfig({ + useGitIgnore: false, + dir: { + input: "test/stubs", + output: "", + includes: "", + }, + }); + evf.init(); + + t.deepEqual( + evf.getIgnores().filter((entry) => entry.indexOf("_site") > -1), + [] + ); +}); + +test("Single input file is in the output directory, issues #186", (t) => { + let eleventyConfig = new TemplateConfig(); + let evf = new EleventyFiles( + "test/stubs/test.njk", + "test/stubs/", + ["njk"], + eleventyConfig + ); + evf._setConfig({ + useGitIgnore: false, + dir: { + input: "test/stubs", + output: "", + includes: "", + }, + }); + evf.init(); + t.deepEqual( + evf.getIgnores().filter((entry) => entry.indexOf("_site") > -1), + [] + ); +}); From 6e20f63b20562d97c3a2b40ae911d1820f5bd584 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 07:22:21 -0500 Subject: [PATCH 472/746] Always ignore node_modules by default. Previous behavior only ignored node_modules by default if you did not have a .gitignore or your .gitignore was empty. Opt-out using `eleventyConfig.ignores.delete("node_modules/**");` Also adds a configuration option to allow modification of ignores: `eleventyConfig.ignores.add("my_ignore_file.md");` Fixes #383 Fixes #1405 Fixes #894 --- src/EleventyFiles.js | 46 +++++++---------- src/UserConfig.js | 5 ++ ...leventyFilesGitIgnoreEleventyIgnoreTest.js | 51 +++---------------- test/EleventyFilesTest.js | 11 ++-- test/stubs/ignore7/.gitignore | 1 - test/stubs/ignore7/ignoredFolder/ignored.md | 1 - test/stubs/ignore8/.eleventyignore | 3 -- test/stubs/ignore8/.gitignore | 1 - test/stubs/ignore8/ignoredFolder/ignored.md | 1 - 9 files changed, 31 insertions(+), 89 deletions(-) delete mode 100644 test/stubs/ignore7/.gitignore delete mode 100644 test/stubs/ignore7/ignoredFolder/ignored.md delete mode 100644 test/stubs/ignore8/.eleventyignore delete mode 100644 test/stubs/ignore8/.gitignore delete mode 100644 test/stubs/ignore8/ignoredFolder/ignored.md diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index dfd0c4e0c..8a94f0df6 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -112,6 +112,10 @@ class EleventyFiles { /* For testing */ _setConfig(config) { + if (!config.ignores) { + config.ignores = new Set(); + config.ignores.add("node_modules/**"); + } this.config = config; this.initConfig(); } @@ -200,47 +204,28 @@ class EleventyFiles { return Array.from(uniqueIgnores); } - static getFileIgnores(ignoreFiles, defaultIfFileDoesNotExist) { + static getFileIgnores(ignoreFiles) { if (!Array.isArray(ignoreFiles)) { ignoreFiles = [ignoreFiles]; } let ignores = []; - let fileFound = false; - let dirs = []; for (let ignorePath of ignoreFiles) { ignorePath = TemplatePath.normalize(ignorePath); let dir = TemplatePath.getDirFromFilePath(ignorePath); - dirs.push(dir); if (fs.existsSync(ignorePath) && fs.statSync(ignorePath).size > 0) { - fileFound = true; let ignoreContent = fs.readFileSync(ignorePath, "utf-8"); - // make sure that empty .gitignore with spaces takes default ignore. - if (ignoreContent.trim().length === 0) { - fileFound = false; - } else { - ignores = ignores.concat( - EleventyFiles.normalizeIgnoreContent(dir, ignoreContent) - ); - } - } - } - - if (!fileFound && defaultIfFileDoesNotExist) { - ignores.push(TemplateGlob.normalizePath(defaultIfFileDoesNotExist)); - for (let dir of dirs) { - ignores.push( - TemplateGlob.normalizePath(dir, defaultIfFileDoesNotExist) + ignores = ignores.concat( + EleventyFiles.normalizeIgnoreContent(dir, ignoreContent) ); } } - ignores.forEach(function (path) { - debug(`${ignoreFiles} ignoring: ${path}`); - }); + ignores.forEach((path) => debug(`${ignoreFiles} ignoring: ${path}`)); + return ignores; } @@ -296,15 +281,18 @@ class EleventyFiles { } getIgnores() { - let files = []; let rootDirectory = this.localPathRoot || TemplatePath.getWorkingDir(); + let files = []; + + for (let ignore of this.config.ignores) { + files = files.concat(TemplateGlob.normalizePath(rootDirectory, ignore)); + } if (this.config.useGitIgnore) { files = files.concat( - EleventyFiles.getFileIgnores( - [TemplatePath.join(rootDirectory, ".gitignore")], - "node_modules/**" - ) + EleventyFiles.getFileIgnores([ + TemplatePath.join(rootDirectory, ".gitignore"), + ]) ); } diff --git a/src/UserConfig.js b/src/UserConfig.js index 1cea64648..fa88fc160 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -53,7 +53,11 @@ class UserConfig { this.activeNamespace = ""; this.DateTime = DateTime; this.dynamicPermalinks = true; + this.useGitIgnore = true; + this.ignores = new Set(); + this.ignores.add("node_modules/**"); + this.dataDeepMerge = true; this.extensionMap = new Set(); this.watchJavaScriptDependencies = true; @@ -708,6 +712,7 @@ class UserConfig { libraryOverrides: this.libraryOverrides, dynamicPermalinks: this.dynamicPermalinks, useGitIgnore: this.useGitIgnore, + ignores: this.ignores, dataDeepMerge: this.dataDeepMerge, watchJavaScriptDependencies: this.watchJavaScriptDependencies, additionalWatchTargets: this.additionalWatchTargets, diff --git a/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js index 59c1f386c..9660493b7 100644 --- a/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js +++ b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js @@ -18,7 +18,6 @@ test("Get ignores (no .eleventyignore no .gitignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore1/_site/**", @@ -37,6 +36,7 @@ test("Get ignores (no .eleventyignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalrootgitignore/node_modules/**", "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", "./test/stubs/ignorelocalrootgitignore/test.md", "./test/stubs/ignore2/_site/**", @@ -62,6 +62,7 @@ test("Get ignores (no .eleventyignore, using setUseGitIgnore(false))", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalroot/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore2/_site/**", ]); @@ -79,7 +80,6 @@ test("Get ignores (no .gitignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore3/ignoredFolder/**", @@ -100,6 +100,7 @@ test("Get ignores (project .eleventyignore and root .gitignore)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalrootgitignore/node_modules/**", "./test/stubs/ignorelocalrootgitignore/thisshouldnotexist12345", "./test/stubs/ignorelocalrootgitignore/test.md", "./test/stubs/ignore4/ignoredFolder/**", @@ -127,6 +128,7 @@ test("Get ignores (project .eleventyignore and root .gitignore, using setUseGitI evf._setLocalPathRoot("./test/stubs/ignorelocalrootgitignore"); t.deepEqual(evf.getIgnores(), [ + "./test/stubs/ignorelocalrootgitignore/node_modules/**", "./test/stubs/ignorelocalrootgitignore/test.md", "./test/stubs/ignore4/ignoredFolder/**", "./test/stubs/ignore4/ignoredFolder/ignored.md", @@ -147,7 +149,6 @@ test("Get ignores (no .eleventyignore .gitignore exists but empty)", (t) => { evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore5/_site/**", @@ -166,7 +167,6 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", "./test/stubs/ignorelocalroot/node_modules/**", "./test/stubs/ignorelocalroot/test.md", "./test/stubs/ignore6/ignoredFolder/**", @@ -175,47 +175,6 @@ test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore is ]); }); -test("Get ignores (no .eleventyignore .gitignore exists but has spaces inside)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore7", - "test/stubs/ignore7/_site", - [], - eleventyConfig - ); - evf.init(); - - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore7/_site/**", - ]); -}); - -test("Get ignores (both .eleventyignore and .gitignore exists, but .gitignore has spaces inside)", (t) => { - let eleventyConfig = new TemplateConfig(); - let evf = new EleventyFiles( - "test/stubs/ignore8", - "test/stubs/ignore8/_site", - [], - eleventyConfig - ); - evf.init(); - evf._setLocalPathRoot("./test/stubs/ignorelocalroot"); - - t.deepEqual(evf.getIgnores(), [ - "./node_modules/**", - "./test/stubs/ignorelocalroot/node_modules/**", - "./test/stubs/ignorelocalroot/test.md", - "./test/stubs/ignore8/ignoredFolder/**", - "./test/stubs/ignore8/ignoredFolder/ignored.md", - "./test/stubs/ignore8/_site/**", - ]); -}); - test("Bad expected output, this indicates a bug upstream in a dependency. Input to 'src' and empty includes dir (issue #403, full paths in eleventyignore)", async (t) => { let eleventyConfig = new TemplateConfig(); let evf = new EleventyFiles( @@ -224,9 +183,11 @@ test("Bad expected output, this indicates a bug upstream in a dependency. Input ["liquid"], eleventyConfig ); + evf.setEleventyIgnoreContent( "!" + TemplatePath.absolutePath("test/stubs-403/_includes") + "/**" ); + evf._setConfig({ useGitIgnore: false, dir: { diff --git a/test/EleventyFilesTest.js b/test/EleventyFilesTest.js index c35ca09d6..46c9a7083 100644 --- a/test/EleventyFilesTest.js +++ b/test/EleventyFilesTest.js @@ -1,7 +1,6 @@ const test = require("ava"); const fastglob = require("fast-glob"); const EleventyFiles = require("../src/EleventyFiles"); -const TemplatePath = require("../src/TemplatePath"); const TemplateConfig = require("../src/TemplateConfig"); const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); @@ -224,13 +223,9 @@ test("Parse multiple .eleventyignores", (t) => { ); }); -test("defaults if passed file name does not exist", (t) => { - let ignores = EleventyFiles.getFileIgnores( - ".thisfiledoesnotexist", - "node_modules/**" - ); - t.truthy(ignores.length); - t.is(ignores[0], "./node_modules/**"); +test("Passed file name does not exist", (t) => { + let ignores = EleventyFiles.getFileIgnores(".thisfiledoesnotexist"); + t.deepEqual(ignores, []); }); test(".eleventyignore files", async (t) => { diff --git a/test/stubs/ignore7/.gitignore b/test/stubs/ignore7/.gitignore deleted file mode 100644 index 8b1378917..000000000 --- a/test/stubs/ignore7/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test/stubs/ignore7/ignoredFolder/ignored.md b/test/stubs/ignore7/ignoredFolder/ignored.md deleted file mode 100644 index 16ab01333..000000000 --- a/test/stubs/ignore7/ignoredFolder/ignored.md +++ /dev/null @@ -1 +0,0 @@ -# This should be ignored diff --git a/test/stubs/ignore8/.eleventyignore b/test/stubs/ignore8/.eleventyignore deleted file mode 100644 index de22e21c5..000000000 --- a/test/stubs/ignore8/.eleventyignore +++ /dev/null @@ -1,3 +0,0 @@ -ignoredFolder -./ignoredFolder/ignored.md -# This is a comment diff --git a/test/stubs/ignore8/.gitignore b/test/stubs/ignore8/.gitignore deleted file mode 100644 index 8b1378917..000000000 --- a/test/stubs/ignore8/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test/stubs/ignore8/ignoredFolder/ignored.md b/test/stubs/ignore8/ignoredFolder/ignored.md deleted file mode 100644 index 16ab01333..000000000 --- a/test/stubs/ignore8/ignoredFolder/ignored.md +++ /dev/null @@ -1 +0,0 @@ -# This should be ignored From 0407ef72e28c1010bca1883b35e2c59fec6cc45c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 09:48:37 -0500 Subject: [PATCH 473/746] Removes experimental requirement for https://github.com/11ty/eleventy/issues/117 --- src/UserConfig.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index fa88fc160..a84adf272 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -652,10 +652,6 @@ class UserConfig { } addExtension(fileExtension, options = {}) { - if (!process.env.ELEVENTY_EXPERIMENTAL) { - return; - } - this.extensionMap.add( Object.assign( { From cdd6764a468605fa0f324ece87607ed8eae42efe Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 10:26:48 -0500 Subject: [PATCH 474/746] Revert "Removes experimental requirement for https://github.com/11ty/eleventy/issues/117" This reverts commit 0407ef72e28c1010bca1883b35e2c59fec6cc45c. --- src/UserConfig.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/UserConfig.js b/src/UserConfig.js index a84adf272..fa88fc160 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -652,6 +652,10 @@ class UserConfig { } addExtension(fileExtension, options = {}) { + if (!process.env.ELEVENTY_EXPERIMENTAL) { + return; + } + this.extensionMap.add( Object.assign( { From b72d4f9d85c5a73d831f1c0dccd6644ba74527b6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 10:38:17 -0500 Subject: [PATCH 475/746] =?UTF-8?q?Redirects=20should=20be=20inserted=20at?= =?UTF-8?q?=20the=20beginning=20instead=20of=20the=20end=20so=20that=20exi?= =?UTF-8?q?sting=20redirects=20(like=20for=20404)=20don=E2=80=99t=20take?= =?UTF-8?q?=20precedence.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Plugins/ServerlessBundlerPlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index b9da9cfe0..ab312a8e1 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -43,7 +43,7 @@ function addRedirectsWithoutDuplicates(name, config, newRedirects) { } } if (!found) { - redirects.push(r); + redirects.unshift(r); } } From aa6ca648b8a30f5cff6e695ec53d369e7b056515 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 10:38:44 -0500 Subject: [PATCH 476/746] v1.0.0-canary.33 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 523e04ffb..212ee12c4 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.32", + "version": "1.0.0-canary.33", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 9deb86c734bc943b00f7989b68b9383760f21285 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 16:13:12 -0500 Subject: [PATCH 477/746] Fixes https://github.com/11ty/eleventy/issues/1833 --- src/Plugins/ServerlessBundlerPlugin.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index ab312a8e1..5e8e3c5e7 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -35,6 +35,16 @@ function addRedirectsWithoutDuplicates(name, config, newRedirects) { ); }); + // Sort for stable order + newRedirects.sort((a, b) => { + if (a.from < b.from) { + return -1; + } else if (a.from > b.from) { + return 1; + } + return 0; + }); + for (let r of newRedirects) { let found = false; for (let entry of redirects) { From a59195af45cba20d0f72900ea5959bff9338f322 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 16:31:24 -0500 Subject: [PATCH 478/746] v1.0.0-canary.34 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 212ee12c4..999d079ad 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.33", + "version": "1.0.0-canary.34", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From c9f73e65b0045664985d95baf39b207ab15a382e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 17:29:56 -0500 Subject: [PATCH 479/746] Fixes #1832 --- src/Template.js | 16 ++++++++++++++-- test/TemplateTest.js | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Template.js b/src/Template.js index 60f804d62..b55ae9e9e 100755 --- a/src/Template.js +++ b/src/Template.js @@ -2,6 +2,7 @@ const fs = require("fs-extra"); const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); +const get = require("lodash/get"); const { DateTime } = require("luxon"); const TemplateData = require("./TemplateData"); @@ -253,6 +254,17 @@ class Template extends TemplateContent { return this._usePermalinkRoot; } + // Makes page.url out of the serverless pathname + getServerlessOutputHref(data, resolvedLink) { + if (resolvedLink === false) { + let pathname = get(data, "eleventy.serverless.pathname"); + if (pathname) { + return pathname; + } + } + return resolvedLink; + } + // TODO instead of htmlIOException, do a global search to check if output path = input path and then add extra suffix async getOutputLocations(data) { let link = await this._getLink(data); @@ -266,7 +278,7 @@ class Template extends TemplateContent { return { link: link.toLink(), - href: link.toHref(), + href: this.getServerlessOutputHref(data, link.toHref()), path: path, }; } @@ -280,7 +292,7 @@ class Template extends TemplateContent { // Preferred to use the singular `getOutputLocations` above. async getOutputHref(data) { let link = await this._getLink(data); - return link.toHref(); + return this.getServerlessOutputHref(data, link.toHref()); } // Preferred to use the singular `getOutputLocations` above. diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 891432f68..b3ab4649c 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2301,3 +2301,26 @@ test("permalink object _getLink", async (t) => { serverless: "/serverless/", }); }); + +test("Resolve page.url from eleventy serverless data", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", + "./test/stubs/", + "./test/stubs/_site" + ); + let fakeData = { + eleventy: { + serverless: { + pathname: "/test/", + }, + }, + permalink: { + serverless: "/serverless/", + }, + }; + let outputHref = await tmpl.getOutputHref(fakeData); + t.is(outputHref, "/test/"); + + let { href } = await tmpl.getOutputLocations(fakeData); + t.is(href, "/test/"); +}); From a502bb104f81554acb068b2ff2ef0c6746f0fbf1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 14 Jun 2021 17:43:29 -0500 Subject: [PATCH 480/746] Fix https://github.com/11ty/eleventy/issues/1832 for templates that have both build and serverless --- src/Template.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Template.js b/src/Template.js index b55ae9e9e..d37a7cbdb 100755 --- a/src/Template.js +++ b/src/Template.js @@ -256,12 +256,11 @@ class Template extends TemplateContent { // Makes page.url out of the serverless pathname getServerlessOutputHref(data, resolvedLink) { - if (resolvedLink === false) { - let pathname = get(data, "eleventy.serverless.pathname"); - if (pathname) { - return pathname; - } + let pathname = get(data, "eleventy.serverless.pathname"); + if (pathname) { + return pathname; } + return resolvedLink; } From bb70c464996f9c955cf0aee4cd136ee0a1817451 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Jun 2021 07:04:38 -0500 Subject: [PATCH 481/746] Fixes issues related to #1832 (both path and link should be false in serverless mode) --- src/Template.js | 25 ++++++++++---- test/TemplateTest.js | 77 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 8 deletions(-) diff --git a/src/Template.js b/src/Template.js index d37a7cbdb..7b1240f89 100755 --- a/src/Template.js +++ b/src/Template.js @@ -254,14 +254,11 @@ class Template extends TemplateContent { return this._usePermalinkRoot; } - // Makes page.url out of the serverless pathname - getServerlessOutputHref(data, resolvedLink) { + _getServerlessPath(data) { let pathname = get(data, "eleventy.serverless.pathname"); if (pathname) { return pathname; } - - return resolvedLink; } // TODO instead of htmlIOException, do a global search to check if output path = input path and then add extra suffix @@ -275,15 +272,28 @@ class Template extends TemplateContent { path = link.toPath(this.outputDir); } + // Makes page.url out of the serverless pathname + let serverlessPath = this._getServerlessPath(data); + if (serverlessPath) { + return { + link: false, + href: serverlessPath, + path: false, + }; + } + return { link: link.toLink(), - href: this.getServerlessOutputHref(data, link.toHref()), + href: link.toHref(), path: path, }; } // Preferred to use the singular `getOutputLocations` above. async getOutputLink(data) { + if (this._getServerlessPath(data)) { + return false; + } let link = await this._getLink(data); return link.toLink(); } @@ -291,11 +301,14 @@ class Template extends TemplateContent { // Preferred to use the singular `getOutputLocations` above. async getOutputHref(data) { let link = await this._getLink(data); - return this.getServerlessOutputHref(data, link.toHref()); + return this._getServerlessPath(data) || link.toHref(); } // Preferred to use the singular `getOutputLocations` above. async getOutputPath(data) { + if (this._getServerlessPath(data)) { + return false; + } let link = await this._getLink(data); if (await this.usePermalinkRoot()) { return link.toPathFromRoot(); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index b3ab4649c..996ce61a1 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2315,12 +2315,85 @@ test("Resolve page.url from eleventy serverless data", async (t) => { }, }, permalink: { - serverless: "/serverless/", + serverless: "/serverless/", // this is ignored and pathname above is used! }, }; let outputHref = await tmpl.getOutputHref(fakeData); t.is(outputHref, "/test/"); - let { href } = await tmpl.getOutputLocations(fakeData); + let outputLink = await tmpl.getOutputLink(fakeData); + t.is(outputLink, false); + + let outputPath = await tmpl.getOutputPath(fakeData); + t.is(outputPath, false); + + let { href, link, path } = await tmpl.getOutputLocations(fakeData); t.is(href, "/test/"); + t.is(link, false); + t.is(path, false); +}); + +test("Resolve page.url from eleventy serverless data (when build also exists in permalink)", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", + "./test/stubs/", + "./test/stubs/_site" + ); + let fakeData = { + eleventy: { + serverless: { + pathname: "/test/", + }, + }, + permalink: { + build: "/build/", + serverless: "/serverless/", // this is ignored and pathname above is used! + }, + }; + + let outputHref = await tmpl.getOutputHref(fakeData); + t.is(outputHref, "/test/"); + + // These should be false because the eleventy.serverless object is set. + // When in build-mode they would not be false. + let outputLink = await tmpl.getOutputLink(fakeData); + t.is(outputLink, false); + + let outputPath = await tmpl.getOutputPath(fakeData); + t.is(outputPath, false); + + let { href, link, path } = await tmpl.getOutputLocations(fakeData); + t.is(href, "/test/"); + t.is(link, false); + t.is(path, false); +}); + +test("Do not resolve page.url from eleventy serverless data (when build also exists in permalink)", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", + "./test/stubs/", + "./test/stubs/_site" + ); + let fakeData = { + permalink: { + build: "/build/", + serverless: "/serverless/", + }, + }; + + let outputHref = await tmpl.getOutputHref(fakeData); + t.is(outputHref, "/build/"); + + // These should be false because the eleventy.serverless object is set. + // When in build-mode they would not be false. + let outputLink = await tmpl.getOutputLink(fakeData); + t.is(outputLink, "/build/index.html"); + + let outputPath = await tmpl.getOutputPath(fakeData); + t.is(outputPath, "./test/stubs/_site/build/index.html"); + + let { href, link, path } = await tmpl.getOutputLocations(fakeData); + t.is(href, "/build/"); + t.is(link, "/build/index.html"); + t.is(path, "./test/stubs/_site/build/index.html"); }); From 84cc8d58df1feca42d73bc8e28adf8532aa71185 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Jun 2021 07:50:11 -0500 Subject: [PATCH 482/746] Fixes #1313 Fixes #1792 --- cmd.js | 112 ++++++++++--------- src/Eleventy.js | 2 +- test/cmdTest.js | 22 ++++ test/stubs/cmd-help-processing/_data/test.js | 2 + 4 files changed, 82 insertions(+), 56 deletions(-) create mode 100644 test/stubs/cmd-help-processing/_data/test.js diff --git a/cmd.js b/cmd.js index 718c79758..2c59f9834 100755 --- a/cmd.js +++ b/cmd.js @@ -77,67 +77,69 @@ try { // reuse ErrorHandler instance in Eleventy errorHandler = elev.errorHandler; - if (argv.to === "json" || argv.to === "ndjson") { - // override logging output - elev.setIsVerbose(false); - } + if (argv.version) { + console.log(elev.getVersion()); + } else if (argv.help) { + console.log(elev.getHelp()); + } else { + if (argv.to === "json" || argv.to === "ndjson") { + // override logging output + elev.setIsVerbose(false); + } - elev.setPathPrefix(argv.pathprefix); - elev.setDryRun(argv.dryrun); - elev.setIncrementalBuild(argv.incremental); - elev.setPassthroughAll(argv.passthroughall); - elev.setFormats(argv.formats); + elev.setPathPrefix(argv.pathprefix); + elev.setDryRun(argv.dryrun); + elev.setIncrementalBuild(argv.incremental); + elev.setPassthroughAll(argv.passthroughall); + 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 - .init() - .then(function () { - try { - if (argv.version) { - console.log(elev.getVersion()); - } else if (argv.help) { - console.log(elev.getHelp()); - } else if (argv.serve) { - let startBrowsersync = true; - elev - .watch() - .catch((e) => { - // Build failed but error message already displayed. - startBrowsersync = false; - // A build error occurred and we aren’t going to --serve - }) - .then(function () { - if (startBrowsersync) { - elev.serve(argv.port); - } - }); - } else if (argv.watch) { - elev.watch().catch((e) => { - // A build error occurred and we aren’t going to --watch - }); - } else { - if (argv.to === "json") { - elev.toJSON().then(function (result) { - console.log(JSON.stringify(result, null, 2)); + // careful, we can’t use async/await here to error properly + // with old node versions in `please-upgrade-node` above. + elev + .init() + .then(function () { + try { + if (argv.serve) { + let startBrowsersync = true; + elev + .watch() + .catch((e) => { + // Build failed but error message already displayed. + startBrowsersync = false; + // A build error occurred and we aren’t going to --serve + }) + .then(function () { + if (startBrowsersync) { + elev.serve(argv.port); + } + }); + } else if (argv.watch) { + elev.watch().catch((e) => { + // A build error occurred and we aren’t going to --watch }); - } else if (argv.to === "ndjson") { - elev.toNDJSON().then(function (stream) { - stream.pipe(process.stdout); - }); - } else if (!argv.to || argv.to === "fs") { - elev.write(); } else { - throw new EleventyCommandCheckError( - `Invalid --to value: ${argv.to}. Supported values: \`fs\` (default), \`json\`, and \`ndjson\`.` - ); + if (argv.to === "json") { + elev.toJSON().then(function (result) { + console.log(JSON.stringify(result, null, 2)); + }); + } else if (argv.to === "ndjson") { + elev.toNDJSON().then(function (stream) { + stream.pipe(process.stdout); + }); + } else if (!argv.to || argv.to === "fs") { + elev.write(); + } else { + throw new EleventyCommandCheckError( + `Invalid --to value: ${argv.to}. Supported values: \`fs\` (default), \`json\`, and \`ndjson\`.` + ); + } } + } catch (e) { + errorHandler.fatal(e, "Eleventy CLI Error"); } - } catch (e) { - errorHandler.fatal(e, "Eleventy CLI Error"); - } - }) - .catch(errorHandler.fatal.bind(errorHandler)); + }) + .catch(errorHandler.fatal.bind(errorHandler)); + } } catch (e) { let errorHandler = new EleventyErrorHandler(); errorHandler.fatal(e, "Eleventy CLI Fatal Error"); diff --git a/src/Eleventy.js b/src/Eleventy.js index 7634e1acc..28be98245 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -487,7 +487,7 @@ Verbose Output: ${this.verboseMode}`); * @returns {String} - The version of Eleventy. */ getVersion() { - return require("../package.json").version; + return pkg.version; } /** diff --git a/test/cmdTest.js b/test/cmdTest.js index 778fcb65a..6fb63bf07 100644 --- a/test/cmdTest.js +++ b/test/cmdTest.js @@ -30,3 +30,25 @@ test.cb("Test command line exit code for global data error", (t) => { } ); }); + +test.cb("Test data should not process in a --help", (t) => { + exec( + "node ./cmd.js --input=test/stubs/cmd-help-processing --help", + (error, stdout, stderr) => { + t.falsy(error); + t.is(stdout.indexOf("THIS SHOULD NOT LOG TO CONSOLE"), -1); + t.end(); + } + ); +}); + +test.cb("Test data should not process in a --version", (t) => { + exec( + "node ./cmd.js --input=test/stubs/cmd-help-processing --version", + (error, stdout, stderr) => { + t.falsy(error); + t.is(stdout.indexOf("THIS SHOULD NOT LOG TO CONSOLE"), -1); + t.end(); + } + ); +}); diff --git a/test/stubs/cmd-help-processing/_data/test.js b/test/stubs/cmd-help-processing/_data/test.js new file mode 100644 index 000000000..5729f3042 --- /dev/null +++ b/test/stubs/cmd-help-processing/_data/test.js @@ -0,0 +1,2 @@ +console.log("THIS SHOULD NOT LOG TO CONSOLE"); +module.exports = []; From 72c17bdfaa8e6d8239927a5a30dd48d6109bdd0c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Jun 2021 08:13:26 -0500 Subject: [PATCH 483/746] Housekeeping --- test/TemplateRenderJavaScriptTest.js | 2 +- test/TemplateTest.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 49af36358..cdbc8e191 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -196,7 +196,7 @@ test("JS Render with a function", async (t) => { t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILLT9000

"); }); -// This doesn’t work, per arrow functions +// This doesn’t work because arrow functions don’t do `this` test.skip("Issue #934: JS Render with an arrow function and javascript function", async (t) => { let tr = getNewTemplateRender("./test/stubs/function-filter-arrow.11ty.js"); tr.config = { diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 996ce61a1..028dda9b2 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2042,7 +2042,7 @@ This is content.` }); test.skip("Custom Front Matter Parsing Options (using TOML)", async (t) => { - // Depends on https://github.com/jonschlinkert/gray-matter/issues/92 for Windows + // Currently fails on Windows, needs https://github.com/jonschlinkert/gray-matter/issues/92 let toml = require("toml"); let tmpl = getNewTemplate( @@ -2055,7 +2055,6 @@ test.skip("Custom Front Matter Parsing Options (using TOML)", async (t) => { toml: toml.parse.bind(toml), }, }; - tmpl.config = newConfig; let frontmatter = await tmpl.getFrontMatter(); t.deepEqual(frontmatter.data, { From ff824ba9ddc012521d96412ee789847018c0ba03 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Jun 2021 16:28:40 -0500 Subject: [PATCH 484/746] Option to use build url for page.url in serverless mode. --- src/Serverless.js | 3 +++ src/Template.js | 13 +++++++++++-- test/TemplateTest.js | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/Serverless.js b/src/Serverless.js index b0a77443b..92f2587aa 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -21,6 +21,8 @@ class Serverless { { inputDir: ".", functionsDir: "functions/", + // Whether the serverless pathname overrides the page.url data value. + pathnameOverridesPageUrl: true, matchUrlToPattern(path, urlToCompare) { let pattern = new UrlPattern(urlToCompare); return pattern.match(path); @@ -146,6 +148,7 @@ class Serverless { // Add the params to Global Data eleventyConfig.addGlobalData("eleventy.serverless", { pathname: this.path, + pathnameOverridesPageUrl: this.options.pathnameOverridesPageUrl, query: this.options.query, path: pathParams, }); diff --git a/src/Template.js b/src/Template.js index 7b1240f89..aaf9313db 100755 --- a/src/Template.js +++ b/src/Template.js @@ -254,6 +254,10 @@ class Template extends TemplateContent { return this._usePermalinkRoot; } + _useServerlessOverride(data) { + return get(data, "eleventy.serverless.pathnameOverridesPageUrl", true); + } + _getServerlessPath(data) { let pathname = get(data, "eleventy.serverless.pathname"); if (pathname) { @@ -277,7 +281,9 @@ class Template extends TemplateContent { if (serverlessPath) { return { link: false, - href: serverlessPath, + href: this._useServerlessOverride(data) + ? serverlessPath + : link.toHref(), path: false, }; } @@ -301,7 +307,10 @@ class Template extends TemplateContent { // Preferred to use the singular `getOutputLocations` above. async getOutputHref(data) { let link = await this._getLink(data); - return this._getServerlessPath(data) || link.toHref(); + let pathname = this._getServerlessPath(data); + return pathname && this._useServerlessOverride(data) + ? pathname + : link.toHref(); } // Preferred to use the singular `getOutputLocations` above. diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 028dda9b2..06067c478 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2396,3 +2396,39 @@ test("Do not resolve page.url from eleventy serverless data (when build also exi t.is(link, "/build/index.html"); t.is(path, "./test/stubs/_site/build/index.html"); }); + +test("Do not override page.url with serverless url", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", + "./test/stubs/", + "./test/stubs/_site" + ); + let fakeData = { + eleventy: { + serverless: { + pathname: "/test/", + pathnameOverridesPageUrl: false, + }, + }, + permalink: { + build: "/build/", + serverless: "/serverless/", + }, + }; + + let outputHref = await tmpl.getOutputHref(fakeData); + t.is(outputHref, "/build/"); + + // These should be false because the eleventy.serverless object is set. + // When in build-mode they would not be false. + let outputLink = await tmpl.getOutputLink(fakeData); + t.is(outputLink, false); + + let outputPath = await tmpl.getOutputPath(fakeData); + t.is(outputPath, false); + + let { href, link, path } = await tmpl.getOutputLocations(fakeData); + t.is(href, "/build/"); + t.is(link, false); + t.is(path, false); +}); From a491ff04758edb97c3bf4f56727a455b892de2dd Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Jun 2021 16:30:00 -0500 Subject: [PATCH 485/746] v1.0.0-canary.35 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 999d079ad..e0f5c65c3 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.34", + "version": "1.0.0-canary.35", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 3344c8e054c59ea4bdb8385f9e51ce90f2d94fe5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Jun 2021 09:27:06 -0500 Subject: [PATCH 486/746] Fix for page.filePathStem in serverless mode. --- src/Eleventy.js | 8 ++++++++ src/EleventyFiles.js | 1 + src/Serverless.js | 19 +++++++++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 28be98245..92af6cf29 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -96,6 +96,13 @@ class Eleventy { */ this.isDryRun = false; + /** + * @member {Boolean} - Explicit input directory (usually used when input is a single file/serverless) + */ + if (options.inputDir) { + this.setInputDir(options.inputDir); + } + if (performance) { debug("Eleventy warm up time (in ms) %o", performance.now()); } @@ -374,6 +381,7 @@ Verbose Output: ${this.verboseMode}`); getEnvironmentVariableValues() { let configPath = this.eleventyConfig.getLocalProjectConfigFile(); let absolutePathToConfig = TemplatePath.absolutePath(configPath); + // TODO(zachleat): if config is not in root (e.g. using --config=) let root = TemplatePath.getDirFromFilePath(absolutePathToConfig); return { diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 8a94f0df6..8871acfc8 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -70,6 +70,7 @@ class EleventyFiles { if (this.input === this.inputDir) { this.templateGlobs = this.extensionMap.getGlobs(this.inputDir); } else { + // input is not a directory this.templateGlobs = TemplateGlob.map([this.input]); } diff --git a/src/Serverless.js b/src/Serverless.js index 92f2587aa..47fa6b83e 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -113,7 +113,7 @@ class Serverless { process.chdir(this.dir); } - let inputDir = path.join(this.dir, this.options.inputDir); + let inputDir = this.options.inputDir; let configPath = path.join(this.dir, this.configFilename); let { pathParams, inputPath } = this.matchUrlPattern(this.path); @@ -133,11 +133,12 @@ class Serverless { debug(`Input dir: ${inputDir}`); debug(`Requested URL: ${this.path}`); - debug(`Path params: ${pathParams}`); + debug("Path params: %o", pathParams); debug(`Input path: ${inputPath}`); let elev = new Eleventy(inputPath, null, { configPath, + inputDir, config: (eleventyConfig) => { if (Object.keys(this.options.precompiledCollections).length > 0) { eleventyConfig.setPrecompiledCollections( @@ -146,16 +147,22 @@ class Serverless { } // Add the params to Global Data - eleventyConfig.addGlobalData("eleventy.serverless", { + let globalData = { pathname: this.path, - pathnameOverridesPageUrl: this.options.pathnameOverridesPageUrl, query: this.options.query, path: pathParams, - }); + }; + + // leave out if default value + if (!this.options.pathnameOverridesPageUrl) { + globalData.pathnameOverridesPageUrl = + this.options.pathnameOverridesPageUrl; + } + + eleventyConfig.addGlobalData("eleventy.serverless", globalData); }, }); - elev.setInputDir(inputDir); await elev.init(); let json = await elev.toJSON(); From 847943a31cd9344339ffef7418df73b31a991ac2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Jun 2021 09:27:49 -0500 Subject: [PATCH 487/746] v1.0.0-canary.36 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e0f5c65c3..03e4a6af8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.35", + "version": "1.0.0-canary.36", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 656b0222a38cd05bbe799766c915a79e7e36e354 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Jun 2021 10:08:24 -0500 Subject: [PATCH 488/746] Make it a bit easier to use supplied redirect handler or provide your own --- src/Plugins/ServerlessBundlerPlugin.js | 79 +++++++++++++++----------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 5e8e3c5e7..f938781ca 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -7,6 +7,39 @@ const TemplatePath = require("../TemplatePath"); const deleteRequireCache = require("../Util/DeleteRequireCache"); const debug = require("debug")("Eleventy:Serverless"); +// Provider specific +const redirectHandlers = { + "netlify-toml": function (name, outputMap) { + let newRedirects = []; + for (let url in outputMap) { + newRedirects.push({ + from: url, + to: `/.netlify/functions/${name}`, + status: 200, + force: true, + _generated_by_eleventy_serverless: name, + }); + } + + let configFilename = "./netlify.toml"; + let cfg = {}; + // parse existing netlify.toml + if (fs.existsSync(configFilename)) { + cfg = TOML.parse(fs.readFileSync(configFilename)); + } + let cfgWithRedirects = addRedirectsWithoutDuplicates( + name, + cfg, + newRedirects + ); + + fs.writeFileSync(configFilename, TOML.stringify(cfgWithRedirects)); + debug( + `Eleventy Serverless (${name}), writing (×${newRedirects.length}): ${configFilename}` + ); + }, +}; + function getNodeModulesList(files) { let pkgs = new Set(); @@ -197,36 +230,9 @@ function EleventyPlugin(eleventyConfig, options = {}) { // Excluded from: `eleventy-app-config-modules.js` and `eleventy-app-globaldata-modules.js` excludeDependencies: [], - // Add automated redirects to netlify.toml (appends or creates, avoids duplicate entries) - redirects: function (outputMap) { - let newRedirects = []; - for (let url in outputMap) { - newRedirects.push({ - from: url, - to: `/.netlify/functions/${options.name}`, - status: 200, - force: true, - _generated_by_eleventy_serverless: options.name, - }); - } - - let configFilename = "./netlify.toml"; - let cfg = {}; - // parse existing netlify.toml - if (fs.existsSync(configFilename)) { - cfg = TOML.parse(fs.readFileSync(configFilename)); - } - let cfgWithRedirects = addRedirectsWithoutDuplicates( - options.name, - cfg, - newRedirects - ); - - fs.writeFileSync(configFilename, TOML.stringify(cfgWithRedirects)); - debug( - `Eleventy Serverless (${options.name}), writing (×${newRedirects.length}): ${configFilename}` - ); - }, + // Add automated redirects (appends or creates, avoids duplicate entries) + // Also accepts a custom callback function(name, outputMap) + redirects: "netlify-toml", }, options ); @@ -334,8 +340,17 @@ function EleventyPlugin(eleventyConfig, options = {}) { ); this.copyCount++; - // Write redirects into netlify.toml (even if no redirects exist for this function to handle deletes) - options.redirects(outputMap); + // Write redirects (even if no redirects exist for this function to handle deletes) + if (options.redirects) { + if ( + typeof options.redirects === "string" && + redirectHandlers[options.redirects] + ) { + redirectHandlers[options.redirects](options.name, outputMap); + } else if (typeof options.redirects === "function") { + options.redirects(options.name, outputMap); + } + } if (mapEntryCount > 0) { // Copy templates to bundle folder From 6a666ba134ec3582ffa4dd29909de08d4664849d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 18 Jun 2021 14:09:25 -0500 Subject: [PATCH 489/746] Fixes #1837 --- src/EleventyFiles.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 8871acfc8..ac351a4b2 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -282,7 +282,7 @@ class EleventyFiles { } getIgnores() { - let rootDirectory = this.localPathRoot || TemplatePath.getWorkingDir(); + let rootDirectory = this.localPathRoot || "."; let files = []; for (let ignore of this.config.ignores) { @@ -301,16 +301,16 @@ class EleventyFiles { files = files.concat(this.eleventyIgnoreContent); } else { let absoluteInputDir = TemplatePath.absolutePath(this.inputDir); - let eleventyIgnores = [ + let eleventyIgnoreFiles = [ TemplatePath.join(rootDirectory, ".eleventyignore"), ]; if (rootDirectory !== absoluteInputDir) { - eleventyIgnores.push( + eleventyIgnoreFiles.push( TemplatePath.join(this.inputDir, ".eleventyignore") ); } - files = files.concat(EleventyFiles.getFileIgnores(eleventyIgnores)); + files = files.concat(EleventyFiles.getFileIgnores(eleventyIgnoreFiles)); } // ignore output dir unless that would exclude all input From 32646153a78b58c6c6ea83b85e75e51b4c3447bf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 18 Jun 2021 14:10:30 -0500 Subject: [PATCH 490/746] v1.0.0-canary.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 03e4a6af8..896932bb9 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.36", + "version": "1.0.0-canary.37", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 52bb4f97075089b3b61e104e76a74372a6fe17f8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 22 Jun 2021 21:20:02 -0500 Subject: [PATCH 491/746] Adds support for page.url in serverless templates. Resolve urls with :path :vars using the serverlessUrl filter. Use an array of urls in serverless keys. Toggle the serverless bundler on and off using the `bundlerEnabled` option in the plugin. --- src/ComputedDataTemplateString.js | 7 +- src/Filters/ServerlessUrl.js | 14 ++ src/Plugins/ServerlessBundlerPlugin.js | 42 ++++- src/Serverless.js | 13 +- src/Template.js | 89 ++++------ src/TemplateContent.js | 8 + src/TemplateData.js | 3 + src/TemplatePermalink.js | 51 ++++-- src/defaultConfig.js | 3 + test/ServerlessUrlTest.js | 36 ++++ test/TemplatePermalinkTest.js | 56 +++++- test/TemplateTest.js | 162 +++++++++++++----- .../permalink-empty-object/empty-object.md | 5 + 13 files changed, 357 insertions(+), 132 deletions(-) create mode 100644 src/Filters/ServerlessUrl.js create mode 100644 test/ServerlessUrlTest.js create mode 100644 test/stubs/permalink-empty-object/empty-object.md diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js index ffa391e6f..6bc71268a 100644 --- a/src/ComputedDataTemplateString.js +++ b/src/ComputedDataTemplateString.js @@ -55,7 +55,12 @@ class ComputedDataTemplateString { } catch (e) { debug("Computed Data first pass data resolution error: %o", e); } - return this.findVarsInOutput(output); + + // page.outputPath on serverless urls returns false. + if (typeof output === "string") { + return this.findVarsInOutput(output); + } + return []; } } diff --git a/src/Filters/ServerlessUrl.js b/src/Filters/ServerlessUrl.js new file mode 100644 index 000000000..a4deb42e0 --- /dev/null +++ b/src/Filters/ServerlessUrl.js @@ -0,0 +1,14 @@ +const UrlPattern = require("url-pattern"); + +function stringify(url, urlData = {}) { + let pattern = new UrlPattern(url); + return pattern.stringify(urlData); +} + +module.exports = function (url, urlData = {}) { + if (Array.isArray(url)) { + return url.slice().map((entry) => stringify(entry, urlData)); + } + + return stringify(url, urlData); +}; diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index f938781ca..09766836f 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -156,13 +156,23 @@ class BundlerHelper { } writeDependencyEntryFile() { - this.writeBundlerDependenciesFile("eleventy-bundler-modules.js", [ - "./eleventy-app-config-modules.js", - "./eleventy-app-globaldata-modules.js", - ]); + // we write this even when disabled because the serverless function expects it + this.writeBundlerDependenciesFile( + "eleventy-bundler-modules.js", + this.options.bundlerEnabled + ? [ + "./eleventy-app-config-modules.js", + "./eleventy-app-globaldata-modules.js", + ] + : [] + ); } writeDependencyConfigFile(configPath) { + if (!this.options.bundlerEnabled) { + return; + } + let modules = getNodeModulesList([configPath]); this.writeBundlerDependenciesFile( "eleventy-app-config-modules.js", @@ -173,6 +183,10 @@ class BundlerHelper { } writeDependencyGlobalDataFile(globalDataFileList) { + if (!this.options.bundlerEnabled) { + return; + } + let modules = getNodeModulesList(globalDataFileList); this.writeBundlerDependenciesFile( "eleventy-app-globaldata-modules.js", @@ -233,6 +247,9 @@ function EleventyPlugin(eleventyConfig, options = {}) { // Add automated redirects (appends or creates, avoids duplicate entries) // Also accepts a custom callback function(name, outputMap) redirects: "netlify-toml", + + // Useful for local develop to disable all bundle copying + bundlerEnabled: true, }, options ); @@ -256,6 +273,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { }); eleventyConfig.on("eleventy.after", async () => { + if (!options.bundlerEnabled) { + return; + } + // extra copy targets // we put these in after a build so that we can grab files generated _by_ the build too if (options.copy && Array.isArray(options.copy)) { @@ -283,7 +304,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { }); eleventyConfig.on("eleventy.env", (env) => { - helper.copyFile(env.config, "eleventy.config.js"); + if (options.bundlerEnabled) { + helper.copyFile(env.config, "eleventy.config.js"); + } + helper.writeDependencyConfigFile(env.config); }); @@ -292,6 +316,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { }); eleventyConfig.on("eleventy.directories", async (dirs) => { + if (!options.bundlerEnabled) { + return; + } + let promises = []; promises.push(helper.recursiveCopy(dirs.data)); promises.push(helper.recursiveCopy(dirs.includes)); @@ -341,7 +369,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { this.copyCount++; // Write redirects (even if no redirects exist for this function to handle deletes) - if (options.redirects) { + if (options.bundlerEnabled && options.redirects) { if ( typeof options.redirects === "string" && redirectHandlers[options.redirects] @@ -352,7 +380,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { } } - if (mapEntryCount > 0) { + if (options.bundlerEnabled && mapEntryCount > 0) { // Copy templates to bundle folder for (let url in outputMap) { helper.recursiveCopy(outputMap[url]); diff --git a/src/Serverless.js b/src/Serverless.js index 47fa6b83e..b2dcee1ec 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -21,8 +21,6 @@ class Serverless { { inputDir: ".", functionsDir: "functions/", - // Whether the serverless pathname overrides the page.url data value. - pathnameOverridesPageUrl: true, matchUrlToPattern(path, urlToCompare) { let pattern = new UrlPattern(urlToCompare); return pattern.match(path); @@ -113,7 +111,7 @@ class Serverless { process.chdir(this.dir); } - let inputDir = this.options.inputDir; + let inputDir = this.options.input || this.options.inputDir; let configPath = path.join(this.dir, this.configFilename); let { pathParams, inputPath } = this.matchUrlPattern(this.path); @@ -136,7 +134,7 @@ class Serverless { debug("Path params: %o", pathParams); debug(`Input path: ${inputPath}`); - let elev = new Eleventy(inputPath, null, { + let elev = new Eleventy(this.options.input || inputPath, null, { configPath, inputDir, config: (eleventyConfig) => { @@ -148,17 +146,10 @@ class Serverless { // Add the params to Global Data let globalData = { - pathname: this.path, query: this.options.query, path: pathParams, }; - // leave out if default value - if (!this.options.pathnameOverridesPageUrl) { - globalData.pathnameOverridesPageUrl = - this.options.pathnameOverridesPageUrl; - } - eleventyConfig.addGlobalData("eleventy.serverless", globalData); }, }); diff --git a/src/Template.js b/src/Template.js index aaf9313db..c37d717f2 100755 --- a/src/Template.js +++ b/src/Template.js @@ -195,30 +195,45 @@ class Template extends TemplateContent { debugDev("Not using dynamic permalinks, using %o", permalink); permalinkValue = permalink; } else if (isPlainObject(permalink)) { - let promises = []; - let keys = []; - for (let key in permalink) { - keys.push(key); - promises.push(super.render(permalink[key], data, true)); - } + // Empty permalink {} object should act as if no permalink was set at all + // and inherit the default behavior + let isEmptyObject = Object.keys(permalink).length === 0; + if (!isEmptyObject) { + let promises = []; + let keys = []; + for (let key in permalink) { + keys.push(key); + if (key !== "build" && Array.isArray(permalink[key])) { + promises.push( + Promise.all( + [...permalink[key]].map((entry) => + super.renderPermalink(entry, data, true) + ) + ) + ); + } else { + promises.push(super.renderPermalink(permalink[key], data, true)); + } + } - let results = await Promise.all(promises); + let results = await Promise.all(promises); - permalinkValue = {}; - for (let j = 0, k = keys.length; j < k; j++) { - let key = keys[j]; - permalinkValue[key] = results[j]; - debug( - "Rendering permalink.%o for %o: %s becomes %o", - key, - this.inputPath, - permalink[key], - results[j] - ); + permalinkValue = {}; + for (let j = 0, k = keys.length; j < k; j++) { + let key = keys[j]; + permalinkValue[key] = results[j]; + debug( + "Rendering permalink.%o for %o: %s becomes %o", + key, + this.inputPath, + permalink[key], + results[j] + ); + } } } else if (permalink) { // render variables inside permalink front matter, bypass markdown - permalinkValue = await super.render(permalink, data, true); + permalinkValue = await super.renderPermalink(permalink, data, true); debug( "Rendering permalink for %o: %s becomes %o", this.inputPath, @@ -242,7 +257,6 @@ class Template extends TemplateContent { ); } - // TODO add support for a key inside the `permalink` object for this async usePermalinkRoot() { if (this._usePermalinkRoot === undefined) { // TODO this only works with immediate front matter and not data files @@ -254,17 +268,6 @@ class Template extends TemplateContent { return this._usePermalinkRoot; } - _useServerlessOverride(data) { - return get(data, "eleventy.serverless.pathnameOverridesPageUrl", true); - } - - _getServerlessPath(data) { - let pathname = get(data, "eleventy.serverless.pathname"); - if (pathname) { - return pathname; - } - } - // TODO instead of htmlIOException, do a global search to check if output path = input path and then add extra suffix async getOutputLocations(data) { let link = await this._getLink(data); @@ -276,18 +279,6 @@ class Template extends TemplateContent { path = link.toPath(this.outputDir); } - // Makes page.url out of the serverless pathname - let serverlessPath = this._getServerlessPath(data); - if (serverlessPath) { - return { - link: false, - href: this._useServerlessOverride(data) - ? serverlessPath - : link.toHref(), - path: false, - }; - } - return { link: link.toLink(), href: link.toHref(), @@ -297,9 +288,6 @@ class Template extends TemplateContent { // Preferred to use the singular `getOutputLocations` above. async getOutputLink(data) { - if (this._getServerlessPath(data)) { - return false; - } let link = await this._getLink(data); return link.toLink(); } @@ -307,17 +295,11 @@ class Template extends TemplateContent { // Preferred to use the singular `getOutputLocations` above. async getOutputHref(data) { let link = await this._getLink(data); - let pathname = this._getServerlessPath(data); - return pathname && this._useServerlessOverride(data) - ? pathname - : link.toHref(); + return link.toHref(); } // Preferred to use the singular `getOutputLocations` above. async getOutputPath(data) { - if (this._getServerlessPath(data)) { - return false; - } let link = await this._getLink(data); if (await this.usePermalinkRoot()) { return link.toPathFromRoot(); @@ -578,6 +560,7 @@ class Template extends TemplateContent { if (this.config.keys.computed in data) { // Note that `permalink` is only a thing that gets consumed—it does not go directly into generated data // this allows computed entries to use page.url or page.outputPath and they’ll be resolved properly + this.computedData.addTemplateString( "page.url", async (data) => await this.getOutputHref(data), diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 813e43756..c89388c5e 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -282,7 +282,15 @@ class TemplateContent { } } + async renderPermalink(permalink, data, bypassMarkdown) { + return this._render(permalink, data, bypassMarkdown); + } + async render(str, data, bypassMarkdown) { + return this._render(str, data, bypassMarkdown); + } + + async _render(str, data, bypassMarkdown) { try { let fn = await this.compile(str, bypassMarkdown); let templateBenchmark = bench.get("Template Render"); diff --git a/src/TemplateData.js b/src/TemplateData.js index 1af9a0506..bf90503db 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -462,6 +462,9 @@ class TemplateData { deleteRequireCache(localPath); let returnValue = require(localPath); + // TODO special exception for Global data `permalink.js` + // module.exports = (data) => `${data.page.filePathStem}/`; // Does not work + // module.exports = () => ((data) => `${data.page.filePathStem}/`); // Works if (typeof returnValue === "function") { returnValue = await returnValue(this.configApiGlobalData || {}); } diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index d70563a6d..cb098be21 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -11,18 +11,35 @@ class TemplatePermalink { this._isRendered = true; this._writeToFileSystem = true; - let rawLink; + let buildLink; + if (isLinkAnObject) { if ("build" in link) { - rawLink = link.build; + buildLink = link.build; + } + + // find the first string key + for (let key in link) { + if (typeof key !== "string") { + continue; + } + if (key !== "build" && link[key] !== false) { + // is array of serverless urls, use the first one + if (Array.isArray(link[key])) { + this.primaryServerlessUrl = link[key][0]; + } else { + this.primaryServerlessUrl = link[key]; + } + } + break; } } else { - rawLink = link; + buildLink = link; } // permalink: false and permalink: build: false - if (typeof rawLink === "boolean") { - if (rawLink === false) { + if (typeof buildLink === "boolean") { + if (buildLink === false) { this._writeToFileSystem = false; } else { throw new Error( @@ -33,8 +50,8 @@ class TemplatePermalink { }false\`?` ); } - } else if (rawLink) { - this.rawLink = rawLink; + } else if (buildLink) { + this.buildLink = buildLink; } this.serverlessUrls = {}; @@ -57,17 +74,19 @@ class TemplatePermalink { return this.serverlessUrls; } - _cleanLink(link) { + _addDefaultLinkFilename(link) { return link + (link.substr(-1) === "/" ? "index.html" : ""); } toLink() { - if (!this.rawLink) { + if (this.primaryServerlessUrl) { + return this.primaryServerlessUrl; + } else if (!this.buildLink) { // empty or false return false; } - let cleanLink = this._cleanLink(this.rawLink); + let cleanLink = this._addDefaultLinkFilename(this.buildLink); let parsed = parsePath(cleanLink); return TemplatePath.join( @@ -84,7 +103,9 @@ class TemplatePermalink { // index.html becomes / // test/index.html becomes test/ toHref() { - if (!this.rawLink) { + if (this.primaryServerlessUrl) { + return this.primaryServerlessUrl; + } else if (!this.buildLink) { // empty or false return false; } @@ -102,6 +123,10 @@ class TemplatePermalink { } toPath(outputDir) { + if (!this.buildLink) { + return false; + } + let uri = this.toLink(); if (uri === false) { @@ -112,6 +137,10 @@ class TemplatePermalink { } toPathFromRoot() { + if (!this.buildLink) { + return false; + } + let uri = this.toLink(); if (uri === false) { diff --git a/src/defaultConfig.js b/src/defaultConfig.js index 20538b6b0..474c124e5 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -1,4 +1,5 @@ const urlFilter = require("./Filters/Url"); +const serverlessUrlFilter = require("./Filters/ServerlessUrl"); const slugFilter = require("./Filters/Slug"); const getCollectionItem = require("./Filters/GetCollectionItem"); @@ -12,6 +13,8 @@ module.exports = function (config) { }); config.addFilter("log", console.log); + config.addFilter("serverlessUrl", serverlessUrlFilter); + config.addFilter("getCollectionItem", (collection, page) => getCollectionItem(collection, page) ); diff --git a/test/ServerlessUrlTest.js b/test/ServerlessUrlTest.js new file mode 100644 index 000000000..7b9e41c2a --- /dev/null +++ b/test/ServerlessUrlTest.js @@ -0,0 +1,36 @@ +const test = require("ava"); +const ServerlessUrl = require("../src/Filters/ServerlessUrl"); + +test("serverlessUrl Stringify", (t) => { + // Straight string + t.is(ServerlessUrl("/test/"), "/test/"); + + // Has data param but doesn’t use it + t.is(ServerlessUrl("/test/", { id: 1 }), "/test/"); + + // Has data param and does use it + t.is(ServerlessUrl("/test/:id/", { id: 1 }), "/test/1/"); + + // Throws error when it needs a data param + t.throws(() => ServerlessUrl("/test/:id/", {})); +}); + +test("serverlessUrl Stringify Arrays", (t) => { + // Straight string + t.deepEqual(ServerlessUrl(["/test/", "/testb/"]), ["/test/", "/testb/"]); + + // Has data param but doesn’t use it + t.deepEqual(ServerlessUrl(["/test/", "/testb/"], { id: 1 }), [ + "/test/", + "/testb/", + ]); + + // Has data param and does use it + t.deepEqual(ServerlessUrl(["/test/:id/", "/testb/:id/"], { id: 1 }), [ + "/test/1/", + "/testb/1/", + ]); + + // Throws error when it needs a data param + t.throws(() => ServerlessUrl(["/test/:id/", "/testb/:id/"], {})); +}); diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index 146a188fe..ca1be5d02 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -171,45 +171,89 @@ test("Permalink Object, just build", (t) => { }); test("Permalink Object, serverless URLs", (t) => { + // serverless t.is( new TemplatePermalink({ serverless: "permalinksubfolder/test.html", }).toLink(), - false + "permalinksubfolder/test.html" ); t.is( new TemplatePermalink({ serverless: "permalinksubfolder/test.html", }).toHref(), - false + "permalinksubfolder/test.html" ); + // request t.is( new TemplatePermalink({ request: "/url/", }).toLink(), - false + "/url/" ); t.is( new TemplatePermalink({ request: "/url/", }).toHref(), - false + "/url/" ); + // rando t.is( new TemplatePermalink({ rando: "/url/", }).toLink(), - false + "/url/" ); t.is( new TemplatePermalink({ rando: "/url/", }).toHref(), - false + "/url/" + ); +}); + +test("Permalink Object, combo build and serverless URLs", (t) => { + t.is( + new TemplatePermalink({ + build: "/url/", + serverless: "/serverless/", + }).toLink(), + "/url/index.html" + ); + + t.is( + new TemplatePermalink({ + build: "/url/", + serverless: "/serverless/", + }).toHref(), + "/url/" + ); + + // reordered, serverless is primary + t.is( + new TemplatePermalink({ + serverless: "/serverless/", + build: "/url/", + }).toLink(), + "/serverless/" ); + + t.is( + new TemplatePermalink({ + serverless: "/serverless/", + build: "/url/", + }).toHref(), + "/serverless/" + ); +}); + +test("Permalink Object, empty object", (t) => { + t.is(new TemplatePermalink({}).toLink(), false); + + t.is(new TemplatePermalink({}).toHref(), false); }); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 06067c478..46ddff515 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2250,8 +2250,8 @@ test("permalink object without build", async (t) => { "./test/stubs/_site" ); - t.is(await tmpl.getOutputLink(), false); - t.is(await tmpl.getOutputHref(), false); + t.is(await tmpl.getOutputLink(), "/url/"); + t.is(await tmpl.getOutputHref(), "/url/"); }); test("permalink object _getLink", async (t) => { @@ -2266,8 +2266,9 @@ test("permalink object _getLink", async (t) => { serverless: "/serverless/", }, }); - t.is(await link.toLink(), false); - t.is(await link.toHref(), false); + t.is(await link.toLink(), "/serverless/"); + t.is(await link.toHref(), "/serverless/"); + t.deepEqual(link.getServerlessUrls(), { serverless: "/serverless/", }); @@ -2299,75 +2300,129 @@ test("permalink object _getLink", async (t) => { t.deepEqual(tmpl.getServerlessUrls(), { serverless: "/serverless/", }); + + // template syntax + let link4 = await tmpl._getLink({ + test: "a", + permalink: { + build: "/build{{ test }}/", + serverless: "/serverless{{ test }}/", + }, + }); + t.is(await link4.toLink(), "/builda/index.html"); + t.is(await link4.toHref(), "/builda/"); + t.deepEqual(link4.getServerlessUrls(), { + serverless: "/serverlessa/", + }); + t.deepEqual(tmpl.getServerlessUrls(), { + serverless: "/serverlessa/", + }); +}); + +test("permalink object _getLink (array of serverless URLs)", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-nobuild/permalink-nobuild.md", + "./test/stubs/", + "./test/stubs/_site" + ); + + // Array of URLs is supported + let link4 = await tmpl._getLink({ + permalink: { + serverless: ["/serverless1/", "/serverless2/"], + }, + }); + t.is(await link4.toLink(), "/serverless1/"); + t.is(await link4.toHref(), "/serverless1/"); + + t.deepEqual(link4.getServerlessUrls(), { + serverless: ["/serverless1/", "/serverless2/"], + }); + t.deepEqual(tmpl.getServerlessUrls(), { + serverless: ["/serverless1/", "/serverless2/"], + }); +}); + +test("permalink object _getLink (array of serverless URLs with template syntax)", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-nobuild/permalink-nobuild.md", + "./test/stubs/", + "./test/stubs/_site" + ); + + // Array of URLs is supported + let link = await tmpl._getLink({ + test: "a", + permalink: { + serverless: ["/serverless1{{ test }}/", "/serverless2{{ test }}/"], + }, + }); + t.is(await link.toLink(), "/serverless1a/"); + t.is(await link.toHref(), "/serverless1a/"); + + t.deepEqual(link.getServerlessUrls(), { + serverless: ["/serverless1a/", "/serverless2a/"], + }); + t.deepEqual(tmpl.getServerlessUrls(), { + serverless: ["/serverless1a/", "/serverless2a/"], + }); }); -test("Resolve page.url from eleventy serverless data", async (t) => { +test("Do not resolve page.url from eleventy serverless data", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", "./test/stubs/", "./test/stubs/_site" ); let fakeData = { - eleventy: { - serverless: { - pathname: "/test/", - }, - }, permalink: { - serverless: "/serverless/", // this is ignored and pathname above is used! + serverless: "/serverless/", }, }; let outputHref = await tmpl.getOutputHref(fakeData); - t.is(outputHref, "/test/"); + t.is(outputHref, "/serverless/"); let outputLink = await tmpl.getOutputLink(fakeData); - t.is(outputLink, false); + t.is(outputLink, "/serverless/"); let outputPath = await tmpl.getOutputPath(fakeData); t.is(outputPath, false); let { href, link, path } = await tmpl.getOutputLocations(fakeData); - t.is(href, "/test/"); - t.is(link, false); + t.is(href, "/serverless/"); + t.is(link, "/serverless/"); t.is(path, false); }); -test("Resolve page.url from eleventy serverless data (when build also exists in permalink)", async (t) => { +test("Do not resolve page.url from eleventy serverless data (when build also exists in permalink and serverless global data exists)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", "./test/stubs/", "./test/stubs/_site" ); let fakeData = { - eleventy: { - serverless: { - pathname: "/test/", - }, - }, permalink: { build: "/build/", - serverless: "/serverless/", // this is ignored and pathname above is used! + serverless: "/serverless/", }, }; let outputHref = await tmpl.getOutputHref(fakeData); - t.is(outputHref, "/test/"); + t.is(outputHref, "/build/"); - // These should be false because the eleventy.serverless object is set. - // When in build-mode they would not be false. let outputLink = await tmpl.getOutputLink(fakeData); - t.is(outputLink, false); + t.is(outputLink, "/build/index.html"); let outputPath = await tmpl.getOutputPath(fakeData); - t.is(outputPath, false); + t.is(outputPath, "./test/stubs/_site/build/index.html"); let { href, link, path } = await tmpl.getOutputLocations(fakeData); - t.is(href, "/test/"); - t.is(link, false); - t.is(path, false); + t.is(href, "/build/"); + t.is(link, "/build/index.html"); + t.is(path, "./test/stubs/_site/build/index.html"); }); -test("Do not resolve page.url from eleventy serverless data (when build also exists in permalink)", async (t) => { +test("Do not resolve page.url from eleventy serverless data (when build also exists in permalink and serverless global data does not exist)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", "./test/stubs/", @@ -2404,12 +2459,6 @@ test("Do not override page.url with serverless url", async (t) => { "./test/stubs/_site" ); let fakeData = { - eleventy: { - serverless: { - pathname: "/test/", - pathnameOverridesPageUrl: false, - }, - }, permalink: { build: "/build/", serverless: "/serverless/", @@ -2419,16 +2468,43 @@ test("Do not override page.url with serverless url", async (t) => { let outputHref = await tmpl.getOutputHref(fakeData); t.is(outputHref, "/build/"); - // These should be false because the eleventy.serverless object is set. - // When in build-mode they would not be false. let outputLink = await tmpl.getOutputLink(fakeData); - t.is(outputLink, false); + t.is(outputLink, "/build/index.html"); let outputPath = await tmpl.getOutputPath(fakeData); - t.is(outputPath, false); + t.is(outputPath, "./test/stubs/_site/build/index.html"); let { href, link, path } = await tmpl.getOutputLocations(fakeData); t.is(href, "/build/"); - t.is(link, false); - t.is(path, false); + t.is(link, "/build/index.html"); + t.is(path, "./test/stubs/_site/build/index.html"); +}); + +test("Permalink is an object but an empty object (inherit default behavior)", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-empty-object/empty-object.md", + "./test/stubs/", + "./test/stubs/_site" + ); + let data = await tmpl.getData(); + + let outputHref = await tmpl.getOutputHref(data); + t.is(outputHref, "/permalink-empty-object/empty-object/"); + + let outputLink = await tmpl.getOutputLink(data); + t.is(outputLink, "permalink-empty-object/empty-object/index.html"); + + let outputPath = await tmpl.getOutputPath(data); + t.is( + outputPath, + "./test/stubs/_site/permalink-empty-object/empty-object/index.html" + ); + + let { href, link, path } = await tmpl.getOutputLocations(data); + t.is(href, "/permalink-empty-object/empty-object/"); + t.is(link, "permalink-empty-object/empty-object/index.html"); + t.is( + path, + "./test/stubs/_site/permalink-empty-object/empty-object/index.html" + ); }); diff --git a/test/stubs/permalink-empty-object/empty-object.md b/test/stubs/permalink-empty-object/empty-object.md new file mode 100644 index 000000000..3c97bc7ad --- /dev/null +++ b/test/stubs/permalink-empty-object/empty-object.md @@ -0,0 +1,5 @@ +--- +permalink: {} +--- + +This should be the same as if permalink was not set at all. From 9936e25b7ba8abeb4d1297ed50163801d2de69f9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 23 Jun 2021 21:51:57 -0500 Subject: [PATCH 492/746] Prefer path to be included in the options object. --- src/Serverless.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Serverless.js b/src/Serverless.js index b2dcee1ec..3e2847ce0 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -9,7 +9,21 @@ const debug = require("debug")("Eleventy:Serverless"); class Serverless { constructor(name, path, options = {}) { this.name = name; - this.path = path; + + // second argument is path + if (typeof path === "string") { + this.path = path; + } else { + // options is the second argument and path is inside options + options = path; + this.path = options.path; + } + + if (!this.path) { + throw new Error( + "`path` must exist in the options argument in Eleventy Serverless." + ); + } // ServerlessBundlerPlugin hard-codes to this (even if you used a different file name) this.configFilename = "eleventy.config.js"; From 0e54cce4be241fe3fd72fedfb8ccae1b1840f223 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 23 Jun 2021 21:54:00 -0500 Subject: [PATCH 493/746] Generate serverless function file if one does not exist. --- .../DefaultServerlessFunctionContent.js | 51 ++++++++++++++++ src/Plugins/ServerlessBundlerPlugin.js | 61 +++++++++++++++---- 2 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 src/Plugins/DefaultServerlessFunctionContent.js diff --git a/src/Plugins/DefaultServerlessFunctionContent.js b/src/Plugins/DefaultServerlessFunctionContent.js new file mode 100644 index 000000000..47945cd43 --- /dev/null +++ b/src/Plugins/DefaultServerlessFunctionContent.js @@ -0,0 +1,51 @@ +const { EleventyServerless } = require("@11ty/eleventy"); + +// Explicit dependencies for the bundler from config file and global data. +// The file is generated by the Eleventy Serverless Bundler Plugin. +require("./eleventy-bundler-modules.js"); + +async function handler(event) { + let elev = new EleventyServerless("%%NAME%%", { + path: event.path, + query: event.queryStringParameters, + inputDir: "%%INPUT_DIR%%", + functionsDir: "%%FUNCTIONS_DIR%%", + }); + + try { + return { + statusCode: 200, + headers: { + "Content-Type": "text/html; charset=UTF-8", + }, + body: await elev.render(), + }; + } catch (error) { + // Only console log for matching serverless paths + // (otherwise you’ll see a bunch of BrowserSync 404s for non-dynamic URLs during --serve) + if (elev.isServerlessUrl(event.path)) { + console.log("Serverless Error:", error); + } + + return { + statusCode: error.httpStatusCode || 500, + body: JSON.stringify( + { + error: error.message, + }, + null, + 2 + ), + }; + } +} + +// Choose one: +// * Runs on each request: AWS Lambda (or Netlify Function) +// * Runs on first request only: Netlify On-demand Builder +// (don’t forget to `npm install @netlify/functions`) + +exports.handler = handler; + +//const { builder } = require("@netlify/functions"); +//exports.handler = builder(handler); diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 09766836f..183fa1203 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -1,4 +1,5 @@ const fs = require("fs"); +const fsp = fs.promises; const path = require("path"); const TOML = require("@iarna/toml"); const copy = require("recursive-copy"); @@ -159,7 +160,7 @@ class BundlerHelper { // we write this even when disabled because the serverless function expects it this.writeBundlerDependenciesFile( "eleventy-bundler-modules.js", - this.options.bundlerEnabled + this.options.copyEnabled ? [ "./eleventy-app-config-modules.js", "./eleventy-app-globaldata-modules.js", @@ -169,7 +170,7 @@ class BundlerHelper { } writeDependencyConfigFile(configPath) { - if (!this.options.bundlerEnabled) { + if (!this.options.copyEnabled) { return; } @@ -183,7 +184,7 @@ class BundlerHelper { } writeDependencyGlobalDataFile(globalDataFileList) { - if (!this.options.bundlerEnabled) { + if (!this.options.copyEnabled) { return; } @@ -225,9 +226,36 @@ class BundlerHelper { res.write(result.body); res.end(); - console.log(`Dynamic Render: ${req.url} (${Date.now() - start}ms)`); + console.log( + `Serverless (${this.name}): ${req.url} (${Date.now() - start}ms)` + ); }; } + + async ensureDir() { + return fsp.mkdir(this.getOutputPath(""), { + recursive: true, + }); + } + + async writeServerlessFunctionFile() { + let filepath = this.getOutputPath("index.js"); + if (!fs.existsSync(filepath)) { + let defaultContentPath = TemplatePath.absolutePath( + __dirname, + "./DefaultServerlessFunctionContent.js" + ); + + let contents = await fsp.readFile(defaultContentPath, "utf-8"); + contents = contents.replace(/\%\%NAME\%\%/g, this.name); + contents = contents.replace(/\%\%INPUT_DIR\%\%/g, this.options.inputDir); + contents = contents.replace( + /\%\%FUNCTIONS_DIR\%\%/g, + this.options.functionsDir + ); + return fsp.writeFile(filepath, contents); + } + } } function EleventyPlugin(eleventyConfig, options = {}) { @@ -249,7 +277,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { redirects: "netlify-toml", // Useful for local develop to disable all bundle copying - bundlerEnabled: true, + copyEnabled: true, + + // Input directory (used to generate the default serverless file) + inputDir: ".", }, options ); @@ -269,11 +300,13 @@ function EleventyPlugin(eleventyConfig, options = {}) { eleventyConfig.on("eleventy.before", async () => { helper.reset(); + await helper.ensureDir(); + await helper.writeServerlessFunctionFile(); helper.writeDependencyEntryFile(); }); eleventyConfig.on("eleventy.after", async () => { - if (!options.bundlerEnabled) { + if (!options.copyEnabled) { return; } @@ -303,12 +336,14 @@ function EleventyPlugin(eleventyConfig, options = {}) { ); }); - eleventyConfig.on("eleventy.env", (env) => { - if (options.bundlerEnabled) { + eleventyConfig.on("eleventy.env", async (env) => { + await helper.ensureDir(); + + if (options.copyEnabled) { helper.copyFile(env.config, "eleventy.config.js"); - } - helper.writeDependencyConfigFile(env.config); + helper.writeDependencyConfigFile(env.config); + } }); eleventyConfig.on("eleventy.globalDataFiles", (fileList) => { @@ -316,7 +351,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { }); eleventyConfig.on("eleventy.directories", async (dirs) => { - if (!options.bundlerEnabled) { + if (!options.copyEnabled) { return; } @@ -369,7 +404,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { this.copyCount++; // Write redirects (even if no redirects exist for this function to handle deletes) - if (options.bundlerEnabled && options.redirects) { + if (options.copyEnabled && options.redirects) { if ( typeof options.redirects === "string" && redirectHandlers[options.redirects] @@ -380,7 +415,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { } } - if (options.bundlerEnabled && mapEntryCount > 0) { + if (options.copyEnabled && mapEntryCount > 0) { // Copy templates to bundle folder for (let url in outputMap) { helper.recursiveCopy(outputMap[url]); From a38621303c9ef2132a64b1d022dad25ebf5b21bc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 23 Jun 2021 22:25:42 -0500 Subject: [PATCH 494/746] v1.0.0-canary.38 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 896932bb9..d41af6fe8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.37", + "version": "1.0.0-canary.38", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 571f8cf5bc124f7a0bd35d891797f377ddb54b0e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 25 Jun 2021 21:30:23 -0500 Subject: [PATCH 495/746] Data, Includes, and Layouts directories should not be required by the bundler. --- src/Plugins/ServerlessBundlerPlugin.js | 37 ++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 183fa1203..c46f2979f 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -1,6 +1,7 @@ const fs = require("fs"); const fsp = fs.promises; const path = require("path"); +const isGlob = require("is-glob"); const TOML = require("@iarna/toml"); const copy = require("recursive-copy"); const dependencyTree = require("@11ty/dependency-tree"); @@ -127,23 +128,25 @@ class BundlerHelper { } recursiveCopy(src, dest, options = {}) { - let finalDest = this.getOutputPath(dest || src); - return copy( - src, - finalDest, - Object.assign( - { - overwrite: true, - dot: true, - junk: false, - results: false, - }, - this.options.copyOptions, - options - ) - ).on(copy.events.COPY_FILE_COMPLETE, () => { - this.copyCount++; - }); + if (isGlob(src) || fs.existsSync(src)) { + let finalDest = this.getOutputPath(dest || src); + return copy( + src, + finalDest, + Object.assign( + { + overwrite: true, + dot: true, + junk: false, + results: false, + }, + this.options.copyOptions, + options + ) + ).on(copy.events.COPY_FILE_COMPLETE, () => { + this.copyCount++; + }); + } } writeBundlerDependenciesFile(filename, deps = []) { From 7c198625a477b030b83bf01d2f7d73cde8eb1b26 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 25 Jun 2021 22:13:33 -0500 Subject: [PATCH 496/746] I like this code better for: Data, Includes, and Layouts directories should not be required by the bundler. --- src/Plugins/ServerlessBundlerPlugin.js | 39 ++++++++++++++------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index c46f2979f..39432fb42 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -128,25 +128,28 @@ class BundlerHelper { } recursiveCopy(src, dest, options = {}) { - if (isGlob(src) || fs.existsSync(src)) { - let finalDest = this.getOutputPath(dest || src); - return copy( - src, - finalDest, - Object.assign( - { - overwrite: true, - dot: true, - junk: false, - results: false, - }, - this.options.copyOptions, - options - ) - ).on(copy.events.COPY_FILE_COMPLETE, () => { - this.copyCount++; - }); + // skip this one if not a glob and doesn’t exist + if (!isGlob(src) && !fs.existsSync(src)) { + return; } + + let finalDest = this.getOutputPath(dest || src); + return copy( + src, + finalDest, + Object.assign( + { + overwrite: true, + dot: true, + junk: false, + results: false, + }, + this.options.copyOptions, + options + ) + ).on(copy.events.COPY_FILE_COMPLETE, () => { + this.copyCount++; + }); } writeBundlerDependenciesFile(filename, deps = []) { From 56465a089da13ff30b443afdb4eb3101f7ba5094 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 25 Jun 2021 22:19:02 -0500 Subject: [PATCH 497/746] Fixes #1862 --- src/ComputedData.js | 12 +++++++++++- src/ComputedDataTemplateString.js | 4 ++-- src/Template.js | 2 +- test/ComputedDataTest.js | 19 +++++++++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/ComputedData.js b/src/ComputedData.js index 61560e4ab..e4831b646 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -8,18 +8,28 @@ const ComputedDataProxy = require("./ComputedDataProxy"); const debug = require("debug")("Eleventy:ComputedData"); class ComputedData { - constructor() { + constructor(config) { this.computed = {}; this.templateStringKeyLookup = {}; this.computedKeys = new Set(); this.declaredDependencies = {}; this.queue = new ComputedDataQueue(); + this.config = config; } add(key, fn, declaredDependencies = []) { this.computedKeys.add(key); this.declaredDependencies[key] = declaredDependencies; + // bind config filters/JS functions + if (typeof fn === "function") { + let fns = {}; + if (this.config) { + fns = this.config.javascriptFunctions; + } + fn = fn.bind(fns); + } + lodashSet(this.computed, key, fn); } diff --git a/src/ComputedDataTemplateString.js b/src/ComputedDataTemplateString.js index 6bc71268a..a513ac90f 100644 --- a/src/ComputedDataTemplateString.js +++ b/src/ComputedDataTemplateString.js @@ -16,8 +16,8 @@ class ComputedDataTemplateString { // is this ¯\_(lisp)_/¯ // must be strings that won’t be escaped by template languages - this.prefix = "(((((11ty((((("; - this.suffix = ")))))11ty)))))"; + this.prefix = "(((11ty((("; + this.suffix = ")))11ty)))"; } getProxyData() { diff --git a/src/Template.js b/src/Template.js index c37d717f2..6b8898c98 100755 --- a/src/Template.js +++ b/src/Template.js @@ -555,7 +555,7 @@ class Template extends TemplateContent { async addComputedData(data) { // will _not_ consume renderData - this.computedData = new ComputedData(); + this.computedData = new ComputedData(this.config); if (this.config.keys.computed in data) { // Note that `permalink` is only a thing that gets consumed—it does not go directly into generated data diff --git a/test/ComputedDataTest.js b/test/ComputedDataTest.js index 320a33653..7106e72bf 100644 --- a/test/ComputedDataTest.js +++ b/test/ComputedDataTest.js @@ -1,5 +1,6 @@ const test = require("ava"); const ComputedData = require("../src/ComputedData"); +const TemplateConfig = require("../src/TemplateConfig"); test("Basic get/set", async (t) => { let cd = new ComputedData(); @@ -393,3 +394,21 @@ test("Get var order and process it in two stages", async (t) => { // t.deepEqual(cd.queue.getOrder(), ["collections.all", "key1", "collections.dog", "key2", "key0"]); }); + +test("Use JavaScript functions (filters) in computed data functions", async (t) => { + let eleventyCfg = new TemplateConfig(); + let cfg = eleventyCfg.getConfig(); + cfg.javascriptFunctions.alwaysBlue = function (str) { + return str + " is blue"; + }; + let cd = new ComputedData(cfg); + + cd.add("key1", function (data) { + return this.alwaysBlue("this is a test"); + }); + + let data = {}; + await cd.setupData(data); + + t.is(data.key1, "this is a test is blue"); +}); From fccfd19a407288f374488f243c7f18b63f8ccfac Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 30 Jun 2021 08:53:30 -0500 Subject: [PATCH 498/746] =?UTF-8?q?Fix=20error=20message=20output=20in=20s?= =?UTF-8?q?uccessful=20log.=20Fix=20test=20with=20ENV=20variable=20failing?= =?UTF-8?q?=20in=20ava=E2=80=99s=20--serial=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Eleventy.js | 4 ++++ test/EleventyTest.js | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 92af6cf29..49db4710e 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -450,6 +450,10 @@ Verbose Output: ${this.verboseMode}`); this._logger = logger; } + disableLogger() { + this._logger.overrideLogger(false); + } + /* Getter for error handler */ get errorHandler() { if (!this._errorHandler) { diff --git a/test/EleventyTest.js b/test/EleventyTest.js index ee90de111..5e8252096 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -45,10 +45,10 @@ test("Eleventy set input/output", async (t) => { }); test("Eleventy process.ENV", async (t) => { - let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); - - process.env.ELEVENTY_ROOT = ""; + delete process.env.ELEVENTY_ROOT; t.falsy(process.env.ELEVENTY_ROOT); + + let elev = new Eleventy("./test/stubs", "./test/stubs/_site"); await elev.init(); t.truthy(process.env.ELEVENTY_ROOT); @@ -154,6 +154,7 @@ test("Eleventy set input/output, one file input exitCode", async (t) => { "./test/stubs/exitCode/_site" ); elev.setIsVerbose(false); + elev.disableLogger(); await elev.init(); await elev.write(); From e7811f43b80340eda349493327cdef402c7c5940 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 30 Jun 2021 10:06:41 -0500 Subject: [PATCH 499/746] Get those console logs out of the tests. --- package.json | 1 + src/Eleventy.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d41af6fe8..993e39741 100755 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "bugs": "https://github.com/11ty/eleventy/issues", "homepage": "https://www.11ty.dev/", "ava": { + "environmentVariables": {}, "failFast": false, "files": [ "./test/*.js" diff --git a/src/Eleventy.js b/src/Eleventy.js index 49db4710e..1ed6f6cbb 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -477,6 +477,7 @@ Verbose Output: ${this.verboseMode}`); isVerbose = false; } + bench.setVerboseOutput(isVerbose); this.verboseMode = isVerbose; } @@ -938,7 +939,6 @@ Arguments: }; this.errorHandler.fatal(e, "Problem writing Eleventy templates"); } finally { - // Note, this executes even though we return above in `catch` bench.finish(); if (to === "fs") { this.logger.message( @@ -953,9 +953,9 @@ Arguments: debug(` Getting frustrated? Have a suggestion/feature request/feedback? I want to hear it! Open an issue: https://github.com/11ty/eleventy/issues/new`); - - return ret; } + + return ret; } } From 6a9c03e4815b1baf08883661e71a3f90df8dc7d2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 30 Jun 2021 11:28:27 -0500 Subject: [PATCH 500/746] Use the parser to determine the symbols used in a template string (Nunjucks-only so far). This avoids using the double function execution hack and will be more reliable with things that use filters. --- src/ComputedData.js | 37 ++++++++++++++++++------ src/Engines/Nunjucks.js | 34 ++++++++++++++++++++++ src/Template.js | 11 ++++--- src/TemplateContent.js | 12 ++++++++ test/TemplateRenderNunjucksTest.js | 25 ++++++++++++++++ test/TemplateTest-ComputedData.js | 21 +++++++++++++- test/stubs-computed-symbolparse/test.njk | 6 ++++ 7 files changed, 132 insertions(+), 14 deletions(-) create mode 100644 test/stubs-computed-symbolparse/test.njk diff --git a/src/ComputedData.js b/src/ComputedData.js index e4831b646..0cc74f6e7 100644 --- a/src/ComputedData.js +++ b/src/ComputedData.js @@ -10,6 +10,7 @@ const debug = require("debug")("Eleventy:ComputedData"); class ComputedData { constructor(config) { this.computed = {}; + this.symbolParseFunctions = {}; this.templateStringKeyLookup = {}; this.computedKeys = new Set(); this.declaredDependencies = {}; @@ -17,24 +18,33 @@ class ComputedData { this.config = config; } - add(key, fn, declaredDependencies = []) { + add(key, renderFn, declaredDependencies = [], symbolParseFn = undefined) { this.computedKeys.add(key); this.declaredDependencies[key] = declaredDependencies; // bind config filters/JS functions - if (typeof fn === "function") { + if (typeof renderFn === "function") { let fns = {}; if (this.config) { fns = this.config.javascriptFunctions; } - fn = fn.bind(fns); + renderFn = renderFn.bind(fns); } - lodashSet(this.computed, key, fn); + lodashSet(this.computed, key, renderFn); + + if (symbolParseFn) { + lodashSet(this.symbolParseFunctions, key, symbolParseFn); + } } - addTemplateString(key, fn, declaredDependencies = []) { - this.add(key, fn, declaredDependencies); + addTemplateString( + key, + renderFn, + declaredDependencies = [], + symbolParseFn = undefined + ) { + this.add(key, renderFn, declaredDependencies, symbolParseFn); this.templateStringKeyLookup[key] = true; } @@ -49,13 +59,22 @@ class ComputedData { if (typeof computed !== "function") { // add nodes for non functions (primitives like booleans, etc) + // This will not handle template strings, as they are normalized to functions this.queue.addNode(key); } else { this.queue.uses(key, this.declaredDependencies[key]); - let isTemplateString = !!this.templateStringKeyLookup[key]; - let proxy = isTemplateString ? proxyByTemplateString : proxyByProxy; - let varsUsed = await proxy.findVarsUsed(computed, data); + let symbolParseFn = lodashGet(this.symbolParseFunctions, key); + let varsUsed = []; + if (symbolParseFn) { + // use the parseForSymbols function in the TemplateEngine + varsUsed = symbolParseFn(); + } else if (symbolParseFn !== false) { + // skip resolution is this is false (just use declaredDependencies) + let isTemplateString = !!this.templateStringKeyLookup[key]; + let proxy = isTemplateString ? proxyByTemplateString : proxyByProxy; + varsUsed = await proxy.findVarsUsed(computed, data); + } debug("%o accesses %o variables", key, varsUsed); let filteredVarsUsed = varsUsed.filter((varUsed) => { diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 1c6fe5be9..229bad3e8 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -1,4 +1,6 @@ const NunjucksLib = require("nunjucks"); +const parser = NunjucksLib.parser; +const nodes = NunjucksLib.nodes; const TemplateEngine = require("./TemplateEngine"); const TemplatePath = require("../TemplatePath"); const EleventyErrorUtil = require("../EleventyErrorUtil"); @@ -358,6 +360,37 @@ class Nunjucks extends TemplateEngine { ); } + /* Outputs an Array of lodash.get selectors */ + parseForSymbols(str) { + let obj = parser.parse(str); + let linesplit = str.split("\n"); + let values = obj.findAll(nodes.Value); + let symbols = obj.findAll(nodes.Symbol).map((entry) => { + let name = [entry.value]; + let nestedIndex = -1; + for (let val of values) { + if (nestedIndex > -1) { + /* deep.object.syntax */ + if (linesplit[val.lineno].charAt(nestedIndex) === ".") { + name.push(val.value); + nestedIndex += val.value.length + 1; + } else { + nestedIndex = -1; + } + } else if ( + val.lineno === entry.lineno && + val.colno === entry.colno && + val.value === entry.value + ) { + nestedIndex = entry.colno + entry.value.length; + } + } + return name.join("."); + }); + + return symbols; + } + async compile(str, inputPath) { if (!this.needsCompilation(str)) { return async function () { @@ -375,6 +408,7 @@ class Nunjucks extends TemplateEngine { } else { tmpl = new NunjucksLib.Template(str, this.njkEnv, inputPath, true); } + return async function (data) { return new Promise(function (resolve, reject) { tmpl.render(data, function (err, res) { diff --git a/src/Template.js b/src/Template.js index 6b8898c98..2f6b7a4f2 100755 --- a/src/Template.js +++ b/src/Template.js @@ -543,9 +543,10 @@ class Template extends TemplateContent { computedData.addTemplateString( parentKey, async (innerData) => { - return await super.render(obj, innerData, true); + return await this.renderComputedData(obj, innerData, true); }, - declaredDependencies + declaredDependencies, + this.getParseForSymbolsFunction(obj) ); } else { // Numbers, booleans, etc @@ -564,13 +565,15 @@ class Template extends TemplateContent { this.computedData.addTemplateString( "page.url", async (data) => await this.getOutputHref(data), - data.permalink ? ["permalink"] : undefined + data.permalink ? ["permalink"] : undefined, + false // skip symbol resolution ); this.computedData.addTemplateString( "page.outputPath", async (data) => await this.getOutputPath(data), - data.permalink ? ["permalink"] : undefined + data.permalink ? ["permalink"] : undefined, + false // skip symbol resolution ); // actually add the computed data diff --git a/src/TemplateContent.js b/src/TemplateContent.js index c89388c5e..fc478daf7 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -282,6 +282,18 @@ class TemplateContent { } } + getParseForSymbolsFunction(str) { + if ("parseForSymbols" in this.engine) { + return () => { + return this.engine.parseForSymbols(str); + }; + } + } + + async renderComputedData(str, data) { + return this._render(str, data, true); + } + async renderPermalink(permalink, data, bypassMarkdown) { return this._render(permalink, data, bypassMarkdown); } diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 5738268b8..20767e6d3 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -805,3 +805,28 @@ test("Nunjucks bypass compilation", async (t) => { t.is(tr.engine.needsCompilation("

{% tag %}{% endtag %}

"), true); t.is(tr.engine.needsCompilation("

test

"), false); }); + +test("Nunjucks Parse for Symbols", async (t) => { + let tr = getNewTemplateRender("njk"); + let engine = tr.engine; + + t.deepEqual(engine.parseForSymbols("

{{ name }}

"), ["name"]); + t.deepEqual(engine.parseForSymbols("

{{ eleventy.deep.nested }}

"), [ + "eleventy.deep.nested", + ]); + t.deepEqual(engine.parseForSymbols("

{{ a }} {{ b }}

"), ["a", "b"]); + t.deepEqual( + engine.parseForSymbols("

{% if true %}{{ c }}{% endif %}

"), + ["c"] + ); + t.deepEqual( + engine.parseForSymbols("

{% if false %}{{ c }}{% endif %}

"), + ["c"] + ); + t.deepEqual(engine.parseForSymbols("{{ collections.all[0] }}>"), [ + "collections.all", + ]); + t.deepEqual(engine.parseForSymbols("{{ collections.mine }}>"), [ + "collections.mine", + ]); +}); diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index 4a5c74b8f..8eb755738 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -1,5 +1,4 @@ const test = require("ava"); -const Template = require("../src/Template"); const TemplateData = require("../src/TemplateData"); const getNewTemplate = require("./_getNewTemplateForTests"); const TemplateConfig = require("../src/TemplateConfig"); @@ -167,3 +166,23 @@ test("eleventyComputed intermixes with global data", async (t) => { t.is(data.image3, "third-global"); t.is(data.eleventyNavigation.key, "nested-first-global"); }); + +test("eleventyComputed using symbol parsing on template strings", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs-computed-symbolparse/test.njk", + "./test/stubs-computed-symbolparse/", + "./test/stubs-computed-symbolparse/_site" + ); + tmpl.config.nunjucksFilters.fail = function (str) { + // Filter expects a certain String format, don’t use the (((11ty))) string hack + if (!str || str.length !== 1) { + throw new Error("Expect a one character string"); + } + return `${str}`; + }; + + let data = await getRenderedData(tmpl); + t.is(data.a, "a"); + t.is(data.b, "b"); + t.is(data.c, "ab"); +}); diff --git a/test/stubs-computed-symbolparse/test.njk b/test/stubs-computed-symbolparse/test.njk new file mode 100644 index 000000000..5de08120f --- /dev/null +++ b/test/stubs-computed-symbolparse/test.njk @@ -0,0 +1,6 @@ +--- +eleventyComputed: + c: "{{ a | fail }}{{ b | fail }}" + a: "a" + b: "b" +--- \ No newline at end of file From 9c83e5bc513d66631f2711dac1762725b7f9327a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 30 Jun 2021 11:28:45 -0500 Subject: [PATCH 501/746] Move a few tests to a separate file. --- test/TemplateTest.js | 121 -------------------------------- test/TemplateTest_Permalink.js | 124 +++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 121 deletions(-) create mode 100644 test/TemplateTest_Permalink.js diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 46ddff515..8c590884a 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1,5 +1,4 @@ const test = require("ava"); -const fs = require("fs-extra"); const fsp = require("fs").promises; const pretty = require("pretty"); @@ -19,37 +18,6 @@ async function getRenderedData(tmpl, pageNumber = 0) { return templates[pageNumber].data; } -async function getTemplateMapEntriesWithContent(template, data) { - let entries = await template.getTemplateMapEntries(data); - - return Promise.all( - entries.map(async (entry) => { - entry._pages = await entry.template.getTemplates(entry.data); - await Promise.all( - entry._pages.map(async (page) => { - page.templateContent = await entry.template.getTemplateMapContent( - page - ); - return page; - }) - ); - return entry; - }) - ); -} - -async function writeMapEntries(mapEntries) { - let promises = []; - for (let entry of mapEntries) { - if (entry.template.behavior.isWriteable()) { - promises.push( - entry.template._write(entry.outputPath, entry.templateContent) - ); - } - } - return Promise.all(promises); -} - function cleanHtml(str) { return pretty(str, { ocd: true }); } @@ -1375,95 +1343,6 @@ test("Test a linter", async (t) => { await tmpl._testCompleteRender(); }); -test("permalink: false", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/permalink-false/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/"), true); - t.is(fs.existsSync("./test/stubs/permalink-false/test.md"), true); - - // Output does not exist - t.is(fs.existsSync("./test/stubs/_site/permalink-false/"), false); - t.is(fs.existsSync("./test/stubs/_site/permalink-false/test/"), false); - t.is( - fs.existsSync("./test/stubs/_site/permalink-false/test/index.html"), - false - ); -}); - -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", - "./test/stubs/", - "./test/stubs/_site" - ); - - let data = await tmpl.getData(); - await t.throwsAsync(async () => { - await tmpl.getOutputLink(data); - }); -}); - -test("Disable dynamic permalinks", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/dynamic-permalink/test.njk", - "./test/stubs/", - "./test/stubs/_site" - ); - - t.is(await tmpl.getOutputLink(), "/{{justastring}}/index.html"); - t.is(await tmpl.getOutputHref(), "/{{justastring}}/"); -}); - test("Front Matter Tags (Single)", async (t) => { let tmpl = getNewTemplate( "./test/stubs/templatetest-frontmatter/single.njk", diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js new file mode 100644 index 000000000..71fc79683 --- /dev/null +++ b/test/TemplateTest_Permalink.js @@ -0,0 +1,124 @@ +const test = require("ava"); +const fs = require("fs"); + +const getNewTemplate = require("./_getNewTemplateForTests"); + +async function writeMapEntries(mapEntries) { + let promises = []; + for (let entry of mapEntries) { + if (entry.template.behavior.isWriteable()) { + promises.push( + entry.template._write(entry.outputPath, entry.templateContent) + ); + } + } + return Promise.all(promises); +} + +async function getTemplateMapEntriesWithContent(template, data) { + let entries = await template.getTemplateMapEntries(data); + + return Promise.all( + entries.map(async (entry) => { + entry._pages = await entry.template.getTemplates(entry.data); + await Promise.all( + entry._pages.map(async (page) => { + page.templateContent = await entry.template.getTemplateMapContent( + page + ); + return page; + }) + ); + return entry; + }) + ); +} + +test("permalink: false", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalink-false/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/"), true); + t.is(fs.existsSync("./test/stubs/permalink-false/test.md"), true); + + // Output does not exist + t.is(fs.existsSync("./test/stubs/_site/permalink-false/"), false); + t.is(fs.existsSync("./test/stubs/_site/permalink-false/test/"), false); + t.is( + fs.existsSync("./test/stubs/_site/permalink-false/test/index.html"), + false + ); +}); + +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", + "./test/stubs/", + "./test/stubs/_site" + ); + + let data = await tmpl.getData(); + await t.throwsAsync(async () => { + await tmpl.getOutputLink(data); + }); +}); + +test("Disable dynamic permalinks", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/dynamic-permalink/test.njk", + "./test/stubs/", + "./test/stubs/_site" + ); + + t.is(await tmpl.getOutputLink(), "/{{justastring}}/index.html"); + t.is(await tmpl.getOutputHref(), "/{{justastring}}/"); +}); From 79245d85bcfba3ce8e8b75d84315c6c5bd81bbd3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 30 Jun 2021 14:36:40 -0500 Subject: [PATCH 502/746] Add AST traversal for Liquid strings in eleventyComputed --- src/Engines/Liquid.js | 12 ++++++++ src/Engines/Nunjucks.js | 2 +- test/TemplateRenderLiquidTest.js | 31 +++++++++++++++++++++ test/TemplateRenderNunjucksTest.js | 7 +++++ test/TemplateTest-ComputedData.js | 22 ++++++++++++++- test/stubs-computed-symbolparse/test.liquid | 6 ++++ 6 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 test/stubs-computed-symbolparse/test.liquid diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 536d0f699..743b8667f 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -203,6 +203,18 @@ class Liquid extends TemplateEngine { }); } + parseForSymbols(str) { + let tokenizer = new liquidLib.Tokenizer(str); + let tokens = tokenizer.readTopLevelTokens(); + let symbols = tokens + .filter((token) => token.kind === liquidLib.TokenKind.Output) + .map((token) => { + // manually remove filters 😅 + return token.content.split("|").map((entry) => entry.trim())[0]; + }); + return symbols; + } + needsCompilation(str) { let options = this.liquidLib.options; diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 229bad3e8..1c5133cbe 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -388,7 +388,7 @@ class Nunjucks extends TemplateEngine { return name.join("."); }); - return symbols; + return Array.from(new Set(symbols)); } async compile(str, inputPath) { diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index ec99a850c..3fbafc0fa 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1046,3 +1046,34 @@ test("Liquid reverse filter in {% for %}", async (t) => { ); t.is(await fn({ test: [1, 2, 3] }), "321"); }); + +test("Liquid Parse for Symbols", async (t) => { + let tr = getNewTemplateRender("liquid"); + let engine = tr.engine; + + t.deepEqual(engine.parseForSymbols("

{{ name }}

"), ["name"]); + t.deepEqual(engine.parseForSymbols("

{{ eleventy.deep.nested }}

"), [ + "eleventy.deep.nested", + ]); + t.deepEqual(engine.parseForSymbols("

{{ a }} {{ b }}

"), ["a", "b"]); + t.deepEqual( + engine.parseForSymbols("

{% if true %}{{ c }}{% endif %}

"), + ["c"] + ); + t.deepEqual( + engine.parseForSymbols("

{% if false %}{{ c }}{% endif %}

"), + ["c"] + ); + + t.deepEqual(engine.parseForSymbols("{{ collections.all[0] }}>"), [ + // Note that the Nunjucks parser returns collections.all + "collections.all[0]", + ]); + t.deepEqual(engine.parseForSymbols("{{ collections.mine }}>"), [ + "collections.mine", + ]); + + t.deepEqual(engine.parseForSymbols("{{ collections.mine | test }}>"), [ + "collections.mine", + ]); +}); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 20767e6d3..bffd73756 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -824,9 +824,16 @@ test("Nunjucks Parse for Symbols", async (t) => { ["c"] ); t.deepEqual(engine.parseForSymbols("{{ collections.all[0] }}>"), [ + // Note that the Liquid parser returns collections.all[0] "collections.all", ]); t.deepEqual(engine.parseForSymbols("{{ collections.mine }}>"), [ "collections.mine", ]); + + t.deepEqual(engine.parseForSymbols("{{ collections.mine | test }}>"), [ + // TODO not ideal to have `test` in here? + "test", + "collections.mine", + ]); }); diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index 8eb755738..06a74b70c 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -167,7 +167,7 @@ test("eleventyComputed intermixes with global data", async (t) => { t.is(data.eleventyNavigation.key, "nested-first-global"); }); -test("eleventyComputed using symbol parsing on template strings", async (t) => { +test("eleventyComputed using symbol parsing on template strings (nunjucks)", async (t) => { let tmpl = getNewTemplate( "./test/stubs-computed-symbolparse/test.njk", "./test/stubs-computed-symbolparse/", @@ -186,3 +186,23 @@ test("eleventyComputed using symbol parsing on template strings", async (t) => { t.is(data.b, "b"); t.is(data.c, "ab"); }); + +test.skip("eleventyComputed using symbol parsing on template strings (liquid)", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs-computed-symbolparse/test.liquid", + "./test/stubs-computed-symbolparse/", + "./test/stubs-computed-symbolparse/_site" + ); + tmpl.config.liquidFilters.fail = function (str) { + // Filter expects a certain String format, don’t use the (((11ty))) string hack + if (!str || str.length !== 1) { + throw new Error("Expect a one character string: " + str); + } + return `${str}`; + }; + + let data = await getRenderedData(tmpl); + t.is(data.a, "a"); + t.is(data.b, "b"); + t.is(data.c, "ab"); +}); diff --git a/test/stubs-computed-symbolparse/test.liquid b/test/stubs-computed-symbolparse/test.liquid new file mode 100644 index 000000000..5de08120f --- /dev/null +++ b/test/stubs-computed-symbolparse/test.liquid @@ -0,0 +1,6 @@ +--- +eleventyComputed: + c: "{{ a | fail }}{{ b | fail }}" + a: "a" + b: "b" +--- \ No newline at end of file From 84449ab597302a87975f32e6b25ca3f555907d11 Mon Sep 17 00:00:00 2001 From: Holben888 Date: Wed, 30 Jun 2021 19:00:49 -0500 Subject: [PATCH 503/746] Feat: Allow default engine overrides using addExtension --- src/Engines/Custom.js | 31 ++++++++++++++- src/TemplateEngineManager.js | 73 ++++++++++++++++++++++++------------ 2 files changed, 77 insertions(+), 27 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index e2e910639..8503435ed 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -10,6 +10,8 @@ class CustomEngine extends TemplateEngine { "init" in this.entry && typeof this.entry.init === "function"; this.initStarted = false; this.initFinished = false; + + this._defaultEngine = undefined; } getExtensionMapEntry() { @@ -26,6 +28,10 @@ class CustomEngine extends TemplateEngine { ); } + setDefaultEngine(defaultEngine) { + this._defaultEngine = defaultEngine; + } + needsToReadFileContents() { if ("read" in this.entry) { return this.entry.read; @@ -67,11 +73,32 @@ class CustomEngine extends TemplateEngine { } } - async compile(str, inputPath) { + async compile(str, inputPath, ...args) { await this._runningInit(); + let defaultCompiler; + if (this._defaultEngine) { + defaultCompiler = async (data) => { + const render = await this._defaultEngine.compile( + str, + inputPath, + ...args + ); + return await render(data); + }; + } + + // Fall back to default compiler if the user does not provide their own + if (!this.entry.compile && defaultCompiler) { + return defaultCompiler; + } + // TODO generalize this (look at JavaScript.js) - return this.entry.compile.bind({ config: this.config })(str, inputPath); + return this.entry.compile.bind({ config: this.config })( + str, + inputPath, + defaultCompiler + ); } get defaultTemplateFileExtension() { diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 0540e2412..ed1202241 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -45,6 +45,33 @@ class TemplateEngineManager { return !!this.getClassNameFromTemplateKey(name); } + getEngineClassByExtension(extension) { + // We include these as raw strings (and not more readable variables) so they’re parsed by the bundler. + if (extension === "ejs") { + return require("./Engines/Ejs"); + } else if (extension === "md") { + return require("./Engines/Markdown"); + } else if (extension === "html") { + return require("./Engines/Html"); + } else if (extension === "hbs") { + return require("./Engines/Handlebars"); + } else if (extension === "mustache") { + return require("./Engines/Mustache"); + } else if (extension === "haml") { + return require("./Engines/Haml"); + } else if (extension === "pug") { + return require("./Engines/Pug"); + } else if (extension === "njk") { + return require("./Engines/Nunjucks"); + } else if (extension === "liquid") { + return require("./Engines/Liquid"); + } else if (extension === "11ty.js") { + return require("./Engines/JavaScript"); + } else { + return require("./Engines/Custom"); + } + } + getEngine(name, includesDir, extensionMap) { if (!this.hasEngine(name)) { throw new Error( @@ -56,36 +83,32 @@ class TemplateEngineManager { return this.engineCache[name]; } - let cls; - // We include these as raw strings (and not more readable variables) so they’re parsed by the bundler. - if (name === "ejs") { - cls = require("./Engines/Ejs"); - } else if (name === "md") { - cls = require("./Engines/Markdown"); - } else if (name === "html") { - cls = require("./Engines/Html"); - } else if (name === "hbs") { - cls = require("./Engines/Handlebars"); - } else if (name === "mustache") { - cls = require("./Engines/Mustache"); - } else if (name === "haml") { - cls = require("./Engines/Haml"); - } else if (name === "pug") { - cls = require("./Engines/Pug"); - } else if (name === "njk") { - cls = require("./Engines/Nunjucks"); - } else if (name === "liquid") { - cls = require("./Engines/Liquid"); - } else if (name === "11ty.js") { - cls = require("./Engines/JavaScript"); - } else { - cls = require("./Engines/Custom"); - } + let cls = this.getEngineClassByExtension(name); let instance = new cls(name, includesDir, this.config); instance.extensionMap = extensionMap; instance.engineManager = this; + // If the user providers a "Custom" engine using addExtension, + // But that engine's instance is *not* custom, + // The user must be overriding an existing engine + // i.e. addExtension('md', function overrideBehavior() {...}) + if ( + this.getClassNameFromTemplateKey(name) === "Custom" && + instance.constructor.name !== "CustomEngine" + ) { + const CustomEngine = require("./Engines/Custom"); + const overrideCustomEngine = new CustomEngine( + name, + includesDir, + this.config + ); + // 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); + instance = overrideCustomEngine; + } + // Make sure cache key is based on name and not path // Custom class is used for all plugins, cache once per plugin this.engineCache[name] = instance; From c3b7deab7d3038e4dddffb43bdfbeb150c414579 Mon Sep 17 00:00:00 2001 From: Holben888 Date: Wed, 30 Jun 2021 19:01:20 -0500 Subject: [PATCH 504/746] feat: add unit tests for engine overrides --- test/TemplateRenderCustomTest.js | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index b0fc3a5d5..eed501669 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -34,6 +34,70 @@ test("Custom plaintext Render", async (t) => { t.is(await fn({}), "

Paragraph

"); }); +test("Custom Markdown Render with `compile` override", async (t) => { + let eleventyConfig = new TemplateConfig(); + + eleventyConfig.userConfig.extensionMap.add({ + extension: "md", + key: "md", + compile: function (str, inputPath) { + return function (data) { + return `${str.trim()}`; + }; + }, + }); + + let tr = getNewTemplateRender("md", null, eleventyConfig); + + let fn = await tr.getCompiledTemplate("# Markdown?"); + t.is((await fn()).trim(), "# Markdown?"); + t.is((await fn({})).trim(), "# Markdown?"); +}); + +test("Custom Markdown Render without `compile` override", async (t) => { + let eleventyConfig = new TemplateConfig(); + let initCalled = false; + + eleventyConfig.userConfig.extensionMap.add({ + extension: "md", + key: "md", + init: function () { + initCalled = true; + }, + }); + + let tr = getNewTemplateRender("md", null, eleventyConfig); + + let fn = await tr.getCompiledTemplate("# Header"); + t.is(initCalled, true); + t.is((await fn()).trim(), "

Header

"); + t.is((await fn({})).trim(), "

Header

"); +}); + +test("Custom Markdown Render with `compile` override + call to default compiler", async (t) => { + let eleventyConfig = new TemplateConfig(); + + eleventyConfig.userConfig.extensionMap.add({ + extension: "md", + key: "md", + compile: function (str, inputPath, defaultCompiler) { + return async function (data) { + const result = await defaultCompiler(data); + return `${result.trim()}`; + }; + }, + }); + + let tr = getNewTemplateRender("md", null, eleventyConfig); + + let fn = await tr.getCompiledTemplate("Hey {{name}}"); + t.is((await fn()).trim(), "

Hey

"); + t.is( + (await fn({ name: "Zach" })).trim(), + "

Hey Zach

" + ); +}); + test("Custom Vue Render", async (t) => { let tr = getNewTemplateRender("vue"); From 236afeee4b1c22cc7db0f09a49c4053746cc066f Mon Sep 17 00:00:00 2001 From: Holben888 Date: Thu, 1 Jul 2021 09:52:29 -0500 Subject: [PATCH 505/746] refactor: move defaultCompiler to "this" context --- src/Engines/Custom.js | 10 +++++----- test/TemplateRenderCustomTest.js | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 8503435ed..d62d47562 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -94,11 +94,11 @@ class CustomEngine extends TemplateEngine { } // TODO generalize this (look at JavaScript.js) - return this.entry.compile.bind({ config: this.config })( - str, - inputPath, - defaultCompiler - ); + return this.entry.compile + // give the user access to this engine's default compiler, if any + .bind({ config: this.config, defaultCompiler })(str, inputPath) + // bind again for access inside function (data) {...} + .bind({ defaultCompiler }); } get defaultTemplateFileExtension() { diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index eed501669..2a0dd3bc8 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -80,9 +80,9 @@ test("Custom Markdown Render with `compile` override + call to default compiler" eleventyConfig.userConfig.extensionMap.add({ extension: "md", key: "md", - compile: function (str, inputPath, defaultCompiler) { + compile: function (str, inputPath) { return async function (data) { - const result = await defaultCompiler(data); + const result = await this.defaultCompiler(data); return `${result.trim()}`; }; }, From 375aec479be5ab608aea11162f2dbf742820e7b7 Mon Sep 17 00:00:00 2001 From: Benjamin Holmes Date: Thu, 1 Jul 2021 10:01:32 -0500 Subject: [PATCH 506/746] Update comment in src/TemplateEngineManager.js --- src/TemplateEngineManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index ed1202241..8b0756bd1 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -92,7 +92,7 @@ class TemplateEngineManager { // If the user providers a "Custom" engine using addExtension, // But that engine's instance is *not* custom, // The user must be overriding an existing engine - // i.e. addExtension('md', function overrideBehavior() {...}) + // i.e. addExtension('md', { ...overrideBehavior }) if ( this.getClassNameFromTemplateKey(name) === "Custom" && instance.constructor.name !== "CustomEngine" From 8a6b7bff65334c2edba08905b93a62dfb5823449 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 1 Jul 2021 15:09:04 -0500 Subject: [PATCH 507/746] Nunjucks parser needs to know about custom tags (shortcodes) --- src/Engines/Nunjucks.js | 61 ++++++++++++++++++++++++------ test/TemplateRenderNunjucksTest.js | 8 ++++ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 1c5133cbe..8916cc254 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -1,6 +1,4 @@ const NunjucksLib = require("nunjucks"); -const parser = NunjucksLib.parser; -const nodes = NunjucksLib.nodes; const TemplateEngine = require("./TemplateEngine"); const TemplatePath = require("../TemplatePath"); const EleventyErrorUtil = require("../EleventyErrorUtil"); @@ -206,8 +204,8 @@ class Nunjucks extends TemplateEngine { return obj; } - addShortcode(shortcodeName, shortcodeFn, isAsync = false) { - function ShortcodeFunction() { + _getShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) { + return function ShortcodeFunction() { this.tags = [shortcodeName]; this.parse = function (parser, nodes) { @@ -271,13 +269,11 @@ class Nunjucks extends TemplateEngine { } } }; - } - - this.njkEnv.addExtension(shortcodeName, new ShortcodeFunction()); + }; } - addPairedShortcode(shortcodeName, shortcodeFn, isAsync = false) { - function PairedShortcodeFunction() { + _getPairedShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) { + return function PairedShortcodeFunction() { this.tags = [shortcodeName]; this.parse = function (parser, nodes) { @@ -341,9 +337,17 @@ class Nunjucks extends TemplateEngine { } } }; - } + }; + } + + addShortcode(shortcodeName, shortcodeFn, isAsync = false) { + let fn = this._getShortcodeFn(shortcodeName, shortcodeFn, isAsync); + this.njkEnv.addExtension(shortcodeName, new fn()); + } - this.njkEnv.addExtension(shortcodeName, new PairedShortcodeFunction()); + addPairedShortcode(shortcodeName, shortcodeFn, isAsync = false) { + let fn = this._getPairedShortcodeFn(shortcodeName, shortcodeFn, isAsync); + this.njkEnv.addExtension(shortcodeName, new fn()); } needsCompilation(str) { @@ -360,9 +364,42 @@ class Nunjucks extends TemplateEngine { ); } + _getParseExtensions() { + if (this._parseExtensions) { + return this._parseExtensions; + } + + // add extensions so the parser knows about our custom tags/blocks + let ext = []; + for (let name in this.config.nunjucksTags) { + let fn = this._getShortcodeFn(name, () => {}); + ext.push(new fn()); + } + for (let name in this.config.nunjucksShortcodes) { + let fn = this._getShortcodeFn(name, () => {}); + ext.push(new fn()); + } + for (let name in this.config.nunjucksAsyncShortcodes) { + let fn = this._getShortcodeFn(name, () => {}, true); + ext.push(new fn()); + } + for (let name in this.config.nunjucksPairedShortcodes) { + let fn = this._getPairedShortcodeFn(name, () => {}); + ext.push(new fn()); + } + for (let name in this.config.nunjucksAsyncPairedShortcodes) { + let fn = this._getPairedShortcodeFn(name, () => {}, true); + ext.push(new fn()); + } + + this._parseExtensions = ext; + return ext; + } + /* Outputs an Array of lodash.get selectors */ parseForSymbols(str) { - let obj = parser.parse(str); + const { parser, nodes } = NunjucksLib; + let obj = parser.parse(str, this._getParseExtensions()); let linesplit = str.split("\n"); let values = obj.findAll(nodes.Value); let symbols = obj.findAll(nodes.Symbol).map((entry) => { diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index bffd73756..c147400ca 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -837,3 +837,11 @@ test("Nunjucks Parse for Symbols", async (t) => { "collections.mine", ]); }); + +test("Nunjucks Parse for Symbols with custom block", async (t) => { + let tr = getNewTemplateRender("njk"); + let engine = tr.engine; + engine.config.nunjucksShortcodes.test = function () {}; + + t.deepEqual(engine.parseForSymbols("

{{ name }} {% test %}

"), ["name"]); +}); From 89fd4a2e549f5a9a9061c6e8891ee128110389fa Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 1 Jul 2021 16:27:43 -0500 Subject: [PATCH 508/746] Move a few tests --- test/TemplateTest.js | 64 -------------------------------- test/TemplateTest_Permalink.js | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 64 deletions(-) diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 8c590884a..2fe3b499a 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -593,70 +593,6 @@ test("Clone the template", async (t) => { t.is(cloned.extensionMap, tmpl.extensionMap); }); -test("Permalink with variables!", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/permalinkdata.njk", - "./test/stubs/", - "./dist" - ); - - t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-candidate/index.html"); -}); - -test("Permalink with variables and JS front matter!", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/permalinkdata-jsfn.njk", - "./test/stubs/", - "./dist" - ); - - t.is(await tmpl.getOutputPath(), "./dist/subdir/slug/index.html"); -}); - -// This is broken right now, permalink must use the same template language as the template -test.skip("Use a JavaScript function for permalink in any template language", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/permalinkdata-jspermalinkfn.njk", - "./test/stubs/", - "./dist" - ); - - t.is(await tmpl.getOutputPath(), "./dist/subdir/slug/index.html"); -}); - -test("Permalink with dates!", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/permalinkdate.liquid", - "./test/stubs/", - "./dist" - ); - - t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); -}); - -test("Permalink with dates on file name regex!", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/2016-02-01-permalinkdate.liquid", - "./test/stubs/", - "./dist" - ); - - t.is(await tmpl.getOutputPath(), "./dist/2016/02/01/index.html"); -}); - -test("Reuse permalink in directory specific data file", async (t) => { - let eleventyConfig = new TemplateConfig(); - let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - let tmpl = getNewTemplate( - "./test/stubs/reuse-permalink/test1.liquid", - "./test/stubs/", - "./dist", - dataObj - ); - - t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); -}); - test("mapDataAsRenderedTemplates", async (t) => { let tmpl = getNewTemplate( "./test/stubs/default.ejs", diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index 71fc79683..69ad7236a 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -1,5 +1,7 @@ const test = require("ava"); const fs = require("fs"); +const TemplateConfig = require("../src/TemplateConfig"); +const TemplateData = require("../src/TemplateData"); const getNewTemplate = require("./_getNewTemplateForTests"); @@ -122,3 +124,69 @@ test("Disable dynamic permalinks", async (t) => { t.is(await tmpl.getOutputLink(), "/{{justastring}}/index.html"); t.is(await tmpl.getOutputHref(), "/{{justastring}}/"); }); + + +test("Permalink with variables!", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalinkdata.njk", + "./test/stubs/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-candidate/index.html"); +}); + +test("Permalink with variables and JS front matter!", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalinkdata-jsfn.njk", + "./test/stubs/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/slug/index.html"); +}); + +// This is broken right now, permalink must use the same template language as the template +test.skip("Use a JavaScript function for permalink in any template language", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalinkdata-jspermalinkfn.njk", + "./test/stubs/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/slug/index.html"); +}); + +test("Permalink with dates!", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/permalinkdate.liquid", + "./test/stubs/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); +}); + +test("Permalink with dates on file name regex!", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/2016-02-01-permalinkdate.liquid", + "./test/stubs/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/2016/02/01/index.html"); +}); + +test("Reuse permalink in directory specific data file", async (t) => { + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/reuse-permalink/test1.liquid", + "./test/stubs/", + "./dist", + dataObj + ); + + t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); +}); + From b2c494289f77f9348abe9266a04f591fdd1c6b69 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 1 Jul 2021 16:28:04 -0500 Subject: [PATCH 509/746] Fixes https://github.com/11ty/eleventy/issues/278 --- package.json | 1 + src/Filters/Slug.js | 6 +++--- src/Filters/Slugify.js | 5 +++++ src/defaultConfig.js | 4 ++++ test/TemplateTest_Permalink.js | 19 +++++++++++++++++++ test/slugify-filter/apostrophe.njk | 5 +++++ test/slugify-filter/test.njk | 5 +++++ 7 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 src/Filters/Slugify.js create mode 100644 test/slugify-filter/apostrophe.njk create mode 100644 test/slugify-filter/test.njk diff --git a/package.json b/package.json index 993e39741..e2aa489dd 100755 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "dependencies": { "@11ty/dependency-tree": "^2.0.0", "@iarna/toml": "^2.2.5", + "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.26.14", "chalk": "^4.1.0", "chokidar": "^3.5.1", diff --git a/src/Filters/Slug.js b/src/Filters/Slug.js index 739c3d2d6..804faa8fb 100644 --- a/src/Filters/Slug.js +++ b/src/Filters/Slug.js @@ -1,8 +1,8 @@ const slugify = require("slugify"); -module.exports = function(str) { - return slugify(str, { +module.exports = function(str, options = {}) { + return slugify(str, Object.assign({ replacement: "-", lower: true - }); + }, options)); }; diff --git a/src/Filters/Slugify.js b/src/Filters/Slugify.js new file mode 100644 index 000000000..033f1868a --- /dev/null +++ b/src/Filters/Slugify.js @@ -0,0 +1,5 @@ +const slugify = require("@sindresorhus/slugify"); + +module.exports = function(str, options = {}) { + return slugify(str, options); +}; diff --git a/src/defaultConfig.js b/src/defaultConfig.js index 474c124e5..09712ff66 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -1,11 +1,15 @@ const urlFilter = require("./Filters/Url"); const serverlessUrlFilter = require("./Filters/ServerlessUrl"); const slugFilter = require("./Filters/Slug"); +const slugifyFilter = require("./Filters/Slugify"); const getCollectionItem = require("./Filters/GetCollectionItem"); module.exports = function (config) { let eleventyConfig = this; + config.addFilter("slug", slugFilter); + config.addFilter("slugify", slugifyFilter); + config.addFilter("url", function (url, pathPrefixOverride) { let pathPrefix = pathPrefixOverride || eleventyConfig.getConfig().pathPrefix; diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index 69ad7236a..d82533446 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -190,3 +190,22 @@ test("Reuse permalink in directory specific data file", async (t) => { t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); }); +test("Using slugify filter!", async (t) => { + let tmpl = getNewTemplate( + "./test/slugify-filter/test.njk", + "./test/slugify-filter/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-love-candidate-lyublyu/index.html"); +}); + +test("Using slugify filter with apostrophe", async (t) => { + let tmpl = getNewTemplate( + "./test/slugify-filter/apostrophe.njk", + "./test/slugify-filter/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/hi-i-m-zach/index.html"); +}); diff --git a/test/slugify-filter/apostrophe.njk b/test/slugify-filter/apostrophe.njk new file mode 100644 index 000000000..b0b444eb3 --- /dev/null +++ b/test/slugify-filter/apostrophe.njk @@ -0,0 +1,5 @@ +--- +title: "Hi I'm Zach" +permalink: subdir/{{ title | slugify }}/index.html +--- +Slugged. diff --git a/test/slugify-filter/test.njk b/test/slugify-filter/test.njk new file mode 100644 index 000000000..6f778ce24 --- /dev/null +++ b/test/slugify-filter/test.njk @@ -0,0 +1,5 @@ +--- +title: _Slug ♥ CANDIDATE люблю $#%- +permalink: subdir/{{ title | slugify }}/index.html +--- +Slugged. From 76f06cf92b942653f970a94f3bf3857b7d99ca5e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 1 Jul 2021 16:31:58 -0500 Subject: [PATCH 510/746] Add test for commas --- test/TemplateTest_Permalink.js | 10 ++++++++++ test/slugify-filter/comma.njk | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 test/slugify-filter/comma.njk diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index d82533446..b1e7fecf1 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -209,3 +209,13 @@ test("Using slugify filter with apostrophe", async (t) => { t.is(await tmpl.getOutputPath(), "./dist/subdir/hi-i-m-zach/index.html"); }); + +test("Using slugify filter with comma", async (t) => { + let tmpl = getNewTemplate( + "./test/slugify-filter/comma.njk", + "./test/slugify-filter/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/hi-i-m-zach/index.html"); +}); diff --git a/test/slugify-filter/comma.njk b/test/slugify-filter/comma.njk new file mode 100644 index 000000000..051808553 --- /dev/null +++ b/test/slugify-filter/comma.njk @@ -0,0 +1,5 @@ +--- +title: "Hi, I'm Zach" +permalink: subdir/{{ title | slugify }}/index.html +--- +Slugged. From d5d110cba92d6abe230b014743df9f75211c4fac Mon Sep 17 00:00:00 2001 From: Jake Mulley Date: Sun, 4 Jul 2021 19:01:57 +0100 Subject: [PATCH 511/746] Deduplicate tags when using deepDataMerge --- src/TemplateData.js | 3 +++ test/TemplateTest.js | 20 ++++++++++++++++++++ test/stubs/data-cascade/template.11tydata.js | 4 ++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index bf90503db..92eeaa145 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -586,6 +586,9 @@ class TemplateData { } else if (data.tags === null) { data.tags = []; } + + // Deduplicate tags + data.tags = [...new Set(data.tags)]; } return data; diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 8c590884a..dd92d6fc6 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1489,6 +1489,26 @@ test("Data Cascade Tag Merge (Deep merge)", async (t) => { t.deepEqual(data.tags.sort(), ["tagA", "tagB", "tagC", "tagD"]); }); +test("Data Cascade Tag Merge (Deep Merge - Deduplication)", async (t) => { + let eleventyConfig = new TemplateConfig(); + // Default changed in 1.0 + // eleventyConfig.userConfig.setDataDeepMerge(true); + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + await dataObj.cacheData(); + + let tmpl = getNewTemplate( + "./test/stubs/data-cascade/template.njk", + "./test/stubs/", + "./dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.deepEqual(data.tags.sort(), ["tagA", "tagB", "tagC", "tagD"]); +}); + test("Data Cascade Tag Merge (Shallow merge)", async (t) => { let eleventyConfig = new TemplateConfig(); // Default changed in 1.0 diff --git a/test/stubs/data-cascade/template.11tydata.js b/test/stubs/data-cascade/template.11tydata.js index c28b80b76..d78ea3ab4 100644 --- a/test/stubs/data-cascade/template.11tydata.js +++ b/test/stubs/data-cascade/template.11tydata.js @@ -1,8 +1,8 @@ module.exports = { parent: { child: 2, - datafile: true + datafile: true, }, datafile: true, - tags: ["tagC", "tagD"] + tags: ["tagC", "tagD", "tagD"], }; From 042019cd710da7c8e615598d9ccfdac7935b5e81 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 6 Jul 2021 10:36:23 -0500 Subject: [PATCH 512/746] Duplicate tests --- test/TemplateTest.js | 58 -------------------------------------------- 1 file changed, 58 deletions(-) diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 8c590884a..bcf7216c4 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2273,64 +2273,6 @@ test("Do not resolve page.url from eleventy serverless data", async (t) => { t.is(path, false); }); -test("Do not resolve page.url from eleventy serverless data (when build also exists in permalink and serverless global data exists)", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", - "./test/stubs/", - "./test/stubs/_site" - ); - let fakeData = { - permalink: { - build: "/build/", - serverless: "/serverless/", - }, - }; - - let outputHref = await tmpl.getOutputHref(fakeData); - t.is(outputHref, "/build/"); - - let outputLink = await tmpl.getOutputLink(fakeData); - t.is(outputLink, "/build/index.html"); - - let outputPath = await tmpl.getOutputPath(fakeData); - t.is(outputPath, "./test/stubs/_site/build/index.html"); - - let { href, link, path } = await tmpl.getOutputLocations(fakeData); - t.is(href, "/build/"); - t.is(link, "/build/index.html"); - t.is(path, "./test/stubs/_site/build/index.html"); -}); - -test("Do not resolve page.url from eleventy serverless data (when build also exists in permalink and serverless global data does not exist)", async (t) => { - let tmpl = getNewTemplate( - "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", - "./test/stubs/", - "./test/stubs/_site" - ); - let fakeData = { - permalink: { - build: "/build/", - serverless: "/serverless/", - }, - }; - - let outputHref = await tmpl.getOutputHref(fakeData); - t.is(outputHref, "/build/"); - - // These should be false because the eleventy.serverless object is set. - // When in build-mode they would not be false. - let outputLink = await tmpl.getOutputLink(fakeData); - t.is(outputLink, "/build/index.html"); - - let outputPath = await tmpl.getOutputPath(fakeData); - t.is(outputPath, "./test/stubs/_site/build/index.html"); - - let { href, link, path } = await tmpl.getOutputLocations(fakeData); - t.is(href, "/build/"); - t.is(link, "/build/index.html"); - t.is(path, "./test/stubs/_site/build/index.html"); -}); - test("Do not override page.url with serverless url", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalink-build-serverless/permalink-build-serverless.md", From 4eded235dc8505140d24a309cfb3e9792fee44bc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 6 Jul 2021 21:03:17 -0500 Subject: [PATCH 513/746] Resolves PR comment https://github.com/11ty/eleventy/pull/1873#discussion_r663253148 --- test/TemplateTest_Permalink.js | 10 ---------- test/slugify-filter/apostrophe.njk | 5 ----- 2 files changed, 15 deletions(-) delete mode 100644 test/slugify-filter/apostrophe.njk diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index b1e7fecf1..6f27e7246 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -200,16 +200,6 @@ test("Using slugify filter!", async (t) => { t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-love-candidate-lyublyu/index.html"); }); -test("Using slugify filter with apostrophe", async (t) => { - let tmpl = getNewTemplate( - "./test/slugify-filter/apostrophe.njk", - "./test/slugify-filter/", - "./dist" - ); - - t.is(await tmpl.getOutputPath(), "./dist/subdir/hi-i-m-zach/index.html"); -}); - test("Using slugify filter with comma", async (t) => { let tmpl = getNewTemplate( "./test/slugify-filter/comma.njk", diff --git a/test/slugify-filter/apostrophe.njk b/test/slugify-filter/apostrophe.njk deleted file mode 100644 index b0b444eb3..000000000 --- a/test/slugify-filter/apostrophe.njk +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "Hi I'm Zach" -permalink: subdir/{{ title | slugify }}/index.html ---- -Slugged. From 6169883e442815331fd74dcceac5242e752e2ced Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 6 Jul 2021 21:24:08 -0500 Subject: [PATCH 514/746] Add tests for passing in options to slug and slugify filters. Switch to decamelize default for slugify filter. --- src/Filters/Slugify.js | 4 +++- test/TemplateTest_Permalink.js | 22 +++++++++++++++++++++- test/slugify-filter/comma.njk | 2 +- test/slugify-filter/slug-options.njk | 5 +++++ test/slugify-filter/slugify-options.njk | 5 +++++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 test/slugify-filter/slug-options.njk create mode 100644 test/slugify-filter/slugify-options.njk diff --git a/src/Filters/Slugify.js b/src/Filters/Slugify.js index 033f1868a..5bb4f1fcc 100644 --- a/src/Filters/Slugify.js +++ b/src/Filters/Slugify.js @@ -1,5 +1,7 @@ const slugify = require("@sindresorhus/slugify"); module.exports = function(str, options = {}) { - return slugify(str, options); + return slugify(str, Object.assign({ + decamelize: false + }, options)); }; diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index 6f27e7246..1ce3729d0 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -200,7 +200,7 @@ test("Using slugify filter!", async (t) => { t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-love-candidate-lyublyu/index.html"); }); -test("Using slugify filter with comma", async (t) => { +test("Using slugify filter with comma and apostrophe", async (t) => { let tmpl = getNewTemplate( "./test/slugify-filter/comma.njk", "./test/slugify-filter/", @@ -209,3 +209,23 @@ test("Using slugify filter with comma", async (t) => { t.is(await tmpl.getOutputPath(), "./dist/subdir/hi-i-m-zach/index.html"); }); + +test("Using slug filter with options params", async (t) => { + let tmpl = getNewTemplate( + "./test/slugify-filter/slug-options.njk", + "./test/slugify-filter/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/hi_i_am_zach/index.html"); +}); + +test("Using slugify filter with options params", async (t) => { + let tmpl = getNewTemplate( + "./test/slugify-filter/slugify-options.njk", + "./test/slugify-filter/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/hi-i-m-z-ach/index.html"); +}); diff --git a/test/slugify-filter/comma.njk b/test/slugify-filter/comma.njk index 051808553..fd3a31fca 100644 --- a/test/slugify-filter/comma.njk +++ b/test/slugify-filter/comma.njk @@ -1,5 +1,5 @@ --- -title: "Hi, I'm Zach" +title: "Hi, I'm ZAch" permalink: subdir/{{ title | slugify }}/index.html --- Slugged. diff --git a/test/slugify-filter/slug-options.njk b/test/slugify-filter/slug-options.njk new file mode 100644 index 000000000..543d5a6d2 --- /dev/null +++ b/test/slugify-filter/slug-options.njk @@ -0,0 +1,5 @@ +--- +title: "Hi, I am ZAch" +permalink: "subdir/{{ title | slug({replacement:'_'}) }}/index.html" +--- +Slugged. diff --git a/test/slugify-filter/slugify-options.njk b/test/slugify-filter/slugify-options.njk new file mode 100644 index 000000000..c958c1874 --- /dev/null +++ b/test/slugify-filter/slugify-options.njk @@ -0,0 +1,5 @@ +--- +title: "Hi, I'm ZAch" +permalink: "subdir/{{ title | slugify({decamelize: true}) }}/index.html" +--- +Slugged. From 2f59c34a8a17571612258b2b37c84dd1f529e008 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 8 Jul 2021 09:23:11 -0500 Subject: [PATCH 515/746] Fixes https://github.com/11ty/eleventy/issues/1877 --- src/Template.js | 1 + test/EleventyTest.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/Template.js b/src/Template.js index 2f6b7a4f2..2ea020978 100755 --- a/src/Template.js +++ b/src/Template.js @@ -794,6 +794,7 @@ class Template extends TemplateContent { let obj = { url: page.url, inputPath: page.inputPath, + outputPath: page.outputPath, content: content, }; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 5e8252096..39ddb6151 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -177,6 +177,7 @@ test("Eleventy to json", async (t) => { { url: "/test/", inputPath: "./test/stubs--to/test.md", + outputPath: "_site/test/index.html", content: "

hi

\n", }, ] @@ -187,6 +188,7 @@ test("Eleventy to json", async (t) => { { url: "/test2/", inputPath: "./test/stubs--to/test2.liquid", + outputPath: "_site/test2/index.html", content: "hello", }, ] From 70133c03b7390810140ac6897531ab3f0a04a106 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 11 Jul 2021 13:53:08 -0500 Subject: [PATCH 516/746] A few minor changes to facilitate https://github.com/11ty/eleventy-upgrade-help --- src/Eleventy.js | 11 +++++++---- src/UserConfig.js | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 1ed6f6cbb..65682629e 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -906,8 +906,11 @@ Arguments: } try { - await this.config.events.emit("beforeBuild"); - await this.config.events.emit("eleventy.before"); + let eventsArg = { + inputDir: this.config.inputDir, + }; + await this.config.events.emit("beforeBuild", eventsArg); + await this.config.events.emit("eleventy.before", eventsArg); let promise; if (to === "fs") { @@ -930,8 +933,8 @@ Arguments: ret = this.logger.closeStream(to); } - await this.config.events.emit("afterBuild"); - await this.config.events.emit("eleventy.after"); + await this.config.events.emit("afterBuild", eventsArg); + await this.config.events.emit("eleventy.after", eventsArg); } catch (e) { hasError = true; ret = { diff --git a/src/UserConfig.js b/src/UserConfig.js index fa88fc160..63c56c7dd 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -616,9 +616,14 @@ class UserConfig { } setDataDeepMerge(deepMerge) { + this._dataDeepMergeModified = true; this.dataDeepMerge = !!deepMerge; } + isDataDeepMergeModified() { + return this._dataDeepMergeModified; + } + addWatchTarget(additionalWatchTargets) { this.additionalWatchTargets.push(additionalWatchTargets); } From 2623e771b31e97ca7fec100c1d4a86439d830d80 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 11 Jul 2021 23:18:57 -0500 Subject: [PATCH 517/746] Changes dynamicPartials default from false to true. Fixes https://github.com/11ty/eleventy/issues/240 --- src/Engines/Liquid.js | 2 +- test/TemplateRenderLiquidTest.js | 163 +++++++++--------- .../_includes/layout.liquid | 2 +- test/stubs/includer.liquid | 2 +- 4 files changed, 85 insertions(+), 84 deletions(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 743b8667f..16eda7ebd 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -48,7 +48,7 @@ class Liquid extends TemplateEngine { let defaults = { root: [super.getIncludesDir()], // overrides in compile with inputPath below extname: ".liquid", - dynamicPartials: false, + dynamicPartials: true, strictFilters: true, // TODO? // cache: true, diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 3fbafc0fa..46bba3a72 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -64,10 +64,11 @@ test("Liquid Render Include", async (t) => { "liquid" ); - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate("

{% include included %}

"); + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate("

{% include included %}

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

This is an include.

"); }); @@ -77,26 +78,35 @@ test("Liquid Render Relative Include", async (t) => { "liquid" ); - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate("

{% include ./included %}

"); + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate("

{% include ./included %}

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

This is an include.

"); }); test("Liquid Render Relative (current dir) Include", async (t) => { - let fn = await getNewTemplateRender( + let tr = await getNewTemplateRender( "./test/stubs/relative-liquid/does_not_exist_and_thats_ok.liquid", "./test/stubs/" - ).getCompiledTemplate("

{% include ./dir/included %}

"); + ); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate("

{% include ./dir/included %}

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

TIME IS RELATIVE.

"); }); test("Liquid Render Relative (parent dir) Include", async (t) => { - let fn = await getNewTemplateRender( + let tr = await getNewTemplateRender( "./test/stubs/relative-liquid/dir/does_not_exist_and_thats_ok.liquid", "./test/stubs/" - ).getCompiledTemplate("

{% include ../dir/included %}

"); + ); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate("

{% include ../dir/included %}

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

TIME IS RELATIVE.

"); }); @@ -106,7 +116,7 @@ test.skip("Liquid Render Relative (relative include should ignore _includes dir) "./test/stubs/" ); - let fn = await tr.getCompiledTemplate(`

{% include ./included %}

`); + let fn = await tr.getCompiledTemplate(`

{% include './included' %}

`); // This is currently wrong, it uses _includes/included.liquid instead of ./included.liquid // Not changing the above to ../stubs/included works fine because that’s not an ambiguous reference. @@ -119,10 +129,11 @@ test("Liquid Render Include with Liquid Suffix", async (t) => { "liquid" ); - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate("

{% include included.liquid %}

"); + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate("

{% include included.liquid %}

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

This is an include.

"); }); @@ -132,10 +143,11 @@ test("Liquid Render Include with HTML Suffix", async (t) => { "liquid" ); - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate("

{% include included.html %}

"); + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate("

{% include included.html %}

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

This is an include.

"); }); @@ -145,10 +157,11 @@ test("Liquid Render Include with HTML Suffix and Data Pass in", async (t) => { "liquid" ); - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate( + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate( "{% include included-data.html, myVariable: 'myValue' %}" ); t.is((await fn()).trim(), "This is an include. myValue"); @@ -432,57 +445,65 @@ test("Liquid Async Paired Shortcode", async (t) => { }); test("Liquid Render Include Subfolder", async (t) => { - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate(`

{% include subfolder/included.liquid %}

`); + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate( + `

{% include subfolder/included.liquid %}

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

This is an include.

"); }); test("Liquid Render Include Subfolder HTML", async (t) => { - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate(`

{% include subfolder/included.html %}

`); + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate( + `

{% include subfolder/included.html %}

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

This is an include.

"); }); test("Liquid Render Include Subfolder No file extension", async (t) => { - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate(`

{% include subfolder/included %}

`); + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + tr.engine.setLiquidOptions({ + dynamicPartials: false, + }); + let fn = await tr.getCompiledTemplate( + `

{% include subfolder/included %}

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

This is an include.

"); }); -// Skipped tests pending https://github.com/harttle/liquidjs/issues/61 -// Resolution: we’re going to leave this skipped as LiquidJS will require dynamicPartials -// to be on for quoted includes! -test.skip("Liquid Render Include Subfolder Single quotes", async (t) => { - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate(`

{% include 'subfolder/included.liquid' %}

`); +// Related to https://github.com/harttle/liquidjs/issues/61 +// Note that we swapped the dynamicPartials default in Eleventy 1.0 from false to true +test("Liquid Render Include Subfolder Single quotes", async (t) => { + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + let fn = await tr.getCompiledTemplate( + `

{% include 'subfolder/included.liquid' %}

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

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Double quotes", async (t) => { - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate(`

{% include "subfolder/included.liquid" %}

`); +test("Liquid Render Include Subfolder Double quotes", async (t) => { + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + let fn = await tr.getCompiledTemplate( + `

{% include "subfolder/included.liquid" %}

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

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Single quotes HTML", async (t) => { - let fn = await getNewTemplateRender( - "liquid", - "./test/stubs/" - ).getCompiledTemplate(`

{% include 'subfolder/included.html' %}

`); +test("Liquid Render Include Subfolder Single quotes HTML", async (t) => { + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + let fn = await tr.getCompiledTemplate( + `

{% include 'subfolder/included.html' %}

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

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Double quotes HTML", async (t) => { +test("Liquid Render Include Subfolder Double quotes HTML", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -490,7 +511,7 @@ test.skip("Liquid Render Include Subfolder Double quotes HTML", async (t) => { t.is(await fn(), "

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Single quotes No file extension", async (t) => { +test("Liquid Render Include Subfolder Single quotes No file extension", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" @@ -498,27 +519,25 @@ test.skip("Liquid Render Include Subfolder Single quotes No file extension", asy t.is(await fn(), "

This is an include.

"); }); -test.skip("Liquid Render Include Subfolder Double quotes No file extension", async (t) => { +test("Liquid Render Include Subfolder Double quotes No file extension", async (t) => { let fn = await getNewTemplateRender( "liquid", "./test/stubs/" ).getCompiledTemplate(`

{% include "subfolder/included" %}

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

This is an include.

"); }); -/* End skipped tests */ +/* End tests related to dynamicPartials */ test("Liquid Options Overrides", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); + tr.engine.setLiquidOptions({ dynamicPartials: false }); let options = tr.engine.getLiquidOptions(); - t.is(options.dynamicPartials, true); + t.is(options.dynamicPartials, false); }); test("Liquid Render Include Subfolder Single quotes no extension dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include 'subfolder/included' %}

` ); @@ -530,8 +549,6 @@ test("Liquid Render Include Subfolder Single quotes (relative include current di "./test/stubs/does_not_exist_and_thats_ok.liquid", "./test/stubs/" ); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include './relative-liquid/dir/included' %}

` ); @@ -543,8 +560,6 @@ test("Liquid Render Include Subfolder Single quotes (relative include parent dir "./test/stubs/subfolder/does_not_exist_and_thats_ok.liquid", "./test/stubs/" ); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include '../relative-liquid/dir/included' %}

` ); @@ -553,8 +568,6 @@ test("Liquid Render Include Subfolder Single quotes (relative include parent dir test("Liquid Render Include Subfolder Double quotes no extension dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include "subfolder/included" %}

` ); @@ -563,8 +576,6 @@ test("Liquid Render Include Subfolder Double quotes no extension dynamicPartials test("Liquid Render Include Subfolder Single quotes dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include 'subfolder/included.liquid' %}

` ); @@ -573,8 +584,6 @@ test("Liquid Render Include Subfolder Single quotes dynamicPartials true", async test("Liquid Render Include Subfolder Double quotes dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include "subfolder/included.liquid" %}

` ); @@ -583,8 +592,6 @@ test("Liquid Render Include Subfolder Double quotes dynamicPartials true", async test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include 'subfolder/included.html' %}

` ); @@ -593,8 +600,6 @@ test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true", test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include "subfolder/included.html" %}

` ); @@ -603,8 +608,6 @@ test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true", test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true, data passed in", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include 'subfolder/included.html', myVariable: 'myValue' %}

` ); @@ -613,8 +616,6 @@ test("Liquid Render Include Subfolder Single quotes HTML dynamicPartials true, d test("Liquid Render Include Subfolder Double quotes HTML dynamicPartials true, data passed in", async (t) => { let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: true }); - let fn = await tr.getCompiledTemplate( `

{% include "subfolder/included.html", myVariable: "myValue" %}

` ); diff --git a/test/stubs-layout-cache/_includes/layout.liquid b/test/stubs-layout-cache/_includes/layout.liquid index 33be0009f..b7464c4f0 100644 --- a/test/stubs-layout-cache/_includes/layout.liquid +++ b/test/stubs-layout-cache/_includes/layout.liquid @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/test/stubs/includer.liquid b/test/stubs/includer.liquid index b52e8fe23..a7ebcf1f3 100644 --- a/test/stubs/includer.liquid +++ b/test/stubs/includer.liquid @@ -1 +1 @@ -

{% include included %}

+

{% include 'included' %}

From 326a2b28413ae5a1361261a0267eae01961c88f4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 12 Jul 2021 07:06:42 -0500 Subject: [PATCH 518/746] =?UTF-8?q?Use=20the=20upstream=20default=20for=20?= =?UTF-8?q?liquidjs=20dynamicPartials=20(it=E2=80=99s=20true)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Engines/Liquid.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 16eda7ebd..5dabeda64 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -48,7 +48,6 @@ class Liquid extends TemplateEngine { let defaults = { root: [super.getIncludesDir()], // overrides in compile with inputPath below extname: ".liquid", - dynamicPartials: true, strictFilters: true, // TODO? // cache: true, From 10200e0f12c1fed521a90a398eb5b758bfe80638 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 12 Jul 2021 08:13:38 -0500 Subject: [PATCH 519/746] Update husky --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2aa489dd..536e7e83e 100755 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.0", "ava": "^3.15.0", - "husky": "^5.1.3", + "husky": "^7.0.1", "ink-docstrap": "1.3.2", "js-yaml": "^4.0.0", "jsdoc": "3.6.7", From 493801322c7fffa49b0f681e64cdbc962ac9e5f8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 12 Jul 2021 08:16:18 -0500 Subject: [PATCH 520/746] Update lint-staged --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 536e7e83e..4d4d6463c 100755 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "ink-docstrap": "1.3.2", "js-yaml": "^4.0.0", "jsdoc": "3.6.7", - "lint-staged": "^10.5.4", + "lint-staged": "^11.0.0", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.2.1", From 5fce0f7834a2fa49f59bd894b8b65d2cf8484bf3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 12 Jul 2021 08:23:21 -0500 Subject: [PATCH 521/746] Removes ViperHTML dev test via npm warn "npm WARN deprecated viperhtml@2.17.1: viperHTML is maintenance only: check ucontent or heresy-ssr instead" --- test/TemplateRenderJavaScriptTest.js | 13 ------------- test/stubs/viperhtml.11ty.js | 9 --------- 2 files changed, 22 deletions(-) delete mode 100644 test/stubs/viperhtml.11ty.js diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index cdbc8e191..64e82a50d 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -162,19 +162,6 @@ test("JS Render using Vue (with a layout)", async (t) => { ); }); -test("JS Render using ViperHTML", async (t) => { - let fn = await getNewTemplateRender( - "./test/stubs/viperhtml.11ty.js" - ).getCompiledTemplate(); - t.is( - await fn({ name: "Zach", html: "Hi" }), - `
- This is a viper template, Zach - Hi -
` - ); -}); - test("JS Render with a function", async (t) => { t.plan(8); diff --git a/test/stubs/viperhtml.11ty.js b/test/stubs/viperhtml.11ty.js deleted file mode 100644 index 9b171dcea..000000000 --- a/test/stubs/viperhtml.11ty.js +++ /dev/null @@ -1,9 +0,0 @@ -const viperHTML = require("viperhtml"); - -// Returns buffer -module.exports = function(data) { - return viperHTML.wire()`
- This is a viper template, ${data.name} - ${[data.html]} -
`; -}; From a72ccbdc187d5f47be8b0e3de958844e4be342c7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 12 Jul 2021 08:29:30 -0500 Subject: [PATCH 522/746] Update dependencies. Includes major version bumps to luxon and fs-extra --- package.json | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 4d4d6463c..badc580f6 100755 --- a/package.json +++ b/package.json @@ -75,56 +75,55 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.0", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.1", "ava": "^3.15.0", "husky": "^7.0.1", "ink-docstrap": "1.3.2", - "js-yaml": "^4.0.0", "jsdoc": "3.6.7", + "js-yaml": "^4.1.0", "lint-staged": "^11.0.0", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", - "prettier": "^2.2.1", + "prettier": "^2.3.2", "rimraf": "^3.0.2", - "sass": "^1.32.11", + "sass": "^1.35.2", "toml": "^3.0.0", - "viperhtml": "^2.17.1", - "vue": "^2.6.12", - "vue-server-renderer": "^2.6.12" + "vue": "^2.6.14", + "vue-server-renderer": "^2.6.14" }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", - "browser-sync": "^2.26.14", - "chalk": "^4.1.0", - "chokidar": "^3.5.1", - "debug": "^4.3.1", + "browser-sync": "^2.27.4", + "chalk": "^4.1.1", + "chokidar": "^3.5.2", + "debug": "^4.3.2", "dependency-graph": "^0.11.0", "ejs": "^3.1.6", - "fast-glob": "^3.2.5", - "fs-extra": "^9.1.0", - "gray-matter": "^4.0.2", + "fast-glob": "^3.2.7", + "fs-extra": "^10.0.0", + "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", "is-glob": "^4.0.1", - "liquidjs": "^9.23.2", + "liquidjs": "^9.25.1", "lodash": "^4.17.21", - "luxon": "^1.26.0", - "markdown-it": "^12.0.4", + "luxon": "^2.0.1", + "markdown-it": "^12.1.0", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^5.0.0", - "mustache": "^4.1.0", + "mustache": "^4.2.0", "normalize-path": "^3.0.0", "nunjucks": "^3.2.3", "parse-filepath": "^1.0.2", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^3.0.2", - "recursive-copy": "^2.0.11", - "semver": "^7.3.4", - "slugify": "^1.4.7", + "recursive-copy": "^2.0.13", + "semver": "^7.3.5", + "slugify": "^1.5.3", "split": "^1.0.1", "time-require": "^0.1.2", "url-pattern": "^1.0.3", From 6d3632c3a5024186a93a7e70d6c576b45eceb262 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 12 Jul 2021 08:37:17 -0500 Subject: [PATCH 523/746] Remove a few deps, more info at https://github.com/11ty/eleventy/issues/1885#issuecomment-878286079 --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index badc580f6..7ccfaf7d6 100755 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ ], "scripts": { "default": "npm run test", - "doc": "jsdoc -c .jsdoc.conf.json -d ./api-docs -p ./package.json -R README.md -t ./node_modules/ink-docstrap/template -r src/", "test": "npx ava --verbose", "lint-staged": "lint-staged", "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js", @@ -78,8 +77,6 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.1", "ava": "^3.15.0", "husky": "^7.0.1", - "ink-docstrap": "1.3.2", - "jsdoc": "3.6.7", "js-yaml": "^4.1.0", "lint-staged": "^11.0.0", "markdown-it-emoji": "^2.0.0", From 616c9f7237c06c0eb1419f13a0b6982d82068f5f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 12 Jul 2021 09:22:45 -0500 Subject: [PATCH 524/746] =?UTF-8?q?Clean=20npm=20audit=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ccfaf7d6..4b331d17b 100755 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.1", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.2", "ava": "^3.15.0", "husky": "^7.0.1", "js-yaml": "^4.1.0", From 850236af429ea1406436dd8e974d7b7bcdf92a06 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 13 Jul 2021 07:53:07 -0500 Subject: [PATCH 525/746] Fixes https://github.com/11ty/eleventy/issues/854 --- src/Filters/Slug.js | 16 +++++++++++----- src/Filters/Slugify.js | 14 ++++++++++---- test/TemplateTest_Permalink.js | 26 ++++++++++++++++++++++++-- test/slugify-filter/slug-number.njk | 5 +++++ test/slugify-filter/slugify-number.njk | 5 +++++ 5 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 test/slugify-filter/slug-number.njk create mode 100644 test/slugify-filter/slugify-number.njk diff --git a/src/Filters/Slug.js b/src/Filters/Slug.js index 804faa8fb..9e9f13a47 100644 --- a/src/Filters/Slug.js +++ b/src/Filters/Slug.js @@ -1,8 +1,14 @@ const slugify = require("slugify"); -module.exports = function(str, options = {}) { - return slugify(str, Object.assign({ - replacement: "-", - lower: true - }, options)); +module.exports = function (str, options = {}) { + return slugify( + "" + str, + Object.assign( + { + replacement: "-", + lower: true, + }, + options + ) + ); }; diff --git a/src/Filters/Slugify.js b/src/Filters/Slugify.js index 5bb4f1fcc..d26eb60e3 100644 --- a/src/Filters/Slugify.js +++ b/src/Filters/Slugify.js @@ -1,7 +1,13 @@ const slugify = require("@sindresorhus/slugify"); -module.exports = function(str, options = {}) { - return slugify(str, Object.assign({ - decamelize: false - }, options)); +module.exports = function (str, options = {}) { + return slugify( + "" + str, + Object.assign( + { + decamelize: false, + }, + options + ) + ); }; diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index 1ce3729d0..c846efd32 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -125,7 +125,6 @@ test("Disable dynamic permalinks", async (t) => { t.is(await tmpl.getOutputHref(), "/{{justastring}}/"); }); - test("Permalink with variables!", async (t) => { let tmpl = getNewTemplate( "./test/stubs/permalinkdata.njk", @@ -197,7 +196,10 @@ test("Using slugify filter!", async (t) => { "./dist" ); - t.is(await tmpl.getOutputPath(), "./dist/subdir/slug-love-candidate-lyublyu/index.html"); + t.is( + await tmpl.getOutputPath(), + "./dist/subdir/slug-love-candidate-lyublyu/index.html" + ); }); test("Using slugify filter with comma and apostrophe", async (t) => { @@ -229,3 +231,23 @@ test("Using slugify filter with options params", async (t) => { t.is(await tmpl.getOutputPath(), "./dist/subdir/hi-i-m-z-ach/index.html"); }); + +test("Using slugify filter with a number #854", async (t) => { + let tmpl = getNewTemplate( + "./test/slugify-filter/slugify-number.njk", + "./test/slugify-filter/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/1/index.html"); +}); + +test("Using slug filter with a number #854", async (t) => { + let tmpl = getNewTemplate( + "./test/slugify-filter/slug-number.njk", + "./test/slugify-filter/", + "./dist" + ); + + t.is(await tmpl.getOutputPath(), "./dist/subdir/1/index.html"); +}); diff --git a/test/slugify-filter/slug-number.njk b/test/slugify-filter/slug-number.njk new file mode 100644 index 000000000..07b3e1195 --- /dev/null +++ b/test/slugify-filter/slug-number.njk @@ -0,0 +1,5 @@ +--- +number: 1 +permalink: subdir/{{ number | slug }}/index.html +--- +Slugged. diff --git a/test/slugify-filter/slugify-number.njk b/test/slugify-filter/slugify-number.njk new file mode 100644 index 000000000..3307efa21 --- /dev/null +++ b/test/slugify-filter/slugify-number.njk @@ -0,0 +1,5 @@ +--- +number: 1 +permalink: subdir/{{ number | slugify }}/index.html +--- +Slugged. From 5ca1aa755dfb0fac76a86aba360c0cd7a78e780d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 13 Jul 2021 08:35:40 -0500 Subject: [PATCH 526/746] Start of https://github.com/11ty/eleventy/issues/1891 --- src/EleventyFiles.js | 2 +- src/EleventyServe.js | 7 +++++-- test/TemplatePassthroughManagerTest.js | 12 +++--------- test/TemplateWriterTest.js | 12 +++--------- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index ac351a4b2..e022200cc 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -1,4 +1,4 @@ -const fs = require("fs-extra"); +const fs = require("fs"); const fastglob = require("fast-glob"); const EleventyExtensionMap = require("./EleventyExtensionMap"); diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 2051c3835..145059d74 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -1,4 +1,4 @@ -const fs = require("fs-extra"); +const fs = require("fs"); const path = require("path"); const TemplatePath = require("./TemplatePath"); @@ -121,7 +121,10 @@ class EleventyServe { } serveRedirect(dirName) { - fs.outputFile( + fs.mkdirSync(this.getRedirectDir(dirName), { + recursive: true, + }); + fs.writeFileSync( this.getRedirectFilename(dirName), ` diff --git a/test/TemplatePassthroughManagerTest.js b/test/TemplatePassthroughManagerTest.js index 23f37ef36..3c8c1422c 100644 --- a/test/TemplatePassthroughManagerTest.js +++ b/test/TemplatePassthroughManagerTest.js @@ -1,5 +1,5 @@ const test = require("ava"); -const fs = require("fs-extra"); +const fs = require("fs"); const TemplatePassthroughManager = require("../src/TemplatePassthroughManager"); const TemplateConfig = require("../src/TemplateConfig"); const EleventyFiles = require("../src/EleventyFiles"); @@ -114,14 +114,8 @@ test("Naughty paths outside of project dir", async (t) => { "./test/stubs/img.jpg", ]; - let results = await Promise.all( - output.map(function (path) { - return fs.exists(path); - }) - ); - - for (let result of results) { - t.false(result); + for (let path of output) { + t.false(fs.existsSync(path)); } }); diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index c8f9d4526..b9e34e085 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -1,5 +1,5 @@ const test = require("ava"); -const fs = require("fs-extra"); +const fs = require("fs"); const rimraf = require("rimraf"); const fastglob = require("fast-glob"); const parsePath = require("parse-filepath"); @@ -733,14 +733,8 @@ test("Passthrough file output", async (t) => { "./test/stubs/template-passthrough/_site/test.js", ]; - let results = await Promise.all( - output.map(function (path) { - return fs.exists(path); - }) - ); - - for (let result of results) { - t.true(result); + for (let path of output) { + t.true(fs.existsSync(path)); } rimraf.sync("./test/stubs/template-passthrough/_site/"); From b8687ee27d73e5f68fa9f708b5e17fa5366795e0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 13 Jul 2021 16:23:13 -0500 Subject: [PATCH 527/746] Update one more dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b331d17b..939611349 100755 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "ava": "^3.15.0", "husky": "^7.0.1", "js-yaml": "^4.1.0", - "lint-staged": "^11.0.0", + "lint-staged": "^11.0.1", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.3.2", From 93ea6a4f85733a2f0cf0bb4c4e83f7c8b65149b6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 13 Jul 2021 16:27:02 -0500 Subject: [PATCH 528/746] v1.0.0-canary.39 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 939611349..221307e9a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.38", + "version": "1.0.0-canary.39", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 31dc9b02e8ba64d1658470ba5d02880487b4bc22 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 14 Jul 2021 08:09:15 -0500 Subject: [PATCH 529/746] Serverless fix: changing serverless paths previously required a dev server restart --- src/Serverless.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Serverless.js b/src/Serverless.js index 3e2847ce0..d35056218 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -4,6 +4,7 @@ const fs = require("fs"); const Eleventy = require("./Eleventy"); const TemplatePath = require("./TemplatePath"); const UrlPattern = require("url-pattern"); +const deleteRequireCache = require("./Util/DeleteRequireCache"); const debug = require("debug")("Eleventy:Serverless"); class Serverless { @@ -75,7 +76,10 @@ class Serverless { debug( `Including content map (maps output URLs to input files) from ${fullPath}` ); - return require(fullPath); + deleteRequireCache(fullPath); + + let mapContent = require(fullPath); + return mapContent; } isServerlessUrl(urlPath) { From 92417d399dcb511dd3dedd7781847eff75397b60 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 14 Jul 2021 09:14:59 -0500 Subject: [PATCH 530/746] =?UTF-8?q?Reset=20environment=20variables=20durin?= =?UTF-8?q?g=20watch=20or=20they=E2=80=99ll=20always=20be=20in=20serverles?= =?UTF-8?q?s=20mode=20(even=20in=20build)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Eleventy.js | 4 ++++ src/EleventyExtensionMap.js | 4 ++++ src/TemplateConfig.js | 7 +++---- src/TemplateEngineManager.js | 4 ++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 65682629e..9b714f1ae 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -239,6 +239,7 @@ class Eleventy { templateCache.clear(); bench.reset(); this.eleventyFiles.restart(); + this.extensionMap.reset(); // reload package.json values (if applicable) // TODO only reset this if it changed @@ -543,6 +544,9 @@ Arguments: * @method */ resetConfig() { + this.env = this.getEnvironmentVariableValues(); + this.initializeEnvironmentVariables(this.env); + this.eleventyConfig.reset(); this.config = this.eleventyConfig.getConfig(); diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index 6a76b7a36..d4417e7cf 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -53,6 +53,10 @@ class EleventyExtensionMap { return this._engineManager; } + reset() { + this.engineManager.reset(); + } + /* Used for layout path resolution */ getFileList(path, dir) { if (!path) { diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 075d119db..c1889608b 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -175,9 +175,7 @@ class TemplateConfig { if (fs.existsSync(path)) { try { // remove from require cache so it will grab a fresh copy - if (path in require.cache) { - deleteRequireCache(path); - } + deleteRequireCache(path); localConfig = require(path); // debug( "localConfig require return value: %o", localConfig ); @@ -220,7 +218,8 @@ class TemplateConfig { debug("Eleventy local project config file not found, skipping."); } - let eleventyConfigApiMergingObject = this.userConfig.getMergingConfigObject(); + let eleventyConfigApiMergingObject = + this.userConfig.getMergingConfigObject(); // remove special merge keys from object let savedForSpecialMerge = { diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 0540e2412..c9744211b 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -35,6 +35,10 @@ class TemplateEngineManager { return this._keyToClassNameMap; } + reset() { + this.engineCache = {}; + } + getClassNameFromTemplateKey(key) { let keys = this.keyToClassNameMap; From 8a3572015f93fa0de870eb6b1cb74aa03eec3a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Thu, 15 Jul 2021 21:49:11 +0200 Subject: [PATCH 531/746] docs: add docstring for EleventyBaseError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By extension, this will also document the signature for derived errors. Signed-off-by: André Jaenisch --- src/EleventyBaseError.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/EleventyBaseError.js b/src/EleventyBaseError.js index b27ac7d32..f5269131d 100644 --- a/src/EleventyBaseError.js +++ b/src/EleventyBaseError.js @@ -1,12 +1,21 @@ +/** + * This class serves as basis for all Eleventy-specific errors. + */ class EleventyBaseError extends Error { + /** + * @param {string} message - The error message to display. + * @param {Error} originalError - The original error catched. + */ constructor(message, originalError) { super(message); + /** @type {string} - The error message to display. */ this.name = this.constructor.name; Error.captureStackTrace(this, this.constructor); if (originalError) { + /** @type {Error} - The original error catched. */ this.originalError = originalError; } } From 4c9c718299b7210c301ea6232d294c467a0e5dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Mon, 19 Jul 2021 14:05:14 +0200 Subject: [PATCH 532/746] Remove fs-extra dependency (#1891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @zachleat proposed removing fs-extra since the build in FS module now provides a promise based option and supports recursive options. This Commit only uses the ```require("fs")``` instead of ```require("fs").promises``` or ```require("fs/promises")```, since the last one is not support in Node Version <14 and the sync API is used. Except for Template.js no file logic needed to be changed to remove fs-extra. According to my run of "npm test" test results are not changed by this commit. Signed-off-by: Raphael Höser --- package.json | 1 - src/Engines/TemplateEngine.js | 2 +- src/Template.js | 23 ++++++++--------------- src/TemplateConfig.js | 2 +- src/TemplateContent.js | 4 ++-- src/TemplateData.js | 8 ++++---- src/TemplateLayoutPathResolver.js | 2 +- 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 221307e9a..e701987d5 100755 --- a/package.json +++ b/package.json @@ -99,7 +99,6 @@ "dependency-graph": "^0.11.0", "ejs": "^3.1.6", "fast-glob": "^3.2.7", - "fs-extra": "^10.0.0", "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 0d949e071..58a1eacc3 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -1,5 +1,5 @@ const fastglob = require("fast-glob"); -const fs = require("fs-extra"); +const fs = require("fs"); const TemplatePath = require("../TemplatePath"); const TemplateConfig = require("../TemplateConfig"); const EleventyExtensionMap = require("../EleventyExtensionMap"); diff --git a/src/Template.js b/src/Template.js index 2ea020978..83b923e65 100755 --- a/src/Template.js +++ b/src/Template.js @@ -1,4 +1,5 @@ -const fs = require("fs-extra"); +const fs = require("fs"); +const path = require("path"); const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); @@ -751,11 +752,11 @@ class Template extends TemplateContent { } else { let templateBenchmark = bench.get("Template Write"); templateBenchmark.before(); - return fs.outputFile(outputPath, finalContent).then(() => { - templateBenchmark.after(); - this.writeCount++; - debug(`${outputPath} ${lang.finished}.`); - }); + await fs.promises.mkdir(path.parse(outputPath).dir, { recursive: true }); + await fs.promises.writeFile(outputPath, finalContent); + templateBenchmark.after(); + this.writeCount++; + debug(`${outputPath} ${lang.finished}.`); } } @@ -868,15 +869,7 @@ class Template extends TemplateContent { return this._stats; } - this._stats = new Promise((resolve, reject) => { - fs.stat(this.inputPath, (err, stats) => { - if (err) { - reject(err); - } else { - resolve(stats); - } - }); - }); + this._stats = fs.promises.stat(this.inputPath); return this._stats; } diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index c1889608b..837a1b822 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -1,4 +1,4 @@ -const fs = require("fs-extra"); +const fs = require("fs"); const chalk = require("chalk"); const lodashUniq = require("lodash/uniq"); const lodashMerge = require("lodash/merge"); diff --git a/src/TemplateContent.js b/src/TemplateContent.js index fc478daf7..eae6b6427 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -1,5 +1,5 @@ const os = require("os"); -const fs = require("fs-extra"); +const fs = require("fs"); const normalize = require("normalize-path"); const matter = require("gray-matter"); const lodashSet = require("lodash/set"); @@ -161,7 +161,7 @@ class TemplateContent { content = TemplateContent.getCached(this.inputPath); } if (!content) { - content = await fs.readFile(this.inputPath, "utf-8"); + content = await fs.promises.readFile(this.inputPath, "utf-8"); if (this.config.useTemplateCache) { TemplateContent.cache(this.inputPath, content); diff --git a/src/TemplateData.js b/src/TemplateData.js index 92eeaa145..8397555a4 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -1,4 +1,4 @@ -const fs = require("fs-extra"); +const fs = require("fs"); const fastglob = require("fast-glob"); const parsePath = require("parse-filepath"); const lodashset = require("lodash/set"); @@ -29,7 +29,7 @@ class FSExistsCache { exists(path) { let exists = this._cache.get(path); if (!this.has(path)) { - exists = fs.pathExistsSync(path); + exists = fs.existsSync(path); this._cache.set(path, exists); } return exists; @@ -140,7 +140,7 @@ class TemplateData { async _checkInputDir() { if (this.inputDirNeedsCheck) { - let globalPathStat = await fs.stat(this.inputDir); + let globalPathStat = await fs.promises.stat(this.inputDir); if (!globalPathStat.isDirectory()) { throw new Error("Could not find data path directory: " + this.inputDir); @@ -392,7 +392,7 @@ class TemplateData { async _loadFileContents(path) { let rawInput; try { - rawInput = await fs.readFile(path, "utf-8"); + rawInput = await fs.promises.readFile(path, "utf-8"); } catch (e) { // if file does not exist, return nothing } diff --git a/src/TemplateLayoutPathResolver.js b/src/TemplateLayoutPathResolver.js index 2af7e5af6..58f407409 100644 --- a/src/TemplateLayoutPathResolver.js +++ b/src/TemplateLayoutPathResolver.js @@ -1,4 +1,4 @@ -const fs = require("fs-extra"); +const fs = require("fs"); const TemplatePath = require("./TemplatePath"); // const debug = require("debug")("Eleventy:TemplateLayoutPathResolver"); From 79b37ee69eb9953001e953078dc64dbdb8c7a92f Mon Sep 17 00:00:00 2001 From: Tanner Date: Tue, 20 Jul 2021 15:17:36 -0700 Subject: [PATCH 533/746] Adds code of conduct link to top of markdown file --- CODE_OF_CONDUCT.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 010193058..318db5786 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,5 +1,7 @@ # Eleventy Community Code of Conduct +View the [Code of Conduct](https://www.11ty.dev/docs/code-of-conduct/) on 11ty.dev + ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. From 05dcc5d0d74a8ac709c7ed189f216e89865b7a30 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 26 Jul 2021 09:16:13 -0500 Subject: [PATCH 534/746] Minor tweaks for https://github.com/11ty/eleventy/issues/1891 --- src/Template.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Template.js b/src/Template.js index 83b923e65..7afc1b133 100755 --- a/src/Template.js +++ b/src/Template.js @@ -3,7 +3,6 @@ const path = require("path"); const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); -const get = require("lodash/get"); const { DateTime } = require("luxon"); const TemplateData = require("./TemplateData"); @@ -752,11 +751,16 @@ class Template extends TemplateContent { } else { let templateBenchmark = bench.get("Template Write"); templateBenchmark.before(); - await fs.promises.mkdir(path.parse(outputPath).dir, { recursive: true }); - await fs.promises.writeFile(outputPath, finalContent); - templateBenchmark.after(); - this.writeCount++; - debug(`${outputPath} ${lang.finished}.`); + + // TODO add a cache to check if this was already created + let templateOutputDir = path.parse(outputPath).dir; + await fs.promises.mkdir(templateOutputDir, { recursive: true }); + + return fs.promises.writeFile(outputPath, finalContent).then(() => { + templateBenchmark.after(); + this.writeCount++; + debug(`${outputPath} ${lang.finished}.`); + }); } } From 5cea0b28e97084d1c6618923d40e7e1d3123962d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 26 Jul 2021 14:32:38 -0500 Subject: [PATCH 535/746] Fixes https://github.com/11ty/eleventy/issues/1823 --- src/Template.js | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Template.js b/src/Template.js index 7afc1b133..82e6ea779 100755 --- a/src/Template.js +++ b/src/Template.js @@ -878,10 +878,31 @@ class Template extends TemplateContent { return this._stats; } - async getMappedDate(data) { - // TODO(slightlyoff): lots of I/O! + async _getDateInstance(key = "birthtimeMs") { + let stat = await this.getInputFileStat(); + + // Issue 1823: https://github.com/11ty/eleventy/issues/1823 + // return current Date in a Lambda + // otherwise ctime would be "1980-01-01T00:00:00.000Z" + // otherwise birthtime would be "1970-01-01T00:00:00.000Z" + if (stat.birthtimeMs === 0) { + return new Date(); + } + + let newDate = new Date(stat[key]); + + debug( + "Template date: using file’s %o for %o of %o (from %o)", + key, + this.inputPath, + newDate, + stat.birthtimeMs + ); - // should we use Luxon dates everywhere? Right now using built-in `Date` + return newDate; + } + + async getMappedDate(data) { if ("date" in data && data.date) { debug( "getMappedDate: using a date in the data for %o of %o", @@ -895,11 +916,9 @@ class Template extends TemplateContent { } else { // string if (data.date.toLowerCase() === "last modified") { - let stat = await this.getInputFileStat(); - return new Date(stat.ctimeMs); + return this._getDateInstance("ctimeMs"); } else if (data.date.toLowerCase() === "created") { - let stat = await this.getInputFileStat(); - return new Date(stat.birthtimeMs); + return this._getDateInstance("birthtimeMs"); } else { // try to parse with Luxon let date = DateTime.fromISO(data.date, { zone: "utc" }); @@ -931,17 +950,7 @@ class Template extends TemplateContent { return dateObj; } - let stat = await this.getInputFileStat(); - let createdDate = new Date(stat.birthtimeMs); - debug( - "getMappedDate: using file created time for %o of %o (from %o)", - this.inputPath, - createdDate, - stat.birthtimeMs - ); - - // CREATED - return createdDate; + return this._getDateInstance("birthtimeMs"); } } From d5b3da38059d44177ac070269a0521131c3c1658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Mon, 26 Jul 2021 22:50:46 +0200 Subject: [PATCH 536/746] Remove parse-filepath dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As described in #1903 this commit removes the parse-filepath dependency from 11ty in favor of the native path.parse. Some files needed renaming of some variables which were named "path" and shadowed the path module. I hope I selected reasonable replacements. In TemplatePath.js I also changed the documentation links to point to the nodejs api doc instead of the npm package. According to a local test run it does not change test results. Signed-off-by: Raphael Höser --- package.json | 1 - src/Template.js | 18 ++++++++++++------ src/TemplateData.js | 13 ++++++++----- src/TemplateFileSlug.js | 4 ++-- src/TemplatePath.js | 13 ++++++------- src/TemplatePermalink.js | 4 ++-- test/TemplateWriterTest.js | 24 +++++++++++++++--------- 7 files changed, 45 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index e701987d5..23bcedf6c 100755 --- a/package.json +++ b/package.json @@ -113,7 +113,6 @@ "mustache": "^4.2.0", "normalize-path": "^3.0.0", "nunjucks": "^3.2.3", - "parse-filepath": "^1.0.2", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^3.0.2", diff --git a/src/Template.js b/src/Template.js index 82e6ea779..1e28dca09 100755 --- a/src/Template.js +++ b/src/Template.js @@ -1,6 +1,5 @@ const fs = require("fs"); const path = require("path"); -const parsePath = require("parse-filepath"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); const { DateTime } = require("luxon"); @@ -23,11 +22,18 @@ const debugDev = require("debug")("Dev:Eleventy:Template"); const bench = require("./BenchmarkManager").get("Aggregate"); class Template extends TemplateContent { - constructor(path, inputDir, outputDir, templateData, extensionMap, config) { - debugDev("new Template(%o)", path); - super(path, inputDir, config); - - this.parsed = parsePath(path); + constructor( + templatePath, + inputDir, + outputDir, + templateData, + extensionMap, + config + ) { + debugDev("new Template(%o)", templatePath); + super(templatePath, inputDir, config); + + this.parsed = path.parse(templatePath); // for pagination this.extraOutputSubdirectory = ""; diff --git a/src/TemplateData.js b/src/TemplateData.js index 8397555a4..b615c304c 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -1,6 +1,6 @@ const fs = require("fs"); const fastglob = require("fast-glob"); -const parsePath = require("parse-filepath"); +const path = require("path"); const lodashset = require("lodash/set"); const lodashget = require("lodash/get"); const lodashUniq = require("lodash/uniq"); @@ -241,9 +241,12 @@ class TemplateData { return paths; } - getObjectPathForDataFile(path) { - let reducedPath = TemplatePath.stripLeadingSubPath(path, this.dataDir); - let parsed = parsePath(reducedPath); + getObjectPathForDataFile(dataFilePath) { + let reducedPath = TemplatePath.stripLeadingSubPath( + dataFilePath, + this.dataDir + ); + let parsed = path.parse(reducedPath); let folders = parsed.dir ? parsed.dir.split("/") : []; folders.push(parsed.name); @@ -515,7 +518,7 @@ class TemplateData { async getLocalDataPaths(templatePath) { let paths = []; - let parsed = parsePath(templatePath); + let parsed = path.parse(templatePath); let inputDir = TemplatePath.addLeadingDotSlash( TemplatePath.normalize(this.inputDir) ); diff --git a/src/TemplateFileSlug.js b/src/TemplateFileSlug.js index 435714266..ed95edeb8 100644 --- a/src/TemplateFileSlug.js +++ b/src/TemplateFileSlug.js @@ -1,4 +1,4 @@ -const parsePath = require("parse-filepath"); +const path = require("path"); const TemplatePath = require("./TemplatePath"); class TemplateFileSlug { @@ -14,7 +14,7 @@ class TemplateFileSlug { this.dirs = dirs; this.dirs.pop(); - this.parsed = parsePath(inputPath); + this.parsed = path.parse(inputPath); this.filenameNoExt = extensionMap.removeTemplateExtension(this.parsed.base); } diff --git a/src/TemplatePath.js b/src/TemplatePath.js index a4c94d31a..680891d72 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -1,6 +1,5 @@ const path = require("path"); const normalize = require("normalize-path"); -const parsePath = require("parse-filepath"); const fs = require("fs"); function TemplatePath() {} @@ -31,23 +30,23 @@ TemplatePath.getDir = function (path) { * Returns the directory portion of a path that either points to a file * or ends in a glob pattern. If `path` points to a directory, * the returned value will have its last path segment stripped - * due to how [`parsePath`][1] works. + * due to how [`path.parse`][1] works. * - * [1]: https://www.npmjs.com/package/parse-filepath + * [1]: https://nodejs.org/api/path.html#path_path_parse_path * * @param {String} path A path * @returns {String} the directory portion of a path. */ -TemplatePath.getDirFromFilePath = function (path) { - return parsePath(path).dir || "."; +TemplatePath.getDirFromFilePath = function (filePath) { + return path.parse(filePath).dir || "."; }; /** * Returns the last path segment in a path (no leading/trailing slashes). * - * Assumes [`parsePath`][1] was called on `path` before. + * Assumes [`path.parse`][1] was called on `path` before. * - * [1]: https://www.npmjs.com/package/parse-filepath + * [1]: https://nodejs.org/api/path.html#path_path_parse_path * * @param {String} path A path * @returns {String} the last path segment in a path diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index cb098be21..117a34c2c 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -1,4 +1,4 @@ -const parsePath = require("parse-filepath"); +const path = require("path"); const TemplatePath = require("./TemplatePath"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); @@ -87,7 +87,7 @@ class TemplatePermalink { } let cleanLink = this._addDefaultLinkFilename(this.buildLink); - let parsed = parsePath(cleanLink); + let parsed = path.parse(cleanLink); return TemplatePath.join( parsed.dir, diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index b9e34e085..0af72e4b4 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -2,7 +2,7 @@ const test = require("ava"); const fs = require("fs"); const rimraf = require("rimraf"); const fastglob = require("fast-glob"); -const parsePath = require("parse-filepath"); +const path = require("path"); const EleventyFiles = require("../src/EleventyFiles"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const TemplateWriter = require("../src/TemplateWriter"); @@ -149,8 +149,14 @@ test("__testGetCollectionsData with custom collection (ascending)", async (t) => let templateMap = await tw._createTemplateMap(paths); let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.customPostsAsc.length, 2); - t.is(parsePath(collectionsData.customPostsAsc[0].inputPath).base, "test1.md"); - t.is(parsePath(collectionsData.customPostsAsc[1].inputPath).base, "test2.md"); + t.is( + path.parse(collectionsData.customPostsAsc[0].inputPath).base, + "test1.md" + ); + t.is( + path.parse(collectionsData.customPostsAsc[1].inputPath).base, + "test2.md" + ); }); test("__testGetCollectionsData with custom collection (descending)", async (t) => { @@ -173,8 +179,8 @@ test("__testGetCollectionsData with custom collection (descending)", async (t) = let templateMap = await tw._createTemplateMap(paths); let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.customPosts.length, 2); - t.is(parsePath(collectionsData.customPosts[0].inputPath).base, "test2.md"); - t.is(parsePath(collectionsData.customPosts[1].inputPath).base, "test1.md"); + t.is(path.parse(collectionsData.customPosts[0].inputPath).base, "test2.md"); + t.is(path.parse(collectionsData.customPosts[1].inputPath).base, "test1.md"); }); test("__testGetCollectionsData with custom collection (filter only to markdown input)", async (t) => { @@ -198,8 +204,8 @@ test("__testGetCollectionsData with custom collection (filter only to markdown i let templateMap = await tw._createTemplateMap(paths); let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.onlyMarkdown.length, 2); - t.is(parsePath(collectionsData.onlyMarkdown[0].inputPath).base, "test1.md"); - t.is(parsePath(collectionsData.onlyMarkdown[1].inputPath).base, "test2.md"); + t.is(path.parse(collectionsData.onlyMarkdown[0].inputPath).base, "test1.md"); + t.is(path.parse(collectionsData.onlyMarkdown[1].inputPath).base, "test2.md"); }); test("Pagination with a Collection", async (t) => { @@ -472,8 +478,8 @@ test("Custom collection returns array", async (t) => { let templateMap = await tw._createTemplateMap(paths); let collectionsData = await templateMap._testGetCollectionsData(); t.is(collectionsData.returnAllInputPaths.length, 2); - t.is(parsePath(collectionsData.returnAllInputPaths[0]).base, "test1.md"); - t.is(parsePath(collectionsData.returnAllInputPaths[1]).base, "test2.md"); + t.is(path.parse(collectionsData.returnAllInputPaths[0]).base, "test1.md"); + t.is(path.parse(collectionsData.returnAllInputPaths[1]).base, "test2.md"); }); test("Custom collection returns a string", async (t) => { From 4f2f2e617c2017658e6f16b652103b9c9113332d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 27 Jul 2021 07:12:20 -0500 Subject: [PATCH 537/746] Add a TODO --- src/Eleventy.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Eleventy.js b/src/Eleventy.js index 9b714f1ae..de70adc7e 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -104,6 +104,7 @@ class Eleventy { } if (performance) { + // TODO this doesn’t reset in serverless mode correctly (cumulative from start of --serve/watch) debug("Eleventy warm up time (in ms) %o", performance.now()); } From f733001f1e76a38e4576b525d7506950f4370fef Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 27 Jul 2021 07:30:26 -0500 Subject: [PATCH 538/746] Apply Prettier to src/ Pairs with #1560. --- .prettierrc.json | 2 +- src/EleventyWatchTargets.js | 10 +++++----- src/Template.js | 4 +++- src/TemplateGlob.js | 2 +- src/TemplateWriter.js | 4 +++- src/Util/Capitalize.js | 6 +++--- src/Util/Pluralize.js | 2 +- src/Util/Sortable.js | 2 +- 8 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index d68aa739e..131fb143d 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,3 +1,3 @@ { - "arrowParens": "avoid" + "arrowParens": "always" } diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index 0079a3213..8a4a52fdd 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -62,7 +62,7 @@ class EleventyWatchTargets { } addAndMakeGlob(targets) { - targets = this._normalizeTargets(targets).map(entry => + targets = this._normalizeTargets(targets).map((entry) => TemplatePath.convertToRecursiveGlobSync(entry) ); this.addRaw(targets); @@ -90,15 +90,15 @@ class EleventyWatchTargets { getJavaScriptDependenciesFromList(files = []) { let depSet = new Set(); files - .filter(file => file.endsWith(".js") || file.endsWith(".cjs")) // TODO does this need to work with aliasing? what other JS extensions will have deps? - .forEach(file => { + .filter((file) => file.endsWith(".js") || file.endsWith(".cjs")) // TODO does this need to work with aliasing? what other JS extensions will have deps? + .forEach((file) => { dependencyTree(file, { allowNotFound: true }) - .map(dependency => { + .map((dependency) => { return TemplatePath.addLeadingDotSlash( TemplatePath.relativePath(dependency) ); }) - .forEach(dependency => { + .forEach((dependency) => { depSet.add(dependency); }); }); diff --git a/src/Template.js b/src/Template.js index 7571b79af..425d6275b 100755 --- a/src/Template.js +++ b/src/Template.js @@ -946,7 +946,9 @@ class Template extends TemplateContent { } else { let filenameRegex = this.inputPath.match(/(\d{4}-\d{2}-\d{2})/); if (filenameRegex !== null) { - let dateObj = DateTime.fromISO(filenameRegex[1], { zone: 'utc' }).toJSDate(); + let dateObj = DateTime.fromISO(filenameRegex[1], { + zone: "utc", + }).toJSDate(); debug( "getMappedDate: using filename regex time for %o of %o: %o", this.inputPath, diff --git a/src/TemplateGlob.js b/src/TemplateGlob.js index f72631be5..ff472eedc 100644 --- a/src/TemplateGlob.js +++ b/src/TemplateGlob.js @@ -25,7 +25,7 @@ class TemplateGlob { if (typeof files === "string") { return TemplateGlob.normalize(files); } else if (Array.isArray(files)) { - return files.map(function(path) { + return files.map(function (path) { return TemplateGlob.normalize(path); }); } else { diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 975290515..73b3a4c9b 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -226,7 +226,9 @@ class TemplateWriter { let promises = []; for (let path of paths) { if (this.extensionMap.hasEngine(path)) { - promises.push(this.templateMap.add(this._createTemplate(path, paths, to))); + promises.push( + this.templateMap.add(this._createTemplate(path, paths, to)) + ); } debug(`${path} begun adding to map.`); } diff --git a/src/Util/Capitalize.js b/src/Util/Capitalize.js index a946db29c..f82f164e4 100644 --- a/src/Util/Capitalize.js +++ b/src/Util/Capitalize.js @@ -1,14 +1,14 @@ -module.exports = function(str, options) { +module.exports = function (str, options) { options = Object.assign( { - lowercaseRestOfWord: false + lowercaseRestOfWord: false, }, options ); return str .split(" ") - .map(function(word) { + .map(function (word) { return ( word.substr(0, 1).toUpperCase() + (options.lowercaseRestOfWord diff --git a/src/Util/Pluralize.js b/src/Util/Pluralize.js index b36f60cde..cc51d8996 100644 --- a/src/Util/Pluralize.js +++ b/src/Util/Pluralize.js @@ -1,3 +1,3 @@ -module.exports = function(count, singleWord, pluralWord) { +module.exports = function (count, singleWord, pluralWord) { return count === 1 ? singleWord : pluralWord; }; diff --git a/src/Util/Sortable.js b/src/Util/Sortable.js index 242b800c5..b32b32b38 100644 --- a/src/Util/Sortable.js +++ b/src/Util/Sortable.js @@ -11,7 +11,7 @@ class Sortable { "A-Z": "Ascending", "Z-A": "Descending", "0-9": "NumericAscending", - "9-0": "NumericDescending" + "9-0": "NumericDescending", }; } From ab8327844107ffe11e8770fc45a3881be78f8d3c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 27 Jul 2021 09:12:12 -0500 Subject: [PATCH 539/746] Skipped test https://github.com/11ty/eleventy/issues/1905 --- test/TemplateTest_Permalink.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index c846efd32..c7832a9d9 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -166,7 +166,7 @@ test("Permalink with dates!", async (t) => { t.is(await tmpl.getOutputPath(), "./dist/2016/01/01/index.html"); }); -test("Permalink with dates on file name regex!", async (t) => { +test.skip("Permalink with dates on file name regex!", async (t) => { let tmpl = getNewTemplate( "./test/stubs/2016-02-01-permalinkdate.liquid", "./test/stubs/", From 34900f3cf9a097faad9ab616f2924ccd1c6bf2b4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 27 Jul 2021 09:27:48 -0500 Subject: [PATCH 540/746] Update deps --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index df30d5832..28ef1dec2 100755 --- a/package.json +++ b/package.json @@ -79,12 +79,12 @@ "ava": "^3.15.0", "husky": "^7.0.1", "js-yaml": "^4.1.0", - "lint-staged": "^11.0.1", + "lint-staged": "^11.1.1", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.3.2", "rimraf": "^3.0.2", - "sass": "^1.35.2", + "sass": "^1.36.0", "toml": "^3.0.0", "vue": "^2.6.14", "vue-server-renderer": "^2.6.14" @@ -93,7 +93,7 @@ "@11ty/dependency-tree": "^2.0.0", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", - "browser-sync": "^2.27.4", + "browser-sync": "^2.27.5", "chalk": "^4.1.1", "chokidar": "^3.5.2", "debug": "^4.3.2", @@ -119,7 +119,7 @@ "pug": "^3.0.2", "recursive-copy": "^2.0.13", "semver": "^7.3.5", - "slugify": "^1.5.3", + "slugify": "^1.6.0", "split": "^1.0.1", "time-require": "^0.1.2", "url-pattern": "^1.0.3", From b19db35064a4b97625f34f477f06802a92e5271f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Tue, 27 Jul 2021 20:49:56 +0200 Subject: [PATCH 541/746] docs: document AsyncEventEmitter and harmonise function signature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Jaenisch --- src/Util/AsyncEventEmitter.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Util/AsyncEventEmitter.js b/src/Util/AsyncEventEmitter.js index acf08e5c5..5a8364d08 100644 --- a/src/Util/AsyncEventEmitter.js +++ b/src/Util/AsyncEventEmitter.js @@ -1,13 +1,22 @@ const EventEmitter = require("events"); +/** + * This class emits events asynchronously. + * It can be used for time measurements during a build. + */ class AsyncEventEmitter extends EventEmitter { + /** + * @param {string} type - The event name to emit. + * @param {*[]} args - Additional arguments that get passed to listeners. + * @returns {Promise<*[]>} - Promise resolves once all listeners were invoked + */ async emit(type, ...args) { let listeners = this.listeners(type); - if (!listeners.length) { - return; + if (listeners.length === 0) { + return []; } - return await Promise.all(listeners.map((h) => h.apply(this, args))); + return Promise.all(listeners.map((listener) => listener.apply(this, args))); } } From f958cd3eec6882dd2613114d827ecbecad3d3d07 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 28 Jul 2021 08:21:49 -0500 Subject: [PATCH 542/746] Uh, fix the syntax errors from a bad merge. --- src/TemplateConfig.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 03f71693a..699f0d6c6 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -160,25 +160,24 @@ class TemplateConfig { debug("rootConfig %o", this.rootConfig); } - processPlugins(localConfig) { - // eleventyConfig.plugins - eleventyConfig.plugins.forEach(({ plugin, options }) => { - eleventyConfig.dir = localConfig.dir; + processPlugins(userConfig, localConfig) { + userConfig.plugins.forEach(({ plugin, options }) => { + userConfig.dir = localConfig.dir; // TODO support function.name in plugin config functions debug("Adding plugin (unknown name: check your config file)."); let pluginBench = aggregateBench.get("Configuration addPlugin"); if (typeof plugin === "function") { pluginBench.before(); let configFunction = plugin; - configFunction(eleventyConfig, options); + configFunction(userConfig, options); pluginBench.after(); } else if (plugin && plugin.configFunction) { pluginBench.before(); if (options && typeof options.init === "function") { - options.init.call(eleventyConfig, plugin.initArguments || {}); + options.init.call(userConfig, plugin.initArguments || {}); } - plugin.configFunction(eleventyConfig, options); + plugin.configFunction(userConfig, options); pluginBench.after(); } else { throw new UserConfigError( @@ -251,9 +250,10 @@ class TemplateConfig { // Delay processing plugins until after the result of localConfig is returned // But BEFORE the rest of the config options are merged // this way we can pass directories and other template information to plugins - this.processPlugins(localConfig); + this.processPlugins(this.userConfig, localConfig); - let eleventyConfigApiMergingObject = eleventyConfig.getMergingConfigObject(); + let eleventyConfigApiMergingObject = + this.userConfig.getMergingConfigObject(); // remove special merge keys from object From ebc8927e052de8f086a5966ef6e1dfc63d3d1a0b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 28 Jul 2021 08:51:18 -0500 Subject: [PATCH 543/746] Fix broken tests. --- src/UserConfig.js | 1 + test/TemplateRenderMarkdownTest.js | 31 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index c45717ae6..3df22861b 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -711,6 +711,7 @@ class UserConfig { extensionMap: this.extensionMap, quietMode: this.quietMode, events: this.events, + plugins: this.plugins, useTemplateCache: this.useTemplateCache, precompiledCollections: this.precompiledCollections, }; diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js index d88e63a90..ffcbfc1b8 100644 --- a/test/TemplateRenderMarkdownTest.js +++ b/test/TemplateRenderMarkdownTest.js @@ -139,12 +139,11 @@ This is some code. test("Markdown Render: use prism highlighter (no language)", async (t) => { let tr = getNewTemplateRender("md"); - let userConfig = new UserConfig(); + let eleventyConfig = new TemplateConfig(); + let userConfig = eleventyConfig.userConfig; userConfig.addPlugin(eleventySyntaxHighlightPlugin); - let markdownHighlight = userConfig.getMergingConfigObject() - .markdownHighlighter; - + let markdownHighlight = eleventyConfig.getConfig().markdownHighlighter; let mdLib = md(); mdLib.set({ highlight: markdownHighlight, @@ -163,11 +162,11 @@ This is some code. test("Markdown Render: use prism highlighter", async (t) => { let tr = getNewTemplateRender("md"); - let userConfig = new UserConfig(); + let eleventyConfig = new TemplateConfig(); + let userConfig = eleventyConfig.userConfig; userConfig.addPlugin(eleventySyntaxHighlightPlugin); - let markdownHighlight = userConfig.getMergingConfigObject() - .markdownHighlighter; + let markdownHighlight = eleventyConfig.getConfig().markdownHighlighter; let mdLib = md(); mdLib.set({ @@ -186,11 +185,11 @@ var key = "value"; test("Markdown Render: use prism highlighter (no space before language)", async (t) => { let tr = getNewTemplateRender("md"); - let userConfig = new UserConfig(); + let eleventyConfig = new TemplateConfig(); + let userConfig = eleventyConfig.userConfig; userConfig.addPlugin(eleventySyntaxHighlightPlugin); - let markdownHighlight = userConfig.getMergingConfigObject() - .markdownHighlighter; + let markdownHighlight = eleventyConfig.getConfig().markdownHighlighter; let mdLib = md(); mdLib.set({ @@ -209,11 +208,11 @@ var key = "value"; test("Markdown Render: use prism highlighter, line highlighting", async (t) => { let tr = getNewTemplateRender("md"); - let userConfig = new UserConfig(); + let eleventyConfig = new TemplateConfig(); + let userConfig = eleventyConfig.userConfig; userConfig.addPlugin(eleventySyntaxHighlightPlugin); - let markdownHighlight = userConfig.getMergingConfigObject() - .markdownHighlighter; + let markdownHighlight = eleventyConfig.getConfig().markdownHighlighter; let mdLib = md(); mdLib.set({ @@ -232,11 +231,11 @@ var key = "value"; test("Markdown Render: use prism highlighter, line highlighting with fallback `text` language.", async (t) => { let tr = getNewTemplateRender("md"); - let userConfig = new UserConfig(); + let eleventyConfig = new TemplateConfig(); + let userConfig = eleventyConfig.userConfig; userConfig.addPlugin(eleventySyntaxHighlightPlugin); - let markdownHighlight = userConfig.getMergingConfigObject() - .markdownHighlighter; + let markdownHighlight = eleventyConfig.getConfig().markdownHighlighter; let mdLib = md(); mdLib.set({ From 0f64e41283f0d6fc9630e49a95e797e754b94b3d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 28 Jul 2021 09:30:34 -0500 Subject: [PATCH 544/746] =?UTF-8?q?Check=20to=20make=20sure=20directory=20?= =?UTF-8?q?is=20non-empty=20when=20creating.=20Fixes=20error=20with=20?= =?UTF-8?q?=E2=80=9CENOENT:=20no=20such=20file=20or=20directory,=20mkdir?= =?UTF-8?q?=20''=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Template.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Template.js b/src/Template.js index 425d6275b..1c0d2ae5a 100755 --- a/src/Template.js +++ b/src/Template.js @@ -760,7 +760,9 @@ class Template extends TemplateContent { // TODO add a cache to check if this was already created let templateOutputDir = path.parse(outputPath).dir; - await fs.promises.mkdir(templateOutputDir, { recursive: true }); + if (templateOutputDir) { + await fs.promises.mkdir(templateOutputDir, { recursive: true }); + } return fs.promises.writeFile(outputPath, finalContent).then(() => { templateBenchmark.after(); From 828ee785fea82c4c84933c53e85ea5a69a883c64 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 28 Jul 2021 12:45:51 -0500 Subject: [PATCH 545/746] Fix regression with serverless config merge --- src/TemplateConfig.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 699f0d6c6..ca3ed762a 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -110,7 +110,7 @@ class TemplateConfig { getConfig() { if (!this.hasConfigMerged) { debugDev("Merging via getConfig (first time)"); - this.config = this.mergeConfig(this.projectConfigPath); + this.config = this.mergeConfig(); this.hasConfigMerged = true; } return this.config; @@ -129,7 +129,8 @@ class TemplateConfig { debugDev( "Merging in getConfig again after setting the local project config path." ); - this.config = this.mergeConfig(path); + this.hasConfigMerged = false; + this.getConfig(); } } @@ -160,24 +161,24 @@ class TemplateConfig { debug("rootConfig %o", this.rootConfig); } - processPlugins(userConfig, localConfig) { - userConfig.plugins.forEach(({ plugin, options }) => { - userConfig.dir = localConfig.dir; + processPlugins({ dir }) { + this.userConfig.plugins.forEach(({ plugin, options }) => { + this.userConfig.dir = dir; // TODO support function.name in plugin config functions debug("Adding plugin (unknown name: check your config file)."); let pluginBench = aggregateBench.get("Configuration addPlugin"); if (typeof plugin === "function") { pluginBench.before(); let configFunction = plugin; - configFunction(userConfig, options); + configFunction(this.userConfig, options); pluginBench.after(); } else if (plugin && plugin.configFunction) { pluginBench.before(); if (options && typeof options.init === "function") { - options.init.call(userConfig, plugin.initArguments || {}); + options.init.call(this.userConfig, plugin.initArguments || {}); } - plugin.configFunction(userConfig, options); + plugin.configFunction(this.userConfig, options); pluginBench.after(); } else { throw new UserConfigError( @@ -195,10 +196,7 @@ class TemplateConfig { */ mergeConfig() { let localConfig = {}; - let path = TemplatePath.join( - TemplatePath.getWorkingDir(), - this.projectConfigPath - ); + let path = TemplatePath.absolutePath(this.projectConfigPath); debug(`Merging config with ${path}`); @@ -250,7 +248,7 @@ class TemplateConfig { // Delay processing plugins until after the result of localConfig is returned // But BEFORE the rest of the config options are merged // this way we can pass directories and other template information to plugins - this.processPlugins(this.userConfig, localConfig); + this.processPlugins(localConfig); let eleventyConfigApiMergingObject = this.userConfig.getMergingConfigObject(); From e6a8077edc0a256daefa1e94a3c4103bb972dccc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 28 Jul 2021 12:47:18 -0500 Subject: [PATCH 546/746] Reuse inputDir when returned in configuration file. Thanks @MadeByMike via https://github.com/11ty/eleventy/pull/1320 --- src/Plugins/ServerlessBundlerPlugin.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 39432fb42..bc6867caf 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -265,6 +265,11 @@ class BundlerHelper { } function EleventyPlugin(eleventyConfig, options = {}) { + let inputDir = "."; + if (eleventyConfig.dir && eleventyConfig.dir.input) { + inputDir = eleventyConfig.dir.input; + } + options = Object.assign( { name: "", @@ -286,7 +291,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { copyEnabled: true, // Input directory (used to generate the default serverless file) - inputDir: ".", + inputDir, }, options ); From 598e4ca016a25bd3f87805f75e035fa57c5de8ef Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 29 Jul 2021 08:28:09 -0500 Subject: [PATCH 547/746] Ability to re-use logger in plugins (for serverless plugin to works with verbose mode for free) --- src/Eleventy.js | 6 ++++++ src/Plugins/ServerlessBundlerPlugin.js | 11 ++++++----- src/TemplateConfig.js | 17 ++++++++++++++++- src/Util/ConsoleLogger.js | 2 ++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index de70adc7e..f88322f10 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -42,6 +42,8 @@ class Eleventy { } } + this.eleventyConfig.setLogger(this.logger); + if (options.config && typeof options.config === "function") { // TODO use return object here? options.config(this.eleventyConfig.userConfig); @@ -449,6 +451,7 @@ Verbose Output: ${this.verboseMode}`); /* Setter for Logger */ set logger(logger) { + this.eleventyConfig.setLogger(logger); this._logger = logger; } @@ -478,6 +481,9 @@ Verbose Output: ${this.verboseMode}`); if (process.env.DEBUG) { isVerbose = false; } + if (this.logger) { + this.logger.isVerbose = isVerbose; + } bench.setVerboseOutput(isVerbose); this.verboseMode = isVerbose; diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index bc6867caf..b62f204f5 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -102,11 +102,12 @@ function addRedirectsWithoutDuplicates(name, config, newRedirects) { } class BundlerHelper { - constructor(name, options) { + constructor(name, options, eleventyConfig) { this.name = name; this.options = options; this.dir = path.join(options.functionsDir, name); this.copyCount = 0; + this.eleventyConfig = eleventyConfig; } reset() { @@ -232,7 +233,7 @@ class BundlerHelper { res.write(result.body); res.end(); - console.log( + this.eleventyConfig.logger.forceLog( `Serverless (${this.name}): ${req.url} (${Date.now() - start}ms)` ); }; @@ -303,7 +304,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { } if (process.env.ELEVENTY_SOURCE === "cli") { - let helper = new BundlerHelper(options.name, options); + let helper = new BundlerHelper(options.name, options, eleventyConfig); eleventyConfig.setBrowserSyncConfig({ middleware: [helper.browserSyncMiddleware()], @@ -340,8 +341,8 @@ function EleventyPlugin(eleventyConfig, options = {}) { await Promise.all(promises); } - console.log( - `Eleventy Serverless: ${helper.copyCount} file${ + eleventyConfig.logger.log( + `Serverless: ${helper.copyCount} file${ helper.copyCount !== 1 ? "s" : "" } bundled to ${helper.getOutputPath("")}.` ); diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index ca3ed762a..7106bffeb 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -64,6 +64,11 @@ class TemplateConfig { this.hasConfigMerged = false; } + /* Getter for Logger */ + setLogger(logger) { + this.logger = logger; + } + /** * Normalises local project config file path. * @@ -161,9 +166,19 @@ class TemplateConfig { debug("rootConfig %o", this.rootConfig); } + /* + * Process the userland plugins from the Config + * + * @param {Object} - the return Object from the user’s config file. + */ processPlugins({ dir }) { + this.userConfig.dir = dir; + + if (this.logger) { + this.userConfig.logger = this.logger; + } + this.userConfig.plugins.forEach(({ plugin, options }) => { - this.userConfig.dir = dir; // TODO support function.name in plugin config functions debug("Adding plugin (unknown name: check your config file)."); let pluginBench = aggregateBench.get("Configuration addPlugin"); diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 59569a9a7..931821a82 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -69,6 +69,8 @@ class ConsoleLogger { if (!forceToConsole && (!this.isVerbose || process.env.DEBUG)) { debug(message); } else if (this._logger !== false) { + message = `[11ty] ${message}`; + let logger = this._logger || console; if (chalkColor && this.isChalkEnabled) { logger[type](chalk[chalkColor](message)); From a11a8ba97f0d7c1447e8cf711ac861ef5e5a1e0d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 29 Jul 2021 09:11:20 -0500 Subject: [PATCH 548/746] Reinstate async filter test in liquid!! Fixes https://github.com/11ty/eleventy/issues/831 --- test/TemplateRenderLiquidTest.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 46bba3a72..4c40827e3 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -176,17 +176,16 @@ test("Liquid Custom Filter", async (t) => { t.is(await tr._testRender("{{ 'test' | prefixWithZach }}", {}), "Zachtest"); }); -test.skip("Liquid Async Filter", async (t) => { +test("Liquid Async Filter", async (t) => { let tr = getNewTemplateRender("liquid", "test/stubs"); - tr.engine.addFilter({ - myAsyncFilter: function (value) { - return new Promise((resolve, reject) => { - setTimeout(function () { - resolve(`HI${value}`); - }, 100); - }); - }, + tr.engine.addFilter("myAsyncFilter", async function (value) { + return new Promise((resolve, reject) => { + setTimeout(function () { + resolve(`HI${value}`); + }, 100); + }); }); + let fn = await tr.getCompiledTemplate("{{ 'test' | myAsyncFilter }}"); t.is((await fn()).trim(), "HItest"); }); From 94757865113283a0993f65e926bf810d9a633e13 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 29 Jul 2021 22:07:46 -0500 Subject: [PATCH 549/746] Fixes https://github.com/11ty/eleventy/pull/1909 by removing unnecessary Capitlize utility --- src/Util/Capitalize.js | 20 -------------------- src/Util/Sortable.js | 27 +++++++++++++++++---------- test/CapitalizeTest.js | 12 ------------ test/SortableTest.js | 16 ---------------- 4 files changed, 17 insertions(+), 58 deletions(-) delete mode 100644 src/Util/Capitalize.js delete mode 100644 test/CapitalizeTest.js diff --git a/src/Util/Capitalize.js b/src/Util/Capitalize.js deleted file mode 100644 index f82f164e4..000000000 --- a/src/Util/Capitalize.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = function (str, options) { - options = Object.assign( - { - lowercaseRestOfWord: false, - }, - options - ); - - return str - .split(" ") - .map(function (word) { - return ( - word.substr(0, 1).toUpperCase() + - (options.lowercaseRestOfWord - ? word.substr(1).toLowerCase() - : word.substr(1)) - ); - }) - .join(" "); -}; diff --git a/src/Util/Sortable.js b/src/Util/Sortable.js index b32b32b38..e9c052bd1 100644 --- a/src/Util/Sortable.js +++ b/src/Util/Sortable.js @@ -1,5 +1,3 @@ -const capitalize = require("./Capitalize"); - class Sortable { constructor() { this.isSortAscending = true; @@ -8,10 +6,10 @@ class Sortable { this._dirty = true; this.sortFunctionStringMap = { - "A-Z": "Ascending", - "Z-A": "Descending", - "0-9": "NumericAscending", - "9-0": "NumericDescending", + "A-Z": "sortFunctionAscending", + "Z-A": "sortFunctionDescending", + "0-9": "sortFunctionNumericAscending", + "9-0": "sortFunctionNumericDescending", }; } @@ -28,11 +26,20 @@ class Sortable { if (!sortFunction) { sortFunction = this.getSortFunction(); } else if (typeof sortFunction === "string") { - if (sortFunction in this.sortFunctionStringMap) { - sortFunction = this.sortFunctionStringMap[sortFunction]; + let key = sortFunction; + let name; + if (key in this.sortFunctionStringMap) { + name = this.sortFunctionStringMap[key]; + } + if (Sortable[name]) { + sortFunction = Sortable[name]; + } else { + throw new Error( + `Invalid String argument for sort(). Received \`${key}\`. Valid values: ${Object.keys( + this.sortFunctionStringMap + )}` + ); } - - sortFunction = Sortable["sortFunction" + capitalize(sortFunction)]; } return this.items.slice().sort(sortFunction); diff --git a/test/CapitalizeTest.js b/test/CapitalizeTest.js deleted file mode 100644 index 9dbad903e..000000000 --- a/test/CapitalizeTest.js +++ /dev/null @@ -1,12 +0,0 @@ -const test = require("ava"); -const capitalize = require("../src/Util/Capitalize"); - -test("capitalize", (t) => { - t.is(capitalize("hello"), "Hello"); - t.is(capitalize("hello world"), "Hello World"); - t.is(capitalize("Testing TESTING"), "Testing TESTING"); - t.is( - capitalize("Testing TESTING", { lowercaseRestOfWord: true }), - "Testing Testing" - ); -}); diff --git a/test/SortableTest.js b/test/SortableTest.js index da6c98cc7..49cf34f53 100644 --- a/test/SortableTest.js +++ b/test/SortableTest.js @@ -162,22 +162,6 @@ test("Date Descending", (t) => { t.deepEqual(s.sort(), [date3, date2, date1]); }); -test("Alphabetic Ascending (str sort arg)", (t) => { - let s = new Sortable(); - s.add("a"); - s.add("z"); - s.add("m"); - t.deepEqual(s.sort("ascending"), ["a", "m", "z"]); -}); - -test("Alphabetic Descending (str sort arg)", (t) => { - let s = new Sortable(); - s.add("a"); - s.add("z"); - s.add("m"); - t.deepEqual(s.sort("descending"), ["z", "m", "a"]); -}); - test("Alphabetic Ascending (short str sort arg)", (t) => { let s = new Sortable(); s.add("a"); From b19ce68e79c41f663a22fb7e84b2b3a59883542e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Fri, 30 Jul 2021 22:56:45 +0200 Subject: [PATCH 550/746] docs: document ConsoleLogger class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Jaenisch --- src/Util/ConsoleLogger.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 931821a82..5d8bea6d2 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -2,10 +2,16 @@ const chalk = require("chalk"); const debug = require("debug")("Eleventy:Logger"); const Readable = require("stream").Readable; const split = require("split"); +/** @typedef {import('stream').Readble Readable} */ +/** + * Logger implementation that logs to STDOUT. + */ class ConsoleLogger { constructor() { + /** @private */ this._isVerbose = true; + /** @type {Readable} */ this.outputStream = Readable(); } @@ -17,6 +23,7 @@ class ConsoleLogger { this._isVerbose = !!verbose; } + /** @returns {boolean} */ get isChalkEnabled() { if (this._isChalkEnabled !== undefined) { return this._isChalkEnabled; @@ -32,23 +39,28 @@ class ConsoleLogger { this._logger = logger; } + /** @param {string} msg */ log(msg) { this.message(msg); } + /** @param {string} msg */ forceLog(msg) { this.message(msg, undefined, undefined, true); } + /** @param {string} msg */ warn(msg) { this.message(msg, "warn", "yellow"); } // Is this used? + /** @param {string} msg */ error(msg) { this.message(msg, "error", "red"); } + /** @param {string} msg */ toStream(msg) { this.outputStream.push(msg); } @@ -65,6 +77,14 @@ class ConsoleLogger { return this.outputStream; } + /** + * Formats the message to log. + * + * @param {string} message - The raw message to log. + * @param {'log'|'warn'|'error'} [type='log'] - The error level to log. + * @param {boolean} [chalkColor=false] - Use coloured log output? + * @param {boolean} [forceToConsole=false] - Enforce a log on console instead of specified target. + */ message(message, type = "log", chalkColor = false, forceToConsole = false) { if (!forceToConsole && (!this.isVerbose || process.env.DEBUG)) { debug(message); From dc71620c92d1042f026021a6e6785bdc582228a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Sat, 31 Jul 2021 00:09:27 +0200 Subject: [PATCH 551/746] fix: spell readble correctly as readable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Jaenisch --- src/Util/ConsoleLogger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 5d8bea6d2..f52c0135e 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -2,7 +2,7 @@ const chalk = require("chalk"); const debug = require("debug")("Eleventy:Logger"); const Readable = require("stream").Readable; const split = require("split"); -/** @typedef {import('stream').Readble Readable} */ +/** @typedef {import('stream').Readable Readable} */ /** * Logger implementation that logs to STDOUT. From 975816f9d53d480fc22d757b91d69a785dfd50aa Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Aug 2021 10:20:11 -0500 Subject: [PATCH 552/746] Removing ELEVENTY_EXPERIMENTAL requirement for `addExtension` in 1.0 --- src/UserConfig.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index 3df22861b..a1c77300a 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -639,10 +639,6 @@ class UserConfig { } addExtension(fileExtension, options = {}) { - if (!process.env.ELEVENTY_EXPERIMENTAL) { - return; - } - this.extensionMap.add( Object.assign( { From d55eb07d791f7534cb3f713c2e5827952d133893 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Aug 2021 10:49:12 -0500 Subject: [PATCH 553/746] Rename a variable for https://github.com/11ty/eleventy/issues/1742 --- src/Template.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Template.js b/src/Template.js index 1c0d2ae5a..07c5c411b 100755 --- a/src/Template.js +++ b/src/Template.js @@ -946,15 +946,15 @@ class Template extends TemplateContent { } } } else { - let filenameRegex = this.inputPath.match(/(\d{4}-\d{2}-\d{2})/); - if (filenameRegex !== null) { - let dateObj = DateTime.fromISO(filenameRegex[1], { + let filepathRegex = this.inputPath.match(/(\d{4}-\d{2}-\d{2})/); + if (filepathRegex !== null) { + let dateObj = DateTime.fromISO(filepathRegex[1], { zone: "utc", }).toJSDate(); debug( "getMappedDate: using filename regex time for %o of %o: %o", this.inputPath, - filenameRegex[1], + filepathRegex[1], dateObj ); return dateObj; From cf10ae26acc181dcdca1f79cc0c0b97354964f81 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Aug 2021 16:14:03 -0500 Subject: [PATCH 554/746] =?UTF-8?q?Fix=20regression=20with=20https://githu?= =?UTF-8?q?b.com/11ty/eleventy/pull/1320=20fix=20error=20when=20a=20config?= =?UTF-8?q?=20that=20doesn=E2=80=99t=20return=20an=20object.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TemplateConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 7106bffeb..8cf347a52 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -263,7 +263,7 @@ class TemplateConfig { // Delay processing plugins until after the result of localConfig is returned // But BEFORE the rest of the config options are merged // this way we can pass directories and other template information to plugins - this.processPlugins(localConfig); + this.processPlugins(localConfig || {}); let eleventyConfigApiMergingObject = this.userConfig.getMergingConfigObject(); From 324cb26a858286d92a3c9c17c885dadcfab89982 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Aug 2021 16:14:58 -0500 Subject: [PATCH 555/746] Add limited number of tests for EleventyServerless Related to #1901 --- src/Eleventy.js | 3 ++- test/ServerlessTest.js | 24 +++++++++++++++++++ .../test1/eleventy-serverless-map.json | 3 +++ .../functions/test1/eleventy.config.js | 5 ++++ test/serverless-stubs-config/test1.md | 6 +++++ .../test1/eleventy-serverless-map.json | 3 +++ test/serverless-stubs/test1.md | 6 +++++ 7 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/ServerlessTest.js create mode 100644 test/serverless-stubs-config/functions/test1/eleventy-serverless-map.json create mode 100644 test/serverless-stubs-config/functions/test1/eleventy.config.js create mode 100644 test/serverless-stubs-config/test1.md create mode 100644 test/serverless-stubs/functions/test1/eleventy-serverless-map.json create mode 100644 test/serverless-stubs/test1.md diff --git a/src/Eleventy.js b/src/Eleventy.js index f88322f10..0c51805e6 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -364,7 +364,8 @@ class Eleventy { }; debug(`Directories: -Input: ${dirs.input} +Input (Dir): ${dirs.input} +Input (File?): ${this.rawInput} Data: ${dirs.data} Includes: ${dirs.includes} Layouts: ${dirs.layouts} diff --git a/test/ServerlessTest.js b/test/ServerlessTest.js new file mode 100644 index 000000000..5e7c424c0 --- /dev/null +++ b/test/ServerlessTest.js @@ -0,0 +1,24 @@ +const test = require("ava"); +const EleventyServerless = require("../src/Serverless"); + +test("Test a one-template markdown render.", async (t) => { + let elev = new EleventyServerless("test1", { + path: "/", + query: {}, + inputDir: "./test/serverless-stubs/", + functionsDir: "./test/serverless-stubs/functions/", + }); + + t.is((await elev.render()).trim(), "

Hi

"); +}); + +test("Test a transform on serverless output.", async (t) => { + let elev = new EleventyServerless("test1", { + path: "/", + query: {}, + inputDir: "./test/serverless-stubs-config/", + functionsDir: "./test/serverless-stubs-config/functions/", + }); + + t.is((await elev.render()).trim(), "

Hi

Hi

"); +}); diff --git a/test/serverless-stubs-config/functions/test1/eleventy-serverless-map.json b/test/serverless-stubs-config/functions/test1/eleventy-serverless-map.json new file mode 100644 index 000000000..e04d1f71d --- /dev/null +++ b/test/serverless-stubs-config/functions/test1/eleventy-serverless-map.json @@ -0,0 +1,3 @@ +{ + "/": "./test/serverless-stubs-config/test1.md" +} \ No newline at end of file diff --git a/test/serverless-stubs-config/functions/test1/eleventy.config.js b/test/serverless-stubs-config/functions/test1/eleventy.config.js new file mode 100644 index 000000000..70e37d8eb --- /dev/null +++ b/test/serverless-stubs-config/functions/test1/eleventy.config.js @@ -0,0 +1,5 @@ +module.exports = function (eleventyConfig) { + eleventyConfig.addTransform("transform-html", function (content) { + return `${content}`.trim() + "

Hi

"; + }); +}; diff --git a/test/serverless-stubs-config/test1.md b/test/serverless-stubs-config/test1.md new file mode 100644 index 000000000..fb35093f5 --- /dev/null +++ b/test/serverless-stubs-config/test1.md @@ -0,0 +1,6 @@ +--- +permalink: + test1: / +--- + +# Hi diff --git a/test/serverless-stubs/functions/test1/eleventy-serverless-map.json b/test/serverless-stubs/functions/test1/eleventy-serverless-map.json new file mode 100644 index 000000000..0d593ab76 --- /dev/null +++ b/test/serverless-stubs/functions/test1/eleventy-serverless-map.json @@ -0,0 +1,3 @@ +{ + "/": "./test/serverless-stubs/test1.md" +} \ No newline at end of file diff --git a/test/serverless-stubs/test1.md b/test/serverless-stubs/test1.md new file mode 100644 index 000000000..fb35093f5 --- /dev/null +++ b/test/serverless-stubs/test1.md @@ -0,0 +1,6 @@ +--- +permalink: + test1: / +--- + +# Hi From 21630bfc292a5d42cf61b86f3b51841419c7cd67 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Aug 2021 16:23:10 -0500 Subject: [PATCH 556/746] Add Windows support for TemplatePath.absolutePath --- src/TemplatePath.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/TemplatePath.js b/src/TemplatePath.js index 680891d72..4c59e27a5 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -134,18 +134,18 @@ TemplatePath.normalizeUrlPath = function (...urlPaths) { TemplatePath.absolutePath = function (...paths) { let i = 0; // check all the paths before we short circuit from the first index - for (let path of paths) { - if (path.startsWith("/") && i > 0) { + for (let p of paths) { + if (path.isAbsolute(p) && i > 0) { throw new Error( - `Only the first parameter to Template.absolutePath can be an absolute path. Received: ${path} from ${paths}` + `Only the first parameter to Template.absolutePath can be an absolute path. Received: ${p} from ${paths}` ); } i++; } let j = 0; - for (let path of paths) { - if (j === 0 && path.startsWith("/")) { + for (let p of paths) { + if (j === 0 && path.isAbsolute(p)) { return TemplatePath.join(...paths); } j++; From 81075ec3a29b5c06f1a9c23efa1a58f910e51416 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 6 Aug 2021 16:56:12 -0500 Subject: [PATCH 557/746] Fixes https://github.com/11ty/eleventy/issues/1911 --- src/Plugins/ServerlessBundlerPlugin.js | 12 ++++++++++++ src/TemplateData.js | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index b62f204f5..53e57b314 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -362,6 +362,18 @@ function EleventyPlugin(eleventyConfig, options = {}) { helper.writeDependencyGlobalDataFile(fileList); }); + eleventyConfig.on("eleventy.dataFiles", async (fileList) => { + if (!options.copyEnabled) { + return; + } + + let promises = []; + for (let file of fileList) { + promises.push(helper.recursiveCopy(file)); + } + await Promise.all(promises); + }); + eleventyConfig.on("eleventy.directories", async (dirs) => { if (!options.copyEnabled) { return; diff --git a/src/TemplateData.js b/src/TemplateData.js index b615c304c..149e5a2a0 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -343,6 +343,8 @@ class TemplateData { return this._fsExistsCache.exists(path); }); + this.config.events.emit("eleventy.dataFiles", localDataPaths); + if (!localDataPaths.length) { return localData; } From c611e7463a4a0e6dd53c322721d0a6788db22c0f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 9 Aug 2021 10:55:47 -0500 Subject: [PATCH 558/746] Add tests for #1060. Also fixes issue with using literal value https://github.com/11ty/eleventy/pull/1060#issuecomment-881936530 --- src/UserConfig.js | 14 +++++++++----- test/TemplateRenderNunjucksTest.js | 30 ++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index a1c77300a..057a46623 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -245,7 +245,7 @@ class UserConfig { return this; } - addNunjucksGlobal(name, globalFn) { + addNunjucksGlobal(name, globalType) { name = this.getNamespacedName(name); if (this.nunjucksGlobals[name]) { @@ -257,10 +257,14 @@ class UserConfig { ); } - this.nunjucksGlobals[name] = bench.add( - `"${name}" Nunjucks Global`, - globalFn - ); + if (typeof globalType === "function") { + this.nunjucksGlobals[name] = bench.add( + `"${name}" Nunjucks Global`, + globalType + ); + } else { + this.nunjucksGlobals[name] = globalType; + } } addTransform(name, callback) { diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index c147400ca..07919d2e5 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -3,15 +3,15 @@ const TemplateRender = require("../src/TemplateRender"); const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); -function getNewTemplateRender(name, inputDir) { - let eleventyConfig = new TemplateConfig(); +function getNewTemplateRender(name, inputDir, eleventyConfig) { + if (!eleventyConfig) { + eleventyConfig = new TemplateConfig(); + } let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; } -class TestEleventyError extends Error {} - async function getPromise(resolveTo) { return new Promise(function (resolve) { setTimeout(function () { @@ -845,3 +845,25 @@ test("Nunjucks Parse for Symbols with custom block", async (t) => { t.deepEqual(engine.parseForSymbols("

{{ name }} {% test %}

"), ["name"]); }); + +test("Use addNunjucksGlobal with function", async (t) => { + let templateConfig = new TemplateConfig(); + templateConfig.userConfig.addNunjucksGlobal("fortytwo", function () { + return 42; + }); + + let tr = getNewTemplateRender("njk", null, templateConfig); + + let fn = await tr.getCompiledTemplate("

{{ fortytwo() }}

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

42

"); +}); + +test("Use addNunjucksGlobal with literal", async (t) => { + let templateConfig = new TemplateConfig(); + templateConfig.userConfig.addNunjucksGlobal("fortytwo", 42); + + let tr = getNewTemplateRender("njk", null, templateConfig); + + let fn = await tr.getCompiledTemplate("

{{ fortytwo }}

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

42

"); +}); From ad8a020a5d95bafe1ef0bb8ab5a52cddf6209922 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 9 Aug 2021 10:58:48 -0500 Subject: [PATCH 559/746] Add skipped test for async --- test/TemplateRenderNunjucksTest.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 07919d2e5..f62621e5f 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -867,3 +867,14 @@ test("Use addNunjucksGlobal with literal", async (t) => { let fn = await tr.getCompiledTemplate("

{{ fortytwo }}

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

42

"); }); + +// Async not supported here +test.skip("Use addNunjucksGlobal with async function", async (t) => { + let templateConfig = new TemplateConfig(); + templateConfig.userConfig.addNunjucksGlobal("fortytwo", getPromise(42)); + + let tr = getNewTemplateRender("njk", null, templateConfig); + + let fn = await tr.getCompiledTemplate("

{{ fortytwo() }}

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

42

"); +}); From 49e8acaa752f43d57778e590224f68879d9ade38 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 9 Aug 2021 16:38:46 -0500 Subject: [PATCH 560/746] Minor dep updates --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 28ef1dec2..c29ebc93b 100755 --- a/package.json +++ b/package.json @@ -79,12 +79,12 @@ "ava": "^3.15.0", "husky": "^7.0.1", "js-yaml": "^4.1.0", - "lint-staged": "^11.1.1", + "lint-staged": "^11.1.2", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.3.2", "rimraf": "^3.0.2", - "sass": "^1.36.0", + "sass": "^1.37.5", "toml": "^3.0.0", "vue": "^2.6.14", "vue-server-renderer": "^2.6.14" @@ -94,7 +94,7 @@ "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.5", - "chalk": "^4.1.1", + "chalk": "^4.1.2", "chokidar": "^3.5.2", "debug": "^4.3.2", "dependency-graph": "^0.11.0", @@ -106,8 +106,8 @@ "is-glob": "^4.0.1", "liquidjs": "^9.25.1", "lodash": "^4.17.21", - "luxon": "^2.0.1", - "markdown-it": "^12.1.0", + "luxon": "^2.0.2", + "markdown-it": "^12.2.0", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^5.0.0", From f46473d8459f0df21db9ce86f920659f3da00f99 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 9 Aug 2021 16:39:00 -0500 Subject: [PATCH 561/746] v1.0.0-canary.40 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c29ebc93b..de0307797 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.39", + "version": "1.0.0-canary.40", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From bbe9dd8f6adbbce495519299ee278d497628fefc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 10 Aug 2021 17:28:00 -0500 Subject: [PATCH 562/746] Regression with Nested addPlugin calls. Fixes https://github.com/11ty/eleventy/issues/1925 --- src/TemplateConfig.js | 25 ++--------- src/UserConfig.js | 37 +++++++++++++++- test/TemplateConfigTest.js | 90 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 23 deletions(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 8cf347a52..032f3ecf5 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -8,7 +8,6 @@ const UserConfig = require("./UserConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); const debugDev = require("debug")("Dev:Eleventy:TemplateConfig"); const deleteRequireCache = require("./Util/DeleteRequireCache"); -const aggregateBench = require("./BenchmarkManager").get("Aggregate"); /** * @module 11ty/eleventy/TemplateConfig @@ -178,28 +177,10 @@ class TemplateConfig { this.userConfig.logger = this.logger; } - this.userConfig.plugins.forEach(({ plugin, options }) => { - // TODO support function.name in plugin config functions - debug("Adding plugin (unknown name: check your config file)."); - let pluginBench = aggregateBench.get("Configuration addPlugin"); - if (typeof plugin === "function") { - pluginBench.before(); - let configFunction = plugin; - configFunction(this.userConfig, options); - pluginBench.after(); - } else if (plugin && plugin.configFunction) { - pluginBench.before(); - if (options && typeof options.init === "function") { - options.init.call(this.userConfig, plugin.initArguments || {}); - } + this.userConfig._enablePluginExecution(); - plugin.configFunction(this.userConfig, options); - pluginBench.after(); - } else { - throw new UserConfigError( - "Invalid EleventyConfig.addPlugin signature. Should be a function or a valid Eleventy plugin object." - ); - } + this.userConfig.plugins.forEach(({ plugin, options }) => { + this.userConfig._executePlugin(plugin, options); }); } diff --git a/src/UserConfig.js b/src/UserConfig.js index 057a46623..14ead844d 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -5,6 +5,7 @@ const EventEmitter = require("./Util/AsyncEventEmitter"); const EleventyBaseError = require("./EleventyBaseError"); const merge = require("./Util/Merge"); const bench = require("./BenchmarkManager").get("Configuration"); +const aggregateBench = require("./BenchmarkManager").get("Aggregate"); const debug = require("debug")("Eleventy:UserConfig"); const pkg = require("../package.json"); @@ -72,6 +73,7 @@ class UserConfig { this.quietMode = false; this.plugins = []; + this._pluginExecution = false; this.useTemplateCache = true; } @@ -94,6 +96,11 @@ class UserConfig { return this.events.emit(eventName, ...args); } + // Internal method + _enablePluginExecution() { + this._pluginExecution = true; + } + // This is a method for plugins, probably shouldn’t use this in projects. // Projects should use `setLibrary` as documented here: // https://github.com/11ty/eleventy/blob/master/docs/engines/markdown.md#use-your-own-options @@ -301,7 +308,35 @@ class UserConfig { } addPlugin(plugin, options) { - this.plugins.push({ plugin, options }); + if (this._pluginExecution) { + this._executePlugin(plugin, options); + } else { + this.plugins.push({ plugin, options }); + } + } + + _executePlugin(plugin, options) { + // TODO support function.name in plugin config functions + debug("Adding plugin (unknown name: check your config file)."); + let pluginBench = aggregateBench.get("Configuration addPlugin"); + if (typeof plugin === "function") { + pluginBench.before(); + let configFunction = plugin; + configFunction(this, options); + pluginBench.after(); + } else if (plugin && plugin.configFunction) { + pluginBench.before(); + if (options && typeof options.init === "function") { + options.init.call(this, plugin.initArguments || {}); + } + + plugin.configFunction(this, options); + pluginBench.after(); + } else { + throw new UserConfigError( + "Invalid EleventyConfig.addPlugin signature. Should be a function or a valid Eleventy plugin object." + ); + } } getNamespacedName(name) { diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 0429cc027..648d41611 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -404,3 +404,93 @@ test(".addWatchTarget adds a watch target", (t) => { let cfg = templateCfg.getConfig(); t.deepEqual(cfg.additionalWatchTargets, ["/testdirectory/"]); }); + +test("Nested .addPlugin calls", (t) => { + t.plan(2); + let templateCfg = new TemplateConfig(); + + templateCfg.userConfig.addPlugin(function OuterPlugin(eleventyConfig) { + t.truthy(true); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + t.truthy(true); + }); + }); + + templateCfg.getConfig(); +}); + +test("Nested .addPlugin calls (×3)", (t) => { + t.plan(3); + let templateCfg = new TemplateConfig(); + + templateCfg.userConfig.addPlugin(function OuterPlugin(eleventyConfig) { + t.truthy(true); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + t.truthy(true); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + t.truthy(true); + }); + }); + }); + + templateCfg.getConfig(); +}); + +test("Nested .addPlugin calls order", (t) => { + t.plan(3); + let templateCfg = new TemplateConfig(); + let order = []; + + templateCfg.userConfig.addPlugin(function OuterPlugin(eleventyConfig) { + order.push(1); + t.deepEqual(order, [1]); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + order.push(2); + t.deepEqual(order, [1, 2]); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + order.push(3); + t.deepEqual(order, [1, 2, 3]); + }); + }); + }); + + templateCfg.getConfig(); +}); + +test("Nested .addPlugin calls. More complex order", (t) => { + t.plan(5); + let templateCfg = new TemplateConfig(); + let order = []; + + templateCfg.userConfig.addPlugin(function OuterPlugin(eleventyConfig) { + order.push("1"); + t.deepEqual(order, ["1"]); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + order.push("2"); + t.deepEqual(order, ["1", "2"]); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + order.push("3a"); + t.deepEqual(order, ["1", "2", "3a"]); + }); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + order.push("3b"); + t.deepEqual(order, ["1", "2", "3a", "3b"]); + }); + }); + + eleventyConfig.addPlugin(function InnerPlugin(eleventyConfig) { + order.push("2b"); + t.deepEqual(order, ["1", "2", "3a", "3b", "2b"]); + }); + }); + + templateCfg.getConfig(); +}); From ecd813be1a8153f4e290d4ba309e6ac21177f4da Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 10 Aug 2021 17:30:22 -0500 Subject: [PATCH 563/746] Adds a comment about nested calls --- src/TemplateConfig.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 032f3ecf5..fbbbd1f3f 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -177,6 +177,7 @@ class TemplateConfig { this.userConfig.logger = this.logger; } + // for Nested addPlugin calls, Issue #1925 this.userConfig._enablePluginExecution(); this.userConfig.plugins.forEach(({ plugin, options }) => { From 89309a7b19d4f27827a8de73228a830a38cd9e19 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 10 Aug 2021 17:31:00 -0500 Subject: [PATCH 564/746] v1.0.0-canary.41 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de0307797..954db15c8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.40", + "version": "1.0.0-canary.41", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 292ec3083ebce80ce733a4ef4c72d17d11204b16 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 13 Aug 2021 20:18:07 -0500 Subject: [PATCH 565/746] We now write a metadata file to the bundler output for configuration data, this will prevent mismatched data when making changes to the input directory after the serverless index.js file has already been generated. Fixes #1929 --- src/Eleventy.js | 2 +- .../DefaultServerlessFunctionContent.js | 1 - src/Plugins/ServerlessBundlerPlugin.js | 41 +++++++++++-------- src/Serverless.js | 21 +++++++++- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 0c51805e6..5eeed93e3 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -365,7 +365,7 @@ class Eleventy { debug(`Directories: Input (Dir): ${dirs.input} -Input (File?): ${this.rawInput} +Input (File): ${this.rawInput} Data: ${dirs.data} Includes: ${dirs.includes} Layouts: ${dirs.layouts} diff --git a/src/Plugins/DefaultServerlessFunctionContent.js b/src/Plugins/DefaultServerlessFunctionContent.js index 47945cd43..a44268eb0 100644 --- a/src/Plugins/DefaultServerlessFunctionContent.js +++ b/src/Plugins/DefaultServerlessFunctionContent.js @@ -8,7 +8,6 @@ async function handler(event) { let elev = new EleventyServerless("%%NAME%%", { path: event.path, query: event.queryStringParameters, - inputDir: "%%INPUT_DIR%%", functionsDir: "%%FUNCTIONS_DIR%%", }); diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 53e57b314..a4a769830 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -255,7 +255,6 @@ class BundlerHelper { let contents = await fsp.readFile(defaultContentPath, "utf-8"); contents = contents.replace(/\%\%NAME\%\%/g, this.name); - contents = contents.replace(/\%\%INPUT_DIR\%\%/g, this.options.inputDir); contents = contents.replace( /\%\%FUNCTIONS_DIR\%\%/g, this.options.functionsDir @@ -266,11 +265,6 @@ class BundlerHelper { } function EleventyPlugin(eleventyConfig, options = {}) { - let inputDir = "."; - if (eleventyConfig.dir && eleventyConfig.dir.input) { - inputDir = eleventyConfig.dir.input; - } - options = Object.assign( { name: "", @@ -290,9 +284,6 @@ function EleventyPlugin(eleventyConfig, options = {}) { // Useful for local develop to disable all bundle copying copyEnabled: true, - - // Input directory (used to generate the default serverless file) - inputDir, }, options ); @@ -375,16 +366,31 @@ function EleventyPlugin(eleventyConfig, options = {}) { }); eleventyConfig.on("eleventy.directories", async (dirs) => { - if (!options.copyEnabled) { - return; - } - let promises = []; - promises.push(helper.recursiveCopy(dirs.data)); - promises.push(helper.recursiveCopy(dirs.includes)); - if (dirs.layouts) { - promises.push(helper.recursiveCopy(dirs.layouts)); + if (options.copyEnabled) { + promises.push(helper.recursiveCopy(dirs.data)); + promises.push(helper.recursiveCopy(dirs.includes)); + if (dirs.layouts) { + promises.push(helper.recursiveCopy(dirs.layouts)); + } } + + let filename = helper.getOutputPath("eleventy-serverless.json"); + promises.push( + fsp.writeFile( + filename, + JSON.stringify( + { + dir: dirs, + }, + null, + 2 + ) + ) + ); + debug(`Eleventy Serverless (${options.name}), writing ${filename}`); + this.copyCount++; + await Promise.all(promises); }); @@ -406,6 +412,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { continue; } + // duplicates that don’t use the same input file, throw an error. if (outputMap[eligibleUrl]) { throw new Error( `Serverless URL conflict: multiple input files are using the same URL path (in \`permalink\`): ${outputMap[eligibleUrl]} and ${entry.inputPath}` diff --git a/src/Serverless.js b/src/Serverless.js index d35056218..0fcdd6d9b 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -29,12 +29,15 @@ class Serverless { // ServerlessBundlerPlugin hard-codes to this (even if you used a different file name) this.configFilename = "eleventy.config.js"; + // Configuration Information + this.configInfoFilename = "eleventy-serverless.json"; + // Maps input files to eligible serverless URLs this.mapFilename = "eleventy-serverless-map.json"; this.options = Object.assign( { - inputDir: ".", + inputDir: null, // override only, we now inject this. functionsDir: "functions/", matchUrlToPattern(path, urlToCompare) { let pattern = new UrlPattern(urlToCompare); @@ -76,12 +79,23 @@ class Serverless { debug( `Including content map (maps output URLs to input files) from ${fullPath}` ); + // TODO dedicated reset method, don’t delete this every time deleteRequireCache(fullPath); let mapContent = require(fullPath); return mapContent; } + getConfigInfo() { + let fullPath = TemplatePath.absolutePath(this.dir, this.configInfoFilename); + debug(`Including config info file from ${fullPath}`); + // TODO dedicated reset method, don’t delete this every time + deleteRequireCache(fullPath); + + let configInfo = require(fullPath); + return configInfo; + } + isServerlessUrl(urlPath) { let contentMap = this.getContentMap(); @@ -129,7 +143,10 @@ class Serverless { process.chdir(this.dir); } - let inputDir = this.options.input || this.options.inputDir; + let inputDir = + this.options.input || + this.options.inputDir || + this.getConfigInfo().dir.input; let configPath = path.join(this.dir, this.configFilename); let { pathParams, inputPath } = this.matchUrlPattern(this.path); From 3efa80041b32125893f0e725f9453e459b5db0be Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 13 Aug 2021 21:03:59 -0500 Subject: [PATCH 566/746] Another stab at #1884 --- src/Plugins/ServerlessBundlerPlugin.js | 7 +++++++ src/TemplatePath.js | 16 ++++++++++------ test/TemplatePathTest.js | 4 ++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index a4a769830..8e60b78e3 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -106,6 +106,13 @@ class BundlerHelper { this.name = name; this.options = options; this.dir = path.join(options.functionsDir, name); + if (path.isAbsolute(this.dir)) { + throw new Error( + "Absolute paths are not yet supported for `functionsDir` in the serverless bundler. Received: " + + options.functionsDir + ); + } + this.copyCount = 0; this.eleventyConfig = eleventyConfig; } diff --git a/src/TemplatePath.js b/src/TemplatePath.js index 4c59e27a5..0943dfbe6 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -183,16 +183,20 @@ TemplatePath.addLeadingDotSlashArray = function (paths) { * @param {String} path * @returns {String} */ -TemplatePath.addLeadingDotSlash = function (path) { - if (path === "." || path === "..") { - return path + "/"; +TemplatePath.addLeadingDotSlash = function (pathArg) { + if (pathArg === "." || pathArg === "..") { + return pathArg + "/"; } - if (path.startsWith("/") || path.startsWith("./") || path.startsWith("../")) { - return path; + if ( + path.isAbsolute(pathArg) || + pathArg.startsWith("./") || + pathArg.startsWith("../") + ) { + return pathArg; } - return "./" + path; + return "./" + pathArg; }; /** diff --git a/test/TemplatePathTest.js b/test/TemplatePathTest.js index 6c7600a2e..87ededdea 100644 --- a/test/TemplatePathTest.js +++ b/test/TemplatePathTest.js @@ -160,6 +160,10 @@ test("addLeadingDotSlash", (t) => { t.is(TemplatePath.addLeadingDotSlash("/dist"), "/dist"); t.is(TemplatePath.addLeadingDotSlash("dist"), "./dist"); t.is(TemplatePath.addLeadingDotSlash(".nyc_output"), "./.nyc_output"); + + // TODO How to test this on Windows? path.isAbsolute is OS dependent 😱 + // let windowsAbsolutePath = `C:\\Users\\$USER\\$PROJECT\\netlify\\functions\\serverless\\index`; + // t.is(TemplatePath.addLeadingDotSlash(windowsAbsolutePath), windowsAbsolutePath); }); test("addLeadingDotSlashArray", (t) => { From 0eee96d7a6bcf4ad68c7a381501cb0a529c8fcbe Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 14 Aug 2021 14:58:14 -0500 Subject: [PATCH 567/746] Fixes #1678. Adds process.env.ELEVENTY_NUNJUCKS_SPEEDBOOST_OPTOUT as an escape hatch to bypass the monkey patch if ever needed. --- src/Engines/Nunjucks.js | 209 +++++++++++++++++++++------------------- 1 file changed, 110 insertions(+), 99 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 8916cc254..d6aa01a49 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -9,105 +9,116 @@ const eventBus = require("../EventBus"); * The IFFE below apply a monkey-patch to Nunjucks internals to cache * compiled templates and re-use them where possible. */ -// (function () { -// let templateCache = new Map(); - -// let getKey = (obj) => { -// return [ -// obj.path || obj.tmplStr, -// obj.tmplStr.length, -// obj.env.asyncFilters.length, -// obj.env.extensionsList -// .map((e) => { -// return e.__id || ""; -// }) -// .join(":"), -// ].join(" :: "); -// }; - -// let evictByPath = (path) => { -// let keys = templateCache.keys(); -// // Likely to be slow; do we care? -// for (let k of keys) { -// if (k.indexOf(path) >= 0) { -// templateCache.delete(k); -// } -// } -// }; -// eventBus.on("eleventy.resourceModified", evictByPath); - -// let _compile = NunjucksLib.Template.prototype._compile; -// NunjucksLib.Template.prototype._compile = function _wrap_compile(...args) { -// if (!this.compiled && !this.tmplProps && templateCache.has(getKey(this))) { -// let pathProps = templateCache.get(getKey(this)); -// this.blocks = pathProps.blocks; -// this.rootRenderFunc = pathProps.rootRenderFunc; -// this.compiled = true; -// } else { -// _compile.call(this, ...args); -// templateCache.set(getKey(this), { -// blocks: this.blocks, -// rootRenderFunc: this.rootRenderFunc, -// }); -// } -// }; - -// let extensionIdCounter = 0; -// let addExtension = NunjucksLib.Environment.prototype.addExtension; -// NunjucksLib.Environment.prototype.addExtension = function _wrap_addExtension( -// name, -// ext -// ) { -// if (!("__id" in ext)) { -// ext.__id = extensionIdCounter++; -// } -// return addExtension.call(this, name, ext); -// }; - -// // NunjucksLib.runtime.Frame.prototype.set is the hotest in-template method. -// // We replace it with a version that doesn't allocate a `parts` array on -// // repeat key use. -// let partsCache = new Map(); -// let partsFromCache = (name) => { -// if (partsCache.has(name)) { -// return partsCache.get(name); -// } - -// let parts = name.split("."); -// partsCache.set(name, parts); -// return parts; -// }; - -// let frameSet = NunjucksLib.runtime.Frame.prototype.set; -// NunjucksLib.runtime.Frame.prototype.set = function _replacement_set( -// name, -// val, -// resolveUp -// ) { -// let parts = partsFromCache(name); -// let frame = this; -// let obj = frame.variables; - -// if (resolveUp) { -// if ((frame = this.resolve(parts[0], true))) { -// frame.set(name, val); -// return; -// } -// } - -// // A slightly faster version of the intermediate object allocation loop -// let count = parts.length - 1; -// let i = 0; -// let id = parts[0]; -// while (i < count) { -// if (!obj.hasOwnProperty(id)) { -// obj = obj[id] = {}; -// } -// id = parts[++i]; -// } -// obj[id] = val; -// }; -// })(); +(function () { + if (process.env.ELEVENTY_NUNJUCKS_SPEEDBOOST_OPTOUT) { + return; + } + + let templateCache = new Map(); + + let getKey = (obj) => { + return [ + obj.path || obj.tmplStr, + obj.tmplStr.length, + obj.env.asyncFilters.length, + obj.env.extensionsList + .map((e) => { + return e.__id || ""; + }) + .join(":"), + ].join(" :: "); + }; + + let evictByPath = (path) => { + let keys = templateCache.keys(); + // Likely to be slow; do we care? + for (let k of keys) { + if (k.indexOf(path) >= 0) { + templateCache.delete(k); + } + } + }; + eventBus.on("eleventy.resourceModified", evictByPath); + + let _compile = NunjucksLib.Template.prototype._compile; + NunjucksLib.Template.prototype._compile = function _wrap_compile(...args) { + if (!this.compiled && !this.tmplProps && templateCache.has(getKey(this))) { + let pathProps = templateCache.get(getKey(this)); + this.blocks = pathProps.blocks; + this.rootRenderFunc = pathProps.rootRenderFunc; + this.compiled = true; + } else { + _compile.call(this, ...args); + templateCache.set(getKey(this), { + blocks: this.blocks, + rootRenderFunc: this.rootRenderFunc, + }); + } + }; + + let extensionIdCounter = 0; + let addExtension = NunjucksLib.Environment.prototype.addExtension; + NunjucksLib.Environment.prototype.addExtension = function _wrap_addExtension( + name, + ext + ) { + if (!("__id" in ext)) { + ext.__id = extensionIdCounter++; + } + return addExtension.call(this, name, ext); + }; + + // NunjucksLib.runtime.Frame.prototype.set is the hotest in-template method. + // We replace it with a version that doesn't allocate a `parts` array on + // repeat key use. + let partsCache = new Map(); + let partsFromCache = (name) => { + if (partsCache.has(name)) { + return partsCache.get(name); + } + + let parts = name.split("."); + partsCache.set(name, parts); + return parts; + }; + + let frameSet = NunjucksLib.runtime.Frame.prototype.set; + NunjucksLib.runtime.Frame.prototype.set = function _replacement_set( + name, + val, + resolveUp + ) { + let parts = partsFromCache(name); + let frame = this; + let obj = frame.variables; + + if (resolveUp) { + if ((frame = this.resolve(parts[0], true))) { + frame.set(name, val); + return; + } + } + + // A slightly faster version of the intermediate object allocation loop + let count = parts.length - 1; + let i = 0; + let id = parts[0]; + while (i < count) { + // TODO(zachleat) use Object.hasOwn when supported + if ("hasOwnProperty" in obj) { + if (!obj.hasOwnProperty(id)) { + obj = obj[id] = {}; + } + } else if (!(id in obj)) { + // Handle Objects with null prototypes (Nunjucks looping stuff) + obj = obj[id] = {}; + } + + id = parts[++i]; + } + obj[id] = val; + }; +})(); class EleventyShortcodeError extends EleventyBaseError {} From c404506c53eaeccb2049145bd2e9e867385fa2b0 Mon Sep 17 00:00:00 2001 From: Holben888 Date: Sat, 14 Aug 2021 19:42:10 -0500 Subject: [PATCH 568/746] refactor: rename defaultCompiler to defaultRenderer --- src/Engines/Custom.js | 19 ++++++++++--------- test/TemplateRenderCustomTest.js | 8 ++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index d62d47562..318991898 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -76,9 +76,9 @@ class CustomEngine extends TemplateEngine { async compile(str, inputPath, ...args) { await this._runningInit(); - let defaultCompiler; + let defaultRenderer; if (this._defaultEngine) { - defaultCompiler = async (data) => { + defaultRenderer = async (data) => { const render = await this._defaultEngine.compile( str, inputPath, @@ -89,16 +89,17 @@ class CustomEngine extends TemplateEngine { } // Fall back to default compiler if the user does not provide their own - if (!this.entry.compile && defaultCompiler) { - return defaultCompiler; + if (!this.entry.compile && defaultRenderer) { + return defaultRenderer; } // TODO generalize this (look at JavaScript.js) - return this.entry.compile - // give the user access to this engine's default compiler, if any - .bind({ config: this.config, defaultCompiler })(str, inputPath) - // bind again for access inside function (data) {...} - .bind({ defaultCompiler }); + return ( + this.entry.compile + .bind({ config: this.config })(str, inputPath) + // give the user access to this engine's default renderer, if any + .bind({ defaultRenderer }) + ); } get defaultTemplateFileExtension() { diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index 2a0dd3bc8..eac4c5414 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -82,7 +82,7 @@ test("Custom Markdown Render with `compile` override + call to default compiler" key: "md", compile: function (str, inputPath) { return async function (data) { - const result = await this.defaultCompiler(data); + const result = await this.defaultRenderer(data); return `${result.trim()}`; }; }, @@ -116,8 +116,8 @@ test("Custom Vue Render", async (t) => { }, }); - let fn = await tr.getCompiledTemplate(`

Paragraph

`); - t.is(await fn({ test: "Hello" }), `

Hello

`); + let fn = await tr.getCompiledTemplate('

Paragraph

'); + t.is(await fn({ test: "Hello" }), '

Hello

'); }); const sass = require("sass"); @@ -154,7 +154,7 @@ test("Custom Sass Render", async (t) => { }, }); - let fn = await tr.getCompiledTemplate(`$color: blue; p { color: $color; }`); + let fn = await tr.getCompiledTemplate("$color: blue; p { color: $color; }"); t.is( (await fn({})).trim(), `p { From c4c5455c058106eca50d0d2cfb387d0faf03e5cf Mon Sep 17 00:00:00 2001 From: Holben888 Date: Sat, 14 Aug 2021 19:42:49 -0500 Subject: [PATCH 569/746] refactor: use this.getEngineClassByExtension() for custom engine require --- src/TemplateEngineManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 8b0756bd1..26a38e381 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -97,7 +97,7 @@ class TemplateEngineManager { this.getClassNameFromTemplateKey(name) === "Custom" && instance.constructor.name !== "CustomEngine" ) { - const CustomEngine = require("./Engines/Custom"); + const CustomEngine = this.getEngineClassByExtension(); const overrideCustomEngine = new CustomEngine( name, includesDir, From 9f8bed319b2923a1755d415c3b2a3ab9e72c4c01 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 15 Aug 2021 15:10:49 -0500 Subject: [PATCH 570/746] Adds `.setNunjucksEnvironmentOptions` configuration API method. Options documented here: https://mozilla.github.io/nunjucks/api.html#configure Cleans up the Liquid/Pug options code a bit, was unnecessarily complex for testing Fixes #895. --- src/Engines/Liquid.js | 15 +--- src/Engines/Nunjucks.js | 10 ++- src/Engines/Pug.js | 11 +-- src/UserConfig.js | 17 ++++- test/TemplateRenderLiquidTest.js | 106 +++++++++++++++++++---------- test/TemplateRenderNunjucksTest.js | 32 +++++++++ test/TemplateRenderPugTest.js | 21 ++++-- 7 files changed, 145 insertions(+), 67 deletions(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 5dabeda64..125523641 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -8,10 +8,9 @@ class Liquid extends TemplateEngine { constructor(name, includesDir, config) { super(name, includesDir, config); - this.liquidOptions = {}; + this.liquidOptions = this.config.liquidOptions || {}; this.setLibrary(this.config.libraryOverrides.liquid); - this.setLiquidOptions(this.config.liquidOptions); this.argLexer = moo.compile({ number: /[0-9]+\.*[0-9]*/, @@ -23,11 +22,9 @@ class Liquid extends TemplateEngine { this.cacheable = true; } - setLibrary(lib) { - this.liquidLibOverride = lib; - + setLibrary(override) { // warning, the include syntax supported here does not exactly match what Jekyll uses. - this.liquidLib = lib || new liquidLib.Liquid(this.getLiquidOptions()); + this.liquidLib = override || new liquidLib.Liquid(this.getLiquidOptions()); this.setEngineLib(this.liquidLib); this.addFilters(this.config.liquidFilters); @@ -38,12 +35,6 @@ class Liquid extends TemplateEngine { this.addAllPairedShortcodes(this.config.liquidPairedShortcodes); } - setLiquidOptions(options) { - this.liquidOptions = options; - - this.setLibrary(this.liquidLibOverride); - } - getLiquidOptions() { let defaults = { root: [super.getIncludesDir()], // overrides in compile with inputPath below diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index d6aa01a49..7bb0003ab 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -125,18 +125,24 @@ class EleventyShortcodeError extends EleventyBaseError {} class Nunjucks extends TemplateEngine { constructor(name, includesDir, config) { super(name, includesDir, config); + this.nunjucksEnvironmentOptions = + this.config.nunjucksEnvironmentOptions || {}; this.setLibrary(this.config.libraryOverrides.njk); this.cacheable = true; } - setLibrary(env) { + setLibrary(override) { let fsLoader = new NunjucksLib.FileSystemLoader([ super.getIncludesDir(), TemplatePath.getWorkingDir(), ]); - this.njkEnv = env || new NunjucksLib.Environment(fsLoader); + + this.njkEnv = + override || + new NunjucksLib.Environment(fsLoader, this.nunjucksEnvironmentOptions); + // Correct, but overbroad. Better would be to evict more granularly, but // resolution from paths isn't straightforward. eventBus.on("eleventy.resourceModified", (path) => { diff --git a/src/Engines/Pug.js b/src/Engines/Pug.js index de0322b3d..9e0619c32 100644 --- a/src/Engines/Pug.js +++ b/src/Engines/Pug.js @@ -5,21 +5,16 @@ class Pug extends TemplateEngine { constructor(name, includesDir, config) { super(name, includesDir, config); - this.pugOptions = {}; + this.pugOptions = this.config.pugOptions || {}; this.setLibrary(this.config.libraryOverrides.pug); - this.setPugOptions(this.config.pugOptions); } - setLibrary(lib) { - this.pugLib = lib || PugLib; + setLibrary(override) { + this.pugLib = override || PugLib; this.setEngineLib(this.pugLib); } - setPugOptions(options) { - this.pugOptions = options; - } - getPugOptions() { let includesDir = super.getIncludesDir(); diff --git a/src/UserConfig.js b/src/UserConfig.js index 14ead844d..e088151cc 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -29,6 +29,7 @@ class UserConfig { this.liquidFilters = {}; this.liquidShortcodes = {}; this.liquidPairedShortcodes = {}; + this.nunjucksEnvironmentOptions = {}; this.nunjucksFilters = {}; this.nunjucksAsyncFilters = {}; this.nunjucksTags = {}; @@ -400,9 +401,16 @@ class UserConfig { setLibrary(engineName, libraryInstance) { // Pug options are passed to `compile` and not in the library constructor so we don’t need to warn - if (engineName === "liquid" && this.mdOptions) { + if (engineName === "liquid" && Object.keys(this.liquidOptions).length) { debug( - "WARNING: using `eleventyConfig.setLibrary` will override any configuration set using `.setLiquidOptions` or with the `liquidOptions` key in the config object. You’ll need to pass these options to the library yourself." + "WARNING: using `eleventyConfig.setLibrary` will override any configuration set using `.setLiquidOptions` via the config API. You’ll need to pass these options to the library yourself." + ); + } else if ( + engineName === "njk" && + Object.keys(this.nunjucksEnvironmentOptions).length + ) { + debug( + "WARNING: using `eleventyConfig.setLibrary` will override any configuration set using `.setNunjucksEnvironmentOptions` via the config API. You’ll need to pass these options to the library yourself." ); } @@ -417,6 +425,10 @@ class UserConfig { this.liquidOptions = options; } + setNunjucksEnvironmentOptions(options) { + this.nunjucksEnvironmentOptions = options; + } + setEjsOptions(options) { this.ejsOptions = options; } @@ -716,6 +728,7 @@ class UserConfig { liquidFilters: this.liquidFilters, liquidShortcodes: this.liquidShortcodes, liquidPairedShortcodes: this.liquidPairedShortcodes, + nunjucksEnvironmentOptions: this.nunjucksEnvironmentOptions, nunjucksFilters: this.nunjucksFilters, nunjucksAsyncFilters: this.nunjucksAsyncFilters, nunjucksTags: this.nunjucksTags, diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 4c40827e3..67e59a43e 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -3,8 +3,12 @@ const TemplateRender = require("../src/TemplateRender"); const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); -function getNewTemplateRender(name, inputDir) { +function getNewTemplateRender(name, inputDir, userConfig = {}) { let eleventyConfig = new TemplateConfig(); + for (let key in userConfig) { + eleventyConfig.userConfig[key] = userConfig[key]; + } + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; @@ -64,10 +68,12 @@ test("Liquid Render Include", async (t) => { "liquid" ); - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate("

{% include included %}

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

This is an include.

"); }); @@ -78,10 +84,12 @@ test("Liquid Render Relative Include", async (t) => { "liquid" ); - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate("

{% include ./included %}

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

This is an include.

"); }); @@ -89,11 +97,14 @@ test("Liquid Render Relative Include", async (t) => { test("Liquid Render Relative (current dir) Include", async (t) => { let tr = await getNewTemplateRender( "./test/stubs/relative-liquid/does_not_exist_and_thats_ok.liquid", - "./test/stubs/" + "./test/stubs/", + { + liquidOptions: { + dynamicPartials: false, + }, + } ); - tr.engine.setLiquidOptions({ - dynamicPartials: false, - }); + let fn = await tr.getCompiledTemplate("

{% include ./dir/included %}

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

TIME IS RELATIVE.

"); }); @@ -101,11 +112,14 @@ test("Liquid Render Relative (current dir) Include", async (t) => { test("Liquid Render Relative (parent dir) Include", async (t) => { let tr = await getNewTemplateRender( "./test/stubs/relative-liquid/dir/does_not_exist_and_thats_ok.liquid", - "./test/stubs/" + "./test/stubs/", + { + liquidOptions: { + dynamicPartials: false, + }, + } ); - tr.engine.setLiquidOptions({ - dynamicPartials: false, - }); + let fn = await tr.getCompiledTemplate("

{% include ../dir/included %}

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

TIME IS RELATIVE.

"); }); @@ -129,10 +143,12 @@ test("Liquid Render Include with Liquid Suffix", async (t) => { "liquid" ); - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate("

{% include included.liquid %}

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

This is an include.

"); }); @@ -143,10 +159,12 @@ test("Liquid Render Include with HTML Suffix", async (t) => { "liquid" ); - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate("

{% include included.html %}

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

This is an include.

"); }); @@ -157,10 +175,12 @@ test("Liquid Render Include with HTML Suffix and Data Pass in", async (t) => { "liquid" ); - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate( "{% include included-data.html, myVariable: 'myValue' %}" ); @@ -444,10 +464,12 @@ test("Liquid Async Paired Shortcode", async (t) => { }); test("Liquid Render Include Subfolder", async (t) => { - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate( `

{% include subfolder/included.liquid %}

` ); @@ -455,10 +477,12 @@ test("Liquid Render Include Subfolder", async (t) => { }); test("Liquid Render Include Subfolder HTML", async (t) => { - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate( `

{% include subfolder/included.html %}

` ); @@ -466,10 +490,12 @@ test("Liquid Render Include Subfolder HTML", async (t) => { }); test("Liquid Render Include Subfolder No file extension", async (t) => { - let tr = await getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ - dynamicPartials: false, + let tr = await getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, }); + let fn = await tr.getCompiledTemplate( `

{% include subfolder/included %}

` ); @@ -528,8 +554,11 @@ test("Liquid Render Include Subfolder Double quotes No file extension", async (t /* End tests related to dynamicPartials */ test("Liquid Options Overrides", async (t) => { - let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ dynamicPartials: false }); + let tr = getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + dynamicPartials: false, + }, + }); let options = tr.engine.getLiquidOptions(); t.is(options.dynamicPartials, false); @@ -691,8 +720,11 @@ test.skip("Liquid Include Scope Leak", async (t) => { // Note: this strictFilters default changed in 1.0 from false to true test("Liquid Missing Filter Issue #183 (no strictFilters)", async (t) => { - let tr = getNewTemplateRender("liquid", "./test/stubs/"); - tr.engine.setLiquidOptions({ strictFilters: false }); + let tr = getNewTemplateRender("liquid", "./test/stubs/", { + liquidOptions: { + strictFilters: false, + }, + }); try { await tr._testRender("{{ 'test' | prefixWithZach }}", {}); diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index f62621e5f..ffa39b674 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -7,6 +7,7 @@ function getNewTemplateRender(name, inputDir, eleventyConfig) { if (!eleventyConfig) { eleventyConfig = new TemplateConfig(); } + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; @@ -878,3 +879,34 @@ test.skip("Use addNunjucksGlobal with async function", async (t) => { let fn = await tr.getCompiledTemplate("

{{ fortytwo() }}

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

42

"); }); + +test("Use config driven Nunjucks Environment Options (throws on undefined variable)", async (t) => { + let templateConfig = new TemplateConfig(); + templateConfig.userConfig.setNunjucksEnvironmentOptions({ + throwOnUndefined: true, + }); + + let tr = getNewTemplateRender("njk", null, templateConfig); + + let fn = await tr.getCompiledTemplate("

{{ test }}

"); + await t.throwsAsync(async () => { + await fn({}); + }); +}); + +test("Use config driven Nunjucks Environment Options (autoescape)", async (t) => { + let templateConfig = new TemplateConfig(); + templateConfig.userConfig.setNunjucksEnvironmentOptions({ + autoescape: false, + }); + + let tr = getNewTemplateRender("njk", null, templateConfig); + + let fn = await tr.getCompiledTemplate("

{{ test }}

"); + t.is( + await fn({ + test: "Hi", + }), + "

Hi

" + ); +}); diff --git a/test/TemplateRenderPugTest.js b/test/TemplateRenderPugTest.js index 595978d2a..d369ff481 100644 --- a/test/TemplateRenderPugTest.js +++ b/test/TemplateRenderPugTest.js @@ -3,8 +3,12 @@ const TemplateRender = require("../src/TemplateRender"); const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); -function getNewTemplateRender(name, inputDir) { - let eleventyConfig = new TemplateConfig(); +function getNewTemplateRender(name, inputDir, config) { + let eleventyConfig = config; + if (!eleventyConfig) { + eleventyConfig = new TemplateConfig(); + } + let tr = new TemplateRender(name, inputDir, eleventyConfig); tr.extensionMap = new EleventyExtensionMap([], eleventyConfig); return tr; @@ -105,8 +109,11 @@ test("Pug Render Include (Relative, dot dot slash)", async (t) => { }); test("Pug Options Overrides", async (t) => { - let tr = getNewTemplateRender("pug", "./test/stubs/"); - tr.engine.setPugOptions({ testoption: "testoverride" }); + let cfg = new TemplateConfig(); + cfg.userConfig.setPugOptions({ + testoption: "testoverride", + }); + let tr = getNewTemplateRender("pug", "./test/stubs/", cfg); let options = tr.engine.getPugOptions(); t.is(options.testoption, "testoverride"); @@ -128,8 +135,8 @@ test("Pug Render: with Library Override", async (t) => { }); test("Pug Filter", async (t) => { - let tr = getNewTemplateRender("pug", "./test/stubs/"); - tr.engine.setPugOptions({ + let cfg = new TemplateConfig(); + cfg.userConfig.setPugOptions({ filters: { makeUppercase: function (text, options) { return text.toUpperCase(); @@ -137,6 +144,8 @@ test("Pug Filter", async (t) => { }, }); + let tr = getNewTemplateRender("pug", "./test/stubs/", cfg); + let fn = await tr.getCompiledTemplate(`p :makeUppercase() Zach From 28f76d36f8e68226f70d85b4161a0293b5d5a9f9 Mon Sep 17 00:00:00 2001 From: Anton Kostin Date: Wed, 18 Aug 2021 15:59:16 +0700 Subject: [PATCH 571/746] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 0ad7545c2..ebcbb6b4e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Zach Leatherman @zachleat +Copyright (c) 2021 Zach Leatherman @zachleat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 6fc8eb1282707890b5124ecc35e9a1d2a7d0b31e Mon Sep 17 00:00:00 2001 From: monochromer Date: Fri, 3 Sep 2021 16:35:20 +0500 Subject: [PATCH 572/746] Check `permalink` field before set extra output subdirectory for pagination --- src/Plugins/Pagination.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 8bec4c8e5..a64c91c46 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -310,7 +310,9 @@ class Pagination { let cloned = tmpl.clone(); // TODO maybe also move this permalink additions up into the pagination class - if (pageNumber > 0 && !this.data[this.config.keys.permalink]) { + let hasPermalinkField = Boolean(this.data[this.config.keys.permalink]); + let hasComputedPermalinkField = Boolean(this.data.eleventyComputed && this.data.eleventyComputed[this.config.keys.permalink]); + if (pageNumber > 0 && !(hasPermalinkField || hasComputedPermalinkField)) { cloned.setExtraOutputSubdirectory(pageNumber); } From be3db7882c4b9cd0452ec58f9c385364aed671e0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 3 Sep 2021 11:16:58 -0500 Subject: [PATCH 573/746] Removes valid-url dependency and relies on core url package. --- package.json | 3 +-- src/Eleventy.js | 3 ++- src/Filters/Url.js | 18 +++++++++++------- test/UrlTest.js | 1 - 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 954db15c8..770e4bd66 100755 --- a/package.json +++ b/package.json @@ -122,7 +122,6 @@ "slugify": "^1.6.0", "split": "^1.0.1", "time-require": "^0.1.2", - "url-pattern": "^1.0.3", - "valid-url": "^1.0.9" + "url-pattern": "^1.0.3" } } diff --git a/src/Eleventy.js b/src/Eleventy.js index 5eeed93e3..37313d362 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -407,7 +407,8 @@ Verbose Output: ${this.verboseMode}`); process.env.ELEVENTY_SOURCE = this.source; - // careful here, setting to false will cast to string "false" which is truthy + // TODO @zachleat this needs to be extensible. https://github.com/11ty/eleventy/issues/1957 + // Careful here, setting to false will cast to string "false" which is truthy. if (process.env.AWS_LAMBDA_FUNCTION_NAME) { process.env.ELEVENTY_SERVERLESS = true; debug("Setting process.env.ELEVENTY_SERVERLESS: %o", true); diff --git a/src/Filters/Url.js b/src/Filters/Url.js index 5cfba4932..fb7e955a1 100644 --- a/src/Filters/Url.js +++ b/src/Filters/Url.js @@ -1,17 +1,21 @@ -const validUrl = require("valid-url"); const TemplatePath = require("../TemplatePath"); +function isValidUrl(url) { + try { + new URL(url); + return true; + } catch (e) { + // invalid url OR local path + return false; + } +} + // This is also used in the Eleventy Navigation plugin module.exports = function (url, pathPrefix) { // work with undefined url = url || ""; - if ( - validUrl.isUri(url) || - url.indexOf("http://") === 0 || - url.indexOf("https://") === 0 || - (url.indexOf("//") === 0 && url !== "//") - ) { + if (isValidUrl(url) || (url.indexOf("//") === 0 && url !== "//")) { return url; } diff --git a/test/UrlTest.js b/test/UrlTest.js index 2601e8f36..a3374bc6c 100644 --- a/test/UrlTest.js +++ b/test/UrlTest.js @@ -97,7 +97,6 @@ test("Test url filter with passthrough urls", (t) => { t.is(url("http://a.b-c.de", ""), "http://a.b-c.de"); t.is(url("http://223.255.255.254", ""), "http://223.255.255.254"); - // these tests were failing without the http/https bypass—upstream issues with valid-url t.is(url("http://✪df.ws/123", ""), "http://✪df.ws/123"); t.is(url("http://➡.ws/䨹", ""), "http://➡.ws/䨹"); t.is(url("http://⌘.ws", ""), "http://⌘.ws"); From ad8177f797ec9e4a630d184e8410398a2ff0ad88 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 3 Sep 2021 11:50:46 -0500 Subject: [PATCH 574/746] Adds help text for --to https://github.com/11ty/eleventy/issues/1640 --- src/Eleventy.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 37313d362..26a704323 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -520,30 +520,45 @@ Verbose Output: ${this.verboseMode}`); * @returns {String} - The help mesage. */ getHelp() { - return `usage: eleventy + return `Usage: eleventy eleventy --input=. --output=./_site eleventy --serve Arguments: + --version + --input=. Input template files (default: \`.\`) + --output=_site Write HTML output to this folder (default: \`_site\`) + --serve Run web server on --port (default 8080) and watch them too + --watch Wait for files to change and automatically rewrite (no web server) + --formats=liquid,md Whitelist only certain template types (default: \`*\`) + --quiet Don’t print all written files (off by default) + --config=filename.js Override the eleventy config file path (default: \`.eleventy.js\`) + --pathprefix='/' Change all url template filters to use this subdirectory. + --dryrun Don’t write any files. Useful with \`DEBUG=Eleventy* npx eleventy\` + + --to=json + --to=ndjson + Change the output to JSON or NDJSON (default: \`fs\`) + --help`; } From 3618f639c47855601fe6af2eda2ad07870a28c7f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 3 Sep 2021 13:59:24 -0500 Subject: [PATCH 575/746] Fixes https://github.com/11ty/eleventy/issues/1858 --- src/Plugins/Pagination.js | 4 +-- src/Template.js | 6 ++-- src/TemplateBehavior.js | 8 +++-- src/TemplatePermalink.js | 12 +++---- test/TemplatePermalinkTest.js | 66 +++++++++++++++++----------------- test/TemplateTest.js | 43 +++++++++++----------- test/TemplateTest_Permalink.js | 4 +-- 7 files changed, 73 insertions(+), 70 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 8bec4c8e5..a2fce8ef9 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -327,8 +327,8 @@ class Pagination { // TO DO subdirectory to links if the site doesn’t live at / // TODO missing data argument means Template.getData is regenerated, maybe doesn’t matter because of data cache? - let { link, href } = await cloned.getOutputLocations(); - links.push("/" + link); + let { rawPath, href } = await cloned.getOutputLocations(); + links.push("/" + rawPath); hrefs.push(href); } diff --git a/src/Template.js b/src/Template.js index 07c5c411b..5843cb481 100755 --- a/src/Template.js +++ b/src/Template.js @@ -286,16 +286,16 @@ class Template extends TemplateContent { } return { - link: link.toLink(), + rawPath: link.toOutputPath(), href: link.toHref(), path: path, }; } // Preferred to use the singular `getOutputLocations` above. - async getOutputLink(data) { + async getRawOutputPath(data) { let link = await this._getLink(data); - return link.toLink(); + return link.toOutputPath(); } // Preferred to use the singular `getOutputLocations` above. diff --git a/src/TemplateBehavior.js b/src/TemplateBehavior.js index 22626ad32..c8a92422e 100644 --- a/src/TemplateBehavior.js +++ b/src/TemplateBehavior.js @@ -36,12 +36,16 @@ class TemplateBehavior { let keys = new Set(); if (isPlainObject(data.permalink)) { - keys.add(...Object.keys(data.permalink)); + for (let key of Object.keys(data.permalink)) { + keys.add(key); + } } let computedKey = this.config.keys.computed; if (computedKey in data && isPlainObject(data[computedKey].permalink)) { - keys.add(...Object.keys(data[computedKey].permalink)); + for (let key of Object.keys(data[computedKey].permalink)) { + keys.add(key); + } } if (keys.size) { diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 117a34c2c..883908981 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -78,10 +78,8 @@ class TemplatePermalink { return link + (link.substr(-1) === "/" ? "index.html" : ""); } - toLink() { - if (this.primaryServerlessUrl) { - return this.primaryServerlessUrl; - } else if (!this.buildLink) { + toOutputPath() { + if (!this.buildLink) { // empty or false return false; } @@ -110,7 +108,7 @@ class TemplatePermalink { return false; } - let transformedLink = this.toLink(); + let transformedLink = this.toOutputPath(); let original = (transformedLink.charAt(0) !== "/" ? "/" : "") + transformedLink; let needle = "/index.html"; @@ -127,7 +125,7 @@ class TemplatePermalink { return false; } - let uri = this.toLink(); + let uri = this.toOutputPath(); if (uri === false) { return false; @@ -141,7 +139,7 @@ class TemplatePermalink { return false; } - let uri = this.toLink(); + let uri = this.toOutputPath(); if (uri === false) { return false; diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index ca1be5d02..2678e5221 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -3,11 +3,11 @@ const TemplatePermalink = require("../src/TemplatePermalink"); test("Simple straight permalink", (t) => { t.is( - new TemplatePermalink("permalinksubfolder/test.html").toLink(), + new TemplatePermalink("permalinksubfolder/test.html").toOutputPath(), "permalinksubfolder/test.html" ); t.is( - new TemplatePermalink("./permalinksubfolder/test.html").toLink(), + new TemplatePermalink("./permalinksubfolder/test.html").toOutputPath(), "permalinksubfolder/test.html" ); @@ -28,15 +28,15 @@ test("Simple straight permalink", (t) => { test("Permalink without filename", (t) => { t.is( - new TemplatePermalink("permalinksubfolder/").toLink(), + new TemplatePermalink("permalinksubfolder/").toOutputPath(), "permalinksubfolder/index.html" ); t.is( - new TemplatePermalink("./permalinksubfolder/").toLink(), + new TemplatePermalink("./permalinksubfolder/").toOutputPath(), "permalinksubfolder/index.html" ); t.is( - new TemplatePermalink("/permalinksubfolder/").toLink(), + new TemplatePermalink("/permalinksubfolder/").toOutputPath(), "/permalinksubfolder/index.html" ); @@ -56,11 +56,11 @@ test("Permalink without filename", (t) => { test("Permalink with pagination subdir", (t) => { t.is( - new TemplatePermalink("permalinksubfolder/test.html", "0/").toLink(), + new TemplatePermalink("permalinksubfolder/test.html", "0/").toOutputPath(), "permalinksubfolder/0/test.html" ); t.is( - new TemplatePermalink("permalinksubfolder/test.html", "1/").toLink(), + new TemplatePermalink("permalinksubfolder/test.html", "1/").toOutputPath(), "permalinksubfolder/1/test.html" ); @@ -77,33 +77,33 @@ test("Permalink with pagination subdir", (t) => { test("Permalink generate", (t) => { let gen = TemplatePermalink.generate; - t.is(gen("./", "index").toLink(), "index.html"); + t.is(gen("./", "index").toOutputPath(), "index.html"); t.is(gen("./", "index").toHref(), "/"); - t.is(gen(".", "index").toLink(), "index.html"); + t.is(gen(".", "index").toOutputPath(), "index.html"); t.is(gen(".", "index").toHref(), "/"); - t.is(gen(".", "test").toLink(), "test/index.html"); + t.is(gen(".", "test").toOutputPath(), "test/index.html"); t.is(gen(".", "test").toHref(), "/test/"); - t.is(gen(".", "test", "0/").toLink(), "test/0/index.html"); + t.is(gen(".", "test", "0/").toOutputPath(), "test/0/index.html"); t.is(gen(".", "test", "0/").toHref(), "/test/0/"); - t.is(gen(".", "test", "1/").toLink(), "test/1/index.html"); + t.is(gen(".", "test", "1/").toOutputPath(), "test/1/index.html"); t.is(gen(".", "test", "1/").toHref(), "/test/1/"); }); test("Permalink generate with suffix", (t) => { let gen = TemplatePermalink.generate; - t.is(gen(".", "test", null, "-o").toLink(), "test/index-o.html"); + t.is(gen(".", "test", null, "-o").toOutputPath(), "test/index-o.html"); t.is(gen(".", "test", null, "-o").toHref(), "/test/index-o.html"); - t.is(gen(".", "test", "1/", "-o").toLink(), "test/1/index-o.html"); + t.is(gen(".", "test", "1/", "-o").toOutputPath(), "test/1/index-o.html"); t.is(gen(".", "test", "1/", "-o").toHref(), "/test/1/index-o.html"); }); test("Permalink generate with new extension", (t) => { let gen = TemplatePermalink.generate; - t.is(gen(".", "test", null, null, "css").toLink(), "test.css"); + t.is(gen(".", "test", null, null, "css").toOutputPath(), "test.css"); t.is(gen(".", "test", null, null, "css").toHref(), "/test.css"); - t.is(gen(".", "test", "1/", null, "css").toLink(), "1/test.css"); + t.is(gen(".", "test", "1/", null, "css").toOutputPath(), "1/test.css"); t.is(gen(".", "test", "1/", null, "css").toHref(), "/1/test.css"); }); @@ -111,15 +111,15 @@ test("Permalink generate with subfolders", (t) => { let gen = TemplatePermalink.generate; t.is( - gen("permalinksubfolder/", "index").toLink(), + gen("permalinksubfolder/", "index").toOutputPath(), "permalinksubfolder/index.html" ); t.is( - gen("permalinksubfolder/", "test").toLink(), + gen("permalinksubfolder/", "test").toOutputPath(), "permalinksubfolder/test/index.html" ); t.is( - gen("permalinksubfolder/", "test", "1/", "-o").toLink(), + gen("permalinksubfolder/", "test", "1/", "-o").toOutputPath(), "permalinksubfolder/test/1/index-o.html" ); @@ -144,7 +144,7 @@ test("Permalink matching folder and filename", (t) => { t.is(hasDupe("component", "component"), true); t.is(hasDupe("component/", "component"), true); - t.is(gen("component/", "component").toLink(), "component/index.html"); + t.is(gen("component/", "component").toOutputPath(), "component/index.html"); t.is(gen("component/", "component").toHref(), "/component/"); }); @@ -152,21 +152,21 @@ test("Permalink Object, just build", (t) => { t.is( new TemplatePermalink({ build: "permalinksubfolder/test.html", - }).toLink(), + }).toOutputPath(), "permalinksubfolder/test.html" ); t.is( new TemplatePermalink({ build: false, - }).toLink(), + }).toOutputPath(), false ); t.throws(() => { new TemplatePermalink({ build: true, - }).toLink(); + }).toOutputPath(); }); }); @@ -175,8 +175,8 @@ test("Permalink Object, serverless URLs", (t) => { t.is( new TemplatePermalink({ serverless: "permalinksubfolder/test.html", - }).toLink(), - "permalinksubfolder/test.html" + }).toOutputPath(), + false ); t.is( @@ -190,8 +190,8 @@ test("Permalink Object, serverless URLs", (t) => { t.is( new TemplatePermalink({ request: "/url/", - }).toLink(), - "/url/" + }).toOutputPath(), + false ); t.is( @@ -205,8 +205,8 @@ test("Permalink Object, serverless URLs", (t) => { t.is( new TemplatePermalink({ rando: "/url/", - }).toLink(), - "/url/" + }).toOutputPath(), + false ); t.is( @@ -222,7 +222,7 @@ test("Permalink Object, combo build and serverless URLs", (t) => { new TemplatePermalink({ build: "/url/", serverless: "/serverless/", - }).toLink(), + }).toOutputPath(), "/url/index.html" ); @@ -239,8 +239,8 @@ test("Permalink Object, combo build and serverless URLs", (t) => { new TemplatePermalink({ serverless: "/serverless/", build: "/url/", - }).toLink(), - "/serverless/" + }).toOutputPath(), + "/url/index.html" ); t.is( @@ -253,7 +253,7 @@ test("Permalink Object, combo build and serverless URLs", (t) => { }); test("Permalink Object, empty object", (t) => { - t.is(new TemplatePermalink({}).toLink(), false); + t.is(new TemplatePermalink({}).toOutputPath(), false); t.is(new TemplatePermalink({}).toHref(), false); }); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 386bef34b..837b5e40d 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1090,7 +1090,7 @@ test("renderContent on a markdown file, permalink should not render markdown", a "/news/my-test-file/index.html" ); - t.is(await tmpl.getOutputLink(), "/news/my-test-file/index.html"); + t.is(await tmpl.getRawOutputPath(), "/news/my-test-file/index.html"); }); test("renderContent on a markdown file, permalink should not render markdown (with variable)", async (t) => { @@ -1109,7 +1109,7 @@ test("renderContent on a markdown file, permalink should not render markdown (wi "/news/my-title/index.html" ); - t.is(await tmpl.getOutputLink(), "/news/my-title/index.html"); + t.is(await tmpl.getRawOutputPath(), "/news/my-title/index.html"); }); test("renderContent on a markdown file, permalink should not render markdown (has override)", async (t) => { @@ -1124,7 +1124,7 @@ test("renderContent on a markdown file, permalink should not render markdown (ha "/news/my-test-file/index.html" ); - t.is(await tmpl.getOutputLink(), "/news/my-test-file/index.html"); + t.is(await tmpl.getRawOutputPath(), "/news/my-test-file/index.html"); }); /* Transforms */ @@ -2074,7 +2074,7 @@ test("permalink object with build", async (t) => { "./test/stubs/_site" ); - t.is(await tmpl.getOutputLink(), "/url/index.html"); + t.is(await tmpl.getRawOutputPath(), "/url/index.html"); t.is(await tmpl.getOutputHref(), "/url/"); }); @@ -2085,7 +2085,8 @@ test("permalink object without build", async (t) => { "./test/stubs/_site" ); - t.is(await tmpl.getOutputLink(), "/url/"); + t.is(await tmpl.getRawOutputPath(), false); + t.is(await tmpl.getOutputPath(), false); t.is(await tmpl.getOutputHref(), "/url/"); }); @@ -2101,7 +2102,7 @@ test("permalink object _getLink", async (t) => { serverless: "/serverless/", }, }); - t.is(await link.toLink(), "/serverless/"); + t.is(await link.toOutputPath(), false); t.is(await link.toHref(), "/serverless/"); t.deepEqual(link.getServerlessUrls(), { @@ -2116,7 +2117,7 @@ test("permalink object _getLink", async (t) => { build: "/build/", }, }); - t.is(await link2.toLink(), "/build/index.html"); + t.is(await link2.toOutputPath(), "/build/index.html"); t.is(await link2.toHref(), "/build/"); t.deepEqual(link2.getServerlessUrls(), {}); t.deepEqual(tmpl.getServerlessUrls(), {}); @@ -2127,7 +2128,7 @@ test("permalink object _getLink", async (t) => { serverless: "/serverless/", }, }); - t.is(await link3.toLink(), "/build/index.html"); + t.is(await link3.toOutputPath(), "/build/index.html"); t.is(await link3.toHref(), "/build/"); t.deepEqual(link3.getServerlessUrls(), { serverless: "/serverless/", @@ -2144,7 +2145,7 @@ test("permalink object _getLink", async (t) => { serverless: "/serverless{{ test }}/", }, }); - t.is(await link4.toLink(), "/builda/index.html"); + t.is(await link4.toOutputPath(), "/builda/index.html"); t.is(await link4.toHref(), "/builda/"); t.deepEqual(link4.getServerlessUrls(), { serverless: "/serverlessa/", @@ -2167,7 +2168,7 @@ test("permalink object _getLink (array of serverless URLs)", async (t) => { serverless: ["/serverless1/", "/serverless2/"], }, }); - t.is(await link4.toLink(), "/serverless1/"); + t.is(await link4.toOutputPath(), false); t.is(await link4.toHref(), "/serverless1/"); t.deepEqual(link4.getServerlessUrls(), { @@ -2192,7 +2193,7 @@ test("permalink object _getLink (array of serverless URLs with template syntax)" serverless: ["/serverless1{{ test }}/", "/serverless2{{ test }}/"], }, }); - t.is(await link.toLink(), "/serverless1a/"); + t.is(await link.toOutputPath(), false); t.is(await link.toHref(), "/serverless1a/"); t.deepEqual(link.getServerlessUrls(), { @@ -2217,15 +2218,15 @@ test("Do not resolve page.url from eleventy serverless data", async (t) => { let outputHref = await tmpl.getOutputHref(fakeData); t.is(outputHref, "/serverless/"); - let outputLink = await tmpl.getOutputLink(fakeData); - t.is(outputLink, "/serverless/"); + let outputLink = await tmpl.getRawOutputPath(fakeData); + t.is(outputLink, false); let outputPath = await tmpl.getOutputPath(fakeData); t.is(outputPath, false); - let { href, link, path } = await tmpl.getOutputLocations(fakeData); + let { href, rawPath, path } = await tmpl.getOutputLocations(fakeData); t.is(href, "/serverless/"); - t.is(link, "/serverless/"); + t.is(rawPath, false); t.is(path, false); }); @@ -2245,15 +2246,15 @@ test("Do not override page.url with serverless url", async (t) => { let outputHref = await tmpl.getOutputHref(fakeData); t.is(outputHref, "/build/"); - let outputLink = await tmpl.getOutputLink(fakeData); + let outputLink = await tmpl.getRawOutputPath(fakeData); t.is(outputLink, "/build/index.html"); let outputPath = await tmpl.getOutputPath(fakeData); t.is(outputPath, "./test/stubs/_site/build/index.html"); - let { href, link, path } = await tmpl.getOutputLocations(fakeData); + let { href, rawPath, path } = await tmpl.getOutputLocations(fakeData); t.is(href, "/build/"); - t.is(link, "/build/index.html"); + t.is(rawPath, "/build/index.html"); t.is(path, "./test/stubs/_site/build/index.html"); }); @@ -2268,7 +2269,7 @@ test("Permalink is an object but an empty object (inherit default behavior)", as let outputHref = await tmpl.getOutputHref(data); t.is(outputHref, "/permalink-empty-object/empty-object/"); - let outputLink = await tmpl.getOutputLink(data); + let outputLink = await tmpl.getRawOutputPath(data); t.is(outputLink, "permalink-empty-object/empty-object/index.html"); let outputPath = await tmpl.getOutputPath(data); @@ -2277,9 +2278,9 @@ test("Permalink is an object but an empty object (inherit default behavior)", as "./test/stubs/_site/permalink-empty-object/empty-object/index.html" ); - let { href, link, path } = await tmpl.getOutputLocations(data); + let { href, rawPath, path } = await tmpl.getOutputLocations(data); t.is(href, "/permalink-empty-object/empty-object/"); - t.is(link, "permalink-empty-object/empty-object/index.html"); + t.is(rawPath, "permalink-empty-object/empty-object/index.html"); t.is( path, "./test/stubs/_site/permalink-empty-object/empty-object/index.html" diff --git a/test/TemplateTest_Permalink.js b/test/TemplateTest_Permalink.js index c7832a9d9..ff73f9be9 100644 --- a/test/TemplateTest_Permalink.js +++ b/test/TemplateTest_Permalink.js @@ -110,7 +110,7 @@ test("permalink: true", async (t) => { let data = await tmpl.getData(); await t.throwsAsync(async () => { - await tmpl.getOutputLink(data); + await tmpl.getRawOutputPath(data); }); }); @@ -121,7 +121,7 @@ test("Disable dynamic permalinks", async (t) => { "./test/stubs/_site" ); - t.is(await tmpl.getOutputLink(), "/{{justastring}}/index.html"); + t.is(await tmpl.getRawOutputPath(), "/{{justastring}}/index.html"); t.is(await tmpl.getOutputHref(), "/{{justastring}}/"); }); From 713d61c24e5e0a0bc9587219a1268435efe63de9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 3 Sep 2021 14:33:34 -0500 Subject: [PATCH 576/746] v1.0.0-canary.42 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 770e4bd66..63bb1bffb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.41", + "version": "1.0.0-canary.42", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From f83fc0bcc0eb5d6403c6aa5f5f89587dec77cf29 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 6 Sep 2021 15:17:48 -0500 Subject: [PATCH 577/746] Swap to ELEVENTY_NUNJUCKS_SPEEDBOOST_OPTIN. Fixes #1960. Related to #1678. --- src/Engines/Nunjucks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 7bb0003ab..fa48daf8f 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -10,7 +10,7 @@ const eventBus = require("../EventBus"); * compiled templates and re-use them where possible. */ (function () { - if (process.env.ELEVENTY_NUNJUCKS_SPEEDBOOST_OPTOUT) { + if (!process.env.ELEVENTY_NUNJUCKS_SPEEDBOOST_OPTIN) { return; } From f59866198bf1a0f221248617889ff0d2990d398f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 6 Sep 2021 15:18:17 -0500 Subject: [PATCH 578/746] v1.0.0-canary.43 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63bb1bffb..88b5413ce 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.42", + "version": "1.0.0-canary.43", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 229f3801d506d30beb745ef907cf86fe69df623e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 8 Sep 2021 12:38:12 -0500 Subject: [PATCH 579/746] Make process.env.ELEVENTY_SERVERLESS work correctly when using --serve. --- src/Eleventy.js | 4 +++- src/Serverless.js | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 26a704323..e365b7cfe 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -407,7 +407,9 @@ Verbose Output: ${this.verboseMode}`); process.env.ELEVENTY_SOURCE = this.source; - // TODO @zachleat this needs to be extensible. https://github.com/11ty/eleventy/issues/1957 + // TODO (@zachleat) this needs to be extensible. https://github.com/11ty/eleventy/issues/1957 + // Note: when using --serve, ELEVENTY_SERVERLESS is set manually in Serverless.js + // Careful here, setting to false will cast to string "false" which is truthy. if (process.env.AWS_LAMBDA_FUNCTION_NAME) { process.env.ELEVENTY_SERVERLESS = true; diff --git a/src/Serverless.js b/src/Serverless.js index 0fcdd6d9b..8c6e8dfce 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -54,6 +54,21 @@ class Serverless { this.dir = this.getProjectDir(); } + initializeEnvironmentVariables() { + // set and delete env variables to make it work the same on --serve + this.serverlessEnvironmentVariableAlreadySet = + !!process.env.ELEVENTY_SERVERLESS; + if (!this.serverlessEnvironmentVariableAlreadySet) { + process.env.ELEVENTY_SERVERLESS = true; + } + } + + deleteEnvironmentVariables() { + if (!this.serverlessEnvironmentVariableAlreadySet) { + delete process.env.ELEVENTY_SERVERLESS; + } + } + getProjectDir() { // TODO? improve with process.env.LAMBDA_TASK_ROOT—was `/var/task/` on lambda (not local) let dir = path.join(this.options.functionsDir, this.name); @@ -169,6 +184,9 @@ class Serverless { debug("Path params: %o", pathParams); debug(`Input path: ${inputPath}`); + // TODO (@zachleat) change to use this hook: https://github.com/11ty/eleventy/issues/1957 + this.initializeEnvironmentVariables(); + let elev = new Eleventy(this.options.input || inputPath, null, { configPath, inputDir, @@ -192,6 +210,10 @@ class Serverless { await elev.init(); let json = await elev.toJSON(); + + // TODO (@zachleat) https://github.com/11ty/eleventy/issues/1957 + this.deleteEnvironmentVariables(); + if (!json.length) { let err = new Error( `Couldn’t find any generated output from Eleventy (URL path parameters: ${JSON.stringify( From e9bd82da3f506956340d085f0a1f07a1b1ba3eee Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 8 Sep 2021 12:39:29 -0500 Subject: [PATCH 580/746] v1.0.0-canary.44 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88b5413ce..876284994 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.43", + "version": "1.0.0-canary.44", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 7be489346df5755e49dbd5ff002faf450cd94ee2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Sep 2021 10:21:47 -0500 Subject: [PATCH 581/746] Fixes https://github.com/11ty/eleventy/issues/1977 --- src/Template.js | 3 +++ src/TemplateData.js | 11 +++++++++++ src/TemplatePermalink.js | 11 +++++++++++ test/ServerlessTest.js | 11 +++++++++++ test/TemplatePermalinkTest.js | 10 ++++++++++ .../functions/test1/eleventy-serverless-map.json | 3 +++ test/serverless-stubs-page-url/test1.md | 6 ++++++ 7 files changed, 55 insertions(+) create mode 100644 test/serverless-stubs-page-url/functions/test1/eleventy-serverless-map.json create mode 100644 test/serverless-stubs-page-url/test1.md diff --git a/src/Template.js b/src/Template.js index 5843cb481..b0a3ea8a6 100755 --- a/src/Template.js +++ b/src/Template.js @@ -174,6 +174,9 @@ class Template extends TemplateContent { permalinkValue, this.extraOutputSubdirectory ); + if (this.templateData) { + perm.setServerlessPathData(this.templateData.getServerlessPathData()); + } this.behavior.setFromPermalink(perm); this.serverlessUrls = perm.getServerlessUrls(); diff --git a/src/TemplateData.js b/src/TemplateData.js index 149e5a2a0..85a1b88e3 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -598,6 +598,17 @@ class TemplateData { return data; } + + getServerlessPathData() { + if ( + this.configApiGlobalData && + this.configApiGlobalData.eleventy && + this.configApiGlobalData.eleventy.serverless && + this.configApiGlobalData.eleventy.serverless.path + ) { + return this.configApiGlobalData.eleventy.serverless.path; + } + } } module.exports = TemplateData; diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 883908981..5de1a0a11 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -2,6 +2,7 @@ const path = require("path"); const TemplatePath = require("./TemplatePath"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); +const serverlessUrlFilter = require("./Filters/ServerlessUrl"); class TemplatePermalink { // `link` with template syntax should have already been rendered in Template.js @@ -70,6 +71,10 @@ class TemplatePermalink { this.extraPaginationSubdir = extraSubdir || ""; } + setServerlessPathData(data) { + this.serverlessPathData = data; + } + getServerlessUrls() { return this.serverlessUrls; } @@ -102,6 +107,12 @@ class TemplatePermalink { // test/index.html becomes test/ toHref() { if (this.primaryServerlessUrl) { + if (this.serverlessPathData) { + return serverlessUrlFilter( + this.primaryServerlessUrl, + this.serverlessPathData + ); + } return this.primaryServerlessUrl; } else if (!this.buildLink) { // empty or false diff --git a/test/ServerlessTest.js b/test/ServerlessTest.js index 5e7c424c0..a5ce0a08e 100644 --- a/test/ServerlessTest.js +++ b/test/ServerlessTest.js @@ -22,3 +22,14 @@ test("Test a transform on serverless output.", async (t) => { t.is((await elev.render()).trim(), "

Hi

Hi

"); }); + +test("Test page.url on serverless output.", async (t) => { + let elev = new EleventyServerless("test1", { + path: "/sample/", + query: {}, + inputDir: "./test/serverless-stubs-page-url/", + functionsDir: "./test/serverless-stubs-page-url/functions/", + }); + + t.is((await elev.render()).trim(), "

/sample/

"); +}); diff --git a/test/TemplatePermalinkTest.js b/test/TemplatePermalinkTest.js index 2678e5221..9f410a5f4 100644 --- a/test/TemplatePermalinkTest.js +++ b/test/TemplatePermalinkTest.js @@ -257,3 +257,13 @@ test("Permalink Object, empty object", (t) => { t.is(new TemplatePermalink({}).toHref(), false); }); + +test("Permalink Object, serverless with path params", (t) => { + let perm = new TemplatePermalink({ + serverless: "/serverless/:test/", + }); + perm.setServerlessPathData({ + test: "yeearg", + }); + t.is(perm.toHref(), "/serverless/yeearg/"); +}); diff --git a/test/serverless-stubs-page-url/functions/test1/eleventy-serverless-map.json b/test/serverless-stubs-page-url/functions/test1/eleventy-serverless-map.json new file mode 100644 index 000000000..1da05e56f --- /dev/null +++ b/test/serverless-stubs-page-url/functions/test1/eleventy-serverless-map.json @@ -0,0 +1,3 @@ +{ + "/:test/": "./test/serverless-stubs-page-url/test1.md" +} \ No newline at end of file diff --git a/test/serverless-stubs-page-url/test1.md b/test/serverless-stubs-page-url/test1.md new file mode 100644 index 000000000..cb4e4cba3 --- /dev/null +++ b/test/serverless-stubs-page-url/test1.md @@ -0,0 +1,6 @@ +--- +permalink: + test1: /:test/ +--- + +# {{ page.url }} From 1ea7a8217365a0c3de7cd2ab3fdfb250d8e078d7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 26 Sep 2021 22:24:00 -0500 Subject: [PATCH 582/746] Fixes #915. --- src/Template.js | 20 +++-- src/TemplateData.js | 13 ++- src/TemplateLayout.js | 2 +- test/TemplateDataTest.js | 8 +- test/TemplateLayoutTest.js | 4 +- test/TemplateTest-DataCascade.js | 85 +++++++++++++++++++ test/TemplateTest.js | 27 +----- test/UserDataExtensionsTest.js | 2 +- .../global-versus-layout/_data/cascade.js | 1 + .../global-versus-layout/_includes/base.njk | 3 + .../global-versus-layout/test.njk | 3 + .../src/_includes/base.njk | 3 + .../src/src.11tydata.js | 3 + .../layout-versus-dirdatafile/src/test.njk | 3 + .../_includes/base.njk | 3 + .../test.11tydata.js | 3 + .../layout-versus-tmpldatafile/test.njk | 3 + 17 files changed, 148 insertions(+), 38 deletions(-) create mode 100644 test/TemplateTest-DataCascade.js create mode 100644 test/stubs-data-cascade/global-versus-layout/_data/cascade.js create mode 100644 test/stubs-data-cascade/global-versus-layout/_includes/base.njk create mode 100644 test/stubs-data-cascade/global-versus-layout/test.njk create mode 100644 test/stubs-data-cascade/layout-versus-dirdatafile/src/_includes/base.njk create mode 100644 test/stubs-data-cascade/layout-versus-dirdatafile/src/src.11tydata.js create mode 100644 test/stubs-data-cascade/layout-versus-dirdatafile/src/test.njk create mode 100644 test/stubs-data-cascade/layout-versus-tmpldatafile/_includes/base.njk create mode 100644 test/stubs-data-cascade/layout-versus-tmpldatafile/test.11tydata.js create mode 100644 test/stubs-data-cascade/layout-versus-tmpldatafile/test.njk diff --git a/src/Template.js b/src/Template.js index b0a3ea8a6..971eef071 100755 --- a/src/Template.js +++ b/src/Template.js @@ -128,12 +128,12 @@ class Template extends TemplateContent { return this._layout; } - async getLayoutChain() { + async _testGetLayoutChain() { if (!this._layout) { await this.getData(); } - return this._layout.getLayoutChain(); + return this._layout._testGetLayoutChain(); } get baseFile() { @@ -360,10 +360,17 @@ class Template extends TemplateContent { if (!this.dataCache) { debugDev("%o getData()", this.inputPath); let localData = {}; + let globalData = {}; if (this.templateData) { - localData = await this.templateData.getLocalData(this.inputPath); - debugDev("%o getData() getLocalData", this.inputPath); + localData = await this.templateData.getTemplateDirectoryData( + this.inputPath + ); + globalData = await this.templateData.getGlobalData(this.inputPath); + debugDev( + "%o getData() getTemplateDirectoryData and getGlobalData", + this.inputPath + ); } let frontMatterData = await this.getFrontMatterData(); @@ -371,6 +378,7 @@ class Template extends TemplateContent { frontMatterData[this.config.keys.layout] || localData[this.config.keys.layout]; + // Layout front matter data let mergedLayoutData = {}; if (layoutKey) { let layout = this.getLayout(layoutKey); @@ -382,11 +390,13 @@ class Template extends TemplateContent { ); } + // START HERE, move front merged layout data lower than local data let mergedData = TemplateData.mergeDeep( this.config, {}, - localData, + globalData, mergedLayoutData, + localData, frontMatterData ); mergedData = await this.addPageDate(mergedData); diff --git a/src/TemplateData.js b/src/TemplateData.js index 85a1b88e3..8c2aa3117 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -359,7 +359,18 @@ class TemplateData { return localData; } - async getLocalData(templatePath) { + async getTemplateDirectoryData(templatePath) { + let localDataPaths = await this.getLocalDataPaths(templatePath); + let importedData = await this.combineLocalData(localDataPaths); + // OK-ish: shallow merge when combining template/data dir files + return Object.assign({}, importedData); + } + + async getGlobalData() { + return this.getData(); + } + + async _testGetLocalData(templatePath) { let localDataPaths = await this.getLocalDataPaths(templatePath); let importedData = await this.combineLocalData(localDataPaths); let globalData = await this.getData(); diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index 99761f777..da15d1647 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -109,7 +109,7 @@ class TemplateLayout extends TemplateContent { return data; } - async getLayoutChain() { + async _testGetLayoutChain() { if (!this.layoutChain) { await this.getData(); } diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 408589bb0..6c1be9c52 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -61,7 +61,7 @@ test("Add local data", async (t) => { t.is(data.globalData.datakey1, "datavalue1"); t.is(data.globalData.datakey2, "@11ty/eleventy"); - let withLocalData = await dataObj.getLocalData( + let withLocalData = await dataObj._testGetLocalData( "./test/stubs/component/component.njk" ); t.is(withLocalData.globalData.datakey1, "datavalue1"); @@ -79,7 +79,7 @@ test("Get local data async JS", async (t) => { let eleventyConfig = new TemplateConfig(); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - let withLocalData = await dataObj.getLocalData( + let withLocalData = await dataObj._testGetLocalData( "./test/stubs/component-async/component.njk" ); @@ -97,7 +97,7 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does exis let beforeDataKeyCount = Object.keys(data); // template file does exist - let withLocalData = await dataObj.getLocalData( + let withLocalData = await dataObj._testGetLocalData( "./test/stubs/datafiledoesnotexist/template.njk" ); t.is(withLocalData.globalData.datakey1, "datavalue1"); @@ -113,7 +113,7 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does not let data = await dataObj.getData(); let beforeDataKeyCount = Object.keys(data); - let withLocalData = await dataObj.getLocalData( + let withLocalData = await dataObj._testGetLocalData( "./test/stubs/datafiledoesnotexist/templatedoesnotexist.njk" ); t.is(withLocalData.globalData.datakey1, "datavalue1"); diff --git a/test/TemplateLayoutTest.js b/test/TemplateLayoutTest.js index 0f5bb2887..ebea1c8eb 100644 --- a/test/TemplateLayoutTest.js +++ b/test/TemplateLayoutTest.js @@ -48,7 +48,7 @@ test("Get Layout Chain", async (t) => { "./test/stubs" ); - t.deepEqual(await tl.getLayoutChain(), [ + t.deepEqual(await tl._testGetLayoutChain(), [ "./test/stubs/_includes/layouts/layout-inherit-a.njk", "./test/stubs/_includes/layouts/layout-inherit-b.njk", "./test/stubs/_includes/layouts/layout-inherit-c.njk", @@ -72,7 +72,7 @@ test("Get Front Matter Data", async (t) => { secondinherits: "b", thirdinherits: "c", }); - t.deepEqual(await tl.getLayoutChain(), [ + t.deepEqual(await tl._testGetLayoutChain(), [ "./test/stubs/_includes/layouts/layout-inherit-a.njk", "./test/stubs/_includes/layouts/layout-inherit-b.njk", "./test/stubs/_includes/layouts/layout-inherit-c.njk", diff --git a/test/TemplateTest-DataCascade.js b/test/TemplateTest-DataCascade.js new file mode 100644 index 000000000..f48a8f7f4 --- /dev/null +++ b/test/TemplateTest-DataCascade.js @@ -0,0 +1,85 @@ +const test = require("ava"); +const getNewTemplate = require("./_getNewTemplateForTests"); +const TemplateConfig = require("../src/TemplateConfig"); +const TemplateData = require("../src/TemplateData"); + +// Prior to and including 0.10.0 this mismatched the documentation)! (Issue #915) +test("Layout front matter does not override template data files", async (t) => { + let eleventyConfig = new TemplateConfig(); + + let dataObj = new TemplateData( + "./test/stubs-data-cascade/layout-data-files/", + eleventyConfig + ); + let tmpl = getNewTemplate( + "./test/stubs-data-cascade/layout-data-files/test.njk", + "./test/stubs-data-cascade/layout-data-files/", + "./dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(data.shared, "datafile"); +}); + +test("Layout front matter should not override global data (sanity check, Issue 915)", async (t) => { + let eleventyConfig = new TemplateConfig(); + + let dataObj = new TemplateData( + "./test/stubs-data-cascade/global-versus-layout/", + eleventyConfig + ); + let tmpl = getNewTemplate( + "./test/stubs-data-cascade/global-versus-layout/test.njk", + "./test/stubs-data-cascade/global-versus-layout/", + "./dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(data.cascade, "from-layout-file"); +}); + +test("Template data files should be more specific in data cascade than Layout front matter (breaking change in 1.0, issue 915)", async (t) => { + let eleventyConfig = new TemplateConfig(); + + let dataObj = new TemplateData( + "./test/stubs-data-cascade/layout-versus-tmpldatafile/", + eleventyConfig + ); + let tmpl = getNewTemplate( + "./test/stubs-data-cascade/layout-versus-tmpldatafile/test.njk", + "./test/stubs-data-cascade/layout-versus-tmpldatafile/", + "./dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(data.cascade, "template-data-file"); +}); + +test("Directory data files should be more specific in data cascade than Layout front matter (breaking change in 1.0, issue 915)", async (t) => { + let eleventyConfig = new TemplateConfig(); + + let dataObj = new TemplateData( + "./test/stubs-data-cascade/layout-versus-dirdatafile/src/", + eleventyConfig + ); + let tmpl = getNewTemplate( + "./test/stubs-data-cascade/layout-versus-dirdatafile/src/test.njk", + "./test/stubs-data-cascade/layout-versus-dirdatafile/src/", + "./dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(data.cascade, "dir-data-file"); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 837b5e40d..009a9ec92 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -527,7 +527,7 @@ test("Posts inherits local JSON, layouts", async (t) => { "./test/stubs/posts/post1.11tydata.js", ]); - let localData = await dataObj.getLocalData(tmpl.getInputPath()); + let localData = await dataObj._testGetLocalData(tmpl.getInputPath()); t.is(localData.layout, "mylocallayout.njk"); t.truthy(localData.pkg); @@ -565,7 +565,7 @@ test("Template and folder name are the same, make sure data imports work ok", as "./test/stubs/posts/posts.11tydata.js", ]); - let localData = await dataObj.getLocalData(tmpl.getInputPath()); + let localData = await dataObj._testGetLocalData(tmpl.getInputPath()); t.is(localData.layout, "mylocallayout.njk"); t.truthy(localData.pkg); @@ -1930,27 +1930,6 @@ test("Issue #446: Layout has a permalink with a different template language than t.is(data.page.url, "/test/"); }); -// Prior to and including 0.10.0 this mismatched the documentation)! -test("Layout front matter should override template files", async (t) => { - let eleventyConfig = new TemplateConfig(); - - let dataObj = new TemplateData( - "./test/stubs-data-cascade/layout-data-files/", - eleventyConfig - ); - let tmpl = getNewTemplate( - "./test/stubs-data-cascade/layout-data-files/test.njk", - "./test/stubs-data-cascade/layout-data-files/", - "./dist", - dataObj, - null, - eleventyConfig - ); - - let data = await tmpl.getData(); - t.is(data.shared, "layout"); -}); - test("Get Layout Chain", async (t) => { let tmpl = getNewTemplate( "./test/stubs-incremental/layout-chain/test.njk", @@ -1958,7 +1937,7 @@ test("Get Layout Chain", async (t) => { "./dist" ); - let layoutChain = await tmpl.getLayoutChain(); + let layoutChain = await tmpl._testGetLayoutChain(); t.deepEqual(layoutChain, [ "./test/stubs-incremental/layout-chain/_includes/base.njk", "./test/stubs-incremental/layout-chain/_includes/parent.njk", diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index d07384230..065e2d169 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -26,7 +26,7 @@ test("Local data", async (t) => { t.is(data.globalData4.datakey1, "datavalue4"); t.is(data.globalData4.datakey2, "@11ty/eleventy--nosj"); - let withLocalData = await dataObj.getLocalData( + let withLocalData = await dataObj._testGetLocalData( "./test/stubs-630/component-yaml/component.njk" ); diff --git a/test/stubs-data-cascade/global-versus-layout/_data/cascade.js b/test/stubs-data-cascade/global-versus-layout/_data/cascade.js new file mode 100644 index 000000000..5b7921ec8 --- /dev/null +++ b/test/stubs-data-cascade/global-versus-layout/_data/cascade.js @@ -0,0 +1 @@ +module.exports = "from-global-data"; diff --git a/test/stubs-data-cascade/global-versus-layout/_includes/base.njk b/test/stubs-data-cascade/global-versus-layout/_includes/base.njk new file mode 100644 index 000000000..f1c57e5bc --- /dev/null +++ b/test/stubs-data-cascade/global-versus-layout/_includes/base.njk @@ -0,0 +1,3 @@ +--- +cascade: "from-layout-file" +--- \ No newline at end of file diff --git a/test/stubs-data-cascade/global-versus-layout/test.njk b/test/stubs-data-cascade/global-versus-layout/test.njk new file mode 100644 index 000000000..95694dff6 --- /dev/null +++ b/test/stubs-data-cascade/global-versus-layout/test.njk @@ -0,0 +1,3 @@ +--- +layout: "base.njk" +--- \ No newline at end of file diff --git a/test/stubs-data-cascade/layout-versus-dirdatafile/src/_includes/base.njk b/test/stubs-data-cascade/layout-versus-dirdatafile/src/_includes/base.njk new file mode 100644 index 000000000..f1c57e5bc --- /dev/null +++ b/test/stubs-data-cascade/layout-versus-dirdatafile/src/_includes/base.njk @@ -0,0 +1,3 @@ +--- +cascade: "from-layout-file" +--- \ No newline at end of file diff --git a/test/stubs-data-cascade/layout-versus-dirdatafile/src/src.11tydata.js b/test/stubs-data-cascade/layout-versus-dirdatafile/src/src.11tydata.js new file mode 100644 index 000000000..a37afe526 --- /dev/null +++ b/test/stubs-data-cascade/layout-versus-dirdatafile/src/src.11tydata.js @@ -0,0 +1,3 @@ +module.exports = { + cascade: "dir-data-file", +}; diff --git a/test/stubs-data-cascade/layout-versus-dirdatafile/src/test.njk b/test/stubs-data-cascade/layout-versus-dirdatafile/src/test.njk new file mode 100644 index 000000000..95694dff6 --- /dev/null +++ b/test/stubs-data-cascade/layout-versus-dirdatafile/src/test.njk @@ -0,0 +1,3 @@ +--- +layout: "base.njk" +--- \ No newline at end of file diff --git a/test/stubs-data-cascade/layout-versus-tmpldatafile/_includes/base.njk b/test/stubs-data-cascade/layout-versus-tmpldatafile/_includes/base.njk new file mode 100644 index 000000000..f1c57e5bc --- /dev/null +++ b/test/stubs-data-cascade/layout-versus-tmpldatafile/_includes/base.njk @@ -0,0 +1,3 @@ +--- +cascade: "from-layout-file" +--- \ No newline at end of file diff --git a/test/stubs-data-cascade/layout-versus-tmpldatafile/test.11tydata.js b/test/stubs-data-cascade/layout-versus-tmpldatafile/test.11tydata.js new file mode 100644 index 000000000..01a61c626 --- /dev/null +++ b/test/stubs-data-cascade/layout-versus-tmpldatafile/test.11tydata.js @@ -0,0 +1,3 @@ +module.exports = { + cascade: "template-data-file", +}; diff --git a/test/stubs-data-cascade/layout-versus-tmpldatafile/test.njk b/test/stubs-data-cascade/layout-versus-tmpldatafile/test.njk new file mode 100644 index 000000000..95694dff6 --- /dev/null +++ b/test/stubs-data-cascade/layout-versus-tmpldatafile/test.njk @@ -0,0 +1,3 @@ +--- +layout: "base.njk" +--- \ No newline at end of file From c1b9ebeb7fc305ab77c48d26eabfa542580ef8ed Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Sep 2021 09:49:52 -0500 Subject: [PATCH 583/746] Fixes #919 --- src/Template.js | 1 - src/TemplateData.js | 17 +++++++++++++---- test/PaginationTest.js | 21 +++++++++++++++++++++ test/stubs-919/test.11tydata.js | 5 +++++ test/stubs-919/test.njk | 10 ++++++++++ test/stubs-919/test2.njk | 0 6 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 test/stubs-919/test.11tydata.js create mode 100644 test/stubs-919/test.njk create mode 100644 test/stubs-919/test2.njk diff --git a/src/Template.js b/src/Template.js index 971eef071..0a77bff89 100755 --- a/src/Template.js +++ b/src/Template.js @@ -390,7 +390,6 @@ class Template extends TemplateContent { ); } - // START HERE, move front merged layout data lower than local data let mergedData = TemplateData.mergeDeep( this.config, {}, diff --git a/src/TemplateData.js b/src/TemplateData.js index 8c2aa3117..67c473bdb 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -57,6 +57,7 @@ class TemplateData { this.rawImports = {}; this.globalData = null; + this.templateDirectoryData = {}; // It's common for data files not to exist, so we avoid going to the FS to // re-check if they do via a quick-and-dirty cache. @@ -121,6 +122,7 @@ class TemplateData { clearData() { this.globalData = null; + this.templateDirectoryData = {}; } async cacheData() { @@ -360,16 +362,23 @@ class TemplateData { } async getTemplateDirectoryData(templatePath) { - let localDataPaths = await this.getLocalDataPaths(templatePath); - let importedData = await this.combineLocalData(localDataPaths); - // OK-ish: shallow merge when combining template/data dir files - return Object.assign({}, importedData); + if (!this.templateDirectoryData[templatePath]) { + let localDataPaths = await this.getLocalDataPaths(templatePath); + let importedData = await this.combineLocalData(localDataPaths); + + this.templateDirectoryData[templatePath] = Object.assign( + {}, + importedData + ); + } + return this.templateDirectoryData[templatePath]; } async getGlobalData() { return this.getData(); } + // TODO get rid of this, it’s been refactored to separate `getTemplateDirectoryData` and `getGlobalData` calls async _testGetLocalData(templatePath) { let localDataPaths = await this.getLocalDataPaths(templatePath); let importedData = await this.combineLocalData(localDataPaths); diff --git a/test/PaginationTest.js b/test/PaginationTest.js index 270ed6146..a1d67e0c8 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -793,3 +793,24 @@ test("Pagination mutable global data", async (t) => { t.deepEqual(templates[1].data.item, { key3: "item3", key4: "item4" }); t.deepEqual(templates[2].data.item, { key5: "item5", key6: "item6" }); }); + +test("Pagination template/dir data files run once, Issue 919", async (t) => { + let eleventyConfig = new TemplateConfig(); + let dataObj = new TemplateData("./test/stubs-919/", eleventyConfig); + + let tmpl = getNewTemplate( + "./test/stubs-919/test.njk", + "./test/stubs-919/", + "./dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + + t.is(templates.length, 3); + t.is(templates[0].data.test, templates[1].data.test); + t.is(templates[1].data.test, templates[2].data.test); +}); diff --git a/test/stubs-919/test.11tydata.js b/test/stubs-919/test.11tydata.js new file mode 100644 index 000000000..1a34c93d5 --- /dev/null +++ b/test/stubs-919/test.11tydata.js @@ -0,0 +1,5 @@ +module.exports = function () { + return { + test: Math.random(), + }; +}; diff --git a/test/stubs-919/test.njk b/test/stubs-919/test.njk new file mode 100644 index 000000000..0e94cdaac --- /dev/null +++ b/test/stubs-919/test.njk @@ -0,0 +1,10 @@ +--- +root: + - one + - two + - three +pagination: + data: "root" + size: 1 +--- +{{ test | log }} \ No newline at end of file diff --git a/test/stubs-919/test2.njk b/test/stubs-919/test2.njk new file mode 100644 index 000000000..e69de29bb From 508114a6743fac1741d581cbf19d54b7d96d974a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Sep 2021 09:57:02 -0500 Subject: [PATCH 584/746] Refactor to get rid of _test method caused by changes to #915 --- src/TemplateData.js | 12 ------------ test/TemplateDataTest.js | 23 +++++++++++++++++++---- test/TemplateTest.js | 12 ++++++++---- test/UserDataExtensionsTest.js | 2 +- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 67c473bdb..ab5e4b360 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -378,18 +378,6 @@ class TemplateData { return this.getData(); } - // TODO get rid of this, it’s been refactored to separate `getTemplateDirectoryData` and `getGlobalData` calls - async _testGetLocalData(templatePath) { - let localDataPaths = await this.getLocalDataPaths(templatePath); - let importedData = await this.combineLocalData(localDataPaths); - let globalData = await this.getData(); - - // OK-ish: shallow merge when combining template/data dir files with global data files - let localData = Object.assign({}, globalData, importedData); - // debug("`getLocalData` for %o: %O", templatePath, localData); - return localData; - } - getUserDataExtensions() { if (!this.config.dataExtensions) { return []; diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 6c1be9c52..1d19ff0ec 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -2,6 +2,17 @@ const test = require("ava"); const TemplateData = require("../src/TemplateData"); const TemplateConfig = require("../src/TemplateConfig"); +async function testGetLocalData(tmplData, templatePath) { + let localDataPaths = await tmplData.getLocalDataPaths(templatePath); + let importedData = await tmplData.combineLocalData(localDataPaths); + let globalData = await tmplData.getData(); + + // OK-ish: shallow merge when combining template/data dir files with global data files + let localData = Object.assign({}, globalData, importedData); + // debug("`getLocalData` for %o: %O", templatePath, localData); + return localData; +} + test("Create", async (t) => { let eleventyConfig = new TemplateConfig(); let config = eleventyConfig.getConfig(); @@ -61,7 +72,8 @@ test("Add local data", async (t) => { t.is(data.globalData.datakey1, "datavalue1"); t.is(data.globalData.datakey2, "@11ty/eleventy"); - let withLocalData = await dataObj._testGetLocalData( + let withLocalData = await testGetLocalData( + dataObj, "./test/stubs/component/component.njk" ); t.is(withLocalData.globalData.datakey1, "datavalue1"); @@ -79,7 +91,8 @@ test("Get local data async JS", async (t) => { let eleventyConfig = new TemplateConfig(); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - let withLocalData = await dataObj._testGetLocalData( + let withLocalData = await testGetLocalData( + dataObj, "./test/stubs/component-async/component.njk" ); @@ -97,7 +110,8 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does exis let beforeDataKeyCount = Object.keys(data); // template file does exist - let withLocalData = await dataObj._testGetLocalData( + let withLocalData = await testGetLocalData( + dataObj, "./test/stubs/datafiledoesnotexist/template.njk" ); t.is(withLocalData.globalData.datakey1, "datavalue1"); @@ -113,7 +127,8 @@ test("addLocalData() doesn’t exist but doesn’t fail (template file does not let data = await dataObj.getData(); let beforeDataKeyCount = Object.keys(data); - let withLocalData = await dataObj._testGetLocalData( + let withLocalData = await testGetLocalData( + dataObj, "./test/stubs/datafiledoesnotexist/templatedoesnotexist.njk" ); t.is(withLocalData.globalData.datakey1, "datavalue1"); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 009a9ec92..81571ac56 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -527,9 +527,11 @@ test("Posts inherits local JSON, layouts", async (t) => { "./test/stubs/posts/post1.11tydata.js", ]); - let localData = await dataObj._testGetLocalData(tmpl.getInputPath()); + let localData = await dataObj.getTemplateDirectoryData(tmpl.getInputPath()); t.is(localData.layout, "mylocallayout.njk"); - t.truthy(localData.pkg); + + let globalData = await dataObj.getGlobalData(); + t.truthy(globalData.pkg); let data = await tmpl.getData(); t.is(localData.layout, "mylocallayout.njk"); @@ -565,9 +567,11 @@ test("Template and folder name are the same, make sure data imports work ok", as "./test/stubs/posts/posts.11tydata.js", ]); - let localData = await dataObj._testGetLocalData(tmpl.getInputPath()); + let localData = await dataObj.getTemplateDirectoryData(tmpl.getInputPath()); t.is(localData.layout, "mylocallayout.njk"); - t.truthy(localData.pkg); + + let globalData = await dataObj.getGlobalData(); + t.truthy(globalData.pkg); let data = await tmpl.getData(); t.is(localData.layout, "mylocallayout.njk"); diff --git a/test/UserDataExtensionsTest.js b/test/UserDataExtensionsTest.js index 065e2d169..e46ec4568 100644 --- a/test/UserDataExtensionsTest.js +++ b/test/UserDataExtensionsTest.js @@ -26,7 +26,7 @@ test("Local data", async (t) => { t.is(data.globalData4.datakey1, "datavalue4"); t.is(data.globalData4.datakey2, "@11ty/eleventy--nosj"); - let withLocalData = await dataObj._testGetLocalData( + let withLocalData = await dataObj.getTemplateDirectoryData( "./test/stubs-630/component-yaml/component.njk" ); From 261958df8cde87f1e947aa75a93c3598d4fd1fb7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Sep 2021 21:15:48 -0500 Subject: [PATCH 585/746] Fixes https://github.com/11ty/eleventy/issues/1988 --- package.json | 4 ++-- src/Filters/ServerlessUrl.js | 6 +++--- src/Serverless.js | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 876284994..4e61b99a7 100755 --- a/package.json +++ b/package.json @@ -114,6 +114,7 @@ "mustache": "^4.2.0", "normalize-path": "^3.0.0", "nunjucks": "^3.2.3", + "path-to-regexp": "^6.2.0", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^3.0.2", @@ -121,7 +122,6 @@ "semver": "^7.3.5", "slugify": "^1.6.0", "split": "^1.0.1", - "time-require": "^0.1.2", - "url-pattern": "^1.0.3" + "time-require": "^0.1.2" } } diff --git a/src/Filters/ServerlessUrl.js b/src/Filters/ServerlessUrl.js index a4deb42e0..33d15999f 100644 --- a/src/Filters/ServerlessUrl.js +++ b/src/Filters/ServerlessUrl.js @@ -1,8 +1,8 @@ -const UrlPattern = require("url-pattern"); +const { compile } = require("path-to-regexp"); function stringify(url, urlData = {}) { - let pattern = new UrlPattern(url); - return pattern.stringify(urlData); + let fn = compile(url, { encode: encodeURIComponent }); + return fn(urlData); } module.exports = function (url, urlData = {}) { diff --git a/src/Serverless.js b/src/Serverless.js index 8c6e8dfce..e6043054d 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -3,7 +3,7 @@ const fs = require("fs"); const Eleventy = require("./Eleventy"); const TemplatePath = require("./TemplatePath"); -const UrlPattern = require("url-pattern"); +const { match } = require("path-to-regexp"); const deleteRequireCache = require("./Util/DeleteRequireCache"); const debug = require("debug")("Eleventy:Serverless"); @@ -40,8 +40,8 @@ class Serverless { inputDir: null, // override only, we now inject this. functionsDir: "functions/", matchUrlToPattern(path, urlToCompare) { - let pattern = new UrlPattern(urlToCompare); - return pattern.match(path); + let fn = match(urlToCompare, { decode: decodeURIComponent }); + return fn(path); }, // Query String Parameters query: {}, @@ -131,7 +131,7 @@ class Serverless { if (result) { matches.push({ compareTo: url, - pathParams: result, + pathParams: result.params, inputPath: contentMap[url], }); } From c03d1d915bb38f48d0cc5309f714cc91da6cd493 Mon Sep 17 00:00:00 2001 From: Ziding Zhang Date: Tue, 28 Sep 2021 11:10:03 +0100 Subject: [PATCH 586/746] Create SECURITY.md To let the repository confirm zach@zachleat.com as its security contact. Closes #1985 --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..defd666c9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +Please report security issues to `zach@zachleat.com` From 2824db33bab6ef5e8790f2f15a651d331c146f30 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 3 Oct 2021 14:06:53 -0500 Subject: [PATCH 587/746] Update deps. Lock to liquidjs 9.25 for https://github.com/harttle/liquidjs/issues/395 --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4e61b99a7..e2fdd128a 100755 --- a/package.json +++ b/package.json @@ -77,14 +77,14 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.2", "ava": "^3.15.0", - "husky": "^7.0.1", + "husky": "^7.0.2", "js-yaml": "^4.1.0", "lint-staged": "^11.1.2", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", - "prettier": "^2.3.2", + "prettier": "^2.4.1", "rimraf": "^3.0.2", - "sass": "^1.37.5", + "sass": "^1.42.1", "toml": "^3.0.0", "vue": "^2.6.14", "vue-server-renderer": "^2.6.14" @@ -103,8 +103,8 @@ "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", - "is-glob": "^4.0.1", - "liquidjs": "^9.25.1", + "is-glob": "^4.0.3", + "liquidjs": "9.25.1", "lodash": "^4.17.21", "luxon": "^2.0.2", "markdown-it": "^12.2.0", From 42d7265aad49c6789cb986de0dcedd70f47190ff Mon Sep 17 00:00:00 2001 From: Jiapei Liang Date: Mon, 4 Oct 2021 15:07:16 -0400 Subject: [PATCH 588/746] Updated LICENSE year to 2021 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 0ad7545c2..ebcbb6b4e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Zach Leatherman @zachleat +Copyright (c) 2021 Zach Leatherman @zachleat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From c78fdee4c02706a3cae3e9d43c3850dfe9bca66f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 6 Oct 2021 10:54:15 -0500 Subject: [PATCH 589/746] v1.0.0-beta.1 --- docs-src/_data/coverage.json | 115 ++++++++++++++++++----------------- docs/coverage.md | 107 ++++++++++++++++---------------- package.json | 6 +- 3 files changed, 119 insertions(+), 109 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 3fdef09ce..456254685 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,67 +1,72 @@ -{"total": {"lines":{"total":3463,"covered":3064,"skipped":0,"pct":88.48},"statements":{"total":3485,"covered":3085,"skipped":0,"pct":88.52},"functions":{"total":818,"covered":714,"skipped":0,"pct":87.29},"branches":{"total":1499,"covered":1213,"skipped":0,"pct":80.92}} +{"total": {"lines":{"total":4567,"covered":3786,"skipped":0,"pct":82.89},"statements":{"total":4592,"covered":3807,"skipped":0,"pct":82.9},"functions":{"total":1008,"covered":841,"skipped":0,"pct":83.43},"branches":{"total":2090,"covered":1563,"skipped":0,"pct":74.78}} +,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":55,"covered":34,"skipped":0,"pct":61.81},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":55,"covered":34,"skipped":0,"pct":61.81},"branches":{"total":24,"covered":14,"skipped":0,"pct":58.33}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":35,"skipped":0,"pct":76.09},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.67},"statements":{"total":46,"covered":35,"skipped":0,"pct":76.09},"branches":{"total":21,"covered":13,"skipped":0,"pct":61.9}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.78},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.78},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} -,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":46,"covered":46,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":46,"covered":46,"skipped":0,"pct":100},"branches":{"total":17,"covered":17,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.04},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.04},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.63}} -,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.73}} -,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":24,"covered":24,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/Config.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":221,"covered":122,"skipped":0,"pct":55.2},"functions":{"total":40,"covered":20,"skipped":0,"pct":50},"statements":{"total":222,"covered":122,"skipped":0,"pct":54.95},"branches":{"total":70,"covered":30,"skipped":0,"pct":42.86}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":47,"covered":37,"skipped":0,"pct":78.72},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":47,"covered":37,"skipped":0,"pct":78.72},"branches":{"total":19,"covered":12,"skipped":0,"pct":63.15}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.77},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.77},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":60,"covered":60,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":60,"covered":60,"skipped":0,"pct":100},"branches":{"total":29,"covered":28,"skipped":0,"pct":96.55}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.03},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.03},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.62}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":26,"covered":24,"skipped":0,"pct":92.3},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":26,"covered":24,"skipped":0,"pct":92.3},"branches":{"total":7,"covered":5,"skipped":0,"pct":71.42}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":310,"covered":197,"skipped":0,"pct":63.54},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":311,"covered":197,"skipped":0,"pct":63.34},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheck.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} -,"/Users/zachleat/Code/eleventy/src/EleventyConfig.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":35,"skipped":0,"pct":89.74},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":39,"covered":35,"skipped":0,"pct":89.74},"branches":{"total":43,"covered":29,"skipped":0,"pct":67.44}} -,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":19,"covered":19,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":64,"covered":64,"skipped":0,"pct":100},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":64,"covered":64,"skipped":0,"pct":100},"branches":{"total":31,"covered":31,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":165,"covered":155,"skipped":0,"pct":93.94},"functions":{"total":40,"covered":36,"skipped":0,"pct":90},"statements":{"total":165,"covered":155,"skipped":0,"pct":93.94},"branches":{"total":61,"covered":51,"skipped":0,"pct":83.61}} -,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":59,"covered":22,"skipped":0,"pct":37.29},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":59,"covered":22,"skipped":0,"pct":37.29},"branches":{"total":36,"covered":10,"skipped":0,"pct":27.78}} -,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":33,"covered":33,"skipped":0,"pct":100},"functions":{"total":16,"covered":16,"skipped":0,"pct":100},"statements":{"total":35,"covered":35,"skipped":0,"pct":100},"branches":{"total":17,"covered":15,"skipped":0,"pct":88.24}} -,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.84},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.84},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":309,"covered":294,"skipped":0,"pct":95.15},"functions":{"total":55,"covered":54,"skipped":0,"pct":98.18},"statements":{"total":311,"covered":296,"skipped":0,"pct":95.18},"branches":{"total":115,"covered":102,"skipped":0,"pct":88.7}} -,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":31,"covered":28,"skipped":0,"pct":90.32},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":34,"covered":31,"skipped":0,"pct":91.18},"branches":{"total":10,"covered":7,"skipped":0,"pct":70}} -,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":62,"covered":55,"skipped":0,"pct":88.71},"functions":{"total":10,"covered":6,"skipped":0,"pct":60},"statements":{"total":62,"covered":55,"skipped":0,"pct":88.71},"branches":{"total":26,"covered":24,"skipped":0,"pct":92.31}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":98,"covered":94,"skipped":0,"pct":95.92},"functions":{"total":18,"covered":18,"skipped":0,"pct":100},"statements":{"total":98,"covered":94,"skipped":0,"pct":95.92},"branches":{"total":36,"covered":33,"skipped":0,"pct":91.67}} -,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":221,"covered":212,"skipped":0,"pct":95.93},"functions":{"total":40,"covered":39,"skipped":0,"pct":97.5},"statements":{"total":224,"covered":215,"skipped":0,"pct":95.98},"branches":{"total":78,"covered":68,"skipped":0,"pct":87.18}} -,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":28,"covered":28,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":28,"covered":28,"skipped":0,"pct":100},"branches":{"total":10,"covered":10,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheckError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":36,"skipped":0,"pct":92.3},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":39,"covered":36,"skipped":0,"pct":92.3},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.56}} +,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":82,"covered":80,"skipped":0,"pct":97.56},"functions":{"total":25,"covered":24,"skipped":0,"pct":96},"statements":{"total":82,"covered":80,"skipped":0,"pct":97.56},"branches":{"total":39,"covered":35,"skipped":0,"pct":89.74}} +,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":188,"covered":167,"skipped":0,"pct":88.82},"functions":{"total":45,"covered":39,"skipped":0,"pct":86.66},"statements":{"total":190,"covered":168,"skipped":0,"pct":88.42},"branches":{"total":67,"covered":49,"skipped":0,"pct":73.13}} +,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":70,"covered":26,"skipped":0,"pct":37.14},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":70,"covered":26,"skipped":0,"pct":37.14},"branches":{"total":36,"covered":9,"skipped":0,"pct":25}} +,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":39,"covered":39,"skipped":0,"pct":100},"functions":{"total":17,"covered":17,"skipped":0,"pct":100},"statements":{"total":40,"covered":40,"skipped":0,"pct":100},"branches":{"total":21,"covered":19,"skipped":0,"pct":90.47}} +,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} +,"/Users/zachleat/Code/eleventy/src/EventBus.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":93,"covered":68,"skipped":0,"pct":73.11},"functions":{"total":11,"covered":9,"skipped":0,"pct":81.81},"statements":{"total":93,"covered":68,"skipped":0,"pct":73.11},"branches":{"total":36,"covered":22,"skipped":0,"pct":61.11}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":380,"covered":359,"skipped":0,"pct":94.47},"functions":{"total":70,"covered":69,"skipped":0,"pct":98.57},"statements":{"total":382,"covered":361,"skipped":0,"pct":94.5},"branches":{"total":165,"covered":142,"skipped":0,"pct":86.06}} +,"/Users/zachleat/Code/eleventy/src/TemplateBehavior.js": {"lines":{"total":24,"covered":21,"skipped":0,"pct":87.5},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":24,"covered":21,"skipped":0,"pct":87.5},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} +,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} +,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} +,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":83,"covered":71,"skipped":0,"pct":85.54},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":83,"covered":71,"skipped":0,"pct":85.54},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":159,"covered":143,"skipped":0,"pct":89.93},"functions":{"total":33,"covered":33,"skipped":0,"pct":100},"statements":{"total":159,"covered":143,"skipped":0,"pct":89.93},"branches":{"total":73,"covered":54,"skipped":0,"pct":73.97}} +,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":264,"covered":252,"skipped":0,"pct":95.45},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":267,"covered":255,"skipped":0,"pct":95.5},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} +,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":52,"covered":50,"skipped":0,"pct":96.15},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":50,"skipped":0,"pct":96.15},"branches":{"total":34,"covered":33,"skipped":0,"pct":97.05}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateGlob.js": {"lines":{"total":15,"covered":14,"skipped":0,"pct":93.33},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} -,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":76,"covered":75,"skipped":0,"pct":98.68},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":18,"covered":17,"skipped":0,"pct":94.44}} -,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":49,"covered":46,"skipped":0,"pct":93.88},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":49,"covered":46,"skipped":0,"pct":93.88},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} -,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":243,"covered":238,"skipped":0,"pct":97.94},"functions":{"total":33,"covered":32,"skipped":0,"pct":96.97},"statements":{"total":243,"covered":238,"skipped":0,"pct":97.94},"branches":{"total":125,"covered":113,"skipped":0,"pct":90.4}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":45,"covered":43,"skipped":0,"pct":95.56},"functions":{"total":12,"covered":11,"skipped":0,"pct":91.67},"statements":{"total":45,"covered":43,"skipped":0,"pct":95.56},"branches":{"total":12,"covered":10,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":82,"covered":72,"skipped":0,"pct":87.8},"functions":{"total":22,"covered":20,"skipped":0,"pct":90.91},"statements":{"total":82,"covered":72,"skipped":0,"pct":87.8},"branches":{"total":34,"covered":25,"skipped":0,"pct":73.53}} -,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":93,"covered":93,"skipped":0,"pct":100},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.67},"statements":{"total":94,"covered":94,"skipped":0,"pct":100},"branches":{"total":48,"covered":48,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":32,"covered":32,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":32,"covered":32,"skipped":0,"pct":100},"branches":{"total":27,"covered":26,"skipped":0,"pct":96.3}} -,"/Users/zachleat/Code/eleventy/src/TemplatePermalinkNoWrite.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":80,"covered":79,"skipped":0,"pct":98.75},"functions":{"total":22,"covered":22,"skipped":0,"pct":100},"statements":{"total":80,"covered":79,"skipped":0,"pct":98.75},"branches":{"total":46,"covered":45,"skipped":0,"pct":97.83}} -,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":112,"covered":88,"skipped":0,"pct":78.57},"functions":{"total":32,"covered":23,"skipped":0,"pct":71.88},"statements":{"total":112,"covered":88,"skipped":0,"pct":78.57},"branches":{"total":28,"covered":14,"skipped":0,"pct":50}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":215,"covered":128,"skipped":0,"pct":59.53},"functions":{"total":57,"covered":26,"skipped":0,"pct":45.61},"statements":{"total":216,"covered":129,"skipped":0,"pct":59.72},"branches":{"total":88,"covered":41,"skipped":0,"pct":46.59}} -,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":14,"covered":11,"skipped":0,"pct":78.57},"functions":{"total":4,"covered":1,"skipped":0,"pct":25},"statements":{"total":14,"covered":11,"skipped":0,"pct":78.57},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":34,"covered":15,"skipped":0,"pct":44.12},"functions":{"total":7,"covered":4,"skipped":0,"pct":57.14},"statements":{"total":34,"covered":15,"skipped":0,"pct":44.12},"branches":{"total":20,"covered":5,"skipped":0,"pct":25}} -,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.74},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.74},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} -,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":30,"covered":30,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":30,"covered":30,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":9,"covered":9,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":9,"covered":9,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":78,"covered":72,"skipped":0,"pct":92.3},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":79,"covered":73,"skipped":0,"pct":92.4},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} +,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":48,"covered":44,"skipped":0,"pct":91.66},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":48,"covered":44,"skipped":0,"pct":91.66},"branches":{"total":22,"covered":18,"skipped":0,"pct":81.81}} +,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":277,"covered":268,"skipped":0,"pct":96.75},"functions":{"total":37,"covered":35,"skipped":0,"pct":94.59},"statements":{"total":277,"covered":268,"skipped":0,"pct":96.75},"branches":{"total":150,"covered":129,"skipped":0,"pct":86}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":60,"covered":57,"skipped":0,"pct":95},"functions":{"total":14,"covered":13,"skipped":0,"pct":92.85},"statements":{"total":60,"covered":57,"skipped":0,"pct":95},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":90,"covered":80,"skipped":0,"pct":88.88},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":90,"covered":80,"skipped":0,"pct":88.88},"branches":{"total":36,"covered":27,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":96,"covered":96,"skipped":0,"pct":100},"functions":{"total":27,"covered":26,"skipped":0,"pct":96.29},"statements":{"total":97,"covered":97,"skipped":0,"pct":100},"branches":{"total":54,"covered":54,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":78,"covered":70,"skipped":0,"pct":89.74},"functions":{"total":10,"covered":9,"skipped":0,"pct":90},"statements":{"total":78,"covered":70,"skipped":0,"pct":89.74},"branches":{"total":69,"covered":62,"skipped":0,"pct":89.85}} +,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":86,"skipped":0,"pct":94.5},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":86,"skipped":0,"pct":94.5},"branches":{"total":59,"covered":53,"skipped":0,"pct":89.83}} +,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":146,"covered":118,"skipped":0,"pct":80.82},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":146,"covered":118,"skipped":0,"pct":80.82},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":245,"covered":155,"skipped":0,"pct":63.26},"functions":{"total":65,"covered":35,"skipped":0,"pct":53.84},"statements":{"total":245,"covered":155,"skipped":0,"pct":63.26},"branches":{"total":99,"covered":44,"skipped":0,"pct":44.44}} +,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":42,"covered":29,"skipped":0,"pct":69.04},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":42,"covered":29,"skipped":0,"pct":69.04},"branches":{"total":26,"covered":15,"skipped":0,"pct":57.69}} +,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} +,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":29,"covered":29,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":29,"covered":29,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":12,"covered":12,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":12,"covered":12,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":58,"covered":56,"skipped":0,"pct":96.55},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":59,"covered":57,"skipped":0,"pct":96.61},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/Engines/JavaScriptTemplateLiteral.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":77,"covered":74,"skipped":0,"pct":96.1},"functions":{"total":27,"covered":26,"skipped":0,"pct":96.3},"statements":{"total":77,"covered":74,"skipped":0,"pct":96.1},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} -,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.63},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.89},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.63},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} +,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":85,"covered":82,"skipped":0,"pct":96.47},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":86,"covered":83,"skipped":0,"pct":96.51},"branches":{"total":23,"covered":19,"skipped":0,"pct":82.6}} +,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":35,"covered":32,"skipped":0,"pct":91.42},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.88},"statements":{"total":35,"covered":32,"skipped":0,"pct":91.42},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":87,"covered":78,"skipped":0,"pct":89.66},"functions":{"total":24,"covered":23,"skipped":0,"pct":95.83},"statements":{"total":87,"covered":78,"skipped":0,"pct":89.66},"branches":{"total":33,"covered":31,"skipped":0,"pct":93.94}} -,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":5,"covered":5,"skipped":0,"pct":100},"statements":{"total":17,"covered":17,"skipped":0,"pct":100},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.89}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":58,"covered":58,"skipped":0,"pct":100},"functions":{"total":21,"covered":21,"skipped":0,"pct":100},"statements":{"total":60,"covered":60,"skipped":0,"pct":100},"branches":{"total":10,"covered":10,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":201,"covered":132,"skipped":0,"pct":65.67},"functions":{"total":47,"covered":34,"skipped":0,"pct":72.34},"statements":{"total":201,"covered":132,"skipped":0,"pct":65.67},"branches":{"total":88,"covered":58,"skipped":0,"pct":65.9}} +,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":68,"covered":66,"skipped":0,"pct":97.05},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":70,"covered":68,"skipped":0,"pct":97.14},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.85}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentUnrenderedTemplateError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Filters/GetCollectionItem.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.86}} -,"/Users/zachleat/Code/eleventy/src/Filters/Slug.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":18,"covered":18,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":18,"covered":18,"skipped":0,"pct":100},"branches":{"total":21,"covered":21,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":115,"covered":106,"skipped":0,"pct":92.17},"functions":{"total":18,"covered":17,"skipped":0,"pct":94.44},"statements":{"total":119,"covered":110,"skipped":0,"pct":92.44},"branches":{"total":90,"covered":75,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/Util/Capitalize.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Filters/GetCollectionItem.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.85}} +,"/Users/zachleat/Code/eleventy/src/Filters/ServerlessUrl.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/Filters/Slug.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} +,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":136,"covered":121,"skipped":0,"pct":88.97},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":140,"covered":125,"skipped":0,"pct":89.28},"branches":{"total":90,"covered":70,"skipped":0,"pct":77.77}} +,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":181,"covered":12,"skipped":0,"pct":6.62},"functions":{"total":31,"covered":0,"skipped":0,"pct":0},"statements":{"total":183,"covered":12,"skipped":0,"pct":6.55},"branches":{"total":89,"covered":0,"skipped":0,"pct":0}} +,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":31,"covered":26,"skipped":0,"pct":83.87},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":31,"covered":26,"skipped":0,"pct":83.87},"branches":{"total":21,"covered":18,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":9,"covered":9,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.86},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.86},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} +,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.85},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.85},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/Util/Pluralize.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":44,"covered":42,"skipped":0,"pct":95.45},"functions":{"total":21,"covered":19,"skipped":0,"pct":90.48},"statements":{"total":45,"covered":43,"skipped":0,"pct":95.56},"branches":{"total":18,"covered":18,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":48,"covered":45,"skipped":0,"pct":93.75},"functions":{"total":20,"covered":18,"skipped":0,"pct":90},"statements":{"total":48,"covered":45,"skipped":0,"pct":93.75},"branches":{"total":20,"covered":18,"skipped":0,"pct":90}} } diff --git a/docs/coverage.md b/docs/coverage.md index 2316128dd..f4d63dc26 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,70 +1,75 @@ -# Code Coverage for Eleventy v0.11.0 +# Code Coverage for Eleventy v1.0.0-beta.1 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 88.48% | 88.52% | 87.29% | 80.92% | +| `total` | 82.89% | 82.9% | 83.43% | 74.78% | +| `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | | `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | -| `src/BenchmarkGroup.js` | 76.09% | 76.09% | 66.67% | 61.9% | -| `src/BenchmarkManager.js` | 77.78% | 77.78% | 75% | 75% | -| `src/ComputedData.js` | 100% | 100% | 100% | 100% | -| `src/ComputedDataProxy.js` | 98.04% | 98.04% | 100% | 90.63% | -| `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.73% | -| `src/ComputedDataTemplateString.js` | 100% | 100% | 100% | 83.33% | -| `src/Config.js` | 100% | 100% | 100% | 100% | -| `src/Eleventy.js` | 55.2% | 54.95% | 50% | 42.86% | +| `src/BenchmarkGroup.js` | 78.72% | 78.72% | 66.66% | 63.15% | +| `src/BenchmarkManager.js` | 77.77% | 77.77% | 75% | 75% | +| `src/ComputedData.js` | 100% | 100% | 100% | 96.55% | +| `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | +| `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | +| `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | +| `src/Eleventy.js` | 63.54% | 63.34% | 67.34% | 63.71% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | -| `src/EleventyCommandCheck.js` | 100% | 100% | 100% | 87.5% | -| `src/EleventyConfig.js` | 100% | 100% | 100% | 100% | -| `src/EleventyErrorHandler.js` | 89.74% | 89.74% | 100% | 67.44% | +| `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | +| `src/EleventyErrorHandler.js` | 92.3% | 92.3% | 100% | 67.56% | | `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | -| `src/EleventyExtensionMap.js` | 100% | 100% | 100% | 100% | -| `src/EleventyFiles.js` | 93.94% | 93.94% | 90% | 83.61% | -| `src/EleventyServe.js` | 37.29% | 37.29% | 56.25% | 27.78% | -| `src/EleventyWatch.js` | 100% | 100% | 100% | 88.24% | -| `src/EleventyWatchTargets.js` | 91.84% | 91.84% | 85.71% | 93.33% | -| `src/Template.js` | 95.15% | 95.18% | 98.18% | 88.7% | -| `src/TemplateCache.js` | 100% | 100% | 100% | 100% | -| `src/TemplateCollection.js` | 90.32% | 91.18% | 93.33% | 70% | -| `src/TemplateConfig.js` | 88.71% | 88.71% | 60% | 92.31% | -| `src/TemplateContent.js` | 95.92% | 95.92% | 100% | 91.67% | -| `src/TemplateData.js` | 95.93% | 95.98% | 97.5% | 87.18% | -| `src/TemplateEngineManager.js` | 100% | 100% | 100% | 100% | +| `src/EleventyExtensionMap.js` | 97.56% | 97.56% | 96% | 89.74% | +| `src/EleventyFiles.js` | 88.82% | 88.42% | 86.66% | 73.13% | +| `src/EleventyServe.js` | 37.14% | 37.14% | 56.25% | 25% | +| `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | +| `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | +| `src/EventBus.js` | 100% | 100% | 100% | 100% | +| `src/Serverless.js` | 73.11% | 73.11% | 81.81% | 61.11% | +| `src/Template.js` | 94.47% | 94.5% | 98.57% | 86.06% | +| `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | +| `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | +| `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | +| `src/TemplateConfig.js` | 85.54% | 85.54% | 64.28% | 85.36% | +| `src/TemplateContent.js` | 89.93% | 89.93% | 100% | 73.97% | +| `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | +| `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | | `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | -| `src/TemplateLayout.js` | 98.68% | 98.7% | 100% | 94.44% | -| `src/TemplateLayoutPathResolver.js` | 93.88% | 93.88% | 100% | 85% | -| `src/TemplateMap.js` | 97.94% | 97.94% | 96.97% | 90.4% | -| `src/TemplatePassthrough.js` | 95.56% | 95.56% | 91.67% | 83.33% | -| `src/TemplatePassthroughManager.js` | 87.8% | 87.8% | 90.91% | 73.53% | -| `src/TemplatePath.js` | 100% | 100% | 96.67% | 100% | -| `src/TemplatePermalink.js` | 100% | 100% | 100% | 96.3% | -| `src/TemplatePermalinkNoWrite.js` | 100% | 100% | 100% | 100% | -| `src/TemplateRender.js` | 98.75% | 98.75% | 100% | 97.83% | -| `src/TemplateWriter.js` | 78.57% | 78.57% | 71.88% | 50% | -| `src/UserConfig.js` | 59.53% | 59.72% | 45.61% | 46.59% | -| `src/defaultConfig.js` | 78.57% | 78.57% | 25% | 100% | -| `src/Engines/Custom.js` | 44.12% | 44.12% | 57.14% | 25% | -| `src/Engines/Ejs.js` | 94.74% | 94.74% | 85.71% | 88.89% | +| `src/TemplateLayout.js` | 92.3% | 92.4% | 100% | 85% | +| `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | +| `src/TemplateMap.js` | 96.75% | 96.75% | 94.59% | 86% | +| `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | +| `src/TemplatePassthroughManager.js` | 88.88% | 88.88% | 100% | 75% | +| `src/TemplatePath.js` | 100% | 100% | 96.29% | 100% | +| `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | +| `src/TemplateRender.js` | 94.5% | 94.5% | 100% | 89.83% | +| `src/TemplateWriter.js` | 80.82% | 80.82% | 71.79% | 52.77% | +| `src/UserConfig.js` | 63.26% | 63.26% | 53.84% | 44.44% | +| `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | +| `src/Engines/Custom.js` | 69.04% | 69.04% | 66.66% | 57.69% | +| `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | | `src/Engines/JavaScript.js` | 96.55% | 96.61% | 100% | 83.33% | -| `src/Engines/JavaScriptTemplateLiteral.js` | 94.44% | 94.44% | 100% | 100% | -| `src/Engines/Liquid.js` | 96.1% | 96.1% | 96.3% | 85% | -| `src/Engines/Markdown.js` | 90.63% | 90.63% | 88.89% | 81.25% | +| `src/Engines/Liquid.js` | 96.47% | 96.51% | 96.66% | 82.6% | +| `src/Engines/Markdown.js` | 91.42% | 91.42% | 88.88% | 81.25% | | `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | -| `src/Engines/Nunjucks.js` | 89.66% | 89.66% | 95.83% | 93.94% | -| `src/Engines/Pug.js` | 100% | 100% | 100% | 88.89% | -| `src/Engines/TemplateEngine.js` | 100% | 100% | 100% | 100% | +| `src/Engines/Nunjucks.js` | 65.67% | 65.67% | 72.34% | 65.9% | +| `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | +| `src/Engines/TemplateEngine.js` | 97.05% | 97.14% | 95.65% | 92.85% | | `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | +| `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | | `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | -| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.86% | +| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.85% | +| `src/Filters/ServerlessUrl.js` | 100% | 100% | 100% | 75% | | `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | -| `src/Filters/Url.js` | 100% | 100% | 100% | 100% | -| `src/Plugins/Pagination.js` | 92.17% | 92.44% | 94.44% | 83.33% | -| `src/Util/Capitalize.js` | 100% | 100% | 100% | 100% | +| `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | +| `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | +| `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | +| `src/Plugins/ServerlessBundlerPlugin.js` | 6.62% | 6.55% | 0% | 0% | +| `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | +| `src/Util/ConsoleLogger.js` | 83.87% | 83.87% | 76.92% | 85.71% | | `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | | `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 100% | -| `src/Util/Merge.js` | 92.86% | 92.86% | 100% | 87.5% | +| `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | | `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | -| `src/Util/Sortable.js` | 95.45% | 95.56% | 90.48% | 100% | +| `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% | diff --git a/package.json b/package.json index e2fdd128a..9a93b00c3 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.44", + "version": "1.0.0-beta.1", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -79,7 +79,7 @@ "ava": "^3.15.0", "husky": "^7.0.2", "js-yaml": "^4.1.0", - "lint-staged": "^11.1.2", + "lint-staged": "^11.2.0", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.4.1", @@ -120,7 +120,7 @@ "pug": "^3.0.2", "recursive-copy": "^2.0.13", "semver": "^7.3.5", - "slugify": "^1.6.0", + "slugify": "^1.6.1", "split": "^1.0.1", "time-require": "^0.1.2" } From 24a0f2f5518b91e2a97203ae66a9f71bb6ab8cbd Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 6 Oct 2021 22:09:43 -0500 Subject: [PATCH 590/746] Fixes #2001. --- src/UserConfig.js | 6 ++++- test/SemverCheckTest.js | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 test/SemverCheckTest.js diff --git a/src/UserConfig.js b/src/UserConfig.js index e088151cc..56535ec8e 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -80,7 +80,11 @@ class UserConfig { } versionCheck(expected) { - if (!semver.satisfies(pkg.version, expected)) { + if ( + !semver.satisfies(pkg.version, expected, { + includePrerelease: true, + }) + ) { throw new UserConfigError( `This project requires the Eleventy version to match '${expected}' but found ${pkg.version}. Use \`npm update @11ty/eleventy -g\` to upgrade the eleventy global or \`npm update @11ty/eleventy --save\` to upgrade your local project version.` ); diff --git a/test/SemverCheckTest.js b/test/SemverCheckTest.js new file mode 100644 index 000000000..0ed16cb3d --- /dev/null +++ b/test/SemverCheckTest.js @@ -0,0 +1,49 @@ +const test = require("ava"); +const semver = require("semver"); + +test("Satisfies sanity checks with beta/canary", (t) => { + t.true( + semver.satisfies("1.0.0-beta.1", ">= 0.7.0", { + includePrerelease: true, + }), + "1.0 Beta is valid for 0.x" + ); + + t.true( + semver.satisfies("1.0.0-canary.1", ">= 0.7.0", { + includePrerelease: true, + }), + "1.0 Canary is valid for 0.x" + ); + + t.true( + semver.satisfies("1.0.0-beta.1", ">= 0.7.0", { + includePrerelease: true, + }), + "1.0 Beta is valid for 0.x" + ); + + t.true( + semver.satisfies("1.0.0", ">= 0.7.0", { + includePrerelease: true, + }), + "1.0 is valid for 0.x" + ); + + // keep canary around, it won’t have the `includePrerelease` option in `UserConfig->versionCheck` + t.true( + semver.satisfies("1.0.0", ">=0.7 || >=1.0.0-canary", { + includePrerelease: true, + }) + ); + t.true( + semver.satisfies("1.0.0-beta.1", ">=0.7 || >=1.0.0-canary", { + includePrerelease: true, + }) + ); + t.true( + semver.satisfies("1.0.0-canary.1", ">=0.7 || >=1.0.0-canary", { + includePrerelease: true, + }) + ); +}); From 7b568830320efafee03613c886e38c52da6b414d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 7 Oct 2021 09:58:48 -0500 Subject: [PATCH 591/746] v1.0.0-beta.2 --- docs/coverage.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/coverage.md b/docs/coverage.md index f4d63dc26..c6919fbda 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,4 +1,4 @@ -# Code Coverage for Eleventy v1.0.0-beta.1 +# Code Coverage for Eleventy v1.0.0-beta.2 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | diff --git a/package.json b/package.json index 9a93b00c3..f1bde15a3 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.1", + "version": "1.0.0-beta.2", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From d48cf041d46f6e0e8c4befde12e18e08fc06e9f1 Mon Sep 17 00:00:00 2001 From: JKC-Codes <34430187+JKC-Codes@users.noreply.github.com> Date: Thu, 7 Oct 2021 17:20:03 +0100 Subject: [PATCH 592/746] Fix being unable to namespace when using addPlugin --- src/TemplateConfig.js | 7 +++++- src/UserConfig.js | 6 ++++- test/TemplateConfigTest.js | 51 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index fbbbd1f3f..adbd99cbe 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -180,9 +180,14 @@ class TemplateConfig { // for Nested addPlugin calls, Issue #1925 this.userConfig._enablePluginExecution(); - this.userConfig.plugins.forEach(({ plugin, options }) => { + let storedActiveNamespace = this.userConfig.activeNamespace; + + this.userConfig.plugins.forEach(({ plugin, options, pluginNamespace }) => { + this.userConfig.activeNamespace = pluginNamespace; this.userConfig._executePlugin(plugin, options); }); + + this.userConfig.activeNamespace = storedActiveNamespace; } /** diff --git a/src/UserConfig.js b/src/UserConfig.js index 56535ec8e..b938702b2 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -316,7 +316,11 @@ class UserConfig { if (this._pluginExecution) { this._executePlugin(plugin, options); } else { - this.plugins.push({ plugin, options }); + this.plugins.push({ + plugin, + options, + pluginNamespace: this.activeNamespace, + }); } } diff --git a/test/TemplateConfigTest.js b/test/TemplateConfigTest.js index 648d41611..6338062dd 100644 --- a/test/TemplateConfigTest.js +++ b/test/TemplateConfigTest.js @@ -115,6 +115,7 @@ test("Add universal filter", (t) => { t.not(Object.keys(cfg.handlebarsHelpers).indexOf("myFilterName"), -1); t.not(Object.keys(cfg.nunjucksFilters).indexOf("myFilterName"), -1); }); + test("Add namespaced universal filter", (t) => { let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), @@ -163,6 +164,56 @@ test("Add namespaced universal filter using underscore", (t) => { ); }); +test("Add namespaced plugin", (t) => { + let templateCfg = new TemplateConfig(); + + templateCfg.userConfig.namespace("testNamespace", function () { + templateCfg.userConfig.addPlugin(function (eleventyConfig) { + eleventyConfig.addFilter("MyFilterName", function () {}); + }); + }); + + let cfg = templateCfg.getConfig(); + t.not( + Object.keys(cfg.liquidFilters).indexOf("testNamespaceMyFilterName"), + -1 + ); + t.not( + Object.keys(cfg.handlebarsHelpers).indexOf("testNamespaceMyFilterName"), + -1 + ); + t.not( + Object.keys(cfg.nunjucksFilters).indexOf("testNamespaceMyFilterName"), + -1 + ); +}); + +test("Add namespaced plugin using underscore", (t) => { + let templateCfg = new TemplateConfig( + require("../src/defaultConfig.js"), + "./test/stubs/config.js" + ); + templateCfg.userConfig.namespace("testNamespace_", function () { + templateCfg.userConfig.addPlugin(function (config) { + config.addFilter("myFilterName", function () {}); + }); + }); + + let cfg = templateCfg.getConfig(); + t.not( + Object.keys(cfg.liquidFilters).indexOf("testNamespace_myFilterName"), + -1 + ); + t.not( + Object.keys(cfg.handlebarsHelpers).indexOf("testNamespace_myFilterName"), + -1 + ); + t.not( + Object.keys(cfg.nunjucksFilters).indexOf("testNamespace_myFilterName"), + -1 + ); +}); + test("Empty namespace", (t) => { let templateCfg = new TemplateConfig( require("../src/defaultConfig.js"), From 9e26ea2d4f4bec9bd2b6b32429db77682c09ae98 Mon Sep 17 00:00:00 2001 From: Oscar Dominguez Date: Tue, 12 Oct 2021 21:23:09 +0200 Subject: [PATCH 593/746] ci(workflow): add 'npm' cache for actions/setup-node in .github/workflows --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ed6b98d7..6715151a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,11 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup node - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} + cache: npm - run: npm install - run: npm test env: - YARN_GPG: no \ No newline at end of file + YARN_GPG: no From 4b2cbc4d21b1935f30fab55910cfb8391b4ff8cc Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 16 Oct 2021 15:37:02 -0500 Subject: [PATCH 594/746] Fixes #2002 --- src/Template.js | 2 +- test/TemplateTest-ComputedData.js | 13 +++++++++++++ test/stubs-computed-array/test.liquid | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/stubs-computed-array/test.liquid diff --git a/src/Template.js b/src/Template.js index 0a77bff89..51ef8fbe0 100755 --- a/src/Template.js +++ b/src/Template.js @@ -543,7 +543,7 @@ class Template extends TemplateContent { // this check must come before isPlainObject if (typeof obj === "function") { computedData.add(parentKey, obj, declaredDependencies); - } else if (isPlainObject(obj)) { + } else if (Array.isArray(obj) || isPlainObject(obj)) { for (let key in obj) { let keys = []; if (parentKey) { diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index 06a74b70c..2101f577c 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -187,6 +187,7 @@ test("eleventyComputed using symbol parsing on template strings (nunjucks)", asy t.is(data.c, "ab"); }); +// TODO why is this skipped? https://github.com/11ty/eleventy/commit/79245d85bcfba3ce8e8b75d84315c6c5bd81bbd3 test.skip("eleventyComputed using symbol parsing on template strings (liquid)", async (t) => { let tmpl = getNewTemplate( "./test/stubs-computed-symbolparse/test.liquid", @@ -206,3 +207,15 @@ test.skip("eleventyComputed using symbol parsing on template strings (liquid)", t.is(data.b, "b"); t.is(data.c, "ab"); }); + +test("eleventyComputed render strings in arrays", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs-computed-array/test.liquid", + "./test/stubs-computed-array/", + "./test/stubs-computed-array/_site" + ); + + let data = await getRenderedData(tmpl); + t.deepEqual(data.array, ["static value", "test"]); + t.is(data.notArray, "test"); +}); diff --git a/test/stubs-computed-array/test.liquid b/test/stubs-computed-array/test.liquid new file mode 100644 index 000000000..1bbf55e21 --- /dev/null +++ b/test/stubs-computed-array/test.liquid @@ -0,0 +1,8 @@ +--- +dynamicValue: "test" +eleventyComputed: + notArray: "{{ dynamicValue }}" + array: + - "static value" + - "{{ dynamicValue }}" +--- \ No newline at end of file From 87c4f5ce314dc6cc28f8ab0768c048bdb6c61131 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 16 Oct 2021 15:42:10 -0500 Subject: [PATCH 595/746] =?UTF-8?q?Try=20to=20unskip=20a=20test,=20let?= =?UTF-8?q?=E2=80=99s=20see=20what=20CI=20does?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/TemplateTest-ComputedData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index 2101f577c..cccdaa088 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -188,7 +188,7 @@ test("eleventyComputed using symbol parsing on template strings (nunjucks)", asy }); // TODO why is this skipped? https://github.com/11ty/eleventy/commit/79245d85bcfba3ce8e8b75d84315c6c5bd81bbd3 -test.skip("eleventyComputed using symbol parsing on template strings (liquid)", async (t) => { +test("eleventyComputed using symbol parsing on template strings (liquid)", async (t) => { let tmpl = getNewTemplate( "./test/stubs-computed-symbolparse/test.liquid", "./test/stubs-computed-symbolparse/", From f63d5fecd85231738cdc1e99b98a054fd1c2126a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 16 Oct 2021 15:45:06 -0500 Subject: [PATCH 596/746] The unskipped test went fine, removing the comment. --- test/TemplateTest-ComputedData.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/TemplateTest-ComputedData.js b/test/TemplateTest-ComputedData.js index cccdaa088..bcf7a4b57 100644 --- a/test/TemplateTest-ComputedData.js +++ b/test/TemplateTest-ComputedData.js @@ -187,7 +187,6 @@ test("eleventyComputed using symbol parsing on template strings (nunjucks)", asy t.is(data.c, "ab"); }); -// TODO why is this skipped? https://github.com/11ty/eleventy/commit/79245d85bcfba3ce8e8b75d84315c6c5bd81bbd3 test("eleventyComputed using symbol parsing on template strings (liquid)", async (t) => { let tmpl = getNewTemplate( "./test/stubs-computed-symbolparse/test.liquid", From bfab9b14846fb88b207e0b5f81e6e806550aba90 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 16 Oct 2021 15:45:56 -0500 Subject: [PATCH 597/746] Update some deps --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f1bde15a3..6ae02e66a 100755 --- a/package.json +++ b/package.json @@ -75,16 +75,16 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.2", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", "ava": "^3.15.0", "husky": "^7.0.2", "js-yaml": "^4.1.0", - "lint-staged": "^11.2.0", + "lint-staged": "^11.2.3", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.4.1", "rimraf": "^3.0.2", - "sass": "^1.42.1", + "sass": "^1.43.2", "toml": "^3.0.0", "vue": "^2.6.14", "vue-server-renderer": "^2.6.14" From 861d5c9b909b7104b1619c48f7e59501da1bc6ce Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 18 Oct 2021 10:43:14 -0500 Subject: [PATCH 598/746] Fixes #2006 --- package.json | 1 - src/Template.js | 3 ++- src/TemplateWriter.js | 3 +-- src/Util/ConsoleLogger.js | 8 -------- test/EleventyTest.js | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 6ae02e66a..e6ad017d0 100755 --- a/package.json +++ b/package.json @@ -121,7 +121,6 @@ "recursive-copy": "^2.0.13", "semver": "^7.3.5", "slugify": "^1.6.1", - "split": "^1.0.1", "time-require": "^0.1.2" } } diff --git a/src/Template.js b/src/Template.js index 51ef8fbe0..07c88d9e4 100755 --- a/src/Template.js +++ b/src/Template.js @@ -1,4 +1,5 @@ const fs = require("fs"); +const os = require("os"); const path = require("path"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); @@ -825,7 +826,7 @@ class Template extends TemplateContent { if (to === "ndjson") { let jsonString = JSON.stringify(obj); - this.logger.toStream(jsonString + "\n"); + this.logger.toStream(jsonString + os.EOL); return; } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 73b3a4c9b..ffda9f977 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -8,7 +8,6 @@ const EleventyErrorHandler = require("./EleventyErrorHandler"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const ConsoleLogger = require("./Util/ConsoleLogger"); -const lodashFlatten = require("lodash/flatten"); const debug = require("debug")("Eleventy:TemplateWriter"); const debugDev = require("debug")("Dev:Eleventy:TemplateWriter"); @@ -334,7 +333,7 @@ class TemplateWriter { return Promise.all(promises) .then((results) => { - let flat = lodashFlatten(results); // switch to results.flat(1) with Node 12+ + let flat = results.flat(); return flat; }) .catch((e) => { diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 931821a82..40825a5f7 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -1,7 +1,6 @@ const chalk = require("chalk"); const debug = require("debug")("Eleventy:Logger"); const Readable = require("stream").Readable; -const split = require("split"); class ConsoleLogger { constructor() { @@ -55,13 +54,6 @@ class ConsoleLogger { closeStream(to = "") { this.outputStream.push(null); - - if (to === "ndjson") { - return this.outputStream.pipe( - // split(JSON.parse, null, { trailing: false }) - split(null, null, { trailing: false }) - ); - } return this.outputStream; } diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 39ddb6151..f724ae7a4 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -195,6 +195,43 @@ test("Eleventy to json", async (t) => { ); }); +test("Eleventy to ndjson", async (t) => { + let elev = new Eleventy("./test/stubs--to/"); + + elev.setIsVerbose(false); + + await elev.init(); + + let stream = await elev.toNDJSON(); + let count = 0; + await new Promise((resolve) => { + stream.on("data", function (buf) { + count++; + let jsonObj = JSON.parse(buf.toString()); + if (jsonObj.url === "/test/") { + t.deepEqual(jsonObj, { + url: "/test/", + inputPath: "./test/stubs--to/test.md", + outputPath: "_site/test/index.html", + content: "

hi

\n", + }); + } + if (jsonObj.url === "/test2/") { + t.deepEqual(jsonObj, { + url: "/test2/", + inputPath: "./test/stubs--to/test2.liquid", + outputPath: "_site/test2/index.html", + content: "hello", + }); + } + + if (count >= 2) { + resolve(); + } + }); + }); +}); + test.cb("Eleventy to ndjson (returns a stream)", (t) => { let elev = new Eleventy("./test/stubs--to/"); @@ -208,6 +245,7 @@ test.cb("Eleventy to ndjson (returns a stream)", (t) => { t.deepEqual(jsonObj, { url: "/test/", inputPath: "./test/stubs--to/test.md", + outputPath: "_site/test/index.html", content: "

hi

\n", }); } @@ -215,6 +253,7 @@ test.cb("Eleventy to ndjson (returns a stream)", (t) => { t.deepEqual(jsonObj, { url: "/test2/", inputPath: "./test/stubs--to/test2.liquid", + outputPath: "_site/test2/index.html", content: "hello", }); } From ac21306bed85243f9c035cf8f44f1b1b0021df81 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 19 Oct 2021 10:58:32 -0500 Subject: [PATCH 599/746] Fixes #1299 --- src/Eleventy.js | 2 +- src/TemplatePassthroughManager.js | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index e365b7cfe..c0bf95792 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -808,7 +808,7 @@ Arguments: // See: TemplateWriter:pathCache and EleventyWatchTargets let result = await this.write(); if (result.error) { - // build failed—quit watch early + // initial build failed—quit watch early return Promise.reject(result.error); } diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index bbb4e29fd..09039f1de 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -154,6 +154,7 @@ class TemplatePassthroughManager { } isPassthroughCopyFile(paths, changedFile) { + // passthrough copy by non-matching engine extension (via templateFormats) for (let path of paths) { if (path === changedFile && !this.extensionMap.hasEngine(path)) { return true; @@ -162,7 +163,7 @@ class TemplatePassthroughManager { for (let path of this.getConfigPaths()) { if (TemplatePath.startsWithSubPath(changedFile, path.inputPath)) { - return true; + return path; } } @@ -171,7 +172,20 @@ class TemplatePassthroughManager { getAllNormalizedPaths(paths) { if (this.incrementalFile) { - if (this.isPassthroughCopyFile(paths, this.incrementalFile)) { + let isPassthrough = this.isPassthroughCopyFile( + paths, + this.incrementalFile + ); + if (isPassthrough) { + if (isPassthrough.outputPath) { + return [ + this._normalizePaths( + this.incrementalFile, + isPassthrough.outputPath + ), + ]; + } + return [this._normalizePaths(this.incrementalFile)]; } return []; From 48c026922a1b59f33c9a3d512b10db03c711439a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 19 Oct 2021 11:00:50 -0500 Subject: [PATCH 600/746] Test fixes for #1299 --- test/TemplatePassthroughManagerTest.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/TemplatePassthroughManagerTest.js b/test/TemplatePassthroughManagerTest.js index 3c8c1422c..1803f3c63 100644 --- a/test/TemplatePassthroughManagerTest.js +++ b/test/TemplatePassthroughManagerTest.js @@ -23,8 +23,18 @@ test("isPassthroughCopyFile", async (t) => { }; let mgr = new TemplatePassthroughManager(eleventyConfig); - t.true(mgr.isPassthroughCopyFile([], "./img/test.png")); - t.true(mgr.isPassthroughCopyFile([], "./fonts/Roboto.woff")); + t.truthy(mgr.isPassthroughCopyFile([], "./img/test.png")); + t.deepEqual(mgr.isPassthroughCopyFile([], "./img/test.png"), { + inputPath: "./img", + outputPath: true, + }); + + t.truthy(mgr.isPassthroughCopyFile([], "./fonts/Roboto.woff")); + t.deepEqual(mgr.isPassthroughCopyFile([], "./fonts/Roboto.woff"), { + inputPath: "./fonts", + outputPath: true, + }); + t.false(mgr.isPassthroughCopyFile([], "./docs/test.njk")); t.false(mgr.isPassthroughCopyFile([], "./other-dir/test.png")); t.true( From 43db0ea5ce7fcd4725b920efdf774f4f3c2b04da Mon Sep 17 00:00:00 2001 From: Paul Shryock Date: Tue, 19 Oct 2021 11:56:48 -0400 Subject: [PATCH 601/746] [#1938]: Add --port to CLI --help --- src/Eleventy.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Eleventy.js b/src/Eleventy.js index c0bf95792..d056c4934 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -539,6 +539,9 @@ Arguments: --serve Run web server on --port (default 8080) and watch them too + --port + Run the --serve web server on this port (default 8080) + --watch Wait for files to change and automatically rewrite (no web server) From 3e34fbb09b35420e82275c4c936c2a3893df25d1 Mon Sep 17 00:00:00 2001 From: ThewBear <26767607+ThewBear@users.noreply.github.com> Date: Tue, 26 Oct 2021 13:33:45 +0000 Subject: [PATCH 602/746] Update browser-sync to 2.27.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e6ad017d0..f5099dcc3 100755 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "@11ty/dependency-tree": "^2.0.0", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", - "browser-sync": "^2.27.5", + "browser-sync": "^2.27.6", "chalk": "^4.1.2", "chokidar": "^3.5.2", "debug": "^4.3.2", From 0b8fd91ee9bdcac7227ee1e4527a9dcabf67cc6d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Oct 2021 10:16:56 -0500 Subject: [PATCH 603/746] Adds `redirects: "netlify-toml-builders"` and `redirects: "netlify-toml-functions"` to fix #2051 --- src/Plugins/ServerlessBundlerPlugin.js | 66 +++++++++++++++----------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 8e60b78e3..e492c5dbc 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -9,36 +9,48 @@ const TemplatePath = require("../TemplatePath"); const deleteRequireCache = require("../Util/DeleteRequireCache"); const debug = require("debug")("Eleventy:Serverless"); +function netlifyTomlRedirectHandler(name, outputMap, target) { + if (!target) { + throw new Error( + `Missing redirect target in Eleventy Serverless Bundler Plugin. Received ${target}` + ); + } + + let newRedirects = []; + for (let url in outputMap) { + newRedirects.push({ + from: url, + to: `${target}${name}`, + status: 200, + force: true, + _generated_by_eleventy_serverless: name, + }); + } + + let configFilename = "./netlify.toml"; + let cfg = {}; + // parse existing netlify.toml + if (fs.existsSync(configFilename)) { + cfg = TOML.parse(fs.readFileSync(configFilename)); + } + let cfgWithRedirects = addRedirectsWithoutDuplicates(name, cfg, newRedirects); + + fs.writeFileSync(configFilename, TOML.stringify(cfgWithRedirects)); + debug( + `Eleventy Serverless (${name}), writing (×${newRedirects.length}): ${configFilename}` + ); +} + // Provider specific const redirectHandlers = { "netlify-toml": function (name, outputMap) { - let newRedirects = []; - for (let url in outputMap) { - newRedirects.push({ - from: url, - to: `/.netlify/functions/${name}`, - status: 200, - force: true, - _generated_by_eleventy_serverless: name, - }); - } - - let configFilename = "./netlify.toml"; - let cfg = {}; - // parse existing netlify.toml - if (fs.existsSync(configFilename)) { - cfg = TOML.parse(fs.readFileSync(configFilename)); - } - let cfgWithRedirects = addRedirectsWithoutDuplicates( - name, - cfg, - newRedirects - ); - - fs.writeFileSync(configFilename, TOML.stringify(cfgWithRedirects)); - debug( - `Eleventy Serverless (${name}), writing (×${newRedirects.length}): ${configFilename}` - ); + return netlifyTomlRedirectHandler(name, outputMap, "/.netlify/functions/"); + }, + "netlify-toml-functions": function (name, outputMap) { + return netlifyTomlRedirectHandler(name, outputMap, "/.netlify/functions/"); + }, + "netlify-toml-builders": function (name, outputMap) { + return netlifyTomlRedirectHandler(name, outputMap, "/.netlify/builders/"); }, }; From 0d854b15732e3a842659f2e1b03d4a56d56dc762 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Oct 2021 10:41:27 -0500 Subject: [PATCH 604/746] Update a few deps --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f5099dcc3..a8e56c2d1 100755 --- a/package.json +++ b/package.json @@ -77,14 +77,14 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", "ava": "^3.15.0", - "husky": "^7.0.2", + "husky": "^7.0.4", "js-yaml": "^4.1.0", - "lint-staged": "^11.2.3", + "lint-staged": "^11.2.5", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.4.1", "rimraf": "^3.0.2", - "sass": "^1.43.2", + "sass": "^1.43.3", "toml": "^3.0.0", "vue": "^2.6.14", "vue-server-renderer": "^2.6.14" From 1647b3a3994963b0ebe56fb6d693fd0b313414b1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Oct 2021 10:42:04 -0500 Subject: [PATCH 605/746] v1.0.0-beta.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a8e56c2d1..cb6b94cf8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.3", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 19b4884e83e420a3b42f334aa922140f9cb18353 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 26 Oct 2021 10:42:55 -0500 Subject: [PATCH 606/746] Coverage --- docs-src/_data/coverage.json | 16 ++++++++-------- docs/coverage.md | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 456254685..16639a200 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":4567,"covered":3786,"skipped":0,"pct":82.89},"statements":{"total":4592,"covered":3807,"skipped":0,"pct":82.9},"functions":{"total":1008,"covered":841,"skipped":0,"pct":83.43},"branches":{"total":2090,"covered":1563,"skipped":0,"pct":74.78}} +{"total": {"lines":{"total":4575,"covered":3788,"skipped":0,"pct":82.79},"statements":{"total":4600,"covered":3809,"skipped":0,"pct":82.8},"functions":{"total":1011,"covered":842,"skipped":0,"pct":83.28},"branches":{"total":2094,"covered":1565,"skipped":0,"pct":74.73},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":55,"covered":34,"skipped":0,"pct":61.81},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":55,"covered":34,"skipped":0,"pct":61.81},"branches":{"total":24,"covered":14,"skipped":0,"pct":58.33}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":47,"covered":37,"skipped":0,"pct":78.72},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":47,"covered":37,"skipped":0,"pct":78.72},"branches":{"total":19,"covered":12,"skipped":0,"pct":63.15}} @@ -19,11 +19,11 @@ ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} ,"/Users/zachleat/Code/eleventy/src/EventBus.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":93,"covered":68,"skipped":0,"pct":73.11},"functions":{"total":11,"covered":9,"skipped":0,"pct":81.81},"statements":{"total":93,"covered":68,"skipped":0,"pct":73.11},"branches":{"total":36,"covered":22,"skipped":0,"pct":61.11}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":380,"covered":359,"skipped":0,"pct":94.47},"functions":{"total":70,"covered":69,"skipped":0,"pct":98.57},"statements":{"total":382,"covered":361,"skipped":0,"pct":94.5},"branches":{"total":165,"covered":142,"skipped":0,"pct":86.06}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":381,"covered":360,"skipped":0,"pct":94.48},"functions":{"total":70,"covered":69,"skipped":0,"pct":98.57},"statements":{"total":383,"covered":362,"skipped":0,"pct":94.51},"branches":{"total":167,"covered":144,"skipped":0,"pct":86.22}} ,"/Users/zachleat/Code/eleventy/src/TemplateBehavior.js": {"lines":{"total":24,"covered":21,"skipped":0,"pct":87.5},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":24,"covered":21,"skipped":0,"pct":87.5},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} -,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":83,"covered":71,"skipped":0,"pct":85.54},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":83,"covered":71,"skipped":0,"pct":85.54},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} +,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":86,"covered":74,"skipped":0,"pct":86.04},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":86,"covered":74,"skipped":0,"pct":86.04},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} ,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":159,"covered":143,"skipped":0,"pct":89.93},"functions":{"total":33,"covered":33,"skipped":0,"pct":100},"statements":{"total":159,"covered":143,"skipped":0,"pct":89.93},"branches":{"total":73,"covered":54,"skipped":0,"pct":73.97}} ,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":264,"covered":252,"skipped":0,"pct":95.45},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":267,"covered":255,"skipped":0,"pct":95.5},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} ,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":52,"covered":50,"skipped":0,"pct":96.15},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":50,"skipped":0,"pct":96.15},"branches":{"total":34,"covered":33,"skipped":0,"pct":97.05}} @@ -33,12 +33,12 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":48,"covered":44,"skipped":0,"pct":91.66},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":48,"covered":44,"skipped":0,"pct":91.66},"branches":{"total":22,"covered":18,"skipped":0,"pct":81.81}} ,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":277,"covered":268,"skipped":0,"pct":96.75},"functions":{"total":37,"covered":35,"skipped":0,"pct":94.59},"statements":{"total":277,"covered":268,"skipped":0,"pct":96.75},"branches":{"total":150,"covered":129,"skipped":0,"pct":86}} ,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":60,"covered":57,"skipped":0,"pct":95},"functions":{"total":14,"covered":13,"skipped":0,"pct":92.85},"statements":{"total":60,"covered":57,"skipped":0,"pct":95},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":90,"covered":80,"skipped":0,"pct":88.88},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":90,"covered":80,"skipped":0,"pct":88.88},"branches":{"total":36,"covered":27,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":93,"covered":80,"skipped":0,"pct":86.02},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":93,"covered":80,"skipped":0,"pct":86.02},"branches":{"total":38,"covered":27,"skipped":0,"pct":71.05}} ,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":96,"covered":96,"skipped":0,"pct":100},"functions":{"total":27,"covered":26,"skipped":0,"pct":96.29},"statements":{"total":97,"covered":97,"skipped":0,"pct":100},"branches":{"total":54,"covered":54,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":78,"covered":70,"skipped":0,"pct":89.74},"functions":{"total":10,"covered":9,"skipped":0,"pct":90},"statements":{"total":78,"covered":70,"skipped":0,"pct":89.74},"branches":{"total":69,"covered":62,"skipped":0,"pct":89.85}} ,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":86,"skipped":0,"pct":94.5},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":86,"skipped":0,"pct":94.5},"branches":{"total":59,"covered":53,"skipped":0,"pct":89.83}} -,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":146,"covered":118,"skipped":0,"pct":80.82},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":146,"covered":118,"skipped":0,"pct":80.82},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":245,"covered":155,"skipped":0,"pct":63.26},"functions":{"total":65,"covered":35,"skipped":0,"pct":53.84},"statements":{"total":245,"covered":155,"skipped":0,"pct":63.26},"branches":{"total":99,"covered":44,"skipped":0,"pct":44.44}} +,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":245,"covered":156,"skipped":0,"pct":63.67},"functions":{"total":65,"covered":36,"skipped":0,"pct":55.38},"statements":{"total":245,"covered":156,"skipped":0,"pct":63.67},"branches":{"total":99,"covered":45,"skipped":0,"pct":45.45}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":42,"covered":29,"skipped":0,"pct":69.04},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":42,"covered":29,"skipped":0,"pct":69.04},"branches":{"total":26,"covered":15,"skipped":0,"pct":57.69}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} @@ -61,9 +61,9 @@ ,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} ,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":136,"covered":121,"skipped":0,"pct":88.97},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":140,"covered":125,"skipped":0,"pct":89.28},"branches":{"total":90,"covered":70,"skipped":0,"pct":77.77}} -,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":181,"covered":12,"skipped":0,"pct":6.62},"functions":{"total":31,"covered":0,"skipped":0,"pct":0},"statements":{"total":183,"covered":12,"skipped":0,"pct":6.55},"branches":{"total":89,"covered":0,"skipped":0,"pct":0}} +,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":186,"covered":12,"skipped":0,"pct":6.45},"functions":{"total":34,"covered":0,"skipped":0,"pct":0},"statements":{"total":188,"covered":12,"skipped":0,"pct":6.38},"branches":{"total":91,"covered":0,"skipped":0,"pct":0}} ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":31,"covered":26,"skipped":0,"pct":83.87},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":31,"covered":26,"skipped":0,"pct":83.87},"branches":{"total":21,"covered":18,"skipped":0,"pct":85.71}} +,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":28,"covered":24,"skipped":0,"pct":85.71},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":28,"covered":24,"skipped":0,"pct":85.71},"branches":{"total":19,"covered":17,"skipped":0,"pct":89.47}} ,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":9,"covered":9,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.85},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.85},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} diff --git a/docs/coverage.md b/docs/coverage.md index c6919fbda..5ba62ff05 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,8 +1,8 @@ -# Code Coverage for Eleventy v1.0.0-beta.2 +# Code Coverage for Eleventy v1.0.0-beta.3 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 82.89% | 82.9% | 83.43% | 74.78% | +| `total` | 82.79% | 82.8% | 83.28% | 74.73% | | `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | | `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | | `src/BenchmarkGroup.js` | 78.72% | 78.72% | 66.66% | 63.15% | @@ -23,11 +23,11 @@ | `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | | `src/EventBus.js` | 100% | 100% | 100% | 100% | | `src/Serverless.js` | 73.11% | 73.11% | 81.81% | 61.11% | -| `src/Template.js` | 94.47% | 94.5% | 98.57% | 86.06% | +| `src/Template.js` | 94.48% | 94.51% | 98.57% | 86.22% | | `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | | `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | | `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | -| `src/TemplateConfig.js` | 85.54% | 85.54% | 64.28% | 85.36% | +| `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | | `src/TemplateContent.js` | 89.93% | 89.93% | 100% | 73.97% | | `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | | `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | @@ -37,12 +37,12 @@ | `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | | `src/TemplateMap.js` | 96.75% | 96.75% | 94.59% | 86% | | `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | -| `src/TemplatePassthroughManager.js` | 88.88% | 88.88% | 100% | 75% | +| `src/TemplatePassthroughManager.js` | 86.02% | 86.02% | 100% | 71.05% | | `src/TemplatePath.js` | 100% | 100% | 96.29% | 100% | | `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | | `src/TemplateRender.js` | 94.5% | 94.5% | 100% | 89.83% | -| `src/TemplateWriter.js` | 80.82% | 80.82% | 71.79% | 52.77% | -| `src/UserConfig.js` | 63.26% | 63.26% | 53.84% | 44.44% | +| `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | +| `src/UserConfig.js` | 63.67% | 63.67% | 55.38% | 45.45% | | `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | | `src/Engines/Custom.js` | 69.04% | 69.04% | 66.66% | 57.69% | | `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | @@ -65,9 +65,9 @@ | `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | | `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | | `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | -| `src/Plugins/ServerlessBundlerPlugin.js` | 6.62% | 6.55% | 0% | 0% | +| `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | | `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | -| `src/Util/ConsoleLogger.js` | 83.87% | 83.87% | 76.92% | 85.71% | +| `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | | `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | | `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 100% | | `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | From ccf9c89b94bbed1c3162fbff2c94891267e7f1cb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 3 Nov 2021 17:59:59 -0500 Subject: [PATCH 607/746] Add configuration callback to serverless class. Run your own config code in the serverless function. Fixes #2066 --- src/Serverless.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Serverless.js b/src/Serverless.js index e6043054d..fd5b96aad 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -47,6 +47,8 @@ class Serverless { query: {}, // Inject shared collections precompiledCollections: {}, + // Configuration callback + config: function (eleventyConfig) {}, }, options ); @@ -204,6 +206,10 @@ class Serverless { }; eleventyConfig.addGlobalData("eleventy.serverless", globalData); + + if (this.options.config && typeof this.options.config === "function") { + this.options.config(eleventyConfig); + } }, }); From a9c29f40f8685737ddef2ac79349152acd35c524 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 4 Nov 2021 18:10:07 -0500 Subject: [PATCH 608/746] Adds getOutput method to serverless to return all of the raw entries that match the path (for advanced serverless usage). Adds `dataFilterSelectors` to configuration file to allow some data to pass through to the JSON object returned by Eleventy.prototype.toJSON. These are lodash selectors. --- src/Serverless.js | 24 +++++++++++------------- src/Template.js | 21 +++++++++++++++++++++ src/UserConfig.js | 2 ++ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/Serverless.js b/src/Serverless.js index fd5b96aad..b7b246fed 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -155,7 +155,7 @@ class Serverless { return {}; } - async render() { + async getOutput() { if (this.dir.startsWith("/var/task/")) { process.chdir(this.dir); } @@ -220,9 +220,17 @@ class Serverless { // TODO (@zachleat) https://github.com/11ty/eleventy/issues/1957 this.deleteEnvironmentVariables(); + return json.filter((entry) => { + return entry.inputPath === inputPath; + }); + } + + async render() { + let json = await this.getOutput(); + if (!json.length) { let err = new Error( - `Couldn’t find any generated output from Eleventy (URL path parameters: ${JSON.stringify( + `Couldn’t find any generated output from Eleventy (Input path: ${inputPath}, URL path parameters: ${JSON.stringify( pathParams )}).` ); @@ -230,17 +238,7 @@ class Serverless { throw err; } - for (let entry of json) { - if (entry.inputPath === inputPath) { - return entry.content; - } - } - - // Log to Serverless Function output - console.log(json); - throw new Error( - `Couldn’t find any matching output from Eleventy for ${inputPath} (${json.length} pages rendered).` - ); + return json[0].content; } } diff --git a/src/Template.js b/src/Template.js index 07c88d9e4..3dc6f6074 100755 --- a/src/Template.js +++ b/src/Template.js @@ -3,6 +3,8 @@ const os = require("os"); const path = require("path"); const normalize = require("normalize-path"); const isPlainObject = require("lodash/isPlainObject"); +const lodashGet = require("lodash/get"); +const lodashSet = require("lodash/set"); const { DateTime } = require("luxon"); const TemplateData = require("./TemplateData"); @@ -805,6 +807,15 @@ class Template extends TemplateContent { return content; } + retrieveDataForJsonOutput(data, selectors) { + let filtered = {}; + for (let selector of selectors) { + let value = lodashGet(data, selector); + lodashSet(filtered, selector, value); + } + return filtered; + } + async generateMapEntry(mapEntry, to) { return Promise.all( mapEntry._pages.map(async (page) => { @@ -824,6 +835,16 @@ class Template extends TemplateContent { content: content, }; + if ( + this.config.dataFilterSelectors && + this.config.dataFilterSelectors.size > 0 + ) { + obj.data = this.retrieveDataForJsonOutput( + page.data, + this.config.dataFilterSelectors + ); + } + if (to === "ndjson") { let jsonString = JSON.stringify(obj); this.logger.toStream(jsonString + os.EOL); diff --git a/src/UserConfig.js b/src/UserConfig.js index b938702b2..0c0ed8d0f 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -77,6 +77,7 @@ class UserConfig { this._pluginExecution = false; this.useTemplateCache = true; + this.dataFilterSelectors = new Set(); } versionCheck(expected) { @@ -770,6 +771,7 @@ class UserConfig { plugins: this.plugins, useTemplateCache: this.useTemplateCache, precompiledCollections: this.precompiledCollections, + dataFilterSelectors: this.dataFilterSelectors, }; } } From 17cb0cb356b4533000a5f3ff309d9e4b18d087b1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Nov 2021 12:31:30 -0500 Subject: [PATCH 609/746] Change default serverless function to use new getOutput method. --- src/Plugins/DefaultServerlessFunctionContent.js | 7 ++++++- src/Serverless.js | 15 +++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Plugins/DefaultServerlessFunctionContent.js b/src/Plugins/DefaultServerlessFunctionContent.js index a44268eb0..d252a599b 100644 --- a/src/Plugins/DefaultServerlessFunctionContent.js +++ b/src/Plugins/DefaultServerlessFunctionContent.js @@ -12,12 +12,17 @@ async function handler(event) { }); try { + let [page] = await elev.getOutput(); + + // If you want some of the data cascade available in `page.data`, use `eleventyConfig.dataFilterSelectors`. + // Read more: https://www.11ty.dev/docs/config/#data-filter-selectors + return { statusCode: 200, headers: { "Content-Type": "text/html; charset=UTF-8", }, - body: await elev.render(), + body: page.content, }; } catch (error) { // Only console log for matching serverless paths diff --git a/src/Serverless.js b/src/Serverless.js index b7b246fed..2ed9278ee 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -220,15 +220,11 @@ class Serverless { // TODO (@zachleat) https://github.com/11ty/eleventy/issues/1957 this.deleteEnvironmentVariables(); - return json.filter((entry) => { + let filtered = json.filter((entry) => { return entry.inputPath === inputPath; }); - } - async render() { - let json = await this.getOutput(); - - if (!json.length) { + if (!filtered.length) { let err = new Error( `Couldn’t find any generated output from Eleventy (Input path: ${inputPath}, URL path parameters: ${JSON.stringify( pathParams @@ -238,6 +234,13 @@ class Serverless { throw err; } + return filtered; + } + + /* Deprecated, use `getOutput` directly instead. */ + async render() { + let json = await this.getOutput(); + return json[0].content; } } From 6c664cc98a3449e46f3091eee76672a79a650243 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 5 Nov 2021 12:34:31 -0500 Subject: [PATCH 610/746] v1.0.0-beta.4 --- docs-src/_data/coverage.json | 8 ++++---- docs/coverage.md | 10 +++++----- package.json | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 16639a200..bcb4bda6f 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":4575,"covered":3788,"skipped":0,"pct":82.79},"statements":{"total":4600,"covered":3809,"skipped":0,"pct":82.8},"functions":{"total":1011,"covered":842,"skipped":0,"pct":83.28},"branches":{"total":2094,"covered":1565,"skipped":0,"pct":74.73},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":4587,"covered":3796,"skipped":0,"pct":82.75},"statements":{"total":4612,"covered":3817,"skipped":0,"pct":82.76},"functions":{"total":1015,"covered":845,"skipped":0,"pct":83.25},"branches":{"total":2100,"covered":1570,"skipped":0,"pct":74.76},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":55,"covered":34,"skipped":0,"pct":61.81},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":55,"covered":34,"skipped":0,"pct":61.81},"branches":{"total":24,"covered":14,"skipped":0,"pct":58.33}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":47,"covered":37,"skipped":0,"pct":78.72},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":47,"covered":37,"skipped":0,"pct":78.72},"branches":{"total":19,"covered":12,"skipped":0,"pct":63.15}} @@ -18,8 +18,8 @@ ,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":39,"covered":39,"skipped":0,"pct":100},"functions":{"total":17,"covered":17,"skipped":0,"pct":100},"statements":{"total":40,"covered":40,"skipped":0,"pct":100},"branches":{"total":21,"covered":19,"skipped":0,"pct":90.47}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} ,"/Users/zachleat/Code/eleventy/src/EventBus.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":93,"covered":68,"skipped":0,"pct":73.11},"functions":{"total":11,"covered":9,"skipped":0,"pct":81.81},"statements":{"total":93,"covered":68,"skipped":0,"pct":73.11},"branches":{"total":36,"covered":22,"skipped":0,"pct":61.11}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":381,"covered":360,"skipped":0,"pct":94.48},"functions":{"total":70,"covered":69,"skipped":0,"pct":98.57},"statements":{"total":383,"covered":362,"skipped":0,"pct":94.51},"branches":{"total":167,"covered":144,"skipped":0,"pct":86.22}} +,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":95,"covered":72,"skipped":0,"pct":75.78},"functions":{"total":14,"covered":12,"skipped":0,"pct":85.71},"statements":{"total":95,"covered":72,"skipped":0,"pct":75.78},"branches":{"total":38,"covered":24,"skipped":0,"pct":63.15}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":390,"covered":363,"skipped":0,"pct":93.07},"functions":{"total":71,"covered":69,"skipped":0,"pct":97.18},"statements":{"total":392,"covered":365,"skipped":0,"pct":93.11},"branches":{"total":171,"covered":147,"skipped":0,"pct":85.96}} ,"/Users/zachleat/Code/eleventy/src/TemplateBehavior.js": {"lines":{"total":24,"covered":21,"skipped":0,"pct":87.5},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":24,"covered":21,"skipped":0,"pct":87.5},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} @@ -38,7 +38,7 @@ ,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":78,"covered":70,"skipped":0,"pct":89.74},"functions":{"total":10,"covered":9,"skipped":0,"pct":90},"statements":{"total":78,"covered":70,"skipped":0,"pct":89.74},"branches":{"total":69,"covered":62,"skipped":0,"pct":89.85}} ,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":86,"skipped":0,"pct":94.5},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":86,"skipped":0,"pct":94.5},"branches":{"total":59,"covered":53,"skipped":0,"pct":89.83}} ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":245,"covered":156,"skipped":0,"pct":63.67},"functions":{"total":65,"covered":36,"skipped":0,"pct":55.38},"statements":{"total":245,"covered":156,"skipped":0,"pct":63.67},"branches":{"total":99,"covered":45,"skipped":0,"pct":45.45}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":157,"skipped":0,"pct":63.82},"functions":{"total":65,"covered":36,"skipped":0,"pct":55.38},"statements":{"total":246,"covered":157,"skipped":0,"pct":63.82},"branches":{"total":99,"covered":45,"skipped":0,"pct":45.45}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":42,"covered":29,"skipped":0,"pct":69.04},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":42,"covered":29,"skipped":0,"pct":69.04},"branches":{"total":26,"covered":15,"skipped":0,"pct":57.69}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} diff --git a/docs/coverage.md b/docs/coverage.md index 5ba62ff05..edcfb03ec 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,8 +1,8 @@ -# Code Coverage for Eleventy v1.0.0-beta.3 +# Code Coverage for Eleventy v1.0.0-beta.4 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 82.79% | 82.8% | 83.28% | 74.73% | +| `total` | 82.75% | 82.76% | 83.25% | 74.76% | | `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | | `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | | `src/BenchmarkGroup.js` | 78.72% | 78.72% | 66.66% | 63.15% | @@ -22,8 +22,8 @@ | `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | | `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | | `src/EventBus.js` | 100% | 100% | 100% | 100% | -| `src/Serverless.js` | 73.11% | 73.11% | 81.81% | 61.11% | -| `src/Template.js` | 94.48% | 94.51% | 98.57% | 86.22% | +| `src/Serverless.js` | 75.78% | 75.78% | 85.71% | 63.15% | +| `src/Template.js` | 93.07% | 93.11% | 97.18% | 85.96% | | `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | | `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | | `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | @@ -42,7 +42,7 @@ | `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | | `src/TemplateRender.js` | 94.5% | 94.5% | 100% | 89.83% | | `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | -| `src/UserConfig.js` | 63.67% | 63.67% | 55.38% | 45.45% | +| `src/UserConfig.js` | 63.82% | 63.82% | 55.38% | 45.45% | | `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | | `src/Engines/Custom.js` | 69.04% | 69.04% | 66.66% | 57.69% | | `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | diff --git a/package.json b/package.json index cb6b94cf8..d3c7dc9ac 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.3", + "version": "1.0.0-beta.4", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -79,12 +79,12 @@ "ava": "^3.15.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", - "lint-staged": "^11.2.5", + "lint-staged": "^11.2.6", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.4.1", "rimraf": "^3.0.2", - "sass": "^1.43.3", + "sass": "^1.43.4", "toml": "^3.0.0", "vue": "^2.6.14", "vue-server-renderer": "^2.6.14" @@ -93,7 +93,7 @@ "@11ty/dependency-tree": "^2.0.0", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", - "browser-sync": "^2.27.6", + "browser-sync": "^2.27.7", "chalk": "^4.1.2", "chokidar": "^3.5.2", "debug": "^4.3.2", From f8a2137a73214defde850228d8c4e9e759b953f0 Mon Sep 17 00:00:00 2001 From: Harttle Date: Sat, 6 Nov 2021 03:23:10 +0800 Subject: [PATCH 611/746] feat: upgrade liquidjs to ^9.28.4, fixes #1995 --- package.json | 2 +- test/TemplateRenderLiquidTest.js | 78 +++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index d3c7dc9ac..43e4ad60a 100755 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", + "liquidjs": "^9.28.4", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.4.1", @@ -104,7 +105,6 @@ "hamljs": "^0.6.2", "handlebars": "^4.7.7", "is-glob": "^4.0.3", - "liquidjs": "9.25.1", "lodash": "^4.17.21", "luxon": "^2.0.2", "markdown-it": "^12.2.0", diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 67e59a43e..8d8dcbbdb 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -2,9 +2,10 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); +const { Drop } = require("liquidjs"); -function getNewTemplateRender(name, inputDir, userConfig = {}) { - let eleventyConfig = new TemplateConfig(); +function getNewTemplateRender(name, inputDir, userConfig = {}, templateConfig) { + let eleventyConfig = new TemplateConfig(templateConfig); for (let key in userConfig) { eleventyConfig.userConfig[key] = userConfig[key]; } @@ -102,6 +103,11 @@ test("Liquid Render Relative (current dir) Include", async (t) => { liquidOptions: { dynamicPartials: false, }, + }, + { + dir: { + includes: "relative-liquid", + }, } ); @@ -117,6 +123,11 @@ test("Liquid Render Relative (parent dir) Include", async (t) => { liquidOptions: { dynamicPartials: false, }, + }, + { + dir: { + includes: "relative-liquid", + }, } ); @@ -124,10 +135,16 @@ test("Liquid Render Relative (parent dir) Include", async (t) => { t.is(await fn(), "

TIME IS RELATIVE.

"); }); -test.skip("Liquid Render Relative (relative include should ignore _includes dir) Include", async (t) => { +test("Liquid Render Relative (relative include should ignore _includes dir) Include", async (t) => { let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", - "./test/stubs/" + "./test/stubs/", + {}, + { + dir: { + includes: ".", + }, + } ); let fn = await tr.getCompiledTemplate(`

{% include './included' %}

`); @@ -575,7 +592,13 @@ test("Liquid Render Include Subfolder Single quotes no extension dynamicPartials test("Liquid Render Include Subfolder Single quotes (relative include current dir) dynamicPartials true", async (t) => { let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", - "./test/stubs/" + "./test/stubs/", + {}, + { + dir: { + includes: "relative-liquid", + }, + } ); let fn = await tr.getCompiledTemplate( `

{% include './relative-liquid/dir/included' %}

` @@ -586,7 +609,13 @@ test("Liquid Render Include Subfolder Single quotes (relative include current di test("Liquid Render Include Subfolder Single quotes (relative include parent dir) dynamicPartials true", async (t) => { let tr = getNewTemplateRender( "./test/stubs/subfolder/does_not_exist_and_thats_ok.liquid", - "./test/stubs/" + "./test/stubs/", + {}, + { + dir: { + includes: "relative-liquid", + }, + } ); let fn = await tr.getCompiledTemplate( `

{% include '../relative-liquid/dir/included' %}

` @@ -704,17 +733,32 @@ test("Liquid Shortcode Multiple Args", async (t) => { ); }); -test.skip("Liquid Include Scope Leak", async (t) => { +test("Liquid Include Scope Leak", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" ); - // This might be by design? + // This is by design, `include` assigns value to its parent scope, + // use `{% render %}` for separated, clean scope + // see: https://github.com/harttle/liquidjs/issues/404#issuecomment-955660149 let fn = await getNewTemplateRender( "liquid", "./test/stubs/" - ).getCompiledTemplate("

{% include scopeleak %}{{ test }}

"); + ).getCompiledTemplate("

{% include 'scopeleak' %}{{ test }}

"); + t.is(await fn({ test: 1 }), "

22

"); +}); + +test("Liquid Render Scope Leak", async (t) => { + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); + + let fn = await getNewTemplateRender( + "liquid", + "./test/stubs/" + ).getCompiledTemplate("

{% render 'scopeleak' %}{{ test }}

"); t.is(await fn({ test: 1 }), "

21

"); }); @@ -957,15 +1001,17 @@ test("Issue 600: Liquid Shortcode argument with underscores", async (t) => { ); }); -test.skip("Issue 611: Run a function", async (t) => { - // This works in Nunjucks +test("Issue 611: Run a function", async (t) => { + // function calls in Nunjucks can be replaced by custom Drops let tr = getNewTemplateRender("liquid", "./test/stubs/"); - + class CustomDrop extends Drop { + valueOf() { + return "alkdsjfksljaZach"; + } + } t.is( - await tr._testRender("{{ test() }}", { - test: function () { - return "alkdsjfksljaZach"; - }, + await tr._testRender("{{ test }}", { + test: new CustomDrop(), }), "alkdsjfksljaZach" ); From 9fce1684cb68dc236c4e6683787d558b90544991 Mon Sep 17 00:00:00 2001 From: Harttle Date: Sat, 6 Nov 2021 03:42:27 +0800 Subject: [PATCH 612/746] fix: upgrade liquidjs to 9.28.5 to allow './' recognized as relative on Windows, #1995 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 43e4ad60a..f9cb0a8b2 100755 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", - "liquidjs": "^9.28.4", + "liquidjs": "^9.28.5", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.4.1", From 35e694356b7250848b1e8bddf7d5b0d1314ca3f2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Nov 2021 14:13:30 -0600 Subject: [PATCH 613/746] Move back to deps not devDeps https://github.com/11ty/eleventy/pull/2071/files#r744329650 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f9cb0a8b2..b99c4dd94 100755 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", - "liquidjs": "^9.28.5", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", "prettier": "^2.4.1", @@ -105,6 +104,7 @@ "hamljs": "^0.6.2", "handlebars": "^4.7.7", "is-glob": "^4.0.3", + "liquidjs": "^9.28.5", "lodash": "^4.17.21", "luxon": "^2.0.2", "markdown-it": "^12.2.0", From bafa008dfce082b528ea4b4a36cfea1adbb43fff Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Nov 2021 14:15:03 -0600 Subject: [PATCH 614/746] Comment no longer applicable. --- test/TemplateRenderLiquidTest.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 8d8dcbbdb..9eb78835e 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -148,9 +148,6 @@ test("Liquid Render Relative (relative include should ignore _includes dir) Incl ); let fn = await tr.getCompiledTemplate(`

{% include './included' %}

`); - - // This is currently wrong, it uses _includes/included.liquid instead of ./included.liquid - // Not changing the above to ../stubs/included works fine because that’s not an ambiguous reference. t.is(await fn(), "

This is not in the includes dir.

"); }); From bdeba62314eabd25390d87aa4a7ef7bcdbfc9c8e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 8 Nov 2021 16:05:35 -0600 Subject: [PATCH 615/746] Changes to fix #2071 without needing additional changes to template config. --- src/Engines/Custom.js | 4 ++-- src/Engines/Ejs.js | 4 ++-- src/Engines/Haml.js | 4 ++-- src/Engines/Handlebars.js | 4 ++-- src/Engines/Html.js | 6 ++--- src/Engines/JavaScript.js | 4 ++-- src/Engines/Liquid.js | 11 ++++------ src/Engines/Markdown.js | 6 ++--- src/Engines/Mustache.js | 4 ++-- src/Engines/Nunjucks.js | 4 ++-- src/Engines/Pug.js | 4 ++-- src/Engines/TemplateEngine.js | 12 ++++++++-- src/TemplateEngineManager.js | 12 ++++------ src/TemplateRender.js | 24 ++++++++++---------- test/TemplateRenderLiquidTest.js | 35 +++++------------------------- test/TemplateRenderMarkdownTest.js | 7 +++--- 16 files changed, 62 insertions(+), 83 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 318991898..40d475070 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -2,8 +2,8 @@ const TemplateEngine = require("./TemplateEngine"); const getJavaScriptData = require("../Util/GetJavaScriptData"); class CustomEngine extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.entry = this.getExtensionMapEntry(); this.needsInit = diff --git a/src/Engines/Ejs.js b/src/Engines/Ejs.js index a05714813..d8cc187c4 100644 --- a/src/Engines/Ejs.js +++ b/src/Engines/Ejs.js @@ -2,8 +2,8 @@ const ejsLib = require("ejs"); const TemplateEngine = require("./TemplateEngine"); class Ejs extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.ejsOptions = {}; diff --git a/src/Engines/Haml.js b/src/Engines/Haml.js index 0dd6ec02c..24795b081 100644 --- a/src/Engines/Haml.js +++ b/src/Engines/Haml.js @@ -2,8 +2,8 @@ const HamlLib = require("hamljs"); const TemplateEngine = require("./TemplateEngine"); class Haml extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.setLibrary(this.config.libraryOverrides.haml); } diff --git a/src/Engines/Handlebars.js b/src/Engines/Handlebars.js index 03b05d899..02dd4f52f 100644 --- a/src/Engines/Handlebars.js +++ b/src/Engines/Handlebars.js @@ -2,8 +2,8 @@ const HandlebarsLib = require("handlebars"); const TemplateEngine = require("./TemplateEngine"); class Handlebars extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.setLibrary(this.config.libraryOverrides.hbs); } diff --git a/src/Engines/Html.js b/src/Engines/Html.js index 8415a6c0a..02c702d4c 100644 --- a/src/Engines/Html.js +++ b/src/Engines/Html.js @@ -1,8 +1,8 @@ const TemplateEngine = require("./TemplateEngine"); class Html extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.cacheable = true; } @@ -10,7 +10,7 @@ class Html extends TemplateEngine { if (preTemplateEngine) { let engine = this.engineManager.getEngine( preTemplateEngine, - super.getIncludesDir(), + this.dirs, this.extensionMap ); let fnReady = engine.compile(str, inputPath); diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 6fce05b33..a76870b57 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -7,8 +7,8 @@ const getJavaScriptData = require("../Util/GetJavaScriptData"); class JavaScriptTemplateNotDefined extends EleventyBaseError {} class JavaScript extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.instances = {}; } diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 125523641..f3be8f170 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -5,8 +5,8 @@ const TemplatePath = require("../TemplatePath"); // const debug = require("debug")("Eleventy:Liquid"); class Liquid extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.liquidOptions = this.config.liquidOptions || {}; @@ -37,7 +37,7 @@ class Liquid extends TemplateEngine { getLiquidOptions() { let defaults = { - root: [super.getIncludesDir()], // overrides in compile with inputPath below + root: [this.dirs.includes, this.dirs.input], // supplemented in compile with inputPath below extname: ".liquid", strictFilters: true, // TODO? @@ -229,10 +229,7 @@ class Liquid extends TemplateEngine { if (!inputPath || inputPath === "njk" || inputPath === "md") { // do nothing } else { - options.root = [ - super.getIncludesDir(), - TemplatePath.getDirFromFilePath(inputPath), - ]; + options.root = [TemplatePath.getDirFromFilePath(inputPath)]; } return async function (data) { diff --git a/src/Engines/Markdown.js b/src/Engines/Markdown.js index 851fc61c3..fc5a795ac 100644 --- a/src/Engines/Markdown.js +++ b/src/Engines/Markdown.js @@ -3,8 +3,8 @@ const TemplateEngine = require("./TemplateEngine"); // const debug = require("debug")("Eleventy:Markdown"); class Markdown extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.markdownOptions = {}; @@ -53,7 +53,7 @@ class Markdown extends TemplateEngine { if (typeof preTemplateEngine === "string") { engine = this.engineManager.getEngine( preTemplateEngine, - super.getIncludesDir(), + this.dirs, this.extensionMap ); } else { diff --git a/src/Engines/Mustache.js b/src/Engines/Mustache.js index 77bdb1244..84386dda8 100644 --- a/src/Engines/Mustache.js +++ b/src/Engines/Mustache.js @@ -2,8 +2,8 @@ const MustacheLib = require("mustache"); const TemplateEngine = require("./TemplateEngine"); class Mustache extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.setLibrary(this.config.libraryOverrides.mustache); } diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index fa48daf8f..457ee60b6 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -123,8 +123,8 @@ const eventBus = require("../EventBus"); class EleventyShortcodeError extends EleventyBaseError {} class Nunjucks extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.nunjucksEnvironmentOptions = this.config.nunjucksEnvironmentOptions || {}; diff --git a/src/Engines/Pug.js b/src/Engines/Pug.js index 9e0619c32..100b0c6f2 100644 --- a/src/Engines/Pug.js +++ b/src/Engines/Pug.js @@ -2,8 +2,8 @@ const PugLib = require("pug"); const TemplateEngine = require("./TemplateEngine"); class Pug extends TemplateEngine { - constructor(name, includesDir, config) { - super(name, includesDir, config); + constructor(name, dirs, config) { + super(name, dirs, config); this.pugOptions = this.config.pugOptions || {}; diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 58a1eacc3..225d7abeb 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -10,9 +10,17 @@ const aggregateBench = require("../BenchmarkManager").get("Aggregate"); class TemplateEngineConfigError extends EleventyBaseError {} class TemplateEngine { - constructor(name, includesDir, config) { + constructor(name, dirs, config) { this.name = name; - this.includesDir = includesDir; + + if (!dirs) { + dirs = {}; + } + + this.dirs = dirs; + this.inputDir = dirs.input; + this.includesDir = dirs.includes; + this.partialsHaveBeenCached = false; this.partials = []; this.engineLib = null; diff --git a/src/TemplateEngineManager.js b/src/TemplateEngineManager.js index 20d0e1153..e74339fc0 100644 --- a/src/TemplateEngineManager.js +++ b/src/TemplateEngineManager.js @@ -76,10 +76,10 @@ class TemplateEngineManager { } } - getEngine(name, includesDir, extensionMap) { + getEngine(name, dirs, extensionMap) { if (!this.hasEngine(name)) { throw new Error( - `Template Engine ${name} does not exist in getEngine (includes dir: ${includesDir})` + `Template Engine ${name} does not exist in getEngine (dirs: ${dirs})` ); } @@ -89,7 +89,7 @@ class TemplateEngineManager { let cls = this.getEngineClassByExtension(name); - let instance = new cls(name, includesDir, this.config); + let instance = new cls(name, dirs, this.config); instance.extensionMap = extensionMap; instance.engineManager = this; @@ -102,11 +102,7 @@ class TemplateEngineManager { instance.constructor.name !== "CustomEngine" ) { const CustomEngine = this.getEngineClassByExtension(); - const overrideCustomEngine = new CustomEngine( - name, - includesDir, - this.config - ); + const overrideCustomEngine = new CustomEngine(name, dirs, this.config); // 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); diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 789b5fa97..2fa6139e5 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -24,10 +24,12 @@ class TemplateRender { this.config = config; this.engineNameOrPath = tmplPath; - this.inputDir = inputDir; - // optional - this.includesDir = this._normalizeIncludesDir(inputDir); + this.inputDir = inputDir ? inputDir : this.config.dir.input; + this.includesDir = TemplatePath.join( + this.inputDir, + this.config.dir.includes + ); this.parseMarkdownWith = this.config.markdownTemplateEngine; this.parseHtmlWith = this.config.htmlTemplateEngine; @@ -67,7 +69,7 @@ class TemplateRender { this._engine = this.extensionMap.engineManager.getEngine( this._engineName, - this.includesDir, + this.getDirs(), this.extensionMap ); this._engine.config = this.config; @@ -190,15 +192,15 @@ class TemplateRender { return this.engineName; } - getIncludesDir() { - return this.includesDir; + getDirs() { + return { + input: this.inputDir, + includes: this.includesDir, + }; } - _normalizeIncludesDir(dir) { - return TemplatePath.join( - dir ? dir : this.config.dir.input, - this.config.dir.includes - ); + getIncludesDir() { + return this.includesDir; } isEngine(engine) { diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 9eb78835e..0bbe0e431 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -4,8 +4,8 @@ const TemplateConfig = require("../src/TemplateConfig"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const { Drop } = require("liquidjs"); -function getNewTemplateRender(name, inputDir, userConfig = {}, templateConfig) { - let eleventyConfig = new TemplateConfig(templateConfig); +function getNewTemplateRender(name, inputDir, userConfig = {}) { + let eleventyConfig = new TemplateConfig(); for (let key in userConfig) { eleventyConfig.userConfig[key] = userConfig[key]; } @@ -103,11 +103,6 @@ test("Liquid Render Relative (current dir) Include", async (t) => { liquidOptions: { dynamicPartials: false, }, - }, - { - dir: { - includes: "relative-liquid", - }, } ); @@ -123,11 +118,6 @@ test("Liquid Render Relative (parent dir) Include", async (t) => { liquidOptions: { dynamicPartials: false, }, - }, - { - dir: { - includes: "relative-liquid", - }, } ); @@ -139,12 +129,7 @@ test("Liquid Render Relative (relative include should ignore _includes dir) Incl let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", "./test/stubs/", - {}, - { - dir: { - includes: ".", - }, - } + {} ); let fn = await tr.getCompiledTemplate(`

{% include './included' %}

`); @@ -590,12 +575,7 @@ test("Liquid Render Include Subfolder Single quotes (relative include current di let tr = getNewTemplateRender( "./test/stubs/does_not_exist_and_thats_ok.liquid", "./test/stubs/", - {}, - { - dir: { - includes: "relative-liquid", - }, - } + {} ); let fn = await tr.getCompiledTemplate( `

{% include './relative-liquid/dir/included' %}

` @@ -607,12 +587,7 @@ test("Liquid Render Include Subfolder Single quotes (relative include parent dir let tr = getNewTemplateRender( "./test/stubs/subfolder/does_not_exist_and_thats_ok.liquid", "./test/stubs/", - {}, - { - dir: { - includes: "relative-liquid", - }, - } + {} ); let fn = await tr.getCompiledTemplate( `

{% include '../relative-liquid/dir/included' %}

` diff --git a/test/TemplateRenderMarkdownTest.js b/test/TemplateRenderMarkdownTest.js index ffcbfc1b8..641f685c6 100644 --- a/test/TemplateRenderMarkdownTest.js +++ b/test/TemplateRenderMarkdownTest.js @@ -256,7 +256,8 @@ test("Markdown Render: use Markdown inside of a Liquid shortcode (Issue #536)", let tr = getNewTemplateRender("md"); let eleventyConfig = new TemplateConfig(); let cls = require("../src/Engines/Liquid"); - let liquidEngine = new cls("liquid", tr.getIncludesDir(), eleventyConfig); + + let liquidEngine = new cls("liquid", tr.getDirs(), eleventyConfig); liquidEngine.addShortcode("testShortcode", function () { return "## My Other Title"; }); @@ -280,7 +281,7 @@ test("Markdown Render: use Markdown inside of a Nunjucks shortcode (Issue #536)" let tr = getNewTemplateRender("md"); let eleventyConfig = new TemplateConfig(); let cls = require("../src/Engines/Nunjucks"); - let nunjucksEngine = new cls("njk", tr.getIncludesDir(), eleventyConfig); + let nunjucksEngine = new cls("njk", tr.getDirs(), eleventyConfig); nunjucksEngine.addShortcode("testShortcode", function () { return "## My Other Title"; }); @@ -329,7 +330,7 @@ test("Markdown Render: use Markdown inside of a Nunjucks paired shortcode (Issue let eleventyConfig = new TemplateConfig(); let cls = require("../src/Engines/Nunjucks"); - let nunjucksEngine = new cls("njk", tr.getIncludesDir(), eleventyConfig); + let nunjucksEngine = new cls("njk", tr.getDirs(), eleventyConfig); nunjucksEngine.addPairedShortcode("testShortcode", function (content) { return content; }); From 2c1000afeb800a9814d87c01c6ccf4ee7c8455bf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 12 Nov 2021 21:55:57 -0600 Subject: [PATCH 616/746] Expose config and ignores via eventbus --- src/Eleventy.js | 2 ++ src/EleventyFiles.js | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index c0bf95792..cd7e81869 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -316,6 +316,8 @@ class Eleventy { * @returns {} - tbd. */ async init() { + await this.config.events.emit("eleventy.config", this.eleventyConfig); + if (this.env) { await this.config.events.emit("eleventy.env", this.env); } diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index e022200cc..e3a1d6e99 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -184,6 +184,12 @@ class EleventyFiles { setupGlobs() { this.fileIgnores = this.getIgnores(); this.extraIgnores = this._getIncludesAndDataDirs(); + this.uniqueIgnores = this.getIgnoreGlobs(); + + // Conditional added for tests that don’t have a config + if (this.config && this.config.events) { + this.config.events.emit("eleventy.ignores", this.uniqueIgnores); + } if (this.passthroughAll) { this.normalizedTemplateGlobs = TemplateGlob.map([ @@ -360,10 +366,11 @@ class EleventyFiles { // returns a promise debug("Searching for: %o", globs); + this._glob = fastglob(globs, { caseSensitiveMatch: false, dot: true, - ignore: this.getIgnoreGlobs(), + ignore: this.uniqueIgnores, }); return this._glob; From e0047392b3326e6449f3d99563cdf91c44ee5827 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 12 Nov 2021 21:56:31 -0600 Subject: [PATCH 617/746] Performance boost: Cache get front matter data calls --- src/TemplateContent.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/TemplateContent.js b/src/TemplateContent.js index eae6b6427..6380d450c 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -189,13 +189,18 @@ class TemplateContent { } async getFrontMatterData() { + if (this._frontMatterDataCache) { + return this._frontMatterDataCache; + } + if (!this.frontMatter) { await this.read(); } - let extraData = await this.engine.getExtraDataFromFile(this.inputPath); let data = TemplateData.mergeDeep({}, this.frontMatter.data, extraData); - return TemplateData.cleanupData(data); + let cleanedData = TemplateData.cleanupData(data); + this._frontMatterDataCache = cleanedData; + return cleanedData; } async getEngineOverride() { From 87b7717b3bfab42535bf0b34c433d68c6eabb272 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 12 Nov 2021 21:57:49 -0600 Subject: [PATCH 618/746] Option to retrieve data from multiple sources in custom template types (pass in an array to `getData`) Also now expose mixins (usually the config javascriptFunctions) to get data calls --- src/Engines/Custom.js | 42 +++++++++++++++++++++++++++++++++-- src/Util/GetJavaScriptData.js | 6 +++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 40d475070..9969560f7 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -58,7 +58,7 @@ class CustomEngine extends TemplateEngine { if ("getData" in this.entry) { if (typeof this.entry.getData === "function") { - return await this.entry.getData(inputPath); + return this.entry.getData(inputPath); } else { if (!("getInstanceFromInputPath" in this.entry)) { return Promise.reject( @@ -67,8 +67,46 @@ class CustomEngine extends TemplateEngine { ) ); } + + let keys = new Set(); + if (this.entry.getData === true) { + keys.add("data"); + } else if (Array.isArray(this.entry.getData)) { + for (let key of this.entry.getData) { + keys.add(key); + } + } + if (keys.size === 0) { + return Promise.reject( + new Error( + `getData must be an array of keys or \`true\` in your addExtension configuration.` + ) + ); + } + let inst = await this.entry.getInstanceFromInputPath(inputPath); - return await getJavaScriptData(inst, inputPath); + let mixins; + if (this.config) { + mixins = this.config.javascriptFunctions; + } + + // override keys set at the plugin level in the individual template + if (inst.eleventyDataKey) { + keys = new Set(inst.eleventyDataKey); + } + + let promises = []; + for (let key of keys) { + promises.push(getJavaScriptData(inst, inputPath, key, mixins)); + } + + let results = await Promise.all(promises); + let data = {}; + for (let result of results) { + Object.assign(data, result); + } + + return data; } } } diff --git a/src/Util/GetJavaScriptData.js b/src/Util/GetJavaScriptData.js index f1d2289f9..05803903f 100644 --- a/src/Util/GetJavaScriptData.js +++ b/src/Util/GetJavaScriptData.js @@ -2,12 +2,14 @@ const EleventyBaseError = require("../EleventyBaseError"); class JavaScriptInvalidDataFormatError extends EleventyBaseError {} -module.exports = async function (inst, inputPath, key = "data") { +module.exports = async function (inst, inputPath, key = "data", mixins = {}) { if (inst && key in inst) { // get extra data from `data` method, // either as a function or getter or object literal let result = await (typeof inst[key] === "function" - ? inst[key]() + ? Object.keys(mixins).length > 0 + ? inst[key].call(mixins) + : inst[key]() : inst[key]); if (typeof result !== "object") { throw new JavaScriptInvalidDataFormatError( From 7c82736e52823b2eddf062490e3f58c7cf72fa7a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 12 Nov 2021 21:58:33 -0600 Subject: [PATCH 619/746] Ability to reuse the default lexer in parseAguments --- src/Engines/Liquid.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index f3be8f170..1e2259895 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -5,6 +5,14 @@ const TemplatePath = require("../TemplatePath"); // const debug = require("debug")("Eleventy:Liquid"); class Liquid extends TemplateEngine { + static argumentLexerOptions = { + number: /[0-9]+\.*[0-9]*/, + doubleQuoteString: /"(?:\\["\\]|[^\n"\\])*"/, + singleQuoteString: /'(?:\\['\\]|[^\n'\\])*'/, + keyword: /[a-zA-Z0-9.\-_]+/, + "ignore:whitespace": /[, \t]+/, // includes comma separator + }; + constructor(name, dirs, config) { super(name, dirs, config); @@ -12,13 +20,7 @@ class Liquid extends TemplateEngine { this.setLibrary(this.config.libraryOverrides.liquid); - this.argLexer = moo.compile({ - number: /[0-9]+\.*[0-9]*/, - doubleQuoteString: /"(?:\\["\\]|[^\n"\\])*"/, - singleQuoteString: /'(?:\\['\\]|[^\n'\\])*'/, - keyword: /[a-zA-Z0-9.\-_]+/, - "ignore:whitespace": /[, \t]+/, // includes comma separator - }); + this.argLexer = moo.compile(Liquid.argumentLexerOptions); this.cacheable = true; } @@ -93,6 +95,10 @@ class Liquid extends TemplateEngine { static async parseArguments(lexer, str, scope, engine) { let argArray = []; + if (!lexer) { + lexer = moo.compile(Liquid.argumentLexerOptions); + } + if (typeof str === "string") { // TODO key=value key2=value // TODO JSON? From e1af27fab20a73a8dacc5693809a4a86d87303a6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 12 Nov 2021 23:11:39 -0600 Subject: [PATCH 620/746] v1.0.0-beta.5 --- docs-src/_data/coverage.json | 16 ++++++++-------- docs/coverage.md | 18 +++++++++--------- package.json | 6 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index bcb4bda6f..0ba8d4974 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":4587,"covered":3796,"skipped":0,"pct":82.75},"statements":{"total":4612,"covered":3817,"skipped":0,"pct":82.76},"functions":{"total":1015,"covered":845,"skipped":0,"pct":83.25},"branches":{"total":2100,"covered":1570,"skipped":0,"pct":74.76},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":4621,"covered":3810,"skipped":0,"pct":82.44},"statements":{"total":4646,"covered":3831,"skipped":0,"pct":82.45},"functions":{"total":1015,"covered":845,"skipped":0,"pct":83.25},"branches":{"total":2123,"covered":1581,"skipped":0,"pct":74.47},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":55,"covered":34,"skipped":0,"pct":61.81},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":55,"covered":34,"skipped":0,"pct":61.81},"branches":{"total":24,"covered":14,"skipped":0,"pct":58.33}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":47,"covered":37,"skipped":0,"pct":78.72},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":47,"covered":37,"skipped":0,"pct":78.72},"branches":{"total":19,"covered":12,"skipped":0,"pct":63.15}} @@ -7,13 +7,13 @@ ,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.03},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.03},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.62}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":26,"covered":24,"skipped":0,"pct":92.3},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":26,"covered":24,"skipped":0,"pct":92.3},"branches":{"total":7,"covered":5,"skipped":0,"pct":71.42}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":310,"covered":197,"skipped":0,"pct":63.54},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":311,"covered":197,"skipped":0,"pct":63.34},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":311,"covered":198,"skipped":0,"pct":63.66},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":312,"covered":198,"skipped":0,"pct":63.46},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheckError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":36,"skipped":0,"pct":92.3},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":39,"covered":36,"skipped":0,"pct":92.3},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.56}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":82,"covered":80,"skipped":0,"pct":97.56},"functions":{"total":25,"covered":24,"skipped":0,"pct":96},"statements":{"total":82,"covered":80,"skipped":0,"pct":97.56},"branches":{"total":39,"covered":35,"skipped":0,"pct":89.74}} -,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":188,"covered":167,"skipped":0,"pct":88.82},"functions":{"total":45,"covered":39,"skipped":0,"pct":86.66},"statements":{"total":190,"covered":168,"skipped":0,"pct":88.42},"branches":{"total":67,"covered":49,"skipped":0,"pct":73.13}} +,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":191,"covered":170,"skipped":0,"pct":89},"functions":{"total":45,"covered":39,"skipped":0,"pct":86.66},"statements":{"total":193,"covered":171,"skipped":0,"pct":88.6},"branches":{"total":71,"covered":53,"skipped":0,"pct":74.64}} ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":70,"covered":26,"skipped":0,"pct":37.14},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":70,"covered":26,"skipped":0,"pct":37.14},"branches":{"total":36,"covered":9,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":39,"covered":39,"skipped":0,"pct":100},"functions":{"total":17,"covered":17,"skipped":0,"pct":100},"statements":{"total":40,"covered":40,"skipped":0,"pct":100},"branches":{"total":21,"covered":19,"skipped":0,"pct":90.47}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} @@ -24,7 +24,7 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":86,"covered":74,"skipped":0,"pct":86.04},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":86,"covered":74,"skipped":0,"pct":86.04},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":159,"covered":143,"skipped":0,"pct":89.93},"functions":{"total":33,"covered":33,"skipped":0,"pct":100},"statements":{"total":159,"covered":143,"skipped":0,"pct":89.93},"branches":{"total":73,"covered":54,"skipped":0,"pct":73.97}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":163,"covered":147,"skipped":0,"pct":90.18},"functions":{"total":33,"covered":33,"skipped":0,"pct":100},"statements":{"total":163,"covered":147,"skipped":0,"pct":90.18},"branches":{"total":75,"covered":56,"skipped":0,"pct":74.66}} ,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":264,"covered":252,"skipped":0,"pct":95.45},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":267,"covered":255,"skipped":0,"pct":95.5},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} ,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":52,"covered":50,"skipped":0,"pct":96.15},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":50,"skipped":0,"pct":96.15},"branches":{"total":34,"covered":33,"skipped":0,"pct":97.05}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} @@ -40,18 +40,18 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} ,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":157,"skipped":0,"pct":63.82},"functions":{"total":65,"covered":36,"skipped":0,"pct":55.38},"statements":{"total":246,"covered":157,"skipped":0,"pct":63.82},"branches":{"total":99,"covered":45,"skipped":0,"pct":45.45}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":42,"covered":29,"skipped":0,"pct":69.04},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":42,"covered":29,"skipped":0,"pct":69.04},"branches":{"total":26,"covered":15,"skipped":0,"pct":57.69}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":61,"covered":29,"skipped":0,"pct":47.54},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":61,"covered":29,"skipped":0,"pct":47.54},"branches":{"total":36,"covered":15,"skipped":0,"pct":41.66}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":29,"covered":29,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":29,"covered":29,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":12,"covered":12,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":12,"covered":12,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":58,"covered":56,"skipped":0,"pct":96.55},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":59,"covered":57,"skipped":0,"pct":96.61},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":85,"covered":82,"skipped":0,"pct":96.47},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":86,"covered":83,"skipped":0,"pct":96.51},"branches":{"total":23,"covered":19,"skipped":0,"pct":82.6}} +,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":88,"covered":84,"skipped":0,"pct":95.45},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":89,"covered":85,"skipped":0,"pct":95.5},"branches":{"total":25,"covered":20,"skipped":0,"pct":80}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":35,"covered":32,"skipped":0,"pct":91.42},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.88},"statements":{"total":35,"covered":32,"skipped":0,"pct":91.42},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":201,"covered":132,"skipped":0,"pct":65.67},"functions":{"total":47,"covered":34,"skipped":0,"pct":72.34},"statements":{"total":201,"covered":132,"skipped":0,"pct":65.67},"branches":{"total":88,"covered":58,"skipped":0,"pct":65.9}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":68,"covered":66,"skipped":0,"pct":97.05},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":70,"covered":68,"skipped":0,"pct":97.14},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.85}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":72,"covered":70,"skipped":0,"pct":97.22},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":74,"covered":72,"skipped":0,"pct":97.29},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentUnrenderedTemplateError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -65,7 +65,7 @@ ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":28,"covered":24,"skipped":0,"pct":85.71},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":28,"covered":24,"skipped":0,"pct":85.71},"branches":{"total":19,"covered":17,"skipped":0,"pct":89.47}} ,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":9,"covered":9,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":12,"covered":11,"skipped":0,"pct":91.66}} ,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.85},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.85},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/Util/Pluralize.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":48,"covered":45,"skipped":0,"pct":93.75},"functions":{"total":20,"covered":18,"skipped":0,"pct":90},"statements":{"total":48,"covered":45,"skipped":0,"pct":93.75},"branches":{"total":20,"covered":18,"skipped":0,"pct":90}} diff --git a/docs/coverage.md b/docs/coverage.md index edcfb03ec..8c218f467 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,8 +1,8 @@ -# Code Coverage for Eleventy v1.0.0-beta.4 +# Code Coverage for Eleventy v1.0.0-beta.5 | Filename | % Lines | % Statements | % Functions | % Branches | | ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 82.75% | 82.76% | 83.25% | 74.76% | +| `total` | 82.44% | 82.45% | 83.25% | 74.47% | | `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | | `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | | `src/BenchmarkGroup.js` | 78.72% | 78.72% | 66.66% | 63.15% | @@ -11,13 +11,13 @@ | `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | | `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | | `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | -| `src/Eleventy.js` | 63.54% | 63.34% | 67.34% | 63.71% | +| `src/Eleventy.js` | 63.66% | 63.46% | 67.34% | 63.71% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | | `src/EleventyErrorHandler.js` | 92.3% | 92.3% | 100% | 67.56% | | `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | | `src/EleventyExtensionMap.js` | 97.56% | 97.56% | 96% | 89.74% | -| `src/EleventyFiles.js` | 88.82% | 88.42% | 86.66% | 73.13% | +| `src/EleventyFiles.js` | 89% | 88.6% | 86.66% | 74.64% | | `src/EleventyServe.js` | 37.14% | 37.14% | 56.25% | 25% | | `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | | `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | @@ -28,7 +28,7 @@ | `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | | `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | | `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | -| `src/TemplateContent.js` | 89.93% | 89.93% | 100% | 73.97% | +| `src/TemplateContent.js` | 90.18% | 90.18% | 100% | 74.66% | | `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | | `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | @@ -44,18 +44,18 @@ | `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | | `src/UserConfig.js` | 63.82% | 63.82% | 55.38% | 45.45% | | `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | -| `src/Engines/Custom.js` | 69.04% | 69.04% | 66.66% | 57.69% | +| `src/Engines/Custom.js` | 47.54% | 47.54% | 66.66% | 41.66% | | `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | | `src/Engines/JavaScript.js` | 96.55% | 96.61% | 100% | 83.33% | -| `src/Engines/Liquid.js` | 96.47% | 96.51% | 96.66% | 82.6% | +| `src/Engines/Liquid.js` | 95.45% | 95.5% | 96.66% | 80% | | `src/Engines/Markdown.js` | 91.42% | 91.42% | 88.88% | 81.25% | | `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | | `src/Engines/Nunjucks.js` | 65.67% | 65.67% | 72.34% | 65.9% | | `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | -| `src/Engines/TemplateEngine.js` | 97.05% | 97.14% | 95.65% | 92.85% | +| `src/Engines/TemplateEngine.js` | 97.22% | 97.29% | 95.65% | 93.75% | | `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | | `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | | `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | @@ -69,7 +69,7 @@ | `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | | `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | | `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | -| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 100% | +| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 91.66% | | `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | | `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | | `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% | diff --git a/package.json b/package.json index b99c4dd94..d9c24ff5f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -106,7 +106,7 @@ "is-glob": "^4.0.3", "liquidjs": "^9.28.5", "lodash": "^4.17.21", - "luxon": "^2.0.2", + "luxon": "^2.1.1", "markdown-it": "^12.2.0", "minimist": "^1.2.5", "moo": "^0.5.1", @@ -120,7 +120,7 @@ "pug": "^3.0.2", "recursive-copy": "^2.0.13", "semver": "^7.3.5", - "slugify": "^1.6.1", + "slugify": "^1.6.2", "time-require": "^0.1.2" } } From e8f794182fb0a5b5cf431e32cda860bd9acc87fb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 13 Nov 2021 15:52:59 -0600 Subject: [PATCH 621/746] Update Vue tests to Vue3 APIs --- package.json | 4 ++-- test/TemplateRenderCustomTest.js | 17 ++++++++++------- test/TemplateRenderJavaScriptTest.js | 6 +++--- test/stubs/vue-layout.11ty.js | 21 ++++++++++----------- test/stubs/vue.11ty.js | 18 ++++++++++-------- 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index d9c24ff5f..044fe4d17 100755 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", + "@vue/server-renderer": "^3.2.21", "ava": "^3.15.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", @@ -86,8 +87,7 @@ "rimraf": "^3.0.2", "sass": "^1.43.4", "toml": "^3.0.0", - "vue": "^2.6.14", - "vue-server-renderer": "^2.6.14" + "vue": "^3.2.1" }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index eac4c5414..375f0d969 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -2,8 +2,9 @@ const test = require("ava"); const TemplateRender = require("../src/TemplateRender"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const TemplateConfig = require("../src/TemplateConfig"); -const Vue = require("vue"); -const renderer = require("vue-server-renderer").createRenderer(); + +const { createSSRApp } = require("vue"); +const { renderToString } = require("@vue/server-renderer"); function getNewTemplateRender(name, inputDir, eleventyConfig) { if (!eleventyConfig) { @@ -104,20 +105,22 @@ test("Custom Vue Render", async (t) => { tr.eleventyConfig.userConfig.extensionMap.add({ extension: "vue", key: "vue", - compile: function (str, inputPath) { + compile: function (str) { return async function (data) { - const app = new Vue({ + const app = createSSRApp({ template: str, - data: data, + data: function () { + return data; + }, }); - return renderer.renderToString(app); + return renderToString(app); }; }, }); let fn = await tr.getCompiledTemplate('

Paragraph

'); - t.is(await fn({ test: "Hello" }), '

Hello

'); + t.is(await fn({ test: "Hello" }), "

Hello

"); }); const sass = require("sass"); diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 64e82a50d..9ff8f51db 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -142,11 +142,11 @@ test("JS Render using Vue", async (t) => { ).getCompiledTemplate(); t.is( await fn({ name: "Zach" }), - '

Hello Zach, this is a Vue template.

' + "

Hello Zach, this is a Vue template.

" ); t.is( await fn({ name: "Bill" }), - '

Hello Bill, this is a Vue template.

' + "

Hello Bill, this is a Vue template.

" ); }); @@ -158,7 +158,7 @@ test("JS Render using Vue (with a layout)", async (t) => { await fn({ name: "Zach" }), ` Test -

Hello Zach, this is a Vue template.

` +

Hello Zach, this is a Vue template.

` ); }); diff --git a/test/stubs/vue-layout.11ty.js b/test/stubs/vue-layout.11ty.js index 3933a6c8b..0708b05b3 100644 --- a/test/stubs/vue-layout.11ty.js +++ b/test/stubs/vue-layout.11ty.js @@ -1,20 +1,19 @@ -const Vue = require("vue"); -const renderer = require("vue-server-renderer").createRenderer({ - template: ` -{{ title }} -` -}); +const { createSSRApp } = require("vue"); +const { renderToString } = require("@vue/server-renderer"); -module.exports = async function(data) { - var app = new Vue({ +module.exports = async function (data) { + var app = createSSRApp({ template: "

Hello {{ data.name }}, this is a Vue template.

", - data: function() { + data: function () { return { data }; - } + }, // components: { // 'test': ComponentA // } }); - return renderer.renderToString(app, { title: "Test" }); + let content = await renderToString(app, { title: "Test" }); + return ` +Test +${content}`; }; diff --git a/test/stubs/vue.11ty.js b/test/stubs/vue.11ty.js index 048351292..c610bf5b1 100644 --- a/test/stubs/vue.11ty.js +++ b/test/stubs/vue.11ty.js @@ -1,16 +1,18 @@ -const Vue = require("vue"); -const renderer = require("vue-server-renderer").createRenderer(); +const { createSSRApp } = require("vue"); +const { renderToString } = require("@vue/server-renderer"); -module.exports = async function(templateData) { - var app = new Vue({ +module.exports = async function (templateData) { + var app = createSSRApp({ template: "

Hello {{ data.name }}, this is a Vue template.

", - data: { - data: templateData - } + data: function () { + return { + data: templateData, + }; + }, // components: { // 'test': ComponentA // } }); - return renderer.renderToString(app); + return renderToString(app); }; From c89e54b48acad56d57809825572fa8db25d2ada7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 11:04:39 -0600 Subject: [PATCH 622/746] Add EleventyRenderPlugin. Fixes #148 --- .gitignore | 4 +- package.json | 4 +- src/Eleventy.js | 4 + src/EleventyErrorHandler.js | 1 - src/Plugins/RenderPlugin.js | 263 ++++++++++++++++++ test/TemplateRenderPluginTest.js | 145 ++++++++++ .../_includes/include.vue | 14 + test/stubs-render-plugin-vue/vue-sfc.liquid | 7 + .../stubs-render-plugin/_includes/include.njk | 6 + test/stubs-render-plugin/liquid-md.11ty.js | 23 ++ test/stubs-render-plugin/liquid-md.liquid | 10 + test/stubs-render-plugin/liquid.njk | 14 + test/stubs-render-plugin/md.liquid | 10 + .../njk-file-no-syntax.liquid | 1 + .../njk-file-not-exist.liquid | 1 + test/stubs-render-plugin/njk-file.liquid | 7 + test/stubs-render-plugin/nunjucks.11ty.js | 21 ++ test/stubs-render-plugin/nunjucks.liquid | 9 + test/stubs-render-plugin/vue.liquid | 11 + 19 files changed, 552 insertions(+), 3 deletions(-) create mode 100644 src/Plugins/RenderPlugin.js create mode 100644 test/TemplateRenderPluginTest.js create mode 100644 test/stubs-render-plugin-vue/_includes/include.vue create mode 100644 test/stubs-render-plugin-vue/vue-sfc.liquid create mode 100644 test/stubs-render-plugin/_includes/include.njk create mode 100644 test/stubs-render-plugin/liquid-md.11ty.js create mode 100644 test/stubs-render-plugin/liquid-md.liquid create mode 100644 test/stubs-render-plugin/liquid.njk create mode 100644 test/stubs-render-plugin/md.liquid create mode 100644 test/stubs-render-plugin/njk-file-no-syntax.liquid create mode 100644 test/stubs-render-plugin/njk-file-not-exist.liquid create mode 100644 test/stubs-render-plugin/njk-file.liquid create mode 100644 test/stubs-render-plugin/nunjucks.11ty.js create mode 100644 test/stubs-render-plugin/nunjucks.liquid create mode 100644 test/stubs-render-plugin/vue.liquid diff --git a/.gitignore b/.gitignore index 8206118a8..ff99ad0bc 100644 --- a/.gitignore +++ b/.gitignore @@ -12,9 +12,11 @@ api-docs/ .vscode .idea -# Ignore eleventy output when doing manuell tests +# Ignore eleventy output when doing manual tests _site/ package-lock.json +# Ignore test files +.cache test/stubs-layout-cache/_includes/*.js \ No newline at end of file diff --git a/package.json b/package.json index 044fe4d17..a3f8f746e 100755 --- a/package.json +++ b/package.json @@ -66,7 +66,8 @@ "./test/*.js" ], "ignoredByWatcher": [ - "./test/stubs*/**/*" + "./test/stubs*/**/*", + ".cache" ] }, "lint-staged": { @@ -76,6 +77,7 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", + "@11ty/eleventy-plugin-vue": "1.0.0-canary.5", "@vue/server-renderer": "^3.2.21", "ava": "^3.15.0", "husky": "^7.0.4", diff --git a/src/Eleventy.js b/src/Eleventy.js index cd7e81869..6d3c9187a 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -493,6 +493,9 @@ Verbose Output: ${this.verboseMode}`); bench.setVerboseOutput(isVerbose); this.verboseMode = isVerbose; + + // Set verbose mode in config file + this.eleventyConfig.verbose = this.verboseMode; } /** @@ -997,3 +1000,4 @@ Arguments: module.exports = Eleventy; module.exports.EleventyServerless = require("./Serverless"); module.exports.EleventyServerlessBundlerPlugin = require("./Plugins/ServerlessBundlerPlugin"); +module.exports.EleventyRenderPlugin = require("./Plugins/RenderPlugin"); diff --git a/src/EleventyErrorHandler.js b/src/EleventyErrorHandler.js index 9ad36e3df..e58e677bf 100644 --- a/src/EleventyErrorHandler.js +++ b/src/EleventyErrorHandler.js @@ -1,4 +1,3 @@ -const chalk = require("chalk"); const ConsoleLogger = require("./Util/ConsoleLogger"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const debug = require("debug")("Eleventy:EleventyErrorHandler"); diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js new file mode 100644 index 000000000..1557834e6 --- /dev/null +++ b/src/Plugins/RenderPlugin.js @@ -0,0 +1,263 @@ +const path = require("path"); +const fs = require("fs"); +const fsp = fs.promises; + +// TODO first-class Markdown container/component (will need to be synchronous for markdown-it) + +const TemplateRender = require("../TemplateRender"); +const TemplateConfig = require("../TemplateConfig"); +const Liquid = require("../Engines/Liquid"); + +function getFullIncludesDirectory(dir = {}) { + let inputDir = dir.input || "."; + let includesDir = dir.includes || "_includes"; + let fullIncludesDir = path.join(inputDir, includesDir); + + return fullIncludesDir; +} + +async function render(content, templateLang, dir = {}, templateConfig) { + if (!templateLang) { + throw new Error( + "Missing template syntax argument passed to the `template` shortcode." + ); + } + + if (!templateConfig) { + templateConfig = new TemplateConfig(); + } + + let includesDir = getFullIncludesDirectory(dir); + let tr = new TemplateRender(templateLang, includesDir, templateConfig); + tr.setEngineOverride(templateLang); + + return tr.getCompiledTemplate(content); +} + +async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { + if (!inputPath) { + throw new Error( + "Missing file path argument passed to the `templatefile` shortcode." + ); + } + + if (!fs.existsSync(inputPath)) { + throw new Error( + "Could not find render plugin file for renderFile, looking for: " + + inputPath + ); + } + + if (!templateConfig) { + templateConfig = new TemplateConfig(); + } + + let includesDir = getFullIncludesDirectory(dir); + let tr = new TemplateRender(inputPath, includesDir, templateConfig); + if (templateLang) { + tr.setEngineOverride(templateLang); + } + + if (tr.engine.entry && tr.engine.entry.read === false) { + return tr.getCompiledTemplate(null); + } + + // TODO we could make this work with full templates (with front matter?) + let content = await fsp.readFile(inputPath, "utf8"); + return tr.getCompiledTemplate(content); +} + +function EleventyPlugin(eleventyConfig, options = {}) { + function liquidTemplateTag(liquidEngine, tagName) { + return { + parse: function (tagToken, remainTokens) { + this.name = tagToken.name; + this.args = tagToken.args; + this.tokens = []; + + var stream = liquidEngine.parser + .parseStream(remainTokens) + .on("template", (tpl) => this.tokens.push(tpl)) + .on("tag:end" + tagName, () => stream.stop()) + .on("end", () => { + throw new Error(`tag ${tagToken.raw} not closed`); + }); + + stream.start(); + }, + render: async function (ctx) { + let normalizedContext = {}; + if (ctx) { + normalizedContext.page = ctx.get(["page"]); + } + + let argArray = await Liquid.parseArguments( + null, + this.args, + ctx, + this.liquid + ); + + let start = this.tokens[0].token.begin; + let end = this.tokens[this.tokens.length - 1].token.end; + let body = this.tokens[0].token.input.substring(start, end); + + return shortcodeFn.call(normalizedContext, body, ...argArray); + }, + }; + } + + // TODO I don’t think this works with whitespace control, e.g. {%- endrenderTemplate %} + function nunjucksTemplateTag(NunjucksLib, tagName) { + return new (function () { + this.tags = [tagName]; + + this.parse = function (parser, nodes) { + var tok = parser.nextToken(); + + var args = parser.parseSignature(true, true); + const begun = parser.advanceAfterBlockEnd(tok.value); + + // This code was ripped from the Nunjucks parser for `raw` + // https://github.com/mozilla/nunjucks/blob/fd500902d7c88672470c87170796de52fc0f791a/nunjucks/src/parser.js#L655 + const endTagName = "end" + tagName; + // Look for upcoming raw blocks (ignore all other kinds of blocks) + const rawBlockRegex = new RegExp( + "([\\s\\S]*?){%\\s*(" + tagName + "|" + endTagName + ")\\s*(?=%})%}" + ); + let rawLevel = 1; + let str = ""; + let matches = null; + + // Exit when there's nothing to match + // or when we've found the matching "endraw" block + while ( + (matches = parser.tokens._extractRegex(rawBlockRegex)) && + rawLevel > 0 + ) { + const all = matches[0]; + const pre = matches[1]; + const blockName = matches[2]; + + // Adjust rawlevel + if (blockName === tagName) { + rawLevel += 1; + } else if (blockName === endTagName) { + rawLevel -= 1; + } + + // Add to str + if (rawLevel === 0) { + // We want to exclude the last "endraw" + str += pre; + // Move tokenizer to beginning of endraw block + parser.tokens.backN(all.length - pre.length); + } else { + str += all; + } + } + + let body = new nodes.Output(begun.lineno, begun.colno, [ + new nodes.TemplateData(begun.lineno, begun.colno, str), + ]); + return new nodes.CallExtensionAsync(this, "run", args, [body]); + }; + + this.run = function (...args) { + let resolve = args.pop(); + let body = args.pop(); + let [context, ...argArray] = args; + + let normalizedContext = {}; + if (context.ctx && context.ctx.page) { + normalizedContext.page = context.ctx.page; + } + + shortcodeFn + .call(normalizedContext, body(), ...argArray) + .then(function (returnValue) { + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function (e) { + resolve( + new Error( + `Error with Nunjucks paired shortcode \`${tagName}\`${e.message}` + ), + null + ); + }); + }; + })(); + } + + let opts = Object.assign( + { + tagName: "renderTemplate", + tagNameFile: "renderFile", + }, + options + ); + + // This will only work on 1.0.0-beta.5+ but is only necessary if you want to reuse your config inside of template shortcodes. + // Just rendering raw templates (without filters, shortcodes, etc. from your config) will work fine on old versions. + let templateConfig; + eleventyConfig.on("eleventy.config", (cfg) => { + templateConfig = cfg; + }); + + async function shortcodeFn(content, templateLang, data = {}) { + let fn = await render.call( + this, + content, + templateLang, + eleventyConfig.dir, + templateConfig + ); + + // save `page` for reuse + data.page = this.page; + + let output = await fn(data); + // console.log( "--->", this.page.inputPath, "using", templateLang ); + // console.log( { data } ); + // console.log( { content } ); + // console.log( { output } ); + return output; + } + + // Render strings + eleventyConfig.addJavaScriptFunction(opts.tagName, shortcodeFn); + + eleventyConfig.addLiquidTag(opts.tagName, function (liquidEngine) { + return liquidTemplateTag(liquidEngine, opts.tagName); + }); + + eleventyConfig.addNunjucksTag(opts.tagName, function (nunjucksLib) { + return nunjucksTemplateTag(nunjucksLib, opts.tagName); + }); + + // Render File + eleventyConfig.addLiquidShortcode( + opts.tagNameFile, + async function (inputPath, templateLang, data = {}) { + let fn = await renderFile.call( + this, + inputPath, + templateLang, + eleventyConfig.dir, + templateConfig + ); + + // save `page` for re-use + data.page = this.page; + + let output = await fn(data); + // console.log( "--->", this.page.inputPath, "using", inputPath, "using", templateLang ); + // console.log( { data } ); + // console.log( { output } ); + return output; + } + ); +} + +module.exports = EleventyPlugin; diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js new file mode 100644 index 000000000..e8c21dd26 --- /dev/null +++ b/test/TemplateRenderPluginTest.js @@ -0,0 +1,145 @@ +const test = require("ava"); +const RenderPlugin = require("../src/Plugins/RenderPlugin"); +const VuePlugin = require("@11ty/eleventy-plugin-vue"); + +const Eleventy = require("../src/Eleventy"); +const normalizeNewLines = require("./Util/normalizeNewLines"); + +async function getTestOutput(input, configCallback = function () {}) { + let elev = new Eleventy(input, "./_site/", { + config: function (eleventyConfig) { + eleventyConfig.addPlugin(RenderPlugin); + configCallback(eleventyConfig); + }, + }); + elev.setIsVerbose(false); + + // Careful! + elev.disableLogger(); + + await elev.init(); + + let result = await elev.toJSON(); + + if (!result.length) { + throw new Error(`No Eleventy JSON output found for input: ${input}`); + } + return result; +} + +async function getTestOutputForFile(inputFile, configCallback) { + let result = await getTestOutput(inputFile, configCallback); + let html = normalizeNewLines(result[0].content.trim()); + return html; +} + +test("Use liquid in nunjucks", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/liquid.njk" + ); + t.is( + html, + `nunjucksHi +69 + + +* liquidHi test test liquidBye 138` + ); +}); + +test("Use liquid+markdown in 11ty.js", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/liquid-md.11ty.js" + ); + t.is( + html, + `

Markdown

+
    +
  • 2
  • +
` + ); +}); + +test("Use nunjucks in 11ty.js", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/nunjucks.11ty.js" + ); + t.is(html, `* iHtpircsavaj`); +}); + +test("Use nunjucks in liquid", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/nunjucks.liquid" + ); + t.is(html, `* iHdiuqil`); +}); + +test("Use markdown in liquid", async (t) => { + let html = await getTestOutputForFile("./test/stubs-render-plugin/md.liquid"); + t.is( + html, + `

Hello {{ hi }}

+
    +
  • Testing
  • +
` + ); +}); + +test("Use vue in liquid", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/vue.liquid", + function (eleventyConfig) { + eleventyConfig.addPlugin(VuePlugin); + } + ); + t.is(html, `
HELLO WE ARE VUEING

liquidHi

`); +}); + +test("Use vue SFC file in liquid", async (t) => { + // We point this to a directory instead of a single input file because the Eleventy Vue plugin needs + // to be able to find the Vue SFC files too (and won’t if we point to a single input vue file) + let result = await getTestOutput( + "./test/stubs-render-plugin-vue/", + function (eleventyConfig) { + eleventyConfig.addPlugin(VuePlugin); + } + ); + let html = normalizeNewLines(result[0].content.trim()); + t.is(html, `liquidHi`); +}); + +test("Use nunjucks file in liquid (uses renderTemplate inside of the nunjucks file)", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/njk-file.liquid" + ); + t.is( + html, + `TESTING + +TESTING IN LIQUID + +* 999` + ); +}); + +test("Use nunjucks file in liquid without specifying syntax (should infer from extension)", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/njk-file-no-syntax.liquid" + ); + t.is( + html, + `TESTING + +TESTING IN LIQUID + +* 999` + ); +}); + +test("Use nunjucks file in liquid but it doesn’t exist", async (t) => { + await t.throwsAsync(async () => { + await getTestOutputForFile( + "./test/stubs-render-plugin/njk-file-not-exist.liquid" + ); + }); +}); diff --git a/test/stubs-render-plugin-vue/_includes/include.vue b/test/stubs-render-plugin-vue/_includes/include.vue new file mode 100644 index 000000000..d8a3ca84c --- /dev/null +++ b/test/stubs-render-plugin-vue/_includes/include.vue @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/test/stubs-render-plugin-vue/vue-sfc.liquid b/test/stubs-render-plugin-vue/vue-sfc.liquid new file mode 100644 index 000000000..9399e7d3a --- /dev/null +++ b/test/stubs-render-plugin-vue/vue-sfc.liquid @@ -0,0 +1,7 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderFile "./test/stubs-render-plugin-vue/_includes/include.vue" "vue" argData %} \ No newline at end of file diff --git a/test/stubs-render-plugin/_includes/include.njk b/test/stubs-render-plugin/_includes/include.njk new file mode 100644 index 000000000..44230de5e --- /dev/null +++ b/test/stubs-render-plugin/_includes/include.njk @@ -0,0 +1,6 @@ +TESTING +{% renderTemplate "liquid" %} +TESTING IN LIQUID +{% assign liquidassign = 999 %} +* {{ liquidassign }} +{% endrenderTemplate %} \ No newline at end of file diff --git a/test/stubs-render-plugin/liquid-md.11ty.js b/test/stubs-render-plugin/liquid-md.11ty.js new file mode 100644 index 000000000..8425a4938 --- /dev/null +++ b/test/stubs-render-plugin/liquid-md.11ty.js @@ -0,0 +1,23 @@ +class Tmpl { + data() { + return { + argData: { + hi: "javascriptHi", + bye: "javascriptBye", + }, + }; + } + + async render(data) { + return this.renderTemplate( + ` +# Markdown +{% assign t1 = 2 %} +* {{ t1 }} +`, + "liquid,md", + data.argData + ); + } +} +module.exports = Tmpl; diff --git a/test/stubs-render-plugin/liquid-md.liquid b/test/stubs-render-plugin/liquid-md.liquid new file mode 100644 index 000000000..a63b4bcfd --- /dev/null +++ b/test/stubs-render-plugin/liquid-md.liquid @@ -0,0 +1,10 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderTemplate "liquid,md" argData %} +# Hello {{ hi }} +* Testing +{% endrenderTemplate %} diff --git a/test/stubs-render-plugin/liquid.njk b/test/stubs-render-plugin/liquid.njk new file mode 100644 index 000000000..d722aa86c --- /dev/null +++ b/test/stubs-render-plugin/liquid.njk @@ -0,0 +1,14 @@ +--- +# Nunjucks +hi: nunjucksHi +argData: + hi: liquidHi + bye: liquidBye +--- +{%- set nunjucksVar = 69 -%} +{{ hi }} +{{ nunjucksVar }} +{% renderTemplate "liquid", argData %} +{% assign liquidVar = 138 %} +* {{ hi }} test test {{ bye }} {{ liquidVar }} +{% endrenderTemplate %} diff --git a/test/stubs-render-plugin/md.liquid b/test/stubs-render-plugin/md.liquid new file mode 100644 index 000000000..24d6604be --- /dev/null +++ b/test/stubs-render-plugin/md.liquid @@ -0,0 +1,10 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderTemplate "md" argData %} +# Hello {{ hi }} +* Testing +{% endrenderTemplate %} \ No newline at end of file diff --git a/test/stubs-render-plugin/njk-file-no-syntax.liquid b/test/stubs-render-plugin/njk-file-no-syntax.liquid new file mode 100644 index 000000000..918124362 --- /dev/null +++ b/test/stubs-render-plugin/njk-file-no-syntax.liquid @@ -0,0 +1 @@ +{% renderFile "./test/stubs-render-plugin/_includes/include.njk" %} diff --git a/test/stubs-render-plugin/njk-file-not-exist.liquid b/test/stubs-render-plugin/njk-file-not-exist.liquid new file mode 100644 index 000000000..cadce5cd6 --- /dev/null +++ b/test/stubs-render-plugin/njk-file-not-exist.liquid @@ -0,0 +1 @@ +{% renderFile "./test/stubs-render-plugin/THIS_DOES_NOT_EXIST.njk" %} diff --git a/test/stubs-render-plugin/njk-file.liquid b/test/stubs-render-plugin/njk-file.liquid new file mode 100644 index 000000000..653532b43 --- /dev/null +++ b/test/stubs-render-plugin/njk-file.liquid @@ -0,0 +1,7 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderFile "./test/stubs-render-plugin/_includes/include.njk" "njk" argData %} diff --git a/test/stubs-render-plugin/nunjucks.11ty.js b/test/stubs-render-plugin/nunjucks.11ty.js new file mode 100644 index 000000000..628d09c96 --- /dev/null +++ b/test/stubs-render-plugin/nunjucks.11ty.js @@ -0,0 +1,21 @@ +class Tmpl { + data() { + return { + argData: { + hi: "javascriptHi", + bye: "javascriptBye", + }, + }; + } + + async render(data) { + return this.renderTemplate( + ` +* {{ hi | reverse }} +`, + "njk", + data.argData + ); + } +} +module.exports = Tmpl; diff --git a/test/stubs-render-plugin/nunjucks.liquid b/test/stubs-render-plugin/nunjucks.liquid new file mode 100644 index 000000000..ec8e06a39 --- /dev/null +++ b/test/stubs-render-plugin/nunjucks.liquid @@ -0,0 +1,9 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderTemplate "njk" argData %} +* {{ hi | reverse }} +{% endrenderTemplate %} diff --git a/test/stubs-render-plugin/vue.liquid b/test/stubs-render-plugin/vue.liquid new file mode 100644 index 000000000..75631012e --- /dev/null +++ b/test/stubs-render-plugin/vue.liquid @@ -0,0 +1,11 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderTemplate "vue" argData %} +
+ HELLO WE ARE VUEING

+
+{% endrenderTemplate %} \ No newline at end of file From 67e318a21fef0cc6543ee137ee9dc607f44cfba9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 11:17:32 -0600 Subject: [PATCH 623/746] =?UTF-8?q?Skip=20a=20test=20for=20now=E2=80=94nee?= =?UTF-8?q?d=20a=20big=20think=20about=20toJSON=20and=20exit=20codes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/TemplateRenderPluginTest.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index e8c21dd26..ab26af2c1 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -14,8 +14,8 @@ async function getTestOutput(input, configCallback = function () {}) { }); elev.setIsVerbose(false); - // Careful! - elev.disableLogger(); + // Careful with this! + // elev.disableLogger(); await elev.init(); @@ -136,7 +136,9 @@ TESTING IN LIQUID ); }); -test("Use nunjucks file in liquid but it doesn’t exist", async (t) => { +// Skip this for now, toJSON calls actually change the exitCode of the process when they error, which is probably not what we want? +// Not sure yet. +test.skip("Use nunjucks file in liquid but it doesn’t exist", async (t) => { await t.throwsAsync(async () => { await getTestOutputForFile( "./test/stubs-render-plugin/njk-file-not-exist.liquid" From 3ce5bc4301cdd5856ddae4c56d6646294c424858 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 13:28:56 -0600 Subject: [PATCH 624/746] Normalize the input path to the OS --- src/Plugins/RenderPlugin.js | 3 +++ src/TemplatePath.js | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 1557834e6..dc288f284 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -4,6 +4,7 @@ const fsp = fs.promises; // TODO first-class Markdown container/component (will need to be synchronous for markdown-it) +const TemplatePath = require("../TemplatePath"); const TemplateRender = require("../TemplateRender"); const TemplateConfig = require("../TemplateConfig"); const Liquid = require("../Engines/Liquid"); @@ -41,6 +42,8 @@ async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { ); } + inputPath = TemplatePath.normalizeOperatingSystemFilePath(inputPath); + if (!fs.existsSync(inputPath)) { throw new Error( "Could not find render plugin file for renderFile, looking for: " + diff --git a/src/TemplatePath.js b/src/TemplatePath.js index 0943dfbe6..5b14890d9 100644 --- a/src/TemplatePath.js +++ b/src/TemplatePath.js @@ -341,4 +341,16 @@ TemplatePath.removeExtension = function (path, extension = undefined) { return path; }; +/** + * Accepts a relative file path that is using a standard directory separator and + * normalizes it using the local operating system separator. + * e.g. `./my/dir/` stays `./my/dir/` on *nix and becomes `.\\my\\dir\\` on Windows + * + * @param {String} filePath + * @returns {String} a file path with the correct local directory separator. + */ +TemplatePath.normalizeOperatingSystemFilePath = function (filePath, sep = "/") { + return filePath.split(sep).join(path.sep); +}; + module.exports = TemplatePath; From a7bb6c74d0620ec94ba7ea58613db5b99f3b1087 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 14:42:58 -0600 Subject: [PATCH 625/746] Fix the Windows test for "Use vue SFC file in liquid" --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3f8f746e..7b9482999 100755 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", - "@11ty/eleventy-plugin-vue": "1.0.0-canary.5", + "@11ty/eleventy-plugin-vue": "1.0.0-canary.6", "@vue/server-renderer": "^3.2.21", "ava": "^3.15.0", "husky": "^7.0.4", From 5e4885e44b5514564f21f516a96ebede0179f1d4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 14:56:21 -0600 Subject: [PATCH 626/746] Fix the Windows test for "Use vue SFC file in liquid" #2 --- src/Plugins/RenderPlugin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index dc288f284..cb2b6f115 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -42,9 +42,9 @@ async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { ); } - inputPath = TemplatePath.normalizeOperatingSystemFilePath(inputPath); - - if (!fs.existsSync(inputPath)) { + if ( + !fs.existsSync(TemplatePath.normalizeOperatingSystemFilePath(inputPath)) + ) { throw new Error( "Could not find render plugin file for renderFile, looking for: " + inputPath From ec3b3492475949c7c2dfc9da1ce10081647a63d1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 15:04:21 -0600 Subject: [PATCH 627/746] Trying to fix a Windows issue. --- .github/workflows/ci.yml | 4 +++- package.json | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ed6b98d7..5ce21ec60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,8 @@ jobs: with: node-version: ${{ matrix.node }} - run: npm install - - run: npm test + - run: npm run testci + env: + DEBUG: EleventyVue* env: YARN_GPG: no \ No newline at end of file diff --git a/package.json b/package.json index 7b9482999..f1bb6539b 100755 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "default": "npm run test", "format": "prettier src/ --write", "test": "npx ava --verbose", + "testci": "npx ava --verbose --serial", "lint-staged": "lint-staged", "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js", "prepare": "husky install" From f8c4f743c3677560baa297a965f8fa55b0cef8d6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 15:08:02 -0600 Subject: [PATCH 628/746] Restore previous CI setup --- .github/workflows/ci.yml | 2 +- package.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ce21ec60..2b18cfd70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: with: node-version: ${{ matrix.node }} - run: npm install - - run: npm run testci + - run: npm test env: DEBUG: EleventyVue* env: diff --git a/package.json b/package.json index f1bb6539b..7b9482999 100755 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "default": "npm run test", "format": "prettier src/ --write", "test": "npx ava --verbose", - "testci": "npx ava --verbose --serial", "lint-staged": "lint-staged", "coverage": "npx nyc ava && npx nyc report --reporter=json-summary && cp coverage/coverage-summary.json docs-src/_data/coverage.json && node cmd.js --config=docs-src/.eleventy.docs.js", "prepare": "husky install" From 1af48eec0701c4b8420f7fa3ab0ecfb9a5f08dd6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 15:10:24 -0600 Subject: [PATCH 629/746] Restore previous CI setup --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b18cfd70..8ed6b98d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,5 @@ jobs: node-version: ${{ matrix.node }} - run: npm install - run: npm test - env: - DEBUG: EleventyVue* env: YARN_GPG: no \ No newline at end of file From 63c740f73f20a2cdbec46b696718d0766d7913bd Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 15:11:51 -0600 Subject: [PATCH 630/746] Skip a test (temporarily) --- test/TemplateRenderPluginTest.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index ab26af2c1..0cffd481c 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -95,7 +95,8 @@ test("Use vue in liquid", async (t) => { t.is(html, `
HELLO WE ARE VUEING

liquidHi

`); }); -test("Use vue SFC file in liquid", async (t) => { +// Skip until we can get this working on Windows +test.skip("Use vue SFC file in liquid", async (t) => { // We point this to a directory instead of a single input file because the Eleventy Vue plugin needs // to be able to find the Vue SFC files too (and won’t if we point to a single input vue file) let result = await getTestOutput( From 659ccb52bc0496e354dcf93c18fb68399deb8be3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 20:37:30 -0600 Subject: [PATCH 631/746] Opting-back into the test --- package.json | 2 +- test/TemplateRenderPluginTest.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7b9482999..b0303d5f7 100755 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", - "@11ty/eleventy-plugin-vue": "1.0.0-canary.6", + "@11ty/eleventy-plugin-vue": "1.0.0-canary.7", "@vue/server-renderer": "^3.2.21", "ava": "^3.15.0", "husky": "^7.0.4", diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index 0cffd481c..0a729e7b0 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -12,6 +12,7 @@ async function getTestOutput(input, configCallback = function () {}) { configCallback(eleventyConfig); }, }); + elev.setIsVerbose(false); // Careful with this! @@ -96,7 +97,7 @@ test("Use vue in liquid", async (t) => { }); // Skip until we can get this working on Windows -test.skip("Use vue SFC file in liquid", async (t) => { +test("Use vue SFC file in liquid", async (t) => { // We point this to a directory instead of a single input file because the Eleventy Vue plugin needs // to be able to find the Vue SFC files too (and won’t if we point to a single input vue file) let result = await getTestOutput( From 6efae4e242d975aca4836cea030b2c1edd89834d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 14 Nov 2021 20:47:06 -0600 Subject: [PATCH 632/746] The elusive Windows fix. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b0303d5f7..4930e7daa 100755 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ }, "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", - "@11ty/eleventy-plugin-vue": "1.0.0-canary.7", + "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", "@vue/server-renderer": "^3.2.21", "ava": "^3.15.0", "husky": "^7.0.4", From 823243966ca7ca4ec8434904e6b17bc75800aaef Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 09:10:06 -0600 Subject: [PATCH 633/746] Add more tests. Add renderFile shortcodes for nunjucks and JS. --- src/Plugins/RenderPlugin.js | 56 +++++++++++-------- test/TemplateRenderPluginTest.js | 11 +++- test/stubs-render-plugin-vue/vue-sfc.liquid | 2 +- test/stubs-render-plugin/11tyjs-file.njk | 7 +++ .../_includes/include.11ty.js | 1 + .../_includes/include.liquid | 6 ++ .../njk-file-no-syntax.liquid | 1 - test/stubs-render-plugin/njk-file.liquid | 2 +- test/stubs-render-plugin/njk-file.njk | 7 +++ 9 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 test/stubs-render-plugin/11tyjs-file.njk create mode 100644 test/stubs-render-plugin/_includes/include.11ty.js create mode 100644 test/stubs-render-plugin/_includes/include.liquid delete mode 100644 test/stubs-render-plugin/njk-file-no-syntax.liquid create mode 100644 test/stubs-render-plugin/njk-file.njk diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index cb2b6f115..133e91ed5 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -61,7 +61,7 @@ async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { tr.setEngineOverride(templateLang); } - if (tr.engine.entry && tr.engine.entry.read === false) { + if (!tr.engine.needsToReadFileContents()) { return tr.getCompiledTemplate(null); } @@ -105,7 +105,11 @@ function EleventyPlugin(eleventyConfig, options = {}) { let end = this.tokens[this.tokens.length - 1].token.end; let body = this.tokens[0].token.input.substring(start, end); - return shortcodeFn.call(normalizedContext, body, ...argArray); + return renderStringShortcodeFn.call( + normalizedContext, + body, + ...argArray + ); }, }; } @@ -176,7 +180,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { normalizedContext.page = context.ctx.page; } - shortcodeFn + renderStringShortcodeFn .call(normalizedContext, body(), ...argArray) .then(function (returnValue) { resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); @@ -208,7 +212,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { templateConfig = cfg; }); - async function shortcodeFn(content, templateLang, data = {}) { + async function renderStringShortcodeFn(content, templateLang, data = {}) { let fn = await render.call( this, content, @@ -228,8 +232,27 @@ function EleventyPlugin(eleventyConfig, options = {}) { return output; } + async function renderFileShortcodeFn(inputPath, data = {}, templateLang) { + let fn = await renderFile.call( + this, + inputPath, + templateLang, + eleventyConfig.dir, + templateConfig + ); + + // save `page` for re-use + data.page = this.page; + + let output = await fn(data); + // console.log( "--->", this.page.inputPath, "using", inputPath, "using", templateLang ); + // console.log( { data } ); + // console.log( { output } ); + return output; + } + // Render strings - eleventyConfig.addJavaScriptFunction(opts.tagName, shortcodeFn); + eleventyConfig.addJavaScriptFunction(opts.tagName, renderStringShortcodeFn); eleventyConfig.addLiquidTag(opts.tagName, function (liquidEngine) { return liquidTemplateTag(liquidEngine, opts.tagName); @@ -240,26 +263,11 @@ function EleventyPlugin(eleventyConfig, options = {}) { }); // Render File - eleventyConfig.addLiquidShortcode( + eleventyConfig.addJavaScriptFunction(opts.tagNameFile, renderFileShortcodeFn); + eleventyConfig.addLiquidShortcode(opts.tagNameFile, renderFileShortcodeFn); + eleventyConfig.addNunjucksAsyncShortcode( opts.tagNameFile, - async function (inputPath, templateLang, data = {}) { - let fn = await renderFile.call( - this, - inputPath, - templateLang, - eleventyConfig.dir, - templateConfig - ); - - // save `page` for re-use - data.page = this.page; - - let output = await fn(data); - // console.log( "--->", this.page.inputPath, "using", inputPath, "using", templateLang ); - // console.log( { data } ); - // console.log( { output } ); - return output; - } + renderFileShortcodeFn ); } diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index 0a729e7b0..8929999c6 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -124,9 +124,9 @@ TESTING IN LIQUID ); }); -test("Use nunjucks file in liquid without specifying syntax (should infer from extension)", async (t) => { +test("Use nunjucks file in njk (uses renderTemplate inside of the nunjucks file)", async (t) => { let html = await getTestOutputForFile( - "./test/stubs-render-plugin/njk-file-no-syntax.liquid" + "./test/stubs-render-plugin/njk-file.njk" ); t.is( html, @@ -138,6 +138,13 @@ TESTING IN LIQUID ); }); +test("Use 11ty.js file in njk", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/11tyjs-file.njk" + ); + t.is(html, `TESTING`); +}); + // Skip this for now, toJSON calls actually change the exitCode of the process when they error, which is probably not what we want? // Not sure yet. test.skip("Use nunjucks file in liquid but it doesn’t exist", async (t) => { diff --git a/test/stubs-render-plugin-vue/vue-sfc.liquid b/test/stubs-render-plugin-vue/vue-sfc.liquid index 9399e7d3a..c365d187b 100644 --- a/test/stubs-render-plugin-vue/vue-sfc.liquid +++ b/test/stubs-render-plugin-vue/vue-sfc.liquid @@ -4,4 +4,4 @@ argData: hi: liquidHi bye: liquidBye --- -{% renderFile "./test/stubs-render-plugin-vue/_includes/include.vue" "vue" argData %} \ No newline at end of file +{% renderFile "./test/stubs-render-plugin-vue/_includes/include.vue" argData %} \ No newline at end of file diff --git a/test/stubs-render-plugin/11tyjs-file.njk b/test/stubs-render-plugin/11tyjs-file.njk new file mode 100644 index 000000000..27623d69d --- /dev/null +++ b/test/stubs-render-plugin/11tyjs-file.njk @@ -0,0 +1,7 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderFile "./test/stubs-render-plugin/_includes/include.11ty.js", argData %} \ No newline at end of file diff --git a/test/stubs-render-plugin/_includes/include.11ty.js b/test/stubs-render-plugin/_includes/include.11ty.js new file mode 100644 index 000000000..2637dc46d --- /dev/null +++ b/test/stubs-render-plugin/_includes/include.11ty.js @@ -0,0 +1 @@ +module.exports = "TESTING"; diff --git a/test/stubs-render-plugin/_includes/include.liquid b/test/stubs-render-plugin/_includes/include.liquid new file mode 100644 index 000000000..44230de5e --- /dev/null +++ b/test/stubs-render-plugin/_includes/include.liquid @@ -0,0 +1,6 @@ +TESTING +{% renderTemplate "liquid" %} +TESTING IN LIQUID +{% assign liquidassign = 999 %} +* {{ liquidassign }} +{% endrenderTemplate %} \ No newline at end of file diff --git a/test/stubs-render-plugin/njk-file-no-syntax.liquid b/test/stubs-render-plugin/njk-file-no-syntax.liquid deleted file mode 100644 index 918124362..000000000 --- a/test/stubs-render-plugin/njk-file-no-syntax.liquid +++ /dev/null @@ -1 +0,0 @@ -{% renderFile "./test/stubs-render-plugin/_includes/include.njk" %} diff --git a/test/stubs-render-plugin/njk-file.liquid b/test/stubs-render-plugin/njk-file.liquid index 653532b43..64e955622 100644 --- a/test/stubs-render-plugin/njk-file.liquid +++ b/test/stubs-render-plugin/njk-file.liquid @@ -4,4 +4,4 @@ argData: hi: liquidHi bye: liquidBye --- -{% renderFile "./test/stubs-render-plugin/_includes/include.njk" "njk" argData %} +{% renderFile "./test/stubs-render-plugin/_includes/include.njk" argData %} diff --git a/test/stubs-render-plugin/njk-file.njk b/test/stubs-render-plugin/njk-file.njk new file mode 100644 index 000000000..f2bef7fe3 --- /dev/null +++ b/test/stubs-render-plugin/njk-file.njk @@ -0,0 +1,7 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderFile "./test/stubs-render-plugin/_includes/include.liquid", argData %} From b8414d19460fc025b7178dc2d4f5dfd04942077e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 09:16:37 -0600 Subject: [PATCH 634/746] Better error messaging when trying to use 11ty.js string render --- src/Plugins/RenderPlugin.js | 6 ++++++ test/TemplateRenderPluginTest.js | 12 ++++++++++-- test/stubs-render-plugin/11tyjs.liquid | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 test/stubs-render-plugin/11tyjs.liquid diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 133e91ed5..8886edac6 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -32,6 +32,12 @@ async function render(content, templateLang, dir = {}, templateConfig) { let tr = new TemplateRender(templateLang, includesDir, templateConfig); tr.setEngineOverride(templateLang); + if (tr.engine.name === "11ty.js") { + throw new Error( + "11ty.js is not yet supported as a template engine for `renderTemplate`. Use `renderFile` instead!" + ); + } + return tr.getCompiledTemplate(content); } diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index 8929999c6..b5240ab4b 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -68,6 +68,14 @@ test("Use nunjucks in 11ty.js", async (t) => { t.is(html, `* iHtpircsavaj`); }); +// This is not yet supported and currently throws an error. +test.skip("Use 11ty.js in liquid", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/11tyjs.liquid" + ); + t.is(html, `TESTING`); +}); + test("Use nunjucks in liquid", async (t) => { let html = await getTestOutputForFile( "./test/stubs-render-plugin/nunjucks.liquid" @@ -145,8 +153,8 @@ test("Use 11ty.js file in njk", async (t) => { t.is(html, `TESTING`); }); -// Skip this for now, toJSON calls actually change the exitCode of the process when they error, which is probably not what we want? -// Not sure yet. +// Skip this for now, toJSON calls actually change the exitCode of the process when they error, +// which is not ideal. test.skip("Use nunjucks file in liquid but it doesn’t exist", async (t) => { await t.throwsAsync(async () => { await getTestOutputForFile( diff --git a/test/stubs-render-plugin/11tyjs.liquid b/test/stubs-render-plugin/11tyjs.liquid new file mode 100644 index 000000000..1bec6194f --- /dev/null +++ b/test/stubs-render-plugin/11tyjs.liquid @@ -0,0 +1,9 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderTemplate "11ty.js" argData %} +module.exports = "TESTING"; +{% endrenderTemplate %} From 8673082345fc02a648f05eeddf3e54c157e3b201 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 09:21:27 -0600 Subject: [PATCH 635/746] v1.0.0-beta.6 --- docs-src/_data/coverage.json | 24 +++--- docs/coverage.md | 152 ++++++++++++++++++----------------- package.json | 4 +- 3 files changed, 94 insertions(+), 86 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 0ba8d4974..ac88809c4 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,5 +1,8 @@ -{"total": {"lines":{"total":4621,"covered":3810,"skipped":0,"pct":82.44},"statements":{"total":4646,"covered":3831,"skipped":0,"pct":82.45},"functions":{"total":1015,"covered":845,"skipped":0,"pct":83.25},"branches":{"total":2123,"covered":1581,"skipped":0,"pct":74.47},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":4742,"covered":3937,"skipped":0,"pct":83.02},"statements":{"total":4767,"covered":3959,"skipped":0,"pct":83.05},"functions":{"total":1038,"covered":872,"skipped":0,"pct":84},"branches":{"total":2164,"covered":1614,"skipped":0,"pct":74.58},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":55,"covered":34,"skipped":0,"pct":61.81},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":55,"covered":34,"skipped":0,"pct":61.81},"branches":{"total":24,"covered":14,"skipped":0,"pct":58.33}} +,"/Users/zachleat/Code/eleventy/.cache/vue/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_template_id_031efc80_lang.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":47,"covered":37,"skipped":0,"pct":78.72},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":47,"covered":37,"skipped":0,"pct":78.72},"branches":{"total":19,"covered":12,"skipped":0,"pct":63.15}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.77},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.77},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} @@ -7,13 +10,13 @@ ,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.03},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.03},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.62}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":26,"covered":24,"skipped":0,"pct":92.3},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":26,"covered":24,"skipped":0,"pct":92.3},"branches":{"total":7,"covered":5,"skipped":0,"pct":71.42}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":311,"covered":198,"skipped":0,"pct":63.66},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":312,"covered":198,"skipped":0,"pct":63.46},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":313,"covered":200,"skipped":0,"pct":63.89},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":314,"covered":200,"skipped":0,"pct":63.69},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheckError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":39,"covered":36,"skipped":0,"pct":92.3},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":39,"covered":36,"skipped":0,"pct":92.3},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.56}} +,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":38,"covered":35,"skipped":0,"pct":92.1},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":38,"covered":35,"skipped":0,"pct":92.1},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.56}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":82,"covered":80,"skipped":0,"pct":97.56},"functions":{"total":25,"covered":24,"skipped":0,"pct":96},"statements":{"total":82,"covered":80,"skipped":0,"pct":97.56},"branches":{"total":39,"covered":35,"skipped":0,"pct":89.74}} -,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":191,"covered":170,"skipped":0,"pct":89},"functions":{"total":45,"covered":39,"skipped":0,"pct":86.66},"statements":{"total":193,"covered":171,"skipped":0,"pct":88.6},"branches":{"total":71,"covered":53,"skipped":0,"pct":74.64}} +,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":191,"covered":170,"skipped":0,"pct":89},"functions":{"total":45,"covered":40,"skipped":0,"pct":88.88},"statements":{"total":193,"covered":172,"skipped":0,"pct":89.11},"branches":{"total":71,"covered":53,"skipped":0,"pct":74.64}} ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":70,"covered":26,"skipped":0,"pct":37.14},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":70,"covered":26,"skipped":0,"pct":37.14},"branches":{"total":36,"covered":9,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":39,"covered":39,"skipped":0,"pct":100},"functions":{"total":17,"covered":17,"skipped":0,"pct":100},"statements":{"total":40,"covered":40,"skipped":0,"pct":100},"branches":{"total":21,"covered":19,"skipped":0,"pct":90.47}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} @@ -34,22 +37,22 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":277,"covered":268,"skipped":0,"pct":96.75},"functions":{"total":37,"covered":35,"skipped":0,"pct":94.59},"statements":{"total":277,"covered":268,"skipped":0,"pct":96.75},"branches":{"total":150,"covered":129,"skipped":0,"pct":86}} ,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":60,"covered":57,"skipped":0,"pct":95},"functions":{"total":14,"covered":13,"skipped":0,"pct":92.85},"statements":{"total":60,"covered":57,"skipped":0,"pct":95},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":93,"covered":80,"skipped":0,"pct":86.02},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":93,"covered":80,"skipped":0,"pct":86.02},"branches":{"total":38,"covered":27,"skipped":0,"pct":71.05}} -,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":96,"covered":96,"skipped":0,"pct":100},"functions":{"total":27,"covered":26,"skipped":0,"pct":96.29},"statements":{"total":97,"covered":97,"skipped":0,"pct":100},"branches":{"total":54,"covered":54,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":98,"covered":98,"skipped":0,"pct":100},"functions":{"total":28,"covered":27,"skipped":0,"pct":96.42},"statements":{"total":99,"covered":99,"skipped":0,"pct":100},"branches":{"total":55,"covered":55,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":78,"covered":70,"skipped":0,"pct":89.74},"functions":{"total":10,"covered":9,"skipped":0,"pct":90},"statements":{"total":78,"covered":70,"skipped":0,"pct":89.74},"branches":{"total":69,"covered":62,"skipped":0,"pct":89.85}} -,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":86,"skipped":0,"pct":94.5},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":86,"skipped":0,"pct":94.5},"branches":{"total":59,"covered":53,"skipped":0,"pct":89.83}} +,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":87,"skipped":0,"pct":95.6},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":87,"skipped":0,"pct":95.6},"branches":{"total":59,"covered":54,"skipped":0,"pct":91.52}} ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":157,"skipped":0,"pct":63.82},"functions":{"total":65,"covered":36,"skipped":0,"pct":55.38},"statements":{"total":246,"covered":157,"skipped":0,"pct":63.82},"branches":{"total":99,"covered":45,"skipped":0,"pct":45.45}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":164,"skipped":0,"pct":66.66},"functions":{"total":65,"covered":39,"skipped":0,"pct":60},"statements":{"total":246,"covered":164,"skipped":0,"pct":66.66},"branches":{"total":99,"covered":47,"skipped":0,"pct":47.47}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":61,"covered":29,"skipped":0,"pct":47.54},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":61,"covered":29,"skipped":0,"pct":47.54},"branches":{"total":36,"covered":15,"skipped":0,"pct":41.66}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":61,"covered":31,"skipped":0,"pct":50.81},"functions":{"total":9,"covered":7,"skipped":0,"pct":77.77},"statements":{"total":61,"covered":31,"skipped":0,"pct":50.81},"branches":{"total":36,"covered":16,"skipped":0,"pct":44.44}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":29,"covered":29,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":29,"covered":29,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":12,"covered":12,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":12,"covered":12,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":58,"covered":56,"skipped":0,"pct":96.55},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":59,"covered":57,"skipped":0,"pct":96.61},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":88,"covered":84,"skipped":0,"pct":95.45},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":89,"covered":85,"skipped":0,"pct":95.5},"branches":{"total":25,"covered":20,"skipped":0,"pct":80}} +,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":88,"covered":86,"skipped":0,"pct":97.72},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":89,"covered":87,"skipped":0,"pct":97.75},"branches":{"total":25,"covered":21,"skipped":0,"pct":84}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":35,"covered":32,"skipped":0,"pct":91.42},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.88},"statements":{"total":35,"covered":32,"skipped":0,"pct":91.42},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":201,"covered":132,"skipped":0,"pct":65.67},"functions":{"total":47,"covered":34,"skipped":0,"pct":72.34},"statements":{"total":201,"covered":132,"skipped":0,"pct":65.67},"branches":{"total":88,"covered":58,"skipped":0,"pct":65.9}} +,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":201,"covered":137,"skipped":0,"pct":68.15},"functions":{"total":47,"covered":35,"skipped":0,"pct":74.46},"statements":{"total":201,"covered":137,"skipped":0,"pct":68.15},"branches":{"total":88,"covered":59,"skipped":0,"pct":67.04}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} ,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":72,"covered":70,"skipped":0,"pct":97.22},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":74,"covered":72,"skipped":0,"pct":97.29},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -61,6 +64,7 @@ ,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} ,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":136,"covered":121,"skipped":0,"pct":88.97},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":140,"covered":125,"skipped":0,"pct":89.28},"branches":{"total":90,"covered":70,"skipped":0,"pct":77.77}} +,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":107,"covered":96,"skipped":0,"pct":89.71},"functions":{"total":21,"covered":19,"skipped":0,"pct":90.47},"statements":{"total":107,"covered":96,"skipped":0,"pct":89.71},"branches":{"total":40,"covered":26,"skipped":0,"pct":65}} ,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":186,"covered":12,"skipped":0,"pct":6.45},"functions":{"total":34,"covered":0,"skipped":0,"pct":0},"statements":{"total":188,"covered":12,"skipped":0,"pct":6.38},"branches":{"total":91,"covered":0,"skipped":0,"pct":0}} ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":28,"covered":24,"skipped":0,"pct":85.71},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":28,"covered":24,"skipped":0,"pct":85.71},"branches":{"total":19,"covered":17,"skipped":0,"pct":89.47}} diff --git a/docs/coverage.md b/docs/coverage.md index 8c218f467..dde1fe155 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,75 +1,79 @@ -# Code Coverage for Eleventy v1.0.0-beta.5 +# Code Coverage for Eleventy v1.0.0-beta.6 -| Filename | % Lines | % Statements | % Functions | % Branches | -| ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 82.44% | 82.45% | 83.25% | 74.47% | -| `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | -| `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | -| `src/BenchmarkGroup.js` | 78.72% | 78.72% | 66.66% | 63.15% | -| `src/BenchmarkManager.js` | 77.77% | 77.77% | 75% | 75% | -| `src/ComputedData.js` | 100% | 100% | 100% | 96.55% | -| `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | -| `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | -| `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | -| `src/Eleventy.js` | 63.66% | 63.46% | 67.34% | 63.71% | -| `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | -| `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | -| `src/EleventyErrorHandler.js` | 92.3% | 92.3% | 100% | 67.56% | -| `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | -| `src/EleventyExtensionMap.js` | 97.56% | 97.56% | 96% | 89.74% | -| `src/EleventyFiles.js` | 89% | 88.6% | 86.66% | 74.64% | -| `src/EleventyServe.js` | 37.14% | 37.14% | 56.25% | 25% | -| `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | -| `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | -| `src/EventBus.js` | 100% | 100% | 100% | 100% | -| `src/Serverless.js` | 75.78% | 75.78% | 85.71% | 63.15% | -| `src/Template.js` | 93.07% | 93.11% | 97.18% | 85.96% | -| `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | -| `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | -| `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | -| `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | -| `src/TemplateContent.js` | 90.18% | 90.18% | 100% | 74.66% | -| `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | -| `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | -| `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | -| `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | -| `src/TemplateLayout.js` | 92.3% | 92.4% | 100% | 85% | -| `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | -| `src/TemplateMap.js` | 96.75% | 96.75% | 94.59% | 86% | -| `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | -| `src/TemplatePassthroughManager.js` | 86.02% | 86.02% | 100% | 71.05% | -| `src/TemplatePath.js` | 100% | 100% | 96.29% | 100% | -| `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | -| `src/TemplateRender.js` | 94.5% | 94.5% | 100% | 89.83% | -| `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | -| `src/UserConfig.js` | 63.82% | 63.82% | 55.38% | 45.45% | -| `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | -| `src/Engines/Custom.js` | 47.54% | 47.54% | 66.66% | 41.66% | -| `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | -| `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | -| `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | -| `src/Engines/Html.js` | 100% | 100% | 100% | 100% | -| `src/Engines/JavaScript.js` | 96.55% | 96.61% | 100% | 83.33% | -| `src/Engines/Liquid.js` | 95.45% | 95.5% | 96.66% | 80% | -| `src/Engines/Markdown.js` | 91.42% | 91.42% | 88.88% | 81.25% | -| `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | -| `src/Engines/Nunjucks.js` | 65.67% | 65.67% | 72.34% | 65.9% | -| `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | -| `src/Engines/TemplateEngine.js` | 97.22% | 97.29% | 95.65% | 93.75% | -| `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | -| `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | -| `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | -| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.85% | -| `src/Filters/ServerlessUrl.js` | 100% | 100% | 100% | 75% | -| `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | -| `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | -| `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | -| `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | -| `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | -| `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | -| `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | -| `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | -| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 91.66% | -| `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | -| `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | -| `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% | +| Filename | % Lines | % Statements | % Functions | % Branches | +| -------------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | +| `total` | 83.02% | 83.05% | 84% | 74.58% | +| `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | +| `.cache/vue/include.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/include.vue_vue_type_template_id_031efc80_lang.js` | 100% | 100% | 100% | 100% | +| `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | +| `src/BenchmarkGroup.js` | 78.72% | 78.72% | 66.66% | 63.15% | +| `src/BenchmarkManager.js` | 77.77% | 77.77% | 75% | 75% | +| `src/ComputedData.js` | 100% | 100% | 100% | 96.55% | +| `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | +| `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | +| `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | +| `src/Eleventy.js` | 63.89% | 63.69% | 67.34% | 63.71% | +| `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | +| `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | +| `src/EleventyErrorHandler.js` | 92.1% | 92.1% | 100% | 67.56% | +| `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | +| `src/EleventyExtensionMap.js` | 97.56% | 97.56% | 96% | 89.74% | +| `src/EleventyFiles.js` | 89% | 89.11% | 88.88% | 74.64% | +| `src/EleventyServe.js` | 37.14% | 37.14% | 56.25% | 25% | +| `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | +| `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | +| `src/EventBus.js` | 100% | 100% | 100% | 100% | +| `src/Serverless.js` | 75.78% | 75.78% | 85.71% | 63.15% | +| `src/Template.js` | 93.07% | 93.11% | 97.18% | 85.96% | +| `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | +| `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | +| `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | +| `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | +| `src/TemplateContent.js` | 90.18% | 90.18% | 100% | 74.66% | +| `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | +| `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | +| `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | +| `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | +| `src/TemplateLayout.js` | 92.3% | 92.4% | 100% | 85% | +| `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | +| `src/TemplateMap.js` | 96.75% | 96.75% | 94.59% | 86% | +| `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | +| `src/TemplatePassthroughManager.js` | 86.02% | 86.02% | 100% | 71.05% | +| `src/TemplatePath.js` | 100% | 100% | 96.42% | 100% | +| `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | +| `src/TemplateRender.js` | 95.6% | 95.6% | 100% | 91.52% | +| `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | +| `src/UserConfig.js` | 66.66% | 66.66% | 60% | 47.47% | +| `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | +| `src/Engines/Custom.js` | 50.81% | 50.81% | 77.77% | 44.44% | +| `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | +| `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | +| `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | +| `src/Engines/Html.js` | 100% | 100% | 100% | 100% | +| `src/Engines/JavaScript.js` | 96.55% | 96.61% | 100% | 83.33% | +| `src/Engines/Liquid.js` | 97.72% | 97.75% | 96.66% | 84% | +| `src/Engines/Markdown.js` | 91.42% | 91.42% | 88.88% | 81.25% | +| `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | +| `src/Engines/Nunjucks.js` | 68.15% | 68.15% | 74.46% | 67.04% | +| `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | +| `src/Engines/TemplateEngine.js` | 97.22% | 97.29% | 95.65% | 93.75% | +| `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | +| `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | +| `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | +| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.85% | +| `src/Filters/ServerlessUrl.js` | 100% | 100% | 100% | 75% | +| `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | +| `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | +| `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | +| `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | +| `src/Plugins/RenderPlugin.js` | 89.71% | 89.71% | 90.47% | 65% | +| `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | +| `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | +| `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | +| `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | +| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 91.66% | +| `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | +| `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | +| `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% | diff --git a/package.json b/package.json index 4930e7daa..6e5b69c28 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.5", + "version": "1.0.0-beta.6", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -78,7 +78,7 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", - "@vue/server-renderer": "^3.2.21", + "@vue/server-renderer": "^3.2.22", "ava": "^3.15.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", From 1b2d64cc46c4ab2ae02251c427faf258136dea8d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 09:50:13 -0600 Subject: [PATCH 636/746] Falsy template language passed to renderTemplate should be an alias for raw tag and just use plaintext --- src/Plugins/RenderPlugin.js | 14 +++++++------- test/TemplateRenderPluginTest.js | 11 +++++++++++ test/stubs-render-plugin/false.liquid | 4 ++++ 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 test/stubs-render-plugin/false.liquid diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 8886edac6..396445c03 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -17,13 +17,12 @@ function getFullIncludesDirectory(dir = {}) { return fullIncludesDir; } -async function render(content, templateLang, dir = {}, templateConfig) { - if (!templateLang) { - throw new Error( - "Missing template syntax argument passed to the `template` shortcode." - ); - } - +async function render( + content, + templateLang = "html", + dir = {}, + templateConfig +) { if (!templateConfig) { templateConfig = new TemplateConfig(); } @@ -41,6 +40,7 @@ async function render(content, templateLang, dir = {}, templateConfig) { return tr.getCompiledTemplate(content); } +// No templateLang default, it should infer from the inputPath. async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { if (!inputPath) { throw new Error( diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index b5240ab4b..7fd07f9e2 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -162,3 +162,14 @@ test.skip("Use nunjucks file in liquid but it doesn’t exist", async (t) => { ); }); }); + +test("No syntax passed, uses html (plaintext) by default; in liquid (this is basically an alias for the `raw` tag)", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/false.liquid" + ); + t.is( + html, + `# Hello {{ hi }} +* Testing` + ); +}); diff --git a/test/stubs-render-plugin/false.liquid b/test/stubs-render-plugin/false.liquid new file mode 100644 index 000000000..6145c0f90 --- /dev/null +++ b/test/stubs-render-plugin/false.liquid @@ -0,0 +1,4 @@ +{% renderTemplate %} +# Hello {{ hi }} +* Testing +{% endrenderTemplate %} From ff1153c682bd335be6227b7055df715852899202 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 13:48:13 -0600 Subject: [PATCH 637/746] Add a few more tests for the Render Plugin --- src/Plugins/RenderPlugin.js | 4 ++-- test/TemplateRenderPluginTest.js | 15 +++++++++++++++ test/stubs-render-plugin/11tyjs-file-override.njk | 7 +++++++ .../_includes/frontmatter.liquid | 4 ++++ test/stubs-render-plugin/_includes/include-js.txt | 1 + test/stubs-render-plugin/using-frontmatter.liquid | 1 + 6 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 test/stubs-render-plugin/11tyjs-file-override.njk create mode 100644 test/stubs-render-plugin/_includes/frontmatter.liquid create mode 100644 test/stubs-render-plugin/_includes/include-js.txt create mode 100644 test/stubs-render-plugin/using-frontmatter.liquid diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 396445c03..5094e8720 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -44,7 +44,7 @@ async function render( async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { if (!inputPath) { throw new Error( - "Missing file path argument passed to the `templatefile` shortcode." + "Missing file path argument passed to the `renderFile` shortcode." ); } @@ -52,7 +52,7 @@ async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { !fs.existsSync(TemplatePath.normalizeOperatingSystemFilePath(inputPath)) ) { throw new Error( - "Could not find render plugin file for renderFile, looking for: " + + "Could not find render plugin file for the `renderFile` shortcode, looking for: " + inputPath ); } diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index 7fd07f9e2..ef6278661 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -153,6 +153,13 @@ test("Use 11ty.js file in njk", async (t) => { t.is(html, `TESTING`); }); +test("Use txt file in njk (override to 11ty.js)", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/11tyjs-file-override.njk" + ); + t.is(html, `TESTING`); +}); + // Skip this for now, toJSON calls actually change the exitCode of the process when they error, // which is not ideal. test.skip("Use nunjucks file in liquid but it doesn’t exist", async (t) => { @@ -173,3 +180,11 @@ test("No syntax passed, uses html (plaintext) by default; in liquid (this is bas * Testing` ); }); + +// Not yet supported +test.skip("renderFile but the target has front matter.", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/using-frontmatter.liquid" + ); + t.is(html, `frontmatterString`); +}); diff --git a/test/stubs-render-plugin/11tyjs-file-override.njk b/test/stubs-render-plugin/11tyjs-file-override.njk new file mode 100644 index 000000000..8183a0d5c --- /dev/null +++ b/test/stubs-render-plugin/11tyjs-file-override.njk @@ -0,0 +1,7 @@ +--- +hi: value +argData: + hi: liquidHi + bye: liquidBye +--- +{% renderFile "./test/stubs-render-plugin/_includes/include-js.txt", argData, "11ty.js" %} \ No newline at end of file diff --git a/test/stubs-render-plugin/_includes/frontmatter.liquid b/test/stubs-render-plugin/_includes/frontmatter.liquid new file mode 100644 index 000000000..5d06fba7a --- /dev/null +++ b/test/stubs-render-plugin/_includes/frontmatter.liquid @@ -0,0 +1,4 @@ +--- +test: frontmatterString +--- +{{ test }} \ No newline at end of file diff --git a/test/stubs-render-plugin/_includes/include-js.txt b/test/stubs-render-plugin/_includes/include-js.txt new file mode 100644 index 000000000..2637dc46d --- /dev/null +++ b/test/stubs-render-plugin/_includes/include-js.txt @@ -0,0 +1 @@ +module.exports = "TESTING"; diff --git a/test/stubs-render-plugin/using-frontmatter.liquid b/test/stubs-render-plugin/using-frontmatter.liquid new file mode 100644 index 000000000..47cf57cac --- /dev/null +++ b/test/stubs-render-plugin/using-frontmatter.liquid @@ -0,0 +1 @@ +{% renderFile "./test/stubs-render-plugin/_includes/frontmatter.liquid" %} From 55539ad7ffebe7978b68b2054e75f5a14dec9e68 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 13:49:47 -0600 Subject: [PATCH 638/746] For non-data keys, (e.g. serverPrefetch in vue), we can make the object check optional. --- src/Engines/Custom.js | 7 ++++++- src/Util/GetJavaScriptData.js | 13 +++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 9969560f7..408cc9504 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -97,7 +97,12 @@ class CustomEngine extends TemplateEngine { let promises = []; for (let key of keys) { - promises.push(getJavaScriptData(inst, inputPath, key, mixins)); + promises.push( + getJavaScriptData(inst, inputPath, key, { + mixins, + isObjectRequired: key === "data", + }) + ); } let results = await Promise.all(promises); diff --git a/src/Util/GetJavaScriptData.js b/src/Util/GetJavaScriptData.js index 05803903f..92d6fba50 100644 --- a/src/Util/GetJavaScriptData.js +++ b/src/Util/GetJavaScriptData.js @@ -2,7 +2,15 @@ const EleventyBaseError = require("../EleventyBaseError"); class JavaScriptInvalidDataFormatError extends EleventyBaseError {} -module.exports = async function (inst, inputPath, key = "data", mixins = {}) { +module.exports = async function (inst, inputPath, key = "data", options = {}) { + let { mixins, isObjectRequired } = Object.assign( + { + mixins: {}, + isObjectRequired: true, + }, + options + ); + if (inst && key in inst) { // get extra data from `data` method, // either as a function or getter or object literal @@ -11,7 +19,8 @@ module.exports = async function (inst, inputPath, key = "data", mixins = {}) { ? inst[key].call(mixins) : inst[key]() : inst[key]); - if (typeof result !== "object") { + + if (isObjectRequired && typeof result !== "object") { throw new JavaScriptInvalidDataFormatError( `Invalid data format returned from ${inputPath}: typeof ${typeof result}` ); From d82f4dd3e17649ca3d2e2dd18b6c157eeaee669c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 13:55:28 -0600 Subject: [PATCH 639/746] v1.0.0-beta.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e5b69c28..87960dc51 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 46f14df3744bfbf24e6f89fe6825f791cc32ce6a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Nov 2021 13:55:57 -0600 Subject: [PATCH 640/746] Coverage --- docs-src/_data/coverage.json | 6 +++--- docs/coverage.md | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index ac88809c4..839f951f0 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":4742,"covered":3937,"skipped":0,"pct":83.02},"statements":{"total":4767,"covered":3959,"skipped":0,"pct":83.05},"functions":{"total":1038,"covered":872,"skipped":0,"pct":84},"branches":{"total":2164,"covered":1614,"skipped":0,"pct":74.58},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":4741,"covered":3938,"skipped":0,"pct":83.06},"statements":{"total":4766,"covered":3960,"skipped":0,"pct":83.08},"functions":{"total":1038,"covered":872,"skipped":0,"pct":84},"branches":{"total":2165,"covered":1617,"skipped":0,"pct":74.68},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":55,"covered":34,"skipped":0,"pct":61.81},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":55,"covered":34,"skipped":0,"pct":61.81},"branches":{"total":24,"covered":14,"skipped":0,"pct":58.33}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -64,12 +64,12 @@ ,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} ,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":136,"covered":121,"skipped":0,"pct":88.97},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":140,"covered":125,"skipped":0,"pct":89.28},"branches":{"total":90,"covered":70,"skipped":0,"pct":77.77}} -,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":107,"covered":96,"skipped":0,"pct":89.71},"functions":{"total":21,"covered":19,"skipped":0,"pct":90.47},"statements":{"total":107,"covered":96,"skipped":0,"pct":89.71},"branches":{"total":40,"covered":26,"skipped":0,"pct":65}} +,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":105,"covered":96,"skipped":0,"pct":91.42},"functions":{"total":21,"covered":19,"skipped":0,"pct":90.47},"statements":{"total":105,"covered":96,"skipped":0,"pct":91.42},"branches":{"total":39,"covered":27,"skipped":0,"pct":69.23}} ,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":186,"covered":12,"skipped":0,"pct":6.45},"functions":{"total":34,"covered":0,"skipped":0,"pct":0},"statements":{"total":188,"covered":12,"skipped":0,"pct":6.38},"branches":{"total":91,"covered":0,"skipped":0,"pct":0}} ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":28,"covered":24,"skipped":0,"pct":85.71},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":28,"covered":24,"skipped":0,"pct":85.71},"branches":{"total":19,"covered":17,"skipped":0,"pct":89.47}} ,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":12,"covered":11,"skipped":0,"pct":91.66}} +,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.85}} ,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.85},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.85},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/Util/Pluralize.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":48,"covered":45,"skipped":0,"pct":93.75},"functions":{"total":20,"covered":18,"skipped":0,"pct":90},"statements":{"total":48,"covered":45,"skipped":0,"pct":93.75},"branches":{"total":20,"covered":18,"skipped":0,"pct":90}} diff --git a/docs/coverage.md b/docs/coverage.md index dde1fe155..1003c9cc9 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,8 +1,8 @@ -# Code Coverage for Eleventy v1.0.0-beta.6 +# Code Coverage for Eleventy v1.0.0-beta.7 | Filename | % Lines | % Statements | % Functions | % Branches | | -------------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 83.02% | 83.05% | 84% | 74.58% | +| `total` | 83.06% | 83.08% | 84% | 74.68% | | `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | | `.cache/vue/include.js` | 100% | 100% | 100% | 100% | | `.cache/vue/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | @@ -68,12 +68,12 @@ | `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | | `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | | `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | -| `src/Plugins/RenderPlugin.js` | 89.71% | 89.71% | 90.47% | 65% | +| `src/Plugins/RenderPlugin.js` | 91.42% | 91.42% | 90.47% | 69.23% | | `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | | `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | | `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | | `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | -| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 91.66% | +| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 92.85% | | `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | | `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | | `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% | From d311c89c3d1b0585cfedfd9f34967298543d066f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Nov 2021 10:26:49 -0600 Subject: [PATCH 641/746] Fixes #2098 --- src/Plugins/RenderPlugin.js | 16 +++++++++------- test/TemplateRenderPluginTest.js | 14 +++++++++++++- test/stubs-render-plugin/capture-njk.liquid | 11 +++++++++++ test/stubs-render-plugin/nunjucks.liquid | 2 ++ 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 test/stubs-render-plugin/capture-njk.liquid diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 5094e8720..f987dc009 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -31,7 +31,8 @@ async function render( let tr = new TemplateRender(templateLang, includesDir, templateConfig); tr.setEngineOverride(templateLang); - if (tr.engine.name === "11ty.js") { + // TODO tie this to the class, not the extension + if (tr.engine.name === "11ty.js" || tr.engine.name === "11ty.cjs") { throw new Error( "11ty.js is not yet supported as a template engine for `renderTemplate`. Use `renderFile` instead!" ); @@ -78,6 +79,7 @@ async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { function EleventyPlugin(eleventyConfig, options = {}) { function liquidTemplateTag(liquidEngine, tagName) { + // via https://github.com/harttle/liquidjs/blob/b5a22fa0910c708fe7881ef170ed44d3594e18f3/src/builtin/tags/raw.ts return { parse: function (tagToken, remainTokens) { this.name = tagToken.name; @@ -86,10 +88,12 @@ function EleventyPlugin(eleventyConfig, options = {}) { var stream = liquidEngine.parser .parseStream(remainTokens) - .on("template", (tpl) => this.tokens.push(tpl)) - .on("tag:end" + tagName, () => stream.stop()) + .on("token", (token) => { + if (token.name === "end" + tagName) stream.stop(); + else this.tokens.push(token); + }) .on("end", () => { - throw new Error(`tag ${tagToken.raw} not closed`); + throw new Error(`tag ${tagToken.getText()} not closed`); }); stream.start(); @@ -107,9 +111,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { this.liquid ); - let start = this.tokens[0].token.begin; - let end = this.tokens[this.tokens.length - 1].token.end; - let body = this.tokens[0].token.input.substring(start, end); + let body = this.tokens.map((token) => token.getText()).join(""); return renderStringShortcodeFn.call( normalizedContext, diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index ef6278661..75470820d 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -80,7 +80,11 @@ test("Use nunjucks in liquid", async (t) => { let html = await getTestOutputForFile( "./test/stubs-render-plugin/nunjucks.liquid" ); - t.is(html, `* iHdiuqil`); + t.is( + html, + `* iHdiuqil +* lfjksdlba` + ); }); test("Use markdown in liquid", async (t) => { @@ -188,3 +192,11 @@ test.skip("renderFile but the target has front matter.", async (t) => { ); t.is(html, `frontmatterString`); }); + +// Idea from https://twitter.com/raymondcamden/status/1460961620247650312 +test("Capture nunjucks render output to a liquid variable", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/capture-njk.liquid" + ); + t.is(html, `4`); +}); diff --git a/test/stubs-render-plugin/capture-njk.liquid b/test/stubs-render-plugin/capture-njk.liquid new file mode 100644 index 000000000..a60fad087 --- /dev/null +++ b/test/stubs-render-plugin/capture-njk.liquid @@ -0,0 +1,11 @@ +--- +argData: + num: 2 +--- +{% capture nunjucksOutput %} +{% renderTemplate "njk", argData %} +{% set njkVar = num * 2 %} +{{ njkVar }} +{% endrenderTemplate %} +{% endcapture %} +{{ nunjucksOutput }} \ No newline at end of file diff --git a/test/stubs-render-plugin/nunjucks.liquid b/test/stubs-render-plugin/nunjucks.liquid index ec8e06a39..d11e75c16 100644 --- a/test/stubs-render-plugin/nunjucks.liquid +++ b/test/stubs-render-plugin/nunjucks.liquid @@ -5,5 +5,7 @@ argData: bye: liquidBye --- {% renderTemplate "njk" argData %} +{% set bye = "abldskjfl" %} * {{ hi | reverse }} +* {{ bye | reverse }} {% endrenderTemplate %} From 50203907b05e3575fc26550a41cb8dfe21914443 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 17 Nov 2021 10:31:25 -0600 Subject: [PATCH 642/746] v1.0.0-beta.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87960dc51..33ef68260 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.7", + "version": "1.0.0-beta.8", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 22fee95b15be43c45992ad0bd07730d14517fa14 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 18 Nov 2021 09:46:44 -0600 Subject: [PATCH 643/746] Show plugin name if one exists (via function.name) https://github.com/11ty/eleventy/issues/2075#issuecomment-962530456 --- src/UserConfig.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/UserConfig.js b/src/UserConfig.js index 0c0ed8d0f..b772d9df0 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -326,8 +326,7 @@ class UserConfig { } _executePlugin(plugin, options) { - // TODO support function.name in plugin config functions - debug("Adding plugin (unknown name: check your config file)."); + debug(`Adding ${plugin.name || "anonymous"} plugin`); let pluginBench = aggregateBench.get("Configuration addPlugin"); if (typeof plugin === "function") { pluginBench.before(); From 35d53bfeb19b3436b3b426f50047411794f9f2d2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Nov 2021 13:39:26 -0600 Subject: [PATCH 644/746] Was very incorrectly passing includesDir instead of inputDir into TemplateRender. Found via #2100 https://github.com/11ty/eleventy/issues/2100#issuecomment-973623359 --- src/Plugins/RenderPlugin.js | 49 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index f987dc009..d121e079e 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -9,26 +9,30 @@ const TemplateRender = require("../TemplateRender"); const TemplateConfig = require("../TemplateConfig"); const Liquid = require("../Engines/Liquid"); -function getFullIncludesDirectory(dir = {}) { - let inputDir = dir.input || "."; - let includesDir = dir.includes || "_includes"; - let fullIncludesDir = path.join(inputDir, includesDir); - - return fullIncludesDir; +function normalizeDirectories(dir = {}) { + return Object.assign( + { + input: ".", + }, + dir + ); } async function render( content, templateLang = "html", - dir = {}, + normalizedDirs = {}, templateConfig ) { if (!templateConfig) { templateConfig = new TemplateConfig(); } - let includesDir = getFullIncludesDirectory(dir); - let tr = new TemplateRender(templateLang, includesDir, templateConfig); + let tr = new TemplateRender( + templateLang, + normalizedDirs.input, + templateConfig + ); tr.setEngineOverride(templateLang); // TODO tie this to the class, not the extension @@ -42,7 +46,12 @@ async function render( } // No templateLang default, it should infer from the inputPath. -async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { +async function renderFile( + inputPath, + templateLang, + normalizedDirs = {}, + templateConfig +) { if (!inputPath) { throw new Error( "Missing file path argument passed to the `renderFile` shortcode." @@ -62,8 +71,7 @@ async function renderFile(inputPath, templateLang, dir = {}, templateConfig) { templateConfig = new TemplateConfig(); } - let includesDir = getFullIncludesDirectory(dir); - let tr = new TemplateRender(inputPath, includesDir, templateConfig); + let tr = new TemplateRender(inputPath, normalizedDirs.input, templateConfig); if (templateLang) { tr.setEngineOverride(templateLang); } @@ -225,19 +233,14 @@ function EleventyPlugin(eleventyConfig, options = {}) { this, content, templateLang, - eleventyConfig.dir, + normalizeDirectories(eleventyConfig.dir), templateConfig ); // save `page` for reuse data.page = this.page; - let output = await fn(data); - // console.log( "--->", this.page.inputPath, "using", templateLang ); - // console.log( { data } ); - // console.log( { content } ); - // console.log( { output } ); - return output; + return fn(data); } async function renderFileShortcodeFn(inputPath, data = {}, templateLang) { @@ -245,18 +248,14 @@ function EleventyPlugin(eleventyConfig, options = {}) { this, inputPath, templateLang, - eleventyConfig.dir, + normalizeDirectories(eleventyConfig.dir), templateConfig ); // save `page` for re-use data.page = this.page; - let output = await fn(data); - // console.log( "--->", this.page.inputPath, "using", inputPath, "using", templateLang ); - // console.log( { data } ); - // console.log( { output } ); - return output; + return fn(data); } // Render strings From 9da0d581d1cad58e793825a63d7f638567bf04a4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Nov 2021 22:12:48 -0600 Subject: [PATCH 645/746] Apply the fix from #1749 to RenderPlugin too. --- src/Plugins/RenderPlugin.js | 41 +++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index d121e079e..19284c899 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -196,19 +196,38 @@ function EleventyPlugin(eleventyConfig, options = {}) { normalizedContext.page = context.ctx.page; } - renderStringShortcodeFn - .call(normalizedContext, body(), ...argArray) - .then(function (returnValue) { - resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); - }) - .catch(function (e) { + body(function (e, bodyContent) { + if (e) { resolve( - new Error( - `Error with Nunjucks paired shortcode \`${tagName}\`${e.message}` - ), - null + new EleventyShortcodeError( + `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ) ); - }); + } + + Promise.resolve( + renderStringShortcodeFn.call( + normalizedContext, + bodyContent, + ...argArray + ) + ) + .then(function (returnValue) { + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function (e) { + resolve( + new EleventyShortcodeError( + `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ), + null + ); + }); + }); }; })(); } From f3831c317b0d829e398e722c83715e03d6911ec0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 19 Nov 2021 22:21:31 -0600 Subject: [PATCH 646/746] =?UTF-8?q?Going=20all=20in=20on=20async=20Nunjuck?= =?UTF-8?q?s=20shortcodes.=20We=20don=E2=80=99t=20need=20to=20distinguish?= =?UTF-8?q?=20between=20async=20and=20sync=20shortcodes=20in=20Nunjucks=20?= =?UTF-8?q?now,=20due=20to=20#1749.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Engines/Nunjucks.js | 143 +++++++++++++--------------------------- src/UserConfig.js | 80 +++++++--------------- 2 files changed, 66 insertions(+), 157 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index f56bebb3b..4295e252f 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -157,12 +157,7 @@ class Nunjucks extends TemplateEngine { // TODO these all go to the same place (addTag), add warnings for overwrites this.addCustomTags(this.config.nunjucksTags); this.addAllShortcodes(this.config.nunjucksShortcodes); - this.addAllShortcodes(this.config.nunjucksAsyncShortcodes, true); this.addAllPairedShortcodes(this.config.nunjucksPairedShortcodes); - this.addAllPairedShortcodes( - this.config.nunjucksAsyncPairedShortcodes, - true - ); this.addGlobals(this.config.nunjucksGlobals); } @@ -201,15 +196,15 @@ class Nunjucks extends TemplateEngine { this.njkEnv.addGlobal(name, globalFn); } - addAllShortcodes(shortcodes, isAsync = false) { + addAllShortcodes(shortcodes) { for (let name in shortcodes) { - this.addShortcode(name, shortcodes[name], isAsync); + this.addShortcode(name, shortcodes[name]); } } - addAllPairedShortcodes(shortcodes, isAsync = false) { + addAllPairedShortcodes(shortcodes) { for (let name in shortcodes) { - this.addPairedShortcode(name, shortcodes[name], isAsync); + this.addPairedShortcode(name, shortcodes[name]); } } @@ -221,7 +216,7 @@ class Nunjucks extends TemplateEngine { return obj; } - _getShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) { + _getShortcodeFn(shortcodeName, shortcodeFn) { return function ShortcodeFunction() { this.tags = [shortcodeName]; @@ -239,57 +234,37 @@ class Nunjucks extends TemplateEngine { } parser.advanceAfterBlockEnd(tok.value); - if (isAsync) { - return new nodes.CallExtensionAsync(this, "run", args); - } - return new nodes.CallExtension(this, "run", args); + return new nodes.CallExtensionAsync(this, "run", args); }; this.run = function (...args) { - let resolve; - if (isAsync) { - resolve = args.pop(); - } - + let callback = args.pop(); let [context, ...argArray] = args; - if (isAsync) { - shortcodeFn - .call(Nunjucks._normalizeShortcodeContext(context), ...argArray) - .then(function (returnValue) { - resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); - }) - .catch(function (e) { - resolve( - new EleventyShortcodeError( - `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( - e - )}` - ), - null - ); - }); - } else { - try { - return new NunjucksLib.runtime.SafeString( - shortcodeFn.call( - Nunjucks._normalizeShortcodeContext(context), - ...argArray - ) - ); - } catch (e) { - throw new EleventyShortcodeError( - `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( - e - )}` + Promise.resolve( + shortcodeFn.call( + Nunjucks._normalizeShortcodeContext(context), + ...argArray + ) + ) + .then(function (returnValue) { + callback(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function (e) { + callback( + new EleventyShortcodeError( + `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ), + null ); - } - } + }); }; }; } - _getPairedShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) { + _getPairedShortcodeFn(shortcodeName, shortcodeFn) { return function PairedShortcodeFunction() { this.tags = [shortcodeName]; @@ -321,60 +296,38 @@ class Nunjucks extends TemplateEngine { ); } - if (isAsync) { - shortcodeFn - .call( - Nunjucks._normalizeShortcodeContext(context), - bodyContent, - ...argArray - ) - .then(function (returnValue) { - resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); - }) - .catch(function (e) { - resolve( - new EleventyShortcodeError( - `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( - e - )}` - ), - null - ); - }); - } else { - try { - resolve( - null, - new NunjucksLib.runtime.SafeString( - shortcodeFn.call( - Nunjucks._normalizeShortcodeContext(context), - bodyContent, - ...argArray - ) - ) - ); - } catch (e) { + Promise.resolve( + shortcodeFn.call( + Nunjucks._normalizeShortcodeContext(context), + bodyContent, + ...argArray + ) + ) + .then(function (returnValue) { + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( e )}` - ) + ), + null ); - } - } + }); }); }; }; } - addShortcode(shortcodeName, shortcodeFn, isAsync = false) { - let fn = this._getShortcodeFn(shortcodeName, shortcodeFn, isAsync); + addShortcode(shortcodeName, shortcodeFn) { + let fn = this._getShortcodeFn(shortcodeName, shortcodeFn); this.njkEnv.addExtension(shortcodeName, new fn()); } - addPairedShortcode(shortcodeName, shortcodeFn, isAsync = false) { - let fn = this._getPairedShortcodeFn(shortcodeName, shortcodeFn, isAsync); + addPairedShortcode(shortcodeName, shortcodeFn) { + let fn = this._getPairedShortcodeFn(shortcodeName, shortcodeFn); this.njkEnv.addExtension(shortcodeName, new fn()); } @@ -407,18 +360,10 @@ class Nunjucks extends TemplateEngine { let fn = this._getShortcodeFn(name, () => {}); ext.push(new fn()); } - for (let name in this.config.nunjucksAsyncShortcodes) { - let fn = this._getShortcodeFn(name, () => {}, true); - ext.push(new fn()); - } for (let name in this.config.nunjucksPairedShortcodes) { let fn = this._getPairedShortcodeFn(name, () => {}); ext.push(new fn()); } - for (let name in this.config.nunjucksAsyncPairedShortcodes) { - let fn = this._getPairedShortcodeFn(name, () => {}, true); - ext.push(new fn()); - } this._parseExtensions = ext; return ext; diff --git a/src/UserConfig.js b/src/UserConfig.js index b772d9df0..6f682a061 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -35,9 +35,7 @@ class UserConfig { this.nunjucksTags = {}; this.nunjucksGlobals = {}; this.nunjucksShortcodes = {}; - this.nunjucksAsyncShortcodes = {}; this.nunjucksPairedShortcodes = {}; - this.nunjucksAsyncPairedShortcodes = {}; this.handlebarsHelpers = {}; this.handlebarsShortcodes = {}; this.handlebarsPairedShortcodes = {}; @@ -460,52 +458,35 @@ class UserConfig { // Undocumented method as a mitigation to reduce risk of #498 addAsyncShortcode(name, callback) { debug("Adding universal async shortcode %o", this.getNamespacedName(name)); - this.addNunjucksAsyncShortcode(name, callback); + this.addNunjucksShortcode(name, callback); this.addLiquidShortcode(name, callback); this.addJavaScriptFunction(name, callback); // not supported in Handlebars } + // DEPRECATED, with 1.0.0-beta.9 and #1749 we don’t need to distinguish between async/sync shortcodes now addNunjucksAsyncShortcode(name, callback) { + this.addNunjucksShortcode(name, callback); + } + + addNunjucksShortcode(name, callback) { name = this.getNamespacedName(name); - if (this.nunjucksAsyncShortcodes[name]) { + if (this.nunjucksShortcodes[name]) { debug( chalk.yellow( - "Warning, overwriting a Nunjucks Async Shortcode with `addNunjucksAsyncShortcode(%o)`" + "Warning, overwriting a Nunjucks Shortcode with `addNunjucksShortcode(%o)`" ), name ); } - this.nunjucksAsyncShortcodes[name] = bench.add( - `"${name}" Nunjucks Async Shortcode`, + this.nunjucksShortcodes[name] = bench.add( + `"${name}" Nunjucks Shortcode`, callback ); } - addNunjucksShortcode(name, callback, isAsync = false) { - if (isAsync) { - this.addNunjucksAsyncShortcode(name, callback); - } else { - name = this.getNamespacedName(name); - - if (this.nunjucksShortcodes[name]) { - debug( - chalk.yellow( - "Warning, overwriting a Nunjucks Shortcode with `addNunjucksShortcode(%o)`" - ), - name - ); - } - - this.nunjucksShortcodes[name] = bench.add( - `"${name}" Nunjucks Shortcode`, - callback - ); - } - } - addLiquidShortcode(name, callback) { name = this.getNamespacedName(name); @@ -556,52 +537,37 @@ class UserConfig { "Adding universal async paired shortcode %o", this.getNamespacedName(name) ); - this.addPairedNunjucksAsyncShortcode(name, callback); + + // as of 1.0.0-beta.9 and #1749 we don’t need to distinguish between async/sync shortcodes now + this.addPairedNunjucksShortcode(name, callback); this.addPairedLiquidShortcode(name, callback); this.addJavaScriptFunction(name, callback); // not supported in Handlebars } + // DEPRECATED, with 1.0.0-beta.9 and #1749 we don’t need to distinguish between async/sync shortcodes now addPairedNunjucksAsyncShortcode(name, callback) { + this.addPairedNunjucksShortcode(name, callback); + } + + addPairedNunjucksShortcode(name, callback) { name = this.getNamespacedName(name); - if (this.nunjucksAsyncPairedShortcodes[name]) { + if (this.nunjucksPairedShortcodes[name]) { debug( chalk.yellow( - "Warning, overwriting a Nunjucks Async Paired Shortcode with `addPairedNunjucksAsyncShortcode(%o)`" + "Warning, overwriting a Nunjucks Paired Shortcode with `addPairedNunjucksShortcode(%o)`" ), name ); } - this.nunjucksAsyncPairedShortcodes[name] = bench.add( - `"${name}" Nunjucks Async Paired Shortcode`, + this.nunjucksPairedShortcodes[name] = bench.add( + `"${name}" Nunjucks Paired Shortcode`, callback ); } - addPairedNunjucksShortcode(name, callback, isAsync = false) { - if (isAsync) { - this.addPairedNunjucksAsyncShortcode(name, callback); - } else { - name = this.getNamespacedName(name); - - if (this.nunjucksPairedShortcodes[name]) { - debug( - chalk.yellow( - "Warning, overwriting a Nunjucks Paired Shortcode with `addPairedNunjucksShortcode(%o)`" - ), - name - ); - } - - this.nunjucksPairedShortcodes[name] = bench.add( - `"${name}" Nunjucks Paired Shortcode`, - callback - ); - } - } - addPairedLiquidShortcode(name, callback) { name = this.getNamespacedName(name); @@ -741,9 +707,7 @@ class UserConfig { nunjucksAsyncFilters: this.nunjucksAsyncFilters, nunjucksTags: this.nunjucksTags, nunjucksGlobals: this.nunjucksGlobals, - nunjucksAsyncShortcodes: this.nunjucksAsyncShortcodes, nunjucksShortcodes: this.nunjucksShortcodes, - nunjucksAsyncPairedShortcodes: this.nunjucksAsyncPairedShortcodes, nunjucksPairedShortcodes: this.nunjucksPairedShortcodes, handlebarsHelpers: this.handlebarsHelpers, handlebarsShortcodes: this.handlebarsShortcodes, From eca09250a1414fb0d19febc005e532a174338390 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 20 Nov 2021 15:30:13 -0600 Subject: [PATCH 647/746] =?UTF-8?q?Adds=20`setAsync`=20Nunjucks=20shortcod?= =?UTF-8?q?e.=20`set`=20isn=E2=80=99t=20async=20friendly.=20Restores=20`th?= =?UTF-8?q?is.ctx`=20in=20Nunjucks=20shortcodes.=20Fixes=20#2108.=20Fixes?= =?UTF-8?q?=20#1584.=20Fixes=20#1596.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Engines/Nunjucks.js | 7 +++++++ src/Plugins/RenderPlugin.js | 1 + test/TemplateRenderPluginTest.js | 9 +++++++++ test/stubs-render-plugin/capture-liquid.njk | 11 +++++++++++ 4 files changed, 28 insertions(+) create mode 100644 test/stubs-render-plugin/capture-liquid.njk diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 4295e252f..e17e51199 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -155,6 +155,12 @@ class Nunjucks extends TemplateEngine { this.addFilters(this.config.nunjucksAsyncFilters, true); // TODO these all go to the same place (addTag), add warnings for overwrites + // TODO(zachleat): variableName should work with quotes or without quotes (same as {% set %}) + this.addPairedShortcode("setAsync", function (content, variableName) { + this.ctx[variableName] = content; + return ""; + }); + this.addCustomTags(this.config.nunjucksTags); this.addAllShortcodes(this.config.nunjucksShortcodes); this.addAllPairedShortcodes(this.config.nunjucksPairedShortcodes); @@ -211,6 +217,7 @@ class Nunjucks extends TemplateEngine { static _normalizeShortcodeContext(context) { let obj = {}; if (context.ctx && context.ctx.page) { + obj.ctx = context.ctx; obj.page = context.ctx.page; } return obj; diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 19284c899..1d7e4ea7c 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -193,6 +193,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { let normalizedContext = {}; if (context.ctx && context.ctx.page) { + normalizedContext.ctx = context.ctx; normalizedContext.page = context.ctx.page; } diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index 75470820d..d42abc4e5 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -200,3 +200,12 @@ test("Capture nunjucks render output to a liquid variable", async (t) => { ); t.is(html, `4`); }); + +// Idea from https://twitter.com/raymondcamden/status/1460961620247650312 +// Possibly blocked by async in {% set %} https://github.com/mozilla/nunjucks/issues/815 +test("Capture liquid render output to a njk variable", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/capture-liquid.njk" + ); + t.is(html, `4`); +}); diff --git a/test/stubs-render-plugin/capture-liquid.njk b/test/stubs-render-plugin/capture-liquid.njk new file mode 100644 index 000000000..e400dfd5e --- /dev/null +++ b/test/stubs-render-plugin/capture-liquid.njk @@ -0,0 +1,11 @@ +--- +argData: + num: 2 +--- +{% setAsync "liquidOutput" %} +{% renderTemplate "liquid", argData %} +{% assign liquidVar = num | times: 2 %} +{{ liquidVar }} +{% endrenderTemplate %} +{% endsetAsync %} +{{ liquidOutput }} \ No newline at end of file From 7a64e3f48e5a62cbdc17255fda3a8a1d0c09aa29 Mon Sep 17 00:00:00 2001 From: dgrammatiko Date: Sat, 20 Nov 2021 23:17:26 +0100 Subject: [PATCH 648/746] My Signed Commit Signed-off-by: dgrammatiko --- package.json | 2 +- src/TemplateConfig.js | 4 ++-- src/UserConfig.js | 2 +- src/Util/ConsoleLogger.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 33ef68260..332ea2edd 100755 --- a/package.json +++ b/package.json @@ -96,7 +96,6 @@ "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.7", - "chalk": "^4.1.2", "chokidar": "^3.5.2", "debug": "^4.3.2", "dependency-graph": "^0.11.0", @@ -106,6 +105,7 @@ "hamljs": "^0.6.2", "handlebars": "^4.7.7", "is-glob": "^4.0.3", + "kleur": "^4.1.4 ", "liquidjs": "^9.28.5", "lodash": "^4.17.21", "luxon": "^2.1.1", diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index adbd99cbe..dc4f102dc 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -1,5 +1,5 @@ const fs = require("fs"); -const chalk = require("chalk"); +const chalk = require("kleur"); const lodashUniq = require("lodash/uniq"); const lodashMerge = require("lodash/merge"); const TemplatePath = require("./TemplatePath"); @@ -238,7 +238,7 @@ class TemplateConfig { throw new EleventyConfigError( `Error in your Eleventy config file '${path}'.` + (err.message && err.message.includes("Cannot find module") - ? chalk.blueBright(" You may need to run `npm install`.") + ? chalk.cyan(" You may need to run `npm install`.") : ""), err ); diff --git a/src/UserConfig.js b/src/UserConfig.js index 6f682a061..fea641d74 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -1,4 +1,4 @@ -const chalk = require("chalk"); +const chalk = require("kleur"); const semver = require("semver"); const { DateTime } = require("luxon"); const EventEmitter = require("./Util/AsyncEventEmitter"); diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 40825a5f7..68bc50379 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -1,4 +1,4 @@ -const chalk = require("chalk"); +const chalk = require("kleur"); const debug = require("debug")("Eleventy:Logger"); const Readable = require("stream").Readable; From 85213cc5fa5fcb595eddce629f249f458c6132f9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 20 Nov 2021 23:20:51 -0600 Subject: [PATCH 649/746] Revert the thing --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6715151a3..cfe97dcfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} - cache: npm + # cache: npm - run: npm install - run: npm test env: From d4a7d67b6b82ccf0e5a77c1a3530f09a9b5fef65 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 22 Nov 2021 10:35:10 -0600 Subject: [PATCH 650/746] One more test from #2090 --- src/Engines/Liquid.js | 2 +- test/TemplateRenderLiquidTest.js | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 1e2259895..85ac8bc44 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -232,7 +232,7 @@ class Liquid extends TemplateEngine { // Required for relative includes let options = {}; - if (!inputPath || inputPath === "njk" || inputPath === "md") { + if (!inputPath || inputPath === "liquid" || inputPath === "md") { // do nothing } else { options.root = [TemplatePath.getDirFromFilePath(inputPath)]; diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 0bbe0e431..78cdc16fa 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -79,7 +79,7 @@ test("Liquid Render Include", async (t) => { t.is(await fn(), "

This is an include.

"); }); -test("Liquid Render Relative Include", async (t) => { +test("Liquid Render Relative Include (dynamicPartials off)", async (t) => { t.is( getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), "liquid" @@ -91,10 +91,24 @@ test("Liquid Render Relative Include", async (t) => { }, }); + // Important note: when inputPath is set to `liquid`, this *only* uses _includes relative paths in Liquid->compile let fn = await tr.getCompiledTemplate("

{% include ./included %}

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

This is an include.

"); }); +test("Liquid Render Relative Include (dynamicPartials on)", async (t) => { + t.is( + getNewTemplateRender("liquid", "./test/stubs/").getEngineName(), + "liquid" + ); + + let tr = await getNewTemplateRender("liquid", "./test/stubs/"); + + // Important note: when inputPath is set to `liquid`, this *only* uses _includes relative paths in Liquid->compile + let fn = await tr.getCompiledTemplate("

{% include './included' %}

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

This is an include.

"); +}); + test("Liquid Render Relative (current dir) Include", async (t) => { let tr = await getNewTemplateRender( "./test/stubs/relative-liquid/does_not_exist_and_thats_ok.liquid", From f6a1def0dca70a52bad80b9dfefc289bc8aa981d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 6 Dec 2021 09:57:02 -0600 Subject: [PATCH 651/746] Using a Vue renderFile inside of serverPrefetch caused a missing `page.url` error when it tried to add the component to the CSS. --- test/TemplateRenderPluginTest.js | 19 +++++++++- test/Util/removeNewLines.js | 5 +++ .../_includes/include.vue | 17 +++++++++ test/stubs-render-plugin-vue-nested/test.vue | 38 +++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 test/Util/removeNewLines.js create mode 100644 test/stubs-render-plugin-vue-nested/_includes/include.vue create mode 100644 test/stubs-render-plugin-vue-nested/test.vue diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index d42abc4e5..7bc9f9b9d 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -4,6 +4,7 @@ const VuePlugin = require("@11ty/eleventy-plugin-vue"); const Eleventy = require("../src/Eleventy"); const normalizeNewLines = require("./Util/normalizeNewLines"); +const removeNewLines = require("./Util/removeNewLines"); async function getTestOutput(input, configCallback = function () {}) { let elev = new Eleventy(input, "./_site/", { @@ -108,7 +109,6 @@ test("Use vue in liquid", async (t) => { t.is(html, `
HELLO WE ARE VUEING

liquidHi

`); }); -// Skip until we can get this working on Windows test("Use vue SFC file in liquid", async (t) => { // We point this to a directory instead of a single input file because the Eleventy Vue plugin needs // to be able to find the Vue SFC files too (and won’t if we point to a single input vue file) @@ -209,3 +209,20 @@ test("Capture liquid render output to a njk variable", async (t) => { ); t.is(html, `4`); }); + +test("Using a Vue renderFile inside of serverPrefetch (or `data`): Vue -> Liquid -> Markdown -> Vue", async (t) => { + // We point this to a directory instead of a single input file because the Eleventy Vue plugin needs + // to be able to find the Vue SFC files too (and won’t if we point to a single input vue file) + let result = await getTestOutput( + "./test/stubs-render-plugin-vue-nested/", + function (eleventyConfig) { + eleventyConfig.addPlugin(VuePlugin); + } + ); + + let html = removeNewLines(result[0].content.trim()); + t.is( + html, + `

This is 1.

2

` + ); +}); diff --git a/test/Util/removeNewLines.js b/test/Util/removeNewLines.js new file mode 100644 index 000000000..eef56384e --- /dev/null +++ b/test/Util/removeNewLines.js @@ -0,0 +1,5 @@ +function removeNewLines(str) { + return str.replace(/[\r\n]*/g, ""); +} + +module.exports = removeNewLines; diff --git a/test/stubs-render-plugin-vue-nested/_includes/include.vue b/test/stubs-render-plugin-vue-nested/_includes/include.vue new file mode 100644 index 000000000..47f9ba925 --- /dev/null +++ b/test/stubs-render-plugin-vue-nested/_includes/include.vue @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/test/stubs-render-plugin-vue-nested/test.vue b/test/stubs-render-plugin-vue-nested/test.vue new file mode 100644 index 000000000..d594b90ff --- /dev/null +++ b/test/stubs-render-plugin-vue-nested/test.vue @@ -0,0 +1,38 @@ + + + \ No newline at end of file From 8cd56801d3f4c86b60936eee493267f33f90c282 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 10 Dec 2021 14:02:42 -0600 Subject: [PATCH 652/746] Report from @akardet about getData functions being able to mutate config javascriptFunctions (no thank you) Manifested in Vue plugin when `data` function `this.X` assignment polluted global Vue methods. --- src/Engines/Custom.js | 3 +- src/Engines/JavaScript.js | 3 +- test/TemplateRenderCustomTest.js | 50 ++++++++++++++++++++++++++++ test/stubs-custom-extension/test.js1 | 1 + 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 test/stubs-custom-extension/test.js1 diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 408cc9504..5d5b70c1e 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -87,7 +87,8 @@ class CustomEngine extends TemplateEngine { let inst = await this.entry.getInstanceFromInputPath(inputPath); let mixins; if (this.config) { - mixins = this.config.javascriptFunctions; + // Object.assign usage: see TemplateRenderCustomTest.js: `JavaScript functions should not be mutable but not *that* mutable` + mixins = Object.assign({}, this.config.javascriptFunctions); } // override keys set at the plugin level in the individual template diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index a76870b57..5b0c782b6 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -91,7 +91,7 @@ class JavaScript extends TemplateEngine { async getExtraDataFromFile(inputPath) { let inst = this.getInstanceFromInputPath(inputPath); - return await getJavaScriptData(inst, inputPath); + return getJavaScriptData(inst, inputPath); } getJavaScriptFunctions(inst) { @@ -103,6 +103,7 @@ class JavaScript extends TemplateEngine { if (key === "page") { // do nothing } else { + // note: bind creates a new function fns[key] = configFns[key].bind(inst); } } diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index 375f0d969..2e35eb394 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -1,7 +1,9 @@ const test = require("ava"); +const TemplateData = require("../src/TemplateData"); const TemplateRender = require("../src/TemplateRender"); const EleventyExtensionMap = require("../src/EleventyExtensionMap"); const TemplateConfig = require("../src/TemplateConfig"); +const getNewTemplate = require("./_getNewTemplateForTests"); const { createSSRApp } = require("vue"); const { renderToString } = require("@vue/server-renderer"); @@ -165,3 +167,51 @@ test("Custom Sass Render", async (t) => { }` ); }); + +/* +serverPrefetch: function() { + return this.getBlogAuthors().then(response => this.glossary = response) + }, +*/ +test("JavaScript functions should not be mutable but not *that* mutable", async (t) => { + t.plan(3); + + let eleventyConfig = new TemplateConfig(); + + let instance = { + dataForCascade: function () { + // was mutating this.config.javascriptFunctions! + this.shouldnotmutatethething = 1; + return {}; + }, + }; + + eleventyConfig.userConfig.extensionMap.add({ + extension: "js1", + key: "js1", + getData: ["dataForCascade"], + getInstanceFromInputPath: function (inputPath) { + t.truthy(true); + return instance; + }, + compile: function (str, inputPath) { + t.falsy(this.config.javascriptFunctions.shouldnotmutatethething); + + // plaintext + return (data) => { + return str; + }; + }, + }); + + let tmpl = getNewTemplate( + "./test/stubs-custom-extension/test.js1", + "./test/stubs-custom-extension/", + "dist", + null, + null, + eleventyConfig + ); + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "

Paragraph

"); +}); diff --git a/test/stubs-custom-extension/test.js1 b/test/stubs-custom-extension/test.js1 new file mode 100644 index 000000000..38addeaad --- /dev/null +++ b/test/stubs-custom-extension/test.js1 @@ -0,0 +1 @@ +

Paragraph

\ No newline at end of file From 4a79e85bf0361e80922ebb5b414fbf37dc1c18dd Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 10 Dec 2021 14:18:20 -0600 Subject: [PATCH 653/746] 1.0.0-canary.45 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 332ea2edd..7d99c5756 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.8", + "version": "1.0.0-canary.45", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 3537bfe93edcd9e76037da8c44a4d271beb4b4d7 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 10 Dec 2021 17:01:23 -0600 Subject: [PATCH 654/746] Clearn code for init --- src/Engines/Custom.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 5d5b70c1e..ce4c008d6 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -8,8 +8,6 @@ class CustomEngine extends TemplateEngine { this.entry = this.getExtensionMapEntry(); this.needsInit = "init" in this.entry && typeof this.entry.init === "function"; - this.initStarted = false; - this.initFinished = false; this._defaultEngine = undefined; } @@ -43,13 +41,10 @@ class CustomEngine extends TemplateEngine { // before continuing on. async _runningInit() { if (this.needsInit) { - if (this.initStarted) { - await this.initStarted; - } else if (!this.initFinished) { - this.initStarted = this.entry.init.bind({ config: this.config })(); - await this.initStarted; - this.initFinished = true; + if (!this._initing) { + this._initing = this.entry.init.bind({ config: this.config })(); } + await this._initing; } } From f04f9791db8e2d22514004ee0db9e990f6d8f4e8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 10 Dec 2021 17:02:02 -0600 Subject: [PATCH 655/746] =?UTF-8?q?RenderPlugin=20should=20reuse=20the=20e?= =?UTF-8?q?xisting=20extension=20map=20or=20it=20will=20re-initialize=20ne?= =?UTF-8?q?w=20Engine=20instances=20every=20time=E2=80=94this=20was=20bad?= =?UTF-8?q?=20for=20performance.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Eleventy.js | 1 + src/Plugins/RenderPlugin.js | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 6d3c9187a..ce51f862b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -326,6 +326,7 @@ class Eleventy { let formats = this.formatsOverride || this.config.templateFormats; this.extensionMap = new EleventyExtensionMap(formats, this.eleventyConfig); + await this.config.events.emit("eleventy.extensionmap", this.extensionMap); this.eleventyFiles = new EleventyFiles( this.inputDir, diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 1d7e4ea7c..06cf5f6b0 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -1,4 +1,3 @@ -const path = require("path"); const fs = require("fs"); const fsp = fs.promises; @@ -22,7 +21,7 @@ async function render( content, templateLang = "html", normalizedDirs = {}, - templateConfig + { templateConfig, extensionMap } ) { if (!templateConfig) { templateConfig = new TemplateConfig(); @@ -33,6 +32,7 @@ async function render( normalizedDirs.input, templateConfig ); + tr.extensionMap = extensionMap; tr.setEngineOverride(templateLang); // TODO tie this to the class, not the extension @@ -50,7 +50,7 @@ async function renderFile( inputPath, templateLang, normalizedDirs = {}, - templateConfig + { templateConfig, extensionMap } ) { if (!inputPath) { throw new Error( @@ -72,6 +72,7 @@ async function renderFile( } let tr = new TemplateRender(inputPath, normalizedDirs.input, templateConfig); + tr.extensionMap = extensionMap; if (templateLang) { tr.setEngineOverride(templateLang); } @@ -248,13 +249,21 @@ function EleventyPlugin(eleventyConfig, options = {}) { templateConfig = cfg; }); + let extensionMap; + eleventyConfig.on("eleventy.extensionmap", (map) => { + extensionMap = map; + }); + async function renderStringShortcodeFn(content, templateLang, data = {}) { let fn = await render.call( this, content, templateLang, normalizeDirectories(eleventyConfig.dir), - templateConfig + { + templateConfig, + extensionMap, + } ); // save `page` for reuse @@ -269,7 +278,10 @@ function EleventyPlugin(eleventyConfig, options = {}) { inputPath, templateLang, normalizeDirectories(eleventyConfig.dir), - templateConfig + { + templateConfig, + extensionMap, + } ); // save `page` for re-use From 4a505f169a5e0cd087eb5ae25e2c23b8bcd2e060 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 10 Dec 2021 17:02:19 -0600 Subject: [PATCH 656/746] v1.0.0-canary.46 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d99c5756..ad3cabfe8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.45", + "version": "1.0.0-canary.46", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 05906505268c4c3bbba73dced229db8010b67114 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 17 Dec 2021 20:31:51 -0600 Subject: [PATCH 657/746] Better aggregate benchmark output. renderPermalink should never have markdown. Faster/simpler template agnostic permalink as a function --- src/BenchmarkGroup.js | 35 ++++++++++++------------ src/Engines/Custom.js | 23 ++++++++++++++-- src/Template.js | 9 +++--- src/TemplateContent.js | 62 ++++++++++++++++++++++++++++++++++++++---- src/TemplateWriter.js | 2 +- test/TemplateTest.js | 16 +++++++++++ 6 files changed, 115 insertions(+), 32 deletions(-) diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index d986dcefb..deb7f64dd 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -73,29 +73,28 @@ class BenchmarkGroup { return this.benchmarks[type]; } + padNumber(num, length) { + if (("" + num).length >= length) { + return num; + } + + let prefix = new Array(length + 1).join(" "); + return (prefix + num).substr(-1 * length); + } + finish(label, totalTimeSpent) { for (var type in this.benchmarks) { let bench = this.benchmarks[type]; let isAbsoluteMinimumComparison = this.minimumThresholdMs > 0; let totalForBenchmark = bench.getTotal(); - let percent = (totalForBenchmark * 100) / totalTimeSpent; - - let extraOutput = []; - if (!isAbsoluteMinimumComparison) { - extraOutput.push(`${percent.toFixed(1)}%`); - } - let timesCalledCount = bench.getTimesCalled(); - if (timesCalledCount > 1) { - extraOutput.push(`called ${timesCalledCount}×`); - extraOutput.push( - `${(totalForBenchmark / timesCalledCount).toFixed(1)}ms each` - ); - } - - // TODO move the % to the beginning of the string for easier comparison - let str = `Benchmark (${label}): ${type} took ${totalForBenchmark.toFixed( - 0 - )}ms ${extraOutput.length ? `(${extraOutput.join(", ")})` : ""}`; + let percent = Math.round((totalForBenchmark * 100) / totalTimeSpent); + + let output = { + ms: this.padNumber(totalForBenchmark.toFixed(0), 6), + percent: this.padNumber(percent, 3), + calls: this.padNumber(bench.getTimesCalled(), 5), + }; + let str = `Benchmark ${output.ms}ms ${output.percent}% ${output.calls}× (${label}) ${type}`; if ( (isAbsoluteMinimumComparison && diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index ce4c008d6..c7a40d74d 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -1,5 +1,6 @@ const TemplateEngine = require("./TemplateEngine"); const getJavaScriptData = require("../Util/GetJavaScriptData"); +const bench = require("../BenchmarkManager").get("Aggregate"); class CustomEngine extends TemplateEngine { constructor(name, dirs, config) { @@ -41,10 +42,17 @@ class CustomEngine extends TemplateEngine { // before continuing on. async _runningInit() { if (this.needsInit) { + let initBench = bench.get(`Engine (${this.name}) Init`); + initBench.before(); if (!this._initing) { - this._initing = this.entry.init.bind({ config: this.config })(); + this._initing = this.entry.init.bind({ + config: this.config, + bench, + })(); } await this._initing; + this.needsInit = false; + initBench.after(); } } @@ -52,10 +60,16 @@ class CustomEngine extends TemplateEngine { await this._runningInit(); if ("getData" in this.entry) { + let dataBench = bench.get(`Engine (${this.name}) Get Data From File`); + dataBench.before(); + if (typeof this.entry.getData === "function") { - return this.entry.getData(inputPath); + let data = this.entry.getData(inputPath); + dataBench.after(); + return data; } else { if (!("getInstanceFromInputPath" in this.entry)) { + dataBench.after(); return Promise.reject( new Error( `getInstanceFromInputPath callback missing from ${this.name} template engine plugin.` @@ -71,7 +85,9 @@ class CustomEngine extends TemplateEngine { keys.add(key); } } + if (keys.size === 0) { + dataBench.after(); return Promise.reject( new Error( `getData must be an array of keys or \`true\` in your addExtension configuration.` @@ -106,6 +122,7 @@ class CustomEngine extends TemplateEngine { for (let result of results) { Object.assign(data, result); } + dataBench.after(); return data; } @@ -123,7 +140,7 @@ class CustomEngine extends TemplateEngine { inputPath, ...args ); - return await render(data); + return render(data); }; } diff --git a/src/Template.js b/src/Template.js index 3dc6f6074..a30842202 100755 --- a/src/Template.js +++ b/src/Template.js @@ -219,12 +219,12 @@ class Template extends TemplateContent { promises.push( Promise.all( [...permalink[key]].map((entry) => - super.renderPermalink(entry, data, true) + super.renderPermalink(entry, data) ) ) ); } else { - promises.push(super.renderPermalink(permalink[key], data, true)); + promises.push(super.renderPermalink(permalink[key], data)); } } @@ -245,7 +245,7 @@ class Template extends TemplateContent { } } else if (permalink) { // render variables inside permalink front matter, bypass markdown - permalinkValue = await super.renderPermalink(permalink, data, true); + permalinkValue = await super.renderPermalink(permalink, data); debug( "Rendering permalink for %o: %s becomes %o", this.inputPath, @@ -471,8 +471,6 @@ class Template extends TemplateContent { return super.render(str, data, bypassMarkdown); } - // TODO at least some of this isn’t being used in the normal build - // Render is used for `renderData` and `permalink` but otherwise `renderPageEntry` is being used async render(data) { debugDev("%o render()", this.inputPath); if (!data) { @@ -998,6 +996,7 @@ class Template extends TemplateContent { } } + /* This is the primary render mechanism, called via TemplateMap->populateContentDataInMap */ async getTemplateMapContent(pageMapEntry) { pageMapEntry.template.setWrapWithLayouts(false); let content = await pageMapEntry.template.render(pageMapEntry.data); diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 6380d450c..547f82489 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -266,8 +266,13 @@ class TemplateContent { } let templateBenchmark = bench.get("Template Compile"); + let inputPathBenchmark = bench.get( + `> Template Compile > ${this.inputPath}` + ); templateBenchmark.before(); + inputPathBenchmark.before(); let fn = await this.templateRender.getCompiledTemplate(str); + inputPathBenchmark.after(); templateBenchmark.after(); debugDev("%o getCompiledTemplate function created", this.inputPath); if (this.config.useTemplateCache && res) { @@ -295,12 +300,33 @@ class TemplateContent { } } + // used by computed data or for permalink functions + async _renderFunction(fn, data) { + let mixins = Object.assign({}, this.config.javascriptFunctions); + let result = await fn.call(mixins, data); + + // normalize Buffer away if returned from permalink + if (Buffer.isBuffer(result)) { + return result.toString(); + } + + return result; + } + async renderComputedData(str, data) { + if (typeof str === "function") { + return this._renderFunction(str, data); + } + return this._render(str, data, true); } - async renderPermalink(permalink, data, bypassMarkdown) { - return this._render(permalink, data, bypassMarkdown); + async renderPermalink(permalink, data) { + if (typeof permalink === "function") { + return this._renderFunction(permalink, data); + } + + return this._render(permalink, data, true); } async render(str, data, bypassMarkdown) { @@ -310,9 +336,32 @@ class TemplateContent { async _render(str, data, bypassMarkdown) { try { let fn = await this.compile(str, bypassMarkdown); - let templateBenchmark = bench.get("Template Render"); + let templateBenchmark = bench.get("Render"); + let inputPathBenchmark = bench.get( + `> Render > ${this.inputPath}${ + "pagination" in data ? " (Paginated Aggregate)" : "" + }` + ); + let outputUrlBenchmark; + if ("pagination" in data) { + outputUrlBenchmark = bench.get( + `> Render > ${this.inputPath} (Pagination) to ${data.page.url}` + ); + } templateBenchmark.before(); + if (inputPathBenchmark) { + inputPathBenchmark.before(); + } + if (outputUrlBenchmark) { + outputUrlBenchmark.before(); + } let rendered = await fn(data); + if (outputUrlBenchmark) { + outputUrlBenchmark.after(); + } + if (inputPathBenchmark) { + inputPathBenchmark.after(); + } templateBenchmark.after(); debugDev( "%o getCompiledTemplate called, rendered content created", @@ -347,7 +396,6 @@ class TemplateContent { return true; } - let incrementalFileIsFullTemplate = metadata.incrementalFileIsFullTemplate; let extensionEntries = this.getExtensionEntries().filter( (entry) => !!entry.isIncrementalMatch ); @@ -364,10 +412,14 @@ class TemplateContent { return true; } } + + return false; } else { + // This is the fallback way of determining if something is incremental (no isIncrementalMatch available) + // Not great way of building all templates if this is a layout, include, JS dependency. // TODO improve this for default langs - if (!incrementalFileIsFullTemplate) { + if (!metadata.isFullTemplate) { return true; } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index ffda9f977..2dbc1ee35 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -204,7 +204,7 @@ class TemplateWriter { // Passthrough copy check is above this (order is important) } else if ( tmpl.isFileRelevantToThisTemplate(this.incrementalFile, { - incrementalFileIsFullTemplate: this.eleventyFiles.isFullTemplateFile( + isFullTemplate: this.eleventyFiles.isFullTemplateFile( allPaths, this.incrementalFile ), diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 81571ac56..19ce29f74 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2048,6 +2048,22 @@ test("Add Extension via Configuration (txt file)", async (t) => { t.truthy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default.txt")); t.falsy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default2.txt")); t.falsy(tmpl.isFileRelevantToThisTemplate("./test/stubs/default.njk")); + + t.truthy( + tmpl.isFileRelevantToThisTemplate("./test/stubs/default.txt", { + isFullTemplate: true, + }) + ); + t.falsy( + tmpl.isFileRelevantToThisTemplate("./test/stubs/default2.txt", { + isFullTemplate: true, + }) + ); + t.falsy( + tmpl.isFileRelevantToThisTemplate("./test/stubs/default.njk", { + isFullTemplate: true, + }) + ); }); test("permalink object with build", async (t) => { From 3feff6dedca97a188c2b4ce383895ea23107ca5f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 17 Dec 2021 21:27:17 -0600 Subject: [PATCH 658/746] Improvements to per-template benchmarks --- src/TemplateContent.js | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 547f82489..2e0ea949e 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -337,28 +337,30 @@ class TemplateContent { try { let fn = await this.compile(str, bypassMarkdown); let templateBenchmark = bench.get("Render"); - let inputPathBenchmark = bench.get( - `> Render > ${this.inputPath}${ - "pagination" in data ? " (Paginated Aggregate)" : "" - }` - ); - let outputUrlBenchmark; + let paginationSuffix = []; if ("pagination" in data) { - outputUrlBenchmark = bench.get( - `> Render > ${this.inputPath} (Pagination) to ${data.page.url}` - ); + paginationSuffix.push(" (Pagination"); + if (data.pagination.pages) { + paginationSuffix.push( + `: ${data.pagination.pages.length} page${ + data.pagination.pages.length !== 1 ? "s" : "" + }` + ); + } + paginationSuffix.push(")"); } + + let inputPathBenchmark = bench.get( + `> Render > ${this.inputPath}${paginationSuffix.join("")}` + ); + templateBenchmark.before(); if (inputPathBenchmark) { inputPathBenchmark.before(); } - if (outputUrlBenchmark) { - outputUrlBenchmark.before(); - } + let rendered = await fn(data); - if (outputUrlBenchmark) { - outputUrlBenchmark.after(); - } + if (inputPathBenchmark) { inputPathBenchmark.after(); } From ee08fe6181b23ddb1e1f1141b7a0e48231944522 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 17 Dec 2021 21:29:22 -0600 Subject: [PATCH 659/746] Adds compileOptions support to addExtension API for better control of internal caching. compileOptions: { cache: true permalink: false, getCacheKey: function(str, inputPath) { return str; } } --- src/Engines/Custom.js | 29 +++++++++++++++++++++++++++++ src/Engines/JavaScript.js | 2 ++ src/Engines/Liquid.js | 10 ++++------ src/Engines/Nunjucks.js | 10 ++++------ src/Engines/TemplateEngine.js | 8 ++++++++ src/Template.js | 4 ++++ src/TemplateContent.js | 32 +++++++++++++++++++++++++++++--- src/TemplateMap.js | 2 ++ 8 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index c7a40d74d..e958be0e1 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -11,6 +11,11 @@ class CustomEngine extends TemplateEngine { "init" in this.entry && typeof this.entry.init === "function"; this._defaultEngine = undefined; + + // Enable cacheability for this template + if (this.entry.compileOptions && "cache" in this.entry.compileOptions) { + this.cacheable = this.entry.compileOptions.cache; + } } getExtensionMapEntry() { @@ -161,6 +166,30 @@ class CustomEngine extends TemplateEngine { get defaultTemplateFileExtension() { return this.entry.outputFileExtension; } + + getCompileCacheKey(str, inputPath) { + if ( + this.entry.compileOptions && + "getCacheKey" in this.entry.compileOptions + ) { + if (typeof this.entry.compileOptions.getCacheKey !== "function") { + throw new Error( + `\`compileOptions.getCacheKey\` must be a function in addExtension for the ${this.name} type` + ); + } + + return this.entry.compileOptions.getCacheKey(str, inputPath); + } + return super.getCompileCacheKey(str, inputPath); + } + + permalinkNeedsCompilation(str) { + if (this.entry.compileOptions && "permalink" in this.entry.compileOptions) { + return this.entry.compileOptions.permalink; + } + + return true; + } } module.exports = CustomEngine; diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 5b0c782b6..625c6d202 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -10,6 +10,8 @@ class JavaScript extends TemplateEngine { constructor(name, dirs, config) { super(name, dirs, config); this.instances = {}; + + this.cacheable = false; } normalize(result) { diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 85ac8bc44..071315ddc 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -211,6 +211,10 @@ class Liquid extends TemplateEngine { return symbols; } + permalinkNeedsCompilation(str) { + return this.needsCompilation(str); + } + needsCompilation(str) { let options = this.liquidLib.options; @@ -221,12 +225,6 @@ class Liquid extends TemplateEngine { } async compile(str, inputPath) { - if (!this.needsCompilation(str)) { - return async function (data) { - return str; - }; - } - let engine = this.liquidLib; let tmplReady = engine.parse(str, inputPath); diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index e17e51199..2f196332b 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -338,6 +338,10 @@ class Nunjucks extends TemplateEngine { this.njkEnv.addExtension(shortcodeName, new fn()); } + permalinkNeedsCompilation(str) { + return this.needsCompilation(str); + } + needsCompilation(str) { // Defend against syntax customisations: // https://mozilla.github.io/nunjucks/api.html#customizing-syntax @@ -409,12 +413,6 @@ class Nunjucks extends TemplateEngine { } async compile(str, inputPath) { - if (!this.needsCompilation(str)) { - return async function () { - return str; - }; - } - // for(let loader of this.njkEnv.loaders) { // loader.cache = {}; // } diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 225d7abeb..04a417e1e 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -173,10 +173,18 @@ class TemplateEngine { // do nothing } + getCompileCacheKey(str, inputPath) { + return str; + } + get defaultTemplateFileExtension() { return "html"; } + permalinkNeedsCompilation(str) { + return this.needsCompilation(str); + } + // whether or not compile is needed or can we return the plaintext? needsCompilation(str) { return true; diff --git a/src/Template.js b/src/Template.js index a30842202..e7a0053ad 100755 --- a/src/Template.js +++ b/src/Template.js @@ -886,6 +886,10 @@ class Template extends TemplateContent { this.extensionMap, this.eleventyConfig ); + + // Avoid re-reads, especially for pagination + tmpl.setInputContent(this.inputContent); + tmpl.logger = this.logger; for (let transform of this.transforms) { diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 2e0ea949e..65ea44896 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -97,7 +97,11 @@ class TemplateContent { } async read() { - this.inputContent = await this.getInputContent(); + if (this.inputContent) { + await this.inputContent; + } else { + this.inputContent = await this.getInputContent(); + } if (this.inputContent) { let options = this.config.frontMatterParsingOptions || {}; @@ -149,11 +153,15 @@ class TemplateContent { this._inputCache.delete(TemplatePath.absolutePath(path)); } + // Used via clone + setInputContent(content) { + this.inputContent = content; + } + async getInputContent() { if (!this.engine.needsToReadFileContents()) { return ""; } - let templateBenchmark = bench.get("Template Read"); templateBenchmark.before(); let content; @@ -232,12 +240,20 @@ class TemplateContent { } let cacheable = this.engine.cacheable; - return [cacheable, str, engineMap]; + let key = this.engine.getCompileCacheKey(str, this.inputPath); + + return [cacheable, key, engineMap]; } async compile(str, bypassMarkdown) { await this.setupTemplateRender(bypassMarkdown); + if (bypassMarkdown && !this.engine.needsCompilation(str)) { + return async function () { + return str; + }; + } + debugDev( "%o compile() using engine: %o", this.inputPath, @@ -322,6 +338,12 @@ class TemplateContent { } async renderPermalink(permalink, data) { + if ( + typeof permalink === "string" && + !this.engine.permalinkNeedsCompilation(permalink) + ) { + return permalink; + } if (typeof permalink === "function") { return this._renderFunction(permalink, data); } @@ -335,6 +357,10 @@ class TemplateContent { async _render(str, data, bypassMarkdown) { try { + if (bypassMarkdown && !this.engine.needsCompilation(str)) { + return str; + } + let fn = await this.compile(str, bypassMarkdown); let templateBenchmark = bench.get("Render"); let paginationSuffix = []; diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 13f3e45e9..26fe76c8c 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -452,8 +452,10 @@ class TemplateMap { throw new Error(`Content pages not found for ${map.inputPath}`); } if (!map.template.behavior.isRenderable()) { + // Note that empty pagination templates will be skipped here as not renderable continue; } + try { for (let pageEntry of map._pages) { pageEntry.templateContent = await map.template.getTemplateMapContent( From d709b5f8512fb0718c01d187a4a14be76dbcf90b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 17 Dec 2021 21:35:37 -0600 Subject: [PATCH 660/746] =?UTF-8?q?Remap=20data=20to=20{=20=5F:=20data=20}?= =?UTF-8?q?=20if=20an=20object=20isn=E2=80=99t=20passed=20in=20to=20the=20?= =?UTF-8?q?render=20plugin.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Plugins/RenderPlugin.js | 17 ++++++++++++++++- test/TemplateRenderPluginTest.js | 7 +++++++ test/stubs-render-plugin/bad-data.njk | 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/stubs-render-plugin/bad-data.njk diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 06cf5f6b0..d59bc6ea2 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -1,7 +1,8 @@ const fs = require("fs"); const fsp = fs.promises; +const lodashIsPlainObject = require("lodash/isPlainObject"); -// TODO first-class Markdown container/component (will need to be synchronous for markdown-it) +// TODO add a first-class Markdown component to expose this using Markdown-only syntax (will need to be synchronous for markdown-it) const TemplatePath = require("../TemplatePath"); const TemplateRender = require("../TemplateRender"); @@ -266,6 +267,13 @@ function EleventyPlugin(eleventyConfig, options = {}) { } ); + // if the user passes a string or other literal, remap to an object. + if (!lodashIsPlainObject(data)) { + data = { + _: data, + }; + } + // save `page` for reuse data.page = this.page; @@ -284,6 +292,13 @@ function EleventyPlugin(eleventyConfig, options = {}) { } ); + // if the user passes a string or other literal, remap to an object. + if (!lodashIsPlainObject(data)) { + data = { + _: data, + }; + } + // save `page` for re-use data.page = this.page; diff --git a/test/TemplateRenderPluginTest.js b/test/TemplateRenderPluginTest.js index 7bc9f9b9d..c5959b0da 100644 --- a/test/TemplateRenderPluginTest.js +++ b/test/TemplateRenderPluginTest.js @@ -226,3 +226,10 @@ test("Using a Vue renderFile inside of serverPrefetch (or `data`): Vue -> Liquid `

This is 1.

2

` ); }); + +test("Remap non-object data to data._ if object is not passed in", async (t) => { + let html = await getTestOutputForFile( + "./test/stubs-render-plugin/bad-data.njk" + ); + t.is(html, "string"); +}); diff --git a/test/stubs-render-plugin/bad-data.njk b/test/stubs-render-plugin/bad-data.njk new file mode 100644 index 000000000..f3efcbcf5 --- /dev/null +++ b/test/stubs-render-plugin/bad-data.njk @@ -0,0 +1,3 @@ +{% renderTemplate "liquid", "string" %} +{{ _ }} +{% endrenderTemplate %} From e88bbe38cdfc751d2677679b22f8a74856cb449f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 18 Dec 2021 14:48:22 -0600 Subject: [PATCH 661/746] Fixes #2139. Also noticed there were a bunch of "utf-8" fs options that needed to be "utf8" --- package.json | 1 + src/EleventyFiles.js | 2 +- src/EleventyServe.js | 2 +- src/Engines/TemplateEngine.js | 2 +- src/Plugins/ServerlessBundlerPlugin.js | 2 +- src/Template.js | 10 +++++++--- src/TemplateContent.js | 6 ++++-- src/TemplateData.js | 2 +- test/TemplateWriterTest.js | 2 +- 9 files changed, 18 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index ad3cabfe8..0c36bda29 100755 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "dependency-graph": "^0.11.0", "ejs": "^3.1.6", "fast-glob": "^3.2.7", + "graceful-fs": "^4.2.8", "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index e3a1d6e99..bb2f78501 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -223,7 +223,7 @@ class EleventyFiles { let dir = TemplatePath.getDirFromFilePath(ignorePath); if (fs.existsSync(ignorePath) && fs.statSync(ignorePath).size > 0) { - let ignoreContent = fs.readFileSync(ignorePath, "utf-8"); + let ignoreContent = fs.readFileSync(ignorePath, "utf8"); ignores = ignores.concat( EleventyFiles.normalizeIgnoreContent(dir, ignoreContent) diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 145059d74..277b52895 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -101,7 +101,7 @@ class EleventyServe { return; } - let savedPathContent = fs.readFileSync(savedPathFilename, "utf-8"); + let savedPathContent = fs.readFileSync(savedPathFilename, "utf8"); if ( savedPathContent.indexOf("Browsersync pathPrefix Redirect") === -1 ) { diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 04a417e1e..7be86a2b7 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -131,7 +131,7 @@ class TemplateEngine { "." + extension ); }); - partials[partialPathNoExt] = fs.readFileSync(partialFiles[j], "utf-8"); + partials[partialPathNoExt] = fs.readFileSync(partialFiles[j], "utf8"); } debug( diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index e492c5dbc..815179f7c 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -272,7 +272,7 @@ class BundlerHelper { "./DefaultServerlessFunctionContent.js" ); - let contents = await fsp.readFile(defaultContentPath, "utf-8"); + let contents = await fsp.readFile(defaultContentPath, "utf8"); contents = contents.replace(/\%\%NAME\%\%/g, this.name); contents = contents.replace( /\%\%FUNCTIONS_DIR\%\%/g, diff --git a/src/Template.js b/src/Template.js index e7a0053ad..9c2b8781e 100755 --- a/src/Template.js +++ b/src/Template.js @@ -1,4 +1,8 @@ -const fs = require("fs"); +const fs = require("graceful-fs"); +const util = require("util"); +const writeFile = util.promisify(fs.writeFile); +const mkdir = util.promisify(fs.mkdir); + const os = require("os"); const path = require("path"); const normalize = require("normalize-path"); @@ -774,10 +778,10 @@ class Template extends TemplateContent { // TODO add a cache to check if this was already created let templateOutputDir = path.parse(outputPath).dir; if (templateOutputDir) { - await fs.promises.mkdir(templateOutputDir, { recursive: true }); + await mkdir(templateOutputDir, { recursive: true }); } - return fs.promises.writeFile(outputPath, finalContent).then(() => { + return writeFile(outputPath, finalContent).then(() => { templateBenchmark.after(); this.writeCount++; debug(`${outputPath} ${lang.finished}.`); diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 65ea44896..81c8e6202 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -1,5 +1,7 @@ const os = require("os"); -const fs = require("fs"); +const fs = require("graceful-fs"); +const util = require("util"); +const readFile = util.promisify(fs.readFile); const normalize = require("normalize-path"); const matter = require("gray-matter"); const lodashSet = require("lodash/set"); @@ -169,7 +171,7 @@ class TemplateContent { content = TemplateContent.getCached(this.inputPath); } if (!content) { - content = await fs.promises.readFile(this.inputPath, "utf-8"); + content = await readFile(this.inputPath, "utf8"); if (this.config.useTemplateCache) { TemplateContent.cache(this.inputPath, content); diff --git a/src/TemplateData.js b/src/TemplateData.js index ab5e4b360..a26b14c97 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -405,7 +405,7 @@ class TemplateData { async _loadFileContents(path) { let rawInput; try { - rawInput = await fs.promises.readFile(path, "utf-8"); + rawInput = await fs.promises.readFile(path, "utf8"); } catch (e) { // if file does not exist, return nothing } diff --git a/test/TemplateWriterTest.js b/test/TemplateWriterTest.js index 0af72e4b4..8670b0b9e 100644 --- a/test/TemplateWriterTest.js +++ b/test/TemplateWriterTest.js @@ -447,7 +447,7 @@ test("Pagination and TemplateContent", async (t) => { let content = fs.readFileSync( "./test/stubs/pagination-templatecontent/_site/index.html", - "utf-8" + "utf8" ); t.is( content.trim(), From b2e50a859a83e41b49c7db99c63f4823e72abb6b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 18 Dec 2021 19:44:31 -0600 Subject: [PATCH 662/746] Two skipped tests: one should throw an error, one is irrelevant --- test/TemplateRenderJavaScriptTest.js | 16 ---------------- test/TemplateTest.js | 13 ++++++++++--- test/stubs/function-filter-arrow.11ty.js | 3 --- 3 files changed, 10 insertions(+), 22 deletions(-) delete mode 100644 test/stubs/function-filter-arrow.11ty.js diff --git a/test/TemplateRenderJavaScriptTest.js b/test/TemplateRenderJavaScriptTest.js index 9ff8f51db..959398860 100644 --- a/test/TemplateRenderJavaScriptTest.js +++ b/test/TemplateRenderJavaScriptTest.js @@ -183,22 +183,6 @@ test("JS Render with a function", async (t) => { t.is(await fn({ name: "Bill", page: { url: "/hi/" } }), "

BILLT9000

"); }); -// This doesn’t work because arrow functions don’t do `this` -test.skip("Issue #934: JS Render with an arrow function and javascript function", async (t) => { - let tr = getNewTemplateRender("./test/stubs/function-filter-arrow.11ty.js"); - tr.config = { - javascriptFunctions: { - upper: function (val) { - return new String(val).toUpperCase(); - }, - }, - }; - - let fn = await tr.getCompiledTemplate(); - t.is(await fn({ name: "Zach" }), "

ZACH

"); - t.is(await fn({ name: "Bill" }), "

BILL

"); -}); - test("JS Render with a function and async filter", async (t) => { t.plan(4); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 19ce29f74..ef0ae06c9 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1740,15 +1740,22 @@ test("Throws a Premature Template Content Error (haml)", async (t) => { t.is(EleventyErrorUtil.isPrematureTemplateContentError(error), true); }); -test.skip("Issue 413 weird date format", async (t) => { +test("Issue 413 weird date format", async (t) => { let tmpl = getNewTemplate( "./test/stubs-413/date-frontmatter.md", "./test/stubs-413/", "./dist" ); - let data = await tmpl.getData(); - t.is(data.page.date, ""); + let error = await t.throwsAsync(async function () { + await tmpl.getData(); + }); + + t.truthy( + error.message.indexOf( + "date front matter value (2019-03-13 20:18:42 +0000) is invalid" + ) > -1 + ); }); test("Custom Front Matter Parsing Options", async (t) => { diff --git a/test/stubs/function-filter-arrow.11ty.js b/test/stubs/function-filter-arrow.11ty.js deleted file mode 100644 index d9adb2f05..000000000 --- a/test/stubs/function-filter-arrow.11ty.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = ({ name }) => { - return `

${this.upper(name)}

`; -}; From 3fa5293b7f54cf29365cc919cb330fc2ab6175ad Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 18 Dec 2021 19:44:43 -0600 Subject: [PATCH 663/746] v1.0.0-canary.47 --- docs/meta-release.md | 6 ++++++ package.json | 18 +++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/meta-release.md b/docs/meta-release.md index f93cf5071..90557b549 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -1,3 +1,9 @@ +# ESM dependency list + +- `lint-staged` ESM at 12.x +- `@sindresorhus/slugify` ESM at 2.x +- `multimatch` is ESM at 6 + # Canary Release Procedure 1. npmclean aka `rm -rf node_modules && rm -f package-lock.json && npm install` diff --git a/package.json b/package.json index 0c36bda29..6280cb8d5 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.46", + "version": "1.0.0-canary.47", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -78,16 +78,16 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", - "@vue/server-renderer": "^3.2.22", + "@vue/server-renderer": "^3.2.26", "ava": "^3.15.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", "markdown-it-emoji": "^2.0.0", "nyc": "^15.1.0", - "prettier": "^2.4.1", + "prettier": "^2.5.1", "rimraf": "^3.0.2", - "sass": "^1.43.4", + "sass": "^1.45.0", "toml": "^3.0.0", "vue": "^3.2.1" }, @@ -97,7 +97,7 @@ "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.7", "chokidar": "^3.5.2", - "debug": "^4.3.2", + "debug": "^4.3.3", "dependency-graph": "^0.11.0", "ejs": "^3.1.6", "fast-glob": "^3.2.7", @@ -107,10 +107,10 @@ "handlebars": "^4.7.7", "is-glob": "^4.0.3", "kleur": "^4.1.4 ", - "liquidjs": "^9.28.5", + "liquidjs": "^9.30.0", "lodash": "^4.17.21", - "luxon": "^2.1.1", - "markdown-it": "^12.2.0", + "luxon": "^2.2.0", + "markdown-it": "^12.3.0", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^5.0.0", @@ -123,7 +123,7 @@ "pug": "^3.0.2", "recursive-copy": "^2.0.13", "semver": "^7.3.5", - "slugify": "^1.6.2", + "slugify": "^1.6.4", "time-require": "^0.1.2" } } From 17a1867bf4ffb9d3395b8c564e3ee91052d4a34e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 19 Dec 2021 00:00:31 -0600 Subject: [PATCH 664/746] =?UTF-8?q?Revert=20"Going=20all=20in=20on=20async?= =?UTF-8?q?=20Nunjucks=20shortcodes.=20We=20don=E2=80=99t=20need=20to=20di?= =?UTF-8?q?stinguish=20between=20async=20and=20sync=20shortcodes=20in=20Nu?= =?UTF-8?q?njucks=20now,=20due=20to=20#1749."?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f3831c317b0d829e398e722c83715e03d6911ec0. --- src/Engines/Nunjucks.js | 143 +++++++++++++++++++++++++++------------- src/UserConfig.js | 80 +++++++++++++++------- 2 files changed, 157 insertions(+), 66 deletions(-) diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 2f196332b..5d3bcfd1b 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -163,7 +163,12 @@ class Nunjucks extends TemplateEngine { this.addCustomTags(this.config.nunjucksTags); this.addAllShortcodes(this.config.nunjucksShortcodes); + this.addAllShortcodes(this.config.nunjucksAsyncShortcodes, true); this.addAllPairedShortcodes(this.config.nunjucksPairedShortcodes); + this.addAllPairedShortcodes( + this.config.nunjucksAsyncPairedShortcodes, + true + ); this.addGlobals(this.config.nunjucksGlobals); } @@ -202,15 +207,15 @@ class Nunjucks extends TemplateEngine { this.njkEnv.addGlobal(name, globalFn); } - addAllShortcodes(shortcodes) { + addAllShortcodes(shortcodes, isAsync = false) { for (let name in shortcodes) { - this.addShortcode(name, shortcodes[name]); + this.addShortcode(name, shortcodes[name], isAsync); } } - addAllPairedShortcodes(shortcodes) { + addAllPairedShortcodes(shortcodes, isAsync = false) { for (let name in shortcodes) { - this.addPairedShortcode(name, shortcodes[name]); + this.addPairedShortcode(name, shortcodes[name], isAsync); } } @@ -223,7 +228,7 @@ class Nunjucks extends TemplateEngine { return obj; } - _getShortcodeFn(shortcodeName, shortcodeFn) { + _getShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) { return function ShortcodeFunction() { this.tags = [shortcodeName]; @@ -241,37 +246,57 @@ class Nunjucks extends TemplateEngine { } parser.advanceAfterBlockEnd(tok.value); - return new nodes.CallExtensionAsync(this, "run", args); + if (isAsync) { + return new nodes.CallExtensionAsync(this, "run", args); + } + return new nodes.CallExtension(this, "run", args); }; this.run = function (...args) { - let callback = args.pop(); + let resolve; + if (isAsync) { + resolve = args.pop(); + } + let [context, ...argArray] = args; - Promise.resolve( - shortcodeFn.call( - Nunjucks._normalizeShortcodeContext(context), - ...argArray - ) - ) - .then(function (returnValue) { - callback(null, new NunjucksLib.runtime.SafeString(returnValue)); - }) - .catch(function (e) { - callback( - new EleventyShortcodeError( - `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( - e - )}` - ), - null + if (isAsync) { + shortcodeFn + .call(Nunjucks._normalizeShortcodeContext(context), ...argArray) + .then(function (returnValue) { + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function (e) { + resolve( + new EleventyShortcodeError( + `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ), + null + ); + }); + } else { + try { + return new NunjucksLib.runtime.SafeString( + shortcodeFn.call( + Nunjucks._normalizeShortcodeContext(context), + ...argArray + ) ); - }); + } catch (e) { + throw new EleventyShortcodeError( + `Error with Nunjucks shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ); + } + } }; }; } - _getPairedShortcodeFn(shortcodeName, shortcodeFn) { + _getPairedShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) { return function PairedShortcodeFunction() { this.tags = [shortcodeName]; @@ -303,38 +328,60 @@ class Nunjucks extends TemplateEngine { ); } - Promise.resolve( - shortcodeFn.call( - Nunjucks._normalizeShortcodeContext(context), - bodyContent, - ...argArray - ) - ) - .then(function (returnValue) { - resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); - }) - .catch(function (e) { + if (isAsync) { + shortcodeFn + .call( + Nunjucks._normalizeShortcodeContext(context), + bodyContent, + ...argArray + ) + .then(function (returnValue) { + resolve(null, new NunjucksLib.runtime.SafeString(returnValue)); + }) + .catch(function (e) { + resolve( + new EleventyShortcodeError( + `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( + e + )}` + ), + null + ); + }); + } else { + try { + resolve( + null, + new NunjucksLib.runtime.SafeString( + shortcodeFn.call( + Nunjucks._normalizeShortcodeContext(context), + bodyContent, + ...argArray + ) + ) + ); + } catch (e) { resolve( new EleventyShortcodeError( `Error with Nunjucks paired shortcode \`${shortcodeName}\`${EleventyErrorUtil.convertErrorToString( e )}` - ), - null + ) ); - }); + } + } }); }; }; } - addShortcode(shortcodeName, shortcodeFn) { - let fn = this._getShortcodeFn(shortcodeName, shortcodeFn); + addShortcode(shortcodeName, shortcodeFn, isAsync = false) { + let fn = this._getShortcodeFn(shortcodeName, shortcodeFn, isAsync); this.njkEnv.addExtension(shortcodeName, new fn()); } - addPairedShortcode(shortcodeName, shortcodeFn) { - let fn = this._getPairedShortcodeFn(shortcodeName, shortcodeFn); + addPairedShortcode(shortcodeName, shortcodeFn, isAsync = false) { + let fn = this._getPairedShortcodeFn(shortcodeName, shortcodeFn, isAsync); this.njkEnv.addExtension(shortcodeName, new fn()); } @@ -371,10 +418,18 @@ class Nunjucks extends TemplateEngine { let fn = this._getShortcodeFn(name, () => {}); ext.push(new fn()); } + for (let name in this.config.nunjucksAsyncShortcodes) { + let fn = this._getShortcodeFn(name, () => {}, true); + ext.push(new fn()); + } for (let name in this.config.nunjucksPairedShortcodes) { let fn = this._getPairedShortcodeFn(name, () => {}); ext.push(new fn()); } + for (let name in this.config.nunjucksAsyncPairedShortcodes) { + let fn = this._getPairedShortcodeFn(name, () => {}, true); + ext.push(new fn()); + } this._parseExtensions = ext; return ext; diff --git a/src/UserConfig.js b/src/UserConfig.js index fea641d74..43a5e3d50 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -35,7 +35,9 @@ class UserConfig { this.nunjucksTags = {}; this.nunjucksGlobals = {}; this.nunjucksShortcodes = {}; + this.nunjucksAsyncShortcodes = {}; this.nunjucksPairedShortcodes = {}; + this.nunjucksAsyncPairedShortcodes = {}; this.handlebarsHelpers = {}; this.handlebarsShortcodes = {}; this.handlebarsPairedShortcodes = {}; @@ -458,35 +460,52 @@ class UserConfig { // Undocumented method as a mitigation to reduce risk of #498 addAsyncShortcode(name, callback) { debug("Adding universal async shortcode %o", this.getNamespacedName(name)); - this.addNunjucksShortcode(name, callback); + this.addNunjucksAsyncShortcode(name, callback); this.addLiquidShortcode(name, callback); this.addJavaScriptFunction(name, callback); // not supported in Handlebars } - // DEPRECATED, with 1.0.0-beta.9 and #1749 we don’t need to distinguish between async/sync shortcodes now addNunjucksAsyncShortcode(name, callback) { - this.addNunjucksShortcode(name, callback); - } - - addNunjucksShortcode(name, callback) { name = this.getNamespacedName(name); - if (this.nunjucksShortcodes[name]) { + if (this.nunjucksAsyncShortcodes[name]) { debug( chalk.yellow( - "Warning, overwriting a Nunjucks Shortcode with `addNunjucksShortcode(%o)`" + "Warning, overwriting a Nunjucks Async Shortcode with `addNunjucksAsyncShortcode(%o)`" ), name ); } - this.nunjucksShortcodes[name] = bench.add( - `"${name}" Nunjucks Shortcode`, + this.nunjucksAsyncShortcodes[name] = bench.add( + `"${name}" Nunjucks Async Shortcode`, callback ); } + addNunjucksShortcode(name, callback, isAsync = false) { + if (isAsync) { + this.addNunjucksAsyncShortcode(name, callback); + } else { + name = this.getNamespacedName(name); + + if (this.nunjucksShortcodes[name]) { + debug( + chalk.yellow( + "Warning, overwriting a Nunjucks Shortcode with `addNunjucksShortcode(%o)`" + ), + name + ); + } + + this.nunjucksShortcodes[name] = bench.add( + `"${name}" Nunjucks Shortcode`, + callback + ); + } + } + addLiquidShortcode(name, callback) { name = this.getNamespacedName(name); @@ -537,37 +556,52 @@ class UserConfig { "Adding universal async paired shortcode %o", this.getNamespacedName(name) ); - - // as of 1.0.0-beta.9 and #1749 we don’t need to distinguish between async/sync shortcodes now - this.addPairedNunjucksShortcode(name, callback); + this.addPairedNunjucksAsyncShortcode(name, callback); this.addPairedLiquidShortcode(name, callback); this.addJavaScriptFunction(name, callback); // not supported in Handlebars } - // DEPRECATED, with 1.0.0-beta.9 and #1749 we don’t need to distinguish between async/sync shortcodes now addPairedNunjucksAsyncShortcode(name, callback) { - this.addPairedNunjucksShortcode(name, callback); - } - - addPairedNunjucksShortcode(name, callback) { name = this.getNamespacedName(name); - if (this.nunjucksPairedShortcodes[name]) { + if (this.nunjucksAsyncPairedShortcodes[name]) { debug( chalk.yellow( - "Warning, overwriting a Nunjucks Paired Shortcode with `addPairedNunjucksShortcode(%o)`" + "Warning, overwriting a Nunjucks Async Paired Shortcode with `addPairedNunjucksAsyncShortcode(%o)`" ), name ); } - this.nunjucksPairedShortcodes[name] = bench.add( - `"${name}" Nunjucks Paired Shortcode`, + this.nunjucksAsyncPairedShortcodes[name] = bench.add( + `"${name}" Nunjucks Async Paired Shortcode`, callback ); } + addPairedNunjucksShortcode(name, callback, isAsync = false) { + if (isAsync) { + this.addPairedNunjucksAsyncShortcode(name, callback); + } else { + name = this.getNamespacedName(name); + + if (this.nunjucksPairedShortcodes[name]) { + debug( + chalk.yellow( + "Warning, overwriting a Nunjucks Paired Shortcode with `addPairedNunjucksShortcode(%o)`" + ), + name + ); + } + + this.nunjucksPairedShortcodes[name] = bench.add( + `"${name}" Nunjucks Paired Shortcode`, + callback + ); + } + } + addPairedLiquidShortcode(name, callback) { name = this.getNamespacedName(name); @@ -707,7 +741,9 @@ class UserConfig { nunjucksAsyncFilters: this.nunjucksAsyncFilters, nunjucksTags: this.nunjucksTags, nunjucksGlobals: this.nunjucksGlobals, + nunjucksAsyncShortcodes: this.nunjucksAsyncShortcodes, nunjucksShortcodes: this.nunjucksShortcodes, + nunjucksAsyncPairedShortcodes: this.nunjucksAsyncPairedShortcodes, nunjucksPairedShortcodes: this.nunjucksPairedShortcodes, handlebarsHelpers: this.handlebarsHelpers, handlebarsShortcodes: this.handlebarsShortcodes, From d68dcbf603be8e0285605edafe2d64b3a80b8e6b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 19 Dec 2021 00:03:45 -0600 Subject: [PATCH 665/746] Removes `time-require` for reasons stated in #2129 --- cmd.js | 4 ---- package.json | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/cmd.js b/cmd.js index 2c59f9834..a59bfb851 100755 --- a/cmd.js +++ b/cmd.js @@ -11,10 +11,6 @@ require("please-upgrade-node")(pkg, { }); const debug = require("debug")("Eleventy:cmd"); -if (process.env.DEBUG) { - require("time-require"); -} - const EleventyErrorHandler = require("./src/EleventyErrorHandler"); try { diff --git a/package.json b/package.json index 6280cb8d5..2aee2229f 100755 --- a/package.json +++ b/package.json @@ -123,7 +123,6 @@ "pug": "^3.0.2", "recursive-copy": "^2.0.13", "semver": "^7.3.5", - "slugify": "^1.6.4", - "time-require": "^0.1.2" + "slugify": "^1.6.4" } } From 5ba458dc09b824145b0633f26544378187cceb6f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 19 Dec 2021 00:06:22 -0600 Subject: [PATCH 666/746] v1.0.0-canary.48 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2aee2229f..3abb2a581 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.47", + "version": "1.0.0-canary.48", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 70478c50fac2b5db7deef054518e11cdda99bc2a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 19 Dec 2021 14:47:30 -0600 Subject: [PATCH 667/746] Test for #2140 --- test/TemplateRenderNunjucksTest.js | 54 +++++++++++++++++++++++++ test/stubs-njk-async/_includes/loop.njk | 1 + 2 files changed, 55 insertions(+) create mode 100644 test/stubs-njk-async/_includes/loop.njk diff --git a/test/TemplateRenderNunjucksTest.js b/test/TemplateRenderNunjucksTest.js index 87496571e..c754e60fb 100644 --- a/test/TemplateRenderNunjucksTest.js +++ b/test/TemplateRenderNunjucksTest.js @@ -944,3 +944,57 @@ test("Use config driven Nunjucks Environment Options (autoescape)", async (t) => "

Hi

" ); }); + +test("Nunjucks Shortcode in a loop (everything is sync)", async (t) => { + let templateConfig = new TemplateConfig(); + templateConfig.userConfig.addNunjucksShortcode( + "genericshortcode", + function (str) { + return str; + } + ); + + let tr = getNewTemplateRender( + "njk", + "./test/stubs-njk-async/", + templateConfig + ); + + let fn = await tr.getCompiledTemplate( + "{% for item in list %}{% include 'loop.njk' %}{% endfor %}" + ); + + t.is( + await fn({ + list: ["a", "b", "c"], + }), + "included_a-aincluded_b-bincluded_c-c" + ); +}); + +// TODO! +test.skip("Weird issue with number arguments in a loop (not parsing literals properly?)", async (t) => { + let templateConfig = new TemplateConfig(); + templateConfig.userConfig.addNunjucksShortcode( + "genericshortcode", + function (str) { + return str; + } + ); + + let tr = getNewTemplateRender( + "njk", + "./test/stubs-njk-async/", + templateConfig + ); + let fn = await tr.getCompiledTemplate( + "{% for item in list %}{{item}}-{% genericshortcode item %}{% endfor %}" + ); + + t.is( + await fn({ + list: [1, 2, 3], + }), + "1-12-23-3" + ); +}); diff --git a/test/stubs-njk-async/_includes/loop.njk b/test/stubs-njk-async/_includes/loop.njk new file mode 100644 index 000000000..1e04746bc --- /dev/null +++ b/test/stubs-njk-async/_includes/loop.njk @@ -0,0 +1 @@ +included_{{item}}-{% genericshortcode item %} \ No newline at end of file From 36fc4b74e2f17f3a5d229e1851ebdbf4a647383d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 19 Dec 2021 15:31:43 -0600 Subject: [PATCH 668/746] Add support for `compileOptions.permalink` functions in addExtension. Override just the permalink compilation with your own custom function. --- docs/meta-release.md | 2 +- src/TemplateContent.js | 32 +++++++++++--- test/TemplateTest.js | 77 +++++++++++++++++++++++++++++++++ test/stubs/custom-extension.txt | 4 ++ 4 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 test/stubs/custom-extension.txt diff --git a/docs/meta-release.md b/docs/meta-release.md index 90557b549..83b1abcc2 100644 --- a/docs/meta-release.md +++ b/docs/meta-release.md @@ -1,4 +1,4 @@ -# ESM dependency list +# List of dependencies that went ESM - `lint-staged` ESM at 12.x - `@sindresorhus/slugify` ESM at 2.x diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 81c8e6202..a473ca3f7 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -319,9 +319,9 @@ class TemplateContent { } // used by computed data or for permalink functions - async _renderFunction(fn, data) { + async _renderFunction(fn, ...args) { let mixins = Object.assign({}, this.config.javascriptFunctions); - let result = await fn.call(mixins, data); + let result = await fn.call(mixins, ...args); // normalize Buffer away if returned from permalink if (Buffer.isBuffer(result)) { @@ -340,12 +340,30 @@ class TemplateContent { } async renderPermalink(permalink, data) { - if ( - typeof permalink === "string" && - !this.engine.permalinkNeedsCompilation(permalink) - ) { - return permalink; + if (typeof permalink === "string") { + let permalinkCompilation = + this.engine.permalinkNeedsCompilation(permalink); + if (permalinkCompilation === false) { + return permalink; + } + + if (permalinkCompilation && typeof permalinkCompilation === "function") { + /* Usage: + permalink: function(permalinkString, inputPath) { + return async function(data) { + return "THIS IS MY RENDERED PERMALINK"; + } + } + */ + let fn = await this._renderFunction( + permalinkCompilation, + permalink, + this.inputPath + ); + return this._renderFunction(fn, data); + } } + if (typeof permalink === "function") { return this._renderFunction(permalink, data); } diff --git a/test/TemplateTest.js b/test/TemplateTest.js index ef0ae06c9..0c53f8b41 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2292,3 +2292,80 @@ test("Permalink is an object but an empty object (inherit default behavior)", as "./test/stubs/_site/permalink-empty-object/empty-object/index.html" ); }); + +test("Custom extension (.txt) with custom permalink compile function", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + // pass in your own custom permalink function. + permalink: async function (permalinkString, inputPath) { + t.is(permalinkString, "custom-extension.lit"); + t.is(inputPath, "./test/stubs/custom-extension.txt"); + return async function () { + return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; + }; + }, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", + path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", + rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", + }); +}); + +test("Custom extension with and opt-out of permalink compilation", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + permalink: false, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/custom-extension.lit", + path: "dist/custom-extension.lit", + rawPath: "custom-extension.lit", + }); +}); diff --git a/test/stubs/custom-extension.txt b/test/stubs/custom-extension.txt new file mode 100644 index 000000000..d08e8fef9 --- /dev/null +++ b/test/stubs/custom-extension.txt @@ -0,0 +1,4 @@ +--- +permalink: custom-extension.lit +--- +Sample content \ No newline at end of file From 548752bac7ebbb7ddb57703ce11129ac19160d06 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 21 Dec 2021 21:55:08 -0600 Subject: [PATCH 669/746] Allow custom extensions to partially override the default permalink behavior. e.g. useful if you want to add opt-out of file writing for any scss file that starts with an underscore. --- src/Engines/Custom.js | 16 ++-- src/Template.js | 31 ++++++++ src/TemplateContent.js | 43 +++++----- test/TemplateTest.js | 84 ++++++++++++++++++++ test/stubs/custom-extension-no-permalink.txt | 1 + 5 files changed, 149 insertions(+), 26 deletions(-) create mode 100644 test/stubs/custom-extension-no-permalink.txt diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index e958be0e1..7c9c9d712 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -155,12 +155,12 @@ class CustomEngine extends TemplateEngine { } // TODO generalize this (look at JavaScript.js) - return ( - this.entry.compile - .bind({ config: this.config })(str, inputPath) - // give the user access to this engine's default renderer, if any - .bind({ defaultRenderer }) - ); + let fn = this.entry.compile.bind({ config: this.config })(str, inputPath); + if (typeof fn === "function") { + // give the user access to this engine's default renderer, if any + return fn.bind({ defaultRenderer }); + } + return fn; } get defaultTemplateFileExtension() { @@ -185,6 +185,10 @@ class CustomEngine extends TemplateEngine { permalinkNeedsCompilation(str) { if (this.entry.compileOptions && "permalink" in this.entry.compileOptions) { + let p = this.entry.compileOptions.permalink; + if (p === false || p === "raw") { + return false; + } return this.entry.compileOptions.permalink; } diff --git a/src/Template.js b/src/Template.js index 9c2b8781e..9c679e12e 100755 --- a/src/Template.js +++ b/src/Template.js @@ -259,6 +259,27 @@ class Template extends TemplateContent { debugDev("Permalink rendered with data: %o", data); } + // Override default permalink behavior. Only do this if permalink was _not_ in the data cascade + if (!permalink) { + let permalinkCompilation = this.engine.permalinkNeedsCompilation(""); + if (typeof permalinkCompilation === "function") { + let ret = await this._renderFunction( + permalinkCompilation, + permalinkValue, + this.inputPath + ); + if (ret !== undefined) { + if (typeof ret === "function") { + // function + permalinkValue = await this._renderFunction(ret, data); + } else { + // scalar + permalinkValue = ret; + } + } + } + } + if (permalinkValue !== undefined) { return this._getRawPermalinkInstance(permalinkValue); } @@ -781,6 +802,16 @@ class Template extends TemplateContent { await mkdir(templateOutputDir, { recursive: true }); } + if (Buffer.isBuffer(finalContent)) { + finalContent = finalContent.toString(); + } + + if (typeof finalContent !== "string") { + throw new Error( + `The return value from the render function for the ${this.engine.name} template was not a string. Received ${finalContent}` + ); + } + return writeFile(outputPath, finalContent).then(() => { templateBenchmark.after(); this.writeCount++; diff --git a/src/TemplateContent.js b/src/TemplateContent.js index a473ca3f7..5b4c7656b 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -340,29 +340,30 @@ class TemplateContent { } async renderPermalink(permalink, data) { - if (typeof permalink === "string") { - let permalinkCompilation = - this.engine.permalinkNeedsCompilation(permalink); - if (permalinkCompilation === false) { - return permalink; - } + let permalinkCompilation = this.engine.permalinkNeedsCompilation(permalink); + // No string compilation: + // ({ compileOptions: { permalink: "raw" }}) + // These mean `permalink: false`, which is no file system writing: + // ({ compileOptions: { permalink: () => false }}) + // ({ compileOptions: { permalink: () => (() = > false) }}) + if (permalinkCompilation === false) { + return permalink; + } - if (permalinkCompilation && typeof permalinkCompilation === "function") { - /* Usage: - permalink: function(permalinkString, inputPath) { - return async function(data) { - return "THIS IS MY RENDERED PERMALINK"; - } - } - */ - let fn = await this._renderFunction( - permalinkCompilation, - permalink, - this.inputPath - ); - return this._renderFunction(fn, data); + /* Usage: + permalink: function(permalinkString, inputPath) { + return async function(data) { + return "THIS IS MY RENDERED PERMALINK"; } } + */ + if (permalinkCompilation && typeof permalinkCompilation === "function") { + permalink = await this._renderFunction( + permalinkCompilation, + permalink, + this.inputPath + ); + } if (typeof permalink === "function") { return this._renderFunction(permalink, data); @@ -382,6 +383,8 @@ class TemplateContent { } let fn = await this.compile(str, bypassMarkdown); + + // Benchmark let templateBenchmark = bench.get("Render"); let paginationSuffix = []; if ("pagination" in data) { diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 0c53f8b41..c4c52b01e 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2369,3 +2369,87 @@ test("Custom extension with and opt-out of permalink compilation", async (t) => rawPath: "custom-extension.lit", }); }); + +test("Custom extension (.txt) with custom permalink compile function but no permalink in the data cascade", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + // pass in your own custom permalink function. + permalink: async function (permalinkString, inputPath) { + t.is(permalinkString, undefined); + t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); + + return async function () { + return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; + }; + }, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension-no-permalink.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", + path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", + rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", + }); +}); + +test("Custom extension (.txt) with custom permalink compile function (that returns a string not a function) but no permalink in the data cascade", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + permalink: async function (permalinkString, inputPath) { + t.is(permalinkString, undefined); + t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); + + // unique part of this test: this is a string, not a function + return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; + }, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension-no-permalink.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", + path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", + rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", + }); +}); diff --git a/test/stubs/custom-extension-no-permalink.txt b/test/stubs/custom-extension-no-permalink.txt new file mode 100644 index 000000000..2c47b8ae9 --- /dev/null +++ b/test/stubs/custom-extension-no-permalink.txt @@ -0,0 +1 @@ +Sample content \ No newline at end of file From 88cdebbccfc0307f9c2660d345da48fd780f91f6 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Dec 2021 11:01:41 -0600 Subject: [PATCH 670/746] Test re-org --- test/TemplateTest-CompileOptions.js | 208 ++++++++++++++++++++++++++++ test/TemplateTest.js | 161 --------------------- 2 files changed, 208 insertions(+), 161 deletions(-) create mode 100644 test/TemplateTest-CompileOptions.js diff --git a/test/TemplateTest-CompileOptions.js b/test/TemplateTest-CompileOptions.js new file mode 100644 index 000000000..2adf7016a --- /dev/null +++ b/test/TemplateTest-CompileOptions.js @@ -0,0 +1,208 @@ +const test = require("ava"); + +const TemplateConfig = require("../src/TemplateConfig"); +const TemplateData = require("../src/TemplateData"); + +const getNewTemplate = require("./_getNewTemplateForTests"); + +test("Custom extension (.txt) with custom permalink compile function", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + // pass in your own custom permalink function. + permalink: async function (permalinkString, inputPath) { + t.is(permalinkString, "custom-extension.lit"); + t.is(inputPath, "./test/stubs/custom-extension.txt"); + return async function () { + return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; + }; + }, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", + path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", + rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", + }); +}); + +test("Custom extension with and opt-out of permalink compilation", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + permalink: false, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/custom-extension.lit", + path: "dist/custom-extension.lit", + rawPath: "custom-extension.lit", + }); +}); + +test("Custom extension (.txt) with custom permalink compile function but no permalink in the data cascade", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + // pass in your own custom permalink function. + permalink: async function (permalinkString, inputPath) { + t.is(permalinkString, undefined); + t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); + + return async function () { + return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; + }; + }, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension-no-permalink.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", + path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", + rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", + }); +}); + +test("Custom extension (.txt) with custom permalink compile function (that returns a string not a function) but no permalink in the data cascade", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + permalink: async function (permalinkString, inputPath) { + t.is(permalinkString, undefined); + t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); + + // unique part of this test: this is a string, not a function + return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; + }, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension-no-permalink.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", + path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", + rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", + }); +}); + +test("Custom extension (.txt) with custom permalink compile function that returns false", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + permalink: async function (permalinkString, inputPath) { + t.is(permalinkString, undefined); + t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); + + // unique part of this test: this returns false + return false; + }, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension-no-permalink.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: false, + path: false, + rawPath: false, + }); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index c4c52b01e..ef0ae06c9 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -2292,164 +2292,3 @@ test("Permalink is an object but an empty object (inherit default behavior)", as "./test/stubs/_site/permalink-empty-object/empty-object/index.html" ); }); - -test("Custom extension (.txt) with custom permalink compile function", async (t) => { - let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.extensionMap.add({ - extension: "txt", - key: "txt", - compileOptions: { - // pass in your own custom permalink function. - permalink: async function (permalinkString, inputPath) { - t.is(permalinkString, "custom-extension.lit"); - t.is(inputPath, "./test/stubs/custom-extension.txt"); - return async function () { - return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; - }; - }, - }, - compile: function (str, inputPath) { - // plaintext - return function (data) { - return str; - }; - }, - }); - - let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - let tmpl = getNewTemplate( - "./test/stubs/custom-extension.txt", - "./test/stubs/", - "dist", - dataObj, - null, - eleventyConfig - ); - - let data = await tmpl.getData(); - t.is(await tmpl.render(data), "Sample content"); - t.deepEqual(await tmpl.getOutputLocations(data), { - href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", - path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", - rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", - }); -}); - -test("Custom extension with and opt-out of permalink compilation", async (t) => { - let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.extensionMap.add({ - extension: "txt", - key: "txt", - compileOptions: { - permalink: false, - }, - compile: function (str, inputPath) { - // plaintext - return function (data) { - return str; - }; - }, - }); - - let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - let tmpl = getNewTemplate( - "./test/stubs/custom-extension.txt", - "./test/stubs/", - "dist", - dataObj, - null, - eleventyConfig - ); - - let data = await tmpl.getData(); - t.is(await tmpl.render(data), "Sample content"); - t.deepEqual(await tmpl.getOutputLocations(data), { - href: "/custom-extension.lit", - path: "dist/custom-extension.lit", - rawPath: "custom-extension.lit", - }); -}); - -test("Custom extension (.txt) with custom permalink compile function but no permalink in the data cascade", async (t) => { - let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.extensionMap.add({ - extension: "txt", - key: "txt", - compileOptions: { - // pass in your own custom permalink function. - permalink: async function (permalinkString, inputPath) { - t.is(permalinkString, undefined); - t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); - - return async function () { - return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; - }; - }, - }, - compile: function (str, inputPath) { - // plaintext - return function (data) { - return str; - }; - }, - }); - - let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - let tmpl = getNewTemplate( - "./test/stubs/custom-extension-no-permalink.txt", - "./test/stubs/", - "dist", - dataObj, - null, - eleventyConfig - ); - - let data = await tmpl.getData(); - t.is(await tmpl.render(data), "Sample content"); - t.deepEqual(await tmpl.getOutputLocations(data), { - href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", - path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", - rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", - }); -}); - -test("Custom extension (.txt) with custom permalink compile function (that returns a string not a function) but no permalink in the data cascade", async (t) => { - let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.extensionMap.add({ - extension: "txt", - key: "txt", - compileOptions: { - permalink: async function (permalinkString, inputPath) { - t.is(permalinkString, undefined); - t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); - - // unique part of this test: this is a string, not a function - return "HAHA_THIS_ALWAYS_GOES_HERE.txt"; - }, - }, - compile: function (str, inputPath) { - // plaintext - return function (data) { - return str; - }; - }, - }); - - let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - let tmpl = getNewTemplate( - "./test/stubs/custom-extension-no-permalink.txt", - "./test/stubs/", - "dist", - dataObj, - null, - eleventyConfig - ); - - let data = await tmpl.getData(); - t.is(await tmpl.render(data), "Sample content"); - t.deepEqual(await tmpl.getOutputLocations(data), { - href: "/HAHA_THIS_ALWAYS_GOES_HERE.txt", - path: "dist/HAHA_THIS_ALWAYS_GOES_HERE.txt", - rawPath: "HAHA_THIS_ALWAYS_GOES_HERE.txt", - }); -}); From 59ea524da4a61400c2c01918735c6d1493d93458 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Dec 2021 11:01:57 -0600 Subject: [PATCH 671/746] v1.0.0-canary.49 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3abb2a581..d3f09a9ad 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.48", + "version": "1.0.0-canary.49", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From f10bc1b5e7d77ba37d0e8e36610df8c34bfa236d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 22 Dec 2021 11:04:32 -0600 Subject: [PATCH 672/746] v1.0.0-beta.9 --- docs-src/_data/coverage.json | 36 ++++---- docs/coverage.md | 162 ++++++++++++++++++----------------- package.json | 2 +- 3 files changed, 106 insertions(+), 94 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 839f951f0..caeafdf38 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,16 +1,22 @@ -{"total": {"lines":{"total":4741,"covered":3938,"skipped":0,"pct":83.06},"statements":{"total":4766,"covered":3960,"skipped":0,"pct":83.08},"functions":{"total":1038,"covered":872,"skipped":0,"pct":84},"branches":{"total":2165,"covered":1617,"skipped":0,"pct":74.68},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":55,"covered":34,"skipped":0,"pct":61.81},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":55,"covered":34,"skipped":0,"pct":61.81},"branches":{"total":24,"covered":14,"skipped":0,"pct":58.33}} +{"total": {"lines":{"total":4848,"covered":4057,"skipped":0,"pct":83.68},"statements":{"total":4875,"covered":4081,"skipped":0,"pct":83.71},"functions":{"total":1055,"covered":892,"skipped":0,"pct":84.54},"branches":{"total":2223,"covered":1676,"skipped":0,"pct":75.39},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":53,"covered":33,"skipped":0,"pct":62.26},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":53,"covered":33,"skipped":0,"pct":62.26},"branches":{"total":22,"covered":13,"skipped":0,"pct":59.09}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_template_id_031efc80_lang.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/test.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/test.vue_vue_type_script_lang.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/test.vue_vue_type_template_id_06d771ae_lang.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/_includes/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/_includes/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/.cache/vue/_includes/include.vue_vue_type_template_id_d3bb7f88_lang.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":47,"covered":37,"skipped":0,"pct":78.72},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":47,"covered":37,"skipped":0,"pct":78.72},"branches":{"total":19,"covered":12,"skipped":0,"pct":63.15}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":45,"covered":34,"skipped":0,"pct":75.55},"functions":{"total":10,"covered":7,"skipped":0,"pct":70},"statements":{"total":45,"covered":34,"skipped":0,"pct":75.55},"branches":{"total":15,"covered":9,"skipped":0,"pct":60}} ,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.77},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.77},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} ,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":60,"covered":60,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":60,"covered":60,"skipped":0,"pct":100},"branches":{"total":29,"covered":28,"skipped":0,"pct":96.55}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.03},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.03},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.62}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":26,"covered":24,"skipped":0,"pct":92.3},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":26,"covered":24,"skipped":0,"pct":92.3},"branches":{"total":7,"covered":5,"skipped":0,"pct":71.42}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":313,"covered":200,"skipped":0,"pct":63.89},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":314,"covered":200,"skipped":0,"pct":63.69},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":314,"covered":201,"skipped":0,"pct":64.01},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":315,"covered":201,"skipped":0,"pct":63.8},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheckError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":38,"covered":35,"skipped":0,"pct":92.1},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":38,"covered":35,"skipped":0,"pct":92.1},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.56}} @@ -22,12 +28,12 @@ ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} ,"/Users/zachleat/Code/eleventy/src/EventBus.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":95,"covered":72,"skipped":0,"pct":75.78},"functions":{"total":14,"covered":12,"skipped":0,"pct":85.71},"statements":{"total":95,"covered":72,"skipped":0,"pct":75.78},"branches":{"total":38,"covered":24,"skipped":0,"pct":63.15}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":390,"covered":363,"skipped":0,"pct":93.07},"functions":{"total":71,"covered":69,"skipped":0,"pct":97.18},"statements":{"total":392,"covered":365,"skipped":0,"pct":93.11},"branches":{"total":171,"covered":147,"skipped":0,"pct":85.96}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":406,"covered":378,"skipped":0,"pct":93.1},"functions":{"total":71,"covered":69,"skipped":0,"pct":97.18},"statements":{"total":408,"covered":380,"skipped":0,"pct":93.13},"branches":{"total":183,"covered":157,"skipped":0,"pct":85.79}} ,"/Users/zachleat/Code/eleventy/src/TemplateBehavior.js": {"lines":{"total":24,"covered":21,"skipped":0,"pct":87.5},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":24,"covered":21,"skipped":0,"pct":87.5},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":86,"covered":74,"skipped":0,"pct":86.04},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":86,"covered":74,"skipped":0,"pct":86.04},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":163,"covered":147,"skipped":0,"pct":90.18},"functions":{"total":33,"covered":33,"skipped":0,"pct":100},"statements":{"total":163,"covered":147,"skipped":0,"pct":90.18},"branches":{"total":75,"covered":56,"skipped":0,"pct":74.66}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":202,"covered":182,"skipped":0,"pct":90.09},"functions":{"total":36,"covered":35,"skipped":0,"pct":97.22},"statements":{"total":202,"covered":182,"skipped":0,"pct":90.09},"branches":{"total":107,"covered":84,"skipped":0,"pct":78.5}} ,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":264,"covered":252,"skipped":0,"pct":95.45},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":267,"covered":255,"skipped":0,"pct":95.5},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} ,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":52,"covered":50,"skipped":0,"pct":96.15},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":50,"skipped":0,"pct":96.15},"branches":{"total":34,"covered":33,"skipped":0,"pct":97.05}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} @@ -39,22 +45,22 @@ ,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":93,"covered":80,"skipped":0,"pct":86.02},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":93,"covered":80,"skipped":0,"pct":86.02},"branches":{"total":38,"covered":27,"skipped":0,"pct":71.05}} ,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":98,"covered":98,"skipped":0,"pct":100},"functions":{"total":28,"covered":27,"skipped":0,"pct":96.42},"statements":{"total":99,"covered":99,"skipped":0,"pct":100},"branches":{"total":55,"covered":55,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":78,"covered":70,"skipped":0,"pct":89.74},"functions":{"total":10,"covered":9,"skipped":0,"pct":90},"statements":{"total":78,"covered":70,"skipped":0,"pct":89.74},"branches":{"total":69,"covered":62,"skipped":0,"pct":89.85}} -,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":87,"skipped":0,"pct":95.6},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":87,"skipped":0,"pct":95.6},"branches":{"total":59,"covered":54,"skipped":0,"pct":91.52}} +,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":86,"skipped":0,"pct":94.5},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":86,"skipped":0,"pct":94.5},"branches":{"total":59,"covered":53,"skipped":0,"pct":89.83}} ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":164,"skipped":0,"pct":66.66},"functions":{"total":65,"covered":39,"skipped":0,"pct":60},"statements":{"total":246,"covered":164,"skipped":0,"pct":66.66},"branches":{"total":99,"covered":47,"skipped":0,"pct":47.47}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":168,"skipped":0,"pct":68.29},"functions":{"total":65,"covered":40,"skipped":0,"pct":61.53},"statements":{"total":246,"covered":168,"skipped":0,"pct":68.29},"branches":{"total":101,"covered":52,"skipped":0,"pct":51.48}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":61,"covered":31,"skipped":0,"pct":50.81},"functions":{"total":9,"covered":7,"skipped":0,"pct":77.77},"statements":{"total":61,"covered":31,"skipped":0,"pct":50.81},"branches":{"total":36,"covered":16,"skipped":0,"pct":44.44}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":84,"covered":70,"skipped":0,"pct":83.33},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":84,"covered":70,"skipped":0,"pct":83.33},"branches":{"total":54,"covered":40,"skipped":0,"pct":74.07}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":29,"covered":29,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":29,"covered":29,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":12,"covered":12,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":12,"covered":12,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":58,"covered":56,"skipped":0,"pct":96.55},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":59,"covered":57,"skipped":0,"pct":96.61},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":88,"covered":86,"skipped":0,"pct":97.72},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":89,"covered":87,"skipped":0,"pct":97.75},"branches":{"total":25,"covered":21,"skipped":0,"pct":84}} +,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":59,"covered":57,"skipped":0,"pct":96.61},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":60,"covered":58,"skipped":0,"pct":96.66},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":86,"covered":84,"skipped":0,"pct":97.67},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":87,"covered":85,"skipped":0,"pct":97.7},"branches":{"total":23,"covered":19,"skipped":0,"pct":82.6}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":35,"covered":32,"skipped":0,"pct":91.42},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.88},"statements":{"total":35,"covered":32,"skipped":0,"pct":91.42},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":201,"covered":137,"skipped":0,"pct":68.15},"functions":{"total":47,"covered":35,"skipped":0,"pct":74.46},"statements":{"total":201,"covered":137,"skipped":0,"pct":68.15},"branches":{"total":88,"covered":59,"skipped":0,"pct":67.04}} +,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":203,"covered":138,"skipped":0,"pct":67.98},"functions":{"total":49,"covered":37,"skipped":0,"pct":75.51},"statements":{"total":203,"covered":138,"skipped":0,"pct":67.98},"branches":{"total":84,"covered":54,"skipped":0,"pct":64.28}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":72,"covered":70,"skipped":0,"pct":97.22},"functions":{"total":23,"covered":22,"skipped":0,"pct":95.65},"statements":{"total":74,"covered":72,"skipped":0,"pct":97.29},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":74,"covered":73,"skipped":0,"pct":98.64},"functions":{"total":25,"covered":25,"skipped":0,"pct":100},"statements":{"total":76,"covered":75,"skipped":0,"pct":98.68},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentUnrenderedTemplateError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -64,12 +70,12 @@ ,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} ,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":136,"covered":121,"skipped":0,"pct":88.97},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":140,"covered":125,"skipped":0,"pct":89.28},"branches":{"total":90,"covered":70,"skipped":0,"pct":77.77}} -,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":105,"covered":96,"skipped":0,"pct":91.42},"functions":{"total":21,"covered":19,"skipped":0,"pct":90.47},"statements":{"total":105,"covered":96,"skipped":0,"pct":91.42},"branches":{"total":39,"covered":27,"skipped":0,"pct":69.23}} +,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":108,"covered":97,"skipped":0,"pct":89.81},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":110,"covered":99,"skipped":0,"pct":90},"branches":{"total":45,"covered":30,"skipped":0,"pct":66.66}} ,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":186,"covered":12,"skipped":0,"pct":6.45},"functions":{"total":34,"covered":0,"skipped":0,"pct":0},"statements":{"total":188,"covered":12,"skipped":0,"pct":6.38},"branches":{"total":91,"covered":0,"skipped":0,"pct":0}} ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":28,"covered":24,"skipped":0,"pct":85.71},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":28,"covered":24,"skipped":0,"pct":85.71},"branches":{"total":19,"covered":17,"skipped":0,"pct":89.47}} ,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.85}} +,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":14,"covered":14,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.85},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.85},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/Util/Pluralize.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":48,"covered":45,"skipped":0,"pct":93.75},"functions":{"total":20,"covered":18,"skipped":0,"pct":90},"statements":{"total":48,"covered":45,"skipped":0,"pct":93.75},"branches":{"total":20,"covered":18,"skipped":0,"pct":90}} diff --git a/docs/coverage.md b/docs/coverage.md index 1003c9cc9..b3dc63d03 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,79 +1,85 @@ -# Code Coverage for Eleventy v1.0.0-beta.7 +# Code Coverage for Eleventy v1.0.0-beta.9 -| Filename | % Lines | % Statements | % Functions | % Branches | -| -------------------------------------------------------------- | ------- | ------------ | ----------- | ---------- | -| `total` | 83.06% | 83.08% | 84% | 74.68% | -| `cmd.js` | 61.81% | 61.81% | 9.09% | 58.33% | -| `.cache/vue/include.js` | 100% | 100% | 100% | 100% | -| `.cache/vue/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | -| `.cache/vue/include.vue_vue_type_template_id_031efc80_lang.js` | 100% | 100% | 100% | 100% | -| `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | -| `src/BenchmarkGroup.js` | 78.72% | 78.72% | 66.66% | 63.15% | -| `src/BenchmarkManager.js` | 77.77% | 77.77% | 75% | 75% | -| `src/ComputedData.js` | 100% | 100% | 100% | 96.55% | -| `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | -| `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | -| `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | -| `src/Eleventy.js` | 63.89% | 63.69% | 67.34% | 63.71% | -| `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | -| `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | -| `src/EleventyErrorHandler.js` | 92.1% | 92.1% | 100% | 67.56% | -| `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | -| `src/EleventyExtensionMap.js` | 97.56% | 97.56% | 96% | 89.74% | -| `src/EleventyFiles.js` | 89% | 89.11% | 88.88% | 74.64% | -| `src/EleventyServe.js` | 37.14% | 37.14% | 56.25% | 25% | -| `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | -| `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | -| `src/EventBus.js` | 100% | 100% | 100% | 100% | -| `src/Serverless.js` | 75.78% | 75.78% | 85.71% | 63.15% | -| `src/Template.js` | 93.07% | 93.11% | 97.18% | 85.96% | -| `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | -| `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | -| `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | -| `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | -| `src/TemplateContent.js` | 90.18% | 90.18% | 100% | 74.66% | -| `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | -| `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | -| `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | -| `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | -| `src/TemplateLayout.js` | 92.3% | 92.4% | 100% | 85% | -| `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | -| `src/TemplateMap.js` | 96.75% | 96.75% | 94.59% | 86% | -| `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | -| `src/TemplatePassthroughManager.js` | 86.02% | 86.02% | 100% | 71.05% | -| `src/TemplatePath.js` | 100% | 100% | 96.42% | 100% | -| `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | -| `src/TemplateRender.js` | 95.6% | 95.6% | 100% | 91.52% | -| `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | -| `src/UserConfig.js` | 66.66% | 66.66% | 60% | 47.47% | -| `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | -| `src/Engines/Custom.js` | 50.81% | 50.81% | 77.77% | 44.44% | -| `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | -| `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | -| `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | -| `src/Engines/Html.js` | 100% | 100% | 100% | 100% | -| `src/Engines/JavaScript.js` | 96.55% | 96.61% | 100% | 83.33% | -| `src/Engines/Liquid.js` | 97.72% | 97.75% | 96.66% | 84% | -| `src/Engines/Markdown.js` | 91.42% | 91.42% | 88.88% | 81.25% | -| `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | -| `src/Engines/Nunjucks.js` | 68.15% | 68.15% | 74.46% | 67.04% | -| `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | -| `src/Engines/TemplateEngine.js` | 97.22% | 97.29% | 95.65% | 93.75% | -| `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | -| `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | -| `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | -| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.85% | -| `src/Filters/ServerlessUrl.js` | 100% | 100% | 100% | 75% | -| `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | -| `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | -| `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | -| `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | -| `src/Plugins/RenderPlugin.js` | 91.42% | 91.42% | 90.47% | 69.23% | -| `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | -| `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | -| `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | -| `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | -| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 92.85% | -| `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | -| `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | -| `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% | +| Filename | % Lines | % Statements | % Functions | % Branches | +| ------------------------------------------------------------------------ | ------- | ------------ | ----------- | ---------- | +| `total` | 83.68% | 83.71% | 84.54% | 75.39% | +| `cmd.js` | 62.26% | 62.26% | 9.09% | 59.09% | +| `.cache/vue/include.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/include.vue_vue_type_template_id_031efc80_lang.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/test.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/test.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/test.vue_vue_type_template_id_06d771ae_lang.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/_includes/include.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/_includes/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | +| `.cache/vue/_includes/include.vue_vue_type_template_id_d3bb7f88_lang.js` | 100% | 100% | 100% | 100% | +| `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | +| `src/BenchmarkGroup.js` | 75.55% | 75.55% | 70% | 60% | +| `src/BenchmarkManager.js` | 77.77% | 77.77% | 75% | 75% | +| `src/ComputedData.js` | 100% | 100% | 100% | 96.55% | +| `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | +| `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | +| `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | +| `src/Eleventy.js` | 64.01% | 63.8% | 67.34% | 63.71% | +| `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | +| `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | +| `src/EleventyErrorHandler.js` | 92.1% | 92.1% | 100% | 67.56% | +| `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | +| `src/EleventyExtensionMap.js` | 97.56% | 97.56% | 96% | 89.74% | +| `src/EleventyFiles.js` | 89% | 89.11% | 88.88% | 74.64% | +| `src/EleventyServe.js` | 37.14% | 37.14% | 56.25% | 25% | +| `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | +| `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | +| `src/EventBus.js` | 100% | 100% | 100% | 100% | +| `src/Serverless.js` | 75.78% | 75.78% | 85.71% | 63.15% | +| `src/Template.js` | 93.1% | 93.13% | 97.18% | 85.79% | +| `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | +| `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | +| `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | +| `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | +| `src/TemplateContent.js` | 90.09% | 90.09% | 97.22% | 78.5% | +| `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | +| `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | +| `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | +| `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | +| `src/TemplateLayout.js` | 92.3% | 92.4% | 100% | 85% | +| `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | +| `src/TemplateMap.js` | 96.75% | 96.75% | 94.59% | 86% | +| `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | +| `src/TemplatePassthroughManager.js` | 86.02% | 86.02% | 100% | 71.05% | +| `src/TemplatePath.js` | 100% | 100% | 96.42% | 100% | +| `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | +| `src/TemplateRender.js` | 94.5% | 94.5% | 100% | 89.83% | +| `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | +| `src/UserConfig.js` | 68.29% | 68.29% | 61.53% | 51.48% | +| `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | +| `src/Engines/Custom.js` | 83.33% | 83.33% | 100% | 74.07% | +| `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | +| `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | +| `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | +| `src/Engines/Html.js` | 100% | 100% | 100% | 100% | +| `src/Engines/JavaScript.js` | 96.61% | 96.66% | 100% | 83.33% | +| `src/Engines/Liquid.js` | 97.67% | 97.7% | 96.66% | 82.6% | +| `src/Engines/Markdown.js` | 91.42% | 91.42% | 88.88% | 81.25% | +| `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | +| `src/Engines/Nunjucks.js` | 67.98% | 67.98% | 75.51% | 64.28% | +| `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | +| `src/Engines/TemplateEngine.js` | 98.64% | 98.68% | 100% | 93.75% | +| `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | +| `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | +| `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | +| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.85% | +| `src/Filters/ServerlessUrl.js` | 100% | 100% | 100% | 75% | +| `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | +| `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | +| `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | +| `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | +| `src/Plugins/RenderPlugin.js` | 89.81% | 90% | 91.3% | 66.66% | +| `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | +| `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | +| `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | +| `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | +| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 100% | +| `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | +| `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | +| `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% | diff --git a/package.json b/package.json index d3f09a9ad..ed812eeb0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.49", + "version": "1.0.0-beta.9", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 35eeb949ec6632919243e9f9b93ea1c261d5edf3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 26 Dec 2021 23:25:32 -0600 Subject: [PATCH 673/746] Only throw transforms warning if there was a truthy content before. --- src/Template.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Template.js b/src/Template.js index 9c679e12e..514b69b7d 100755 --- a/src/Template.js +++ b/src/Template.js @@ -547,6 +547,7 @@ class Template extends TemplateContent { // Warning: this argument list is the reverse of linters (inputPath then outputPath) async runTransforms(str, inputPath, outputPath) { for (let transform of this.transforms) { + let hadStrBefore = !!str; str = await transform.callback.call( { inputPath, @@ -555,7 +556,7 @@ class Template extends TemplateContent { str, outputPath ); - if (!str) { + if (hadStrBefore && !str) { this.logger.warn( `Warning: Transform \`${transform.name}\` returned empty when writing ${outputPath} from ${inputPath}.` ); From 1ea3a90cc49b636a4c838852a9103e9fe6d2135d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 27 Dec 2021 15:29:56 -0600 Subject: [PATCH 674/746] * Allow render function to return undefined to skip the file write. * `compileOptions: permalink: false` now aliases to `compileOptions: permalink: () => false`. Use `compileOptions: permalink: "raw"` to skip permalink compilation altogether --- src/Engines/Custom.js | 8 +++- src/Template.js | 33 +++++++++----- src/TemplateContent.js | 1 + src/TemplateMap.js | 5 ++- test/TemplateTest-CompileOptions.js | 69 ++++++++++++++++++++++++++++- 5 files changed, 103 insertions(+), 13 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 7c9c9d712..e826e892e 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -186,9 +186,15 @@ class CustomEngine extends TemplateEngine { permalinkNeedsCompilation(str) { if (this.entry.compileOptions && "permalink" in this.entry.compileOptions) { let p = this.entry.compileOptions.permalink; - if (p === false || p === "raw") { + if (p === "raw") { return false; } + + // permalink: false is aliased to permalink: () => false + if (p === false) { + return () => false; + } + return this.entry.compileOptions.permalink; } diff --git a/src/Template.js b/src/Template.js index 514b69b7d..9be98d08d 100755 --- a/src/Template.js +++ b/src/Template.js @@ -492,6 +492,7 @@ class Template extends TemplateContent { return ret; } + // Used only by tests async renderContent(str, data, bypassMarkdown) { return super.render(str, data, bypassMarkdown); } @@ -678,11 +679,18 @@ class Template extends TemplateContent { date: data.page.date, outputPath: data.page.outputPath, url: data.page.url, + checkTemplateContent: true, set templateContent(content) { + if (content === undefined) { + this.checkTemplateContent = false; + } this._templateContent = content; }, get templateContent() { - if (this._templateContent === undefined) { + if ( + this.checkTemplateContent && + this._templateContent === undefined + ) { if (this.template.behavior.isRenderable()) { // should at least warn here throw new TemplateContentPrematureUseError( @@ -728,11 +736,18 @@ class Template extends TemplateContent { pageNumber: pageNumber, outputPath: pageData.page.outputPath, url: pageData.page.url, + checkTemplateContent: true, set templateContent(content) { + if (content === undefined) { + this.checkTemplateContent = false; + } this._templateContent = content; }, get templateContent() { - if (this._templateContent === undefined) { + if ( + this.checkTemplateContent && + this._templateContent === undefined + ) { if (this.template.behavior.isRenderable()) { throw new TemplateContentPrematureUseError( `Tried to use templateContent too early (${this.inputPath} page ${this.pageNumber})` @@ -803,13 +818,9 @@ class Template extends TemplateContent { await mkdir(templateOutputDir, { recursive: true }); } - if (Buffer.isBuffer(finalContent)) { - finalContent = finalContent.toString(); - } - - if (typeof finalContent !== "string") { + if (!Buffer.isBuffer(finalContent) && typeof finalContent !== "string") { throw new Error( - `The return value from the render function for the ${this.engine.name} template was not a string. Received ${finalContent}` + `The return value from the render function for the ${this.engine.name} template was not a String or Buffer. Received ${finalContent}` ); } @@ -854,7 +865,6 @@ class Template extends TemplateContent { return Promise.all( mapEntry._pages.map(async (page) => { let content; - // Note that behavior.render is overridden when using json or ndjson output if (mapEntry.template.behavior.isRenderable()) { // this reuses page.templateContent, it doesn’t render it @@ -907,7 +917,10 @@ class Template extends TemplateContent { return; } - return this._write(page.outputPath, content); + // compile returned undefined + if (content !== undefined) { + return this._write(page.outputPath, content); + } }) ); } diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 5b4c7656b..aa8e4532e 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -344,6 +344,7 @@ class TemplateContent { // No string compilation: // ({ compileOptions: { permalink: "raw" }}) // These mean `permalink: false`, which is no file system writing: + // ({ compileOptions: { permalink: false }}) // ({ compileOptions: { permalink: () => false }}) // ({ compileOptions: { permalink: () => (() = > false) }}) if (permalinkCompilation === false) { diff --git a/src/TemplateMap.js b/src/TemplateMap.js index 26fe76c8c..e296e85b3 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -603,7 +603,10 @@ class TemplateMap { // This check skips precompiled collections if (entry) { let index = item.pageNumber || 0; - item.templateContent = entry._pages[index]._templateContent; + let content = entry._pages[index]._templateContent; + if (content !== undefined) { + item.templateContent = content; + } } } } diff --git a/test/TemplateTest-CompileOptions.js b/test/TemplateTest-CompileOptions.js index 2adf7016a..3065f29c3 100644 --- a/test/TemplateTest-CompileOptions.js +++ b/test/TemplateTest-CompileOptions.js @@ -47,7 +47,7 @@ test("Custom extension (.txt) with custom permalink compile function", async (t) }); }); -test("Custom extension with and opt-out of permalink compilation", async (t) => { +test("Custom extension with and compileOptions.permalink = false", async (t) => { let eleventyConfig = new TemplateConfig(); eleventyConfig.userConfig.extensionMap.add({ extension: "txt", @@ -73,6 +73,41 @@ test("Custom extension with and opt-out of permalink compilation", async (t) => eleventyConfig ); + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); + t.deepEqual(await tmpl.getOutputLocations(data), { + href: false, + path: false, + rawPath: false, + }); +}); + +test("Custom extension with and opt-out of permalink compilation", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + permalink: "raw", + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + let data = await tmpl.getData(); t.is(await tmpl.render(data), "Sample content"); t.deepEqual(await tmpl.getOutputLocations(data), { @@ -206,3 +241,35 @@ test("Custom extension (.txt) with custom permalink compile function that return rawPath: false, }); }); + +test("Custom extension (.txt) that returns undefined from compile", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compile: function (str, inputPath) { + t.is(str, "Sample content"); + return function (data) { + return undefined; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension-no-permalink.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), undefined); + let pages = await tmpl.getTemplates(data); + for (let page of pages) { + page.templateContent = undefined; + t.is(page.templateContent, undefined); // shouldn’t throw an error + } +}); From ed661f4a3208942da27d8d32a34a9cb5aea30ecf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 30 Dec 2021 09:19:46 -0600 Subject: [PATCH 675/746] Fix debug output for Eleventy:cmd --- cmd.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd.js b/cmd.js index a59bfb851..37e6d3414 100755 --- a/cmd.js +++ b/cmd.js @@ -46,8 +46,7 @@ try { }, }); - // TODO fix debug output: `Eleventy:cmd command: eleventy [object Object] +0ms` - debug("command: eleventy ", argv.toString()); + debug("command: eleventy %o", argv); const Eleventy = require("./src/Eleventy"); process.on("unhandledRejection", (error, promise) => { From fb1a7d878e119d5808a08f840d97d51ed26ac473 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 30 Dec 2021 14:26:58 -0600 Subject: [PATCH 676/746] Add outputFileExtension to default page variable --- src/Template.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Template.js b/src/Template.js index 9be98d08d..3319538c3 100755 --- a/src/Template.js +++ b/src/Template.js @@ -468,6 +468,7 @@ class Template extends TemplateContent { data.page.inputPath = this.inputPath; data.page.fileSlug = this.fileSlugStr; data.page.filePathStem = this.filePathStem; + data.page.outputFileExtension = this.engine.defaultTemplateFileExtension; return data; } From 5bc24ca70e16622f253979c3710c195b222fff2c Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 30 Dec 2021 14:28:08 -0600 Subject: [PATCH 677/746] Checks when .compile returns undefined --- src/Plugins/RenderPlugin.js | 16 ++++++++++++++++ src/TemplateContent.js | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index d59bc6ea2..c67c0688f 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -267,6 +267,14 @@ function EleventyPlugin(eleventyConfig, options = {}) { } ); + if (fn === undefined) { + return; + } else if (typeof fn !== "function") { + throw new Error( + `The \`compile\` function did not return a function. Received ${fn}` + ); + } + // if the user passes a string or other literal, remap to an object. if (!lodashIsPlainObject(data)) { data = { @@ -292,6 +300,14 @@ function EleventyPlugin(eleventyConfig, options = {}) { } ); + if (fn === undefined) { + return; + } else if (typeof fn !== "function") { + throw new Error( + `The \`compile\` function did not return a function. Received ${fn}` + ); + } + // if the user passes a string or other literal, remap to an object. if (!lodashIsPlainObject(data)) { data = { diff --git a/src/TemplateContent.js b/src/TemplateContent.js index aa8e4532e..824d58e30 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -384,6 +384,13 @@ class TemplateContent { } let fn = await this.compile(str, bypassMarkdown); + if (fn === undefined) { + return; + } else if (typeof fn !== "function") { + throw new Error( + `The \`compile\` function did not return a function. Received ${fn}` + ); + } // Benchmark let templateBenchmark = bench.get("Render"); From a5101895787ba7a264c37a411fa5178cce1b93d9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 30 Dec 2021 15:14:19 -0600 Subject: [PATCH 678/746] Fixes #2155 --- src/Eleventy.js | 3 +- src/EleventyExtensionMap.js | 51 ++++++++++++++++++++++++++++++++ src/EleventyFiles.js | 9 ++++-- src/Engines/Custom.js | 11 +++++++ src/Engines/JavaScript.js | 4 +++ src/Engines/TemplateEngine.js | 5 ++++ test/EleventyExtensionMapTest.js | 38 ++++++++++++++++++++++++ 7 files changed, 117 insertions(+), 4 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 547aea33c..2cd30c768 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -740,7 +740,8 @@ Arguments: } // Template files .11ty.js - this.watchTargets.addDependencies(this.eleventyFiles.getWatchPathCache()); + let templateFiles = this.eleventyFiles.getWatchPathCache(); + this.watchTargets.addDependencies(templateFiles); // Config file dependencies this.watchTargets.addDependencies( diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index d4417e7cf..f3ebb80c4 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -18,6 +18,8 @@ class EleventyExtensionMap { this.formatKeys = formatKeys; this.setFormats(formatKeys); + + this._spiderJsDepsCache = {}; } setFormats(formatKeys = []) { @@ -87,6 +89,54 @@ class EleventyExtensionMap { return false; } + getCustomExtensionEntry(extension) { + if (!this.config.extensionMap) { + return; + } + + for (let entry of this.config.extensionMap) { + if (entry.extension === extension) { + return entry; + } + } + } + + getValidExtensionsForPath(path) { + let extensions = new Set(); + for (let extension in this.extensionToKeyMap) { + if (path.endsWith(`.${extension}`)) { + extensions.add(extension); + } + } + + // if multiple extensions are valid, sort from longest to shortest + // e.g. .11ty.js and .js + let sorted = Array.from(extensions) + .filter((extension) => this.validTemplateLanguageKeys.includes(extension)) + .sort((a, b) => b.length - a.length); + + return sorted; + } + + shouldSpiderJavaScriptDependencies(path) { + let extensions = this.getValidExtensionsForPath(path); + for (let extension of extensions) { + if (extension in this._spiderJsDepsCache) { + return this._spiderJsDepsCache[extension]; + } + + let cls = this.engineManager.getEngineClassByExtension(extension); + if (cls) { + let entry = this.getCustomExtensionEntry(extension); + let shouldSpider = cls.shouldSpiderJavaScriptDependencies(entry); + this._spiderJsDepsCache[extension] = shouldSpider; + return shouldSpider; + } + } + + return false; + } + getPassthroughCopyGlobs(inputDir) { return this._getGlobs(this.passthroughCopyKeys, inputDir); } @@ -133,6 +183,7 @@ class EleventyExtensionMap { return extensions; } + // Only `addExtension` configuration API extensions getExtensionEntriesFromKey(key) { let entries = []; if ("extensionMap" in this.config) { diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index bb2f78501..bdcb8a584 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -352,9 +352,12 @@ class EleventyFiles { } // Filter out the passthrough copy paths. - return this.pathCache.filter((path) => - this.extensionMap.isFullTemplateFilePath(path) - ); + return this.pathCache.filter((path) => { + return ( + this.extensionMap.isFullTemplateFilePath(path) && + this.extensionMap.shouldSpiderJavaScriptDependencies(path) + ); + }); } _globSearch() { diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index e826e892e..d57596395 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -200,6 +200,17 @@ class CustomEngine extends TemplateEngine { return true; } + + static shouldSpiderJavaScriptDependencies(entry) { + if ( + entry.compileOptions && + "spiderJavaScriptDependencies" in entry.compileOptions + ) { + return entry.compileOptions.spiderJavaScriptDependencies; + } + + return false; + } } module.exports = CustomEngine; diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index 625c6d202..f3134f9f6 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -133,6 +133,10 @@ class JavaScript extends TemplateEngine { }.bind(this); } } + + static shouldSpiderJavaScriptDependencies() { + return true; + } } module.exports = JavaScript; diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 7be86a2b7..30377f486 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -189,6 +189,11 @@ class TemplateEngine { needsCompilation(str) { return true; } + + // See https://www.11ty.dev/docs/watch-serve/#watch-javascript-dependencies + static shouldSpiderJavaScriptDependencies() { + return false; + } } module.exports = TemplateEngine; diff --git a/test/EleventyExtensionMapTest.js b/test/EleventyExtensionMapTest.js index bdf5fab72..e5a61061d 100644 --- a/test/EleventyExtensionMapTest.js +++ b/test/EleventyExtensionMapTest.js @@ -151,3 +151,41 @@ test("isFullTemplateFilePath (not a passthrough copy extension)", (t) => { t.false(map.isFullTemplateFilePath("passthrough.js")); t.false(map.isFullTemplateFilePath("passthrough.css")); }); + +test("getValidExtensionsForPath", (t) => { + let cfg = new TemplateConfig(); + cfg.userConfig.extensionMap.add({ + key: "js", + extension: "js", + }); + + let map = getExtensionMap(["liquid", "njk", "11ty.js", "js"], cfg); + + t.deepEqual(map.getValidExtensionsForPath("template.liquid"), ["liquid"]); + t.deepEqual(map.getValidExtensionsForPath("template.11ty.js"), [ + "11ty.js", + "js", + ]); + t.deepEqual(map.getValidExtensionsForPath("template.pug"), []); + t.deepEqual(map.getValidExtensionsForPath("template.liquid.js"), ["js"]); + t.deepEqual(map.getValidExtensionsForPath("njk.liquid.11ty.js"), [ + "11ty.js", + "js", + ]); +}); + +test("shouldSpiderJavaScriptDependencies", (t) => { + let cfg = new TemplateConfig(); + cfg.userConfig.extensionMap.add({ + key: "js", + extension: "js", + }); + + let map = getExtensionMap(["liquid", "njk", "11ty.js", "js"], cfg); + + t.deepEqual(map.shouldSpiderJavaScriptDependencies("template.liquid"), false); + t.deepEqual(map.shouldSpiderJavaScriptDependencies("template.njk"), false); + t.deepEqual(map.shouldSpiderJavaScriptDependencies("template.css"), false); + t.deepEqual(map.shouldSpiderJavaScriptDependencies("template.11ty.js"), true); + t.deepEqual(map.shouldSpiderJavaScriptDependencies("template.js"), false); +}); From 3cb2d714a9e338c52515441a9ef4326f3ec98481 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 2 Jan 2022 14:31:47 -0600 Subject: [PATCH 679/746] Change cache default for custom extensions to true, but only if `read: true` --- src/Engines/Custom.js | 2 ++ test/TemplateTest-CompileOptions.js | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index d57596395..7a9aa1a5f 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -15,6 +15,8 @@ class CustomEngine extends TemplateEngine { // Enable cacheability for this template if (this.entry.compileOptions && "cache" in this.entry.compileOptions) { this.cacheable = this.entry.compileOptions.cache; + } else if (this.needsToReadFileContents()) { + this.cacheable = true; } } diff --git a/test/TemplateTest-CompileOptions.js b/test/TemplateTest-CompileOptions.js index 3065f29c3..2ffb4e0ac 100644 --- a/test/TemplateTest-CompileOptions.js +++ b/test/TemplateTest-CompileOptions.js @@ -2,6 +2,7 @@ const test = require("ava"); const TemplateConfig = require("../src/TemplateConfig"); const TemplateData = require("../src/TemplateData"); +const TemplateContent = require("../src/TemplateContent"); const getNewTemplate = require("./_getNewTemplateForTests"); @@ -11,6 +12,7 @@ test("Custom extension (.txt) with custom permalink compile function", async (t) extension: "txt", key: "txt", compileOptions: { + cache: false, // pass in your own custom permalink function. permalink: async function (permalinkString, inputPath) { t.is(permalinkString, "custom-extension.lit"); @@ -53,6 +55,7 @@ test("Custom extension with and compileOptions.permalink = false", async (t) => extension: "txt", key: "txt", compileOptions: { + cache: false, permalink: false, }, compile: function (str, inputPath) { @@ -88,6 +91,7 @@ test("Custom extension with and opt-out of permalink compilation", async (t) => extension: "txt", key: "txt", compileOptions: { + cache: false, permalink: "raw", }, compile: function (str, inputPath) { @@ -123,6 +127,7 @@ test("Custom extension (.txt) with custom permalink compile function but no perm extension: "txt", key: "txt", compileOptions: { + cache: false, // pass in your own custom permalink function. permalink: async function (permalinkString, inputPath) { t.is(permalinkString, undefined); @@ -166,6 +171,7 @@ test("Custom extension (.txt) with custom permalink compile function (that retur extension: "txt", key: "txt", compileOptions: { + cache: false, permalink: async function (permalinkString, inputPath) { t.is(permalinkString, undefined); t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); @@ -207,6 +213,7 @@ test("Custom extension (.txt) with custom permalink compile function that return extension: "txt", key: "txt", compileOptions: { + cache: false, permalink: async function (permalinkString, inputPath) { t.is(permalinkString, undefined); t.is(inputPath, "./test/stubs/custom-extension-no-permalink.txt"); @@ -247,6 +254,9 @@ test("Custom extension (.txt) that returns undefined from compile", async (t) => eleventyConfig.userConfig.extensionMap.add({ extension: "txt", key: "txt", + compileOptions: { + cache: false, + }, compile: function (str, inputPath) { t.is(str, "Sample content"); return function (data) { From 97570cf77362d84eaa6c66908458beac8db60a30 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 2 Jan 2022 15:27:01 -0600 Subject: [PATCH 680/746] Custom extensions improvement: Make `getData: false` and `getData: []` work without error. --- src/Engines/Custom.js | 24 +++++++---------- test/TemplateTest-CompileOptions.js | 1 - test/TemplateTest-CustomExtensions.js | 38 +++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 test/TemplateTest-CustomExtensions.js diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 7a9aa1a5f..f731eff37 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -67,23 +67,15 @@ class CustomEngine extends TemplateEngine { await this._runningInit(); if ("getData" in this.entry) { - let dataBench = bench.get(`Engine (${this.name}) Get Data From File`); - dataBench.before(); - if (typeof this.entry.getData === "function") { + let dataBench = bench.get( + `Engine (${this.name}) Get Data From File (Function)` + ); + dataBench.before(); let data = this.entry.getData(inputPath); dataBench.after(); return data; } else { - if (!("getInstanceFromInputPath" in this.entry)) { - dataBench.after(); - return Promise.reject( - new Error( - `getInstanceFromInputPath callback missing from ${this.name} template engine plugin.` - ) - ); - } - let keys = new Set(); if (this.entry.getData === true) { keys.add("data"); @@ -94,14 +86,18 @@ class CustomEngine extends TemplateEngine { } if (keys.size === 0) { - dataBench.after(); + return; + } else if (!("getInstanceFromInputPath" in this.entry)) { return Promise.reject( new Error( - `getData must be an array of keys or \`true\` in your addExtension configuration.` + `getInstanceFromInputPath callback missing from ${this.name} template engine plugin.` ) ); } + let dataBench = bench.get(`Engine (${this.name}) Get Data From File`); + dataBench.before(); + let inst = await this.entry.getInstanceFromInputPath(inputPath); let mixins; if (this.config) { diff --git a/test/TemplateTest-CompileOptions.js b/test/TemplateTest-CompileOptions.js index 2ffb4e0ac..5e9e8fa0d 100644 --- a/test/TemplateTest-CompileOptions.js +++ b/test/TemplateTest-CompileOptions.js @@ -2,7 +2,6 @@ const test = require("ava"); const TemplateConfig = require("../src/TemplateConfig"); const TemplateData = require("../src/TemplateData"); -const TemplateContent = require("../src/TemplateContent"); const getNewTemplate = require("./_getNewTemplateForTests"); diff --git a/test/TemplateTest-CustomExtensions.js b/test/TemplateTest-CustomExtensions.js new file mode 100644 index 000000000..178055320 --- /dev/null +++ b/test/TemplateTest-CustomExtensions.js @@ -0,0 +1,38 @@ +const test = require("ava"); + +const TemplateConfig = require("../src/TemplateConfig"); +const TemplateData = require("../src/TemplateData"); +const TemplateContent = require("../src/TemplateContent"); + +const getNewTemplate = require("./_getNewTemplateForTests"); + +test("Custom extension using getData: false", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + cache: false, + }, + getData: false, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "Sample content"); +}); From 4e2ad5e525c93e5a940d73f4ec506d54f95dbe84 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 Jan 2022 10:21:54 -0600 Subject: [PATCH 681/746] A few tweaks and tests for custom file extensions getData --- src/Engines/Custom.js | 113 ++++++++++---------- test/TemplateTest-CustomExtensions.js | 147 +++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 57 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index f731eff37..f9ca3bc54 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -64,72 +64,73 @@ class CustomEngine extends TemplateEngine { } async getExtraDataFromFile(inputPath) { + if (!("getData" in this.entry) || this.entry.getData === false) { + return; + } + await this._runningInit(); - if ("getData" in this.entry) { - if (typeof this.entry.getData === "function") { - let dataBench = bench.get( - `Engine (${this.name}) Get Data From File (Function)` - ); - dataBench.before(); - let data = this.entry.getData(inputPath); - dataBench.after(); - return data; - } else { - let keys = new Set(); - if (this.entry.getData === true) { - keys.add("data"); - } else if (Array.isArray(this.entry.getData)) { - for (let key of this.entry.getData) { - keys.add(key); - } - } + if (typeof this.entry.getData === "function") { + let dataBench = bench.get( + `Engine (${this.name}) Get Data From File (Function)` + ); + dataBench.before(); + let data = this.entry.getData(inputPath); + dataBench.after(); + return data; + } - if (keys.size === 0) { - return; - } else if (!("getInstanceFromInputPath" in this.entry)) { - return Promise.reject( - new Error( - `getInstanceFromInputPath callback missing from ${this.name} template engine plugin.` - ) - ); - } + // if getData is not false or a function then `getInstanceFromInputPath` must exist + if (!("getInstanceFromInputPath" in this.entry)) { + return Promise.reject( + new Error( + `getInstanceFromInputPath callback missing from ${this.name} template engine plugin.` + ) + ); + } - let dataBench = bench.get(`Engine (${this.name}) Get Data From File`); - dataBench.before(); + let keys = new Set(); + if (this.entry.getData === true) { + keys.add("data"); + } else if (Array.isArray(this.entry.getData)) { + for (let key of this.entry.getData) { + keys.add(key); + } + } - let inst = await this.entry.getInstanceFromInputPath(inputPath); - let mixins; - if (this.config) { - // Object.assign usage: see TemplateRenderCustomTest.js: `JavaScript functions should not be mutable but not *that* mutable` - mixins = Object.assign({}, this.config.javascriptFunctions); - } + let dataBench = bench.get(`Engine (${this.name}) Get Data From File`); + dataBench.before(); - // override keys set at the plugin level in the individual template - if (inst.eleventyDataKey) { - keys = new Set(inst.eleventyDataKey); - } + let inst = await this.entry.getInstanceFromInputPath(inputPath); + // override keys set at the plugin level in the individual template + if (inst.eleventyDataKey) { + keys = new Set(inst.eleventyDataKey); + } - let promises = []; - for (let key of keys) { - promises.push( - getJavaScriptData(inst, inputPath, key, { - mixins, - isObjectRequired: key === "data", - }) - ); - } + let mixins; + if (this.config) { + // Object.assign usage: see TemplateRenderCustomTest.js: `JavaScript functions should not be mutable but not *that* mutable` + mixins = Object.assign({}, this.config.javascriptFunctions); + } - let results = await Promise.all(promises); - let data = {}; - for (let result of results) { - Object.assign(data, result); - } - dataBench.after(); + let promises = []; + for (let key of keys) { + promises.push( + getJavaScriptData(inst, inputPath, key, { + mixins, + isObjectRequired: key === "data", + }) + ); + } - return data; - } + let results = await Promise.all(promises); + let data = {}; + for (let result of results) { + Object.assign(data, result); } + dataBench.after(); + + return data; } async compile(str, inputPath, ...args) { diff --git a/test/TemplateTest-CustomExtensions.js b/test/TemplateTest-CustomExtensions.js index 178055320..cc7b3be85 100644 --- a/test/TemplateTest-CustomExtensions.js +++ b/test/TemplateTest-CustomExtensions.js @@ -6,7 +6,7 @@ const TemplateContent = require("../src/TemplateContent"); const getNewTemplate = require("./_getNewTemplateForTests"); -test("Custom extension using getData: false", async (t) => { +test("Using getData: false without getInstanceFromInputPath works ok", async (t) => { let eleventyConfig = new TemplateConfig(); eleventyConfig.userConfig.extensionMap.add({ extension: "txt", @@ -36,3 +36,148 @@ test("Custom extension using getData: false", async (t) => { let data = await tmpl.getData(); t.is(await tmpl.render(data), "Sample content"); }); + +test("Using getData: true without getInstanceFromInputPath should error", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + cache: false, + }, + getData: true, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + await t.throwsAsync(async () => { + await tmpl.getData(); + }); +}); + +test("Using getData: [] without getInstanceFromInputPath should error", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + cache: false, + }, + getData: [], + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + await t.throwsAsync(async () => { + await tmpl.getData(); + }); +}); + +test("Using getData: true and getInstanceFromInputPath to get data from instance", async (t) => { + let globalData = { + topLevelData: true, + }; + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + cache: false, + }, + getData: true, + getInstanceFromInputPath: function () { + return { + data: globalData, + }; + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(data.topLevelData, true); +}); + +test("Using eleventyDataKey to get a different key data from instance", async (t) => { + let globalData = { + topLevelData: true, + }; + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + cache: false, + }, + getData: [], + getInstanceFromInputPath: function () { + return { + eleventyDataKey: ["otherProp"], + otherProp: globalData, + }; + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(data.topLevelData, true); +}); From d8603741ab720234deeddb6dc23161f59509f29a Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 Jan 2022 14:56:57 -0600 Subject: [PATCH 682/746] Tests for `defaultRenderer` --- package.json | 1 + test/TemplateTest-CustomExtensions.js | 190 ++++++++++++++++++++++++++ test/stubs/default-frontmatter.txt | 4 + test/stubs/default-no-liquid.md | 1 + test/stubs/default.liquid | 1 + test/stubs/default.md | 1 + 6 files changed, 198 insertions(+) create mode 100644 test/stubs/default-frontmatter.txt create mode 100644 test/stubs/default-no-liquid.md create mode 100644 test/stubs/default.liquid create mode 100644 test/stubs/default.md diff --git a/package.json b/package.json index ed812eeb0..ae8e3c495 100755 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", "markdown-it-emoji": "^2.0.0", + "marked": "^4.0.8", "nyc": "^15.1.0", "prettier": "^2.5.1", "rimraf": "^3.0.2", diff --git a/test/TemplateTest-CustomExtensions.js b/test/TemplateTest-CustomExtensions.js index cc7b3be85..be03f0454 100644 --- a/test/TemplateTest-CustomExtensions.js +++ b/test/TemplateTest-CustomExtensions.js @@ -181,3 +181,193 @@ test("Using eleventyDataKey to get a different key data from instance", async (t let data = await tmpl.getData(); t.is(data.topLevelData, true); }); + +test("Uses default renderer (no compile function) when you override an existing extension", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "liquid", + key: "liquid", + compileOptions: { + cache: false, + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default.liquid", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "hi"); +}); + +test("Access to default renderer when you override an existing extension", async (t) => { + t.plan(2); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "liquid", + key: "liquid", + compileOptions: { + cache: false, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + t.true(true); + return this.defaultRenderer(); + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default.liquid", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "hi"); +}); + +test("Overridden liquid gets used from a markdown template", async (t) => { + t.plan(2); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "liquid", + key: "liquid", + compileOptions: { + cache: false, + }, + compile: function (str, inputPath) { + // plaintext + return function (data) { + t.true(true); + return this.defaultRenderer(); + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default.md", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is((await tmpl.render(data)).trim(), "

hi

"); +}); + +test("Use marked for markdown", async (t) => { + const { marked } = require("marked"); + + t.plan(2); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "md", + key: "md", + compileOptions: { + cache: false, + }, + compile: function (str, inputPath) { + let html = marked.parse(str); + // plaintext + return function (data) { + t.true(true); + return html; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default-no-liquid.md", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is((await tmpl.render(data)).trim(), "

hi

"); +}); + +test("Use defaultRenderer for markdown", async (t) => { + t.plan(2); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "md", + key: "md", + compileOptions: { + cache: false, + }, + compile: function (str, inputPath) { + return function (data) { + t.true(true); + return this.defaultRenderer(data); + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default.md", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is((await tmpl.render(data)).trim(), "

hi

"); +}); + +test("Front matter in a custom extension", async (t) => { + t.plan(2); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + cache: false, + }, + compile: function (str, inputPath) { + return function (data) { + return str; + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default-frontmatter.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(data.frontmatter, 1); + t.is((await tmpl.render(data)).trim(), "hi"); +}); diff --git a/test/stubs/default-frontmatter.txt b/test/stubs/default-frontmatter.txt new file mode 100644 index 000000000..e679ecf1a --- /dev/null +++ b/test/stubs/default-frontmatter.txt @@ -0,0 +1,4 @@ +--- +frontmatter: 1 +--- +hi \ No newline at end of file diff --git a/test/stubs/default-no-liquid.md b/test/stubs/default-no-liquid.md new file mode 100644 index 000000000..45b983be3 --- /dev/null +++ b/test/stubs/default-no-liquid.md @@ -0,0 +1 @@ +hi diff --git a/test/stubs/default.liquid b/test/stubs/default.liquid new file mode 100644 index 000000000..c498e3e04 --- /dev/null +++ b/test/stubs/default.liquid @@ -0,0 +1 @@ +{{ "hi" }} \ No newline at end of file diff --git a/test/stubs/default.md b/test/stubs/default.md new file mode 100644 index 000000000..a3a4a823d --- /dev/null +++ b/test/stubs/default.md @@ -0,0 +1 @@ +{{ "hi" }} From 34ace733d8240f55bd3bd60fe5ffff66395bfed1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 Jan 2022 16:46:13 -0600 Subject: [PATCH 683/746] Test for #1555 #1865 #1956 --- test/PaginationTest.js | 14 ++++++++++++++ .../pagination-eleventycomputed-permalink.liquid | 13 +++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 test/stubs/pagination-eleventycomputed-permalink.liquid diff --git a/test/PaginationTest.js b/test/PaginationTest.js index a1d67e0c8..25611e93e 100644 --- a/test/PaginationTest.js +++ b/test/PaginationTest.js @@ -814,3 +814,17 @@ test("Pagination template/dir data files run once, Issue 919", async (t) => { t.is(templates[0].data.test, templates[1].data.test); t.is(templates[1].data.test, templates[2].data.test); }); + +test("Pagination and eleventyComputed permalink, issue #1555 and #1865", async (t) => { + let tmpl = getNewTemplate( + "./test/stubs/pagination-eleventycomputed-permalink.liquid", + "./test/stubs/", + "./dist" + ); + + let data = await tmpl.getData(); + let templates = await tmpl.getTemplates(data); + t.is(templates[0].data.page.url, "/venues/first/"); + t.is(templates[1].data.page.url, "/venues/second/"); + t.is(templates[2].data.page.url, "/venues/third/"); +}); diff --git a/test/stubs/pagination-eleventycomputed-permalink.liquid b/test/stubs/pagination-eleventycomputed-permalink.liquid new file mode 100644 index 000000000..b6adf9062 --- /dev/null +++ b/test/stubs/pagination-eleventycomputed-permalink.liquid @@ -0,0 +1,13 @@ +--- +venues: + - first + - second + - third +pagination: + data: venues + size: 1 + alias: venue + addAllPagesToCollections: true +eleventyComputed: + permalink: "venues/{{ venue }}/" +--- From 9514da23cc07e0a6f1c819208bf669185a56f35f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 Jan 2022 17:43:31 -0600 Subject: [PATCH 684/746] .write, .toJSON, and .toNDJSON will now call .init() for you transparently. --- src/Eleventy.js | 28 ++++++++++--- src/Engines/Custom.js | 3 +- test/EleventyTest.js | 91 +++++++++++++++++++++++++++++-------------- 3 files changed, 85 insertions(+), 37 deletions(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index 2cd30c768..d4f3061b6 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -98,6 +98,12 @@ class Eleventy { */ this.isDryRun = false; + /** + * @member {Boolean} - Has init run? + * @default true + */ + this.needsInit = true; + /** * @member {Boolean} - Explicit input directory (usually used when input is a single file/serverless) */ @@ -381,8 +387,12 @@ Verbose Output: ${this.verboseMode}`); this.config.events.emit("eleventy.directories", dirs); - // …why does this return this - return this.templateData.cacheData(); + let data = this.templateData.cacheData(); + + this.needsInit = false; + + // …why does it return this + return data; } // These are all set as initial global data under eleventy.env.* (see TemplateData->environmentVariables) @@ -933,18 +943,26 @@ Arguments: * @returns {Promise<{}>} ret - tbd. */ async executeBuild(to = "fs") { - let ret; - let hasError = false; + if (this.needsInit) { + if (!this._initing) { + this._initing = this.init(); + } + await this._initing; + this.needsInit = false; + } if (!this.writer) { this.errorHandler.fatal( new Error( - "Did you call Eleventy.init to create the TemplateWriter instance? Hint: you probably didn’t." + "Eleventy didn’t run init() properly and wasn’t able to create a TemplateWriter." ), "Problem writing Eleventy templates" ); } + let ret; + let hasError = false; + try { let eventsArg = { inputDir: this.config.inputDir, diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index f9ca3bc54..0383cda36 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -45,8 +45,7 @@ class CustomEngine extends TemplateEngine { return true; } - // If we init from multiple places, wait for the first init to finish - // before continuing on. + // If we init from multiple places, wait for the first init to finish before continuing on. async _runningInit() { if (this.needsInit) { let initBench = bench.get(`Engine (${this.name}) Init`); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index f724ae7a4..378a78df4 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -155,7 +155,7 @@ test("Eleventy set input/output, one file input exitCode", async (t) => { ); elev.setIsVerbose(false); elev.disableLogger(); - await elev.init(); + // await elev.init(); // no longer necessary await elev.write(); t.is(process.exitCode, 1); @@ -167,7 +167,7 @@ test("Eleventy to json", async (t) => { let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); - await elev.init(); + // await elev.init(); // no longer necessary let result = await elev.toJSON(); @@ -200,7 +200,7 @@ test("Eleventy to ndjson", async (t) => { elev.setIsVerbose(false); - await elev.init(); + // await elev.init(); // no longer necessary let stream = await elev.toNDJSON(); let count = 0; @@ -237,33 +237,34 @@ test.cb("Eleventy to ndjson (returns a stream)", (t) => { elev.setIsVerbose(false); - elev.init().then(() => { - elev.toNDJSON().then((stream) => { - let results = []; - stream.on("data", function (jsonObj) { - if (jsonObj.url === "/test/") { - t.deepEqual(jsonObj, { - url: "/test/", - inputPath: "./test/stubs--to/test.md", - outputPath: "_site/test/index.html", - content: "

hi

\n", - }); - } - if (jsonObj.url === "/test2/") { - t.deepEqual(jsonObj, { - url: "/test2/", - inputPath: "./test/stubs--to/test2.liquid", - outputPath: "_site/test2/index.html", - content: "hello", - }); - } - - results.push(jsonObj); - - if (results.length >= 2) { - t.end(); - } - }); + // elev.init().then(() => { // no longer necessary + // }); + + elev.toNDJSON().then((stream) => { + let results = []; + stream.on("data", function (jsonObj) { + if (jsonObj.url === "/test/") { + t.deepEqual(jsonObj, { + url: "/test/", + inputPath: "./test/stubs--to/test.md", + outputPath: "_site/test/index.html", + content: "

hi

\n", + }); + } + if (jsonObj.url === "/test2/") { + t.deepEqual(jsonObj, { + url: "/test2/", + inputPath: "./test/stubs--to/test2.liquid", + outputPath: "_site/test2/index.html", + content: "hello", + }); + } + + results.push(jsonObj); + + if (results.length >= 2) { + t.end(); + } }); }); }); @@ -291,3 +292,33 @@ test("Config propagates to other instances correctly", async (t) => { t.is(elev.templateData.eleventyConfig, elev.eleventyConfig); t.is(elev.writer.eleventyConfig, elev.eleventyConfig); }); + +test("Eleventy programmatic API without init", async (t) => { + let elev = new Eleventy("./test/stubs--to/"); + elev.setIsVerbose(false); + + let result = await elev.toJSON(); + + t.deepEqual( + result.filter((entry) => entry.url === "/test/"), + [ + { + url: "/test/", + inputPath: "./test/stubs--to/test.md", + outputPath: "_site/test/index.html", + content: "

hi

\n", + }, + ] + ); + t.deepEqual( + result.filter((entry) => entry.url === "/test2/"), + [ + { + url: "/test2/", + inputPath: "./test/stubs--to/test2.liquid", + outputPath: "_site/test2/index.html", + content: "hello", + }, + ] + ); +}); From a2186071a915bea1a40a5d1ba148acf58a7bdb7e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 Jan 2022 17:51:13 -0600 Subject: [PATCH 685/746] Run executeBuild twice, in parallel --- test/EleventyTest.js | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 378a78df4..3fc07c9f9 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -322,3 +322,48 @@ test("Eleventy programmatic API without init", async (t) => { ] ); }); + +test("Can Eleventy run two executeBuilds in parallel?", async (t) => { + let elev = new Eleventy("./test/stubs--to/"); + elev.setIsVerbose(false); + + let p1 = elev.toJSON(); + let p2 = elev.toJSON(); + let [result1, result2] = await Promise.all([p1, p2]); + + let test1Result = [ + { + url: "/test/", + inputPath: "./test/stubs--to/test.md", + outputPath: "_site/test/index.html", + content: "

hi

\n", + }, + ]; + + let test2Result = [ + { + url: "/test2/", + inputPath: "./test/stubs--to/test2.liquid", + outputPath: "_site/test2/index.html", + content: "hello", + }, + ]; + + t.deepEqual( + result1.filter((entry) => entry.url === "/test/"), + test1Result + ); + t.deepEqual( + result1.filter((entry) => entry.url === "/test2/"), + test2Result + ); + + t.deepEqual( + result2.filter((entry) => entry.url === "/test/"), + test1Result + ); + t.deepEqual( + result2.filter((entry) => entry.url === "/test2/"), + test2Result + ); +}); From e343879a2b6d5e46180f8e6bb05c8cbe006c1bfb Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 3 Jan 2022 23:15:40 -0600 Subject: [PATCH 686/746] Comment tweak [skip ci] --- src/Eleventy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Eleventy.js b/src/Eleventy.js index d4f3061b6..76e3ea983 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -99,7 +99,7 @@ class Eleventy { this.isDryRun = false; /** - * @member {Boolean} - Has init run? + * @member {Boolean} - Does the init() method still need to be run (or hasn’t finished yet) * @default true */ this.needsInit = true; From 1d08541d922039fd34ed06014f71e1c12a0aa460 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 Jan 2022 09:54:59 -0600 Subject: [PATCH 687/746] Update deps --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ae8e3c495..44ca4c9c8 100755 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "nyc": "^15.1.0", "prettier": "^2.5.1", "rimraf": "^3.0.2", - "sass": "^1.45.0", + "sass": "^1.45.2", "toml": "^3.0.0", "vue": "^3.2.1" }, @@ -108,9 +108,9 @@ "handlebars": "^4.7.7", "is-glob": "^4.0.3", "kleur": "^4.1.4 ", - "liquidjs": "^9.30.0", + "liquidjs": "^9.32.0", "lodash": "^4.17.21", - "luxon": "^2.2.0", + "luxon": "^2.3.0", "markdown-it": "^12.3.0", "minimist": "^1.2.5", "moo": "^0.5.1", @@ -124,6 +124,6 @@ "pug": "^3.0.2", "recursive-copy": "^2.0.13", "semver": "^7.3.5", - "slugify": "^1.6.4" + "slugify": "^1.6.5" } } From 223f9ab49e5f9ff71693f47b91dc96b1133f5179 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 Jan 2022 10:12:58 -0600 Subject: [PATCH 688/746] Updates to ava 4 https://github.com/avajs/ava/releases/tag/v4.0.0 --- package.json | 2 +- test/BenchmarkTest.js | 56 +++++++++++++------------ test/EleventyTest.js | 12 +++--- test/UserConfigTest.js | 58 ++++++++++++++------------ test/cmdTest.js | 95 +++++++++++++++++++++++------------------- 5 files changed, 121 insertions(+), 102 deletions(-) diff --git a/package.json b/package.json index 44ca4c9c8..94e94036d 100755 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", "@vue/server-renderer": "^3.2.26", - "ava": "^3.15.0", + "ava": "^4.0.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index e6f5e633e..7a26fb730 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -6,19 +6,20 @@ function between(t, value, lowerBound, upperBound) { t.truthy(value <= upperBound); } -test.cb("Standard Benchmark", (t) => { - let b = new Benchmark(); - b.before(); - setTimeout(function () { - b.after(); - t.truthy(b.getTotal() >= 0); - t.end(); - }, 100); +test("Standard Benchmark", async (t) => { + await new Promise((resolve) => { + let b = new Benchmark(); + b.before(); + setTimeout(function () { + b.after(); + t.truthy(b.getTotal() >= 0); + resolve(); + }, 100); + }); }); -test.cb( - "Nested Benchmark (nested calls are ignored while a parent is measuring)", - (t) => { +test("Nested Benchmark (nested calls are ignored while a parent is measuring)", async (t) => { + await new Promise((resolve) => { let b = new Benchmark(); b.before(); @@ -29,24 +30,27 @@ test.cb( b.after(); t.truthy(b.getTotal() >= 10); - t.end(); + resolve(); }, 100); - } -); - -test.cb("Reset Benchmark", (t) => { - let b = new Benchmark(); - b.before(); - b.reset(); + }); +}); - setTimeout(function () { +test("Reset Benchmark", async (t) => { + await new Promise((resolve) => { + let b = new Benchmark(); b.before(); - b.after(); + b.reset(); - t.throws(function () { - // throws because we reset + setTimeout(function () { + b.before(); b.after(); - }); - t.end(); - }, 100); + + t.throws(function () { + // throws because we reset + b.after(); + }); + + resolve(); + }, 100); + }); }); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 3fc07c9f9..1d65b89fc 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -232,17 +232,17 @@ test("Eleventy to ndjson", async (t) => { }); }); -test.cb("Eleventy to ndjson (returns a stream)", (t) => { +test("Eleventy to ndjson (returns a stream)", async (t) => { let elev = new Eleventy("./test/stubs--to/"); elev.setIsVerbose(false); - // elev.init().then(() => { // no longer necessary - // }); + let stream = await elev.toNDJSON(); - elev.toNDJSON().then((stream) => { + await new Promise((resolve) => { let results = []; - stream.on("data", function (jsonObj) { + stream.on("data", function (entry) { + let jsonObj = JSON.parse(entry); if (jsonObj.url === "/test/") { t.deepEqual(jsonObj, { url: "/test/", @@ -263,7 +263,7 @@ test.cb("Eleventy to ndjson (returns a stream)", (t) => { results.push(jsonObj); if (results.length >= 2) { - t.end(); + resolve(); } }); }); diff --git a/test/UserConfigTest.js b/test/UserConfigTest.js index 23e389749..7e9889b1a 100644 --- a/test/UserConfigTest.js +++ b/test/UserConfigTest.js @@ -43,36 +43,40 @@ test("Template Formats (Arrays)", (t) => { // more in TemplateConfigTest.js -test.cb("Events", (t) => { - let userCfg = new UserConfig(); - userCfg.on("testEvent", function (arg1, arg2, arg3) { - t.is(arg1, "arg1"); - t.is(arg2, "arg2"); - t.is(arg3, "arg3"); - t.end(); +test("Events", async (t) => { + await new Promise((resolve) => { + let userCfg = new UserConfig(); + userCfg.on("testEvent", function (arg1, arg2, arg3) { + t.is(arg1, "arg1"); + t.is(arg2, "arg2"); + t.is(arg3, "arg3"); + resolve(); + }); + + userCfg.emit("testEvent", "arg1", "arg2", "arg3"); }); - - userCfg.emit("testEvent", "arg1", "arg2", "arg3"); }); -test.cb("Async Events", (t) => { - let userCfg = new UserConfig(); - let arg1; - - userCfg.on( - "asyncTestEvent", - (_arg1) => - new Promise((resolve) => { - setTimeout(() => { - arg1 = _arg1; - resolve(); - }, 10); - }) - ); - - userCfg.emit("asyncTestEvent", "arg1").then(() => { - t.is(arg1, "arg1"); - t.end(); +test("Async Events", async (t) => { + await new Promise((resolve) => { + let userCfg = new UserConfig(); + let arg1; + + userCfg.on( + "asyncTestEvent", + (_arg1) => + new Promise((resolve) => { + setTimeout(() => { + arg1 = _arg1; + resolve(); + }, 10); + }) + ); + + userCfg.emit("asyncTestEvent", "arg1").then(() => { + t.is(arg1, "arg1"); + resolve(); + }); }); }); diff --git a/test/cmdTest.js b/test/cmdTest.js index 6fb63bf07..988ed7b05 100644 --- a/test/cmdTest.js +++ b/test/cmdTest.js @@ -1,54 +1,65 @@ const test = require("ava"); const { exec } = require("child_process"); +const { resolve } = require("path"); -test.cb("Test command line exit code success", (t) => { - exec( - "node ./cmd.js --input=test/stubs/exitCode_success --dryrun", - (error, stdout, stderr) => { - t.falsy(error); - t.end(); - } - ); +test("Test command line exit code success", async (t) => { + await new Promise((resolve) => { + exec( + "node ./cmd.js --input=test/stubs/exitCode_success --dryrun", + (error, stdout, stderr) => { + t.falsy(error); + resolve(); + } + ); + }); }); -test.cb("Test command line exit code for template error", (t) => { - exec( - "node ./cmd.js --input=test/stubs/exitCode --dryrun", - (error, stdout, stderr) => { - t.is(error.code, 1); - t.end(); - } - ); +test("Test command line exit code for template error", async (t) => { + await new Promise((resolve) => { + exec( + "node ./cmd.js --input=test/stubs/exitCode --dryrun", + (error, stdout, stderr) => { + t.is(error.code, 1); + resolve(); + } + ); + }); }); -test.cb("Test command line exit code for global data error", (t) => { - exec( - "node ./cmd.js --input=test/stubs/exitCode_globalData --dryrun", - (error, stdout, stderr) => { - t.is(error.code, 1); - t.end(); - } - ); +test("Test command line exit code for global data error", async (t) => { + await new Promise((resolve) => { + exec( + "node ./cmd.js --input=test/stubs/exitCode_globalData --dryrun", + (error, stdout, stderr) => { + t.is(error.code, 1); + resolve(); + } + ); + }); }); -test.cb("Test data should not process in a --help", (t) => { - exec( - "node ./cmd.js --input=test/stubs/cmd-help-processing --help", - (error, stdout, stderr) => { - t.falsy(error); - t.is(stdout.indexOf("THIS SHOULD NOT LOG TO CONSOLE"), -1); - t.end(); - } - ); +test("Test data should not process in a --help", async (t) => { + await new Promise((resolve) => { + exec( + "node ./cmd.js --input=test/stubs/cmd-help-processing --help", + (error, stdout, stderr) => { + t.falsy(error); + t.is(stdout.indexOf("THIS SHOULD NOT LOG TO CONSOLE"), -1); + resolve(); + } + ); + }); }); -test.cb("Test data should not process in a --version", (t) => { - exec( - "node ./cmd.js --input=test/stubs/cmd-help-processing --version", - (error, stdout, stderr) => { - t.falsy(error); - t.is(stdout.indexOf("THIS SHOULD NOT LOG TO CONSOLE"), -1); - t.end(); - } - ); +test("Test data should not process in a --version", async (t) => { + await new Promise((resolve) => { + exec( + "node ./cmd.js --input=test/stubs/cmd-help-processing --version", + (error, stdout, stderr) => { + t.falsy(error); + t.is(stdout.indexOf("THIS SHOULD NOT LOG TO CONSOLE"), -1); + resolve(); + } + ); + }); }); From 730252a065166518a303f453c9bfbd993611d0d1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 Jan 2022 10:17:19 -0600 Subject: [PATCH 689/746] Minor tweak for local test stability --- test/TemplateTest-CustomExtensions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/TemplateTest-CustomExtensions.js b/test/TemplateTest-CustomExtensions.js index be03f0454..de92fbb52 100644 --- a/test/TemplateTest-CustomExtensions.js +++ b/test/TemplateTest-CustomExtensions.js @@ -250,9 +250,10 @@ test("Overridden liquid gets used from a markdown template", async (t) => { cache: false, }, compile: function (str, inputPath) { + t.true(true); + // plaintext return function (data) { - t.true(true); return this.defaultRenderer(); }; }, From 32730c42383c23cddd37e2b4f0a70ef0b9e0fb66 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 Jan 2022 10:24:00 -0600 Subject: [PATCH 690/746] v1.0.0-canary.50 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 94e94036d..1acf63419 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.9", + "version": "1.0.0-canary.50", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From ef494a922ad294dc1fbb968330116c0678a57123 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 4 Jan 2022 10:26:37 -0600 Subject: [PATCH 691/746] v1.0.0-beta.10 --- docs-src/_data/coverage.json | 24 ++++++++++++------------ docs/coverage.md | 26 +++++++++++++------------- package.json | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index caeafdf38..eafa799aa 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":4848,"covered":4057,"skipped":0,"pct":83.68},"statements":{"total":4875,"covered":4081,"skipped":0,"pct":83.71},"functions":{"total":1055,"covered":892,"skipped":0,"pct":84.54},"branches":{"total":2223,"covered":1676,"skipped":0,"pct":75.39},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":4911,"covered":4117,"skipped":0,"pct":83.83},"statements":{"total":4939,"covered":4142,"skipped":0,"pct":83.86},"functions":{"total":1064,"covered":901,"skipped":0,"pct":84.68},"branches":{"total":2275,"covered":1722,"skipped":0,"pct":75.69},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":53,"covered":33,"skipped":0,"pct":62.26},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":53,"covered":33,"skipped":0,"pct":62.26},"branches":{"total":22,"covered":13,"skipped":0,"pct":59.09}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -16,31 +16,31 @@ ,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.03},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.03},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.62}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":26,"covered":24,"skipped":0,"pct":92.3},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":26,"covered":24,"skipped":0,"pct":92.3},"branches":{"total":7,"covered":5,"skipped":0,"pct":71.42}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":314,"covered":201,"skipped":0,"pct":64.01},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":315,"covered":201,"skipped":0,"pct":63.8},"branches":{"total":113,"covered":72,"skipped":0,"pct":63.71}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":323,"covered":210,"skipped":0,"pct":65.01},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":324,"covered":210,"skipped":0,"pct":64.81},"branches":{"total":117,"covered":76,"skipped":0,"pct":64.95}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheckError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":38,"covered":35,"skipped":0,"pct":92.1},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":38,"covered":35,"skipped":0,"pct":92.1},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.56}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":82,"covered":80,"skipped":0,"pct":97.56},"functions":{"total":25,"covered":24,"skipped":0,"pct":96},"statements":{"total":82,"covered":80,"skipped":0,"pct":97.56},"branches":{"total":39,"covered":35,"skipped":0,"pct":89.74}} -,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":191,"covered":170,"skipped":0,"pct":89},"functions":{"total":45,"covered":40,"skipped":0,"pct":88.88},"statements":{"total":193,"covered":172,"skipped":0,"pct":89.11},"branches":{"total":71,"covered":53,"skipped":0,"pct":74.64}} +,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":107,"covered":104,"skipped":0,"pct":97.19},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":107,"covered":104,"skipped":0,"pct":97.19},"branches":{"total":49,"covered":43,"skipped":0,"pct":87.75}} +,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":191,"covered":171,"skipped":0,"pct":89.52},"functions":{"total":45,"covered":40,"skipped":0,"pct":88.88},"statements":{"total":193,"covered":173,"skipped":0,"pct":89.63},"branches":{"total":73,"covered":56,"skipped":0,"pct":76.71}} ,"/Users/zachleat/Code/eleventy/src/EleventyServe.js": {"lines":{"total":70,"covered":26,"skipped":0,"pct":37.14},"functions":{"total":16,"covered":9,"skipped":0,"pct":56.25},"statements":{"total":70,"covered":26,"skipped":0,"pct":37.14},"branches":{"total":36,"covered":9,"skipped":0,"pct":25}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":39,"covered":39,"skipped":0,"pct":100},"functions":{"total":17,"covered":17,"skipped":0,"pct":100},"statements":{"total":40,"covered":40,"skipped":0,"pct":100},"branches":{"total":21,"covered":19,"skipped":0,"pct":90.47}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} ,"/Users/zachleat/Code/eleventy/src/EventBus.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":95,"covered":72,"skipped":0,"pct":75.78},"functions":{"total":14,"covered":12,"skipped":0,"pct":85.71},"statements":{"total":95,"covered":72,"skipped":0,"pct":75.78},"branches":{"total":38,"covered":24,"skipped":0,"pct":63.15}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":406,"covered":378,"skipped":0,"pct":93.1},"functions":{"total":71,"covered":69,"skipped":0,"pct":97.18},"statements":{"total":408,"covered":380,"skipped":0,"pct":93.13},"branches":{"total":183,"covered":157,"skipped":0,"pct":85.79}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":411,"covered":383,"skipped":0,"pct":93.18},"functions":{"total":71,"covered":69,"skipped":0,"pct":97.18},"statements":{"total":413,"covered":385,"skipped":0,"pct":93.22},"branches":{"total":195,"covered":168,"skipped":0,"pct":86.15}} ,"/Users/zachleat/Code/eleventy/src/TemplateBehavior.js": {"lines":{"total":24,"covered":21,"skipped":0,"pct":87.5},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":24,"covered":21,"skipped":0,"pct":87.5},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":86,"covered":74,"skipped":0,"pct":86.04},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":86,"covered":74,"skipped":0,"pct":86.04},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":202,"covered":182,"skipped":0,"pct":90.09},"functions":{"total":36,"covered":35,"skipped":0,"pct":97.22},"statements":{"total":202,"covered":182,"skipped":0,"pct":90.09},"branches":{"total":107,"covered":84,"skipped":0,"pct":78.5}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":206,"covered":184,"skipped":0,"pct":89.32},"functions":{"total":36,"covered":35,"skipped":0,"pct":97.22},"statements":{"total":206,"covered":184,"skipped":0,"pct":89.32},"branches":{"total":111,"covered":86,"skipped":0,"pct":77.47}} ,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":264,"covered":252,"skipped":0,"pct":95.45},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":267,"covered":255,"skipped":0,"pct":95.5},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} ,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":52,"covered":50,"skipped":0,"pct":96.15},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":50,"skipped":0,"pct":96.15},"branches":{"total":34,"covered":33,"skipped":0,"pct":97.05}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateGlob.js": {"lines":{"total":15,"covered":14,"skipped":0,"pct":93.33},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":78,"covered":72,"skipped":0,"pct":92.3},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":79,"covered":73,"skipped":0,"pct":92.4},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":48,"covered":44,"skipped":0,"pct":91.66},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":48,"covered":44,"skipped":0,"pct":91.66},"branches":{"total":22,"covered":18,"skipped":0,"pct":81.81}} -,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":277,"covered":268,"skipped":0,"pct":96.75},"functions":{"total":37,"covered":35,"skipped":0,"pct":94.59},"statements":{"total":277,"covered":268,"skipped":0,"pct":96.75},"branches":{"total":150,"covered":129,"skipped":0,"pct":86}} +,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":279,"covered":270,"skipped":0,"pct":96.77},"functions":{"total":37,"covered":35,"skipped":0,"pct":94.59},"statements":{"total":279,"covered":270,"skipped":0,"pct":96.77},"branches":{"total":152,"covered":131,"skipped":0,"pct":86.18}} ,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":60,"covered":57,"skipped":0,"pct":95},"functions":{"total":14,"covered":13,"skipped":0,"pct":92.85},"statements":{"total":60,"covered":57,"skipped":0,"pct":95},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":93,"covered":80,"skipped":0,"pct":86.02},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":93,"covered":80,"skipped":0,"pct":86.02},"branches":{"total":38,"covered":27,"skipped":0,"pct":71.05}} ,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":98,"covered":98,"skipped":0,"pct":100},"functions":{"total":28,"covered":27,"skipped":0,"pct":96.42},"statements":{"total":99,"covered":99,"skipped":0,"pct":100},"branches":{"total":55,"covered":55,"skipped":0,"pct":100}} @@ -49,18 +49,18 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} ,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":168,"skipped":0,"pct":68.29},"functions":{"total":65,"covered":40,"skipped":0,"pct":61.53},"statements":{"total":246,"covered":168,"skipped":0,"pct":68.29},"branches":{"total":101,"covered":52,"skipped":0,"pct":51.48}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":84,"covered":70,"skipped":0,"pct":83.33},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":84,"covered":70,"skipped":0,"pct":83.33},"branches":{"total":54,"covered":40,"skipped":0,"pct":74.07}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":90,"covered":79,"skipped":0,"pct":87.77},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":91,"covered":80,"skipped":0,"pct":87.91},"branches":{"total":60,"covered":48,"skipped":0,"pct":80}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":29,"covered":29,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":29,"covered":29,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Html.js": {"lines":{"total":12,"covered":12,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":12,"covered":12,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":59,"covered":57,"skipped":0,"pct":96.61},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":60,"covered":58,"skipped":0,"pct":96.66},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/Engines/JavaScript.js": {"lines":{"total":60,"covered":58,"skipped":0,"pct":96.66},"functions":{"total":14,"covered":14,"skipped":0,"pct":100},"statements":{"total":61,"covered":59,"skipped":0,"pct":96.72},"branches":{"total":42,"covered":35,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Engines/Liquid.js": {"lines":{"total":86,"covered":84,"skipped":0,"pct":97.67},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":87,"covered":85,"skipped":0,"pct":97.7},"branches":{"total":23,"covered":19,"skipped":0,"pct":82.6}} ,"/Users/zachleat/Code/eleventy/src/Engines/Markdown.js": {"lines":{"total":35,"covered":32,"skipped":0,"pct":91.42},"functions":{"total":9,"covered":8,"skipped":0,"pct":88.88},"statements":{"total":35,"covered":32,"skipped":0,"pct":91.42},"branches":{"total":16,"covered":13,"skipped":0,"pct":81.25}} ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":203,"covered":138,"skipped":0,"pct":67.98},"functions":{"total":49,"covered":37,"skipped":0,"pct":75.51},"statements":{"total":203,"covered":138,"skipped":0,"pct":67.98},"branches":{"total":84,"covered":54,"skipped":0,"pct":64.28}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":74,"covered":73,"skipped":0,"pct":98.64},"functions":{"total":25,"covered":25,"skipped":0,"pct":100},"statements":{"total":76,"covered":75,"skipped":0,"pct":98.68},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":75,"covered":74,"skipped":0,"pct":98.66},"functions":{"total":26,"covered":26,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentUnrenderedTemplateError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -69,8 +69,8 @@ ,"/Users/zachleat/Code/eleventy/src/Filters/Slug.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} -,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":136,"covered":121,"skipped":0,"pct":88.97},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":140,"covered":125,"skipped":0,"pct":89.28},"branches":{"total":90,"covered":70,"skipped":0,"pct":77.77}} -,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":108,"covered":97,"skipped":0,"pct":89.81},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":110,"covered":99,"skipped":0,"pct":90},"branches":{"total":45,"covered":30,"skipped":0,"pct":66.66}} +,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":138,"covered":123,"skipped":0,"pct":89.13},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":142,"covered":127,"skipped":0,"pct":89.43},"branches":{"total":94,"covered":74,"skipped":0,"pct":78.72}} +,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":116,"covered":101,"skipped":0,"pct":87.06},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":118,"covered":103,"skipped":0,"pct":87.28},"branches":{"total":53,"covered":34,"skipped":0,"pct":64.15}} ,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":186,"covered":12,"skipped":0,"pct":6.45},"functions":{"total":34,"covered":0,"skipped":0,"pct":0},"statements":{"total":188,"covered":12,"skipped":0,"pct":6.38},"branches":{"total":91,"covered":0,"skipped":0,"pct":0}} ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":28,"covered":24,"skipped":0,"pct":85.71},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":28,"covered":24,"skipped":0,"pct":85.71},"branches":{"total":19,"covered":17,"skipped":0,"pct":89.47}} diff --git a/docs/coverage.md b/docs/coverage.md index b3dc63d03..aa8989821 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,8 +1,8 @@ -# Code Coverage for Eleventy v1.0.0-beta.9 +# Code Coverage for Eleventy v1.0.0-beta.10 | Filename | % Lines | % Statements | % Functions | % Branches | | ------------------------------------------------------------------------ | ------- | ------------ | ----------- | ---------- | -| `total` | 83.68% | 83.71% | 84.54% | 75.39% | +| `total` | 83.83% | 83.86% | 84.68% | 75.69% | | `cmd.js` | 62.26% | 62.26% | 9.09% | 59.09% | | `.cache/vue/include.js` | 100% | 100% | 100% | 100% | | `.cache/vue/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | @@ -20,31 +20,31 @@ | `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | | `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | | `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | -| `src/Eleventy.js` | 64.01% | 63.8% | 67.34% | 63.71% | +| `src/Eleventy.js` | 65.01% | 64.81% | 67.34% | 64.95% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | | `src/EleventyErrorHandler.js` | 92.1% | 92.1% | 100% | 67.56% | | `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | -| `src/EleventyExtensionMap.js` | 97.56% | 97.56% | 96% | 89.74% | -| `src/EleventyFiles.js` | 89% | 89.11% | 88.88% | 74.64% | +| `src/EleventyExtensionMap.js` | 97.19% | 97.19% | 96.66% | 87.75% | +| `src/EleventyFiles.js` | 89.52% | 89.63% | 88.88% | 76.71% | | `src/EleventyServe.js` | 37.14% | 37.14% | 56.25% | 25% | | `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | | `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | | `src/EventBus.js` | 100% | 100% | 100% | 100% | | `src/Serverless.js` | 75.78% | 75.78% | 85.71% | 63.15% | -| `src/Template.js` | 93.1% | 93.13% | 97.18% | 85.79% | +| `src/Template.js` | 93.18% | 93.22% | 97.18% | 86.15% | | `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | | `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | | `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | | `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | -| `src/TemplateContent.js` | 90.09% | 90.09% | 97.22% | 78.5% | +| `src/TemplateContent.js` | 89.32% | 89.32% | 97.22% | 77.47% | | `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | | `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | | `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | | `src/TemplateLayout.js` | 92.3% | 92.4% | 100% | 85% | | `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | -| `src/TemplateMap.js` | 96.75% | 96.75% | 94.59% | 86% | +| `src/TemplateMap.js` | 96.77% | 96.77% | 94.59% | 86.18% | | `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | | `src/TemplatePassthroughManager.js` | 86.02% | 86.02% | 100% | 71.05% | | `src/TemplatePath.js` | 100% | 100% | 96.42% | 100% | @@ -53,18 +53,18 @@ | `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | | `src/UserConfig.js` | 68.29% | 68.29% | 61.53% | 51.48% | | `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | -| `src/Engines/Custom.js` | 83.33% | 83.33% | 100% | 74.07% | +| `src/Engines/Custom.js` | 87.77% | 87.91% | 100% | 80% | | `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | | `src/Engines/Html.js` | 100% | 100% | 100% | 100% | -| `src/Engines/JavaScript.js` | 96.61% | 96.66% | 100% | 83.33% | +| `src/Engines/JavaScript.js` | 96.66% | 96.72% | 100% | 83.33% | | `src/Engines/Liquid.js` | 97.67% | 97.7% | 96.66% | 82.6% | | `src/Engines/Markdown.js` | 91.42% | 91.42% | 88.88% | 81.25% | | `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | | `src/Engines/Nunjucks.js` | 67.98% | 67.98% | 75.51% | 64.28% | | `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | -| `src/Engines/TemplateEngine.js` | 98.64% | 98.68% | 100% | 93.75% | +| `src/Engines/TemplateEngine.js` | 98.66% | 98.7% | 100% | 93.75% | | `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | | `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | | `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | @@ -73,8 +73,8 @@ | `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | | `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | | `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | -| `src/Plugins/Pagination.js` | 88.97% | 89.28% | 91.3% | 77.77% | -| `src/Plugins/RenderPlugin.js` | 89.81% | 90% | 91.3% | 66.66% | +| `src/Plugins/Pagination.js` | 89.13% | 89.43% | 91.3% | 78.72% | +| `src/Plugins/RenderPlugin.js` | 87.06% | 87.28% | 91.3% | 64.15% | | `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | | `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | | `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | diff --git a/package.json b/package.json index 1acf63419..be98de2de 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-canary.50", + "version": "1.0.0-beta.10", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From fca0104e02006ae15be892e08959670f7e415864 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 7 Jan 2022 20:07:54 -0600 Subject: [PATCH 692/746] Require key for cacheable custom template extensions --- src/TemplateContent.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 824d58e30..65e3734eb 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -269,18 +269,20 @@ class TemplateContent { str, bypassMarkdown ); - if (cacheable && cache.has(key)) { - return cache.get(key); + if (cacheable && key) { + if (cache.has(key)) { + return cache.get(key); + } + + // Compilation is async, so we eagerly cache a Promise that eventually + // resolves to the compiled function + cache.set( + key, + new Promise((resolve) => { + res = resolve; + }) + ); } - - // Compilation is async, so we eagerly cache a Promise that eventually - // resolves to the compiled function - cache.set( - key, - new Promise((resolve) => { - res = resolve; - }) - ); } let templateBenchmark = bench.get("Template Compile"); @@ -299,7 +301,7 @@ class TemplateContent { return fn; } catch (e) { let [cacheable, key, cache] = this._getCompileCache(str, bypassMarkdown); - if (cacheable) { + if (cacheable && key) { cache.delete(key); } debug(`Having trouble compiling template ${this.inputPath}: %O`, str); From 2d5be6c681eaed65b66975831565e6875fe874a3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 7 Jan 2022 20:08:25 -0600 Subject: [PATCH 693/746] Fixed: benchmark was misreporting too many init calls --- src/Engines/Custom.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 0383cda36..7b13ec12d 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -48,9 +48,9 @@ class CustomEngine extends TemplateEngine { // If we init from multiple places, wait for the first init to finish before continuing on. async _runningInit() { if (this.needsInit) { - let initBench = bench.get(`Engine (${this.name}) Init`); - initBench.before(); if (!this._initing) { + this._initBench = bench.get(`Engine (${this.name}) Init`); + this._initBench.before(); this._initing = this.entry.init.bind({ config: this.config, bench, @@ -58,7 +58,11 @@ class CustomEngine extends TemplateEngine { } await this._initing; this.needsInit = false; - initBench.after(); + + if (this._initBench) { + this._initBench.after(); + this._initBench = undefined; + } } } From 7b8b43ba0d777e0f66626a4cc34c7f976ced73c0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 7 Jan 2022 20:09:24 -0600 Subject: [PATCH 694/746] Adds support for `serverlessFilter` as a more straightforward way to fetch the chunk of paginated data in a serverless call --- src/Plugins/Pagination.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Plugins/Pagination.js b/src/Plugins/Pagination.js index 5424f5fe0..94e37b0df 100755 --- a/src/Plugins/Pagination.js +++ b/src/Plugins/Pagination.js @@ -78,9 +78,19 @@ class Pagination { // Warn: this doesn’t run filter/before/pagination transformations // Warn: `pagination.pages`, pageNumber, links, hrefs, etc let serverlessPaginationKey = this._get(data, data.pagination.serverless); - this.chunkedItems = [ - [this._get(this.fullDataSet, serverlessPaginationKey)], - ]; + + if (typeof data.pagination.serverlessFilter === "function") { + this.chunkedItems = [ + data.pagination.serverlessFilter( + this.fullDataSet, + serverlessPaginationKey + ), + ]; + } else { + this.chunkedItems = [ + [this._get(this.fullDataSet, serverlessPaginationKey)], + ]; + } } else { // this returns an array this.target = this._resolveItems(); @@ -311,7 +321,10 @@ class Pagination { // TODO maybe also move this permalink additions up into the pagination class let hasPermalinkField = Boolean(this.data[this.config.keys.permalink]); - let hasComputedPermalinkField = Boolean(this.data.eleventyComputed && this.data.eleventyComputed[this.config.keys.permalink]); + let hasComputedPermalinkField = Boolean( + this.data.eleventyComputed && + this.data.eleventyComputed[this.config.keys.permalink] + ); if (pageNumber > 0 && !(hasPermalinkField || hasComputedPermalinkField)) { cloned.setExtraOutputSubdirectory(pageNumber); } From 2c606a94f53ca0cc50bb0b1fcccf165b4b959ce5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 8 Jan 2022 14:14:06 -0600 Subject: [PATCH 695/746] Update deps --- package.json | 14 +++++++------- src/BenchmarkManager.js | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index be98de2de..a59bc4864 100755 --- a/package.json +++ b/package.json @@ -79,18 +79,18 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", "@vue/server-renderer": "^3.2.26", - "ava": "^4.0.0", + "ava": "^4.0.1", "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", "markdown-it-emoji": "^2.0.0", - "marked": "^4.0.8", + "marked": "^4.0.9", "nyc": "^15.1.0", "prettier": "^2.5.1", "rimraf": "^3.0.2", - "sass": "^1.45.2", + "sass": "^1.47.0", "toml": "^3.0.0", - "vue": "^3.2.1" + "vue": "^3.2.26" }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", @@ -101,8 +101,8 @@ "debug": "^4.3.3", "dependency-graph": "^0.11.0", "ejs": "^3.1.6", - "fast-glob": "^3.2.7", - "graceful-fs": "^4.2.8", + "fast-glob": "^3.2.9", + "graceful-fs": "^4.2.9", "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", @@ -111,7 +111,7 @@ "liquidjs": "^9.32.0", "lodash": "^4.17.21", "luxon": "^2.3.0", - "markdown-it": "^12.3.0", + "markdown-it": "^12.3.2", "minimist": "^1.2.5", "moo": "^0.5.1", "multimatch": "^5.0.0", diff --git a/src/BenchmarkManager.js b/src/BenchmarkManager.js index 1f2d1537f..fd2967cb7 100644 --- a/src/BenchmarkManager.js +++ b/src/BenchmarkManager.js @@ -1,6 +1,8 @@ const BenchmarkGroup = require("./BenchmarkGroup"); const { performance } = require("perf_hooks"); +// TODO this should not be a singleton, it belongs in the config or somewhere on the Eleventy instance. + class BenchmarkManager { constructor() { this.benchmarkGroups = {}; From c8741c002181929c2efabba410b20f98e4e0d91d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sat, 8 Jan 2022 14:26:11 -0600 Subject: [PATCH 696/746] v1.0.0 --- docs-src/_data/coverage.json | 8 ++++---- docs/coverage.md | 10 +++++----- package.json | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index eafa799aa..71cf34f6b 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":4911,"covered":4117,"skipped":0,"pct":83.83},"statements":{"total":4939,"covered":4142,"skipped":0,"pct":83.86},"functions":{"total":1064,"covered":901,"skipped":0,"pct":84.68},"branches":{"total":2275,"covered":1722,"skipped":0,"pct":75.69},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":4916,"covered":4120,"skipped":0,"pct":83.8},"statements":{"total":4944,"covered":4145,"skipped":0,"pct":83.83},"functions":{"total":1064,"covered":901,"skipped":0,"pct":84.68},"branches":{"total":2283,"covered":1726,"skipped":0,"pct":75.6},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":53,"covered":33,"skipped":0,"pct":62.26},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":53,"covered":33,"skipped":0,"pct":62.26},"branches":{"total":22,"covered":13,"skipped":0,"pct":59.09}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -33,7 +33,7 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} ,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":86,"covered":74,"skipped":0,"pct":86.04},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":86,"covered":74,"skipped":0,"pct":86.04},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":206,"covered":184,"skipped":0,"pct":89.32},"functions":{"total":36,"covered":35,"skipped":0,"pct":97.22},"statements":{"total":206,"covered":184,"skipped":0,"pct":89.32},"branches":{"total":111,"covered":86,"skipped":0,"pct":77.47}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":207,"covered":185,"skipped":0,"pct":89.37},"functions":{"total":36,"covered":35,"skipped":0,"pct":97.22},"statements":{"total":207,"covered":185,"skipped":0,"pct":89.37},"branches":{"total":115,"covered":89,"skipped":0,"pct":77.39}} ,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":264,"covered":252,"skipped":0,"pct":95.45},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":267,"covered":255,"skipped":0,"pct":95.5},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} ,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":52,"covered":50,"skipped":0,"pct":96.15},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":50,"skipped":0,"pct":96.15},"branches":{"total":34,"covered":33,"skipped":0,"pct":97.05}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} @@ -49,7 +49,7 @@ ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} ,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":168,"skipped":0,"pct":68.29},"functions":{"total":65,"covered":40,"skipped":0,"pct":61.53},"statements":{"total":246,"covered":168,"skipped":0,"pct":68.29},"branches":{"total":101,"covered":52,"skipped":0,"pct":51.48}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":90,"covered":79,"skipped":0,"pct":87.77},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":91,"covered":80,"skipped":0,"pct":87.91},"branches":{"total":60,"covered":48,"skipped":0,"pct":80}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":92,"covered":81,"skipped":0,"pct":88.04},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":93,"covered":82,"skipped":0,"pct":88.17},"branches":{"total":62,"covered":49,"skipped":0,"pct":79.03}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":29,"covered":29,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":29,"covered":29,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} @@ -69,7 +69,7 @@ ,"/Users/zachleat/Code/eleventy/src/Filters/Slug.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} -,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":138,"covered":123,"skipped":0,"pct":89.13},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":142,"covered":127,"skipped":0,"pct":89.43},"branches":{"total":94,"covered":74,"skipped":0,"pct":78.72}} +,"/Users/zachleat/Code/eleventy/src/Plugins/Pagination.js": {"lines":{"total":140,"covered":123,"skipped":0,"pct":87.85},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":144,"covered":127,"skipped":0,"pct":88.19},"branches":{"total":96,"covered":74,"skipped":0,"pct":77.08}} ,"/Users/zachleat/Code/eleventy/src/Plugins/RenderPlugin.js": {"lines":{"total":116,"covered":101,"skipped":0,"pct":87.06},"functions":{"total":23,"covered":21,"skipped":0,"pct":91.3},"statements":{"total":118,"covered":103,"skipped":0,"pct":87.28},"branches":{"total":53,"covered":34,"skipped":0,"pct":64.15}} ,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":186,"covered":12,"skipped":0,"pct":6.45},"functions":{"total":34,"covered":0,"skipped":0,"pct":0},"statements":{"total":188,"covered":12,"skipped":0,"pct":6.38},"branches":{"total":91,"covered":0,"skipped":0,"pct":0}} ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} diff --git a/docs/coverage.md b/docs/coverage.md index aa8989821..0d0332a79 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,8 +1,8 @@ -# Code Coverage for Eleventy v1.0.0-beta.10 +# Code Coverage for Eleventy v1.0.0 | Filename | % Lines | % Statements | % Functions | % Branches | | ------------------------------------------------------------------------ | ------- | ------------ | ----------- | ---------- | -| `total` | 83.83% | 83.86% | 84.68% | 75.69% | +| `total` | 83.8% | 83.83% | 84.68% | 75.6% | | `cmd.js` | 62.26% | 62.26% | 9.09% | 59.09% | | `.cache/vue/include.js` | 100% | 100% | 100% | 100% | | `.cache/vue/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | @@ -37,7 +37,7 @@ | `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | | `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | | `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | -| `src/TemplateContent.js` | 89.32% | 89.32% | 97.22% | 77.47% | +| `src/TemplateContent.js` | 89.37% | 89.37% | 97.22% | 77.39% | | `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | | `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | @@ -53,7 +53,7 @@ | `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | | `src/UserConfig.js` | 68.29% | 68.29% | 61.53% | 51.48% | | `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | -| `src/Engines/Custom.js` | 87.77% | 87.91% | 100% | 80% | +| `src/Engines/Custom.js` | 88.04% | 88.17% | 100% | 79.03% | | `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | @@ -73,7 +73,7 @@ | `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | | `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | | `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | -| `src/Plugins/Pagination.js` | 89.13% | 89.43% | 91.3% | 78.72% | +| `src/Plugins/Pagination.js` | 87.85% | 88.19% | 91.3% | 77.08% | | `src/Plugins/RenderPlugin.js` | 87.06% | 87.28% | 91.3% | 64.15% | | `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | | `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | diff --git a/package.json b/package.json index a59bc4864..35f5985c3 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0-beta.10", + "version": "1.0.0", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From f16d8cd52e27cb6b49887fc90c1542408e17628f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 11 Jan 2022 17:37:21 -0600 Subject: [PATCH 697/746] Benchmarks should not be a global (this is bad for serverless local dev) --- src/Benchmark.js | 4 ++ src/BenchmarkManager.js | 3 +- src/Eleventy.js | 18 +++++---- src/EleventyFiles.js | 8 ++-- src/Engines/Custom.js | 13 ++++--- src/Engines/TemplateEngine.js | 12 +++++- src/Template.js | 3 +- src/TemplateConfig.js | 2 +- src/TemplateContent.js | 16 +++++--- src/TemplateData.js | 13 ++++--- src/TemplatePassthrough.js | 25 +++++++----- src/TemplatePassthroughManager.js | 7 +++- src/UserConfig.js | 65 ++++++++++++++++++++----------- test/BenchmarkTest.js | 5 --- test/EleventyTest.js | 2 + test/TemplatePassthroughTest.js | 9 ++++- 16 files changed, 130 insertions(+), 75 deletions(-) diff --git a/src/Benchmark.js b/src/Benchmark.js index 0cfcca56f..622e3ba9e 100644 --- a/src/Benchmark.js +++ b/src/Benchmark.js @@ -18,6 +18,10 @@ class Benchmark { this.beforeTimers = []; } + incrementCount() { + this.timesCalled++; + } + // TODO(slightlyoff): // disable all of these hrtime requests when not benchmarking before() { diff --git a/src/BenchmarkManager.js b/src/BenchmarkManager.js index fd2967cb7..1caddd688 100644 --- a/src/BenchmarkManager.js +++ b/src/BenchmarkManager.js @@ -65,5 +65,4 @@ class BenchmarkManager { } } -let manager = new BenchmarkManager(); -module.exports = manager; +module.exports = BenchmarkManager; diff --git a/src/Eleventy.js b/src/Eleventy.js index 76e3ea983..02ae1eccc 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -16,7 +16,6 @@ const { performance } = require("perf_hooks"); const templateCache = require("./TemplateCache"); const simplePlural = require("./Util/Pluralize"); const deleteRequireCache = require("./Util/DeleteRequireCache"); -const bench = require("./BenchmarkManager"); const debug = require("debug")("Eleventy"); const eventBus = require("./EventBus"); @@ -73,6 +72,11 @@ class Eleventy { */ this.config = this.eleventyConfig.getConfig(); + /** + * @member {Object} - Singleton BenchmarkManager instance + */ + this.bench = this.config.benchmarkManager; + /** * @member {Boolean} - Was verbose mode overwritten? * @default false @@ -246,7 +250,7 @@ class Eleventy { debug("Restarting"); this.start = this.getNewTimestamp(); templateCache.clear(); - bench.reset(); + this.bench.reset(); this.eleventyFiles.restart(); this.extensionMap.reset(); @@ -438,9 +442,7 @@ Verbose Output: ${this.verboseMode}`); this.writer.setVerboseOutput(this._isVerboseMode); } - if (bench) { - bench.setVerboseOutput(this._isVerboseMode); - } + this.bench.setVerboseOutput(this._isVerboseMode); if (this.logger) { this.logger.isVerbose = this._isVerboseMode; @@ -502,7 +504,7 @@ Verbose Output: ${this.verboseMode}`); this.logger.isVerbose = isVerbose; } - bench.setVerboseOutput(isVerbose); + this.bench.setVerboseOutput(isVerbose); this.verboseMode = isVerbose; // Set verbose mode in config file @@ -701,7 +703,7 @@ Arguments: * @returns {} - tbd. */ get watcherBench() { - return bench.get("Watcher"); + return this.bench.get("Watcher"); } /** @@ -1000,7 +1002,7 @@ Arguments: }; this.errorHandler.fatal(e, "Problem writing Eleventy templates"); } finally { - bench.finish(); + this.bench.finish(); if (to === "fs") { this.logger.message( this.logFinished(), diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index bdcb8a584..3da8f26aa 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -12,15 +12,17 @@ class EleventyFilesError extends EleventyBaseError {} const debug = require("debug")("Eleventy:EleventyFiles"); // const debugDev = require("debug")("Dev:Eleventy:EleventyFiles"); -const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class EleventyFiles { constructor(input, outputDir, formats, eleventyConfig) { if (!eleventyConfig) { throw new EleventyFilesError("Missing `eleventyConfig`` argument."); } + this.eleventyConfig = eleventyConfig; this.config = eleventyConfig.getConfig(); + this.aggregateBench = this.config.benchmarkManager.get("Aggregate"); + this.input = input; this.inputDir = TemplatePath.getDir(this.input); this.outputDir = outputDir; @@ -380,7 +382,7 @@ class EleventyFiles { } async getFiles() { - let bench = aggregateBench.get("Searching the file system"); + let bench = this.aggregateBench.get("Searching the file system"); bench.before(); let globResults = await this._globSearch(); let paths = TemplatePath.addLeadingDotSlashArray(globResults); @@ -435,7 +437,7 @@ class EleventyFiles { // TODO this isn’t great but reduces complexity avoiding using TemplateData:getLocalDataPaths for each template in the cache async getWatcherTemplateJavaScriptDataFiles() { let globs = await this.templateData.getTemplateJavaScriptDataFileGlob(); - let bench = aggregateBench.get("Searching the file system"); + let bench = this.aggregateBench.get("Searching the file system"); bench.before(); let results = TemplatePath.addLeadingDotSlashArray( await fastglob(globs, { diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 7b13ec12d..a5c5dceb4 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -1,6 +1,5 @@ const TemplateEngine = require("./TemplateEngine"); const getJavaScriptData = require("../Util/GetJavaScriptData"); -const bench = require("../BenchmarkManager").get("Aggregate"); class CustomEngine extends TemplateEngine { constructor(name, dirs, config) { @@ -49,11 +48,13 @@ class CustomEngine extends TemplateEngine { async _runningInit() { if (this.needsInit) { if (!this._initing) { - this._initBench = bench.get(`Engine (${this.name}) Init`); + this._initBench = this.benchmarks.aggregate.get( + `Engine (${this.name}) Init` + ); this._initBench.before(); this._initing = this.entry.init.bind({ config: this.config, - bench, + bench: this.benchmarks.aggregate, })(); } await this._initing; @@ -74,7 +75,7 @@ class CustomEngine extends TemplateEngine { await this._runningInit(); if (typeof this.entry.getData === "function") { - let dataBench = bench.get( + let dataBench = this.benchmarks.aggregate.get( `Engine (${this.name}) Get Data From File (Function)` ); dataBench.before(); @@ -101,7 +102,9 @@ class CustomEngine extends TemplateEngine { } } - let dataBench = bench.get(`Engine (${this.name}) Get Data From File`); + let dataBench = this.benchmarks.aggregate.get( + `Engine (${this.name}) Get Data From File` + ); dataBench.before(); let inst = await this.entry.getInstanceFromInputPath(inputPath); diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 30377f486..8edb5407b 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -5,7 +5,6 @@ const TemplateConfig = require("../TemplateConfig"); const EleventyExtensionMap = require("../EleventyExtensionMap"); const EleventyBaseError = require("../EleventyBaseError"); const debug = require("debug")("Eleventy:TemplateEngine"); -const aggregateBench = require("../BenchmarkManager").get("Aggregate"); class TemplateEngineConfigError extends EleventyBaseError {} @@ -43,6 +42,15 @@ class TemplateEngine { return this._config; } + get benchmarks() { + if (!this._benchmarks) { + this._benchmarks = { + aggregate: this.config.benchmarkManager.get("Aggregate"), + }; + } + return this._benchmarks; + } + get engineManager() { return this._engineManager; } @@ -104,7 +112,7 @@ class TemplateEngine { // TODO: reuse mustache partials in handlebars? let partialFiles = []; if (this.includesDir) { - let bench = aggregateBench.get("Searching the file system"); + let bench = this.benchmarks.aggregate.get("Searching the file system"); bench.before(); this.extensions.forEach(function (extension) { partialFiles = partialFiles.concat( diff --git a/src/Template.js b/src/Template.js index 3319538c3..7cac3cd6a 100755 --- a/src/Template.js +++ b/src/Template.js @@ -26,7 +26,6 @@ const TemplateBehavior = require("./TemplateBehavior"); const debug = require("debug")("Eleventy:Template"); const debugDev = require("debug")("Dev:Eleventy:Template"); -const bench = require("./BenchmarkManager").get("Aggregate"); class Template extends TemplateContent { constructor( @@ -810,7 +809,7 @@ class Template extends TemplateContent { if (!shouldWriteFile) { this.skippedCount++; } else { - let templateBenchmark = bench.get("Template Write"); + let templateBenchmark = this.bench.get("Template Write"); templateBenchmark.before(); // TODO add a cache to check if this was already created diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index dc4f102dc..f29fd91b6 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -63,7 +63,7 @@ class TemplateConfig { this.hasConfigMerged = false; } - /* Getter for Logger */ + /* Setter for Logger */ setLogger(logger) { this.logger = logger; } diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 65e3734eb..1f82ecf36 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -15,7 +15,6 @@ const EleventyBaseError = require("./EleventyBaseError"); const EleventyErrorUtil = require("./EleventyErrorUtil"); const debug = require("debug")("Eleventy:TemplateContent"); const debugDev = require("debug")("Dev:Eleventy:TemplateContent"); -const bench = require("./BenchmarkManager").get("Aggregate"); const eventBus = require("./EventBus"); class TemplateContentConfigError extends EleventyBaseError {} @@ -64,6 +63,10 @@ class TemplateContent { return this._config; } + get bench() { + return this.config.benchmarkManager.get("Aggregate"); + } + get eleventyConfig() { if (this._config instanceof TemplateConfig) { return this._config; @@ -164,7 +167,7 @@ class TemplateContent { if (!this.engine.needsToReadFileContents()) { return ""; } - let templateBenchmark = bench.get("Template Read"); + let templateBenchmark = this.bench.get("Template Read"); templateBenchmark.before(); let content; if (this.config.useTemplateCache) { @@ -271,6 +274,7 @@ class TemplateContent { ); if (cacheable && key) { if (cache.has(key)) { + this.bench.get("Template Compile Cache Hit").incrementCount(); return cache.get(key); } @@ -285,8 +289,8 @@ class TemplateContent { } } - let templateBenchmark = bench.get("Template Compile"); - let inputPathBenchmark = bench.get( + let templateBenchmark = this.bench.get("Template Compile"); + let inputPathBenchmark = this.bench.get( `> Template Compile > ${this.inputPath}` ); templateBenchmark.before(); @@ -395,7 +399,7 @@ class TemplateContent { } // Benchmark - let templateBenchmark = bench.get("Render"); + let templateBenchmark = this.bench.get("Render"); let paginationSuffix = []; if ("pagination" in data) { paginationSuffix.push(" (Pagination"); @@ -409,7 +413,7 @@ class TemplateContent { paginationSuffix.push(")"); } - let inputPathBenchmark = bench.get( + let inputPathBenchmark = this.bench.get( `> Render > ${this.inputPath}${paginationSuffix.join("")}` ); diff --git a/src/TemplateData.js b/src/TemplateData.js index a26b14c97..242fbb79c 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -16,9 +16,6 @@ const debug = require("debug")("Eleventy:TemplateData"); const debugDev = require("debug")("Dev:Eleventy:TemplateData"); const deleteRequireCache = require("./Util/DeleteRequireCache"); -const bench = require("./BenchmarkManager").get("Data"); -const aggregateBench = require("./BenchmarkManager").get("Aggregate"); - class FSExistsCache { constructor() { this._cache = new Map(); @@ -49,6 +46,10 @@ class TemplateData { } this.eleventyConfig = eleventyConfig; this.config = this.eleventyConfig.getConfig(); + this.benchmarks = { + data: this.config.benchmarkManager.get("Data"), + aggregate: this.config.benchmarkManager.get("Aggregate"), + }; this.dataTemplateEngine = this.config.dataTemplateEngine; @@ -216,7 +217,7 @@ class TemplateData { async getGlobalDataFiles() { let priorities = this.getGlobalDataExtensionPriorities(); - let fsBench = aggregateBench.get("Searching the file system"); + let fsBench = this.benchmarks.aggregate.get("Searching the file system"); fsBench.before(); let paths = fastglob.sync(await this.getGlobalDataGlob(), { caseSensitiveMatch: false, @@ -468,9 +469,9 @@ class TemplateData { return {}; } - let aggregateDataBench = aggregateBench.get("Data File"); + let aggregateDataBench = this.benchmarks.aggregate.get("Data File"); aggregateDataBench.before(); - let dataBench = bench.get(`\`${path}\``); + let dataBench = this.benchmarks.data.get(`\`${path}\``); dataBench.before(); deleteRequireCache(localPath); diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index e3fa30278..9f1b11726 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -5,12 +5,19 @@ const TemplatePath = require("./TemplatePath"); const debug = require("debug")("Eleventy:TemplatePassthrough"); const fastglob = require("fast-glob"); const EleventyBaseError = require("./EleventyBaseError"); -const aggregateBench = require("./BenchmarkManager").get("Aggregate"); class TemplatePassthroughError extends EleventyBaseError {} class TemplatePassthrough { - constructor(path, outputDir, inputDir) { + constructor(path, outputDir, inputDir, config) { + if (!config) { + throw new TemplatePassthroughError("Missing `config`."); + } + this.config = config; + this.benchmarks = { + aggregate: this.config.benchmarkManager.get("Aggregate"), + }; + this.rawPath = path; // inputPath is relative to the root of your project and not your Eleventy input directory. @@ -63,15 +70,15 @@ class TemplatePassthrough { async getFiles(glob) { debug("Searching for: %o", glob); - let bench = aggregateBench.get("Searching the file system"); - bench.before(); + let b = this.benchmarks.aggregate.get("Searching the file system"); + b.before(); const files = TemplatePath.addLeadingDotSlashArray( await fastglob(glob, { caseSensitiveMatch: false, dot: true, }) ); - bench.after(); + b.after(); return files; } @@ -98,15 +105,15 @@ class TemplatePassthrough { // returns a promise return copy(src, dest, copyOptions) - .on(copy.events.COPY_FILE_START, function (copyOp) { + .on(copy.events.COPY_FILE_START, (copyOp) => { // Access to individual files at `copyOp.src` debug("Copying individual file %o", copyOp.src); map[copyOp.src] = copyOp.dest; - aggregateBench.get("Passthrough Copy File").before(); + this.benchmarks.aggregate.get("Passthrough Copy File").before(); }) - .on(copy.events.COPY_FILE_COMPLETE, function () { + .on(copy.events.COPY_FILE_COMPLETE, () => { fileCopyCount++; - aggregateBench.get("Passthrough Copy File").after(); + this.benchmarks.aggregate.get("Passthrough Copy File").after(); }) .then(() => { return { diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 09039f1de..f6cb63faf 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -98,7 +98,12 @@ class TemplatePassthroughManager { } getTemplatePassthroughForPath(path) { - return new TemplatePassthrough(path, this.outputDir, this.inputDir); + return new TemplatePassthrough( + path, + this.outputDir, + this.inputDir, + this.config + ); } async copyPassthrough(pass) { diff --git a/src/UserConfig.js b/src/UserConfig.js index 43a5e3d50..e639b0f6e 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -3,9 +3,8 @@ const semver = require("semver"); const { DateTime } = require("luxon"); const EventEmitter = require("./Util/AsyncEventEmitter"); const EleventyBaseError = require("./EleventyBaseError"); +const BenchmarkManager = require("./BenchmarkManager"); const merge = require("./Util/Merge"); -const bench = require("./BenchmarkManager").get("Configuration"); -const aggregateBench = require("./BenchmarkManager").get("Aggregate"); const debug = require("debug")("Eleventy:UserConfig"); const pkg = require("../package.json"); @@ -20,6 +19,13 @@ class UserConfig { reset() { debug("Resetting EleventyConfig to initial values."); this.events = new EventEmitter(); + + this.benchmarkManager = new BenchmarkManager(); + this.benchmarks = { + config: this.benchmarkManager.get("Configuration"), + aggregate: this.benchmarkManager.get("Aggregate"), + }; + this.collections = {}; this.precompiledCollections = {}; this.templateFormats = undefined; @@ -132,7 +138,10 @@ class UserConfig { name ); } - this.liquidTags[name] = bench.add(`"${name}" Liquid Custom Tag`, tagFn); + this.liquidTags[name] = this.benchmarks.config.add( + `"${name}" Liquid Custom Tag`, + tagFn + ); } addLiquidFilter(name, callback) { @@ -147,7 +156,10 @@ class UserConfig { ); } - this.liquidFilters[name] = bench.add(`"${name}" Liquid Filter`, callback); + this.liquidFilters[name] = this.benchmarks.config.add( + `"${name}" Liquid Filter`, + callback + ); } addNunjucksAsyncFilter(name, callback) { @@ -162,7 +174,7 @@ class UserConfig { ); } - this.nunjucksAsyncFilters[name] = bench.add( + this.nunjucksAsyncFilters[name] = this.benchmarks.config.add( `"${name}" Nunjucks Async Filter`, callback ); @@ -185,7 +197,7 @@ class UserConfig { ); } - this.nunjucksFilters[name] = bench.add( + this.nunjucksFilters[name] = this.benchmarks.config.add( `"${name}" Nunjucks Filter`, callback ); @@ -204,7 +216,7 @@ class UserConfig { ); } - this.handlebarsHelpers[name] = bench.add( + this.handlebarsHelpers[name] = this.benchmarks.config.add( `"${name}" Handlebars Helper`, callback ); @@ -249,7 +261,10 @@ class UserConfig { ); } - this.nunjucksTags[name] = bench.add(`"${name}" Nunjucks Custom Tag`, tagFn); + this.nunjucksTags[name] = this.benchmarks.config.add( + `"${name}" Nunjucks Custom Tag`, + tagFn + ); } addGlobalData(name, data) { @@ -271,7 +286,7 @@ class UserConfig { } if (typeof globalType === "function") { - this.nunjucksGlobals[name] = bench.add( + this.nunjucksGlobals[name] = this.benchmarks.config.add( `"${name}" Nunjucks Global`, globalType ); @@ -327,20 +342,23 @@ class UserConfig { _executePlugin(plugin, options) { debug(`Adding ${plugin.name || "anonymous"} plugin`); - let pluginBench = aggregateBench.get("Configuration addPlugin"); + let pluginBenchmark = this.benchmarks.aggregate.get( + "Configuration addPlugin" + ); if (typeof plugin === "function") { - pluginBench.before(); + pluginBenchmark.before(); + this.benchmarks.config; let configFunction = plugin; configFunction(this, options); - pluginBench.after(); + pluginBenchmark.after(); } else if (plugin && plugin.configFunction) { - pluginBench.before(); + pluginBenchmark.before(); if (options && typeof options.init === "function") { options.init.call(this, plugin.initArguments || {}); } plugin.configFunction(this, options); - pluginBench.after(); + pluginBenchmark.after(); } else { throw new UserConfigError( "Invalid EleventyConfig.addPlugin signature. Should be a function or a valid Eleventy plugin object." @@ -478,7 +496,7 @@ class UserConfig { ); } - this.nunjucksAsyncShortcodes[name] = bench.add( + this.nunjucksAsyncShortcodes[name] = this.benchmarks.config.add( `"${name}" Nunjucks Async Shortcode`, callback ); @@ -499,7 +517,7 @@ class UserConfig { ); } - this.nunjucksShortcodes[name] = bench.add( + this.nunjucksShortcodes[name] = this.benchmarks.config.add( `"${name}" Nunjucks Shortcode`, callback ); @@ -518,7 +536,7 @@ class UserConfig { ); } - this.liquidShortcodes[name] = bench.add( + this.liquidShortcodes[name] = this.benchmarks.config.add( `"${name}" Liquid Shortcode`, callback ); @@ -536,7 +554,7 @@ class UserConfig { ); } - this.handlebarsShortcodes[name] = bench.add( + this.handlebarsShortcodes[name] = this.benchmarks.config.add( `"${name}" Handlebars Shortcode`, callback ); @@ -574,7 +592,7 @@ class UserConfig { ); } - this.nunjucksAsyncPairedShortcodes[name] = bench.add( + this.nunjucksAsyncPairedShortcodes[name] = this.benchmarks.config.add( `"${name}" Nunjucks Async Paired Shortcode`, callback ); @@ -595,7 +613,7 @@ class UserConfig { ); } - this.nunjucksPairedShortcodes[name] = bench.add( + this.nunjucksPairedShortcodes[name] = this.benchmarks.config.add( `"${name}" Nunjucks Paired Shortcode`, callback ); @@ -614,7 +632,7 @@ class UserConfig { ); } - this.liquidPairedShortcodes[name] = bench.add( + this.liquidPairedShortcodes[name] = this.benchmarks.config.add( `"${name}" Liquid Paired Shortcode`, callback ); @@ -632,7 +650,7 @@ class UserConfig { ); } - this.handlebarsPairedShortcodes[name] = bench.add( + this.handlebarsPairedShortcodes[name] = this.benchmarks.config.add( `"${name}" Handlebars Paired Shortcode`, callback ); @@ -650,7 +668,7 @@ class UserConfig { ); } - this.javascriptFunctions[name] = bench.add( + this.javascriptFunctions[name] = this.benchmarks.config.add( `"${name}" JavaScript Function`, callback ); @@ -767,6 +785,7 @@ class UserConfig { extensionMap: this.extensionMap, quietMode: this.quietMode, events: this.events, + benchmarkManager: this.benchmarkManager, plugins: this.plugins, useTemplateCache: this.useTemplateCache, precompiledCollections: this.precompiledCollections, diff --git a/test/BenchmarkTest.js b/test/BenchmarkTest.js index 7a26fb730..2ac78ebb6 100644 --- a/test/BenchmarkTest.js +++ b/test/BenchmarkTest.js @@ -1,11 +1,6 @@ const test = require("ava"); const Benchmark = require("../src/Benchmark"); -function between(t, value, lowerBound, upperBound) { - t.truthy(value >= lowerBound); - t.truthy(value <= upperBound); -} - test("Standard Benchmark", async (t) => { await new Promise((resolve) => { let b = new Benchmark(); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 1d65b89fc..155bb9dff 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -278,6 +278,8 @@ test("Two Eleventies, two configs!!! (config used to be a global)", async (t) => let elev2 = new Eleventy(); t.not(elev1.eleventyConfig, elev2.eleventyConfig); + elev1.config.benchmarkManager = null; + elev2.config.benchmarkManager = null; t.is(JSON.stringify(elev1.config), JSON.stringify(elev2.config)); }); diff --git a/test/TemplatePassthroughTest.js b/test/TemplatePassthroughTest.js index f7230c6d8..bc88839f2 100644 --- a/test/TemplatePassthroughTest.js +++ b/test/TemplatePassthroughTest.js @@ -1,14 +1,19 @@ const test = require("ava"); +const TemplateConfig = require("../src/TemplateConfig"); const TemplatePassthrough = require("../src/TemplatePassthrough"); const getTemplatePassthrough = (path, outputDir, inputDir) => { + let eleventyConfig = new TemplateConfig(); + let config = eleventyConfig.getConfig(); + if (typeof path === "object") { - return new TemplatePassthrough(path, outputDir, inputDir); + return new TemplatePassthrough(path, outputDir, inputDir, config); } return new TemplatePassthrough( { inputPath: path, outputPath: true }, outputDir, - inputDir + inputDir, + config ); }; From f91a5fce2c27c58ecd6955221bf04239d71c4e11 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Jan 2022 11:00:49 -0600 Subject: [PATCH 698/746] Issue with duplicate permalinks when `build` missing from permalink object. --- src/TemplateMap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TemplateMap.js b/src/TemplateMap.js index e296e85b3..f07f0531c 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -627,7 +627,7 @@ class TemplateMap { let warnings = {}; for (let entry of this.map) { for (let page of entry._pages) { - if (page.url === false) { + if (page.outputPath === false || page.url === false) { // do nothing (also serverless) } else if (!permalinks[page.url]) { permalinks[page.url] = [entry.inputPath]; From 56b353b0358c56d066f865181ed24f62cc944aa8 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Jan 2022 11:21:11 -0600 Subject: [PATCH 699/746] Update license --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index ebcbb6b4e..b91cc21c8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Zach Leatherman @zachleat +Copyright (c) 2017–2022 Zach Leatherman @zachleat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 85cd110a29abbe043a133cb50a1b069754c73cec Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 12 Jan 2022 11:21:39 -0600 Subject: [PATCH 700/746] v1.0.1-canary.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35f5985c3..c6ac42ecf 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.0", + "version": "1.0.1-canary.1", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From f3201b1ea15cbd55953494e214e6280a498463e1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 13 Jan 2022 10:23:26 -0600 Subject: [PATCH 701/746] If a page has an Array of available serverless URLs, the serverlessUrl filter will return only the URLs that match (instead of throwing an error). If no results match, then an error will be thrown. --- src/Filters/ServerlessUrl.js | 25 ++++++++++++++++++++++++- src/TemplatePermalink.js | 23 ++++++++++++++++------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/Filters/ServerlessUrl.js b/src/Filters/ServerlessUrl.js index 33d15999f..4cf81dc3a 100644 --- a/src/Filters/ServerlessUrl.js +++ b/src/Filters/ServerlessUrl.js @@ -7,7 +7,30 @@ function stringify(url, urlData = {}) { module.exports = function (url, urlData = {}) { if (Array.isArray(url)) { - return url.slice().map((entry) => stringify(entry, urlData)); + let errors = []; + let urls = url + .slice() + .map((entry) => { + // if multiple serverless URLs exist, return the first one that matches + let result = false; + try { + result = stringify(entry, urlData); + } catch (e) { + errors.push(e.message); + } finally { + return result; + } + }) + .filter((entry) => !!entry); + + if (!urls.length) { + throw new Error( + "Looked through an array of serverless URLs but found no matches, errors: " + + errors.join(";") + ); + } + + return urls; } return stringify(url, urlData); diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index 5de1a0a11..f9a4111e5 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -25,12 +25,7 @@ class TemplatePermalink { continue; } if (key !== "build" && link[key] !== false) { - // is array of serverless urls, use the first one - if (Array.isArray(link[key])) { - this.primaryServerlessUrl = link[key][0]; - } else { - this.primaryServerlessUrl = link[key]; - } + this.primaryServerlessUrl = link[key]; // can be an array or string } break; } @@ -108,11 +103,25 @@ class TemplatePermalink { toHref() { if (this.primaryServerlessUrl) { if (this.serverlessPathData) { - return serverlessUrlFilter( + let urls = serverlessUrlFilter( this.primaryServerlessUrl, this.serverlessPathData ); + + // Array of *matching* serverless urls only + if (Array.isArray(urls)) { + // return first + return urls[0]; + } + + return urls; } + + if (Array.isArray(this.primaryServerlessUrl)) { + // return first + return this.primaryServerlessUrl[0]; + } + return this.primaryServerlessUrl; } else if (!this.buildLink) { // empty or false From 7655706b521ec0726d90cb7f097130ffe4154958 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 13 Jan 2022 10:24:21 -0600 Subject: [PATCH 702/746] v1.0.1-canary.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c6ac42ecf..06818f15c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.1-canary.1", + "version": "1.0.1-canary.2", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 08fe54e03da025cda24c4b25b5b8a8d0007b4689 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Sun, 16 Jan 2022 14:45:19 -0600 Subject: [PATCH 703/746] Minor tweaks to help with the https://github.com/11ty/eleventy-plugin-directory-output plugin --- src/BenchmarkGroup.js | 4 ++++ src/BenchmarkManager.js | 4 ++++ src/TemplateContent.js | 16 +++++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/BenchmarkGroup.js b/src/BenchmarkGroup.js index deb7f64dd..1f51addf6 100644 --- a/src/BenchmarkGroup.js +++ b/src/BenchmarkGroup.js @@ -66,6 +66,10 @@ class BenchmarkGroup { this.minimumThresholdPercent = val; } + has(type) { + return !!this.benchmarks[type]; + } + get(type) { if (!this.benchmarks[type]) { this.benchmarks[type] = new Benchmark(); diff --git a/src/BenchmarkManager.js b/src/BenchmarkManager.js index 1caddd688..c656e3c5f 100644 --- a/src/BenchmarkManager.js +++ b/src/BenchmarkManager.js @@ -29,6 +29,10 @@ class BenchmarkManager { this.isVerbose = !!isVerbose; } + hasBenchmarkGroup(name) { + return name in this.benchmarkGroups; + } + getBenchmarkGroup(name) { if (!this.benchmarkGroups[name]) { this.benchmarkGroups[name] = new BenchmarkGroup(); diff --git a/src/TemplateContent.js b/src/TemplateContent.js index 1f82ecf36..ec210e2f2 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -290,9 +290,7 @@ class TemplateContent { } let templateBenchmark = this.bench.get("Template Compile"); - let inputPathBenchmark = this.bench.get( - `> Template Compile > ${this.inputPath}` - ); + let inputPathBenchmark = this.bench.get(`> Compile > ${this.inputPath}`); templateBenchmark.before(); inputPathBenchmark.before(); let fn = await this.templateRender.getCompiledTemplate(str); @@ -416,14 +414,26 @@ class TemplateContent { let inputPathBenchmark = this.bench.get( `> Render > ${this.inputPath}${paginationSuffix.join("")}` ); + let outputPathBenchmark; + if (data.page && data.page.outputPath) { + outputPathBenchmark = this.bench.get( + `> Render > ${data.page.outputPath}` + ); + } templateBenchmark.before(); if (inputPathBenchmark) { inputPathBenchmark.before(); } + if (outputPathBenchmark) { + outputPathBenchmark.before(); + } let rendered = await fn(data); + if (outputPathBenchmark) { + outputPathBenchmark.after(); + } if (inputPathBenchmark) { inputPathBenchmark.after(); } From 900eec421adf21ffba25dbc36ad8d6a4675f5b47 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 18 Jan 2022 11:29:54 -0600 Subject: [PATCH 704/746] Fixes #2179 --- src/TemplateData.js | 8 ++++++-- test/EleventyTest.js | 15 +++++++++++++++ test/TemplateDataTest.js | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/TemplateData.js b/src/TemplateData.js index 242fbb79c..504428aa1 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -294,6 +294,8 @@ class TemplateData { async getInitialGlobalData() { let globalData = {}; + + // via eleventyConfig.addGlobalData if (this.config.globalData) { let keys = Object.keys(this.config.globalData); for (let key of keys) { @@ -306,6 +308,7 @@ class TemplateData { lodashset(globalData, key, returnValue); } } + if (this.environmentVariables) { if (!("eleventy" in globalData)) { globalData.eleventy = {}; @@ -315,15 +318,16 @@ class TemplateData { } Object.assign(globalData.eleventy.env, this.environmentVariables); } + return globalData; } async getData() { let rawImports = this.getRawImports(); - this.configApiGlobalData = await this.getInitialGlobalData(); - if (!this.globalData) { + this.configApiGlobalData = await this.getInitialGlobalData(); + let globalJson = await this.getAllGlobalData(); let mergedGlobalData = merge(globalJson, this.configApiGlobalData); diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 155bb9dff..d79dae8e7 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -369,3 +369,18 @@ test("Can Eleventy run two executeBuilds in parallel?", async (t) => { test2Result ); }); + +test("Eleventy addGlobalData should run once.", async (t) => { + let count = 0; + let elev = new Eleventy("./test/stubs", "./test/stubs/_site", { + config: function (eleventyConfig) { + eleventyConfig.addGlobalData("count", () => { + count++; + return count; + }); + }, + }); + + let results = await elev.toJSON(); + t.is(count, 1); +}); diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index 1d19ff0ec..dffedb454 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -486,6 +486,24 @@ test("addGlobalData values", async (t) => { t.is(data.myAsync, "promise-value"); }); +test("addGlobalData should execute once.", async (t) => { + let count = 0; + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.addGlobalData("count", () => { + count++; + return count; + }); + + let dataObj = new TemplateData( + "./test/stubs-global-data-config-api/", + eleventyConfig + ); + let data = await dataObj.getData(); + + t.is(data.count, 1); + t.is(count, 1); +}); + test("addGlobalData complex key", async (t) => { let eleventyConfig = new TemplateConfig(); eleventyConfig.userConfig.addGlobalData("deep.nested.one", () => "first"); From 3a7f568da165e5bee1955a240919c69298f6b80d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Feb 2022 14:23:55 -0600 Subject: [PATCH 705/746] Swap to use internal IsPlainObject utility rather than lodash/isPlainObject for performance reasons. See #2214. --- src/ComputedDataProxy.js | 6 +-- src/Plugins/RenderPlugin.js | 6 +-- src/Template.js | 2 +- src/TemplateBehavior.js | 2 +- src/TemplateMap.js | 2 +- src/TemplatePermalink.js | 2 +- src/Util/IsPlainObject.js | 24 +++++++++++ src/Util/Merge.js | 2 +- test/IsPlainObjectTest.js | 80 +++++++++++++++++++++++++++++++++++++ 9 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 src/Util/IsPlainObject.js create mode 100644 test/IsPlainObjectTest.js diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index e32ad91d5..82f5bb310 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -1,6 +1,6 @@ const lodashSet = require("lodash/set"); const lodashGet = require("lodash/get"); -const lodashIsPlainObject = require("lodash/isPlainObject"); +const isPlainObject = require("./Util/isPlainObject"); /* Calculates computed data using Proxies */ class ComputedDataProxy { @@ -13,7 +13,7 @@ class ComputedDataProxy { } isArrayOrPlainObject(data) { - return Array.isArray(data) || lodashIsPlainObject(data); + return Array.isArray(data) || isPlainObject(data); } getProxyData(data, keyRef) { @@ -97,7 +97,7 @@ class ComputedDataProxy { } _getProxyData(data, keyRef, parentKey = "") { - if (lodashIsPlainObject(data)) { + if (isPlainObject(data)) { return this._getProxyForObject(data, keyRef, parentKey); } else if (Array.isArray(data)) { return this._getProxyForArray(data, keyRef, parentKey); diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index c67c0688f..10948a278 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -1,6 +1,6 @@ const fs = require("fs"); const fsp = fs.promises; -const lodashIsPlainObject = require("lodash/isPlainObject"); +const isPlainObject = require("../Util/IsPlainObject"); // TODO add a first-class Markdown component to expose this using Markdown-only syntax (will need to be synchronous for markdown-it) @@ -276,7 +276,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { } // if the user passes a string or other literal, remap to an object. - if (!lodashIsPlainObject(data)) { + if (!isPlainObject(data)) { data = { _: data, }; @@ -309,7 +309,7 @@ function EleventyPlugin(eleventyConfig, options = {}) { } // if the user passes a string or other literal, remap to an object. - if (!lodashIsPlainObject(data)) { + if (!isPlainObject(data)) { data = { _: data, }; diff --git a/src/Template.js b/src/Template.js index 7cac3cd6a..6d1166214 100755 --- a/src/Template.js +++ b/src/Template.js @@ -6,7 +6,7 @@ const mkdir = util.promisify(fs.mkdir); const os = require("os"); const path = require("path"); const normalize = require("normalize-path"); -const isPlainObject = require("lodash/isPlainObject"); +const isPlainObject = require("./Util/IsPlainObject"); const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); const { DateTime } = require("luxon"); diff --git a/src/TemplateBehavior.js b/src/TemplateBehavior.js index c8a92422e..9fd82cc5d 100644 --- a/src/TemplateBehavior.js +++ b/src/TemplateBehavior.js @@ -1,4 +1,4 @@ -const isPlainObject = require("lodash/isPlainObject"); +const isPlainObject = require("./Util/IsPlainObject"); class TemplateBehavior { constructor(config) { diff --git a/src/TemplateMap.js b/src/TemplateMap.js index f07f0531c..f441e43ab 100644 --- a/src/TemplateMap.js +++ b/src/TemplateMap.js @@ -1,4 +1,4 @@ -const isPlainObject = require("lodash/isPlainObject"); +const isPlainObject = require("./Util/IsPlainObject"); const DependencyGraph = require("dependency-graph").DepGraph; const TemplateCollection = require("./TemplateCollection"); const EleventyErrorUtil = require("./EleventyErrorUtil"); diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index f9a4111e5..c99f39287 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -1,7 +1,7 @@ const path = require("path"); const TemplatePath = require("./TemplatePath"); const normalize = require("normalize-path"); -const isPlainObject = require("lodash/isPlainObject"); +const isPlainObject = require("./Util/IsPlainObject"); const serverlessUrlFilter = require("./Filters/ServerlessUrl"); class TemplatePermalink { diff --git a/src/Util/IsPlainObject.js b/src/Util/IsPlainObject.js new file mode 100644 index 000000000..1d4c75278 --- /dev/null +++ b/src/Util/IsPlainObject.js @@ -0,0 +1,24 @@ +/* Prior art: this utility was created for https://github.com/11ty/eleventy/issues/2214 + + * Inspired by implementations from `is-what`, `typechecker`, `jQuery`, and `lodash` + + * `is-what` + * More reading at https://www.npmjs.com/package/is-what#user-content-isplainobject-vs-isanyobject + * if (Object.prototype.toString.call(value).slice(8, -1) !== 'Object') return false; + * return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype; + + * `typechecker` + * return value !== null && typeof value === 'object' && value.__proto__ === Object.prototype; + + * Notably jQuery and lodash have very similar implementations. + + * For later, remember the `value === Object(value)` trick + */ + +module.exports = function (value) { + if (value === null || typeof value !== "object") { + return false; + } + let proto = Object.getPrototypeOf(value); + return !proto || proto === Object.prototype; +}; diff --git a/src/Util/Merge.js b/src/Util/Merge.js index 17cb3eeb6..96be170f1 100644 --- a/src/Util/Merge.js +++ b/src/Util/Merge.js @@ -1,4 +1,4 @@ -const isPlainObject = require("lodash/isPlainObject"); +const isPlainObject = require("../Util/IsPlainObject"); const OVERRIDE_PREFIX = "override:"; function getMergedItem(target, source, parentKey) { diff --git a/test/IsPlainObjectTest.js b/test/IsPlainObjectTest.js new file mode 100644 index 000000000..117770d66 --- /dev/null +++ b/test/IsPlainObjectTest.js @@ -0,0 +1,80 @@ +const test = require("ava"); +const isPlainObject = require("../src/Util/IsPlainObject"); + +test("isPlainObject", (t) => { + t.is(isPlainObject(null), false); + t.is(isPlainObject(undefined), false); + t.is(isPlainObject(1), false); + t.is(isPlainObject(true), false); + t.is(isPlainObject(false), false); + t.is(isPlainObject("string"), false); + t.is(isPlainObject([]), false); + t.is(isPlainObject(Symbol("a")), false); + t.is( + isPlainObject(function () {}), + false + ); +}); + +// https://github.com/lodash/lodash/blob/ddfd9b11a0126db2302cb70ec9973b66baec0975/test/test.js#L11447 +// Notably, did not include the test for DOM Elements. +test("Test from lodash.isPlainObject", (t) => { + t.is(isPlainObject({}), true); + t.is(isPlainObject({ a: 1 }), true); + + function Foo(a) { + this.a = 1; + } + + t.is(isPlainObject({ constructor: Foo }), true); + t.is(isPlainObject([1, 2, 3]), false); + t.is(isPlainObject(new Foo(1)), false); +}); + +test("Test from lodash.isPlainObject: should return `true` for objects with a `[[Prototype]]` of `null`", (t) => { + let obj = Object.create(null); + t.is(isPlainObject(obj), true); + + obj.constructor = Object.prototype.constructor; + t.is(isPlainObject(obj), true); +}); + +test("Test from lodash.isPlainObject: should return `true` for objects with a `valueOf` property", (t) => { + t.is(isPlainObject({ valueOf: 0 }), true); +}); + +test("Test from lodash.isPlainObject: should return `true` for objects with a writable `Symbol.toStringTag` property", (t) => { + let obj = {}; + obj[Symbol.toStringTag] = "X"; + + t.is(isPlainObject(obj), true); +}); + +test("Test from lodash.isPlainObject: should return `false` for objects with a custom `[[Prototype]]`", (t) => { + let obj = Object.create({ a: 1 }); + t.is(isPlainObject(obj), false); +}); + +test("Test from lodash.isPlainObject (modified): should return `false` for non-Object objects", (t) => { + t.is(isPlainObject(arguments), true); // WARNING: lodash was false + t.is(isPlainObject(Error), false); + t.is(isPlainObject(Math), true); // WARNING: lodash was false +}); + +test("Test from lodash.isPlainObject: should return `false` for non-objects", (t) => { + t.is(isPlainObject(true), false); + t.is(isPlainObject("a"), false); + t.is(isPlainObject(Symbol("a")), false); +}); + +test("Test from lodash.isPlainObject (modified): should return `true` for objects with a read-only `Symbol.toStringTag` property", (t) => { + var object = {}; + Object.defineProperty(object, Symbol.toStringTag, { + configurable: true, + enumerable: false, + writable: false, + value: "X", + }); + + t.is(isPlainObject(object), true); // WARNING: lodash was false +}); From ffdad870233ec0370804cb876e3bedac63ad3ad9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Feb 2022 14:38:18 -0600 Subject: [PATCH 706/746] Fixes test failure with `Eleventy addGlobalData should run once.` in EleventyTest.js --- test/EleventyTest.js | 2 +- test/stubs-noop/test.txt | 0 test/stubs/dependencies/two-deps.11ty.js | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 test/stubs-noop/test.txt diff --git a/test/EleventyTest.js b/test/EleventyTest.js index d79dae8e7..255480ef6 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -372,7 +372,7 @@ 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", "./test/stubs/_site", { + let elev = new Eleventy("./test/stubs-noop/", "./test/stubs-noop/_site", { config: function (eleventyConfig) { eleventyConfig.addGlobalData("count", () => { count++; diff --git a/test/stubs-noop/test.txt b/test/stubs-noop/test.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/stubs/dependencies/two-deps.11ty.js b/test/stubs/dependencies/two-deps.11ty.js index 5328fa26c..018282839 100644 --- a/test/stubs/dependencies/two-deps.11ty.js +++ b/test/stubs/dependencies/two-deps.11ty.js @@ -1,2 +1,4 @@ const dep1 = require("./dep1"); const dep2 = require("./dep2"); + +module.exports = ""; From 41495e488c9d603c9d8fdfc7b360e28e4f36cb92 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Feb 2022 14:41:32 -0600 Subject: [PATCH 707/746] Missed one addition for #2179 (init is no longer required) --- src/Serverless.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Serverless.js b/src/Serverless.js index 2ed9278ee..cb67a895b 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -213,8 +213,6 @@ class Serverless { }, }); - await elev.init(); - let json = await elev.toJSON(); // TODO (@zachleat) https://github.com/11ty/eleventy/issues/1957 From 3b601e63c3fd339631f9b421a6b4a6c83fdf78b4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Feb 2022 14:46:46 -0600 Subject: [PATCH 708/746] =?UTF-8?q?Case=20sensitivity=20=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ComputedDataProxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ComputedDataProxy.js b/src/ComputedDataProxy.js index 82f5bb310..495941081 100644 --- a/src/ComputedDataProxy.js +++ b/src/ComputedDataProxy.js @@ -1,6 +1,6 @@ const lodashSet = require("lodash/set"); const lodashGet = require("lodash/get"); -const isPlainObject = require("./Util/isPlainObject"); +const isPlainObject = require("./Util/IsPlainObject"); /* Calculates computed data using Proxies */ class ComputedDataProxy { From b843dae6021613b841619777b6d9f901bfb2f6df Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 15 Feb 2022 16:32:10 -0600 Subject: [PATCH 709/746] Resolves https://github.com/11ty/eleventy/pull/2219#pullrequestreview-883715132 --- src/Util/Merge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/Merge.js b/src/Util/Merge.js index 96be170f1..3427dbac6 100644 --- a/src/Util/Merge.js +++ b/src/Util/Merge.js @@ -1,4 +1,4 @@ -const isPlainObject = require("../Util/IsPlainObject"); +const isPlainObject = require("./IsPlainObject"); const OVERRIDE_PREFIX = "override:"; function getMergedItem(target, source, parentKey) { From ff6b56d27503638d3fcef4899fb595c24656e287 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Feb 2022 10:17:47 -0600 Subject: [PATCH 710/746] Fixes #2217 --- src/Engines/Custom.js | 14 ++++-- test/TemplateTest-CustomExtensions.js | 66 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index a5c5dceb4..4ba8ba3de 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -160,11 +160,19 @@ class CustomEngine extends TemplateEngine { } // TODO generalize this (look at JavaScript.js) - let fn = this.entry.compile.bind({ config: this.config })(str, inputPath); - if (typeof fn === "function") { - // give the user access to this engine's default renderer, if any + let fn = this.entry.compile.bind({ + config: this.config, + defaultRenderer, // bind defaultRenderer to compile function + })(str, inputPath); + + // Bind defaultRenderer to render function + if ("then" in fn && typeof fn.then === "function") { + // Promise, wait to bind + return fn.then((fn) => fn.bind({ defaultRenderer })); + } else if ("bind" in fn && typeof fn.bind === "function") { return fn.bind({ defaultRenderer }); } + return fn; } diff --git a/test/TemplateTest-CustomExtensions.js b/test/TemplateTest-CustomExtensions.js index de92fbb52..569f44197 100644 --- a/test/TemplateTest-CustomExtensions.js +++ b/test/TemplateTest-CustomExtensions.js @@ -372,3 +372,69 @@ test("Front matter in a custom extension", async (t) => { t.is(data.frontmatter, 1); t.is((await tmpl.render(data)).trim(), "hi"); }); + +test("Access to default renderer when you override an existing extension (async compile function, arrow render function)", async (t) => { + t.plan(2); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "liquid", + key: "liquid", + compileOptions: { + cache: false, + }, + compile: async function (str, inputPath) { + // plaintext + return async (data) => { + t.true(true); + return this.defaultRenderer(); + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default.liquid", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "hi"); +}); + +test("Access to default renderer when you override an existing extension (async compile function, async render function)", async (t) => { + t.plan(2); + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "liquid", + key: "liquid", + compileOptions: { + cache: false, + }, + compile: async function (str, inputPath) { + // plaintext + return async function (data) { + t.true(true); + return this.defaultRenderer(); + }; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/default.liquid", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), "hi"); +}); From 64b250588e9e0c6a185100b0dac21901c2a936cf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Feb 2022 13:22:11 -0600 Subject: [PATCH 711/746] Update a few dependencies. --- package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 06818f15c..0f2795faa 100755 --- a/package.json +++ b/package.json @@ -76,19 +76,19 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", + "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", - "@vue/server-renderer": "^3.2.26", + "@vue/server-renderer": "^3.2.31", "ava": "^4.0.1", "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^11.2.6", "markdown-it-emoji": "^2.0.0", - "marked": "^4.0.9", + "marked": "^4.0.12", "nyc": "^15.1.0", "prettier": "^2.5.1", "rimraf": "^3.0.2", - "sass": "^1.47.0", + "sass": "^1.49.7", "toml": "^3.0.0", "vue": "^3.2.26" }, @@ -97,18 +97,18 @@ "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.7", - "chokidar": "^3.5.2", + "chokidar": "^3.5.3", "debug": "^4.3.3", "dependency-graph": "^0.11.0", "ejs": "^3.1.6", - "fast-glob": "^3.2.9", + "fast-glob": "^3.2.11", "graceful-fs": "^4.2.9", "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", "is-glob": "^4.0.3", "kleur": "^4.1.4 ", - "liquidjs": "^9.32.0", + "liquidjs": "^9.34.0", "lodash": "^4.17.21", "luxon": "^2.3.0", "markdown-it": "^12.3.2", @@ -122,7 +122,7 @@ "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^3.0.2", - "recursive-copy": "^2.0.13", + "recursive-copy": "^2.0.14", "semver": "^7.3.5", "slugify": "^1.6.5" } From ad6816cad9dfa0e57feab02c3de14fee54e49c36 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Feb 2022 13:53:48 -0600 Subject: [PATCH 712/746] Old config file, not being used. --- .jsdoc.conf.json | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 .jsdoc.conf.json diff --git a/.jsdoc.conf.json b/.jsdoc.conf.json deleted file mode 100644 index 371494113..000000000 --- a/.jsdoc.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "plugins": ["plugins/markdown"], - "templates": { - "systemName": "Eleventy", - "theme": "cosmo", - "navType": "vertical", - "inverseNav": true, - "syntaxTheme": "dark", - "search": false - } -} From 94404531d26ef0b6e7f34ed426a6487bd08711b4 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Feb 2022 14:51:09 -0600 Subject: [PATCH 713/746] Fixes #2145 --- src/Template.js | 3 ++- test/EleventyTest.js | 16 +++++++++++++++- test/stubs-2145/_includes/layout.njk | 4 ++++ test/stubs-2145/test.njk | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/stubs-2145/_includes/layout.njk create mode 100644 test/stubs-2145/test.njk diff --git a/src/Template.js b/src/Template.js index 6d1166214..830ad839c 100755 --- a/src/Template.js +++ b/src/Template.js @@ -403,7 +403,8 @@ class Template extends TemplateContent { let frontMatterData = await this.getFrontMatterData(); let layoutKey = frontMatterData[this.config.keys.layout] || - localData[this.config.keys.layout]; + localData[this.config.keys.layout] || + globalData[this.config.keys.layout]; // Layout front matter data let mergedLayoutData = {}; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 255480ef6..38a3f596b 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -370,7 +370,7 @@ test("Can Eleventy run two executeBuilds in parallel?", async (t) => { ); }); -test("Eleventy addGlobalData should run once.", async (t) => { +test("Eleventy addGlobalData should run once", async (t) => { let count = 0; let elev = new Eleventy("./test/stubs-noop/", "./test/stubs-noop/_site", { config: function (eleventyConfig) { @@ -384,3 +384,17 @@ test("Eleventy addGlobalData should run once.", async (t) => { let results = await elev.toJSON(); t.is(count, 1); }); + +test("Eleventy addGlobalData can feed layouts to populate data cascade with layout data, issue #1245", async (t) => { + let count = 0; + 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"); +}); diff --git a/test/stubs-2145/_includes/layout.njk b/test/stubs-2145/_includes/layout.njk new file mode 100644 index 000000000..b1eda2e81 --- /dev/null +++ b/test/stubs-2145/_includes/layout.njk @@ -0,0 +1,4 @@ +--- +LayoutData: 123 +--- +FromLayout{{ content }} \ No newline at end of file diff --git a/test/stubs-2145/test.njk b/test/stubs-2145/test.njk new file mode 100644 index 000000000..9ea32fa5b --- /dev/null +++ b/test/stubs-2145/test.njk @@ -0,0 +1 @@ +{{ layout }} \ No newline at end of file From b5082b0f9e633891f802ea329da3b22f0a564a35 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Feb 2022 17:16:57 -0600 Subject: [PATCH 714/746] Fixes #646 --- src/EleventyErrorHandler.js | 26 +++++++++++-------- src/Template.js | 43 +++++++++++++++++++------------- src/TemplateConfig.js | 31 ++++++++++++++++++++--- src/TemplateWriter.js | 17 +++++++------ src/UserConfig.js | 15 ++++++++++- src/Util/ConsoleLogger.js | 2 +- test/EleventyErrorHandlerTest.js | 34 +++++++++++++++++-------- 7 files changed, 116 insertions(+), 52 deletions(-) diff --git a/src/EleventyErrorHandler.js b/src/EleventyErrorHandler.js index e58e677bf..3278d1b40 100644 --- a/src/EleventyErrorHandler.js +++ b/src/EleventyErrorHandler.js @@ -45,12 +45,20 @@ class EleventyErrorHandler { if (msg) { this.initialMessage(msg, "error", "red", true); } - this.log(e, "error", undefined, undefined, true); + this.log(e, "error", undefined, true); } //https://nodejs.org/api/process.html - log(e, type = "log", prefix = ">", chalkColor = "", forceToConsole = false) { + log(e, type = "log", chalkColor = "", forceToConsole = false) { + let errorCount = 0; + let errorCountRef = e; + while (errorCountRef) { + errorCount++; + errorCountRef = errorCountRef.originalError; + } + let ref = e; + let index = 1; while (ref) { let nextRef = ref.originalError; if (!nextRef && EleventyErrorUtil.hasEmbeddedError(ref.message)) { @@ -58,13 +66,10 @@ class EleventyErrorHandler { } this.logger.message( - (process.env.DEBUG ? "" : `${prefix} `) + - `${( - EleventyErrorUtil.cleanMessage(ref.message) || - "(No error message provided)" - ).trim()} - -\`${ref.name}\` was thrown${!nextRef && ref.stack ? ":" : ""}`, + `${errorCount > 1 ? `${index}. ` : ""}${( + EleventyErrorUtil.cleanMessage(ref.message) || + "(No error message provided)" + ).trim()} (via ${ref.name})`, type, chalkColor, forceToConsole @@ -85,13 +90,14 @@ class EleventyErrorHandler { ); } this.logger.message( - prefix + stackStr.split("\n").join("\n" + prefix), + "\nOriginal error stack trace: " + stackStr, type, chalkColor, forceToConsole ); } ref = nextRef; + index++; } } diff --git a/src/Template.js b/src/Template.js index 830ad839c..1a3a81428 100755 --- a/src/Template.js +++ b/src/Template.js @@ -19,11 +19,15 @@ const TemplateLayout = require("./TemplateLayout"); const TemplateFileSlug = require("./TemplateFileSlug"); const ComputedData = require("./ComputedData"); 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 TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); +const TemplateContentUnrenderedTemplateError = require("./Errors/TemplateContentUnrenderedTemplateError"); + +const EleventyBaseError = require("./EleventyBaseError"); +class EleventyTransformError extends EleventyBaseError {} + const debug = require("debug")("Eleventy:Template"); const debugDev = require("debug")("Dev:Eleventy:Template"); @@ -54,7 +58,6 @@ class Template extends TemplateContent { this.linters = []; this.transforms = []; - this.plugins = {}; this.templateData = templateData; if (this.templateData) { this.templateData.setInputDir(this.inputDir); @@ -546,21 +549,27 @@ class Template extends TemplateContent { }); } - // Warning: this argument list is the reverse of linters (inputPath then outputPath) async runTransforms(str, inputPath, outputPath) { - for (let transform of this.transforms) { - let hadStrBefore = !!str; - str = await transform.callback.call( - { - inputPath, - outputPath, - }, - str, - outputPath - ); - if (hadStrBefore && !str) { - this.logger.warn( - `Warning: Transform \`${transform.name}\` returned empty when writing ${outputPath} from ${inputPath}.` + for (let { callback, name } of this.transforms) { + try { + let hadStrBefore = !!str; + str = await callback.call( + { + inputPath, + outputPath, + }, + str, + outputPath + ); + if (hadStrBefore && !str) { + this.logger.warn( + `Warning: Transform \`${name}\` returned empty when writing ${outputPath} from ${inputPath}.` + ); + } + } catch (e) { + throw new EleventyTransformError( + `Transform \`${name}\` encountered an error when transforming ${inputPath}.`, + e ); } } diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index f29fd91b6..439b55653 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -30,6 +30,11 @@ const deleteRequireCache = require("./Util/DeleteRequireCache"); */ class EleventyConfigError extends EleventyBaseError {} +/** + * Errors in eleventy plugins. + */ +class EleventyPluginError extends EleventyBaseError {} + /** * Config for a template. * @@ -181,11 +186,29 @@ class TemplateConfig { this.userConfig._enablePluginExecution(); let storedActiveNamespace = this.userConfig.activeNamespace; + for (let { plugin, options, pluginNamespace } of this.userConfig.plugins) { + try { + this.userConfig.activeNamespace = pluginNamespace; + this.userConfig._executePlugin(plugin, options); + } catch (e) { + let name = this.userConfig._getPluginName(plugin); + let namespaces = [storedActiveNamespace, pluginNamespace].filter( + (entry) => !!entry + ); - this.userConfig.plugins.forEach(({ plugin, options, pluginNamespace }) => { - this.userConfig.activeNamespace = pluginNamespace; - this.userConfig._executePlugin(plugin, options); - }); + let namespaceStr = ""; + if (namespaces.length) { + namespaceStr = ` (namespace: ${namespaces.join(".")})`; + } + + throw new EleventyPluginError( + `Error processing ${ + name ? `the \`${name}\`` : "a" + } plugin${namespaceStr}`, + e + ); + } + } this.userConfig.activeNamespace = storedActiveNamespace; } diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 2dbc1ee35..b5ac9dd0d 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -11,8 +11,9 @@ const ConsoleLogger = require("./Util/ConsoleLogger"); const debug = require("debug")("Eleventy:TemplateWriter"); const debugDev = require("debug")("Dev:Eleventy:TemplateWriter"); -class TemplateWriterError extends EleventyBaseError {} -class TemplateWriterWriteError extends EleventyBaseError {} +class TemplateWriterMissingConfigArgError extends EleventyBaseError {} +class EleventyPassthroughCopyError extends EleventyBaseError {} +class EleventyTemplateError extends EleventyBaseError {} class TemplateWriter { constructor( @@ -23,7 +24,7 @@ class TemplateWriter { eleventyConfig ) { if (!eleventyConfig) { - throw new TemplateWriterError("Missing config argument."); + throw new TemplateWriterMissingConfigArgError("Missing config argument."); } this.eleventyConfig = eleventyConfig; this.config = eleventyConfig.getConfig(); @@ -262,7 +263,7 @@ class TemplateWriter { return passthroughManager.copyAll(paths).catch((e) => { this.errorHandler.warn(e, "Error with passthrough copy"); return Promise.reject( - new TemplateWriterWriteError("Having trouble copying", e) + new EleventyPassthroughCopyError("Having trouble copying", e) ); }); } @@ -286,8 +287,8 @@ class TemplateWriter { usedTemplateContentTooEarlyMap.push(mapEntry); } else { return Promise.reject( - new TemplateWriterWriteError( - `Having trouble writing template: ${mapEntry.outputPath}`, + new EleventyTemplateError( + `Having trouble writing template: "${mapEntry.outputPath}"`, e ) ); @@ -300,8 +301,8 @@ class TemplateWriter { promises.push( this._generateTemplate(mapEntry, to).catch(function (e) { return Promise.reject( - new TemplateWriterWriteError( - `Having trouble writing template (second pass): ${mapEntry.outputPath}`, + new EleventyTemplateError( + `Having trouble writing template (second pass): "${mapEntry.outputPath}"`, e ) ); diff --git a/src/UserConfig.js b/src/UserConfig.js index e639b0f6e..5a503edcc 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -340,8 +340,21 @@ class UserConfig { } } + // Using Function.name https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#examples + _getPluginName(plugin) { + if (typeof plugin === "function") { + return plugin.name; + } else if ( + plugin.configFunction && + typeof plugin.configFunction === "function" + ) { + return plugin.configFunction.name; + } + } + _executePlugin(plugin, options) { - debug(`Adding ${plugin.name || "anonymous"} plugin`); + let name = this._getPluginName(plugin); + debug(`Adding ${name || "anonymous"} plugin`); let pluginBenchmark = this.benchmarks.aggregate.get( "Configuration addPlugin" ); diff --git a/src/Util/ConsoleLogger.js b/src/Util/ConsoleLogger.js index 68bc50379..664ee0b7e 100644 --- a/src/Util/ConsoleLogger.js +++ b/src/Util/ConsoleLogger.js @@ -61,7 +61,7 @@ class ConsoleLogger { if (!forceToConsole && (!this.isVerbose || process.env.DEBUG)) { debug(message); } else if (this._logger !== false) { - message = `[11ty] ${message}`; + message = `[11ty] ${message.split("\n").join("\n[11ty] ")}`; let logger = this._logger || console; if (chalkColor && this.isChalkEnabled) { diff --git a/test/EleventyErrorHandlerTest.js b/test/EleventyErrorHandlerTest.js index cc7922908..c2c673f75 100644 --- a/test/EleventyErrorHandlerTest.js +++ b/test/EleventyErrorHandlerTest.js @@ -1,7 +1,7 @@ const test = require("ava"); const EleventyErrorHandler = require("../src/EleventyErrorHandler"); -test("Log a warning, error", (t) => { +test("Log a warning, warning", (t) => { let errorHandler = new EleventyErrorHandler(); let output = []; errorHandler.logger = { @@ -18,24 +18,36 @@ test("Log a warning, error", (t) => { output.push(str); }, }; - errorHandler.warn(new Error("Test warning"), "Hello"); - let expected = `Hello: (more in DEBUG output) -> Test warning - -\`Error\` was thrown: - Error: Test warning`; + let expected = "Hello: (more in DEBUG output)"; t.is(output.join("\n").substr(0, expected.length), expected); +}); - output = []; +test("Log a warning, error", (t) => { + let errorHandler = new EleventyErrorHandler(); + + let output = []; + errorHandler.logger = { + log: function (str) { + output.push(str); + }, + warn: function (str) { + output.push(str); + }, + error: function (str) { + output.push(str); + }, + message: function (str) { + output.push(str); + }, + }; errorHandler.error(new Error("Test error"), "It’s me"); expected = `It’s me: (more in DEBUG output) -> Test error +Test error (via Error) -\`Error\` was thrown: - Error: Test error`; +Original error stack trace: Error: Test error`; t.is(output.join("\n").substr(0, expected.length), expected); }); From 3715a2270252bb550a5c985a9a99158b76a68aa1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Feb 2022 17:32:05 -0600 Subject: [PATCH 715/746] Fixes #670 (though it was already fixed, but this is a sanity check) --- test/EleventyTest.js | 7 +++++++ test/stubs-670/content.liquid | 3 +++ test/stubs-670/index.liquid | 1 + 3 files changed, 11 insertions(+) create mode 100644 test/stubs-670/content.liquid create mode 100644 test/stubs-670/index.liquid diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 38a3f596b..36e99c4ab 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -398,3 +398,10 @@ test("Eleventy addGlobalData can feed layouts to populate data cascade with layo 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"); + + let [result] = await elev.toJSON(); + t.is(result.content.trim(), "./test/stubs-670/content.liquid"); +}); diff --git a/test/stubs-670/content.liquid b/test/stubs-670/content.liquid new file mode 100644 index 000000000..edceab8ea --- /dev/null +++ b/test/stubs-670/content.liquid @@ -0,0 +1,3 @@ +--- +tags: "Cañon City" +--- \ No newline at end of file diff --git a/test/stubs-670/index.liquid b/test/stubs-670/index.liquid new file mode 100644 index 000000000..6d9855de9 --- /dev/null +++ b/test/stubs-670/index.liquid @@ -0,0 +1 @@ +{% for item in collections['Cañon City'] %}{{ item.inputPath }}{% endfor %} \ No newline at end of file From 2c7c65b136a0601df1829d7954f54de7af504935 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 16 Feb 2022 22:09:36 -0600 Subject: [PATCH 716/746] Fixes brittle test for #670 --- test/EleventyTest.js | 11 +++++++++-- test/stubs-670/content.liquid | 3 --- test/stubs-670/content.njk | 4 ++++ test/stubs-670/index.liquid | 1 - test/stubs-670/index.njk | 1 + 5 files changed, 14 insertions(+), 6 deletions(-) delete mode 100644 test/stubs-670/content.liquid create mode 100644 test/stubs-670/content.njk delete mode 100644 test/stubs-670/index.liquid create mode 100644 test/stubs-670/index.njk diff --git a/test/EleventyTest.js b/test/EleventyTest.js index 36e99c4ab..e7f1c2b51 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -402,6 +402,13 @@ test("Eleventy addGlobalData can feed layouts to populate data cascade with layo test("Unicode in front matter `tags`, issue #670", async (t) => { let elev = new Eleventy("./test/stubs-670/", "./test/stubs-670/_site"); - let [result] = await elev.toJSON(); - t.is(result.content.trim(), "./test/stubs-670/content.liquid"); + let results = await elev.toJSON(); + results.sort((a, b) => { + if (a.inputPath > b.inputPath) { + return -1; + } + return 1; + }); + + t.is(results[0].content.trim(), "2,all,Cañon City,"); }); diff --git a/test/stubs-670/content.liquid b/test/stubs-670/content.liquid deleted file mode 100644 index edceab8ea..000000000 --- a/test/stubs-670/content.liquid +++ /dev/null @@ -1,3 +0,0 @@ ---- -tags: "Cañon City" ---- \ No newline at end of file diff --git a/test/stubs-670/content.njk b/test/stubs-670/content.njk new file mode 100644 index 000000000..eca571b93 --- /dev/null +++ b/test/stubs-670/content.njk @@ -0,0 +1,4 @@ +--- +tags: + - Cañon City +--- \ No newline at end of file diff --git a/test/stubs-670/index.liquid b/test/stubs-670/index.liquid deleted file mode 100644 index 6d9855de9..000000000 --- a/test/stubs-670/index.liquid +++ /dev/null @@ -1 +0,0 @@ -{% for item in collections['Cañon City'] %}{{ item.inputPath }}{% endfor %} \ No newline at end of file diff --git a/test/stubs-670/index.njk b/test/stubs-670/index.njk new file mode 100644 index 000000000..1566bb205 --- /dev/null +++ b/test/stubs-670/index.njk @@ -0,0 +1 @@ +{{ collections | length }},{% for key,item in collections %}{{ key }},{% endfor %} \ No newline at end of file From 65ca92859b0bcd0a6deeb821fb59167877a859e9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Feb 2022 16:53:04 -0600 Subject: [PATCH 717/746] Add to git --- test/stubs-142/index.njk | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 test/stubs-142/index.njk diff --git a/test/stubs-142/index.njk b/test/stubs-142/index.njk new file mode 100644 index 000000000..3e3f9eeba --- /dev/null +++ b/test/stubs-142/index.njk @@ -0,0 +1,4 @@ +--- +date: git Last Modified +--- +{{ page.date }} \ No newline at end of file From 8f35e553f80a9a75da3b2eb1a923ecce87f65573 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Feb 2022 17:13:13 -0600 Subject: [PATCH 718/746] Fixes #142. Adds `date: "git Last Modified"` support to use last git commit as `page.date` variable. --- package.json | 1 + src/Template.js | 58 ++++++++++++++++++++-------------- src/Util/DateGitLastUpdated.js | 28 ++++++++++++++++ test/EleventyTest.js | 12 +++++++ test/stubs-142/index.njk | 2 +- 5 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 src/Util/DateGitLastUpdated.js diff --git a/package.json b/package.json index 0f2795faa..bcec400db 100755 --- a/package.json +++ b/package.json @@ -98,6 +98,7 @@ "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.7", "chokidar": "^3.5.3", + "cross-spawn": "^7.0.3", "debug": "^4.3.3", "dependency-graph": "^0.11.0", "ejs": "^3.1.6", diff --git a/src/Template.js b/src/Template.js index 1a3a81428..9bcd4ef49 100755 --- a/src/Template.js +++ b/src/Template.js @@ -6,11 +6,14 @@ const mkdir = util.promisify(fs.mkdir); const os = require("os"); const path = require("path"); const normalize = require("normalize-path"); -const isPlainObject = require("./Util/IsPlainObject"); const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); const { DateTime } = require("luxon"); +const isPlainObject = require("./Util/IsPlainObject"); +const ConsoleLogger = require("./Util/ConsoleLogger"); +const getDateFromGitLastUpdated = require("./Util/DateGitLastUpdated"); + const TemplateData = require("./TemplateData"); const TemplateContent = require("./TemplateContent"); const TemplatePath = require("./TemplatePath"); @@ -19,7 +22,6 @@ const TemplateLayout = require("./TemplateLayout"); const TemplateFileSlug = require("./TemplateFileSlug"); const ComputedData = require("./ComputedData"); const Pagination = require("./Plugins/Pagination"); -const ConsoleLogger = require("./Util/ConsoleLogger"); const TemplateBehavior = require("./TemplateBehavior"); const TemplateContentPrematureUseError = require("./Errors/TemplateContentPrematureUseError"); @@ -1016,30 +1018,40 @@ class Template extends TemplateContent { // YAML does its own date parsing debug("getMappedDate: YAML parsed it: %o", data.date); return data.date; - } else { - // string - if (data.date.toLowerCase() === "last modified") { - return this._getDateInstance("ctimeMs"); - } else if (data.date.toLowerCase() === "created") { - return this._getDateInstance("birthtimeMs"); - } else { - // try to parse with Luxon - let date = DateTime.fromISO(data.date, { zone: "utc" }); - if (!date.isValid) { - throw new Error( - `date front matter value (${data.date}) is invalid for ${this.inputPath}` - ); - } - debug( - "getMappedDate: Luxon parsed %o: %o and %o", - data.date, - date, - date.toJSDate() - ); + } - return date.toJSDate(); + // special strings + if (data.date.toLowerCase() === "git last modified") { + let d = getDateFromGitLastUpdated(this.inputPath); + if (d) { + return d; } + + // return now if this file is not yet available in `git` + return Date.now(); + } + if (data.date.toLowerCase() === "last modified") { + return this._getDateInstance("ctimeMs"); + } + if (data.date.toLowerCase() === "created") { + return this._getDateInstance("birthtimeMs"); + } + + // try to parse with Luxon + let date = DateTime.fromISO(data.date, { zone: "utc" }); + if (!date.isValid) { + throw new Error( + `date front matter value (${data.date}) is invalid for ${this.inputPath}` + ); } + debug( + "getMappedDate: Luxon parsed %o: %o and %o", + data.date, + date, + date.toJSDate() + ); + + return date.toJSDate(); } else { let filepathRegex = this.inputPath.match(/(\d{4}-\d{2}-\d{2})/); if (filepathRegex !== null) { diff --git a/src/Util/DateGitLastUpdated.js b/src/Util/DateGitLastUpdated.js new file mode 100644 index 000000000..905af887b --- /dev/null +++ b/src/Util/DateGitLastUpdated.js @@ -0,0 +1,28 @@ +const spawn = require("cross-spawn"); + +/* Thank you to Vuepress! + * https://github.com/vuejs/vuepress/blob/89440ce552675859189ed4ab254ce19c4bba5447/packages/%40vuepress/plugin-last-updated/index.js + * MIT licensed: https://github.com/vuejs/vuepress/blob/89440ce552675859189ed4ab254ce19c4bba5447/LICENSE + */ +function getGitLastUpdatedTimeStamp(filePath) { + return ( + parseInt( + spawn + .sync( + "git", + // Formats https://www.git-scm.com/docs/git-log#_pretty_formats + // %at author date, UNIX timestamp + ["log", "-1", "--format=%at", filePath] + ) + .stdout.toString("utf-8") + ) * 1000 + ); +} + +// return a Date +module.exports = function (inputPath) { + let timestamp = getGitLastUpdatedTimeStamp(inputPath); + if (timestamp) { + return new Date(timestamp); + } +}; diff --git a/test/EleventyTest.js b/test/EleventyTest.js index e7f1c2b51..e50dce3bd 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -2,6 +2,7 @@ const test = require("ava"); const Eleventy = require("../src/Eleventy"); const EleventyWatchTargets = require("../src/EleventyWatchTargets"); const TemplateConfig = require("../src/TemplateConfig"); +const DateGitLastUpdated = require("../src/Util/DateGitLastUpdated"); test("Eleventy, defaults inherit from config", async (t) => { let elev = new Eleventy(); @@ -412,3 +413,14 @@ test("Unicode in front matter `tags`, issue #670", async (t) => { t.is(results[0].content.trim(), "2,all,Cañon City,"); }); + +test("#142: date 'git Last Modified' populates page.date", async (t) => { + let elev = new Eleventy("./test/stubs-142/", "./test/stubs-142/_site"); + + let results = await elev.toJSON(); + let [result] = results; + + // This doesn’t test the validity of the function, only that it populates page.date. + let comparisonDate = DateGitLastUpdated("./test/stubs-142/index.njk"); + t.is(result.content.trim(), "" + comparisonDate.getTime()); +}); diff --git a/test/stubs-142/index.njk b/test/stubs-142/index.njk index 3e3f9eeba..45d5aee90 100644 --- a/test/stubs-142/index.njk +++ b/test/stubs-142/index.njk @@ -1,4 +1,4 @@ --- date: git Last Modified --- -{{ page.date }} \ No newline at end of file +{{ page.date.getTime() }} \ No newline at end of file From 1df6299d2b985ded402d43d8fb0e763dea37dc93 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Feb 2022 17:42:33 -0600 Subject: [PATCH 719/746] v1.0.1-canary.3 --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index bcec400db..dc91c4a69 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.1-canary.2", + "version": "1.0.1-canary.3", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -88,9 +88,9 @@ "nyc": "^15.1.0", "prettier": "^2.5.1", "rimraf": "^3.0.2", - "sass": "^1.49.7", + "sass": "^1.49.8", "toml": "^3.0.0", - "vue": "^3.2.26" + "vue": "^3.2.31" }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", From 30e355129382e81678e3901b55536dc2881b4ebf Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 18 Feb 2022 14:40:57 -0600 Subject: [PATCH 720/746] Fixes #2221, changes to use event.rawUrl workaround. Also populates rawUrl for local development. --- src/Plugins/DefaultServerlessFunctionContent.js | 8 +++++--- src/Plugins/ServerlessBundlerPlugin.js | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Plugins/DefaultServerlessFunctionContent.js b/src/Plugins/DefaultServerlessFunctionContent.js index d252a599b..8e934fc59 100644 --- a/src/Plugins/DefaultServerlessFunctionContent.js +++ b/src/Plugins/DefaultServerlessFunctionContent.js @@ -6,7 +6,7 @@ require("./eleventy-bundler-modules.js"); async function handler(event) { let elev = new EleventyServerless("%%NAME%%", { - path: event.path, + path: new URL(event.rawUrl).pathname, query: event.queryStringParameters, functionsDir: "%%FUNCTIONS_DIR%%", }); @@ -45,9 +45,11 @@ async function handler(event) { } // Choose one: -// * Runs on each request: AWS Lambda (or Netlify Function) +// * Runs on each request: AWS Lambda, Netlify Function // * Runs on first request only: Netlify On-demand Builder -// (don’t forget to `npm install @netlify/functions`) +// 1. Don’t forget to `npm install @netlify/functions` +// 2. Also use `redirects: "netlify-toml-builders"` in your config file’s serverless bundler options: +// https://www.11ty.dev/docs/plugins/serverless/#bundler-options exports.handler = handler; diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index 815179f7c..a098d814e 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -238,6 +238,7 @@ class BundlerHelper { let result = await serverlessFunction.handler({ httpMethod: "GET", path: url.pathname, + rawUrl: url.toString(), // @netlify/functions builder overwrites these to {} intentionally // See https://github.com/netlify/functions/issues/38 queryStringParameters: queryParams, From 023f1e98f441ea691242be14844d7bf36471c074 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 23 Feb 2022 13:52:48 -0600 Subject: [PATCH 721/746] Fix broken doc requests link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ae7a5236..76c330c5a 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ npm run test - [Code Coverage Statistics](https://github.com/11ty/eleventy/blob/master/docs/coverage.md) - [Benchmark for Performance Regressions](https://github.com/11ty/eleventy-benchmark) -## Major Roadmapped Features +## Community Roadmap - [Top Feature Requests](https://github.com/11ty/eleventy/issues?q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc) (Add your own votes using the 👍 reaction) -- [Documentation Requests](https://github.com/11ty/eleventy/issues?utf8=%E2%9C%93&q=is%3Aissue+sort%3Areactions-%2B1-desc+is%3Aclosed+label%3Adocumentation+label%3Aneeds-votes) (Add your own votes using the 👍 reaction) +- [Documentation Requests](https://github.com/11ty/eleventy/issues?utf8=%E2%9C%93&q=is%3Aissue+sort%3Areactions-1-desc+is%3Aclosed+label%3Adocumentation+label%3Aneeds-votes) (Add your own votes using the 👍 reaction) - [Top Bugs 😱](https://github.com/11ty/eleventy/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Areactions-%2B1-desc) (Add your own votes using the 👍 reaction) - [Newest Bugs 🙀](https://github.com/11ty/eleventy/issues?q=is%3Aopen+is%3Aissue+label%3Abug) From c1c41098214bd72b81a1737b89f6f018b7c82f41 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 23 Feb 2022 13:56:40 -0600 Subject: [PATCH 722/746] Some of the other roadmap links were broken too --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 76c330c5a..c37939bf5 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,8 @@ npm run test ## Community Roadmap -- [Top Feature Requests](https://github.com/11ty/eleventy/issues?q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc) (Add your own votes using the 👍 reaction) -- [Documentation Requests](https://github.com/11ty/eleventy/issues?utf8=%E2%9C%93&q=is%3Aissue+sort%3Areactions-1-desc+is%3Aclosed+label%3Adocumentation+label%3Aneeds-votes) (Add your own votes using the 👍 reaction) +- [Top Feature Requests](https://github.com/11ty/eleventy/issues?q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc+label%3Aenhancement) (Add your own votes using the 👍 reaction) +- [Documentation Requests](https://github.com/11ty/eleventy/issues?q=is%3Aissue+label%3Adocumentation+label%3Aneeds-votes+sort%3Areactions-%2B1-desc) (Add your own votes using the 👍 reaction) - [Top Bugs 😱](https://github.com/11ty/eleventy/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Areactions-%2B1-desc) (Add your own votes using the 👍 reaction) - [Newest Bugs 🙀](https://github.com/11ty/eleventy/issues?q=is%3Aopen+is%3Aissue+label%3Abug) From 7091b3db1d78c17250574dfc81428c7017a9ea53 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 23 Feb 2022 15:53:26 -0600 Subject: [PATCH 723/746] Somehow this test needs a join now. --- test/TemplateRenderLiquidTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TemplateRenderLiquidTest.js b/test/TemplateRenderLiquidTest.js index 78cdc16fa..6cfdec555 100644 --- a/test/TemplateRenderLiquidTest.js +++ b/test/TemplateRenderLiquidTest.js @@ -1098,7 +1098,7 @@ test("Liquid bypass compilation", async (t) => { test("Liquid reverse filter in {{ }}", async (t) => { // https://liquidjs.com/filters/reverse.html let fn = await getNewTemplateRender("liquid").getCompiledTemplate( - "{{ test | reverse }}" + "{{ test | reverse | join: ',' }}" ); t.is(await fn({ test: [1, 2, 3] }), "3,2,1"); }); From 9b5dc84bdfe6ec4f303f5cf4fad6efcc6545394d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 4 Mar 2022 22:35:21 -0600 Subject: [PATCH 724/746] Cherry pick: use @11ty/eleventy-utils for TemplatePath. --- docs-src/.eleventy.docs.js | 10 +- src/Eleventy.js | 5 +- src/EleventyBaseError.js | 4 +- src/EleventyExtensionMap.js | 3 +- src/EleventyFiles.js | 2 +- src/EleventyServe.js | 2 +- src/EleventyWatch.js | 2 +- src/EleventyWatchTargets.js | 3 +- src/Engines/JavaScript.js | 3 +- src/Engines/Liquid.js | 3 +- src/Engines/Nunjucks.js | 3 +- src/Engines/TemplateEngine.js | 3 +- src/Filters/Url.js | 2 +- src/Plugins/RenderPlugin.js | 2 +- src/Plugins/ServerlessBundlerPlugin.js | 3 +- src/Serverless.js | 4 +- src/Template.js | 2 +- src/TemplateCollection.js | 2 +- src/TemplateConfig.js | 2 +- src/TemplateContent.js | 2 +- src/TemplateData.js | 3 +- src/TemplateFileSlug.js | 2 +- src/TemplateGlob.js | 2 +- src/TemplateLayout.js | 3 +- src/TemplateLayoutPathResolver.js | 3 +- src/TemplatePassthrough.js | 5 +- src/TemplatePassthroughManager.js | 5 +- src/TemplatePath.js | 356 ------------------ src/TemplatePermalink.js | 3 +- src/TemplateRender.js | 3 +- src/TemplateWriter.js | 3 +- ...leventyFilesGitIgnoreEleventyIgnoreTest.js | 3 +- test/TemplateGlobTest.js | 3 +- test/TemplatePathTest.js | 346 ----------------- 34 files changed, 60 insertions(+), 742 deletions(-) delete mode 100644 src/TemplatePath.js delete mode 100644 test/TemplatePathTest.js diff --git a/docs-src/.eleventy.docs.js b/docs-src/.eleventy.docs.js index fd4809884..ddd895b8d 100644 --- a/docs-src/.eleventy.docs.js +++ b/docs-src/.eleventy.docs.js @@ -1,18 +1,18 @@ -const TemplatePath = require("../src/TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); module.exports = { templateFormats: ["njk"], dir: { input: "docs-src", data: "_data", - output: "docs" + output: "docs", }, nunjucksFilters: { - removeDir: function(str) { + removeDir: function (str) { return TemplatePath.stripLeadingSubPath( str, TemplatePath.join(__dirname, "..") ); - } - } + }, + }, }; diff --git a/src/Eleventy.js b/src/Eleventy.js index 02ae1eccc..a4c50cd0a 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -1,5 +1,7 @@ +const { TemplatePath } = require("@11ty/eleventy-utils"); +const { performance } = require("perf_hooks"); + const pkg = require("../package.json"); -const TemplatePath = require("./TemplatePath"); const TemplateData = require("./TemplateData"); const TemplateWriter = require("./TemplateWriter"); const EleventyExtensionMap = require("./EleventyExtensionMap"); @@ -11,7 +13,6 @@ const EleventyWatchTargets = require("./EleventyWatchTargets"); const EleventyFiles = require("./EleventyFiles"); const ConsoleLogger = require("./Util/ConsoleLogger"); const TemplateConfig = require("./TemplateConfig"); -const { performance } = require("perf_hooks"); const templateCache = require("./TemplateCache"); const simplePlural = require("./Util/Pluralize"); diff --git a/src/EleventyBaseError.js b/src/EleventyBaseError.js index f5269131d..55682e4c2 100644 --- a/src/EleventyBaseError.js +++ b/src/EleventyBaseError.js @@ -4,7 +4,7 @@ class EleventyBaseError extends Error { /** * @param {string} message - The error message to display. - * @param {Error} originalError - The original error catched. + * @param {Error} originalError - The original error caught. */ constructor(message, originalError) { super(message); @@ -15,7 +15,7 @@ class EleventyBaseError extends Error { Error.captureStackTrace(this, this.constructor); if (originalError) { - /** @type {Error} - The original error catched. */ + /** @type {Error} - The original error caught. */ this.originalError = originalError; } } diff --git a/src/EleventyExtensionMap.js b/src/EleventyExtensionMap.js index f3ebb80c4..c1ed73403 100644 --- a/src/EleventyExtensionMap.js +++ b/src/EleventyExtensionMap.js @@ -1,6 +1,7 @@ +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateEngineManager = require("./TemplateEngineManager"); const TemplateConfig = require("./TemplateConfig"); -const TemplatePath = require("./TemplatePath"); const EleventyBaseError = require("./EleventyBaseError"); class EleventyExtensionMapConfigError extends EleventyBaseError {} diff --git a/src/EleventyFiles.js b/src/EleventyFiles.js index 3da8f26aa..f60f04e5f 100644 --- a/src/EleventyFiles.js +++ b/src/EleventyFiles.js @@ -1,10 +1,10 @@ const fs = require("fs"); const fastglob = require("fast-glob"); +const { TemplatePath } = require("@11ty/eleventy-utils"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const TemplateData = require("./TemplateData"); const TemplateGlob = require("./TemplateGlob"); -const TemplatePath = require("./TemplatePath"); const TemplatePassthroughManager = require("./TemplatePassthroughManager"); const EleventyBaseError = require("./EleventyBaseError"); diff --git a/src/EleventyServe.js b/src/EleventyServe.js index 277b52895..3bcc17597 100644 --- a/src/EleventyServe.js +++ b/src/EleventyServe.js @@ -1,7 +1,7 @@ const fs = require("fs"); const path = require("path"); -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); const EleventyBaseError = require("./EleventyBaseError"); const debug = require("debug")("EleventyServe"); diff --git a/src/EleventyWatch.js b/src/EleventyWatch.js index 537b360dc..bdec68553 100755 --- a/src/EleventyWatch.js +++ b/src/EleventyWatch.js @@ -1,4 +1,4 @@ -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); /* Decides when to watch and in what mode to watch * Incremental builds don’t batch changes, they queue. diff --git a/src/EleventyWatchTargets.js b/src/EleventyWatchTargets.js index 8a4a52fdd..57ba239fd 100644 --- a/src/EleventyWatchTargets.js +++ b/src/EleventyWatchTargets.js @@ -1,5 +1,6 @@ const dependencyTree = require("@11ty/dependency-tree"); -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const deleteRequireCache = require("./Util/DeleteRequireCache"); class EleventyWatchTargets { diff --git a/src/Engines/JavaScript.js b/src/Engines/JavaScript.js index f3134f9f6..947eb2742 100644 --- a/src/Engines/JavaScript.js +++ b/src/Engines/JavaScript.js @@ -1,5 +1,6 @@ +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateEngine = require("./TemplateEngine"); -const TemplatePath = require("../TemplatePath"); const EleventyBaseError = require("../EleventyBaseError"); const deleteRequireCache = require("../Util/DeleteRequireCache"); const getJavaScriptData = require("../Util/GetJavaScriptData"); diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index 071315ddc..cc26c2560 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -1,7 +1,8 @@ const moo = require("moo"); const liquidLib = require("liquidjs"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateEngine = require("./TemplateEngine"); -const TemplatePath = require("../TemplatePath"); // const debug = require("debug")("Eleventy:Liquid"); class Liquid extends TemplateEngine { diff --git a/src/Engines/Nunjucks.js b/src/Engines/Nunjucks.js index 5d3bcfd1b..63ff238c5 100755 --- a/src/Engines/Nunjucks.js +++ b/src/Engines/Nunjucks.js @@ -1,6 +1,7 @@ const NunjucksLib = require("nunjucks"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateEngine = require("./TemplateEngine"); -const TemplatePath = require("../TemplatePath"); const EleventyErrorUtil = require("../EleventyErrorUtil"); const EleventyBaseError = require("../EleventyBaseError"); const eventBus = require("../EventBus"); diff --git a/src/Engines/TemplateEngine.js b/src/Engines/TemplateEngine.js index 8edb5407b..e258c862f 100644 --- a/src/Engines/TemplateEngine.js +++ b/src/Engines/TemplateEngine.js @@ -1,6 +1,7 @@ const fastglob = require("fast-glob"); const fs = require("fs"); -const TemplatePath = require("../TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateConfig = require("../TemplateConfig"); const EleventyExtensionMap = require("../EleventyExtensionMap"); const EleventyBaseError = require("../EleventyBaseError"); diff --git a/src/Filters/Url.js b/src/Filters/Url.js index fb7e955a1..831ead0be 100644 --- a/src/Filters/Url.js +++ b/src/Filters/Url.js @@ -1,4 +1,4 @@ -const TemplatePath = require("../TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); function isValidUrl(url) { try { diff --git a/src/Plugins/RenderPlugin.js b/src/Plugins/RenderPlugin.js index 10948a278..e5ea016cf 100644 --- a/src/Plugins/RenderPlugin.js +++ b/src/Plugins/RenderPlugin.js @@ -1,10 +1,10 @@ const fs = require("fs"); const fsp = fs.promises; const isPlainObject = require("../Util/IsPlainObject"); +const { TemplatePath } = require("@11ty/eleventy-utils"); // TODO add a first-class Markdown component to expose this using Markdown-only syntax (will need to be synchronous for markdown-it) -const TemplatePath = require("../TemplatePath"); const TemplateRender = require("../TemplateRender"); const TemplateConfig = require("../TemplateConfig"); const Liquid = require("../Engines/Liquid"); diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index a098d814e..a76120222 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -5,7 +5,8 @@ const isGlob = require("is-glob"); const TOML = require("@iarna/toml"); const copy = require("recursive-copy"); const dependencyTree = require("@11ty/dependency-tree"); -const TemplatePath = require("../TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const deleteRequireCache = require("../Util/DeleteRequireCache"); const debug = require("debug")("Eleventy:Serverless"); diff --git a/src/Serverless.js b/src/Serverless.js index cb67a895b..a69ad3066 100644 --- a/src/Serverless.js +++ b/src/Serverless.js @@ -1,9 +1,9 @@ const path = require("path"); const fs = require("fs"); +const { match } = require("path-to-regexp"); +const { TemplatePath } = require("@11ty/eleventy-utils"); const Eleventy = require("./Eleventy"); -const TemplatePath = require("./TemplatePath"); -const { match } = require("path-to-regexp"); const deleteRequireCache = require("./Util/DeleteRequireCache"); const debug = require("debug")("Eleventy:Serverless"); diff --git a/src/Template.js b/src/Template.js index 9bcd4ef49..581924b67 100755 --- a/src/Template.js +++ b/src/Template.js @@ -9,6 +9,7 @@ const normalize = require("normalize-path"); const lodashGet = require("lodash/get"); const lodashSet = require("lodash/set"); const { DateTime } = require("luxon"); +const { TemplatePath } = require("@11ty/eleventy-utils"); const isPlainObject = require("./Util/IsPlainObject"); const ConsoleLogger = require("./Util/ConsoleLogger"); @@ -16,7 +17,6 @@ const getDateFromGitLastUpdated = require("./Util/DateGitLastUpdated"); const TemplateData = require("./TemplateData"); const TemplateContent = require("./TemplateContent"); -const TemplatePath = require("./TemplatePath"); const TemplatePermalink = require("./TemplatePermalink"); const TemplateLayout = require("./TemplateLayout"); const TemplateFileSlug = require("./TemplateFileSlug"); diff --git a/src/TemplateCollection.js b/src/TemplateCollection.js index f3026ef02..dad9801c6 100755 --- a/src/TemplateCollection.js +++ b/src/TemplateCollection.js @@ -1,6 +1,6 @@ const multimatch = require("multimatch"); const Sortable = require("./Util/Sortable"); -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); class TemplateCollection extends Sortable { constructor() { diff --git a/src/TemplateConfig.js b/src/TemplateConfig.js index 439b55653..43e8803c8 100644 --- a/src/TemplateConfig.js +++ b/src/TemplateConfig.js @@ -2,7 +2,7 @@ const fs = require("fs"); const chalk = require("kleur"); const lodashUniq = require("lodash/uniq"); const lodashMerge = require("lodash/merge"); -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); const EleventyBaseError = require("./EleventyBaseError"); const UserConfig = require("./UserConfig"); const debug = require("debug")("Eleventy:TemplateConfig"); diff --git a/src/TemplateContent.js b/src/TemplateContent.js index ec210e2f2..8a6a73377 100644 --- a/src/TemplateContent.js +++ b/src/TemplateContent.js @@ -5,11 +5,11 @@ const readFile = util.promisify(fs.readFile); const normalize = require("normalize-path"); const matter = require("gray-matter"); const lodashSet = require("lodash/set"); +const { TemplatePath } = require("@11ty/eleventy-utils"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const TemplateData = require("./TemplateData"); const TemplateRender = require("./TemplateRender"); -const TemplatePath = require("./TemplatePath"); const TemplateConfig = require("./TemplateConfig"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyErrorUtil = require("./EleventyErrorUtil"); diff --git a/src/TemplateData.js b/src/TemplateData.js index 504428aa1..7053dd812 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -4,9 +4,10 @@ const path = require("path"); const lodashset = require("lodash/set"); const lodashget = require("lodash/get"); const lodashUniq = require("lodash/uniq"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const merge = require("./Util/Merge"); const TemplateRender = require("./TemplateRender"); -const TemplatePath = require("./TemplatePath"); const TemplateGlob = require("./TemplateGlob"); const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); diff --git a/src/TemplateFileSlug.js b/src/TemplateFileSlug.js index ed95edeb8..dd3dc2a9a 100644 --- a/src/TemplateFileSlug.js +++ b/src/TemplateFileSlug.js @@ -1,5 +1,5 @@ const path = require("path"); -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); class TemplateFileSlug { constructor(inputPath, inputDir, extensionMap) { diff --git a/src/TemplateGlob.js b/src/TemplateGlob.js index ff472eedc..33c1318c8 100644 --- a/src/TemplateGlob.js +++ b/src/TemplateGlob.js @@ -1,4 +1,4 @@ -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); class TemplateGlob { static normalizePath(...paths) { diff --git a/src/TemplateLayout.js b/src/TemplateLayout.js index da15d1647..5671ca7ea 100644 --- a/src/TemplateLayout.js +++ b/src/TemplateLayout.js @@ -1,7 +1,8 @@ +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateLayoutPathResolver = require("./TemplateLayoutPathResolver"); const TemplateContent = require("./TemplateContent"); const TemplateData = require("./TemplateData"); -const TemplatePath = require("./TemplatePath"); const templateCache = require("./TemplateCache"); // const debug = require("debug")("Eleventy:TemplateLayout"); diff --git a/src/TemplateLayoutPathResolver.js b/src/TemplateLayoutPathResolver.js index 58f407409..66d7adf2a 100644 --- a/src/TemplateLayoutPathResolver.js +++ b/src/TemplateLayoutPathResolver.js @@ -1,5 +1,6 @@ const fs = require("fs"); -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + // const debug = require("debug")("Eleventy:TemplateLayoutPathResolver"); class TemplateLayoutPathResolver { diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index 9f1b11726..9d6366424 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -1,9 +1,10 @@ const fs = require("fs"); const isGlob = require("is-glob"); const copy = require("recursive-copy"); -const TemplatePath = require("./TemplatePath"); -const debug = require("debug")("Eleventy:TemplatePassthrough"); const fastglob = require("fast-glob"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + +const debug = require("debug")("Eleventy:TemplatePassthrough"); const EleventyBaseError = require("./EleventyBaseError"); class TemplatePassthroughError extends EleventyBaseError {} diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index f6cb63faf..142678d8b 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -1,7 +1,9 @@ +const { TemplatePath } = require("@11ty/eleventy-utils"); + const EleventyExtensionMap = require("./EleventyExtensionMap"); const EleventyBaseError = require("./EleventyBaseError"); const TemplatePassthrough = require("./TemplatePassthrough"); -const TemplatePath = require("./TemplatePath"); + const debug = require("debug")("Eleventy:TemplatePassthroughManager"); const debugDev = require("debug")("Dev:Eleventy:TemplatePassthroughManager"); @@ -181,6 +183,7 @@ class TemplatePassthroughManager { paths, this.incrementalFile ); + if (isPassthrough) { if (isPassthrough.outputPath) { return [ diff --git a/src/TemplatePath.js b/src/TemplatePath.js deleted file mode 100644 index 5b14890d9..000000000 --- a/src/TemplatePath.js +++ /dev/null @@ -1,356 +0,0 @@ -const path = require("path"); -const normalize = require("normalize-path"); -const fs = require("fs"); - -function TemplatePath() {} - -/** - * @returns {String} the absolute path to Eleventy’s project directory. - */ -TemplatePath.getWorkingDir = function () { - return TemplatePath.normalize(path.resolve(".")); -}; - -/** - * Returns the directory portion of a path. - * Works for directory and file paths and paths ending in a glob pattern. - * - * @param {String} path A path - * @returns {String} the directory portion of a path. - */ -TemplatePath.getDir = function (path) { - if (TemplatePath.isDirectorySync(path)) { - return path; - } - - return TemplatePath.getDirFromFilePath(path); -}; - -/** - * Returns the directory portion of a path that either points to a file - * or ends in a glob pattern. If `path` points to a directory, - * the returned value will have its last path segment stripped - * due to how [`path.parse`][1] works. - * - * [1]: https://nodejs.org/api/path.html#path_path_parse_path - * - * @param {String} path A path - * @returns {String} the directory portion of a path. - */ -TemplatePath.getDirFromFilePath = function (filePath) { - return path.parse(filePath).dir || "."; -}; - -/** - * Returns the last path segment in a path (no leading/trailing slashes). - * - * Assumes [`path.parse`][1] was called on `path` before. - * - * [1]: https://nodejs.org/api/path.html#path_path_parse_path - * - * @param {String} path A path - * @returns {String} the last path segment in a path - */ -TemplatePath.getLastPathSegment = function (path) { - if (!path.includes("/")) { - return path; - } - - // Trim a trailing slash if there is one - path = path.replace(/\/$/, ""); - - return path.substr(path.lastIndexOf("/") + 1); -}; - -/** - * @param {String} path A path - * @returns {String[]} an array of paths pointing to each path segment of the - * provided `path`. - */ -TemplatePath.getAllDirs = function (path) { - // Trim a trailing slash if there is one - path = path.replace(/\/$/, ""); - - if (!path.includes("/")) { - return [path]; - } - - return path - .split("/") - .map((segment, index, array) => array.slice(0, index + 1).join("/")) - .filter((path) => path !== ".") - .reverse(); -}; - -/** - * Normalizes a path, resolving single-dot and double-dot segments. - * - * Node.js’ [`path.normalize`][1] is called to strip a possible leading `"./"` segment. - * - * [1]: https://nodejs.org/api/path.html#path_path_normalize_path - * - * @param {String} thePath The path that should be normalized. - * @returns {String} the normalized path. - */ -TemplatePath.normalize = function (thePath) { - return normalize(path.normalize(thePath)); -}; - -/** - * Joins all given path segments together. - * - * It uses Node.js’ [`path.join`][1] method and the [normalize-path][2] package. - * - * [1]: https://nodejs.org/api/path.html#path_path_join_paths - * [2]: https://www.npmjs.com/package/normalize-path - * - * @param {String[]} paths An arbitrary amount of path segments. - * @returns {String} the normalized and joined path. - */ -TemplatePath.join = function (...paths) { - return normalize(path.join(...paths)); -}; - -/** - * Joins the given URL path segments and normalizes the resulting path. - * Maintains traling a single trailing slash if the last URL path argument - * had atleast one. - * - * @param {String[]} urlPaths - * @returns {String} a normalized URL path described by the given URL path segments. - */ -TemplatePath.normalizeUrlPath = function (...urlPaths) { - const urlPath = path.posix.join(...urlPaths); - return urlPath.replace(/\/+$/, "/"); -}; - -/** - * Joins the given path segments. Since the first path is absolute, - * the resulting path will be absolute as well. - * - * @param {String[]} paths - * @returns {String} the absolute path described by the given path segments. - */ -TemplatePath.absolutePath = function (...paths) { - let i = 0; - // check all the paths before we short circuit from the first index - for (let p of paths) { - if (path.isAbsolute(p) && i > 0) { - throw new Error( - `Only the first parameter to Template.absolutePath can be an absolute path. Received: ${p} from ${paths}` - ); - } - i++; - } - - let j = 0; - for (let p of paths) { - if (j === 0 && path.isAbsolute(p)) { - return TemplatePath.join(...paths); - } - j++; - } - - return TemplatePath.join(TemplatePath.getWorkingDir(), ...paths); -}; - -/** - * Turns an absolute path into a path relative Eleventy’s project directory. - * - * @param {String} absolutePath - * @returns {String} the relative path. - */ -TemplatePath.relativePath = function (absolutePath) { - return TemplatePath.stripLeadingSubPath( - absolutePath, - TemplatePath.getWorkingDir() - ); -}; - -/** - * Adds a leading dot-slash segment to each path in the `paths` array. - * - * @param {String[]} paths - * @returns {String[]} - */ -TemplatePath.addLeadingDotSlashArray = function (paths) { - return paths.map((path) => TemplatePath.addLeadingDotSlash(path)); -}; - -/** - * Adds a leading dot-slash segment to `path`. - * - * @param {String} path - * @returns {String} - */ -TemplatePath.addLeadingDotSlash = function (pathArg) { - if (pathArg === "." || pathArg === "..") { - return pathArg + "/"; - } - - if ( - path.isAbsolute(pathArg) || - pathArg.startsWith("./") || - pathArg.startsWith("../") - ) { - return pathArg; - } - - return "./" + pathArg; -}; - -/** - * Removes a leading dot-slash segment. - * - * @param {String} path - * @returns {String} the `path` without a leading dot-slash segment. - */ -TemplatePath.stripLeadingDotSlash = function (path) { - return typeof path === "string" ? path.replace(/^\.\//, "") : path; -}; - -/** - * Determines whether a path starts with a given sub path. - * - * @param {String} path A path - * @param {String} subPath A path - * @returns {Boolean} whether `path` starts with `subPath`. - */ -TemplatePath.startsWithSubPath = function (path, subPath) { - path = TemplatePath.normalize(path); - subPath = TemplatePath.normalize(subPath); - - return path.startsWith(subPath); -}; - -/** - * Removes the `subPath` at the start of `path` if present - * and returns the remainding path. - * - * @param {String} path A path - * @param {String} subPath A path - * @returns {String} the `path` without `subPath` at the start of it. - */ -TemplatePath.stripLeadingSubPath = function (path, subPath) { - path = TemplatePath.normalize(path); - subPath = TemplatePath.normalize(subPath); - - if (subPath !== "." && path.startsWith(subPath)) { - return path.substr(subPath.length + 1); - } - - return path; -}; - -/** - * @param {String} path A path - * @returns {Boolean} whether `path` points to an existing directory. - */ -TemplatePath.isDirectorySync = function (path) { - return fs.existsSync(path) && fs.statSync(path).isDirectory(); -}; - -/** - * @param {String} path A path - * @returns {Boolean} whether `path` points to an existing directory. - */ -TemplatePath.isDirectory = async function (path) { - return new Promise((resolve) => { - fs.stat(path, (err, stats) => { - if (stats) { - resolve(stats.isDirectory()); - } - resolve(false); - }); - }); -}; - -/** - * Appends a recursive wildcard glob pattern to `path` - * unless `path` is not a directory; then, `path` is assumed to be a file path - * and is left unchaged. - * - * @param {String} path - * @returns {String} - */ -TemplatePath.convertToRecursiveGlobSync = function (path) { - if (path === "") { - return "./**"; - } - - path = TemplatePath.addLeadingDotSlash(path); - - if (TemplatePath.isDirectorySync(path)) { - return path + (!path.endsWith("/") ? "/" : "") + "**"; - } - - return path; -}; - -/** - * Appends a recursive wildcard glob pattern to `path` - * unless `path` is not a directory; then, `path` is assumed to be a file path - * and is left unchaged. - * - * @param {String} path - * @returns {String} - */ -TemplatePath.convertToRecursiveGlob = async function (path) { - if (path === "") { - return "./**"; - } - - path = TemplatePath.addLeadingDotSlash(path); - - if (await TemplatePath.isDirectory(path)) { - return path + (!path.endsWith("/") ? "/" : "") + "**"; - } - - return path; -}; - -/** - * Returns the extension of the path without the leading dot. - * If the path has no extensions, the empty string is returned. - * - * @param {String} thePath - * @returns {String} the path’s extension if it exists; - * otherwise, the empty string. - */ -TemplatePath.getExtension = function (thePath) { - return path.extname(thePath).replace(/^\./, ""); -}; - -/** - * Removes the extension from a path. - * - * @param {String} path - * @param {String} extension - * @returns {String} - */ -TemplatePath.removeExtension = function (path, extension = undefined) { - if (extension === undefined) { - return path; - } - - const pathExtension = TemplatePath.getExtension(path); - if (pathExtension !== "" && extension.endsWith(pathExtension)) { - return path.substring(0, path.lastIndexOf(pathExtension) - 1); - } - - return path; -}; - -/** - * Accepts a relative file path that is using a standard directory separator and - * normalizes it using the local operating system separator. - * e.g. `./my/dir/` stays `./my/dir/` on *nix and becomes `.\\my\\dir\\` on Windows - * - * @param {String} filePath - * @returns {String} a file path with the correct local directory separator. - */ -TemplatePath.normalizeOperatingSystemFilePath = function (filePath, sep = "/") { - return filePath.split(sep).join(path.sep); -}; - -module.exports = TemplatePath; diff --git a/src/TemplatePermalink.js b/src/TemplatePermalink.js index c99f39287..8121e152c 100644 --- a/src/TemplatePermalink.js +++ b/src/TemplatePermalink.js @@ -1,6 +1,7 @@ const path = require("path"); -const TemplatePath = require("./TemplatePath"); const normalize = require("normalize-path"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const isPlainObject = require("./Util/IsPlainObject"); const serverlessUrlFilter = require("./Filters/ServerlessUrl"); diff --git a/src/TemplateRender.js b/src/TemplateRender.js index 2fa6139e5..9b42b7177 100644 --- a/src/TemplateRender.js +++ b/src/TemplateRender.js @@ -1,4 +1,5 @@ -const TemplatePath = require("./TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateConfig = require("./TemplateConfig"); const EleventyBaseError = require("./EleventyBaseError"); const EleventyExtensionMap = require("./EleventyExtensionMap"); diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index b5ac9dd0d..bf2cc95fe 100755 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -1,5 +1,6 @@ +const { TemplatePath } = require("@11ty/eleventy-utils"); + const Template = require("./Template"); -const TemplatePath = require("./TemplatePath"); const TemplateMap = require("./TemplateMap"); const EleventyFiles = require("./EleventyFiles"); const EleventyExtensionMap = require("./EleventyExtensionMap"); diff --git a/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js index 9660493b7..67a77db16 100644 --- a/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js +++ b/test/EleventyFilesGitIgnoreEleventyIgnoreTest.js @@ -1,6 +1,7 @@ const test = require("ava"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const EleventyFiles = require("../src/EleventyFiles"); -const TemplatePath = require("../src/TemplatePath"); const TemplateConfig = require("../src/TemplateConfig"); /* .eleventyignore and .gitignore combos */ diff --git a/test/TemplateGlobTest.js b/test/TemplateGlobTest.js index f496d9f03..6e14a8aa3 100644 --- a/test/TemplateGlobTest.js +++ b/test/TemplateGlobTest.js @@ -1,6 +1,7 @@ const test = require("ava"); const fastglob = require("fast-glob"); -const TemplatePath = require("../src/TemplatePath"); +const { TemplatePath } = require("@11ty/eleventy-utils"); + const TemplateGlob = require("../src/TemplateGlob"); test("TemplatePath assumptions", (t) => { diff --git a/test/TemplatePathTest.js b/test/TemplatePathTest.js deleted file mode 100644 index 87ededdea..000000000 --- a/test/TemplatePathTest.js +++ /dev/null @@ -1,346 +0,0 @@ -const test = require("ava"); -const fs = require("fs"); -const TemplatePath = require("../src/TemplatePath"); - -test("getDir", (t) => { - t.is(TemplatePath.getDir("README.md"), "."); - t.is(TemplatePath.getDir("test/stubs/config.js"), "test/stubs"); - t.is(TemplatePath.getDir("./test/stubs/config.js"), "./test/stubs"); - t.is(TemplatePath.getDir("test/stubs/*.md"), "test/stubs"); - t.is(TemplatePath.getDir("test/stubs/**"), "test/stubs"); - t.is(TemplatePath.getDir("test/stubs/!(multiple.md)"), "test/stubs"); -}); - -test("getDirFromFilePath", (t) => { - t.is(TemplatePath.getDirFromFilePath("test/stubs/*.md"), "test/stubs"); - t.is(TemplatePath.getDirFromFilePath("test/stubs/!(x.md)"), "test/stubs"); -}); - -test("getLastPathSegment", (t) => { - t.is(TemplatePath.getLastPathSegment("./testing/hello"), "hello"); - t.is(TemplatePath.getLastPathSegment("./testing"), "testing"); - t.is(TemplatePath.getLastPathSegment("./testing/"), "testing"); - t.is(TemplatePath.getLastPathSegment("testing/"), "testing"); - t.is(TemplatePath.getLastPathSegment("testing"), "testing"); -}); - -test("getAllDirs", (t) => { - t.deepEqual(TemplatePath.getAllDirs("."), ["."]); - t.deepEqual(TemplatePath.getAllDirs("./"), ["."]); - t.deepEqual(TemplatePath.getAllDirs("./testing"), ["./testing"]); - t.deepEqual(TemplatePath.getAllDirs("./testing/"), ["./testing"]); - t.deepEqual(TemplatePath.getAllDirs("testing/"), ["testing"]); - t.deepEqual(TemplatePath.getAllDirs("testing"), ["testing"]); - - t.deepEqual(TemplatePath.getAllDirs("./testing/hello"), [ - "./testing/hello", - "./testing", - ]); - - t.deepEqual(TemplatePath.getAllDirs("./src/collections/posts"), [ - "./src/collections/posts", - "./src/collections", - "./src", - ]); - - t.deepEqual( - TemplatePath.getAllDirs("./src/site/content/en/paths/performanceAudits"), - [ - "./src/site/content/en/paths/performanceAudits", - "./src/site/content/en/paths", - "./src/site/content/en", - "./src/site/content", - "./src/site", - "./src", - ] - ); - - t.deepEqual(TemplatePath.getAllDirs("./src/_site/src"), [ - "./src/_site/src", - "./src/_site", - "./src", - ]); - - t.deepEqual(TemplatePath.getAllDirs("./src/_site/src/src/src"), [ - "./src/_site/src/src/src", - "./src/_site/src/src", - "./src/_site/src", - "./src/_site", - "./src", - ]); -}); - -test("normalize", async (t) => { - t.is(TemplatePath.normalize(""), "."); - t.is(TemplatePath.normalize("."), "."); - t.is(TemplatePath.normalize("/"), "/"); - t.is(TemplatePath.normalize("/testing"), "/testing"); - t.is(TemplatePath.normalize("/testing/"), "/testing"); - - // v0.4.0 changed from `./` to `.` - // normalize removes trailing slashes so it should probably be `.` - t.is(TemplatePath.normalize("./"), "."); - t.is(TemplatePath.normalize("./testing"), "testing"); - - t.is(TemplatePath.normalize("../"), ".."); - t.is(TemplatePath.normalize("../testing"), "../testing"); - - t.is(TemplatePath.normalize("./testing/hello"), "testing/hello"); - t.is(TemplatePath.normalize("./testing/hello/"), "testing/hello"); - - t.is(TemplatePath.normalize(".htaccess"), ".htaccess"); -}); - -test("join", async (t) => { - t.is(TemplatePath.join("src", "_includes"), "src/_includes"); - t.is(TemplatePath.join("src", "_includes/"), "src/_includes"); - t.is(TemplatePath.join("src", "/_includes"), "src/_includes"); - t.is(TemplatePath.join("src", "./_includes"), "src/_includes"); - t.is(TemplatePath.join("src", "//_includes"), "src/_includes"); - - t.is(TemplatePath.join("./src", "_includes"), "src/_includes"); - t.is(TemplatePath.join("./src", "_includes/"), "src/_includes"); - t.is(TemplatePath.join("./src", "/_includes"), "src/_includes"); - t.is(TemplatePath.join("./src", "./_includes"), "src/_includes"); - t.is(TemplatePath.join("./src", "//_includes"), "src/_includes"); - - t.is(TemplatePath.join("src", "test", "..", "_includes"), "src/_includes"); -}); - -test("normalizeUrlPath", (t) => { - t.is(TemplatePath.normalizeUrlPath(""), "."); - t.is(TemplatePath.normalizeUrlPath("."), "."); - t.is(TemplatePath.normalizeUrlPath("./"), "./"); - t.is(TemplatePath.normalizeUrlPath(".."), ".."); - t.is(TemplatePath.normalizeUrlPath("../"), "../"); - - t.is(TemplatePath.normalizeUrlPath("/"), "/"); - t.is(TemplatePath.normalizeUrlPath("//"), "/"); - t.is(TemplatePath.normalizeUrlPath("/../"), "/"); - t.is(TemplatePath.normalizeUrlPath("/test"), "/test"); - t.is(TemplatePath.normalizeUrlPath("/test/"), "/test/"); - t.is(TemplatePath.normalizeUrlPath("/test//"), "/test/"); - t.is(TemplatePath.normalizeUrlPath("/test/../"), "/"); - t.is(TemplatePath.normalizeUrlPath("/test/../../"), "/"); -}); - -test("absolutePath", (t) => { - t.is( - TemplatePath.absolutePath(".eleventy.js").split("/").pop(), - ".eleventy.js" - ); - t.is(TemplatePath.absolutePath("/tmp/.eleventy.js"), "/tmp/.eleventy.js"); - t.is( - TemplatePath.absolutePath("/var/task/", ".eleventy.js"), - "/var/task/.eleventy.js" - ); - - t.throws(() => { - TemplatePath.absolutePath("/var/task/", "/var/task/.eleventy.js"); - }); - - t.throws(() => { - TemplatePath.absolutePath("file1.js", "test/file2.js", "/tmp/.eleventy.js"); - }); -}); - -test("absolutePath and relativePath", (t) => { - t.is( - TemplatePath.relativePath(TemplatePath.absolutePath(".eleventy.js")), - ".eleventy.js" - ); -}); - -test("addLeadingDotSlash", (t) => { - t.is(TemplatePath.addLeadingDotSlash("."), "./"); - t.is(TemplatePath.addLeadingDotSlash(".."), "../"); - t.is(TemplatePath.addLeadingDotSlash("./test/stubs"), "./test/stubs"); - t.is(TemplatePath.addLeadingDotSlash("./dist"), "./dist"); - t.is(TemplatePath.addLeadingDotSlash("../dist"), "../dist"); - t.is(TemplatePath.addLeadingDotSlash("/dist"), "/dist"); - t.is(TemplatePath.addLeadingDotSlash("dist"), "./dist"); - t.is(TemplatePath.addLeadingDotSlash(".nyc_output"), "./.nyc_output"); - - // TODO How to test this on Windows? path.isAbsolute is OS dependent 😱 - // let windowsAbsolutePath = `C:\\Users\\$USER\\$PROJECT\\netlify\\functions\\serverless\\index`; - // t.is(TemplatePath.addLeadingDotSlash(windowsAbsolutePath), windowsAbsolutePath); -}); - -test("addLeadingDotSlashArray", (t) => { - t.deepEqual(TemplatePath.addLeadingDotSlashArray(["."]), ["./"]); - t.deepEqual(TemplatePath.addLeadingDotSlashArray([".."]), ["../"]); - t.deepEqual(TemplatePath.addLeadingDotSlashArray(["./test/stubs"]), [ - "./test/stubs", - ]); - t.deepEqual(TemplatePath.addLeadingDotSlashArray(["./dist"]), ["./dist"]); - t.deepEqual(TemplatePath.addLeadingDotSlashArray(["../dist"]), ["../dist"]); - t.deepEqual(TemplatePath.addLeadingDotSlashArray(["/dist"]), ["/dist"]); - t.deepEqual(TemplatePath.addLeadingDotSlashArray(["dist"]), ["./dist"]); - t.deepEqual(TemplatePath.addLeadingDotSlashArray([".nyc_output"]), [ - "./.nyc_output", - ]); -}); - -test("stripLeadingDotSlash", (t) => { - t.is(TemplatePath.stripLeadingDotSlash("./test/stubs"), "test/stubs"); - t.is(TemplatePath.stripLeadingDotSlash("./dist"), "dist"); - t.is(TemplatePath.stripLeadingDotSlash("../dist"), "../dist"); - t.is(TemplatePath.stripLeadingDotSlash("dist"), "dist"); - - t.is(TemplatePath.stripLeadingDotSlash(".htaccess"), ".htaccess"); -}); - -test("startsWithSubPath", (t) => { - t.false(TemplatePath.startsWithSubPath("./testing/hello", "./lskdjklfjz")); - t.false(TemplatePath.startsWithSubPath("./testing/hello", "lskdjklfjz")); - t.false(TemplatePath.startsWithSubPath("testing/hello", "./lskdjklfjz")); - t.false(TemplatePath.startsWithSubPath("testing/hello", "lskdjklfjz")); - - t.true(TemplatePath.startsWithSubPath("./testing/hello", "./testing")); - t.true(TemplatePath.startsWithSubPath("./testing/hello", "testing")); - t.true(TemplatePath.startsWithSubPath("testing/hello", "./testing")); - t.true(TemplatePath.startsWithSubPath("testing/hello", "testing")); - - t.true( - TemplatePath.startsWithSubPath("testing/hello/subdir/test", "testing") - ); - t.false(TemplatePath.startsWithSubPath("testing/hello/subdir/test", "hello")); - t.false( - TemplatePath.startsWithSubPath("testing/hello/subdir/test", "hello/subdir") - ); - t.true( - TemplatePath.startsWithSubPath( - "testing/hello/subdir/test", - "testing/hello/subdir" - ) - ); - t.true( - TemplatePath.startsWithSubPath( - "testing/hello/subdir/test", - "testing/hello/subdir/test" - ) - ); -}); - -test("stripLeadingSubPath", (t) => { - t.is( - TemplatePath.stripLeadingSubPath("./testing/hello", "./lskdjklfjz"), - "testing/hello" - ); - t.is(TemplatePath.stripLeadingSubPath("./test/stubs", "stubs"), "test/stubs"); - t.is(TemplatePath.stripLeadingSubPath("./test/stubs", "./test"), "stubs"); - t.is(TemplatePath.stripLeadingSubPath("./testing/hello", "testing"), "hello"); - t.is(TemplatePath.stripLeadingSubPath("testing/hello", "testing"), "hello"); - t.is(TemplatePath.stripLeadingSubPath("testing/hello", "./testing"), "hello"); - t.is( - TemplatePath.stripLeadingSubPath("testing/hello/subdir/test", "testing"), - "hello/subdir/test" - ); - - t.is(TemplatePath.stripLeadingSubPath(".htaccess", "./"), ".htaccess"); - t.is(TemplatePath.stripLeadingSubPath(".htaccess", "."), ".htaccess"); -}); - -test("convertToRecursiveGlobSync", (t) => { - t.is(TemplatePath.convertToRecursiveGlobSync(""), "./**"); - t.is(TemplatePath.convertToRecursiveGlobSync("."), "./**"); - t.is(TemplatePath.convertToRecursiveGlobSync("./"), "./**"); - t.is( - TemplatePath.convertToRecursiveGlobSync("test/stubs"), - "./test/stubs/**" - ); - t.is( - TemplatePath.convertToRecursiveGlobSync("test/stubs/"), - "./test/stubs/**" - ); - t.is( - TemplatePath.convertToRecursiveGlobSync("./test/stubs/"), - "./test/stubs/**" - ); - t.is( - TemplatePath.convertToRecursiveGlobSync("./test/stubs/config.js"), - "./test/stubs/config.js" - ); -}); - -test("convertToRecursiveGlob", async (t) => { - t.is(await TemplatePath.convertToRecursiveGlob(""), "./**"); - t.is(await TemplatePath.convertToRecursiveGlob("."), "./**"); - t.is(await TemplatePath.convertToRecursiveGlob("./"), "./**"); - t.is( - await TemplatePath.convertToRecursiveGlob("test/stubs"), - "./test/stubs/**" - ); - t.is( - await TemplatePath.convertToRecursiveGlob("test/stubs/"), - "./test/stubs/**" - ); - t.is( - await TemplatePath.convertToRecursiveGlob("./test/stubs/"), - "./test/stubs/**" - ); - t.is( - await TemplatePath.convertToRecursiveGlob("./test/stubs/config.js"), - "./test/stubs/config.js" - ); -}); - -test("getExtension", (t) => { - t.is(TemplatePath.getExtension(""), ""); - t.is(TemplatePath.getExtension("test/stubs"), ""); - t.is(TemplatePath.getExtension("test/stubs.njk"), "njk"); - t.is(TemplatePath.getExtension("test/stubs.hbs"), "hbs"); -}); - -test("removeExtension", (t) => { - t.is(TemplatePath.removeExtension(""), ""); - t.is(TemplatePath.removeExtension("", "hbs"), ""); - - t.is(TemplatePath.removeExtension("test/stubs", "hbs"), "test/stubs"); - t.is(TemplatePath.removeExtension("test/stubs.njk"), "test/stubs.njk"); - t.is(TemplatePath.removeExtension("test/stubs.njk", "hbs"), "test/stubs.njk"); - t.is(TemplatePath.removeExtension("test/stubs.hbs", "hbs"), "test/stubs"); - - t.is(TemplatePath.removeExtension("./test/stubs.njk"), "./test/stubs.njk"); - t.is( - TemplatePath.removeExtension("./test/stubs.njk", "hbs"), - "./test/stubs.njk" - ); - t.is(TemplatePath.removeExtension("./test/stubs.hbs", "hbs"), "./test/stubs"); - - t.is(TemplatePath.removeExtension("test/stubs", ".hbs"), "test/stubs"); - t.is( - TemplatePath.removeExtension("test/stubs.njk", ".hbs"), - "test/stubs.njk" - ); - t.is(TemplatePath.removeExtension("test/stubs.hbs", ".hbs"), "test/stubs"); - t.is( - TemplatePath.removeExtension("./test/stubs.njk", ".hbs"), - "./test/stubs.njk" - ); - t.is( - TemplatePath.removeExtension("./test/stubs.hbs", ".hbs"), - "./test/stubs" - ); -}); - -test("isDirectorySync", (t) => { - t.is(TemplatePath.isDirectorySync("asdlkfjklsadjflkja"), false); - t.is(TemplatePath.isDirectorySync("test"), true); - t.is(TemplatePath.isDirectorySync("test/stubs"), true); - t.is(TemplatePath.isDirectorySync("test/stubs/.eleventyignore"), false); -}); - -test("isDirectory", async (t) => { - t.is(await TemplatePath.isDirectory("asdlkfjklsadjflkja"), false); - t.is(await TemplatePath.isDirectory("test"), true); - t.is(await TemplatePath.isDirectory("test/stubs"), true); - t.is(await TemplatePath.isDirectory("test/stubs/.eleventyignore"), false); -}); - -test("exists", async (t) => { - t.is(fs.existsSync("asdlkfjklsadjflkja"), false); - t.is(fs.existsSync("test"), true); - t.is(fs.existsSync("test/stubs"), true); - t.is(fs.existsSync("test/stubs/.eleventyignore"), true); -}); From 65a9b91d23e27b4c1089c96bc150de98e6acd64b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Mar 2022 09:21:08 -0500 Subject: [PATCH 725/746] Re-adds TemplatePath file for backwards compat --- src/TemplatePath.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/TemplatePath.js diff --git a/src/TemplatePath.js b/src/TemplatePath.js new file mode 100644 index 000000000..8c89004ff --- /dev/null +++ b/src/TemplatePath.js @@ -0,0 +1,4 @@ +const { TemplatePath } = require("@11ty/eleventy-utils"); + +// This is solely for backwards compatibility. +module.exports = TemplatePath; From f5aa491143f1e88456e92d397a8b011ee1814368 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 4 Mar 2022 22:35:21 -0600 Subject: [PATCH 726/746] Fix bug with incremental and passthrough copy with glob patterns --- src/TemplatePassthroughManager.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 142678d8b..0204ba6f0 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -1,3 +1,5 @@ +const multimatch = require("multimatch"); +const isGlob = require("is-glob"); const { TemplatePath } = require("@11ty/eleventy-utils"); const EleventyExtensionMap = require("./EleventyExtensionMap"); @@ -172,6 +174,13 @@ class TemplatePassthroughManager { if (TemplatePath.startsWithSubPath(changedFile, path.inputPath)) { return path; } + if ( + changedFile && + isGlob(path.inputPath) && + multimatch([changedFile], [path.inputPath]).length + ) { + return path; + } } return false; From aba9676f00c436e0372b778c54f32e125561f817 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Mar 2022 09:22:54 -0500 Subject: [PATCH 727/746] Forgot a dep in the eleventy-utils cherry-pick --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index dc91c4a69..1c9b0b410 100755 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", + "@11ty/eleventy-utils": "^2.0.0", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.7", From c9f8d16a9f6346cf3ee9719d90da3f28e723804b Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Mar 2022 08:59:19 -0500 Subject: [PATCH 728/746] Fixes #2278 --- src/TemplatePassthrough.js | 23 +++++++++++++++++++++-- src/TemplatePassthroughManager.js | 12 +++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/TemplatePassthrough.js b/src/TemplatePassthrough.js index 9d6366424..ace372359 100644 --- a/src/TemplatePassthrough.js +++ b/src/TemplatePassthrough.js @@ -1,4 +1,5 @@ const fs = require("fs"); +const path = require("path"); const isGlob = require("is-glob"); const copy = require("recursive-copy"); const fastglob = require("fast-glob"); @@ -30,6 +31,7 @@ class TemplatePassthrough { this.outputDir = outputDir; this.isDryRun = false; + this.isIncremental = false; } getPath() { @@ -55,7 +57,21 @@ class TemplatePassthrough { return this.getOutputPathForGlobFile(inputFileFromGlob); } - return TemplatePath.normalize(TemplatePath.join(outputDir, outputPath)); + // Bug when copying incremental file overwriting output directory (and making it a file) + // e.g. public/test.css -> _site + // https://github.com/11ty/eleventy/issues/2278 + let fullOutputPath = TemplatePath.normalize( + TemplatePath.join(outputDir, outputPath) + ); + + if (this.isIncremental && TemplatePath.isDirectorySync(fullOutputPath)) { + let filename = path.parse(inputPath).base; + return TemplatePath.normalize( + TemplatePath.join(outputDir, outputPath, filename) + ); + } + + return fullOutputPath; } getOutputPathForGlobFile(inputFileFromGlob) { @@ -69,6 +85,10 @@ class TemplatePassthrough { this.isDryRun = !!isDryRun; } + setIsIncremental(isIncremental) { + this.isIncremental = isIncremental; + } + async getFiles(glob) { debug("Searching for: %o", glob); let b = this.benchmarks.aggregate.get("Searching the file system"); @@ -143,7 +163,6 @@ class TemplatePassthrough { debug("Copying %o", this.inputPath); if (!isGlob(this.inputPath) && fs.existsSync(this.inputPath)) { - // IMPORTANT: this returns a promise, does not await for promise to finish promises.push( this.copy(this.inputPath, this.getOutputPath(), copyOptions) ); diff --git a/src/TemplatePassthroughManager.js b/src/TemplatePassthroughManager.js index 0204ba6f0..e6ce45cd2 100644 --- a/src/TemplatePassthroughManager.js +++ b/src/TemplatePassthroughManager.js @@ -101,13 +101,15 @@ class TemplatePassthroughManager { return this.count; } - getTemplatePassthroughForPath(path) { - return new TemplatePassthrough( + getTemplatePassthroughForPath(path, isIncremental = false) { + let inst = new TemplatePassthrough( path, this.outputDir, this.inputDir, this.config ); + inst.setIsIncremental(isIncremental); + return inst; } async copyPassthrough(pass) { @@ -238,7 +240,11 @@ class TemplatePassthroughManager { let normalizedPaths = this.getAllNormalizedPaths(paths); let passthroughs = []; for (let path of normalizedPaths) { - passthroughs.push(this.getTemplatePassthroughForPath(path)); + // if incrementalFile is set but it isn’t a passthrough copy, normalizedPaths will be an empty array + let isIncremental = !!this.incrementalFile; + passthroughs.push( + this.getTemplatePassthroughForPath(path, isIncremental) + ); } return Promise.all( From 2b8fd265075a847bde7bf54c2902194a5fd24f6e Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Mar 2022 09:09:53 -0500 Subject: [PATCH 729/746] Test for #2278 --- test/TemplatePassthroughTest.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/TemplatePassthroughTest.js b/test/TemplatePassthroughTest.js index bc88839f2..c42c762c3 100644 --- a/test/TemplatePassthroughTest.js +++ b/test/TemplatePassthroughTest.js @@ -298,3 +298,13 @@ test("Output paths match with different templatePassthrough methods", async (t) // t.truthy(pass); // t.is(pass.getOutputPath(), "_site/rename.js"); // }); + +test("Bug with incremental copying to a directory output, issue #2278", async (t) => { + let pass1 = getTemplatePassthrough( + { inputPath: "./public/test.css", outputPath: "/" }, + "test/stubs", + "." + ); + pass1.setIsIncremental(true); + t.is(pass1.getOutputPath(), "test/stubs/test.css"); +}); From 5deb71b4a47b4979d7e980a63905c38d461d99f0 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Mar 2022 09:25:49 -0500 Subject: [PATCH 730/746] Wrong version on utils --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c9b0b410..197a2eb55 100755 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", - "@11ty/eleventy-utils": "^2.0.0", + "@11ty/eleventy-utils": "^1.0.0", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.7", From 5d12aad069d37adb8b68b90cf8f4220a044d7164 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Mar 2022 09:26:15 -0500 Subject: [PATCH 731/746] Update dependencies for 1.x --- package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 197a2eb55..9cc5c7785 100755 --- a/package.json +++ b/package.json @@ -79,16 +79,16 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", "@vue/server-renderer": "^3.2.31", - "ava": "^4.0.1", + "ava": "^4.1.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", - "lint-staged": "^11.2.6", + "lint-staged": "^12.3.6", "markdown-it-emoji": "^2.0.0", "marked": "^4.0.12", "nyc": "^15.1.0", - "prettier": "^2.5.1", + "prettier": "^2.6.0", "rimraf": "^3.0.2", - "sass": "^1.49.8", + "sass": "^1.49.9", "toml": "^3.0.0", "vue": "^3.2.31" }, @@ -97,10 +97,10 @@ "@11ty/eleventy-utils": "^1.0.0", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", - "browser-sync": "^2.27.7", + "browser-sync": "^2.27.9", "chokidar": "^3.5.3", "cross-spawn": "^7.0.3", - "debug": "^4.3.3", + "debug": "^4.3.4", "dependency-graph": "^0.11.0", "ejs": "^3.1.6", "fast-glob": "^3.2.11", @@ -110,9 +110,9 @@ "handlebars": "^4.7.7", "is-glob": "^4.0.3", "kleur": "^4.1.4 ", - "liquidjs": "^9.34.0", + "liquidjs": "^9.36.0", "lodash": "^4.17.21", - "luxon": "^2.3.0", + "luxon": "^2.3.1", "markdown-it": "^12.3.2", "minimist": "^1.2.5", "moo": "^0.5.1", From e42467ba839a82f666ab910e45252e34b6033b1d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 11 Apr 2022 14:09:24 -0500 Subject: [PATCH 732/746] Update dependencies --- package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 9cc5c7785..f2d279759 100755 --- a/package.json +++ b/package.json @@ -79,22 +79,22 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", "@vue/server-renderer": "^3.2.31", - "ava": "^4.1.0", + "ava": "^4.2.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", - "lint-staged": "^12.3.6", + "lint-staged": "^12.3.7", "markdown-it-emoji": "^2.0.0", - "marked": "^4.0.12", + "marked": "^4.0.14", "nyc": "^15.1.0", - "prettier": "^2.6.0", + "prettier": "^2.6.2", "rimraf": "^3.0.2", - "sass": "^1.49.9", + "sass": "^1.50.0", "toml": "^3.0.0", "vue": "^3.2.31" }, "dependencies": { "@11ty/dependency-tree": "^2.0.0", - "@11ty/eleventy-utils": "^1.0.0", + "@11ty/eleventy-utils": "^1.0.1", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", "browser-sync": "^2.27.9", @@ -104,7 +104,7 @@ "dependency-graph": "^0.11.0", "ejs": "^3.1.6", "fast-glob": "^3.2.11", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.10", "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", @@ -114,7 +114,7 @@ "lodash": "^4.17.21", "luxon": "^2.3.1", "markdown-it": "^12.3.2", - "minimist": "^1.2.5", + "minimist": "^1.2.6", "moo": "^0.5.1", "multimatch": "^5.0.0", "mustache": "^4.2.0", @@ -125,7 +125,7 @@ "pretty": "^2.0.0", "pug": "^3.0.2", "recursive-copy": "^2.0.14", - "semver": "^7.3.5", + "semver": "^7.3.6", "slugify": "^1.6.5" } } From 7ce1494a58673f605d68e51311966f9249b71357 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 15 Apr 2022 15:16:35 -0500 Subject: [PATCH 733/746] Cherry pick to 1.x: Adds `eleventy.version` and `eleventy.generator` to Eleventy supplied global data to fix #2293. --- src/TemplateData.js | 12 +++++++++--- test/TemplateDataTest.js | 25 +++++++++++++++++++++---- test/TemplateTest.js | 2 ++ test/stubs-empty/.gitkeep | 0 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 test/stubs-empty/.gitkeep diff --git a/src/TemplateData.js b/src/TemplateData.js index 7053dd812..b37615235 100755 --- a/src/TemplateData.js +++ b/src/TemplateData.js @@ -1,9 +1,11 @@ +const pkg = require("../package.json"); const fs = require("fs"); const fastglob = require("fast-glob"); const path = require("path"); const lodashset = require("lodash/set"); const lodashget = require("lodash/get"); const lodashUniq = require("lodash/uniq"); +const semver = require("semver"); const { TemplatePath } = require("@11ty/eleventy-utils"); const merge = require("./Util/Merge"); @@ -310,10 +312,14 @@ class TemplateData { } } + 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}`; + if (this.environmentVariables) { - if (!("eleventy" in globalData)) { - globalData.eleventy = {}; - } if (!("env" in globalData.eleventy)) { globalData.eleventy.env = {}; } diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js index dffedb454..3ba4ab8f9 100644 --- a/test/TemplateDataTest.js +++ b/test/TemplateDataTest.js @@ -456,10 +456,8 @@ test("Parent directory for data (Issue #337)", async (t) => { let data = await dataObj.getData(); - t.deepEqual(data, { - xyz: { - hi: "bye", - }, + t.deepEqual(data.xyz, { + hi: "bye", }); }); @@ -519,3 +517,22 @@ test("addGlobalData complex key", async (t) => { t.is(data.deep.nested.one, "first"); t.is(data.deep.nested.two, "second"); }); + +test("eleventy.version and eleventy.generator returned from data", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.addGlobalData("deep.nested.one", () => "first"); + eleventyConfig.userConfig.addGlobalData("deep.nested.two", () => "second"); + + let dataObj = new TemplateData("./test/stubs-empty/", eleventyConfig); + let data = await dataObj.getData(); + + let version = require("semver") + .coerce(require("../package.json").version) + .toString(); + + t.is(data.eleventy.version, version); + t.is(data.eleventy.generator, `Eleventy v${version}`); + + t.is(data.deep.nested.one, "first"); + t.is(data.deep.nested.two, "second"); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index ef0ae06c9..11aba5cfa 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1362,6 +1362,7 @@ test("Data Cascade (Deep merge)", async (t) => { let data = await tmpl.getData(); t.deepEqual(Object.keys(data).sort(), [ "datafile", + "eleventy", "frontmatter", "page", "parent", @@ -1397,6 +1398,7 @@ test("Data Cascade (Shallow merge)", async (t) => { let data = await tmpl.getData(); t.deepEqual(Object.keys(data).sort(), [ "datafile", + "eleventy", "frontmatter", "page", "parent", diff --git a/test/stubs-empty/.gitkeep b/test/stubs-empty/.gitkeep new file mode 100644 index 000000000..e69de29bb From bf130f7615022907d407a7996a30905d8de564d9 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 15 Apr 2022 15:17:15 -0500 Subject: [PATCH 734/746] Downgrade ava for Node dump errors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f2d279759..c077fa760 100755 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", "@vue/server-renderer": "^3.2.31", - "ava": "^4.2.0", + "ava": "^3.15.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", "lint-staged": "^12.3.7", From e25a7d20b73859dd14d34a13d4421a3f3f2f3da1 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 14 Apr 2022 16:22:30 -0500 Subject: [PATCH 735/746] Fixes #2267 (cherry picked from commit 5def7d8c101f66b2c3bb7c0ff77b4cb9cde9bcbd) --- src/Engines/Custom.js | 15 ++++++++------ test/TemplateRenderCustomTest.js | 16 +++++++++++++++ test/TemplateTest-CustomExtensions.js | 28 +++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/Engines/Custom.js b/src/Engines/Custom.js index 4ba8ba3de..095106430 100644 --- a/src/Engines/Custom.js +++ b/src/Engines/Custom.js @@ -165,12 +165,15 @@ class CustomEngine extends TemplateEngine { defaultRenderer, // bind defaultRenderer to compile function })(str, inputPath); - // Bind defaultRenderer to render function - if ("then" in fn && typeof fn.then === "function") { - // Promise, wait to bind - return fn.then((fn) => fn.bind({ defaultRenderer })); - } else if ("bind" in fn && typeof fn.bind === "function") { - return fn.bind({ defaultRenderer }); + // Support `undefined` to skip compile/render + if (fn) { + // Bind defaultRenderer to render function + if ("then" in fn && typeof fn.then === "function") { + // Promise, wait to bind + return fn.then((fn) => fn.bind({ defaultRenderer })); + } else if ("bind" in fn && typeof fn.bind === "function") { + return fn.bind({ defaultRenderer }); + } } return fn; diff --git a/test/TemplateRenderCustomTest.js b/test/TemplateRenderCustomTest.js index 2e35eb394..b17c76f38 100644 --- a/test/TemplateRenderCustomTest.js +++ b/test/TemplateRenderCustomTest.js @@ -215,3 +215,19 @@ test("JavaScript functions should not be mutable but not *that* mutable", async let data = await tmpl.getData(); t.is(await tmpl.render(data), "

Paragraph

"); }); + +test("Return undefined in compile to ignore #2267", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compile: function (str, inputPath) { + return; + }, + }); + + let tr = getNewTemplateRender("txt", null, eleventyConfig); + + let fn = await tr.getCompiledTemplate("

Paragraph

"); + t.is(fn, undefined); +}); diff --git a/test/TemplateTest-CustomExtensions.js b/test/TemplateTest-CustomExtensions.js index 569f44197..a056a2b13 100644 --- a/test/TemplateTest-CustomExtensions.js +++ b/test/TemplateTest-CustomExtensions.js @@ -438,3 +438,31 @@ test("Access to default renderer when you override an existing extension (async let data = await tmpl.getData(); t.is(await tmpl.render(data), "hi"); }); + +test("Return undefined in compile to ignore #2267", async (t) => { + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.extensionMap.add({ + extension: "txt", + key: "txt", + compileOptions: { + cache: false, + }, + getData: false, + compile: function (str, inputPath) { + return; + }, + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + let tmpl = getNewTemplate( + "./test/stubs/custom-extension.txt", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + let data = await tmpl.getData(); + t.is(await tmpl.render(data), undefined); +}); From 6b3db05866d057cc0c2f073fe5991f92641f69fa Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 14 Apr 2022 12:46:37 -0500 Subject: [PATCH 736/746] Switch to static functions for Eleventy version and help args. Fixes #1313 (cherry picked from commit 2b18aab4be68fa89959495327cb19da16401f66a) --- cmd.js | 24 ++++++++++++------------ src/Eleventy.js | 22 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/cmd.js b/cmd.js index 37e6d3414..4ce85fa09 100755 --- a/cmd.js +++ b/cmd.js @@ -62,21 +62,21 @@ try { ); }); - let elev = new Eleventy(argv.input, argv.output, { - // --quiet and --quiet=true both resolve to true - quietMode: argv.quiet, - configPath: argv.config, - source: "cli", - }); - - // reuse ErrorHandler instance in Eleventy - errorHandler = elev.errorHandler; - if (argv.version) { - console.log(elev.getVersion()); + console.log(Eleventy.getVersion()); } else if (argv.help) { - console.log(elev.getHelp()); + console.log(Eleventy.getHelp()); } else { + let elev = new Eleventy(argv.input, argv.output, { + // --quiet and --quiet=true both resolve to true + quietMode: argv.quiet, + configPath: argv.config, + source: "cli", + }); + + // reuse ErrorHandler instance in Eleventy + errorHandler = elev.errorHandler; + if (argv.to === "json" || argv.to === "ndjson") { // override logging output elev.setIsVerbose(false); diff --git a/src/Eleventy.js b/src/Eleventy.js index a4c50cd0a..08389154b 100644 --- a/src/Eleventy.js +++ b/src/Eleventy.js @@ -527,20 +527,27 @@ Verbose Output: ${this.verboseMode}`); /** * Reads the version of Eleventy. * - * @method + * @static * @returns {String} - The version of Eleventy. */ - getVersion() { + static getVersion() { return pkg.version; } + /** + * @deprecated since 1.0.1, use static Eleventy.getVersion() + */ + getVersion() { + return Eleventy.getVersion(); + } + /** * Shows a help message including usage. * - * @method + * @static * @returns {String} - The help mesage. */ - getHelp() { + static getHelp() { return `Usage: eleventy eleventy --input=. --output=./_site eleventy --serve @@ -586,6 +593,13 @@ Arguments: --help`; } + /** + * @deprecated since 1.0.1, use static Eleventy.getHelp() + */ + getHelp() { + return Eleventy.getHelp(); + } + /** * Resets the config of Eleventy. * From e2b121f50dac6663b2c0b46292021599b42c8dd5 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Wed, 13 Apr 2022 17:48:25 -0500 Subject: [PATCH 737/746] =?UTF-8?q?Add=20a=20named=20function=20for=20serv?= =?UTF-8?q?erless=20middleware=20to=20make=20it=20more=20obvious=20what?= =?UTF-8?q?=E2=80=99s=20happening=20in=20the=20dev=20server.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 4fb89d31e31371c14eab700d355e7d882fb51251) --- src/Plugins/ServerlessBundlerPlugin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Plugins/ServerlessBundlerPlugin.js b/src/Plugins/ServerlessBundlerPlugin.js index a76120222..40d557a75 100644 --- a/src/Plugins/ServerlessBundlerPlugin.js +++ b/src/Plugins/ServerlessBundlerPlugin.js @@ -230,7 +230,7 @@ class BundlerHelper { ); deleteRequireCache(TemplatePath.absolutePath(serverlessFilepath)); - return async (req, res, next) => { + return async function EleventyServerlessMiddleware(req, res, next) { let serverlessFunction = require(serverlessFilepath); let url = new URL(req.url, "http://localhost/"); // any domain will do here, we just want the searchParams let queryParams = Object.fromEntries(url.searchParams); @@ -257,7 +257,7 @@ class BundlerHelper { this.eleventyConfig.logger.forceLog( `Serverless (${this.name}): ${req.url} (${Date.now() - start}ms)` ); - }; + }.bind(this); } async ensureDir() { From 8fd660e9381d91d7b7ac4057a194aeca8cbfb555 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Thu, 17 Mar 2022 08:59:19 -0500 Subject: [PATCH 738/746] Update dependencies for 1.0.1 --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c077fa760..d695d3eb5 100755 --- a/package.json +++ b/package.json @@ -78,11 +78,11 @@ "devDependencies": { "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", - "@vue/server-renderer": "^3.2.31", + "@vue/server-renderer": "^3.2.33", "ava": "^3.15.0", "husky": "^7.0.4", "js-yaml": "^4.1.0", - "lint-staged": "^12.3.7", + "lint-staged": "^12.3.8", "markdown-it-emoji": "^2.0.0", "marked": "^4.0.14", "nyc": "^15.1.0", @@ -90,10 +90,10 @@ "rimraf": "^3.0.2", "sass": "^1.50.0", "toml": "^3.0.0", - "vue": "^3.2.31" + "vue": "^3.2.33" }, "dependencies": { - "@11ty/dependency-tree": "^2.0.0", + "@11ty/dependency-tree": "^2.0.1", "@11ty/eleventy-utils": "^1.0.1", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", @@ -125,7 +125,7 @@ "pretty": "^2.0.0", "pug": "^3.0.2", "recursive-copy": "^2.0.14", - "semver": "^7.3.6", + "semver": "^7.3.7", "slugify": "^1.6.5" } } From b184ac9c8a18630677f7db16e904d3b4b4356c27 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Fri, 15 Apr 2022 15:50:56 -0500 Subject: [PATCH 739/746] v1.0.1-canary.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d695d3eb5..d9170fbf8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.1-canary.3", + "version": "1.0.1-canary.4", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From 6ea19449c45dc024956d703161cb80a9bdfaa638 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 18 Apr 2022 13:46:18 -0500 Subject: [PATCH 740/746] v1.0.1 --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d9170fbf8..26fb67ca5 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.1-canary.4", + "version": "1.0.1", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" @@ -110,9 +110,9 @@ "handlebars": "^4.7.7", "is-glob": "^4.0.3", "kleur": "^4.1.4 ", - "liquidjs": "^9.36.0", + "liquidjs": "^9.36.1", "lodash": "^4.17.21", - "luxon": "^2.3.1", + "luxon": "^2.3.2", "markdown-it": "^12.3.2", "minimist": "^1.2.6", "moo": "^0.5.1", From baca2ad9f19311602ad4d3e08fbb600c57db41b8 Mon Sep 17 00:00:00 2001 From: Ed Pelc Date: Fri, 6 May 2022 10:25:19 -0400 Subject: [PATCH 741/746] fix liquid template argument parsing - fixes undefined arguments in shortcodes and potentially other uses - fixes #2348 and #2154 --- src/Engines/Liquid.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Engines/Liquid.js b/src/Engines/Liquid.js index cc26c2560..87ab9d627 100644 --- a/src/Engines/Liquid.js +++ b/src/Engines/Liquid.js @@ -116,13 +116,16 @@ class Liquid extends TemplateEngine { line: 1, col: 1 }*/ if (arg.type.indexOf("ignore:") === -1) { - argArray.push(await engine.evalValue(arg.value, scope)); + // Push the promise into an array instead of awaiting it here. + // This forces the promises to run in order with the correct scope value for each arg. + // Otherwise they run out of order and can lead to undefined values for arguments in layout template shortcodes. + argArray.push(engine.evalValue(arg.value, scope)); } arg = lexer.next(); } } - return argArray; + return await Promise.all(argArray); } static _normalizeShortcodeScope(ctx) { From 5cae4358dc354a4ce4ee9875dde29d3622efb39f Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 9 May 2022 15:43:16 -0500 Subject: [PATCH 742/746] Cherry pick of 4c710d68965b0d0d19d9a6e7e76b1004f4e6e4e1 --- test/TemplateTest.js | 39 +++++++++++++++++++ ...ithLiquidShortcodeMultipleArguments.liquid | 9 +++++ 2 files changed, 48 insertions(+) create mode 100644 test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid diff --git a/test/TemplateTest.js b/test/TemplateTest.js index 11aba5cfa..c25802cb9 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -293,6 +293,45 @@ test("One Layout (_layoutContent deprecated but supported)", async (t) => { t.is(data.keylayout, "valuelayout"); }); +test("Liquid shortcode with multiple arguments(issue #2348)", async (t) => { + // NOTE issue #2348 was only active when you were processing multiple templates at the same time. + + let eleventyConfig = new TemplateConfig(); + eleventyConfig.userConfig.addShortcode("simplelink", function (text, url) { + return `${text} (${url})`; + }); + + let dataObj = new TemplateData("./test/stubs/", eleventyConfig); + + let tmpl = getNewTemplate( + "./test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid", + "./test/stubs/", + "dist", + dataObj, + null, + eleventyConfig + ); + + t.is( + (await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], + "layoutLiquid.liquid" + ); + + let data = await tmpl.getData(); + t.is(data[tmpl.config.keys.layout], "layoutLiquid.liquid"); + + t.is( + normalizeNewLines(cleanHtml(await tmpl.renderLayout(tmpl, data))), + `
+

Hello.

+ world (/somepage) +
` + ); + + t.is(data.keymain, "valuemain"); + t.is(data.keylayout, "valuelayout"); +}); + test("One Layout (liquid test)", async (t) => { let eleventyConfig = new TemplateConfig(); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); diff --git a/test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid b/test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid new file mode 100644 index 000000000..ca2eefe84 --- /dev/null +++ b/test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid @@ -0,0 +1,9 @@ +--- +layout: layoutLiquid.liquid +keymain: valuemain +title: 'Font Aliasing, or How to Rename a Font in CSS' +permalink: /rename-font2/ +--- + +

Hello.

+{% simplelink "world", "/somepage" %} \ No newline at end of file From 880255e62cfb49dbb88177da2a30cb5e5455d4d2 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 9 May 2022 15:39:02 -0500 Subject: [PATCH 743/746] Cherry pick https://github.com/11ty/eleventy/pull/2369#issuecomment-1121560097 --- test/EleventyTest.js | 29 ++++++++++++++ test/TemplateTest.js | 39 ------------------- test/stubs-2367/_includes/layout.liquid | 6 +++ ...hortcodeMultipleArguments-template2.liquid | 3 ++ ...ithLiquidShortcodeMultipleArguments.liquid | 3 ++ ...ithLiquidShortcodeMultipleArguments.liquid | 9 ----- 6 files changed, 41 insertions(+), 48 deletions(-) create mode 100644 test/stubs-2367/_includes/layout.liquid create mode 100644 test/stubs-2367/templateWithLiquidShortcodeMultipleArguments-template2.liquid create mode 100644 test/stubs-2367/templateWithLiquidShortcodeMultipleArguments.liquid delete mode 100644 test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid diff --git a/test/EleventyTest.js b/test/EleventyTest.js index e50dce3bd..a385cfdc3 100644 --- a/test/EleventyTest.js +++ b/test/EleventyTest.js @@ -3,6 +3,7 @@ const Eleventy = require("../src/Eleventy"); const EleventyWatchTargets = require("../src/EleventyWatchTargets"); const TemplateConfig = require("../src/TemplateConfig"); const DateGitLastUpdated = require("../src/Util/DateGitLastUpdated"); +const normalizeNewLines = require("./Util/normalizeNewLines"); test("Eleventy, defaults inherit from config", async (t) => { let elev = new Eleventy(); @@ -424,3 +425,31 @@ test("#142: date 'git Last Modified' populates page.date", async (t) => { let comparisonDate = DateGitLastUpdated("./test/stubs-142/index.njk"); t.is(result.content.trim(), "" + comparisonDate.getTime()); }); + +test("Liquid shortcode with multiple arguments(issue #2348)", async (t) => { + // NOTE issue #2348 was only active when you were processing multiple templates at the same time. + + let elev = new Eleventy("./test/stubs-2367/", "./test/stubs-2367/_site", { + config: function (eleventyConfig) { + eleventyConfig.addShortcode("simplelink", function (...args) { + return JSON.stringify(args); + }); + }, + }); + + let arr = [ + "layout", + "/mylayout", + "layout", + "/mylayout", + "layout", + "/mylayout", + ]; + let str = normalizeNewLines(`${JSON.stringify(arr)} +${JSON.stringify(arr)}`); + let results = await elev.toJSON(); + t.is(results.length, 2); + let content = results.map((entry) => entry.content).sort(); + t.is(normalizeNewLines(content[0]), str); + t.is(normalizeNewLines(content[1]), str); +}); diff --git a/test/TemplateTest.js b/test/TemplateTest.js index c25802cb9..11aba5cfa 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -293,45 +293,6 @@ test("One Layout (_layoutContent deprecated but supported)", async (t) => { t.is(data.keylayout, "valuelayout"); }); -test("Liquid shortcode with multiple arguments(issue #2348)", async (t) => { - // NOTE issue #2348 was only active when you were processing multiple templates at the same time. - - let eleventyConfig = new TemplateConfig(); - eleventyConfig.userConfig.addShortcode("simplelink", function (text, url) { - return `${text} (${url})`; - }); - - let dataObj = new TemplateData("./test/stubs/", eleventyConfig); - - let tmpl = getNewTemplate( - "./test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid", - "./test/stubs/", - "dist", - dataObj, - null, - eleventyConfig - ); - - t.is( - (await tmpl.getFrontMatter()).data[tmpl.config.keys.layout], - "layoutLiquid.liquid" - ); - - let data = await tmpl.getData(); - t.is(data[tmpl.config.keys.layout], "layoutLiquid.liquid"); - - t.is( - normalizeNewLines(cleanHtml(await tmpl.renderLayout(tmpl, data))), - `
-

Hello.

- world (/somepage) -
` - ); - - t.is(data.keymain, "valuemain"); - t.is(data.keylayout, "valuelayout"); -}); - test("One Layout (liquid test)", async (t) => { let eleventyConfig = new TemplateConfig(); let dataObj = new TemplateData("./test/stubs/", eleventyConfig); diff --git a/test/stubs-2367/_includes/layout.liquid b/test/stubs-2367/_includes/layout.liquid new file mode 100644 index 000000000..6d74116ff --- /dev/null +++ b/test/stubs-2367/_includes/layout.liquid @@ -0,0 +1,6 @@ +--- +text: layout +url: "/mylayout" +--- +{% simplelink text url text url text url %} +{% simplelink text, url, text, url, text, url %} \ No newline at end of file diff --git a/test/stubs-2367/templateWithLiquidShortcodeMultipleArguments-template2.liquid b/test/stubs-2367/templateWithLiquidShortcodeMultipleArguments-template2.liquid new file mode 100644 index 000000000..716072b7f --- /dev/null +++ b/test/stubs-2367/templateWithLiquidShortcodeMultipleArguments-template2.liquid @@ -0,0 +1,3 @@ +--- +layout: layout.liquid +--- \ No newline at end of file diff --git a/test/stubs-2367/templateWithLiquidShortcodeMultipleArguments.liquid b/test/stubs-2367/templateWithLiquidShortcodeMultipleArguments.liquid new file mode 100644 index 000000000..716072b7f --- /dev/null +++ b/test/stubs-2367/templateWithLiquidShortcodeMultipleArguments.liquid @@ -0,0 +1,3 @@ +--- +layout: layout.liquid +--- \ No newline at end of file diff --git a/test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid b/test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid deleted file mode 100644 index ca2eefe84..000000000 --- a/test/stubs/templateWithLiquidShortcodeMultipleArguments.liquid +++ /dev/null @@ -1,9 +0,0 @@ ---- -layout: layoutLiquid.liquid -keymain: valuemain -title: 'Font Aliasing, or How to Rename a Font in CSS' -permalink: /rename-font2/ ---- - -

Hello.

-{% simplelink "world", "/somepage" %} \ No newline at end of file From 8a0d955e32e2cc6616bb83bd75bb23561498b98d Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Aug 2022 17:25:45 -0500 Subject: [PATCH 744/746] Bump dependencies (no major version bumps on deps, only devdeps) --- package.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 26fb67ca5..8cd6f379b 100755 --- a/package.json +++ b/package.json @@ -76,43 +76,43 @@ ] }, "devDependencies": { - "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", + "@11ty/eleventy-plugin-syntaxhighlight": "^4.1.0", "@11ty/eleventy-plugin-vue": "1.0.0-canary.8", - "@vue/server-renderer": "^3.2.33", + "@vue/server-renderer": "^3.2.37", "ava": "^3.15.0", - "husky": "^7.0.4", + "husky": "^8.0.1", "js-yaml": "^4.1.0", - "lint-staged": "^12.3.8", - "markdown-it-emoji": "^2.0.0", - "marked": "^4.0.14", + "lint-staged": "^13.0.3", + "markdown-it-emoji": "^2.0.2", + "marked": "^4.0.18", "nyc": "^15.1.0", - "prettier": "^2.6.2", + "prettier": "^2.7.1", "rimraf": "^3.0.2", - "sass": "^1.50.0", + "sass": "^1.54.4", "toml": "^3.0.0", - "vue": "^3.2.33" + "vue": "^3.2.37" }, "dependencies": { "@11ty/dependency-tree": "^2.0.1", "@11ty/eleventy-utils": "^1.0.1", "@iarna/toml": "^2.2.5", "@sindresorhus/slugify": "^1.1.2", - "browser-sync": "^2.27.9", + "browser-sync": "^2.27.10", "chokidar": "^3.5.3", "cross-spawn": "^7.0.3", "debug": "^4.3.4", "dependency-graph": "^0.11.0", - "ejs": "^3.1.6", + "ejs": "^3.1.8", "fast-glob": "^3.2.11", "graceful-fs": "^4.2.10", "gray-matter": "^4.0.3", "hamljs": "^0.6.2", "handlebars": "^4.7.7", "is-glob": "^4.0.3", - "kleur": "^4.1.4 ", - "liquidjs": "^9.36.1", + "kleur": "^4.1.5", + "liquidjs": "^9.40.0", "lodash": "^4.17.21", - "luxon": "^2.3.2", + "luxon": "^2.5.0", "markdown-it": "^12.3.2", "minimist": "^1.2.6", "moo": "^0.5.1", @@ -120,7 +120,7 @@ "mustache": "^4.2.0", "normalize-path": "^3.0.0", "nunjucks": "^3.2.3", - "path-to-regexp": "^6.2.0", + "path-to-regexp": "^6.2.1", "please-upgrade-node": "^3.2.0", "pretty": "^2.0.0", "pug": "^3.0.2", From bd42a2ae0fa7381f217fb9c7ff790093fc5b9703 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Mon, 15 Aug 2022 17:25:57 -0500 Subject: [PATCH 745/746] v1.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8cd6f379b..fbab56f53 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@11ty/eleventy", - "version": "1.0.1", + "version": "1.0.2", "description": "Transform a directory of templates into HTML.", "publishConfig": { "access": "public" From f90e54f9bdfd1fe0a9b45e7024d4cda2356991c3 Mon Sep 17 00:00:00 2001 From: Zach Leatherman Date: Tue, 16 Aug 2022 08:38:06 -0500 Subject: [PATCH 746/746] v1.0.2 code coverage --- docs-src/_data/coverage.json | 43 +++++++++++++++++----------------- docs/coverage.md | 45 ++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/docs-src/_data/coverage.json b/docs-src/_data/coverage.json index 71cf34f6b..5606d9cd7 100644 --- a/docs-src/_data/coverage.json +++ b/docs-src/_data/coverage.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":4916,"covered":4120,"skipped":0,"pct":83.8},"statements":{"total":4944,"covered":4145,"skipped":0,"pct":83.83},"functions":{"total":1064,"covered":901,"skipped":0,"pct":84.68},"branches":{"total":2283,"covered":1726,"skipped":0,"pct":75.6},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":4904,"covered":4109,"skipped":0,"pct":83.78},"statements":{"total":4931,"covered":4133,"skipped":0,"pct":83.81},"functions":{"total":1050,"covered":888,"skipped":0,"pct":84.57},"branches":{"total":2280,"covered":1716,"skipped":0,"pct":75.26},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/cmd.js": {"lines":{"total":53,"covered":33,"skipped":0,"pct":62.26},"functions":{"total":11,"covered":1,"skipped":0,"pct":9.09},"statements":{"total":53,"covered":33,"skipped":0,"pct":62.26},"branches":{"total":22,"covered":13,"skipped":0,"pct":59.09}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -9,17 +9,17 @@ ,"/Users/zachleat/Code/eleventy/.cache/vue/_includes/include.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/_includes/include.vue_vue_type_script_lang.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/.cache/vue/_includes/include.vue_vue_type_template_id_d3bb7f88_lang.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":18,"covered":17,"skipped":0,"pct":94.44},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":18,"covered":17,"skipped":0,"pct":94.44},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":45,"covered":34,"skipped":0,"pct":75.55},"functions":{"total":10,"covered":7,"skipped":0,"pct":70},"statements":{"total":45,"covered":34,"skipped":0,"pct":75.55},"branches":{"total":15,"covered":9,"skipped":0,"pct":60}} -,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":21,"skipped":0,"pct":77.77},"functions":{"total":8,"covered":6,"skipped":0,"pct":75},"statements":{"total":27,"covered":21,"skipped":0,"pct":77.77},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/Benchmark.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkGroup.js": {"lines":{"total":46,"covered":34,"skipped":0,"pct":73.91},"functions":{"total":11,"covered":7,"skipped":0,"pct":63.63},"statements":{"total":46,"covered":34,"skipped":0,"pct":73.91},"branches":{"total":15,"covered":9,"skipped":0,"pct":60}} +,"/Users/zachleat/Code/eleventy/src/BenchmarkManager.js": {"lines":{"total":27,"covered":20,"skipped":0,"pct":74.07},"functions":{"total":9,"covered":6,"skipped":0,"pct":66.66},"statements":{"total":27,"covered":20,"skipped":0,"pct":74.07},"branches":{"total":8,"covered":6,"skipped":0,"pct":75}} ,"/Users/zachleat/Code/eleventy/src/ComputedData.js": {"lines":{"total":60,"covered":60,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"statements":{"total":60,"covered":60,"skipped":0,"pct":100},"branches":{"total":29,"covered":28,"skipped":0,"pct":96.55}} -,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":50,"skipped":0,"pct":98.03},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":50,"skipped":0,"pct":98.03},"branches":{"total":32,"covered":29,"skipped":0,"pct":90.62}} +,"/Users/zachleat/Code/eleventy/src/ComputedDataProxy.js": {"lines":{"total":51,"covered":49,"skipped":0,"pct":96.07},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":51,"covered":49,"skipped":0,"pct":96.07},"branches":{"total":32,"covered":28,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataQueue.js": {"lines":{"total":21,"covered":21,"skipped":0,"pct":100},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":21,"covered":21,"skipped":0,"pct":100},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} ,"/Users/zachleat/Code/eleventy/src/ComputedDataTemplateString.js": {"lines":{"total":26,"covered":24,"skipped":0,"pct":92.3},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":26,"covered":24,"skipped":0,"pct":92.3},"branches":{"total":7,"covered":5,"skipped":0,"pct":71.42}} -,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":323,"covered":210,"skipped":0,"pct":65.01},"functions":{"total":49,"covered":33,"skipped":0,"pct":67.34},"statements":{"total":324,"covered":210,"skipped":0,"pct":64.81},"branches":{"total":117,"covered":76,"skipped":0,"pct":64.95}} +,"/Users/zachleat/Code/eleventy/src/Eleventy.js": {"lines":{"total":324,"covered":211,"skipped":0,"pct":65.12},"functions":{"total":51,"covered":35,"skipped":0,"pct":68.62},"statements":{"total":325,"covered":211,"skipped":0,"pct":64.92},"branches":{"total":115,"covered":75,"skipped":0,"pct":65.21}} ,"/Users/zachleat/Code/eleventy/src/EleventyBaseError.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyCommandCheckError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":38,"covered":35,"skipped":0,"pct":92.1},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":38,"covered":35,"skipped":0,"pct":92.1},"branches":{"total":37,"covered":25,"skipped":0,"pct":67.56}} +,"/Users/zachleat/Code/eleventy/src/EleventyErrorHandler.js": {"lines":{"total":45,"covered":42,"skipped":0,"pct":93.33},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":45,"covered":42,"skipped":0,"pct":93.33},"branches":{"total":32,"covered":21,"skipped":0,"pct":65.62}} ,"/Users/zachleat/Code/eleventy/src/EleventyErrorUtil.js": {"lines":{"total":23,"covered":23,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":23,"covered":23,"skipped":0,"pct":100},"branches":{"total":20,"covered":20,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/EleventyExtensionMap.js": {"lines":{"total":107,"covered":104,"skipped":0,"pct":97.19},"functions":{"total":30,"covered":29,"skipped":0,"pct":96.66},"statements":{"total":107,"covered":104,"skipped":0,"pct":97.19},"branches":{"total":49,"covered":43,"skipped":0,"pct":87.75}} ,"/Users/zachleat/Code/eleventy/src/EleventyFiles.js": {"lines":{"total":191,"covered":171,"skipped":0,"pct":89.52},"functions":{"total":45,"covered":40,"skipped":0,"pct":88.88},"statements":{"total":193,"covered":173,"skipped":0,"pct":89.63},"branches":{"total":73,"covered":56,"skipped":0,"pct":76.71}} @@ -27,29 +27,28 @@ ,"/Users/zachleat/Code/eleventy/src/EleventyWatch.js": {"lines":{"total":39,"covered":39,"skipped":0,"pct":100},"functions":{"total":17,"covered":17,"skipped":0,"pct":100},"statements":{"total":40,"covered":40,"skipped":0,"pct":100},"branches":{"total":21,"covered":19,"skipped":0,"pct":90.47}} ,"/Users/zachleat/Code/eleventy/src/EleventyWatchTargets.js": {"lines":{"total":49,"covered":45,"skipped":0,"pct":91.83},"functions":{"total":21,"covered":18,"skipped":0,"pct":85.71},"statements":{"total":49,"covered":45,"skipped":0,"pct":91.83},"branches":{"total":15,"covered":14,"skipped":0,"pct":93.33}} ,"/Users/zachleat/Code/eleventy/src/EventBus.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":95,"covered":72,"skipped":0,"pct":75.78},"functions":{"total":14,"covered":12,"skipped":0,"pct":85.71},"statements":{"total":95,"covered":72,"skipped":0,"pct":75.78},"branches":{"total":38,"covered":24,"skipped":0,"pct":63.15}} -,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":411,"covered":383,"skipped":0,"pct":93.18},"functions":{"total":71,"covered":69,"skipped":0,"pct":97.18},"statements":{"total":413,"covered":385,"skipped":0,"pct":93.22},"branches":{"total":195,"covered":168,"skipped":0,"pct":86.15}} +,"/Users/zachleat/Code/eleventy/src/Serverless.js": {"lines":{"total":94,"covered":71,"skipped":0,"pct":75.53},"functions":{"total":14,"covered":12,"skipped":0,"pct":85.71},"statements":{"total":94,"covered":71,"skipped":0,"pct":75.53},"branches":{"total":38,"covered":24,"skipped":0,"pct":63.15}} +,"/Users/zachleat/Code/eleventy/src/Template.js": {"lines":{"total":418,"covered":394,"skipped":0,"pct":94.25},"functions":{"total":71,"covered":70,"skipped":0,"pct":98.59},"statements":{"total":420,"covered":396,"skipped":0,"pct":94.28},"branches":{"total":200,"covered":173,"skipped":0,"pct":86.5}} ,"/Users/zachleat/Code/eleventy/src/TemplateBehavior.js": {"lines":{"total":24,"covered":21,"skipped":0,"pct":87.5},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":24,"covered":21,"skipped":0,"pct":87.5},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} ,"/Users/zachleat/Code/eleventy/src/TemplateCache.js": {"lines":{"total":11,"covered":9,"skipped":0,"pct":81.81},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":11,"covered":9,"skipped":0,"pct":81.81},"branches":{"total":4,"covered":2,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/TemplateCollection.js": {"lines":{"total":42,"covered":37,"skipped":0,"pct":88.09},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":44,"covered":39,"skipped":0,"pct":88.63},"branches":{"total":16,"covered":11,"skipped":0,"pct":68.75}} -,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":86,"covered":74,"skipped":0,"pct":86.04},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":86,"covered":74,"skipped":0,"pct":86.04},"branches":{"total":41,"covered":35,"skipped":0,"pct":85.36}} -,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":207,"covered":185,"skipped":0,"pct":89.37},"functions":{"total":36,"covered":35,"skipped":0,"pct":97.22},"statements":{"total":207,"covered":185,"skipped":0,"pct":89.37},"branches":{"total":115,"covered":89,"skipped":0,"pct":77.39}} -,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":264,"covered":252,"skipped":0,"pct":95.45},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":267,"covered":255,"skipped":0,"pct":95.5},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} +,"/Users/zachleat/Code/eleventy/src/TemplateConfig.js": {"lines":{"total":94,"covered":75,"skipped":0,"pct":79.78},"functions":{"total":14,"covered":8,"skipped":0,"pct":57.14},"statements":{"total":94,"covered":75,"skipped":0,"pct":79.78},"branches":{"total":45,"covered":35,"skipped":0,"pct":77.77}} +,"/Users/zachleat/Code/eleventy/src/TemplateContent.js": {"lines":{"total":214,"covered":193,"skipped":0,"pct":90.18},"functions":{"total":37,"covered":36,"skipped":0,"pct":97.29},"statements":{"total":214,"covered":193,"skipped":0,"pct":90.18},"branches":{"total":123,"covered":98,"skipped":0,"pct":79.67}} +,"/Users/zachleat/Code/eleventy/src/TemplateData.js": {"lines":{"total":267,"covered":255,"skipped":0,"pct":95.5},"functions":{"total":50,"covered":49,"skipped":0,"pct":98},"statements":{"total":270,"covered":258,"skipped":0,"pct":95.55},"branches":{"total":105,"covered":89,"skipped":0,"pct":84.76}} ,"/Users/zachleat/Code/eleventy/src/TemplateEngineManager.js": {"lines":{"total":52,"covered":50,"skipped":0,"pct":96.15},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":52,"covered":50,"skipped":0,"pct":96.15},"branches":{"total":34,"covered":33,"skipped":0,"pct":97.05}} ,"/Users/zachleat/Code/eleventy/src/TemplateFileSlug.js": {"lines":{"total":22,"covered":22,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":22,"covered":22,"skipped":0,"pct":100},"branches":{"total":8,"covered":8,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/TemplateGlob.js": {"lines":{"total":15,"covered":14,"skipped":0,"pct":93.33},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":8,"covered":7,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayout.js": {"lines":{"total":78,"covered":72,"skipped":0,"pct":92.3},"functions":{"total":10,"covered":10,"skipped":0,"pct":100},"statements":{"total":79,"covered":73,"skipped":0,"pct":92.4},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} ,"/Users/zachleat/Code/eleventy/src/TemplateLayoutPathResolver.js": {"lines":{"total":48,"covered":44,"skipped":0,"pct":91.66},"functions":{"total":11,"covered":11,"skipped":0,"pct":100},"statements":{"total":48,"covered":44,"skipped":0,"pct":91.66},"branches":{"total":22,"covered":18,"skipped":0,"pct":81.81}} -,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":279,"covered":270,"skipped":0,"pct":96.77},"functions":{"total":37,"covered":35,"skipped":0,"pct":94.59},"statements":{"total":279,"covered":270,"skipped":0,"pct":96.77},"branches":{"total":152,"covered":131,"skipped":0,"pct":86.18}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":60,"covered":57,"skipped":0,"pct":95},"functions":{"total":14,"covered":13,"skipped":0,"pct":92.85},"statements":{"total":60,"covered":57,"skipped":0,"pct":95},"branches":{"total":14,"covered":12,"skipped":0,"pct":85.71}} -,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":93,"covered":80,"skipped":0,"pct":86.02},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":93,"covered":80,"skipped":0,"pct":86.02},"branches":{"total":38,"covered":27,"skipped":0,"pct":71.05}} -,"/Users/zachleat/Code/eleventy/src/TemplatePath.js": {"lines":{"total":98,"covered":98,"skipped":0,"pct":100},"functions":{"total":28,"covered":27,"skipped":0,"pct":96.42},"statements":{"total":99,"covered":99,"skipped":0,"pct":100},"branches":{"total":55,"covered":55,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":78,"covered":70,"skipped":0,"pct":89.74},"functions":{"total":10,"covered":9,"skipped":0,"pct":90},"statements":{"total":78,"covered":70,"skipped":0,"pct":89.74},"branches":{"total":69,"covered":62,"skipped":0,"pct":89.85}} +,"/Users/zachleat/Code/eleventy/src/TemplateMap.js": {"lines":{"total":279,"covered":270,"skipped":0,"pct":96.77},"functions":{"total":37,"covered":35,"skipped":0,"pct":94.59},"statements":{"total":279,"covered":270,"skipped":0,"pct":96.77},"branches":{"total":154,"covered":133,"skipped":0,"pct":86.36}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthrough.js": {"lines":{"total":70,"covered":66,"skipped":0,"pct":94.28},"functions":{"total":15,"covered":14,"skipped":0,"pct":93.33},"statements":{"total":70,"covered":66,"skipped":0,"pct":94.28},"branches":{"total":20,"covered":17,"skipped":0,"pct":85}} +,"/Users/zachleat/Code/eleventy/src/TemplatePassthroughManager.js": {"lines":{"total":100,"covered":86,"skipped":0,"pct":86},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":100,"covered":86,"skipped":0,"pct":86},"branches":{"total":44,"covered":31,"skipped":0,"pct":70.45}} +,"/Users/zachleat/Code/eleventy/src/TemplatePermalink.js": {"lines":{"total":81,"covered":72,"skipped":0,"pct":88.88},"functions":{"total":10,"covered":9,"skipped":0,"pct":90},"statements":{"total":81,"covered":72,"skipped":0,"pct":88.88},"branches":{"total":71,"covered":63,"skipped":0,"pct":88.73}} ,"/Users/zachleat/Code/eleventy/src/TemplateRender.js": {"lines":{"total":91,"covered":86,"skipped":0,"pct":94.5},"functions":{"total":23,"covered":23,"skipped":0,"pct":100},"statements":{"total":91,"covered":86,"skipped":0,"pct":94.5},"branches":{"total":59,"covered":53,"skipped":0,"pct":89.83}} ,"/Users/zachleat/Code/eleventy/src/TemplateWriter.js": {"lines":{"total":145,"covered":117,"skipped":0,"pct":80.68},"functions":{"total":39,"covered":28,"skipped":0,"pct":71.79},"statements":{"total":145,"covered":117,"skipped":0,"pct":80.68},"branches":{"total":36,"covered":19,"skipped":0,"pct":52.77}} -,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":246,"covered":168,"skipped":0,"pct":68.29},"functions":{"total":65,"covered":40,"skipped":0,"pct":61.53},"statements":{"total":246,"covered":168,"skipped":0,"pct":68.29},"branches":{"total":101,"covered":52,"skipped":0,"pct":51.48}} +,"/Users/zachleat/Code/eleventy/src/UserConfig.js": {"lines":{"total":253,"covered":183,"skipped":0,"pct":72.33},"functions":{"total":66,"covered":43,"skipped":0,"pct":65.15},"statements":{"total":253,"covered":183,"skipped":0,"pct":72.33},"branches":{"total":107,"covered":58,"skipped":0,"pct":54.2}} ,"/Users/zachleat/Code/eleventy/src/defaultConfig.js": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":5,"covered":2,"skipped":0,"pct":40},"statements":{"total":21,"covered":18,"skipped":0,"pct":85.71},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} -,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":92,"covered":81,"skipped":0,"pct":88.04},"functions":{"total":13,"covered":13,"skipped":0,"pct":100},"statements":{"total":93,"covered":82,"skipped":0,"pct":88.17},"branches":{"total":62,"covered":49,"skipped":0,"pct":79.03}} +,"/Users/zachleat/Code/eleventy/src/Engines/Custom.js": {"lines":{"total":94,"covered":84,"skipped":0,"pct":89.36},"functions":{"total":14,"covered":14,"skipped":0,"pct":100},"statements":{"total":96,"covered":86,"skipped":0,"pct":89.58},"branches":{"total":70,"covered":57,"skipped":0,"pct":81.42}} ,"/Users/zachleat/Code/eleventy/src/Engines/Ejs.js": {"lines":{"total":19,"covered":18,"skipped":0,"pct":94.73},"functions":{"total":7,"covered":6,"skipped":0,"pct":85.71},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":9,"covered":8,"skipped":0,"pct":88.88}} ,"/Users/zachleat/Code/eleventy/src/Engines/Haml.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Handlebars.js": {"lines":{"total":29,"covered":29,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":29,"covered":29,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} @@ -60,12 +59,12 @@ ,"/Users/zachleat/Code/eleventy/src/Engines/Mustache.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Engines/Nunjucks.js": {"lines":{"total":203,"covered":138,"skipped":0,"pct":67.98},"functions":{"total":49,"covered":37,"skipped":0,"pct":75.51},"statements":{"total":203,"covered":138,"skipped":0,"pct":67.98},"branches":{"total":84,"covered":54,"skipped":0,"pct":64.28}} ,"/Users/zachleat/Code/eleventy/src/Engines/Pug.js": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} -,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":75,"covered":74,"skipped":0,"pct":98.66},"functions":{"total":26,"covered":26,"skipped":0,"pct":100},"statements":{"total":77,"covered":76,"skipped":0,"pct":98.7},"branches":{"total":16,"covered":15,"skipped":0,"pct":93.75}} +,"/Users/zachleat/Code/eleventy/src/Engines/TemplateEngine.js": {"lines":{"total":77,"covered":76,"skipped":0,"pct":98.7},"functions":{"total":27,"covered":27,"skipped":0,"pct":100},"statements":{"total":79,"covered":78,"skipped":0,"pct":98.73},"branches":{"total":18,"covered":17,"skipped":0,"pct":94.44}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentPrematureUseError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/TemplateContentUnrenderedTemplateError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Errors/UsingCircularTemplateContentReferenceError.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/GetCollectionItem.js": {"lines":{"total":10,"covered":10,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":10,"covered":10,"skipped":0,"pct":100},"branches":{"total":14,"covered":13,"skipped":0,"pct":92.85}} -,"/Users/zachleat/Code/eleventy/src/Filters/ServerlessUrl.js": {"lines":{"total":7,"covered":7,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":4,"covered":3,"skipped":0,"pct":75}} +,"/Users/zachleat/Code/eleventy/src/Filters/ServerlessUrl.js": {"lines":{"total":17,"covered":17,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":17,"covered":17,"skipped":0,"pct":100},"branches":{"total":6,"covered":5,"skipped":0,"pct":83.33}} ,"/Users/zachleat/Code/eleventy/src/Filters/Slug.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Slugify.js": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Filters/Url.js": {"lines":{"total":20,"covered":19,"skipped":0,"pct":95},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":20,"covered":19,"skipped":0,"pct":95},"branches":{"total":21,"covered":20,"skipped":0,"pct":95.23}} @@ -74,8 +73,10 @@ ,"/Users/zachleat/Code/eleventy/src/Plugins/ServerlessBundlerPlugin.js": {"lines":{"total":186,"covered":12,"skipped":0,"pct":6.45},"functions":{"total":34,"covered":0,"skipped":0,"pct":0},"statements":{"total":188,"covered":12,"skipped":0,"pct":6.38},"branches":{"total":91,"covered":0,"skipped":0,"pct":0}} ,"/Users/zachleat/Code/eleventy/src/Util/AsyncEventEmitter.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":7,"covered":7,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/ConsoleLogger.js": {"lines":{"total":28,"covered":24,"skipped":0,"pct":85.71},"functions":{"total":13,"covered":10,"skipped":0,"pct":76.92},"statements":{"total":28,"covered":24,"skipped":0,"pct":85.71},"branches":{"total":19,"covered":17,"skipped":0,"pct":89.47}} +,"/Users/zachleat/Code/eleventy/src/Util/DateGitLastUpdated.js": {"lines":{"total":6,"covered":6,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":6,"covered":6,"skipped":0,"pct":100},"branches":{"total":2,"covered":1,"skipped":0,"pct":50}} ,"/Users/zachleat/Code/eleventy/src/Util/DeleteRequireCache.js": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/GetJavaScriptData.js": {"lines":{"total":8,"covered":8,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":14,"covered":14,"skipped":0,"pct":100}} +,"/Users/zachleat/Code/eleventy/src/Util/IsPlainObject.js": {"lines":{"total":5,"covered":5,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":5,"covered":5,"skipped":0,"pct":100},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Merge.js": {"lines":{"total":28,"covered":26,"skipped":0,"pct":92.85},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":28,"covered":26,"skipped":0,"pct":92.85},"branches":{"total":24,"covered":21,"skipped":0,"pct":87.5}} ,"/Users/zachleat/Code/eleventy/src/Util/Pluralize.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/Users/zachleat/Code/eleventy/src/Util/Sortable.js": {"lines":{"total":48,"covered":45,"skipped":0,"pct":93.75},"functions":{"total":20,"covered":18,"skipped":0,"pct":90},"statements":{"total":48,"covered":45,"skipped":0,"pct":93.75},"branches":{"total":20,"covered":18,"skipped":0,"pct":90}} diff --git a/docs/coverage.md b/docs/coverage.md index 0d0332a79..ce4b3303e 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -1,8 +1,8 @@ -# Code Coverage for Eleventy v1.0.0 +# Code Coverage for Eleventy v1.0.2 | Filename | % Lines | % Statements | % Functions | % Branches | | ------------------------------------------------------------------------ | ------- | ------------ | ----------- | ---------- | -| `total` | 83.8% | 83.83% | 84.68% | 75.6% | +| `total` | 83.78% | 83.81% | 84.57% | 75.26% | | `cmd.js` | 62.26% | 62.26% | 9.09% | 59.09% | | `.cache/vue/include.js` | 100% | 100% | 100% | 100% | | `.cache/vue/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | @@ -13,17 +13,17 @@ | `.cache/vue/_includes/include.js` | 100% | 100% | 100% | 100% | | `.cache/vue/_includes/include.vue_vue_type_script_lang.js` | 100% | 100% | 100% | 100% | | `.cache/vue/_includes/include.vue_vue_type_template_id_d3bb7f88_lang.js` | 100% | 100% | 100% | 100% | -| `src/Benchmark.js` | 94.44% | 94.44% | 100% | 83.33% | -| `src/BenchmarkGroup.js` | 75.55% | 75.55% | 70% | 60% | -| `src/BenchmarkManager.js` | 77.77% | 77.77% | 75% | 75% | +| `src/Benchmark.js` | 94.73% | 94.73% | 100% | 83.33% | +| `src/BenchmarkGroup.js` | 73.91% | 73.91% | 63.63% | 60% | +| `src/BenchmarkManager.js` | 74.07% | 74.07% | 66.66% | 75% | | `src/ComputedData.js` | 100% | 100% | 100% | 96.55% | -| `src/ComputedDataProxy.js` | 98.03% | 98.03% | 100% | 90.62% | +| `src/ComputedDataProxy.js` | 96.07% | 96.07% | 100% | 87.5% | | `src/ComputedDataQueue.js` | 100% | 100% | 100% | 72.72% | | `src/ComputedDataTemplateString.js` | 92.3% | 92.3% | 100% | 71.42% | -| `src/Eleventy.js` | 65.01% | 64.81% | 67.34% | 64.95% | +| `src/Eleventy.js` | 65.12% | 64.92% | 68.62% | 65.21% | | `src/EleventyBaseError.js` | 100% | 100% | 100% | 100% | | `src/EleventyCommandCheckError.js` | 100% | 100% | 100% | 100% | -| `src/EleventyErrorHandler.js` | 92.1% | 92.1% | 100% | 67.56% | +| `src/EleventyErrorHandler.js` | 93.33% | 93.33% | 100% | 65.62% | | `src/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% | | `src/EleventyExtensionMap.js` | 97.19% | 97.19% | 96.66% | 87.75% | | `src/EleventyFiles.js` | 89.52% | 89.63% | 88.88% | 76.71% | @@ -31,29 +31,28 @@ | `src/EleventyWatch.js` | 100% | 100% | 100% | 90.47% | | `src/EleventyWatchTargets.js` | 91.83% | 91.83% | 85.71% | 93.33% | | `src/EventBus.js` | 100% | 100% | 100% | 100% | -| `src/Serverless.js` | 75.78% | 75.78% | 85.71% | 63.15% | -| `src/Template.js` | 93.18% | 93.22% | 97.18% | 86.15% | +| `src/Serverless.js` | 75.53% | 75.53% | 85.71% | 63.15% | +| `src/Template.js` | 94.25% | 94.28% | 98.59% | 86.5% | | `src/TemplateBehavior.js` | 87.5% | 87.5% | 100% | 85.71% | | `src/TemplateCache.js` | 81.81% | 81.81% | 85.71% | 50% | | `src/TemplateCollection.js` | 88.09% | 88.63% | 93.33% | 68.75% | -| `src/TemplateConfig.js` | 86.04% | 86.04% | 64.28% | 85.36% | -| `src/TemplateContent.js` | 89.37% | 89.37% | 97.22% | 77.39% | -| `src/TemplateData.js` | 95.45% | 95.5% | 98% | 84.76% | +| `src/TemplateConfig.js` | 79.78% | 79.78% | 57.14% | 77.77% | +| `src/TemplateContent.js` | 90.18% | 90.18% | 97.29% | 79.67% | +| `src/TemplateData.js` | 95.5% | 95.55% | 98% | 84.76% | | `src/TemplateEngineManager.js` | 96.15% | 96.15% | 85.71% | 97.05% | | `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% | | `src/TemplateGlob.js` | 93.33% | 93.33% | 100% | 87.5% | | `src/TemplateLayout.js` | 92.3% | 92.4% | 100% | 85% | | `src/TemplateLayoutPathResolver.js` | 91.66% | 91.66% | 100% | 81.81% | -| `src/TemplateMap.js` | 96.77% | 96.77% | 94.59% | 86.18% | -| `src/TemplatePassthrough.js` | 95% | 95% | 92.85% | 85.71% | -| `src/TemplatePassthroughManager.js` | 86.02% | 86.02% | 100% | 71.05% | -| `src/TemplatePath.js` | 100% | 100% | 96.42% | 100% | -| `src/TemplatePermalink.js` | 89.74% | 89.74% | 90% | 89.85% | +| `src/TemplateMap.js` | 96.77% | 96.77% | 94.59% | 86.36% | +| `src/TemplatePassthrough.js` | 94.28% | 94.28% | 93.33% | 85% | +| `src/TemplatePassthroughManager.js` | 86% | 86% | 100% | 70.45% | +| `src/TemplatePermalink.js` | 88.88% | 88.88% | 90% | 88.73% | | `src/TemplateRender.js` | 94.5% | 94.5% | 100% | 89.83% | | `src/TemplateWriter.js` | 80.68% | 80.68% | 71.79% | 52.77% | -| `src/UserConfig.js` | 68.29% | 68.29% | 61.53% | 51.48% | +| `src/UserConfig.js` | 72.33% | 72.33% | 65.15% | 54.2% | | `src/defaultConfig.js` | 85.71% | 85.71% | 40% | 100% | -| `src/Engines/Custom.js` | 88.04% | 88.17% | 100% | 79.03% | +| `src/Engines/Custom.js` | 89.36% | 89.58% | 100% | 81.42% | | `src/Engines/Ejs.js` | 94.73% | 94.73% | 85.71% | 88.88% | | `src/Engines/Haml.js` | 100% | 100% | 100% | 100% | | `src/Engines/Handlebars.js` | 100% | 100% | 100% | 83.33% | @@ -64,12 +63,12 @@ | `src/Engines/Mustache.js` | 100% | 100% | 100% | 100% | | `src/Engines/Nunjucks.js` | 67.98% | 67.98% | 75.51% | 64.28% | | `src/Engines/Pug.js` | 100% | 100% | 100% | 81.81% | -| `src/Engines/TemplateEngine.js` | 98.66% | 98.7% | 100% | 93.75% | +| `src/Engines/TemplateEngine.js` | 98.7% | 98.73% | 100% | 94.44% | | `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% | | `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% | | `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% | | `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 92.85% | -| `src/Filters/ServerlessUrl.js` | 100% | 100% | 100% | 75% | +| `src/Filters/ServerlessUrl.js` | 100% | 100% | 100% | 83.33% | | `src/Filters/Slug.js` | 100% | 100% | 100% | 100% | | `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% | | `src/Filters/Url.js` | 95% | 95% | 100% | 95.23% | @@ -78,8 +77,10 @@ | `src/Plugins/ServerlessBundlerPlugin.js` | 6.45% | 6.38% | 0% | 0% | | `src/Util/AsyncEventEmitter.js` | 100% | 100% | 100% | 100% | | `src/Util/ConsoleLogger.js` | 85.71% | 85.71% | 76.92% | 89.47% | +| `src/Util/DateGitLastUpdated.js` | 100% | 100% | 100% | 50% | | `src/Util/DeleteRequireCache.js` | 100% | 100% | 100% | 100% | | `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 100% | +| `src/Util/IsPlainObject.js` | 100% | 100% | 100% | 100% | | `src/Util/Merge.js` | 92.85% | 92.85% | 100% | 87.5% | | `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% | | `src/Util/Sortable.js` | 93.75% | 93.75% | 90% | 90% |