svg-sprite / svg-sprite

SVG sprites & stacks galore — A low-level Node.js module that takes a bunch of SVG files, optimizes them and bakes them into SVG sprites of several types along with suitable stylesheet resources (e.g. CSS, Sass, LESS, Stylus, etc.)
https://github.com/svg-sprite/svg-sprite
MIT License
1.93k stars 254 forks source link

`--symbol-render-*` (maybe all custom templates) does not work from CLI #796

Open wojciechczerniak opened 1 year ago

wojciechczerniak commented 1 year ago

I think there is a difference how CLI args and JSON config are parsed. Looks like --symbol-render-* does not work.

But maybe I'm missing something. In theory my CLI command is the same as my config file, right?

Scenario 1

With this config file, template and CLI command I'm able to generate PHP enum file:

Config:

{
    "shape": {
        "id": {
            "separator": "__",
            "generator": "%s"
        }
    },
    "mode": {
        "symbol": {
            "dest": "public/svg",
            "sprite": "sprite.svg",
            "render": {
                "php": {
                    "template": "resources/svg/template.mustache",
                    "dest": "../../app/Enums/SvgIcons.php"
                }
            }
        }
    }
}

Template

<?php

enum SvgIcons
{
    {{#shapes}}
    case {{ name }};
    {{/shapes}}
}

Output:

<?php

enum SvgIcons
{
    case HandDrawnColor__CalendarApple;
    case HandDrawnColor__CalendarGoogle;
    case HandDrawnColor__CalendarOutlook;
}

CLI:

svg-sprite --config=svg-sprite.json resources/svg/./**/*.svg

Scenario 2

But when I've tried to replicate this without config file, with CLI only using:

svg-sprite --shape-id-generator="%s" --symbol --symbol-dest="public/svg" --symbol-sprite="sprite.svg" --symbol-render-php --symbol-render-php-template="resources/svg/template.mustache" --symbol-render-php-dest="../../app/Enums/SvgIcons.php" resources/svg/./**/*.svg

It does not work. PHP file is not generated from the template.

Investigation

I think that if "php" render never finds it's way to config object.

https://github.com/svg-sprite/svg-sprite/blob/87e9898be7fcfe3dd3c23ac608e5f8035207c4c8/bin/svg-sprite.js#L72-L74

But symbol.render.* does not have map property defined:

https://github.com/svg-sprite/svg-sprite/blob/87e9898be7fcfe3dd3c23ac608e5f8035207c4c8/bin/config.yaml#L613-L619

Therefore it's not mapped to config and config don't have this additional render template.

XhmikosR commented 1 year ago

PRs welcome. CLI isn't currently tested, any help is welcome there too, see #789.

Also, I assume you are using the latest 2x version. I doubt this could be fixed in 3.x, but please try the beta version too.

chimok commented 5 months ago

Hello @wojciechczerniak,

The cli is totaly broken since 1-2 years. I use this simple script you can easy adjust to your needs. Use a name with .mjs extension because I'm using ESM imports.

#!/usr/bin/env node

import fs from 'fs';
import path from 'path';
import yargs from 'yargs'
import glob from 'fast-glob'
import { hideBin } from 'yargs/helpers'
import SVGSpriter from 'svg-sprite';

const { argv } = yargs(hideBin(process.argv)).scriptName("icon-builder.mjs")
    .usage("Usage: $0 -theme <theme>")
    .option("t", {
        alias: "theme",
        describe: "The name of the wordpress theme directory.",
        demandOption: "The theme name is required.",
        type: "string",
    });

const svgoConfig = {
    "log": "info",
    "shape": {
        "id": {
            "generator": (_name, file) => {
                const fileName = file.basename.slice(0, -4);
                return `${fileName}`;
            }
        },
        "dimension": {
            "maxWidth": 48,
            "maxHeight": 48,
            "attributes": true
        },
        "spacing": {
            "padding": 0
        },
        "transform": [
            {
                "svgo": {
                    "plugins": [
                    ]
                }
            }
        ]
    },
    "svg": {
        "xmlDeclaration": true
    },
    "mode": {
        "symbol": {
            "dest": './',
            "sprite": './web/ico.svg',
            "inline": true,
            "example": {
                "template": "./src/icons-template.html.hbs",
                "dest": `./web/app/themes/${argv.theme}/static/icons.html`
            }
        }
    },
    "variables": {}
};

// eslint-disable-next-line no-console
console.log(`Build icons for theme: ${argv.theme}`);

const spriter = new SVGSpriter(svgoConfig);
const files = glob.sync(`./web/app/themes/${argv.theme}/src/icons/*.svg`);
for (const file of files) {
    spriter.add(file, file, fs.readFileSync(file, 'utf8'));
}

spriter.compile((error, result, _data) => {
    // Run through all files that have been created for the `symbol` mode
    for (const type of Object.values(result.symbol)) {
        // Recursively create directories as needed
        fs.mkdirSync(path.dirname(type.path), { recursive: true });
        // Write the generated resource to disk
        fs.writeFileSync(type.path, type.contents);
    }
});