exceljs-lts 4.5.2 → 4.5.4

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/dist/exceljs.js CHANGED
@@ -1851,6 +1851,34 @@ class Image {
1851
1851
  }
1852
1852
  }
1853
1853
  }
1854
+ function isFiniteNumber(value) {
1855
+ return typeof value === 'number' && Number.isFinite(value);
1856
+ }
1857
+ Image.validateRange = function validateRange(range) {
1858
+ if (typeof range === 'string') {
1859
+ let decoded;
1860
+ try {
1861
+ decoded = colCache.decode(range);
1862
+ } catch (e) {
1863
+ decoded = {};
1864
+ }
1865
+ const isRange = ['top', 'left', 'bottom', 'right'].every(key => isFiniteNumber(decoded[key]));
1866
+ const isAddress = isFiniteNumber(decoded.row) && isFiniteNumber(decoded.col);
1867
+ if (!isRange && !isAddress) {
1868
+ throw new Error(`Invalid image range "${range}": expected a cell range such as "B2:D6"`);
1869
+ }
1870
+ return;
1871
+ }
1872
+ if (!range || typeof range !== 'object') {
1873
+ throw new Error('Invalid image range: expected a cell range string or an object with tl and br or ext');
1874
+ }
1875
+ if (!range.br && !range.ext) {
1876
+ throw new Error('Invalid image range: an object range needs either br or ext');
1877
+ }
1878
+ if (range.ext && typeof range.ext !== 'object') {
1879
+ throw new Error('Invalid image range: ext must be an object with width and height');
1880
+ }
1881
+ };
1854
1882
  module.exports = Image;
1855
1883
 
1856
1884
  },{"../utils/col-cache":20,"./anchor":2}],9:[function(require,module,exports){
@@ -4177,7 +4205,14 @@ class Worksheet {
4177
4205
 
4178
4206
  // =========================================================================
4179
4207
  // Images
4208
+ _validateImageId(imageId) {
4209
+ if (imageId === undefined || imageId === null || !this._workbook.getImage(imageId)) {
4210
+ throw new Error(`Image with id ${imageId} not found. Add it with workbook.addImage() first`);
4211
+ }
4212
+ }
4180
4213
  addImage(imageId, range) {
4214
+ this._validateImageId(imageId);
4215
+ Image.validateRange(range);
4181
4216
  const model = {
4182
4217
  type: 'image',
4183
4218
  imageId,
@@ -4189,6 +4224,7 @@ class Worksheet {
4189
4224
  return this._media.filter(m => m.type === 'image');
4190
4225
  }
4191
4226
  addBackgroundImage(imageId) {
4227
+ this._validateImageId(imageId);
4192
4228
  const model = {
4193
4229
  type: 'background',
4194
4230
  imageId
@@ -9652,18 +9688,66 @@ class AutoFilterXform extends BaseXform {
9652
9688
  const firstAddress = getAddress(model.from);
9653
9689
  const secondAddress = getAddress(model.to);
9654
9690
  if (firstAddress && secondAddress) {
9655
- xmlStream.leafNode('autoFilter', {
9656
- ref: `${firstAddress}:${secondAddress}`
9657
- });
9691
+ const ref = `${firstAddress}:${secondAddress}`;
9692
+ if (model.exclude && model.exclude.length) {
9693
+ // hide the filter button on the excluded columns (0 = leftmost column of the range)
9694
+ xmlStream.openNode('autoFilter', {
9695
+ ref
9696
+ });
9697
+ model.exclude.forEach(colId => {
9698
+ xmlStream.leafNode('filterColumn', {
9699
+ colId,
9700
+ hiddenButton: '1'
9701
+ });
9702
+ });
9703
+ xmlStream.closeNode();
9704
+ } else {
9705
+ xmlStream.leafNode('autoFilter', {
9706
+ ref
9707
+ });
9708
+ }
9658
9709
  }
9659
9710
  }
9660
9711
  }
9661
9712
  }
9662
9713
  parseOpen(node) {
9663
- if (node.name === 'autoFilter') {
9664
- this.model = node.attributes.ref;
9714
+ switch (node.name) {
9715
+ case 'autoFilter':
9716
+ this.ref = node.attributes.ref;
9717
+ this.exclude = [];
9718
+ this.model = this.ref;
9719
+ return true;
9720
+ case 'filterColumn':
9721
+ {
9722
+ const {
9723
+ colId,
9724
+ hiddenButton,
9725
+ showButton
9726
+ } = node.attributes;
9727
+ const hidden = hiddenButton === '1' || hiddenButton === 'true' || showButton === '0' || showButton === 'false';
9728
+ if (hidden && colId !== undefined) {
9729
+ this.exclude.push(parseInt(colId, 10));
9730
+ }
9731
+ return true;
9732
+ }
9733
+ default:
9734
+ return true;
9665
9735
  }
9666
9736
  }
9737
+ parseClose(name) {
9738
+ if (name === 'autoFilter') {
9739
+ if (this.exclude.length && this.ref) {
9740
+ const [from, to] = this.ref.split(':');
9741
+ this.model = {
9742
+ from,
9743
+ to: to || from,
9744
+ exclude: this.exclude
9745
+ };
9746
+ }
9747
+ return false;
9748
+ }
9749
+ return true;
9750
+ }
9667
9751
  }
9668
9752
  module.exports = AutoFilterXform;
9669
9753