Skip to content

Adds html-relative Passthrough Copy mode for relative asset references in HTML #3552#3573

Merged
zachleat merged 12 commits into
mainfrom
auto-copy-plugin
Dec 11, 2024
Merged

Adds html-relative Passthrough Copy mode for relative asset references in HTML #3552#3573
zachleat merged 12 commits into
mainfrom
auto-copy-plugin

Conversation

@zachleat

@zachleat zachleat commented Dec 6, 2024

Copy link
Copy Markdown
Member
export default async function(eleventyConfig) {
	// glob here is relative to project root
	eleventyConfig.addPassthroughCopy("content/**/*.mp4", {
		mode: "html-relative"
	});
}

Works great with emulated passthrough copy, too: https://www.11ty.dev/docs/copy/#emulate-passthrough-copy-during-serve

Why (and why not) use this?

Compared with using eleventyConfig.addPassthroughCopy('content/**/*.mp4'),

HtmlRelativeCopy is better because:

  1. it handles relative URLs (and any customizations to permalink) seamlessly without requiring any changes to source content.
    • e.g. <video src="video.mp4"> on template.njk will copy to _site/template/video.mp4 alongside _site/template/index.html
    • e.g. <video src="assets/video.mp4"> on subdir/template.njk will copy to _site/subdir/template/assets/video.mp4 alongside _site/subdir/template/index.html
  2. only copies files that are used by templates.

HtmlRelativeCopy may be worse when:

  1. you aren’t using HTML if your template is not writing an HTML file in output
  2. the reference in your HTML is not found by @11ty/posthtml-urls: https://github.com/11ty/eleventy-posthtml-urls/blob/d3097f44868737627555ebec622b029d7c0b1ab3/lib/defaultOptions.js#L10-L35
  3. it has some build cost, this uses an opt-in posthtml transform (though you’re already feeling this cost if you use the InputPathToUrl, IdAttribute, or HTMLBase plugins)

Restrictions

Some other differences from the usual eleventyConfig.addPassthroughCopy:

  • dot files are filtered from html-relative copy by default (via the dot: false recursive-copy option)
  • source files must be in the current project directory.
  • URLs and any absolute paths are ignored (we may add support for absolute paths later, if folks want it)

Full options list

export default async function(eleventyConfig) {
	// glob or Array of globs to match for copy
	eleventyConfig.addPassthroughCopy("**/*.png", {
		mode: "html-relative",
		paths: [], // additional fallback directories to look for source files
		failOnError: true, // throw an error when a path matches (via `match`) but not found on file system
		copyOptions: { dot: false }, // `recursive-copy` copy options
	});
}

@darthmall

Copy link
Copy Markdown

I have a few questions:

First, in your example with <video src=video.mp4> writing out both _site/template/video.mp4 and _site/template/index.html, where does video.mp4 live? Does it need to live in content/template/video.mp4?

Second, why make this a plugin? I understand wanting to maintain backwards compatibility for the existing passthrough copy function, but couldn't you achieve that by adding options to the passthrough copy function with default values that result in the existing behavior? I feel like having two different ways to copy static assets is going to be a little confusing, especially if the idea is that the built-in one is the one with which people struggle, and the one people probably want because it's more efficient and convenient is a plugin you have to import and add. Personally, I also just find the built-in plugins annoying because it means I have to have extra import statements at the top of my config file for something that is included when I npm install @11ty/eleventy.

Third, when you say "AutoCopy may be worse when you're not using HTML", does that mean when I'm using Markdown?

@Ryuno-Ki

Ryuno-Ki commented Dec 7, 2024

Copy link
Copy Markdown
Contributor

Third, when you say "AutoCopy may be worse when you're not using HTML", does that mean when I'm using Markdown?

You can write to JSON also.

@zachleat

zachleat commented Dec 9, 2024

Copy link
Copy Markdown
Member Author

First, in your example with

Yep! Alternatively there is a paths feature to list directories that can be used as fallback search

Second, why make this a plugin?

Fair point! Let me think about it a bit—it might be more ergonomic to extend the eleventyConfig.addPassthroughCopy method instead!

Third, when you say "AutoCopy may be worse when you're not using HTML", does that mean when I'm using Markdown?

Anything that outputs to HTML is handled by this method (Markdown, Nunjucks, Liquid, 11ty.js, etc etc)! Updated the comment above: you aren’t using HTML your template output format is not .html

@zachleat

zachleat commented Dec 9, 2024

Copy link
Copy Markdown
Member Author

Per @darthmall’s excellent feedback I’ve reworked the API to use eleventyConfig.addPassthroughCopy(glob, { mode: "auto" }) (open to better naming feedback on mode: "auto" not sure if I’m super happy with that). Code samples above have been updated too.

I love this change, thanks for the idea Evan!

(Still open to feedback here!)

A few other naming ideas:

  • mode: "output-relative"
  • mode: "relative"
  • mode: "template-relative"

@wavebeem

Copy link
Copy Markdown

Per @darthmall’s excellent feedback I’ve reworked the API to use eleventyConfig.addPassthroughCopy(glob, { mode: "auto" }) (open to better naming feedback on mode: "auto" not sure if I’m super happy with that). Code samples above have been updated too.

I love this change, thanks for the idea Evan!

(Still open to feedback here!)

