Skip to content

Commit

Permalink
Add bundle transforms support
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Feb 2, 2023
1 parent 5ba451c commit 0a162bb
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 34 deletions.
49 changes: 38 additions & 11 deletions codeManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class CodeManager {
this.name = name;
this.trimOnAdd = true;
this.reset();
this.transforms = [];
}

reset() {
Expand All @@ -76,6 +77,14 @@ class CodeManager {
return ["default"];
}

setTransforms(transforms) {
if(!Array.isArray(transforms)) {
throw new Error("Array expected to setTransforms");
}

this.transforms = transforms;
}

addToPage(pageUrl, code = [], bucket) {
if(!Array.isArray(code) && code) {
code = [code];
Expand Down Expand Up @@ -106,41 +115,59 @@ class CodeManager {
}
}

getForPage(pageUrl, buckets) {
if(!this.pages[pageUrl]) {
debug("No bundle code found for %o on %o, %O", this.name, pageUrl, this.pages);
async runTransforms(str, pageData) {
for (let callback of this.transforms) {
str = await callback.call(
{
page: pageData
},
str
);
}

return str;
}

async getForPage(pageData, buckets) {
let url = pageData.url;
if(!this.pages[url]) {
debug("No bundle code found for %o on %o, %O", this.name, url, this.pages);
return "";
}

buckets = CodeManager.normalizeBuckets(buckets);

debug("Retrieving %o for %o (buckets: %o)", this.name, pageUrl, buckets);
debug("Retrieving %o for %o (buckets: %o)", this.name, url, buckets);
let set = new Set();
for(let b of buckets) {
if(!this.pages[pageUrl][b]) {
if(!this.pages[url][b]) {
// Just continue, if you retrieve code from a bucket that doesn’t exist or has no code, it will return an empty set
continue;
}

for(let entry of this.pages[pageUrl][b]) {
for(let entry of this.pages[url][b]) {
set.add(entry);
}
}

return Array.from(set).join("\n");
let bundleContent = Array.from(set).join("\n");

// returns promise
return this.runTransforms(bundleContent, pageData);
}

writeBundle(pageUrl, buckets, options = {}) {
if(!this.pages[pageUrl]) {
debug("No bundle code found for %o on %o, %O", this.name, pageUrl, this.pages);
async writeBundle(pageData, buckets, options = {}) {
let url = pageData.url;
if(!this.pages[url]) {
debug("No bundle code found for %o on %o, %O", this.name, url, this.pages);
return "";
}

let { output, bundle, write } = options;

buckets = CodeManager.normalizeBuckets(buckets);

let content = this.getForPage(pageUrl, buckets);
let content = await this.getForPage(pageData, buckets);

let writer = new BundleFileOutput(output, bundle);
return writer.writeBundle(content, this.name, write);
Expand Down
7 changes: 3 additions & 4 deletions eleventy.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ function normalizeOptions(options = {}) {
// Plugin defaults
bundles: [], // extra bundles: css, js, and html are guaranteed
toFileDirectory: "bundle",
// post-process
transforms: []
}, options);

options.bundles = Array.from(new Set(["css", "js", "html", ...options.bundles]));
options.bundles = Array.from(new Set(["css", "js", "html", ...(options.bundles || [])]));

return options;
}
Expand All @@ -22,9 +24,6 @@ function eleventyBundlePlugin(eleventyConfig, options = {}) {

options = normalizeOptions(options);

// TODO
// debug("Warning: Currently @11ty/eleventy-plugin-bundle only supports one addPlugin of this plugin per project. Subsequent adds are ignored.");

shortcodesPlugin(eleventyConfig, options);
};

Expand Down
25 changes: 12 additions & 13 deletions eleventy.shortcodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@ const debug = require("debug")("Eleventy:Bundle");
module.exports = function(eleventyConfig, options = {}) {
let managers = {};

if(Array.isArray(options.bundles)) {
options.bundles.forEach(name => {
managers[name] = new CodeManager(name);
options.bundles.forEach(name => {
managers[name] = new CodeManager(name);
managers[name].setTransforms(options.transforms);

// e.g. `css` shortcode to add code to page bundle
// These shortcode names are not configurable on purpose (for wider plugin compatibility)
eleventyConfig.addPairedShortcode(name, function addContent(content, bucket, urlOverride) {
let url = urlOverride || this.page.url;
managers[name].addToPage(url, content, bucket);
return "";
});
// e.g. `css` shortcode to add code to page bundle
// These shortcode names are not configurable on purpose (for wider plugin compatibility)
eleventyConfig.addPairedShortcode(name, function addContent(content, bucket, urlOverride) {
let url = urlOverride || this.page.url;
managers[name].addToPage(url, content, bucket);
return "";
});
}
});

let writeToFileSystem = true;
eleventyConfig.on("eleventy.before", async ({ outputMode }) => {
Expand Down Expand Up @@ -52,7 +51,7 @@ module.exports = function(eleventyConfig, options = {}) {
return OutOfOrderRender.getAssetKey("file", type, bucket);
});

eleventyConfig.addTransform("@11ty/eleventy-bundle", function(content) {
eleventyConfig.addTransform("@11ty/eleventy-bundle", async function(content) {
if((this.page.outputPath || "").endsWith(".html")) {
let render = new OutOfOrderRender(content);
for(let key in managers) {
Expand All @@ -63,7 +62,7 @@ module.exports = function(eleventyConfig, options = {}) {
render.setBundleDirectory(options.toFileDirectory);
render.setWriteToFileSystem(writeToFileSystem);

return render.replaceAll(this.page.url);
return render.replaceAll(this.page);
}

return content;
Expand Down
15 changes: 10 additions & 5 deletions outOfOrderRender.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ class OutOfOrderRender {
this.writeToFileSystem = isWrite;
}

replaceAll(url) {
async replaceAll(pageData) {
let matches = this.findAll();
return matches.map(match => {

let content = await Promise.all(matches.map(match => {
if(typeof match === "string") {
return match;
}
Expand All @@ -65,16 +66,20 @@ class OutOfOrderRender {
throw new Error(`No asset manager found for ${name}. Known keys: ${Object.keys(this.managers)}`);
}
if(type === "get") {
return this.managers[name].getForPage(url, bucket);
// returns promise
return this.managers[name].getForPage(pageData, bucket);
} else if(type === "file") {
return this.managers[name].writeBundle(url, bucket, {
// returns promise
return this.managers[name].writeBundle(pageData, bucket, {
output: this.outputDirectory,
bundle: this.bundleDirectory,
write: this.writeToFileSystem,
});
}
return "";
}).join("");
}));

return content.join("");
}
}

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@11ty/eleventy-plugin-bundle",
"version": "0.0.1",
"version": "1.0.0",
"description": "Little bundles of code, little bundles of joy.",
"main": "eleventy.config.js",
"scripts": {
Expand Down Expand Up @@ -43,6 +43,8 @@
"devDependencies": {
"@11ty/eleventy": "2.0.0-beta.2",
"ava": "^5.1.0",
"postcss": "^8.4.21",
"postcss-nested": "^6.0.0",
"sass": "^1.58.0"
},
"dependencies": {
Expand Down
16 changes: 16 additions & 0 deletions test/stubs/use-transforms/eleventy.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const bundlePlugin = require("../../../");
const postcss = require('postcss');
const postcssNested = require('postcss-nested')

module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(bundlePlugin, {
transforms: [async function(content) {
return new Promise(resolve => {
setTimeout(() => resolve(content), 50);
});
}, async function(content) {
let result = await postcss([postcssNested]).process(content, { from: this.page.inputPath, to: this.page.outputPath })
return result.css;
}]
});
};
6 changes: 6 additions & 0 deletions test/stubs/use-transforms/index.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<style>{% getBundle "css" %}</style>

{%- css %}* { color: blue; }{% endcss %}
{%- css %}* { color: blue; }{% endcss %}
{%- css %}* { color: red; }{% endcss %}
{%- css %}#id { * { color: orange; } }{% endcss %}
10 changes: 10 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,13 @@ test("No bundling", async t => {
</body>
</html>`);
});

test("Use Transforms", async t => {
let elev = new Eleventy("test/stubs/use-transforms/", undefined, {
configPath: "test/stubs/use-transforms/eleventy.config.js"
});
let results = await elev.toJSON();
t.deepEqual(normalize(results[0].content), `<style>* { color: blue; }
* { color: red; }
#id * { color: orange; }</style>`);
});

0 comments on commit 0a162bb

Please sign in to comment.