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

Custom File Extension Handlers #117

Closed
zachleat opened this issue May 10, 2018 · 17 comments
Closed

Custom File Extension Handlers #117

zachleat opened this issue May 10, 2018 · 17 comments
Assignees
Labels
enhancement: favorite Vanity label! The maintainer likes this enhancement request a lot. enhancement

Comments

@zachleat
Copy link
Member

zachleat commented May 10, 2018

Extension to the configuration API that would allow developers to add their own code to handle a new file extension template type.

Some fake code to get the discussion started:

const Vue = require("vue");
const renderer = require("vue-server-renderer").createRenderer();

eleventyConfig.addExtension("vue", function(path, fileContents) {
  return function(data) {
    var app = new Vue({
      template: fileContents,
      data: function() {
        return { data };
      }
    });

    return renderer.renderToString(app);
  };
});

Will process all *.vue files in the --input directory and write the files to --output.

Needs to:

  • Return a repeatable compiled template function (accepts data object)
@zachleat zachleat added enhancement needs-votes A feature request on the backlog that needs upvotes or downvotes. Remove this label when resolved. labels May 10, 2018
@zachleat
Copy link
Member Author

zachleat commented May 10, 2018

This repository is using lodash style issue management for enhancements (see https://twitter.com/samselikoff/status/991395669016436736) This means enhancement issues will now be closed instead of leaving them open.

The enhancement backlog can be found here, please add your 👍 votes to weigh in: https://github.com/11ty/eleventy/issues?utf8=%E2%9C%93&q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc+

@paulrobertlloyd
Copy link
Contributor

paulrobertlloyd commented May 12, 2018

Would this feature mean I could use the existing Markdown template renderer, but with .markdown as the recognised extension instead of .md? In which case, 👍.

@zachleat
Copy link
Member Author

Hmmmmmmmm. Yeah this could likely be extended to do extension aliasing. I reserve the right to create a new issue for this later though 😇

@zachleat
Copy link
Member Author

zachleat commented Feb 5, 2019

@Munter shared tolk https://www.npmjs.com/package/tolk with me which might be very easy very useful crossover with this issue.

https://twitter.com/_munter_/status/1092824532832923653 with

@zachleat
Copy link
Member Author

As exposed in #464, some might want the option to override current implemented file extensions with this method too.

@shreyasminocha
Copy link

Is this on the agenda yet? Seems to be the top issue in needs-votes by a decent margin.

@valtlai
Copy link
Contributor

valtlai commented Nov 5, 2020

Will there be a way to set the permalink from the handler? I want src/main.css to be written in dist/main.css and not dist/main/index.html.

I tried to modify the data in the compile method, but it didn’t have any effect.

The following directory data file could work:

const { extname } = require('path');

exports.eleventyComputed = {
  permalink: ({ page }) => page.filePathStem + extname(page.inputPath)
};

And it actually does if I don’t try to process the template contents in the handler.

@darthmall
Copy link

darthmall commented Nov 14, 2020

In addition to setting permalinks, will custom file extensions be added to collections? I'm thinking about how custom file extension handlers could be used to manage assets (#272). I think to accomplish this, I'd want:

  • processed files added to collections
  • control over the permalink
  • access to the processed file's contents when generating the permalink (for content hashes)

Maybe these could work similarly to JavaScript templates in that they could be a simple function that transforms a file or a class that provides access to more complex configuration.

If I have some vanilla JS in an IIFE that I want to minify, I might just use a function:

eleventyConfig.addExtension("js", async function (path, fileContents) {
  return await terser(fileContents);
});

Given the file "js/global.js", this configuration would output a minified version at "_site/js/global.js".

If I wanted more control, I could create a class to handle transformations.

const crypto = require("crypto");
const path = require("path");

class Scss {
  data(filePath) {
    return {
      assetKey: path.basename(filePath),
      tags: ["_styles"] ,
    };
  }

  render(filePath, fileContents) {
    return sass.renderSync({ file: filePath, ... });
  }

  permalink(data, filePath, transformedContent) {
    let baseName = path.basename(filePath, ".scss"),
      outputPath = path.dirname(filePath);

    // Add a content hash in production for cache busting
    if (process.env.NODE_ENV === "production") {
      const hash = crypto.createHash("md5");
      hash.update(transformedContent);
      baseName += `-${hash.digest("hex").slice(0, 10)`;
    }

    return path.join(outputPath, `${baseName}.css`);
  }
}

And then you just pass the class as the handler for the extension:

eleventyConfig.addExtension("scss", Scss);

One thing this approach doesn't account for is source maps. Whether we're transforming Vue, or SCSS, or just minifying some vanilla JS, we'll probably want source maps.

It could also be that custom extensions aren't a good way to handle asset management of this kind. I've written up a method for managing assets using global data. With the addition of eleventyConfig.addGlobalData in 1.0 (#1280), I think it would be possible to put together a plugin for this method.

@zachleat zachleat added this to Needs triage in Eleventy 1.0 via automation Jun 14, 2021
@zachleat zachleat added this to the Eleventy 1.0.0 milestone Jun 14, 2021
zachleat added a commit that referenced this issue Jun 14, 2021
@zachleat zachleat removed the needs-votes A feature request on the backlog that needs upvotes or downvotes. Remove this label when resolved. label Aug 10, 2021
@zachleat
Copy link
Member Author

Out of the queue, into the milestone!

@zachleat
Copy link
Member Author

This is officially shipped. The all important docs issue is at #2036.

Template Language Plugins automation moved this from Needs triage to Closed Oct 19, 2021
@zachleat
Copy link
Member Author

zachleat commented Jan 3, 2022

Docs are up at https://www.11ty.dev/docs/languages/custom/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement: favorite Vanity label! The maintainer likes this enhancement request a lot. enhancement
Projects
No open projects
Development

No branches or pull requests

10 participants