Browse Source

'按需引用lodash方法'

zhuth 6 years ago
parent
commit
3c659c6d99

+ 7 - 4
src/lib/xlsx-populate/ArgHandler.js

@@ -1,6 +1,9 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const every = require("lodash/every");
+const isNil = require("lodash/isNil");
+const isInteger = require("lodash/isInteger");
 
 /**
  * Method argument handler. Used for overloading methods.
@@ -61,15 +64,15 @@ class ArgHandler {
     _argsMatchTypes(args, types) {
         if (args.length !== types.length) return false;
 
-        return _.every(args, (arg, i) => {
+        return every(args, (arg, i) => {
             const type = types[i];
 
             if (type === '*') return true;
-            if (type === 'nil') return _.isNil(arg);
+            if (type === 'nil') return isNil(arg);
             if (type === 'string') return typeof arg === "string";
             if (type === 'boolean') return typeof arg === "boolean";
             if (type === 'number') return typeof arg === "number";
-            if (type === 'integer') return typeof arg === "number" && _.isInteger(arg);
+            if (type === 'integer') return typeof arg === "number" && isInteger(arg);
             if (type === 'function') return typeof arg === "function";
             if (type === 'array') return Array.isArray(arg);
             if (type === 'date') return arg && arg.constructor === Date;

+ 23 - 18
src/lib/xlsx-populate/Cell.js

@@ -1,6 +1,11 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const isNil = require("lodash/isNil");
+const isObject = require("lodash/isObject");
+const isEmpty = require("lodash/isEmpty");
+const isArray = require("lodash/isArray");
+
 const ArgHandler = require("./ArgHandler");
 const addressConverter = require("./addressConverter");
 const dateConverter = require("./dateConverter");
@@ -89,7 +94,7 @@ class Cell {
         delete this._formulaRef;
 
         // TODO in future version: Move shared formula to some other cell. This would require parsing the formula...
-        if (!_.isNil(hostSharedFormulaId)) this.sheet().clearCellsUsingSharedFormula(hostSharedFormulaId);
+        if (!isNil(hostSharedFormulaId)) this.sheet().clearCellsUsingSharedFormula(hostSharedFormulaId);
 
         return this;
     }
@@ -122,7 +127,7 @@ class Cell {
         const value = this.value();
         if (typeof value !== 'string') return false;
 
-        if (_.isNil(replacement)) {
+        if (isNil(replacement)) {
             return pattern.test(value);
         } else {
             const replaced = value.replace(pattern, replacement);
@@ -475,7 +480,7 @@ class Cell {
         // Set the address.
         node.attributes.r = this.address();
 
-        if (!_.isNil(this._formulaType)) {
+        if (!isNil(this._formulaType)) {
             // Add the formula.
             const fNode = {
                 name: 'f',
@@ -483,12 +488,12 @@ class Cell {
             };
 
             if (this._formulaType !== "normal") fNode.attributes.t = this._formulaType;
-            if (!_.isNil(this._formulaRef)) fNode.attributes.ref = this._formulaRef;
-            if (!_.isNil(this._sharedFormulaId)) fNode.attributes.si = this._sharedFormulaId;
-            if (!_.isNil(this._formula)) fNode.children = [this._formula];
+            if (!isNil(this._formulaRef)) fNode.attributes.ref = this._formulaRef;
+            if (!isNil(this._sharedFormulaId)) fNode.attributes.si = this._sharedFormulaId;
+            if (!isNil(this._formula)) fNode.children = [this._formula];
 
             node.children.push(fNode);
-        } else if (!_.isNil(this._value)) {
+        } else if (!isNil(this._value)) {
             // Add the value. Don't emit value if a formula is set as Excel will show this stale value.
             let type, text;
             if (typeof this._value === "string") {
@@ -512,9 +517,9 @@ class Cell {
         }
 
         // If the style is set, set the style ID.
-        if (!_.isNil(this._style)) {
+        if (!isNil(this._style)) {
             node.attributes.s = this._style.id();
-        } else if (!_.isNil(this._styleId)) {
+        } else if (!isNil(this._styleId)) {
             node.attributes.s = this._styleId;
         }
 
@@ -536,13 +541,13 @@ class Cell {
      * @private
      */
     _init(nodeOrColumnNumber, styleId) {
-        if (_.isObject(nodeOrColumnNumber)) {
+        if (isObject(nodeOrColumnNumber)) {
             // Parse the existing node.
             this._parseNode(nodeOrColumnNumber);
         } else {
             // This is a new cell.
             this._columnNumber = nodeOrColumnNumber;
-            if (!_.isNil(styleId)) this._styleId = styleId;
+            if (!isNil(styleId)) this._styleId = styleId;
         }
     }
 
@@ -558,7 +563,7 @@ class Cell {
         this._columnNumber = ref.columnNumber;
 
         // Store the style ID if present.
-        if (!_.isNil(node.attributes.s)) this._styleId = node.attributes.s;
+        if (!isNil(node.attributes.s)) this._styleId = node.attributes.s;
 
         // Parse the formula if present..
         const fNode = xmlq.findChild(node, 'f');
@@ -568,7 +573,7 @@ class Cell {
             this._formula = fNode.children[0];
 
             this._sharedFormulaId = fNode.attributes.si;
-            if (!_.isNil(this._sharedFormulaId)) {
+            if (!isNil(this._sharedFormulaId)) {
                 // Update the sheet's max shared formula ID so we can set future IDs an index beyond this.
                 this.sheet().updateMaxSharedFormulaId(this._sharedFormulaId);
             }
@@ -579,7 +584,7 @@ class Cell {
             delete fNode.attributes.si;
 
             // If any unknown attributes are still present, store them for later output.
-            if (!_.isEmpty(fNode.attributes)) this._remainingFormulaAttributes = fNode.attributes;
+            if (!isEmpty(fNode.attributes)) this._remainingFormulaAttributes = fNode.attributes;
         }
 
         // Parse the value.
@@ -592,7 +597,7 @@ class Cell {
                 this._value = this.workbook().sharedStrings().getStringByIndex(sharedIndex);
 
                 // rich text
-                if (_.isArray(this._value)) {
+                if (isArray(this._value)) {
                     this._value = new RichText(this._value);
                 }
             } else {
@@ -631,7 +636,7 @@ class Cell {
         delete node.attributes.t;
 
         // If any unknown attributes are still present, store them for later output.
-        if (!_.isEmpty(node.attributes)) this._remainingAttributes = node.attributes;
+        if (!isEmpty(node.attributes)) this._remainingAttributes = node.attributes;
 
         // Delete known children.
         xmlq.removeChild(node, 'f');
@@ -639,7 +644,7 @@ class Cell {
         xmlq.removeChild(node, 'is');
 
         // If any unknown children are still present, store them for later output.
-        if (!_.isEmpty(node.children)) this._remainingChildren = node.children;
+        if (!isEmpty(node.children)) this._remainingChildren = node.children;
     }
 }
 

+ 3 - 2
src/lib/xlsx-populate/ContentTypes.js

@@ -1,6 +1,7 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const find = require("lodash/find");
 
 /**
  * A content type collection.
@@ -40,7 +41,7 @@ class ContentTypes {
      * @returns {{}|undefined} The matching content type or undefined if not found.
      */
     findByPartName(partName) {
-        return _.find(this._node.children, node => node.attributes.PartName === partName);
+        return find(this._node.children, node => node.attributes.PartName === partName);
     }
 
     /**

+ 4 - 3
src/lib/xlsx-populate/Encryptor.js

@@ -8,7 +8,8 @@
  * https://github.com/nolze/ms-offcrypto-tool
  */
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const find = require("lodash/find");
 const cfb = require("cfb");
 const crypto = require("crypto");
 const externals = require("./externals");
@@ -236,8 +237,8 @@ class Encryptor {
     decryptAsync(data, password) {
         // Parse the CFB input and pull out the encryption info and encrypted package entries.
         const parsed = cfb.parse(data);
-        let encryptionInfoBuffer = _.find(parsed.FileIndex, { name: "EncryptionInfo" }).content;
-        let encryptedPackageBuffer = _.find(parsed.FileIndex, { name: "EncryptedPackage" }).content;
+        let encryptionInfoBuffer = find(parsed.FileIndex, { name: "EncryptionInfo" }).content;
+        let encryptedPackageBuffer = find(parsed.FileIndex, { name: "EncryptedPackage" }).content;
 
         // In the browser the CFB content is an array. Convert to a Buffer.
         if (!Buffer.isBuffer(encryptionInfoBuffer)) encryptionInfoBuffer = Buffer.from(encryptionInfoBuffer);

+ 3 - 2
src/lib/xlsx-populate/FormulaError.js

@@ -1,6 +1,7 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const find = require("lodash/find");
 
 /**
  * A formula error (e.g. #DIV/0!).
@@ -72,7 +73,7 @@ FormulaError.VALUE = new FormulaError("#VALUE!");
  * @ignore
  */
 FormulaError.getError = error => {
-    return _.find(FormulaError, value => {
+    return find(FormulaError, value => {
         return value instanceof FormulaError && value.error() === error;
     }) || new FormulaError(error);
 };

+ 5 - 3
src/lib/xlsx-populate/Relationships.js

@@ -1,6 +1,8 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const find = require("lodash/find");
+
 
 const RELATIONSHIP_SCHEMA_PREFIX = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/";
 
@@ -49,7 +51,7 @@ class Relationships {
      * @returns {{}|undefined} The matching relationship or undefined if not found.
      */
     findById(id) {
-        return _.find(this._node.children, node => node.attributes.Id === id);
+        return find(this._node.children, node => node.attributes.Id === id);
     }
 
     /**
@@ -58,7 +60,7 @@ class Relationships {
      * @returns {{}|undefined} The matching relationship or undefined if not found.
      */
     findByType(type) {
-        return _.find(this._node.children, node => node.attributes.Type === `${RELATIONSHIP_SCHEMA_PREFIX}${type}`);
+        return find(this._node.children, node => node.attributes.Type === `${RELATIONSHIP_SCHEMA_PREFIX}${type}`);
     }
 
     /**

+ 6 - 3
src/lib/xlsx-populate/RichText.js

@@ -1,6 +1,9 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const includes = require("lodash/includes");
+const cloneDeep = require("lodash/cloneDeep");
+
 const RichTextFragment = require("./RichTextFragment");
 
 /**
@@ -78,8 +81,8 @@ class RichText {
      * @return {RichText} A deep copied instance
      */
     copy(cell) {
-        const newRichText = new RichText(_.cloneDeep(this.toXml()));
-        if (cell && _.includes(this.text(), '\n')) {
+        const newRichText = new RichText(cloneDeep(this.toXml()));
+        if (cell && includes(this.text(), '\n')) {
             cell.style('wrapText', true);
         }
         return newRichText;

+ 4 - 2
src/lib/xlsx-populate/RichTextFragment.js

@@ -3,7 +3,9 @@
 /* eslint camelcase:off */
 
 const ArgHandler = require("./ArgHandler");
-const _ = require("lodash");
+// const _ = require("lodash");
+const isEmpty = require("lodash/isEmpty");
+
 const xmlq = require("./xmlq");
 const colorIndexes = require("./colorIndexes");
 
@@ -150,7 +152,7 @@ class RichTextFragment {
 
         if (child.attributes.hasOwnProperty('tint')) color.tint = child.attributes.tint;
 
-        if (_.isEmpty(color)) return;
+        if (isEmpty(color)) return;
 
         return color;
     }

+ 10 - 8
src/lib/xlsx-populate/Row.js

@@ -1,6 +1,8 @@
 "use strict";
 
-const _ = require("lodash");
+const isNil = require("lodash/isNil");
+const forEach = require("lodash/forEach");
+const findIndex = require("lodash/findIndex");
 const Cell = require("./Cell");
 const regexify = require("./regexify");
 const ArgHandler = require("./ArgHandler");
@@ -61,8 +63,8 @@ class Row {
         const columnStyleId = this.sheet().existingColumnStyleId(columnNumber);
 
         // Row style takes priority. If a cell has both row and column styles it should have created a cell entry with a cell-specific style.
-        if (!_.isNil(rowStyleId)) styleId = rowStyleId;
-        else if (!_.isNil(columnStyleId)) styleId = columnStyleId;
+        if (!isNil(rowStyleId)) styleId = rowStyleId;
+        else if (!isNil(columnStyleId)) styleId = columnStyleId;
 
         // Create the new cell.
         const cell = new Cell(this, columnNumber, styleId);
@@ -175,7 +177,7 @@ class Row {
                 this._createCellStylesIfNeeded();
 
                 // Style each existing cell within this row. (Cells don't inherit ow/column styles.)
-                _.forEach(this._cells, cell => {
+                forEach(this._cells, cell => {
                     if (cell) cell.style(name, value);
                 });
 
@@ -199,7 +201,7 @@ class Row {
                 this._createCellStylesIfNeeded();
 
                 // Style each existing cell within this row. (Cells don't inherit ow/column styles.)
-                _.forEach(this._cells, cell => {
+                forEach(this._cells, cell => {
                     if (cell) cell.style(style);
                 });
 
@@ -280,7 +282,7 @@ class Row {
      * @ignore
      */
     hasStyle() {
-        return !_.isNil(this._node.attributes.s);
+        return isNil(this._node.attributes.s);
     }
 
     /**
@@ -289,7 +291,7 @@ class Row {
      * @ignore
      */
     minUsedColumnNumber() {
-        return _.findIndex(this._cells);
+        return findIndex(this._cells);
     }
 
     /**
@@ -321,7 +323,7 @@ class Row {
      */
     _createCellStylesIfNeeded() {
         this.sheet().forEachExistingColumnNumber(columnNumber => {
-            if (!_.isNil(this.sheet().existingColumnStyleId(columnNumber))) this.cell(columnNumber);
+            if (!isNil(this.sheet().existingColumnStyleId(columnNumber))) this.cell(columnNumber);
         });
     }
 

+ 4 - 3
src/lib/xlsx-populate/SharedStrings.js

@@ -1,6 +1,7 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const isArray = require("lodash/isArray");
 
 /**
  * The shared strings table.
@@ -26,7 +27,7 @@ class SharedStrings {
      */
     getIndexForString(string) {
         // If the string is found in the cache, return the index.
-        const key = _.isArray(string) ? JSON.stringify(string) : string;
+        const key = isArray(string) ? JSON.stringify(string) : string;
         let index = this._indexMap[key];
         if (index >= 0) return index;
 
@@ -38,7 +39,7 @@ class SharedStrings {
         // Append a new si node.
         this._node.children.push({
             name: "si",
-            children: _.isArray(string) ? string : [
+            children: isArray(string) ? string : [
                 {
                     name: "t",
                     attributes: { 'xml:space': "preserve" },

+ 38 - 25
src/lib/xlsx-populate/Sheet.js

@@ -1,6 +1,19 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const cloneDeep = require("lodash/cloneDeep");
+const filter = require("lodash/filter");
+const findIndex = require("lodash/findIndex");
+const forEach = require("lodash/forEach");
+const clone = require("lodash/clone");
+const values = require("lodash/values");
+const assign = require("lodash/assign");
+const isEqual = require("lodash/isEqual");
+const sortBy = require("lodash/sortBy");
+const isNaN = require("lodash/isNaN");
+const includes = require("lodash/includes");
+const isNumber = require("lodash/isNumber");
+
 const Cell = require("./Cell");
 const Row = require("./Row");
 const Column = require("./Column");
@@ -149,7 +162,7 @@ class Sheet {
             // If the existing node covered earlier columns than the new one, we need to have a col node to cover the min up to our new node.
             if (existingColNode.attributes.min < columnNumber) {
                 // Clone the node and set the max to the column before our new col.
-                const beforeColNode = _.cloneDeep(existingColNode);
+                const beforeColNode = cloneDeep(existingColNode);
                 beforeColNode.attributes.max = columnNumber - 1;
 
                 // Update the col nodes cache.
@@ -159,14 +172,14 @@ class Sheet {
             }
 
             // Make a clone for the new column. Set the min/max to the column number and cache it.
-            colNode = _.cloneDeep(existingColNode);
+            colNode = cloneDeep(existingColNode);
             colNode.attributes.min = columnNumber;
             colNode.attributes.max = columnNumber;
             this._colNodes[columnNumber] = colNode;
 
             // If the max of the existing node is greater than the nre one, create a col node for that too.
             if (existingColNode.attributes.max > columnNumber) {
-                const afterColNode = _.cloneDeep(existingColNode);
+                const afterColNode = cloneDeep(existingColNode);
                 afterColNode.attributes.min = columnNumber + 1;
                 for (let i = afterColNode.attributes.min; i <= afterColNode.attributes.max; i++) {
                     this._colNodes[i] = afterColNode;
@@ -279,7 +292,7 @@ class Sheet {
             })
             .case('*', hidden => {
                 if (hidden) {
-                    const visibleSheets = _.filter(this.workbook().sheets(), sheet => !sheet.hidden());
+                    const visibleSheets = filter(this.workbook().sheets(), sheet => !sheet.hidden());
                     if (visibleSheets.length === 1 && visibleSheets[0] === this) {
                         throw new Error("This sheet may not be hidden as a workbook must contain at least one visible sheet.");
                     }
@@ -470,7 +483,7 @@ class Sheet {
      * @returns {Range|undefined} The used range or undefined if no cells in the sheet are used.
      */
     usedRange() {
-        const minRowNumber = _.findIndex(this._rows);
+        const minRowNumber = findIndex(this._rows);
         const maxRowNumber = this._rows.length - 1;
 
         let minColumnNumber = 0;
@@ -557,7 +570,7 @@ class Sheet {
      * @ignore
      */
     forEachExistingColumnNumber(callback) {
-        _.forEach(this._colNodes, (node, columnNumber) => {
+        forEach(this._colNodes, (node, columnNumber) => {
             if (!node) return;
             callback(columnNumber);
         });
@@ -570,7 +583,7 @@ class Sheet {
      * @ignore
      */
     forEachExistingRow(callback) {
-        _.forEach(this._rows, (row, rowNumber) => {
+        forEach(this._rows, (row, rowNumber) => {
             if (row) callback(row, rowNumber);
         });
 
@@ -828,11 +841,11 @@ class Sheet {
      */
     toXmls() {
         // Shallow clone the node so we don't have to remove these children later if they don't belong.
-        const node = _.clone(this._node);
+        const node = clone(this._node);
         node.children = node.children.slice();
 
         // Add the columns if needed.
-        this._colsNode.children = _.filter(this._colNodes, (colNode, i) => {
+        this._colsNode.children = filter(this._colNodes, (colNode, i) => {
             // Columns should only be present if they have attributes other than min/max.
             return colNode && i === colNode.attributes.min && Object.keys(colNode.attributes).length > 2;
         });
@@ -841,7 +854,7 @@ class Sheet {
         }
 
         // Add the hyperlinks if needed.
-        this._hyperlinksNode.children = _.values(this._hyperlinks);
+        this._hyperlinksNode.children = values(this._hyperlinks);
         if (this._hyperlinksNode.children.length) {
             xmlq.insertInOrder(node, this._hyperlinksNode, nodeOrder);
         }
@@ -856,10 +869,10 @@ class Sheet {
         // Add the pageMargins if needed.
         if (this._pageMarginsNode && this._pageMarginsPresetName) {
             // Clone to preserve the current state of this sheet.
-            const childNode = _.clone(this._pageMarginsNode);
+            const childNode = clone(this._pageMarginsNode);
             if (Object.keys(this._pageMarginsNode.attributes).length) {
                 // Fill in any missing attribute values with presets.
-                childNode.attributes = _.assign(
+                childNode.attributes = assign(
                     this._pageMarginsPresets[this._pageMarginsPresetName],
                     this._pageMarginsNode.attributes);
             } else {
@@ -870,13 +883,13 @@ class Sheet {
         }
 
         // Add the merge cells if needed.
-        this._mergeCellsNode.children = _.values(this._mergeCells);
+        this._mergeCellsNode.children = values(this._mergeCells);
         if (this._mergeCellsNode.children.length) {
             xmlq.insertInOrder(node, this._mergeCellsNode, nodeOrder);
         }
 
         // Add the DataValidation cells if needed.
-        this._dataValidationsNode.children = _.values(this._dataValidations);
+        this._dataValidationsNode.children = values(this._dataValidations);
         if (this._dataValidationsNode.children.length) {
             xmlq.insertInOrder(node, this._dataValidationsNode, nodeOrder);
         }
@@ -1091,17 +1104,17 @@ class Sheet {
                 // Validate preset attribute keys.
                 const pageMarginsAttributeNames = [
                     'left', 'right', 'top', 'bottom', 'header', 'footer'];
-                const isValidPresetAttributeKeys = _.isEqual(
-                    _.sortBy(pageMarginsAttributeNames),
-                    _.sortBy(Object.keys(presetAttributes)));
+                const isValidPresetAttributeKeys = isEqual(
+                    sortBy(pageMarginsAttributeNames),
+                    sortBy(Object.keys(presetAttributes)));
                 if (isValidPresetAttributeKeys === false) {
                     throw new Error(`Sheet.pageMarginsPreset: Invalid preset attributes for one or key(s)! - "${Object.keys(presetAttributes)}"`);
                 }
 
                 // Validate preset attribute values.
-                _.forEach((attributeValue, attributeName) => {
+                forEach((attributeValue, attributeName) => {
                     const attributeNumberValue = parseFloat(attributeValue);
-                    if (_.isNaN(attributeNumberValue) || _.isNumber(attributeNumberValue) === false) {
+                    if (isNaN(attributeNumberValue) || isNumber(attributeNumberValue) === false) {
                         throw new Error(`Sheet.pageMarginsPreset: Invalid preset attribute value! - "${attributeValue}"`);
                     }
                 });
@@ -1149,7 +1162,7 @@ class Sheet {
         return new ArgHandler('Sheet.pane')
             .case(() => {
                 if (paneNode) {
-                    const result = _.cloneDeep(paneNode.attributes);
+                    const result = cloneDeep(paneNode.attributes);
                     if (!result.state) result.state = 'split';
                     return result;
                 }
@@ -1159,7 +1172,7 @@ class Sheet {
                 return this;
             })
             .case(['object'], paneAttributes => {
-                const attributes = _.assign({ activePane: 'bottomRight' }, paneAttributes);
+                const attributes = assign({ activePane: 'bottomRight' }, paneAttributes);
                 checkStateName(attributes.state);
                 checkActivePane(attributes.activePane);
                 if (paneNode) {
@@ -1237,7 +1250,7 @@ class Sheet {
      */
     _getCheckAttributeNameHelper(functionName, supportedAttributeNames) {
         return attributeName => {
-            if (!_.includes(supportedAttributeNames, attributeName)) {
+            if (!includes(supportedAttributeNames, attributeName)) {
                 throw new Error(`Sheet.${functionName}: "${attributeName}" is not supported.`);
             }
         };
@@ -1372,7 +1385,7 @@ class Sheet {
 
         // Cache the col nodes.
         this._colNodes = [];
-        _.forEach(this._colsNode.children, colNode => {
+        forEach(this._colsNode.children, colNode => {
             const min = colNode.attributes.min;
             const max = colNode.attributes.max;
             for (let i = min; i <= max; i++) {
@@ -1475,7 +1488,7 @@ class Sheet {
 
             // Search for a preset that matches existing attributes.
             for (const presetName in this._pageMarginsPresets) {
-                if (_.isEqual(this._pageMarginsNode.attributes, this._pageMarginsPresets[presetName])) {
+                if (isEqual(this._pageMarginsNode.attributes, this._pageMarginsPresets[presetName])) {
                     this._pageMarginsPresetName = presetName;
                     break;
                 }

+ 25 - 16
src/lib/xlsx-populate/Style.js

@@ -3,7 +3,16 @@
 /* eslint camelcase:off */
 
 const ArgHandler = require("./ArgHandler");
-const _ = require("lodash");
+// const _ = require("lodash");
+const isEmpty = require("lodash/isEmpty");
+const map = require("lodash/map");
+const isNil = require("lodash/isNil");
+const forEach = require("lodash/forEach");
+const isObject = require("lodash/isObject");
+const forOwn = require("lodash/forOwn");
+const defaults = require("lodash/defaults");
+const mapValues = require("lodash/mapValues");
+
 const xmlq = require("./xmlq");
 const colorIndexes = require("./colorIndexes");
 
@@ -72,7 +81,7 @@ class Style {
 
         if (child.attributes.hasOwnProperty('tint')) color.tint = child.attributes.tint;
 
-        if (_.isEmpty(color)) return;
+        if (isEmpty(color)) return;
 
         return color;
     }
@@ -361,7 +370,7 @@ class Style {
             const fill = {
                 type: "gradient",
                 gradientType,
-                stops: _.map(gradientFillNode.children, stop => ({
+                stops: map(gradientFillNode.children, stop => ({
                     position: stop.attributes.position,
                     color: this._getColor(stop, "color")
                 }))
@@ -384,7 +393,7 @@ class Style {
         this._fillNode.children = [];
 
         // No fill
-        if (_.isNil(fill)) return;
+        if (isNil(fill)) return;
 
         // Pattern fill
         if (fill.type === "pattern") {
@@ -412,7 +421,7 @@ class Style {
                 degree: fill.angle
             });
 
-            _.forEach(fill.stops, (fillStop, i) => {
+            forEach(fill.stops, (fillStop, i) => {
                 const stop = {
                     name: 'stop',
                     attributes: { position: fillStop.position },
@@ -426,7 +435,7 @@ class Style {
         }
 
         // Solid fill (really a pattern fill with a solid pattern type).
-        if (!_.isObject(fill)) fill = { type: "solid", color: fill };
+        if (!isObject(fill)) fill = { type: "solid", color: fill };
         else if (fill.hasOwnProperty('rgb') || fill.hasOwnProperty("theme")) fill = { color: fill };
 
         const patternFill = {
@@ -458,14 +467,14 @@ class Style {
                 if (direction) sideResult.direction = direction;
             }
 
-            if (!_.isEmpty(sideResult)) result[side] = sideResult;
+            if (!isEmpty(sideResult)) result[side] = sideResult;
         });
 
         return result;
     }
 
     _setBorder(settings) {
-        _.forOwn(settings, (setting, side) => {
+        forOwn(settings, (setting, side) => {
             if (typeof setting === "boolean") {
                 setting = { style: setting ? "thin" : null };
             } else if (typeof setting === "string") {
@@ -497,8 +506,8 @@ class Style {
     }
 
     _set_border(settings) {
-        if (_.isObject(settings) && !settings.hasOwnProperty("style") && !settings.hasOwnProperty("color")) {
-            settings = _.defaults(settings, {
+        if (isObject(settings) && !settings.hasOwnProperty("style") && !settings.hasOwnProperty("color")) {
+            settings = defaults(settings, {
                 left: null,
                 right: null,
                 top: null,
@@ -517,12 +526,12 @@ class Style {
     }
 
     _get_borderColor() {
-        return _.mapValues(this._getBorder(), value => value.color);
+        return mapValues(this._getBorder(), value => value.color);
     }
 
     _set_borderColor(color) {
-        if (_.isObject(color)) {
-            this._setBorder(_.mapValues(color, color => ({ color })));
+        if (isObject(color)) {
+            this._setBorder(mapValues(color, color => ({ color })));
         } else {
             this._setBorder({
                 left: { color },
@@ -535,12 +544,12 @@ class Style {
     }
 
     _get_borderStyle() {
-        return _.mapValues(this._getBorder(), value => value.style);
+        return mapValues(this._getBorder(), value => value.style);
     }
 
     _set_borderStyle(style) {
-        if (_.isObject(style)) {
-            this._setBorder(_.mapValues(style, style => ({ style })));
+        if (isObject(style)) {
+            this._setBorder(mapValues(style, style => ({ style })));
         } else {
             this._setBorder({
                 left: { style },

+ 9 - 6
src/lib/xlsx-populate/StyleSheet.js

@@ -1,6 +1,9 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const cloneDeep = require("lodash/cloneDeep");
+const assign = require("lodash/assign");
+
 const xmlq = require("./xmlq");
 const Style = require("./Style");
 
@@ -69,21 +72,21 @@ class StyleSheet {
         let fontNode, fillNode, borderNode, xfNode;
         if (sourceId >= 0) {
             const sourceXfNode = this._cellXfsNode.children[sourceId];
-            xfNode = _.cloneDeep(sourceXfNode);
+            xfNode = cloneDeep(sourceXfNode);
 
             if (sourceXfNode.attributes.applyFont) {
                 const fontId = sourceXfNode.attributes.fontId;
-                fontNode = _.cloneDeep(this._fontsNode.children[fontId]);
+                fontNode = cloneDeep(this._fontsNode.children[fontId]);
             }
 
             if (sourceXfNode.attributes.applyFill) {
                 const fillId = sourceXfNode.attributes.fillId;
-                fillNode = _.cloneDeep(this._fillsNode.children[fillId]);
+                fillNode = cloneDeep(this._fillsNode.children[fillId]);
             }
 
             if (sourceXfNode.attributes.applyBorder) {
                 const borderId = sourceXfNode.attributes.borderId;
-                borderNode = _.cloneDeep(this._bordersNode.children[borderId]);
+                borderNode = cloneDeep(this._bordersNode.children[borderId]);
             }
         }
 
@@ -105,7 +108,7 @@ class StyleSheet {
         this._bordersNode.children.push(borderNode);
 
         if (!xfNode) xfNode = { name: "xf", attributes: {}, children: [] };
-        _.assign(xfNode.attributes, {
+        assign(xfNode.attributes, {
             fontId: this._fontsNode.children.length - 1,
             fillId: this._fillsNode.children.length - 1,
             borderId: this._bordersNode.children.length - 1,

+ 29 - 19
src/lib/xlsx-populate/Workbook.js

@@ -1,6 +1,16 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const forEach = require("lodash/forEach");
+const filter = require("lodash/filter");
+const isNil = require("lodash/isNil");
+const isInteger = require("lodash/isInteger");
+const find = require("lodash/find");
+const isFunction = require("lodash/isFunction");
+const forOwn = require("lodash/forOwn");
+const some = require("lodash/some");
+const map = require("lodash/map");
+
 const fs = require("fs");
 const JSZip = require('jszip');
 
@@ -110,7 +120,7 @@ class Workbook {
                 if (sheet.hidden()) throw new Error("You may not activate a hidden sheet.");
 
                 // Deselect all sheets except the active one (mirroring ying Excel behavior).
-                _.forEach(this._sheets, current => {
+                forEach(this._sheets, current => {
                     current.tabSelected(current === sheet);
                 });
 
@@ -166,7 +176,7 @@ class Workbook {
         }
 
         // Make sure we are not deleting the only visible sheet.
-        const visibleSheets = _.filter(this._sheets, sheet => !sheet.hidden());
+        const visibleSheets = filter(this._sheets, sheet => !sheet.hidden());
         if (visibleSheets.length === 1 && visibleSheets[0] === sheet) {
             throw new Error("This sheet may not be deleted as a workbook must contain at least one visible sheet.");
         }
@@ -217,9 +227,9 @@ class Workbook {
         // Get the to/from indexes.
         const from = this._sheets.indexOf(sheet);
         let to;
-        if (_.isNil(indexOrBeforeSheet)) {
+        if (isNil(indexOrBeforeSheet)) {
             to = this._sheets.length - 1;
-        } else if (_.isInteger(indexOrBeforeSheet)) {
+        } else if (isInteger(indexOrBeforeSheet)) {
             to = indexOrBeforeSheet;
         } else {
             if (!(indexOrBeforeSheet instanceof Sheet)) {
@@ -328,8 +338,8 @@ class Workbook {
      * @returns {Sheet|undefined} The sheet or undefined if not found.
      */
     sheet(sheetNameOrIndex) {
-        if (_.isInteger(sheetNameOrIndex)) return this._sheets[sheetNameOrIndex];
-        return _.find(this._sheets, sheet => sheet.name() === sheetNameOrIndex);
+        if (isInteger(sheetNameOrIndex)) return this._sheets[sheetNameOrIndex];
+        return find(this._sheets, sheet => sheet.name() === sheetNameOrIndex);
     }
 
     /**
@@ -433,7 +443,7 @@ class Workbook {
      */
     scopedDefinedName(sheetScope, name, refersTo) {
         let definedNamesNode = xmlq.findChild(this._node, "definedNames");
-        let definedNameNode = definedNamesNode && _.find(definedNamesNode.children, node => node.attributes.name === name && node.localSheet === sheetScope);
+        let definedNameNode = definedNamesNode && find(definedNamesNode.children, node => node.attributes.name === name && node.localSheet === sheetScope);
 
         return new ArgHandler('Workbook.scopedDefinedName')
             .case(['*', 'string'], () => {
@@ -528,7 +538,7 @@ class Workbook {
         return this._addSheet(name, indexOrBeforeSheet, () => {
             const cloneXml = node => {
                 // If the node has a toXml method, call it.
-                if (node && _.isFunction(node.toXml)) node = node.toXml();
+                if (node && isFunction(node.toXml)) node = node.toXml();
         
                 if (typeof node === 'object') {
                     if (node.name) {
@@ -538,7 +548,7 @@ class Workbook {
                             children: []
                         };
                         
-                        _.forOwn(node.attributes, (value, name) => {
+                        forOwn(node.attributes, (value, name) => {
                             result.attributes[name] = value;
                         }); 
                     
@@ -578,15 +588,15 @@ class Workbook {
     _addSheet(name, indexOrBeforeSheet, getTemplateNodes) {
         // Validate the sheet name.
         if (!name || typeof name !== "string") throw new Error("Invalid sheet name.");
-        if (_.some(badSheetNameChars, char => name.indexOf(char) >= 0)) throw new Error(`Sheet name may not contain any of the following characters: ${badSheetNameChars.join(" ")}`);
+        if (some(badSheetNameChars, char => name.indexOf(char) >= 0)) throw new Error(`Sheet name may not contain any of the following characters: ${badSheetNameChars.join(" ")}`);
         if (name.length > maxSheetNameLength) throw new Error(`Sheet name may not be greater than ${maxSheetNameLength} characters.`);
         if (this.sheet(name)) throw new Error(`Sheet with name "${name}" already exists.`);
 
         // Get the destination index of new sheet.
         let index;
-        if (_.isNil(indexOrBeforeSheet)) {
+        if (isNil(indexOrBeforeSheet)) {
             index = this._sheets.length;
-        } else if (_.isInteger(indexOrBeforeSheet)) {
+        } else if (isInteger(indexOrBeforeSheet)) {
             index = indexOrBeforeSheet;
         } else {
             if (!(indexOrBeforeSheet instanceof Sheet)) {
@@ -699,7 +709,7 @@ class Workbook {
 
                 // Load each sheet.
                 this._sheetsNode = xmlq.findChild(this._node, "sheets");
-                return externals.Promise.all(_.map(this._sheetsNode.children, (sheetIdNode, i) => {
+                return externals.Promise.all(map(this._sheetsNode.children, (sheetIdNode, i) => {
                     if (sheetIdNode.attributes.sheetId > this._maxSheetId) this._maxSheetId = sheetIdNode.attributes.sheetId;
 
                     return this._parseNodesAsync([`xl/worksheets/sheet${i + 1}.xml`, `xl/worksheets/_rels/sheet${i + 1}.xml.rels`])
@@ -723,9 +733,9 @@ class Workbook {
      * @private
      */
     _parseNodesAsync(names) {
-        return externals.Promise.all(_.map(names, name => this._zip.file(name)))
-            .then(files => externals.Promise.all(_.map(files, file => file && file.async("string"))))
-            .then(texts => externals.Promise.all(_.map(texts, text => text && xmlParser.parseAsync(text))));
+        return externals.Promise.all(map(names, name => this._zip.file(name)))
+            .then(files => externals.Promise.all(map(files, file => file && file.async("string"))))
+            .then(texts => externals.Promise.all(map(texts, text => text && xmlParser.parseAsync(text))));
     }
 
     /**
@@ -744,7 +754,7 @@ class Workbook {
         // but reordering sheets messes this up. So store it on the node and we'll update the index on XML build.
         const definedNamesNode = xmlq.findChild(this._node, "definedNames");
         if (definedNamesNode) {
-            _.forEach(definedNamesNode.children, definedNameNode => {
+            forEach(definedNamesNode.children, definedNameNode => {
                 if (definedNameNode.attributes.hasOwnProperty("localSheetId")) {
                     definedNameNode.localSheet = this._sheets[definedNameNode.attributes.localSheetId];
                 }
@@ -776,7 +786,7 @@ class Workbook {
         // Set the defined names local sheet indexes.
         const definedNamesNode = xmlq.findChild(this._node, "definedNames");
         if (definedNamesNode) {
-            _.forEach(definedNamesNode.children, definedNameNode => {
+            forEach(definedNamesNode.children, definedNameNode => {
                 if (definedNameNode.localSheet) {
                     definedNameNode.attributes.localSheetId = this._sheets.indexOf(definedNameNode.localSheet);
                 }

+ 16 - 8
src/lib/xlsx-populate/XmlBuilder.js

@@ -1,6 +1,14 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const isFunction = require("lodash/isFunction");
+const isObject = require("lodash/isObject");
+const forOwn = require("lodash/forOwn");
+const isEmpty = require("lodash/isEmpty");
+const forEach = require("lodash/forEach");
+const isNil = require("lodash/isNil");
+const find = require("lodash/find");
+
 
 const XML_DECLARATION = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`;
 
@@ -39,9 +47,9 @@ class XmlBuilder {
         }
 
         // If the node has a toXml method, call it.
-        if (node && _.isFunction(node.toXml)) node = node.toXml();
+        if (node && isFunction(node.toXml)) node = node.toXml();
 
-        if (_.isObject(node)) {
+        if (isObject(node)) {
             // If the node is an object, then it maps to an element. Check if it has a name.
             if (!node.name) throw new Error(`XML node does not have name: ${JSON.stringify(node)}`);
 
@@ -49,18 +57,18 @@ class XmlBuilder {
             xml += `<${node.name}`;
 
             // Add any node attributes
-            _.forOwn(node.attributes, (value, name) => {
+            forOwn(node.attributes, (value, name) => {
                 xml += ` ${name}="${this._escapeString(value, true)}"`;
             });
 
-            if (_.isEmpty(node.children)) {
+            if (isEmpty(node.children)) {
                 // Self-close the tag if no children.
                 xml += "/>";
             } else {
                 xml += ">";
                 
                 // Recursively add any children.
-                _.forEach(node.children, child => {
+                forEach(node.children, child => {
                     // Add the children to the XML.
                     xml = this._build(child, xml);
                 });
@@ -68,7 +76,7 @@ class XmlBuilder {
                 // Close the tag.
                 xml += `</${node.name}>`;
             }
-        } else if (!_.isNil(node)) {
+        } else if (!isNil(node)) {
             // It not an object, this should be a text node. Just add it.
             xml += this._escapeString(node);
         }
@@ -85,7 +93,7 @@ class XmlBuilder {
      * @private
      */
     _escapeString(value, isAttribute) {
-        if (_.isNil(value)) return value;
+        if (isNil(value)) return value;
         value = value.toString()
             .replace(/&/g, "&amp;") // Escape '&' first as the other escapes add them.
             .replace(/</g, "&lt;")

+ 3 - 2
src/lib/xlsx-populate/regexify.js

@@ -1,6 +1,7 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const escapeRegExp = require("lodash/escapeRegExp");
 
 /**
  * Convert a pattern to a RegExp.
@@ -10,7 +11,7 @@ const _ = require("lodash");
  */
 module.exports = pattern => {
     if (typeof pattern === "string") {
-        pattern = new RegExp(_.escapeRegExp(pattern), "igm");
+        pattern = new RegExp(escapeRegExp(pattern), "igm");
     }
 
     pattern.lastIndex = 0;

+ 15 - 9
src/lib/xlsx-populate/xmlq.js

@@ -1,6 +1,12 @@
 "use strict";
 
-const _ = require("lodash");
+// const _ = require("lodash");
+const find = require("lodash/find");
+const some = require("lodash/some");
+const isEmpty = require("lodash/isEmpty");
+const remove = require("lodash/remove");
+const isNil = require("lodash/isNil");
+const forOwn = require("lodash/forOwn");
 
 /**
  * XML query methods.
@@ -41,7 +47,7 @@ module.exports = {
      * @returns {undefined|{}} The child if found.
      */
     findChild(node, name) {
-        return _.find(node.children, { name });
+        return find(node.children, { name });
     },
 
     /**
@@ -63,7 +69,7 @@ module.exports = {
      * @returns {boolean} True if found, false otherwise.
      */
     hasChild(node, name) {
-        return _.some(node.children, { name });
+        return some(node.children, { name });
     },
 
     /**
@@ -120,7 +126,7 @@ module.exports = {
      * @returns {boolean} True if empty, false otherwise.
      */
     isEmpty(node) {
-        return _.isEmpty(node.children) && _.isEmpty(node.attributes);
+        return isEmpty(node.children) && isEmpty(node.attributes);
     },
 
     /**
@@ -132,7 +138,7 @@ module.exports = {
     removeChild(node, child) {
         if (!node.children) return;
         if (typeof child === 'string') {
-            _.remove(node.children, { name: child });
+            remove(node.children, { name: child });
         } else {
             const index = node.children.indexOf(child);
             if (index >= 0) node.children.splice(index, 1);
@@ -146,8 +152,8 @@ module.exports = {
      * @returns {undefined}
      */
     setAttributes(node, attributes) {
-        _.forOwn(attributes, (value, attribute) => {
-            if (_.isNil(value)) {
+        forOwn(attributes, (value, attribute) => {
+            if (isNil(value)) {
                 if (node.attributes) delete node.attributes[attribute];
             } else {
                 if (!node.attributes) node.attributes = {};
@@ -165,8 +171,8 @@ module.exports = {
      */
     setChildAttributes(node, name, attributes) {
         let child = this.findChild(node, name);
-        _.forOwn(attributes, (value, attribute) => {
-            if (_.isNil(value)) {
+        forOwn(attributes, (value, attribute) => {
+            if (isNil(value)) {
                 if (child && child.attributes) delete child.attributes[attribute];
             } else {
                 if (!child) {