Last active
August 7, 2021 09:41
-
-
Save daviddarnes/2d6f2db8c304024db67e0e2be6231916 to your computer and use it in GitHub Desktop.
Create SVG sprites in Eleventy using a directory SVG files as a reference, credit to @patrickxchong and @maxboeck for the performance technique and original implementation respectively
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = (eleventyConfig) => { | |
// ... | |
// Icon Sprite | |
eleventyConfig.addWatchTarget("src/assets/svgs/"); | |
eleventyConfig.on("beforeBuild", svgsprite); | |
eleventyConfig.addNunjucksAsyncShortcode("svgsprite", svgsprite); | |
eleventyConfig.addShortcode("icon", (name) => { | |
return `<svg class="icon icon--${name}" role="img" aria-hidden="true" width="24" height="24"><use xlink:href="#icon-${name}" fill="currentColor"></use></svg>`; | |
}); | |
// ... | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require("fs-extra"); | |
const path = require("path"); | |
const util = require("util"); | |
const glob = require("glob"); | |
const File = require("vinyl"); | |
const svgSprite = require("svg-sprite"); | |
let spriteContent = null; // Placeholder sprite variable | |
let cacheKey = ""; // Placeholder cached key | |
const svgPath = "src/assets/svgs"; // Path for all svgs | |
const cwd = path.resolve(svgPath); | |
// SVG sprite configuration | |
const spriteConfig = { | |
mode: { | |
inline: true, | |
symbol: true, | |
}, | |
shape: { | |
transform: ["svgo"], | |
id: { | |
generator: "icon-%s", | |
}, | |
}, | |
svg: { | |
xmlDeclaration: false, | |
doctypeDeclaration: false, | |
}, | |
}; | |
module.exports = async () => { | |
// Get all SVG files in working directory | |
const getFiles = util.promisify(glob); | |
const files = await getFiles("**/*.svg", { cwd: cwd }); | |
// Use all the SVG file timestamps as a cache key string | |
const newCacheKey = files | |
.map((file) => `${file}:${fs.statSync(`${svgPath}/${file}`).mtimeMs}`) | |
.join("|"); | |
// Return existing sprite in spriteContent if the cache key hasn't changed | |
// otherwise skip return and set a new cache key | |
if (spriteContent && newCacheKey === cacheKey) { | |
return spriteContent; | |
} else { | |
cacheKey = newCacheKey; | |
} | |
// Make a new svgSprite instance with configuration | |
const spriter = new svgSprite(spriteConfig); | |
// Wrap spriter compile function in a Promise | |
const compileSprite = async (args) => { | |
return new Promise((resolve, reject) => { | |
spriter.compile(args, (error, result) => { | |
if (error) { | |
return reject(error); | |
} | |
resolve(result.symbol.sprite); | |
}); | |
}); | |
}; | |
// Add all files to the spriter | |
files.forEach(function (file) { | |
spriter.add( | |
new File({ | |
path: path.join(cwd, file), | |
base: cwd, | |
contents: fs.readFileSync(path.join(cwd, file)), | |
}) | |
); | |
}); | |
// Store contents of the sprite in the spriteContent variable | |
// Return the new sprite | |
const sprite = await compileSprite(spriteConfig.mode); | |
spriteContent = sprite.contents.toString("utf8"); | |
return spriteContent; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
--- | |
<div hidden>{% svgsprite %}</div> | |
{% icon "filename" %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment