@videinfra/static-website-builder 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [2.2.0] - 2026-03-06
8
+ ### Changed
9
+ - Updated dependencies
10
+
7
11
  ## [2.1.0] - 2026-03-04
8
12
  ### Changed
9
13
  - Updated gulp-sass to use sass-embedded instead of sass
@@ -26,7 +26,15 @@ export const javascripts = {
26
26
  },
27
27
  ],
28
28
  };
29
- export const stylesheets = {};
29
+ export const stylesheets = {
30
+ // Overwriting to test that source maps are generated
31
+ production: {
32
+ sourcemaps: {
33
+ init: {},
34
+ write: {},
35
+ },
36
+ },
37
+ };
30
38
  export const sizereport = false;
31
39
 
32
40
  export const plugins = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@videinfra/static-website-builder",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Customizable static site project builder",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -29,14 +29,14 @@
29
29
  "dependencies": {
30
30
  "@csstools/postcss-nested-calc": "^5.0.0",
31
31
  "@rollup/plugin-replace": "^6.0.3",
32
- "autoprefixer": "^10.4.23",
32
+ "autoprefixer": "^10.4.27",
33
33
  "browser-sync": "^3.0.4",
34
- "chalk": "4.1.2",
34
+ "chalk": "5.6.2",
35
35
  "chokidar": "^5.0.0",
36
36
  "cross-env": "^10.1.0",
37
37
  "cssnano": "^7.1.2",
38
- "del": "^6.0.0",
39
- "dotenv": "^17.2.3",
38
+ "del": "^8.0.1",
39
+ "dotenv": "^17.3.1",
40
40
  "gulp": "^5.0.1",
41
41
  "gulp-cached": "^1.1.1",
42
42
  "gulp-data": "^1.3.1",
@@ -46,19 +46,17 @@
46
46
  "gulp-ignore": "^3.0.0",
47
47
  "gulp-plumber": "^1.2.1",
48
48
  "gulp-postcss": "^10.0.0",
49
- "gulp-sass": "^5.1.0",
50
49
  "gulp-sitemap": "^8.0.0",
51
50
  "gulp-sizereport": "^1.2.1",
52
- "gulp-sourcemaps": "^2.6.5",
53
- "gulp-svgmin": "^4.1.0",
51
+ "gulp-sourcemaps": "^3.0.0",
54
52
  "gulp-svgstore": "^9.0.0",
55
53
  "lodash.clone": "^4.3.2",
56
54
  "lodash.some": "^4.2.2",
57
- "map-stream": "^0.1.0",
58
55
  "minimist": "^1.2.8",
59
56
  "nano-memoize": "3.0.16",
60
- "rolldown": "^1.0.0-rc.1",
57
+ "rolldown": "^1.0.0-rc.7",
61
58
  "sass-embedded": "^1.97.3",
59
+ "svgo": "^4.0.1",
62
60
  "through": "^2.3.8",
63
61
  "twig": "^1.17.1"
64
62
  },
@@ -1,7 +1,7 @@
1
- import del from 'del';
1
+ import { deleteAsync } from 'del';
2
2
  import { getTaskConfig } from '../../lib/get-config.js';
3
3
 
4
4
  export function beforeBuild(callback) {
5
5
  const patterns = getTaskConfig('clean', 'patterns');
6
- return del(patterns, { force: true });
6
+ return deleteAsync(patterns, { force: true }).then(() => callback());
7
7
  }
@@ -42,16 +42,9 @@ export default function preprocessIconsConfig (config, fullConfig) {
42
42
  }
43
43
 
44
44
  // Use function to output svgmin configuration
45
- // Add ID attribute transformation
46
45
  config.svgmin = function getSVGMinOptions (file) {
47
- var prefix = path.basename(file.relative, path.extname(file.relative));
48
46
  return {
49
- plugins: [{
50
- cleanupIDs: {
51
- prefix: prefix + '-',
52
- minify: true
53
- }
54
- }].concat(svgmin)
47
+ plugins: [].concat(svgmin)
55
48
  }
56
49
  };
57
50
  }
@@ -1,7 +1,7 @@
1
1
  import gulp from 'gulp';
2
2
  import gulpif from 'gulp-if';
3
3
  import svgstore from 'gulp-svgstore';
4
- import svgmin from 'gulp-svgmin';
4
+ import svgmin from '../../vendor/gulp-svgmin/src/index.js';
5
5
  import nanomemoize from 'nano-memoize';
6
6
 
