Skip to content

Commit

Permalink
Swap from built-in plugin to use addPassthroughCopy method
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Dec 9, 2024
1 parent 098d64c commit ff0b012
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 76 deletions.
6 changes: 0 additions & 6 deletions src/Eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import RenderPlugin, * as RenderPluginExtras from "./Plugins/RenderPlugin.js";
import I18nPlugin, * as I18nPluginExtras from "./Plugins/I18nPlugin.js";
import HtmlBasePlugin, * as HtmlBasePluginExtras from "./Plugins/HtmlBasePlugin.js";
import { TransformPlugin as InputPathToUrlTransformPlugin } from "./Plugins/InputPathToUrl.js";
import { AutoCopyPlugin } from "./Plugins/AutoCopyPlugin.js";
import { IdAttributePlugin } from "./Plugins/IdAttributePlugin.js";

const pkg = getEleventyPackageJson();
Expand Down Expand Up @@ -1487,9 +1486,4 @@ export {
* @type {module:11ty/eleventy/Plugins/IdAttributePlugin}
*/
IdAttributePlugin,

/**
* @type {module:11ty/eleventy/Plugins/AutoCopyPlugin}
*/
AutoCopyPlugin,
};
63 changes: 33 additions & 30 deletions src/Plugins/AutoCopyPlugin.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
import { AutoCopy } from "../Util/AutoCopy.js";

