New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@borgar/fx

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@borgar/fx - npm Package Compare versions

Comparing version
5.0.1
to
5.0.2
+3
-0
lib/constants.ts

@@ -17,2 +17,5 @@ export const OPERATOR = 'operator';

export const REF_STRUCT = 'structured';
// TODO: in future, we should type the difference between A1:B1 (REF_RANGE) and
// A1 (REF_CELL) but this will require a major version bump.
export const REF_CELL = 'cell'; // internal only
export const FX_PREFIX = 'fx_prefix';

@@ -19,0 +22,0 @@ export const UNKNOWN = 'unknown';

@@ -69,2 +69,16 @@ import { describe, test, expect } from 'vitest';

describe('fixRanges prefixes', () => {
test('Quotes prefixes as needed', () => {
isFixed('=Sch1!B2', "='Sch1'!B2");
isFixed('=[Foo]Ab12x!B2', '=[Foo]Ab12x!B2');
isFixed('=[Foo]Ab12!B2', "='[Foo]Ab12'!B2");
isFixed('=ABC123!B2', "='ABC123'!B2");
isFixed('=abc123!B2', "='abc123'!B2");
isFixed('=C!B2', "='C'!B2");
isFixed('=R!B2', "='R'!B2");
isFixed('=RC!B2', "='RC'!B2");
isFixed('=CR!B2', '=CR!B2');
});
});
describe('fixRanges A1', () => {

@@ -71,0 +85,0 @@ const opt = { allowTernary: true };

+1
-1

@@ -102,3 +102,3 @@ import { REF_RANGE, REF_BEAM, REF_TERNARY, MAX_COLS, MAX_ROWS } from '../constants.ts';

// LT : this is A1
if (top && canEndRange(str, preOp)) {
if (top && canEndRange(str, preOp) && str.charCodeAt(preOp) !== 33) { // 33 = "!"
return { type: REF_RANGE, value: str.slice(pos, preOp) };

@@ -105,0 +105,0 @@ }

@@ -14,2 +14,3 @@ import { REF_RANGE, REF_BEAM, REF_TERNARY, MAX_COLS, MAX_ROWS } from '../constants.ts';

const MINUS = 45;
const EXCL = 33;

@@ -101,3 +102,3 @@ // C

p += c1;
if (c1 || r1) {
if ((c1 || r1) && str.charCodeAt(p) !== EXCL) {
const op = advRangeOp(str, p);

@@ -104,0 +105,0 @@ const preOp = p;

@@ -1,2 +0,2 @@

import { CONTEXT, CONTEXT_QUOTE, REF_RANGE, REF_NAMED, REF_BEAM, REF_TERNARY, OPERATOR, REF_STRUCT } from './constants.ts';
import { CONTEXT, CONTEXT_QUOTE, REF_RANGE, REF_NAMED, REF_BEAM, REF_TERNARY, OPERATOR, REF_STRUCT, REF_CELL } from './constants.ts';
import type { Token } from './types.ts';

@@ -7,20 +7,22 @@

const validRunsMerge = [
[ REF_RANGE, ':', REF_RANGE ],
[ REF_RANGE, '.:', REF_RANGE ],
[ REF_RANGE, ':.', REF_RANGE ],
[ REF_RANGE, '.:.', REF_RANGE ],
[ REF_CELL, ':', REF_CELL ],
[ REF_CELL, '.:', REF_CELL ],
[ REF_CELL, ':.', REF_CELL ],
[ REF_CELL, '.:.', REF_CELL ],
[ REF_RANGE ],
[ REF_BEAM ],
[ REF_TERNARY ],
[ CONTEXT, '!', REF_RANGE, ':', REF_RANGE ],
[ CONTEXT, '!', REF_RANGE, '.:', REF_RANGE ],
[ CONTEXT, '!', REF_RANGE, ':.', REF_RANGE ],
[ CONTEXT, '!', REF_RANGE, '.:.', REF_RANGE ],
[ CONTEXT, '!', REF_CELL, ':', REF_CELL ],
[ CONTEXT, '!', REF_CELL, '.:', REF_CELL ],
[ CONTEXT, '!', REF_CELL, ':.', REF_CELL ],
[ CONTEXT, '!', REF_CELL, '.:.', REF_CELL ],
[ CONTEXT, '!', REF_CELL ],
[ CONTEXT, '!', REF_RANGE ],
[ CONTEXT, '!', REF_BEAM ],
[ CONTEXT, '!', REF_TERNARY ],
[ CONTEXT_QUOTE, '!', REF_RANGE, ':', REF_RANGE ],
[ CONTEXT_QUOTE, '!', REF_RANGE, '.:', REF_RANGE ],
[ CONTEXT_QUOTE, '!', REF_RANGE, ':.', REF_RANGE ],
[ CONTEXT_QUOTE, '!', REF_RANGE, '.:.', REF_RANGE ],
[ CONTEXT_QUOTE, '!', REF_CELL, ':', REF_CELL ],
[ CONTEXT_QUOTE, '!', REF_CELL, '.:', REF_CELL ],
[ CONTEXT_QUOTE, '!', REF_CELL, ':.', REF_CELL ],
[ CONTEXT_QUOTE, '!', REF_CELL, '.:.', REF_CELL ],
[ CONTEXT_QUOTE, '!', REF_CELL ],
[ CONTEXT_QUOTE, '!', REF_RANGE ],

@@ -66,3 +68,10 @@ [ CONTEXT_QUOTE, '!', REF_BEAM ],

if (token) {
const key = (token.type === OPERATOR) ? token.value : token.type;
const value = token.value;
let key = (token.type === OPERATOR) ? value : token.type;
// we need to prevent merging ["A1:B2" ":" "C3"] as a range is only
// allowed to contain a single ":" operator even if "A1:B2:C3" is
// valid Excel syntax
if (key === REF_RANGE && !value.includes(':')) {
key = REF_CELL;
}
if (key in node) {

@@ -69,0 +78,0 @@ node = node[key];

@@ -338,1 +338,8 @@ /* eslint-disable @stylistic/object-property-newline */

});
describe('Sheet name that looks like an A1 ref', () => {
test('parse correctly', () => {
isA1Equal("'Sch1'!B2", { context: [ 'Sch1' ], range: { top: 1, left: 1, bottom: 1, right: 1 } });
isA1Equal('Sch1!B2', { context: [ 'Sch1' ], range: { top: 1, left: 1, bottom: 1, right: 1 } });
});
});

@@ -33,2 +33,8 @@ import { describe, test, expect } from 'vitest';

});
test('should quote prefixes that look like A1 ranges', () => {
expect(stringifyA1Ref({ context: [ 'Ab12' ], range: rangeA1 })).toBe("'Ab12'!A1");
expect(stringifyA1Ref({ context: [ 'Sch1' ], range: rangeA1 })).toBe("'Sch1'!A1");
expect(stringifyA1Ref({ context: [ 'Foo12345' ], range: rangeA1 })).toBe("'Foo12345'!A1");
});
});

@@ -65,2 +71,14 @@

});
test('should quote prefixes that look like ranges', () => {
expect(stringifyA1RefXlsx({ sheetName: 'C', range: rangeA1 })).toBe("'C'!A1");
expect(stringifyA1RefXlsx({ sheetName: 'R', range: rangeA1 })).toBe("'R'!A1");
expect(stringifyA1RefXlsx({ sheetName: 'RC', range: rangeA1 })).toBe("'RC'!A1");
expect(stringifyA1RefXlsx({ sheetName: 'Ab12', range: rangeA1 })).toBe("'Ab12'!A1");
expect(stringifyA1RefXlsx({ sheetName: 'Sch1', range: rangeA1 })).toBe("'Sch1'!A1");
expect(stringifyA1RefXlsx({ sheetName: 'Foo12345', range: rangeA1 })).toBe("'Foo12345'!A1");
expect(stringifyA1RefXlsx({ workbookName: 'Ab12', range: rangeA1 })).toBe("'[Ab12]'!A1");
expect(stringifyA1RefXlsx({ workbookName: 'Sch1', range: rangeA1 })).toBe("'[Sch1]'!A1");
expect(stringifyA1RefXlsx({ workbookName: 'Foo12345', range: rangeA1 })).toBe("'[Foo12345]'!A1");
});
});

