11ty / eleventy

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

Ability to dynamically generate files, from other files. #2573

Open keithamus opened 2 years ago

keithamus commented 2 years ago

I'm always frustrated when I’m having a super fun time using 11ty and thinking “wow. I love 11ty so much. Everything feels painless”, but then the problem hits.

I’m very lazy and like to avoid writing files to disk unless I really have to. On multiple occasions I’ve found I have a file, let’s say foo.html, and I’d like some sidecar files- maybe foo.css, foo.png and so on. I’d like these files to be generated magically with zero effort on my part, but I’d like to be able to back reference them within my foo.html file under the assumption that they exist.

After a conversation with @zachleat on Twitter we settled on the idea that there could perhaps be an event triggered when Eleventy discovers a file. I think I’d extend that to also being able to emit files from the config, which then also get ingested like a regular file as part of the build.

Describe the solution you'd like

My dream api would be something like:

module.exports = eleventy => {
  eleventy.templateFound(file => {
    const altFile = file.replace('.html', '.png')
    if(path.extname(file) === '.html' && !fs.existsSync(altFile)) {
      eleventy.emitTemplate(altFile, makeData())
    }
  })
}

This way when a template file was discovered during the collection of files, I could emit a newly derived file and add it to the “stack” of files to be built; these new files would go through the regular loading/compiling step (so I could auto generate md files for example). This, I think, could also be useful for generating files based off of data sources, that can still be processed using the template languages like nunjucks:

const locations = require('./data.json')
module.exports = eleventy => {
   for (const location of locations) {
    eleventy.emitTemplate(`locations/${location.name}.md`, `---
tags: ['location']
---

# ${location.name}
…
)
    }
  })
}

Some other example use cases:

Describe alternatives you've considered

Some other alternatives were considered in the twitter conversation, such as using the after event, or using a serverless function.

Snapstromegon commented 2 years ago

To me this sounds a lot like #272 (Official Asset Pipeline). At least IMO it should be under the same feature.

But I definetly agree, an event for discovered and emitted files would be nice. This would also allow to have some kind of custom build metrics monitoring plugin like I already hinted at here.