mirror of
https://github.com/locomotivemtl/locomotive-boilerplate.git
synced 2026-01-15 00:55:08 +08:00
Fix svg-mixer support for sub-directories
By default, svg-mixer only uses the SVG's file name as its ID. If any SVG files are stored in sub-directories, that information is ignored in the assembled spritesheet. This is problematic since context is lost (the sub-directory's name) and risks duplicate symbol IDs. This commit introduces a new NPM dependency, `common-path` to resolve the longest common base path, and uses a dependency of `svg-mixer` named `url-slug` in order to prefix the directory name.
This commit is contained in:
@@ -1,21 +1,36 @@
|
||||
import loconfig from '../helpers/config.js';
|
||||
import glob, { supportsGlob } from '../helpers/glob.js';
|
||||
import message from '../helpers/message.js';
|
||||
import notification from '../helpers/notification.js';
|
||||
import resolve from '../helpers/template.js';
|
||||
import { resolve as resolveTemplate } from '../helpers/template.js';
|
||||
import { merge } from '../utils/index.js';
|
||||
import { basename } from 'node:path';
|
||||
import {
|
||||
basename,
|
||||
dirname,
|
||||
extname,
|
||||
resolve,
|
||||
} from 'node:path';
|
||||
import commonPath from 'common-path';
|
||||
import mixer from 'svg-mixer';
|
||||
import slugify from 'url-slug';
|
||||
|
||||
const basePath = loconfig?.paths?.svgs?.src
|
||||
? resolve(loconfig.paths.svgs.src)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @const {object} defaultMixerOptions - The default shared Mixer options.
|
||||
* @const {object} developmentMixerOptions - The predefined Mixer options for development.
|
||||
* @const {object} productionMixerOptions - The predefined Mixer options for production.
|
||||
* @const {object} defaultMixerOptions - The default shared Mixer options.
|
||||
*/
|
||||
export const defaultMixerOptions = {
|
||||
spriteConfig: {
|
||||
usages: false,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const {object} developmentMixerOptions - The predefined Mixer options for development.
|
||||
* @const {object} productionMixerOptions - The predefined Mixer options for production.
|
||||
*/
|
||||
export const developmentMixerOptions = Object.assign({}, defaultMixerOptions);
|
||||
export const productionMixerOptions = Object.assign({}, defaultMixerOptions);
|
||||
|
||||
@@ -74,10 +89,52 @@ export default async function compileSVGs(mixerOptions = null) {
|
||||
includes = [ includes ];
|
||||
}
|
||||
|
||||
includes = resolve(includes);
|
||||
outfile = resolve(outfile);
|
||||
includes = resolveTemplate(includes);
|
||||
outfile = resolveTemplate(outfile);
|
||||
|
||||
const result = await mixer(includes, mixerOptions);
|
||||
if (supportsGlob && basePath) {
|
||||
includes = await glob(includes);
|
||||
includes = [ ...new Set(includes) ];
|
||||
|
||||
const common = commonPath(includes);
|
||||
if (common.commonDir) {
|
||||
common.commonDir = resolve(common.commonDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the `<symbol id>` attribute and prefix any
|
||||
* SVG files in subdirectories according to the paths
|
||||
* common base path.
|
||||
*
|
||||
* Example for SVG source path `./assets/images/sprite`:
|
||||
*
|
||||
* | Path | ID |
|
||||
* | ------------------------------------ | --------- |
|
||||
* | `./assets/images/sprite/foo.svg` | `foo` |
|
||||
* | `./assets/images/sprite/baz/qux.svg` | `baz-qux` |
|
||||
*
|
||||
* @param {string} path - The absolute path to the file.
|
||||
* @param {string} [query=''] - A query string.
|
||||
* @return {string} The symbol ID.
|
||||
*/
|
||||
mixerOptions.generateSymbolId = (path, query = '') => {
|
||||
let dirName = dirname(path)
|
||||
.replace(common.commonDir ?? basePath, '')
|
||||
.replace(/^\/|\/$/, '')
|
||||
.replace('/', '-');
|
||||
if (dirName) {
|
||||
dirName += '-';
|
||||
}
|
||||
|
||||
const fileName = basename(path, extname(path));
|
||||
const decodedQuery = decodeURIComponent(decodeURIComponent(query));
|
||||
return `${dirName}${fileName}${slugify(decodedQuery)}`;
|
||||
};
|
||||
}
|
||||
|
||||
const result = await mixer(includes, {
|
||||
...mixerOptions,
|
||||
});
|
||||
|
||||
await result.write(outfile);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user