-
Notifications
You must be signed in to change notification settings - Fork 71
/
svgs.js
152 lines (135 loc) · 5.05 KB
/
svgs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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 as resolveTemplate } from '../helpers/template.js';
import { merge } from '../utils/index.js';
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.
*/
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);
/**
* @const {object} developmentSVGsArgs - The predefined `compileSVGs()` options for development.
* @const {object} productionSVGsArgs - The predefined `compileSVGs()` options for production.
*/
export const developmentSVGsArgs = [
developmentMixerOptions,
];
export const productionSVGsArgs = [
productionMixerOptions,
];
/**
* Generates and transforms SVG spritesheets.
*
* @async
* @param {object} [mixerOptions=null] - Customize the Mixer API options.
* If `null`, default production options are used.
* @return {Promise}
*/
export default async function compileSVGs(mixerOptions = null) {
if (mixerOptions == null) {
mixerOptions = productionMixerOptions;
} else if (
mixerOptions !== developmentMixerOptions &&
mixerOptions !== productionMixerOptions
) {
mixerOptions = merge({}, defaultMixerOptions, mixerOptions);
}
/**
* @async
* @param {object} entry - The entrypoint to process.
* @param {string[]} entry.includes - One or more paths to process.
* @param {string} entry.outfile - The file to write to.
* @param {?string} [entry.label] - The task label.
* Defaults to the outfile name.
* @return {Promise}
*/
loconfig.tasks.svgs?.forEach(async ({
includes,
outfile,
label = null
}) => {
if (!label) {
label = basename(outfile || 'undefined');
}
const timeLabel = `${label} compiled in`;
console.time(timeLabel);
try {
if (!Array.isArray(includes)) {
includes = [ includes ];
}
includes = resolveTemplate(includes);
outfile = resolveTemplate(outfile);
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);
message(`${label} compiled`, 'success', timeLabel);
} catch (err) {
message(`Error compiling ${label}`, 'error');
message(err);
notification({
title: `${label} compilation failed 🚨`,
message: `${err.name}: ${err.message}`
});
}
});
};