function AutoCopyPlugin(eleventyConfig, defaultOptions = {}) {
// one AutoCopy instance per entry
function init(eleventyConfig, options) {
let opts = Object.assign(
{
extensions: "html",
match: false,
match: false, // can be one glob string or an array of globs
paths: [], // directories to also look in for files
failOnError: true, // fails when a path matches (via `match`) but not found on file system
copyOptions: undefined,
},
defaultOptions,
options,
);

let ac = eleventyConfig.autoCopy;
if (!ac) {
ac = new AutoCopy();
ac.setUserConfig(eleventyConfig);
eleventyConfig.autoCopy = ac;

ac.setFailOnError(opts.failOnError);
ac.setCopyOptions(opts.copyOptions);

eleventyConfig.htmlTransformer.addUrlTransform(
opts.extensions,
function (targetFilepathOrUrl) {
// @ts-ignore
ac.copy(targetFilepathOrUrl, this.page.inputPath, this.page.outputPath);

// TODO front matter option for manual copy

return targetFilepathOrUrl;
},
{
enabled: () => ac.isEnabled(),
// - MUST run after other plugins but BEFORE HtmlBase plugin
priority: -1,
},
);
}

let ac = new AutoCopy();
ac.setUserConfig(eleventyConfig);
ac.addMatchingGlob(opts.match);
ac.setFailOnError(opts.failOnError);
ac.setCopyOptions(opts.copyOptions);

eleventyConfig.htmlTransformer.addUrlTransform(
opts.extensions,
function (targetFilepathOrUrl) {
// @ts-ignore
ac.copy(targetFilepathOrUrl, this.page.inputPath, this.page.outputPath);

// TODO front matter option for manual copy

return targetFilepathOrUrl;
},
{
enabled: () => ac.isEnabled(),
// - MUST run after other plugins but BEFORE HtmlBase plugin
priority: -1,
},
);

ac.addPaths(opts.paths);
}

function AutoCopyPlugin(eleventyConfig) {
// Important: if this is empty, no URL transforms are added
for (let options of eleventyConfig.autoCopies) {
init(eleventyConfig, options);
}
}

Object.defineProperty(AutoCopyPlugin, "eleventyPackage", {
value: "@11ty/eleventy/autocopy-transform-plugin",
});
Expand Down
14 changes: 13 additions & 1 deletion src/UserConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class UserConfig {

/** @type {object} */
this.passthroughCopies = {};
this.autoCopies = new Set();

/** @type {object} */
this.layoutAliases = {};
Expand Down Expand Up @@ -791,7 +792,17 @@ class UserConfig {
* @returns {any} a reference to the `EleventyConfig` object.
*/
addPassthroughCopy(fileOrDir, copyOptions = {}) {
if (typeof fileOrDir === "string") {
if (copyOptions.mode === "auto") {
if (isPlainObject(fileOrDir)) {
throw new Error(
"mode: 'auto' does not yet support input -> output (objects) mapping. Please pass a string glob or an Array of string globs!",
);
}
this.autoCopies?.add({
match: fileOrDir,
...copyOptions,
});
} else if (typeof fileOrDir === "string") {
this.passthroughCopies[fileOrDir] = { outputPath: true, copyOptions };
} else {
for (let [inputPath, outputPath] of Object.entries(fileOrDir)) {
Expand Down Expand Up @@ -1215,6 +1226,7 @@ class UserConfig {
globalData: this.globalData,
layoutAliases: this.layoutAliases,
layoutResolution: this.layoutResolution,
autoCopies: this.autoCopies,
passthroughCopies: this.passthroughCopies,

// Liquid
Expand Down
4 changes: 4 additions & 0 deletions src/defaultConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FilterPlugin as InputPathToUrlFilterPlugin } from "./Plugins/InputPathT
import { HtmlTransformer } from "./Util/HtmlTransformer.js";
import TransformsUtil from "./Util/TransformsUtil.js";
import MemoizeUtil from "./Util/MemoizeFunction.js";
import { AutoCopyPlugin } from "./Plugins/AutoCopyPlugin.js";

/**
* @module 11ty/eleventy/defaultConfig
Expand Down Expand Up @@ -130,6 +131,9 @@ export default function (config) {
return ut.transformContent(this.outputPath, content, this);
});

// Requires user configuration, so must run as second-stage
config.addPlugin(AutoCopyPlugin);

return {
templateFormats: ["liquid", "md", "njk", "html", "11ty.js"],
// if your site deploys to a subdirectory, change this
Expand Down
104 changes: 65 additions & 39 deletions test/AutoCopyPluginTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import fs from "node:fs";
import { rimrafSync } from "rimraf";
import { TemplatePath } from "@11ty/eleventy-utils";

import { AutoCopyPlugin } from "../src/Plugins/AutoCopyPlugin.js";
import { TransformPlugin as InputPathToUrlTransformPlugin } from "../src/Plugins/InputPathToUrl.js";
import { default as HtmlBasePlugin } from "../src/Plugins/HtmlBasePlugin.js";
import Eleventy from "../src/Eleventy.js";
Expand All @@ -12,9 +11,9 @@ test("Basic usage", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site-basica", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.png"
});
eleventyConfig.addPassthroughCopy("**/*.png", {
mode: "auto"
})

eleventyConfig.on("eleventy.passthrough", copyMap => {
t.deepEqual(copyMap, {
Expand Down Expand Up @@ -62,9 +61,9 @@ test("More complex image path (parent dir)", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site-basicb", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.png"
});
eleventyConfig.addPassthroughCopy("**/*.png", {
mode: "auto"
})

eleventyConfig.on("eleventy.passthrough", copyMap => {
t.deepEqual(copyMap, {
Expand Down Expand Up @@ -113,9 +112,9 @@ test("No matches", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site2", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.jpeg"
});
eleventyConfig.addPassthroughCopy("**/*.jpeg", {
mode: "auto"
})

eleventyConfig.on("eleventy.passthrough", copyMap => {
t.deepEqual(copyMap, { map: {} })
Expand Down Expand Up @@ -144,8 +143,8 @@ test("Match but does not exist (throws error)", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site3", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.png"
eleventyConfig.addPassthroughCopy("**/*.png", {
mode: "auto"
});

eleventyConfig.on("eleventy.passthrough", copyMap => {
Expand All @@ -167,18 +166,14 @@ test("Match but does not exist (throws error)", async (t) => {
t.is(fs.existsSync("test/stubs-autocopy/_site3/test/index.html"), false);
});

test.after.always("cleanup dirs", () => {
rimrafSync("test/stubs-autocopy/_site3");
});

test("Match but does not exist (no error, using `failOnError: false`)", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site4", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.png",
eleventyConfig.addPassthroughCopy("**/*.png", {
mode: "auto",
failOnError: false,
});
})

eleventyConfig.on("eleventy.passthrough", copyMap => {
t.deepEqual(copyMap, { map: {} })
Expand Down Expand Up @@ -207,9 +202,12 @@ test("Copying dotfiles are not allowed", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site5", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*", // WARNING don’t do this
// copyOptions: { debug: true },
// WARNING: don’t do this
eleventyConfig.addPassthroughCopy("**/*", {
mode: "auto",
copyOptions: {
// debug: true,
}
});

eleventyConfig.on("eleventy.passthrough", copyMap => {
Expand Down Expand Up @@ -242,8 +240,8 @@ test("Using with InputPathToUrl plugin", async (t) => {
configPath: false,
config: function (eleventyConfig) {
// order of addPlugin shouldn’t matter here
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.{html,njk}", // you probably wouldn’t do this
eleventyConfig.addPassthroughCopy("**/*.{html,njk}", {
mode: "auto"
});

eleventyConfig.addPlugin(InputPathToUrlTransformPlugin);
Expand Down Expand Up @@ -281,8 +279,8 @@ test("Using with InputPathToUrl plugin (reverse addPlugin order)", async (t) =>
// order of addPlugin shouldn’t matter here
eleventyConfig.addPlugin(InputPathToUrlTransformPlugin);

eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.{html,njk}", // you probably wouldn’t do this
eleventyConfig.addPassthroughCopy("**/*.{html,njk}", {
mode: "auto"
});

eleventyConfig.on("eleventy.passthrough", copyMap => {
Expand Down Expand Up @@ -316,8 +314,8 @@ test("Use with HtmlBasePlugin usage", async (t) => {
pathPrefix: "yolo",
config: function (eleventyConfig) {
eleventyConfig.addPlugin(HtmlBasePlugin);
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.png"
eleventyConfig.addPassthroughCopy("**/*.png", {
mode: "auto"
});

eleventyConfig.on("eleventy.passthrough", copyMap => {
Expand Down Expand Up @@ -368,8 +366,8 @@ test("Using with InputPathToUrl plugin and HtmlBasePlugin", async (t) => {
pathPrefix: "yolo",
config: function (eleventyConfig) {
// order of addPlugin shouldn’t matter here
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.{html,njk}", // you probably wouldn’t do this
eleventyConfig.addPassthroughCopy("**/*.{html,njk}", {
mode: "auto"
});

eleventyConfig.addPlugin(InputPathToUrlTransformPlugin);
Expand Down Expand Up @@ -405,11 +403,11 @@ test("Multiple addPlugin calls (use both globs)", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site9", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.jpg"
eleventyConfig.addPassthroughCopy("**/*.jpg", {
mode: "auto"
});
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.png"
eleventyConfig.addPassthroughCopy("**/*.png", {
mode: "auto"
});

eleventyConfig.on("eleventy.passthrough", copyMap => {
Expand Down Expand Up @@ -466,8 +464,8 @@ test("Array of globs", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site10", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: ["**/*.jpg", "**/*.png"]
eleventyConfig.addPassthroughCopy(["**/*.jpg", "**/*.png"], {
mode: "auto"
});

eleventyConfig.on("eleventy.passthrough", copyMap => {
Expand Down Expand Up @@ -527,10 +525,10 @@ test("overwrite: false", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site11", {
configPath: false,
config: function (eleventyConfig) {
eleventyConfig.addPlugin(AutoCopyPlugin, {
match: "**/*.png",
eleventyConfig.addPassthroughCopy("**/*.png", {
mode: "auto",
copyOptions: {
overwrite: false
overwrite: false,
}
});

Expand Down Expand Up @@ -571,3 +569,31 @@ test("overwrite: false", async (t) => {
test.after.always("cleanup dirs", () => {
rimrafSync("test/stubs-autocopy/_site11");
});

test("Input -> output remapping not yet supported (throws error)", async (t) => {
let elev = new Eleventy("./test/stubs-autocopy/", "./test/stubs-autocopy/_site12", {
configPath: false,
config: function (eleventyConfig) {
// not yet supported
eleventyConfig.addPassthroughCopy({"**/*.png": "yo"}, {
mode: "auto"
});

eleventyConfig.on("eleventy.passthrough", copyMap => {
t.deepEqual(copyMap, { map: {} })
});

eleventyConfig.addTemplate("test.njk", `<img src="missing.png">`)
},
});

elev.disableLogger();

await t.throwsAsync(async () => {
await elev.write();
}, {
message: `mode: 'auto' does not yet support input -> output (objects) mapping. Please pass a string glob or an Array of string globs!`
});

t.is(fs.existsSync("test/stubs-autocopy/_site12/test/index.html"), false);
});

0 comments on commit ff0b012

Please sign in to comment.