Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Pass through copy of asset directory #1540

Closed
rabbaniyon opened this issue Dec 3, 2020 · 8 comments
Closed

Pass through copy of asset directory #1540

rabbaniyon opened this issue Dec 3, 2020 · 8 comments
Labels
education feature: 🗄 passthrough copy Related to the passthrough file copy feature

Comments

@rabbaniyon
Copy link

A blog in posts/first-blog.md contains an image in posts/first-blog.assets/image.png.

By using:

module.exports = function(eleventyConfig) {
 // ...
 eleventyConfig.addPassthroughCopy("posts/**/**/*.png");
}

the directory posts/first-blog/first-blog.assets is copied to _site/posts/first-blog.assets.

Question: how can I set a rule so that it is copied to _site/posts/first-blog/first-blog.assets?

@binyamin
Copy link
Member

binyamin commented Dec 3, 2020

Try this.

module.exports = function(eleventyConfig) {
 // ...
 eleventyConfig.addPassthroughCopy({ "posts/first-blog.assets/image.png": "posts/first-blog/first-blog.assets/"});
}

@rabbaniyon
Copy link
Author

Yes, I have seen this in the documentation.

My question is about a general rule for all files in posts. Consider the following:

posts/
├─ post1.md
├─ post1.assets/
├─ post2.md
├─ post2.assets/
├─ ...
├─ post100.md
├─ post100.assets/

There must be a way without doing it manually.

@Ryuno-Ki
Copy link
Contributor

Ryuno-Ki commented Dec 4, 2020

Hm, perhaps defining it as „template format” and define the permalink URL as data file?

@darekkay
Copy link

Same issue as #379

Another workaround is to have a custom shortcode or filter to rewrite the asset URLs, but it's still not the best solution.

@arrowtype
Copy link

arrowtype commented Jan 27, 2021

@rabbaniyon I really hope this issue can be resolved by something core or official in 11ty, but in the meantime, I found a way to get most of what I wanted for this: permalinks on posts, and images stored next to markdown in my sources.

I’m using the plugin https://github.com/victornpb/eleventy-plugin-page-assets, but due to a small bug in its code, I had to fork it and fix that, then point to the fork in my package.json. (You could point to my fork or the fork used in the PR , but it might make sense to use your own fork, so it isn’t disrupted if someone else deletes or changes their fork in the future ... I don’t really know the best practice in cases like this.

Anyway, my files are now sorted like this (a small compromise was giving up the assets folders):

📁 posts/
  📁 2020-12-15--some-title/
    📄 index.md
    🖼 cover.png
    🖼 image.jpg
  📁 2020-06-18--good-title/
    📄 index.md 
    🖼 cover.png

This is okay for me. It was only a small hassle to move images, and the main things I wanted were my dated folder naming plus (non-dated) permalinks. Of course, I would love for this to be properly supported by 11ty or the 11ty base blog template, because this seems like a very obvious and common way to handle posts with images.

@nhoizey
Copy link
Contributor

nhoizey commented Jan 27, 2021

I had the same need when I started using Eleventy, and finally chose to have the same folders hierarchy in the source as in the build.

Adapting your example, I would have this:

posts/
  📁 2020/
    📁 12/
      📁 15/
        📁 some-title/
          📄 index.md
          🖼 cover.png
          🖼 image.jpg
    📁 06/
      📁 18/
        📁 good-title/
          📄 index.md 
          🖼 cover.png

I use eleventyConfig.addPassthroughCopy('**/*.{jpg,jpeg,png,gif}')) and the default permalink, and it works very well.

@hidegh
Copy link

hidegh commented Feb 14, 2021

The plugin mentioned has some flaws and unfortunately a passthrough will not work with permalinks. So I created a simple copy, that tries to imitate how HUGO handles assets.

The only thing we will need it to render images in lists a bit differently:

  1. if the front matter uses an absolute path to root (starts with /) we just display the image on the given url
  2. if the image is absolute to the content (markdown), we need to prepend the image url with the content's permalink url (this I had to solve also in HUGO)

Also here's the solution with sample posts I played with (not a clean post folder as required, but almost):
11ty-custom.zip

    const path = require("path");
    const fs = require("fs");
    const glob = require ("glob");

    eleventyConfig.addTransform("local-images", function(content, outputPath) {
        // HUGO logic:
        // - if multiple *.md are in a folder (ignoring _index.html) - then no asset-copy over will occure
        // - if single index.html (allowing extra _index.html), then no further sub-dirs will be processed, all sub-dirs and files will be copied (except *.md)
        //
        // Alg:
        // - get all md/html/njk in the directory and sub-dirs, ignoring _index.* (_index.* - could be later used to create list-templates)
        // - if only 1 found = we copy the entire sub-content
        // - otherwise do no copy-over nothing
        
        const template = this;

        console.warn(`TRANSFORM - input: ${template.inputPath}, output: ${outputPath}`);
        
        const outputDir = path.dirname(outputPath);       
        const templateDir = path.dirname(template.inputPath).replace(/^\.\//, "");
        const templateFileName = path.basename(template.inputPath);

        const extensionsRegex = template._config.templateFormats.join(",");
        const mdSearchPattern = path.join(templateDir, `**\\*.{${extensionsRegex}}`);
        const mdIgnorePattern = path.join(templateDir, `**\\_index.{${extensionsRegex}}`);

        const entries = glob.sync(mdSearchPattern, { nodir: true, ignore: mdIgnorePattern });

        // only 1 page template allowed when copying assets
        if (entries.length > 1) {
            console.info(`Skipping copying over files from: ${templateDir} as multiple tempaltes found in directory!`);
            return;
        }

        // copy all hierarchically, except templates
        const fileSearchPattern = path.join(templateDir, `**\\*`);
        const fileIgnorePattern = path.join(templateDir, `**\\*.{${extensionsRegex}}`);

        const filesToCopy = glob.sync(fileSearchPattern, { nodir: true, ignore: fileIgnorePattern });

        for (let filePath of filesToCopy) {
            // strip template dir
            // prepend output dir
            const destPath = path.join(
                outputDir,
                filePath.substr(templateDir.length)
            );

            const destDir = path.dirname(destPath);

            fs.mkdirSync(destDir, { recursive: true });
            fs.copyFileSync(filePath, destPath);
        }

        // keep original content
        return content;
    });

@zachleat
Copy link
Member

zachleat commented Dec 6, 2024

This is solved by the upcoming AutoCopy plugin at #3552. Let’s regroup over there.

@zachleat zachleat closed this as completed Dec 6, 2024
@zachleat zachleat added this to the Eleventy 3.0.1 milestone Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
education feature: 🗄 passthrough copy Related to the passthrough file copy feature
Projects
None yet
Development

No branches or pull requests

8 participants