7
7
  import globs from './../../lib/globs-helper.js';
@@ -18,40 +18,51 @@ test('Multiple TWIG templates rendered', () => {
18
18
 
19
19
  test('SASS variable test', () => {
20
20
  return fsPromises.readFile(path.resolve(publicPath, 'assets/stylesheets/variable-test.css'), { encoding: 'utf8' }).then((css) => {
21
- expect(css).toBe('main{background:#fff;color:#222}');
21
+ expect(css.startsWith('main{background:#fff;color:#222}')).toBe(true);
22
22
  });
23
23
  });
24
24
 
25
25
  test('SASS import test', () => {
26
26
  return fsPromises.readFile(path.resolve(publicPath, 'assets/stylesheets/import-test.css'), { encoding: 'utf8' }).then((css) => {
27
- expect(css).toBe('.btn{background:#222;color:#fff}');
27
+ expect(css.startsWith('.btn{background:#222;color:#fff}')).toBe(true);
28
28
  });
29
29
  });
30
30
 
31
31
  test('SASS sub-folder import test', () => {
32
32
  return fsPromises.readFile(path.resolve(publicPath, 'assets/stylesheets/sub-folder/import-test.css'), { encoding: 'utf8' }).then((css) => {
33
- expect(css).toBe('.btn{background:#222;color:#fff}');
33
+ expect(css.startsWith('.btn{background:#222;color:#fff}')).toBe(true);
34
34
  });
35
35
  });
36
36
 
37
37
  test('SASS autoprefixer test', () => {
38
38
  return fsPromises.readFile(path.resolve(publicPath, 'assets/stylesheets/autoprefixer-test.css'), { encoding: 'utf8' }).then((css) => {
39
- expect(css).toBe('main{clip-path:polygon(0 0,100% 0,100% 100%,0 100%)}');
39
+ expect(css.startsWith('main{clip-path:polygon(0 0,100% 0,100% 100%,0 100%)}')).toBe(true);
40
40
  });
41
41
  });
42
42
 
43
43
  test('CSS nano ignore test', () => {
44
44
  return fsPromises.readFile(path.resolve(publicPath, 'assets/stylesheets/ignore-test.css'), { encoding: 'utf8' }).then((css) => {
45
- expect(css).toBe(':root{--yes: ;--no:initial}');
45
+ expect(css.startsWith(':root{--yes: ;--no:initial}')).toBe(true);
46
46
  });
47
47
  });
48
48
 
49
49
  test('CSS nano nested calc test', () => {
50
50
  return fsPromises.readFile(path.resolve(publicPath, 'assets/stylesheets/nested-calc-test.css'), { encoding: 'utf8' }).then((css) => {
51
- expect(css).toBe('body{padding-top:calc(10vw + 15vh)}');
51
+ expect(css.startsWith('body{padding-top:calc(10vw + 15vh)}')).toBe(true);
52
52
  });
53
53
  });
54
54
 
55
+ test('CSS has sourcemap URL', () => {
56
+ return fsPromises.readFile(path.resolve(publicPath, 'assets/stylesheets/nested-calc-test.css'), { encoding: 'utf8' }).then((css) => {
57
+ expect(css.includes('sourceMappingURL=')).toBe(true);
58
+ });
59
+ });
60
+
61
+ test('CSS sourcemap generated', () => {
62
+ expect.assertions(1);
63
+ return expect(fsPromises.access(path.resolve(publicPath, 'assets/stylesheets/nested-calc-test.css.map'))).resolves.toBe(undefined);
64
+ });
65
+
55
66
  test('Font file woff copied', () => {
56
67
  expect.assertions(1);
57
68
  return expect(fsPromises.access(path.resolve(publicPath, 'assets/fonts/font.woff'))).resolves.toBe(undefined);
@@ -139,7 +150,7 @@ test('currentPagePath available in templates', () => {
139
150
 
140
151
  test('icons generated', () => {
141
152
  return fsPromises.readFile(path.resolve(publicPath, 'assets/images/icons.svg'), { encoding: 'utf8' }).then((svg) => {
142
- expect(svg.indexOf('<symbol id="example-arrow">')).not.toBe(-1);
153
+ expect(svg.indexOf('<symbol id="example-arrow" viewBox="0 0 20 20">')).not.toBe(-1);
143
154
  });
144
155
  });
145
156
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  import path from 'path';
7
7
  import { Transform } from 'stream';
8
- import picocolors from 'picocolors';
8
+ import chalk from 'chalk';
9
9
  import PluginError from 'plugin-error';
10
10
  import replaceExtension from 'replace-ext';
11
11
  import stripAnsi from 'strip-ansi';
12
- import clonedeep from 'lodash.clonedeep';
12
+ import cloneDeep from 'lodash/cloneDeep.js';
13
13
  import sassStingify from './sass-stringify.js';
14
14
 
15
15
  const PLUGIN_NAME = 'gulp-sass';
@@ -36,7 +36,7 @@ const filePush = (file, css, callback) => {
36
36
  const handleError = (error, file, callback) => {
37
37
  const filePath = (error.file === 'stdin' ? file.path : error.file) || file.path;
38
38
  const relativePath = path.relative(process.cwd(), filePath);
39
- const message = `${picocolors.underline(relativePath)}\n${error.formatted}`;
39
+ const message = `${chalk.underline(relativePath)}\n${error.formatted}`;
40
40
 
41
41
  error.messageFormatted = message;
42
42
  error.messageOriginal = error.message;
@@ -69,7 +69,7 @@ const gulpSass = (options) => {
69
69
  return;
70
70
  }
71
71
 
72
- const opts = clonedeep(options || {});
72
+ const opts = cloneDeep(options || {});
73
73
  let source = file.contents.toString();
74
74
 
75
75
  // Stringiyfy variables
@@ -0,0 +1,3 @@
1
+ {
2
+ "presets": [["@babel/preset-env", {"targets": {"node": "12"}}]]
3
+ }
@@ -0,0 +1,16 @@
1
+ # editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ indent_style = space
6
+ indent_size = 4
7
+ end_of_line = lf
8
+ charset = utf-8
9
+ trim_trailing_whitespace = true
10
+ insert_final_newline = true
11
+
12
+ [*.md]
13
+ indent_size = 2
14
+
15
+ [package.json]
16
+ indent_size = 2
@@ -0,0 +1,80 @@
1
+ # 5.0.0
2
+
3
+ * Kaspars Zuks: changed SVGO version to 4.0.0
4
+
5
+ # 4.1.0
6
+
7
+ * Bump svgo to v2.7.0. (thanks to @djphan)
8
+
9
+ # 4.0.1
10
+
11
+ * Move lodash.clonedeep into dependencies, fixes #120 (thanks to @donmahallem)
12
+
13
+ # 4.0.0
14
+
15
+ * Bump svgo to v2.3.1. (thanks to @JohnAlbin)
16
+ * Drop node 10 support.
17
+ * Replace eslint-config-cssnano with xo.
18
+ * Update babel to v7 and ava to v3 (thanks to @JohnAlbin)
19
+ * Update dependencies.
20
+
21
+ # 3.0.0
22
+
23
+ * Bump svgo to v1.3.2.
24
+ * Drop node 8 support.
25
+ * Update dependencies.
26
+
27
+ # 2.2.0
28
+
29
+ * Bump svgo to v1.2.1. (thanks to @ekfuhrmann)
30
+
31
+ # 2.1.0
32
+
33
+ * Bump svgo to v1.1.x.
34
+ * Update babel-dependencies (but not yet to v7).
35
+
36
+ # 2.0.0
37
+
38
+ * Bump svgo to v1.0.x. (thanks to @theverything)
39
+ * Drop dependency on deprecated 'gulp-util'. (thanks to @TheDancingCode)
40
+ * Drop support for old node version.
41
+
42
+ # 1.2.4
43
+
44
+ * Fixed a regression with the per-file options. (thanks to @Odrin)
45
+
46
+ # 1.2.3
47
+
48
+ * Bump svgo to v0.7.x.
49
+
50
+ # 1.2.2
51
+
52
+ * Now compiled with babel 6.
53
+
54
+ # 1.2.1
55
+
56
+ * Bump svgo to v0.6.x.
57
+
58
+ # 1.2.0
59
+
60
+ * Adds the ability to pass per-file objects. (thanks to @w0rm)
61
+
62
+ # 1.1.2
63
+
64
+ * Update code style.
65
+
66
+ # 1.1.1
67
+
68
+ * Update documentation.
69
+
70
+ # 1.1.0
71
+
72
+ * Refactor internals.
73
+
74
+ # 1.0.0
75
+
76
+ * svgmin takes an options object now, instead of a list of plugins.
77
+
78
+ # 0.4.8
79
+
80
+ * Bump svgo to v0.5.
@@ -0,0 +1,22 @@
1
+ Copyright (c) Ben Briggs <beneb.info@gmail.com> (https://beneb.info)
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,166 @@
1
+ # gulp-svgmin
2
+
3
+ [![Build Status](https://travis-ci.org/ben-eb/gulp-svgmin.svg?branch=master)][travis-status]
4
+ [![NPM version](https://badge.fury.io/js/gulp-svgmin.svg)][npm-status]
5
+ [![Dependency Status](https://david-dm.org/ben-eb/gulp-svgmin.svg)][deps-status]
6
+
7
+ > A [Gulp][gulp-url] plugin to minify SVG files with [svgo-url].
8
+
9
+ *If you have any difficulties with the output of this plugin, please use the [SVGO tracker][svgo-bugs].*
10
+
11
+
12
+ ## Install
13
+
14
+ With [npm][npm-url] do:
15
+
16
+ ```
17
+ npm install gulp-svgmin
18
+ ```
19
+
20
+ ## Example
21
+
22
+ ```js
23
+ import { src, dest } from 'gulp';
24
+ import svgmin from 'gulp-svgmin';
25
+
26
+ const defaultTask = () =>
27
+ src('logo.svg')
28
+ .pipe(svgmin())
29
+ .pipe(dest('./out'));
30
+
31
+ export default defaultTask;
32
+ ```
33
+
34
+ ## Configuration file
35
+
36
+ By default, `gulp-svgmin` loads options from a `svgo.config.js` file in your project. See the [svgo’s configuration docs][svgo-config] for more info on how to write one.
37
+
38
+ You can control which directory `svgo` searches for `svgo.config.js` with the `cwd` option. Or you can use a different file name with the `configFile` option.
39
+
40
+ ```js
41
+ import { src, dest } from 'gulp';
42
+ import svgmin from 'gulp-svgmin';
43
+
44
+ const defaultTask = () =>
45
+ src('logo.svg')
46
+ .pipe(svgmin({
47
+ // Specify an absolute directory path to
48
+ // search for the config file.
49
+ cwd: '/users/admin/project/assets',
50
+ // This path is relative to process.cwd()
51
+ // or the 'cwd' option.
52
+ configFile: 'images/svg/config.js',
53
+ }))
54
+ .pipe(dest('./out'));
55
+
56
+ export default defaultTask;
57
+ ```
58
+
59
+ ## Options
60
+
61
+ Instead of using a config file, you can pass an object of svgo’s options to the `gulp-svgmin` plugin. You will need to provide the config in comma separated objects, like the example below.
62
+
63
+ ```js
64
+ const defaultTask = () =>
65
+ src('logo.svg')
66
+ .pipe(svgmin({
67
+ // Ensures the best optimization.
68
+ multipass: true,
69
+ js2svg: {
70
+ // Beutifies the SVG output instead of
71
+ // stripping all white space.
72
+ pretty: true,
73
+ indent: 2,
74
+ },
75
+ // Alter the default list of plugins.
76
+ plugins: [
77
+ // You can enable a plugin with just its name.
78
+ 'sortAttrs',
79
+ {
80
+ name: 'removeViewBox',
81
+ // Disable a plugin by setting active to false.
82
+ active: false,
83
+ },
84
+ {
85
+ name: 'cleanupIDs',
86
+ // Add plugin options.
87
+ params: {
88
+ minify: true,
89
+ }
90
+ },
91
+ ],
92
+ }))
93
+ .pipe(dest('./out'));
94
+ ```
95
+
96
+ You can view the [full list of plugins here][svgo-plugins].
97
+
98
+ By default, the plugins list given to the gulp plugin will alter the default list of svgo plugins. Optionally, you can specify your plugins and set the `full` flag to `true` to indicate that your plugins list should not be merged with the default list of plugins.
99
+
100
+ ```js
101
+ const defaultTask = () =>
102
+ src('logo.svg')
103
+ .pipe(svgmin({
104
+ multipass: true,
105
+ // The plugins list is the full list of plugins
106
+ // to use. The default list is ignored.
107
+ full: true,
108
+ plugins: [
109
+ 'removeDoctype',
110
+ 'removeComments',
111
+ 'sortAttrs',
112
+ // ...
113
+ ],
114
+ }))
115
+ .pipe(dest('./out'));
116
+ ```
117
+
118
+ ## Per-file options
119
+
120
+ To have per-file options, pass a function, that receives `file` object and
121
+ returns `svgo` options. For example, if you need to prefix ids with filenames
122
+ to make them unique before combining svgs with [gulp-svgstore][gulp-svgostore]:
123
+
124
+ ```js
125
+ const defaultTask = () =>
126
+ src('src/*.svg')
127
+ .pipe(svgmin(function getOptions(file) {
128
+ const prefix = path.basename(
129
+ file.relative,
130
+ path.extname(file.relative)
131
+ );
132
+ return {
133
+ plugins: [
134
+ {
135
+ name: 'cleanupIDs',
136
+ parmas: {
137
+ prefix: prefix + '-',
138
+ minify: true,
139
+ },
140
+ },
141
+ ],
142
+ };
143
+ }))
144
+ .pipe(svgstore())
145
+ .pipe(dest('./dest'));
146
+ ```
147
+
148
+ ## Contributing
149
+
150
+ Pull requests are welcome. If you add functionality, then please add unit tests to cover it.
151
+
152
+ ## License
153
+
154
+ MIT © [Ben Briggs](https://beneb.info)
155
+
156
+
157
+ [travis-status]: https://travis-ci.org/ben-eb/gulp-svgmin
158
+ [deps-status]: https://david-dm.org/ben-eb/gulp-svgmin
159
+ [npm-status]: https://badge.fury.io/js/gulp-svgmin
160
+ [npm-url]: https://npmjs.org/package/gulp-svgmin
161
+ [gulp-url]: https://github.com/gulpjs/gulp
162
+ [gulp-svgostore]: https://github.com/w0rm/gulp-svgstore
163
+ [svgo-url]: https://github.com/svg/svgo
164
+ [svgo-bugs]: https://github.com/svg/svgo/issues
165
+ [svgo-config]: https://github.com/svg/svgo#configuration
166
+ [svgo-plugins]: https://github.com/svg/svgo#built-in-plugins
@@ -0,0 +1,126 @@
1
+ import cloneDeep from 'lodash/cloneDeep.js';
2
+ import {loadConfig} from 'svgo';
3
+
4
+ // To prevent multiple scans of the disk for a svgo.config.js file, keep its
5
+ // data in module scope.
6
+ const cache = {};
7
+
8
+ // Load the config from svgo.config.js.
9
+ const loadConfigFromCache = async (configFile, cwd) => {
10
+ if (configFile !== null) {
11
+ // Look for the config in the specified file. loadConfig() will
12
+ // require() the file, which caches it for us.
13
+ return loadConfig(configFile, cwd);
14
+ }
15
+
16
+ // Since no configFile was given, let loadConfig() find a file for us.
17
+
18
+ // If the config file is not in our module cache, look for it on disk.
19
+ if (!(cwd in cache)) {
20
+ // Any usage of loadConfig() with the same cwd will return the same
21
+ // file's config. Store the resulting config in our module cache.
22
+ cache[cwd] = await loadConfig(null, cwd);
23
+ }
24
+
25
+ return cache[cwd];
26
+ };
27
+
28
+ export const getSvgoConfig = async function (
29
+ options = null,
30
+ doDeepClone = false
31
+ ) {
32
+ // Construct the svgo config from the given options.
33
+ let config = {
34
+ ...options,
35
+ };
36
+
37
+ // Get the options that are for this gulp plugin and not for svgo.
38
+ const pluginOptions = {
39
+ full: Boolean(config.full),
40
+ configFile: config.configFile || null,
41
+ cwd: config.cwd || process.cwd(),
42
+ };
43
+ delete config.full;
44
+ delete config.configFile;
45
+ delete config.cwd;
46
+
47
+ // If the options.full flag is specified, then the given options are
48
+ // considered to be the full svgo config.
49
+ if (pluginOptions.full) {
50
+ return config;
51
+ }
52
+
53
+ // Extract the svgo plugins list from the config as we will need to handle
54
+ // them specially later.
55
+ const plugins = config.plugins || [];
56
+ delete config.plugins;
57
+
58
+ const loadedConfig = await loadConfigFromCache(
59
+ pluginOptions.configFile,
60
+ pluginOptions.cwd
61
+ );
62
+
63
+ // Merge the given config with the config loaded from file. (If no
64
+ // config file was found, svgo's loadConfig() returns null.)
65
+ if (loadedConfig) {
66
+ config = {
67
+ // Since gulp-svgmin allows a function to modify config per-file, we
68
+ // want to prevent that function from making modifications to the
69
+ // returned config object that would bleed into subsequent usages of
70
+ // the config object.
71
+ ...(doDeepClone ? cloneDeep(loadedConfig) : loadedConfig),
72
+ ...config,
73
+ };
74
+ }
75
+
76
+ // Merge any plugins given in options.plugins.
77
+ if (config.plugins) {
78
+ // If plugins are provided in a config file, they are assumed to be
79
+ // a final list of plugins; according to svgo version 2 docs, the
80
+ // config file is responsible for merging the default plugins list.
81
+ // So we just need to merge the options.plugins into the list loaded
82
+ // from the config file.
83
+ config.plugins = extendLoadedPlugins(config.plugins, plugins);
84
+ } else {
85
+ const pluginConfig = {
86
+ // Default provided per svgo docs in v2.4.0+
87
+ name: 'preset-default',
88
+ params: {
89
+ overrides: {},
90
+ },
91
+ };
92
+
93
+ // Following format assuming plugins settings are for built ins
94
+ for (const plugin of plugins) {
95
+ for (const [key, value] of Object.entries(plugin)) {
96
+ pluginConfig.params.overrides[key] = value;
97
+ }
98
+ }
99
+
100
+ config.plugins = [pluginConfig];
101
+ }
102
+
103
+ return config;
104
+ };
105
+
106
+ // Based on svgo's extendDefaultPlugins().
107
+ const extendLoadedPlugins = (loadedPlugins, plugins) => {
108
+ const pluginsOrder = [];
109
+ const extendedPlugins = loadedPlugins.map((plugin) => {
110
+ pluginsOrder.push(typeof plugin === 'string' ? plugin : plugin.name);
111
+ return plugin;
112
+ });
113
+
114
+ for (const plugin of plugins) {
115
+ const index = pluginsOrder.indexOf(
116
+ typeof plugin === 'string' ? plugin : plugin.name
117
+ );
118
+ if (index === -1) {
119
+ extendedPlugins.push(plugin);
120
+ } else {
121
+ extendedPlugins[index] = plugin;
122
+ }
123
+ }
124
+
125
+ return extendedPlugins;
126
+ };
@@ -0,0 +1,44 @@
1
+ import PluginError from 'plugin-error';
2
+ import {Transform} from 'stream';
3
+ import {optimize} from 'svgo';
4
+ import {getSvgoConfig} from './get-svgo-config.js';
5
+
6
+ const PLUGIN_NAME = 'gulp-svgmin';
7
+
8
+ export default function (options) {
9
+ const optionsFunction = typeof options === 'function';
10
+
11
+ const stream = new Transform({objectMode: true});
12
+ stream._transform = function (file, encoding, cb) {
13
+ if (file.isStream()) {
14
+ return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
15
+ }
16
+
17
+ if (file.isBuffer()) {
18
+ getSvgoConfig(
19
+ optionsFunction ? options(file) : options,
20
+ optionsFunction
21
+ )
22
+ .then((config) => {
23
+ const result = optimize(String(file.contents), config);
24
+
25
+ // Ignore svgo meta data and return the SVG string.
26
+ if (typeof result.data === 'string') {
27
+ file.contents = Buffer.from(result.data);
28
+ return cb(null, file);
29
+ }
30
+
31
+ // Otherwise, throw an error, even if it is undefined.
32
+ throw result.error;
33
+ })
34
+ .catch((error) => cb(new PluginError(PLUGIN_NAME, error)));
35
+
36
+ return;
37
+ }
38
+
39
+ // Handle all other cases, like file.isNull(), file.isDirectory().
40
+ return cb(null, file);
41
+ };
42
+
43
+ return stream;
44
+ };
@@ -1,5 +1,6 @@
1
1
  // 2024-02-13, Kaspars Zuks: added "options.async" support
2
- import map from 'map-stream';
2
+ // 2026-03-06, Kaspars Zuks: replaced map-stream with through2
3
+ import through from 'through2';
3
4
  import rext from 'replace-ext';
4
5
  import log from 'fancy-log';
5
6
  import PluginError from 'plugin-error';
@@ -20,7 +21,7 @@ export default function (options) {
20
21
  options || {},
21
22
  );
22
23
 
23
- function modifyContents(file, cb) {
24
+ function modifyContents(file, _enc, cb) {
24
25
  var data = file.data || Object.assign({}, options.data);
25
26
 
26
27
  if (file.isNull()) {
@@ -134,5 +135,5 @@ export default function (options) {
134
135
  }
135
136
  }
136
137
 
137
- return map(modifyContents);
138
+ return through.obj(modifyContents);
138
139
  }