11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
16.86k stars 487 forks source link

eleventyConfig is not fully set up when adding plugins/filters/transforms via the configuration API #1647

Closed hidegh closed 1 year ago

hidegh commented 3 years ago

Describe the bug

https://www.11ty.dev/docs/config/#using-the-configuration-api

when using configuration api and adding extra filters/transforms, the inputDir property of the eleventyConfig is not set at the moment when filter is added (only avail. when filter is executed via transform tempate = this, template._config), actually anything that we set up in the return value is missing there,

To Reproduce Steps to reproduce the behavior:

create a custom plugin, when adding, try to access some eleventyConfig data that we set via the main .eleventy.js by returning it as an object: https://www.11ty.dev/docs/config/#using-the-configuration-api

main config:

const localPostImagesPlugin = require("./src/plugins/eleventy-hugo-style-local-post-images");

module.exports = function (eleventyConfig) {
    eleventyConfig.addPlugin(localPostImagesPlugin, {});

    return {
        dir: {
            input: "src",
            output: "_site",
            includes: "includes",
            layouts: "includes/layouts",
            data: "data",

            pathPrefix: "/"
        }
    };
}

plugin:

module.exports = function (eleventyConfig, pluginConfigOptions) {

    // eleventyConfig.inputDir is not avail. here

    pluginConfigOptions = Object.assign(
        {
            // defaults
        },
        pluginConfigOptions
    );

    eleventyConfig.addTransform('eleventy-hugo-style-local-post-images', function (content, outputPath) {
        return imgCopier.call(this, content, outputPath);
    })

}

Expected behavior The configured values should be avail there. Assume this approach would be the easiest:

  1. only change we'd need is to have a config(eleventyconfig) function and move all our filter/transform code there,
  2. the eleventy framework then could request the main config module, do all the setup (from the return value) and after call the config.

Screenshots None

Environment:

Additional context Nope

henrycatalinismith commented 3 years ago

Calls to addPlugin() are synchronous and set up the plugin immediately by running its function. So in your example, Eleventy's input directory config isn't available yet because it isn't set yet. Check out the implementation in UserConfig.js.

Since this is all plain JS code which you have full control over, you can pass any data your plugins need to them directly in the options object. I think that's what the options object is for actually! So do this in your .eleventy.js:

module.exports = function (eleventyConfig) {
  const input = "src"
  eleventyConfig.addPlugin(localPostImagesPlugin, { input })
  return {
    dir: {
      input,
    }
  }
}

And now in your plugin you have access to the input dir just like you wanted!

module.exports = function (eleventyConfig, pluginConfigOptions) {
  // eleventyConfig.inputDir is available now as pluginConfigOptions.input
}

To my eyes, this looks to be by design. Eleventy seems to be quite deliberate about having a small and simple API area rather than providing loads of different ways of accomplishing the same thing.

hidegh commented 2 years ago

@hendotcat

Thanx for the answer - what U described is a valid bypass, but it still leaves us open to other problems in the future. As those plugins are / should run with a full eleventyConfig object, this is an issue that should/could have been addressed, especially when plans for v1.0 were created (@zachleat ). Since I do not need other parts of eleventyConfig, I'm ok, but it's a dangerous architectural problem - when writing standalone plugins, such simple bypasses will just generate extra boilerplate code.

zachleat commented 1 year ago

Sorry for the late response here but this works in 1.0.2:

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(function(eleventyConfig) {
    console.log( eleventyConfig.dir );
  })
  return {
    dir: {
      input: "src",
    }
  }
}

I would note that improvements for CLI arguments in eleventyConfig are noted in https://github.com/11ty/eleventy/issues/2729

Thanks y’all!