11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.

Home Page:https://www.11ty.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Expose input, root, source, config path to plugins

MangelMaxime opened this issue · comments

Is your feature request related to a problem? Please describe.

I am working on an Eleventy plugin which aims to provide an ready out of the box template for Eleventy.

In order, to do that I need to know where the root project is so I can copy includes files in it.

My problem is that Eleventy doesn't expose all the information it has to the plugins.

For example, if I use the programmatic API (mainly for the tests) then the provided input path is never exposed to the plugin.

const elev = new Eleventy("./fixtures/menu-2/", "./fixtures/menu-2/_site", {
    configPath: "./fixtures/menu-2/.eleventy.js",
});

This means that the plugin only knows of the process.cwd() but not where the input files are located.

The same problem exist if when using the CLI the user provides an input argument.

Describe the solution you'd like

It would be nice if Eleventy was exposing more information to the plugin.

List of information I have in mind:

  • input
  • root
  • destination
  • config path

Describe alternatives you've considered

I tried to find another way to find the input path but I could not do that.

Additional context

No response

Your 3 best bets are:

  1. Events https://www.11ty.dev/docs/events/#event-arguments
  2. Env variables https://www.11ty.dev/docs/environment-vars/#eleventy-supplied
  3. eleventy global data: https://www.11ty.dev/docs/data-eleventy-supplied/#eleventy-variable

The other thing I would mention is that:

module.exports = function(eleventyConfig) {
  eleventyConfig.addPlugin(eleventyConfig => {
    // eleventyConfig.dir has the resolved values from the config file
  });
};

(https://www.11ty.dev/docs/config/#configuration-options)

I don't know why, in the past I was under the impression that events listener where not awaited. This could lead to a situation where the files where not yet copied. But it seems to be ok now.

I was able to kind of workaround my problem using:

function configFunction(eleventyConfig: any, options?: Options) {
    let isFirstBuild = true;

    eleventyConfig.on("eleventy.before", async (args : any) => {
        if (isFirstBuild) {
            isFirstBuild = false;
            copyIncludesToUserFolder(args);
        } 
    });
}

Args contains the following value:

{
  inputDir: './fixtures/navigation-3/',
  dir: { input: '.', includes: '_includes', data: '_data', output: '_site' },
  runMode: 'build',
  outputMode: 'json',
  incremental: false
}

where inputDir seems to match the path I give to Eleventy via

const elev = new Eleventy(
    "./fixtures/navigation-3/",
    "./fixtures/navigation-3/_site",
    {
        configPath: "./fixtures/navigation-3/.eleventy.js",
    }
);

I still don't have access to the root path computed by Eleventy but it seems like I can use the current working dir and the inputDir to replicate it.

inputDir is not documented on https://www.11ty.dev/docs/events/#eleventy.before. Is the documentation not update to date or should inputDir not be accessible?

I think the inconsistency here is limited to CLI arguments not being reflected in those configuration values—work is moving forward to fix that in #2729.

I don’t think inputDir is what you want there.

given the following config object return:

return {
    dir: {
      input: "myinput",
      output: "myoutput",
    }
  };

it yields the following values in 2.0.0-beta.3:

[inside addPlugin] {
  data: '_data',
  includes: '_includes',
  input: 'myinput',
  output: 'myoutput'
}
[argument to eleventy.before] {
  dir: {
    data: '_data',
    includes: '_includes',
    input: 'myinput',
    output: 'myoutput'
  },
  incremental: false,
  inputDir: '.',
  outputMode: 'fs',
  runMode: 'build'
}

That looks correct to me. If you’re also using CLI arguments, I think home base for that is #2729

I don’t think inputDir is what you want there.

Indeed using inputDir is a workaround because I don't have access to `eleventy.env.root.

What I am looking for is the absolute path for the includes folder.

The way I had in mind to access it was to access the root path and then join includes path to it.

image

But because I don't have access to the root path from the plugin, what I am doing right now is:

export function copyIncludesToUserFolder(args : EleventyBeforeEventArgs) {
	const includesDir = args.dir.includes;
	const destination = path.join(process.cwd(), args.inputDir, includesDir, "nacara");

    // ...
}

function configFunction(eleventyConfig: any, options?: Options) {
    let isFirstBuild = true;

    eleventyConfig.on("eleventy.before", async (args : any) => {
        if (isFirstBuild) {
            isFirstBuild = false;
            copyIncludesToUserFolder(args);
        } 
    });

    // ...
}

what command do you use to run Eleventy?

@zachleat It depends.

When consuming Eleventy as a user (to build a site) I run npx @11ty/eleventy.

But I am also writing unit tests and in this case, I use the AVA test framework and Eleventy programmatic API:

const elev = new Eleventy(
    "./fixtures/navigation-4/",
    "./fixtures/navigation-4/_site",
    {
        configPath: "./fixtures/navigation-4/.eleventy.js",
    }
);

const json = await elev.toJSON();

The project, I am working on is https://github.com/MangelMaxime/eleventy-layout-nacara.

It is still in WIP, but the idea is to provide a plug-in-play solution to had a ready to use layout to an Eleventy project.

The user just need to add eleventyConfig.addPlugin(eleventyLayoutNacara); to their configuration, and then they get access to ready to use layouts, components and filters.

The way it is archived for the layouts and components, is that when Nacara plugin is loaded it will copy these files under <root>/_includes/nacara so the user can access the layouts by adding layout: nacara/layouts/docs.njk to their Markdown files.

Thank you for taking the time to look at my issue, I am aware that I am probably pushing the plugin system of Eleventy a bit far :)

I'm now also using process.cwd() to find the path to the project root from inside a plugin.

@MangelMaxime I think you should join the discussion in this other issue: