Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
172 views
in Technique[技术] by (71.8m points)

Create an Eleventy collection from SVG folder

Hello everyone, I created a small SVG iconset and want to show them all rendered from a folder on one page using Eleventy. But at the same time, I would need the SVG code since users should be able to quickly copy the SVG code to the clipboard. There are some plugins for SVG content placement but I cannot use them in combination with an eleventy collection.

I was able to place the SVG code into an eleventy page with eleventy-plugin-svg-contents. But since the iconset will be 200+ icons I really do not want to copy & paste them all individually.


Additionally, I already managed to add all SVG files from a folder to a collection, but since it should be a vector icon set I cannot use image files.

{% for icon in collections.iconGallery %}
  <figure>
    <img class="m-2 w-6 h-6" src="{{ icon }}" alt="" />
  </figure>
{% endfor %}

The following thing I would like to achieve:

  • Put all SVG icon-files in one folder
  • Create a collection of all SVG files in that folder
  • Show rendered SVG content (no <img> tag)
  • Show name (filename without extension) and SVG code

For testing purposes I will provide three icons as SVG code examples:

<!-- annotation.svg -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7 8H17M7 12H12M16.8284 17H19C20.1046 17 21 16.1046 21 15V6C21 4.89543 20.1046 4 19 4H5C3.89543 4 3 4.89543 3 6V15C3 16.1046 3.89543 17 5 17H7.17157C7.70201 17 8.21071 17.2107 8.58579 17.5858L10.5858 19.5858C11.3668 20.3668 12.6332 20.3668 13.4142 19.5858L15.4142 17.5858C15.7893 17.2107 16.298 17 16.8284 17Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>

<!-- briefcase.svg -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 7H5C3.89543 7 3 7.89543 3 9V13M8 7V5C8 3.89543 8.89543 3 10 3H14C15.1046 3 16 3.89543 16 5V7M8 7H16M16 7H19C20.1046 7 21 7.89543 21 9V13M3 13V19C3 20.1046 3.89543 21 5 21H19C20.1046 21 21 20.1046 21 19V13M3 13H8M21 13H16M8 13H16M8 13V15M8 13V11M16 13V11M16 13V15" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>

<!-- calendar.svg -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M4 9V19C4 20.1046 4.89543 21 6 21H18C19.1046 21 20 20.1046 20 19V9M4 9V7C4 5.89543 4.89543 5 6 5H8M4 9H20M20 9V7C20 5.89543 19.1046 5 18 5H16M16 5V3M16 5H8M8 3V5" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>

I hope my question was clear enough and if you have any questions let me know in the comments. Thanks to everyone in advance.

question from:https://stackoverflow.com/questions/65846580/create-an-eleventy-collection-from-svg-folder

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I would suggest an alternate approach using JavaScript data files. Since you have full access to the file system through Node, you can just manually parse the folder into an array with all the information you need, including the SVG source.

Quick and dirty, might need some adjustments:

// _data/icons.js
const fg = require('fast-glob');
const path = require('path');
const fs = require('fs');

module.exports = function() {
    return new Promise(async (resolve, reject) => {
        const iconFolder = path.resolve(__dirname, '../path/to/your/icon/folder/');
        const svgIcons = await fg('**/*.svg', { cwd: iconFolder };
        const iconData = await Promise.all(svgIcons.map(async (name) => {
            const nameWithoutExtension = path.parse(name).name;
            const source = fs.readFileSync(path.resolve(iconFolder, name), { encoding: 'utf8' });
            const sourceWithClass = source.replace('<svg', '<svg class="my-custom-class"');
            return { name, source, sourceWithClass, nameWithoutExtension };
        }));
        resolve(iconData);
    });
};

This data file returns an array of objects with the name (or path relative to the icon base folder, if there are subdirectories) and source of each SVG icon in the icon folder. Then you can iterate through that in your template and display the name and sources accordingly.

Note the example above uses fast-glob, though you can of course also manually iterate through the files in the folder using fs.

The same should be possible using collections, since you can put any data strcuture you want in a collection now.

Accessing the data

Eleventy automatically parses data file and makes them available to your templates. So you can access the icon data like this in any template (using Nunjucks syntax as an example):

{% for icon in icons %}
    <figure>
        {# output the svg source code including the added class. the safe filter is necessary to prevent nunjucks from escaping the SVG code  #}
        {{ icon.sourceWithClass | safe }}
        {# output the file name (excluding the extension) #}
        <figcaption>{{ icon.nameWithoutExtension }}</figcaption>
    </figure>
{% endfor %}

Note that the variable name used to access the data (here: icons) depends on the name of the data file. See the documentation for details.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...