A few other naming ideas:

* `mode: "output-relative"`

* `mode: "relative"`

* `mode: "template-relative"`

I finally got around to testing this and had been banging my head on it for like 30 minutes before I thought to check back on this thread and see you're going in a different direction 😅

Couldn't figure out why AutoCopyPlugin was undefined.

"auto" isn't especially specific, and boxes in the API if you want to make a new style in the future (hopefully not, but you never know). The way I'm seeing this mode is... files are statically analyzed from HTML only, right? It feels like a name that reflects the static analysis of HTML might be good. The only issue I see is if you plan additional scanning features... 🤷🏻‍♀️

@zachleat zachleat changed the title Adds AutoCopy plugin #3552 Adds auto Passthrough Copy mode for relative asset references in HTML #3552 Dec 10, 2024
@zachleat zachleat changed the title Adds auto Passthrough Copy mode for relative asset references in HTML #3552 Adds html-relative Passthrough Copy mode for relative asset references in HTML #3552 Dec 11, 2024
@zachleat

Copy link
Copy Markdown
Member Author

Renaming this from AutoCopy to HtmlRelativeCopy (via mode: "html-relative"). Earlier comments edited to reflect new changes!

@zachleat

Copy link
Copy Markdown
Member Author

I finally got around to testing this and had been banging my head on it for like 30 minutes before I thought to check back on this thread and see you're going in a different direction 😅

Couldn't figure out why AutoCopyPlugin was undefined.

Oh no! I’m sorry!

"auto" isn't especially specific, and boxes in the API if you want to make a new style in the future (hopefully not, but you never know). The way I'm seeing this mode is... files are statically analyzed from HTML only, right? It feels like a name that reflects the static analysis of HTML might be good. The only issue I see is if you plan additional scanning features... 🤷🏻‍♀️

I took your suggestion and settled on the html-relative copy name—thanks for the feedback!

@zachleat

Copy link
Copy Markdown
Member Author

Shipping with v3.0.1-alpha.1

@zachleat zachleat merged commit 8bd3b97 into main Dec 11, 2024
@zachleat zachleat deleted the auto-copy-plugin branch December 11, 2024 17:43
@zachleat zachleat added the needs-documentation Documentation for this issue/feature is pending! label Dec 11, 2024
@Reedyn

Reedyn commented Dec 30, 2024

Copy link
Copy Markdown

Any chance to make it detect the files to pass through based on the source rather than the output file?

I organize images in the same directory as the template files but I've overwritten the default markdown image renderer so that it writes out urls to a imgproxy server which converts the local file. The html-relative mode never detects the file since the source file is never directly referenced in the html-files.

If it isn't possible, maybe it would be possible to add detection if the file is referenced in something other than the src-attribute, maybe the data-attributes?


I used to solve this with eleventy-plugin-page-assets, which unfortunately broke with 11ty 3.0

@AleksandrHovhannisyan

Copy link
Copy Markdown
Contributor

Thanks for this! Just shipped it on my site and was able to move my video files so they're co-located with my Markdown blog posts. Much nicer than having to store them all in a global asset folder.

The only pain point was the lack of docs for this feature aside from the release notes and this issue. But that's understandable since it's still in alpha so I assume the docs will be added later.

@bryanfriedman

Copy link
Copy Markdown

Any chance to make it detect the files to pass through based on the source rather than the output file?

I organize images in the same directory as the template files but I've overwritten the default markdown image renderer so that it writes out urls to a imgproxy server which converts the local file. The html-relative mode never detects the file since the source file is never directly referenced in the html-files.

If it isn't possible, maybe it would be possible to add detection if the file is referenced in something other than the src-attribute, maybe the data-attributes?

I used to solve this with eleventy-plugin-page-assets, which unfortunately broke with 11ty 3.0

I'm in exactly the same boat. Would love to see this feature, which looks like #3609 would resolve.

@zachleat zachleat added the feature: 🗄 passthrough copy Related to the passthrough file copy feature label Apr 25, 2025
@zachleat zachleat mentioned this pull request Apr 25, 2025
zachleat added a commit to 11ty/11ty-website that referenced this pull request May 13, 2025
@zachleat

Copy link
Copy Markdown
Member Author

Docs deploying to https://www.11ty.dev/docs/copy/#copy-a-file-alongside-a-template

@bryanfriedman

Copy link
Copy Markdown

Any chance to make it detect the files to pass through based on the source rather than the output file?

I organize images in the same directory as the template files but I've overwritten the default markdown image renderer so that it writes out urls to a imgproxy server which converts the local file. The html-relative mode never detects the file since the source file is never directly referenced in the html-files.

If it isn't possible, maybe it would be possible to add detection if the file is referenced in something other than the src-attribute, maybe the data-attributes?

I used to solve this with eleventy-plugin-page-assets, which unfortunately broke with 11ty 3.0

@Reedyn In case you are still stuck with this problem, just wanted to share that I wrote a custom plugin to handle this case. I submitted a PR too but until it's handled natively, or just for folks who want to use it on an older version, this plugin is out there. Hope it helps you or anyone else who may be interested and stumbles onto this thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature: 🗄 passthrough copy Related to the passthrough file copy feature needs-documentation Documentation for this issue/feature is pending!

Development

Successfully merging this pull request may close these issues.

7 participants