@@ -13,3 +13,24 @@ import type {

const reBannedChars = /[^0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]/;
// A1-XFD1048575 | R | C | RC
const reIsRangelike = /^(R|C|RC|[A-Z]{1,3}\d{1,7})$/i;
export function needQuotes (scope: string, yesItDoes = 0): number {
if (yesItDoes) {
return 1;
}
if (scope) {
if (reBannedChars.test(scope)) {
return 1;
}
if (reIsRangelike.test(scope)) {
return 1;
}
}
return 0;
}
export function quotePrefix (prefix) {
return "'" + prefix.replace(/'/g, "''") + "'";
}
export function stringifyPrefix (

@@ -27,3 +48,3 @@ ref: ReferenceA1 | ReferenceName | ReferenceStruct | ReferenceR1C1

pre = part + pre;
quote += +reBannedChars.test(scope);
quote += needQuotes(scope, quote);
nth++;

@@ -33,3 +54,3 @@ }

if (quote) {
pre = "'" + pre.replace(/'/g, "''") + "'";
pre = quotePrefix(pre);
}

@@ -47,12 +68,12 @@ return pre ? pre + '!' : pre;

pre += '[' + workbookName + ']';
quote += +reBannedChars.test(workbookName);
quote += needQuotes(workbookName);
}
if (sheetName) {
pre += sheetName;
quote += +reBannedChars.test(sheetName);
quote += needQuotes(sheetName);
}
if (quote) {
pre = "'" + pre.replace(/'/g, "''") + "'";
pre = quotePrefix(pre);
}
return pre ? pre + '!' : pre;
}

@@ -103,4 +103,3 @@ import { stringifyR1C1RefXlsx } from './stringifyR1C1Ref.ts';

const tokenValue = token.value;
// We can get away with using the xlsx ref-parser here because it is more permissive
// and we will end up with the same prefix after serialization anyway:
// We can get away with using the xlsx ref-parser here because it is more permissive:
const ref = quickParseA1(tokenValue);

@@ -107,0 +106,0 @@ if (ref) {

{
"name": "@borgar/fx",
"version": "5.0.1",
"version": "5.0.2",
"description": "Utilities for working with Excel formulas",

@@ -71,9 +71,9 @@ "type": "module",

"typescript": "~5.9.3",
"typescript-eslint": "~8.46.2",
"vitest": "~4.0.6",
"globals": "~16.5.0",
"typedoc": "~0.28.14",
"typedoc-plugin-markdown": "~4.9.0",
"tsup": "~8.5.0"
"typescript-eslint": "~8.55.0",
"vitest": "~4.0.18",
"globals": "~17.3.0",
"typedoc": "~0.28.17",
"typedoc-plugin-markdown": "~4.10.0",
"tsup": "~8.5.1"
}
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display