Repository: svg-sprite/svg-sprite
Pull request #616 (2022-03-20 05:47:18)

Replace `_.zipObject` with vanilla JS
TODO:

- [x] decide with which solution to go (1st or 2nd patch); I haven't done any benchmarks, so any help to decide is welcome
- [x] add more tests (help welcome!)

Refs #604 

Kreeg: @XhmikosR I vote for second patch. I think It's just clearer.

Patch:
diff --git a/bin/svg-sprite.js b/bin/svg-sprite.js
index c1c6ff3..1130520 100644
--- a/bin/svg-sprite.js
+++ b/bin/svg-sprite.js
@@ -22,7 +22,7 @@ const yaml = require('js-yaml');
 const glob = require('glob');
 let yargs = require('yargs');
 const SVGSpriter = require('../lib/svg-sprite.js');
-const { isObject } = require('../lib/svg-sprite/utils/index.js');
+const { isObject, zipObject } = require('../lib/svg-sprite/utils/index.js');
 
 yargs
     .usage('Create one or multiple sprites of the given SVG files, optionally along with some stylesheet resources.\nUsage: $0 [options] files')
@@ -210,7 +210,7 @@ if (typeof config.shape.transform === 'string') {
                         const transformConfigFile = argv[`shape-transform-${transform}`];
                         const transformConfigJSON = fs.readFileSync(path.resolve(transformConfigFile), 'utf8');
                         const transformConfig = transformConfigJSON.trim() ? JSON.parse(transformConfigJSON) : {};
-                        this.push(_.zipObject([transform], [transformConfig]));
+                        this.push(zipObject([transform], [transformConfig]));
                     } catch {}
                 } else {
                     this.push(transform);
diff --git a/lib/svg-sprite.js b/lib/svg-sprite.js
index dd85e2f..d1fced0 100644
--- a/lib/svg-sprite.js
+++ b/lib/svg-sprite.js
@@ -22,7 +22,7 @@ const Config = require('./svg-sprite/config.js');
 const Queue = require('./svg-sprite/queue.js');
 const Layouter = require('./svg-sprite/layouter.js');
 const svgo = require('./svg-sprite/transform/svgo.js');
-const { isFunction, isObject, isPlainObject } = require('./svg-sprite/utils/index.js');
+const { isFunction, isObject, isPlainObject, zipObject } = require('./svg-sprite/utils/index.js');
 
 // TODO: after Node.js 12.x, `os.cpus` should never be undefined
 const CPU_COUNT = os.cpus() && os.cpus().length;
@@ -330,7 +330,7 @@ SVGSpriter.prototype._layout = function(config, cb) {
     }
 
     async.parallelLimit(tasks, this._limit, (error, data) => {
-        cb(error, files, _.zipObject(Object.keys(data).map(key => data[key].key), data));
+        cb(error, files, zipObject(Object.keys(data).map(key => data[key].key), data));
     });
 };
 
diff --git a/lib/svg-sprite/utils/index.js b/lib/svg-sprite/utils/index.js
index b88a252..4affcc5 100644
--- a/lib/svg-sprite/utils/index.js
+++ b/lib/svg-sprite/utils/index.js
@@ -41,9 +41,23 @@ function isString(value) {
     return Object.prototype.toString.call(value) === '[object String]';
 }
 
+/**
+ * @param {Array} array1    First array
+ * @param {Array} array2    Second array
+ * @returns {object}        The zipped Object
+ */
+function zipObject(array1, array2) {
+    if (!(Array.isArray(array1) || Array.isArray(array2))) {
+        throw new TypeError('Both parameters must be an array');
+    }
+
+    return Object.fromEntries(array1.map((_, i) => ([array1[i], array2[i]])));
+}
+
 module.exports = {
     isFunction,
     isObject,
     isPlainObject,
-    isString
+    isString,
+    zipObject
 };


Test patch:
diff --git a/test/utils.test.js b/test/utils.test.js
index 4032809..af6662f 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -2,7 +2,13 @@
 
 /* eslint-disable unicorn/new-for-builtins, no-new-wrappers, prefer-regex-literals, jest/prefer-expect-assertions */
 
-const { isFunction, isObject, isString, isPlainObject } = require('../lib/svg-sprite/utils/index.js');
+const {
+    isFunction,
+    isObject,
+    isString,
+    isPlainObject,
+    zipObject
+} = require('../lib/svg-sprite/utils/index.js');
 
 describe('utils', () => {
     describe('isFunction', () => {
@@ -193,4 +199,25 @@ describe('utils', () => {
             expect(isPlainObject(Symbol('test'))).toBe(false);
         });
     });
+
+    describe('zipObject', () => {
+        it('should return the zipped object', () => {
+            expect(zipObject(['a', 'b'], [1, 2])).toStrictEqual({ a: 1, b: 2 });
+        });
+
+        it('should return the zipped object with unbalanced arrays', () => {
+            expect(zipObject(['a', 'b', 'c'], [1, 2])).toStrictEqual({ a: 1, b: 2, c: undefined });
+            expect(zipObject(['a'], [1, 2])).toStrictEqual({ a: 1 });
+        });
+
+        it('should not fail with empty arrays', () => {
+            expect(zipObject([], [])).toStrictEqual({});
+        });
+
+        it('should throw error if non-array value passed', () => {
+            expect(() => {
+                zipObject(1, false);
+            }).toThrow(new TypeError('Both parameters must be an array'));
+        });
+    });
 });