mirror of
https://github.com/fosrl/pangolin.git
synced 2026-10-20 11:39:06 +02:00
Keep plain negative numbers numeric in CSV export
A leading '-' only matters when the value is not a plain number, so -12 and -1.5 stay numeric while payloads like -2+3+cmd|'/c calc'!A0 still get the apostrophe prefix.
This commit is contained in:
@@ -147,6 +147,18 @@ function runTests() {
|
||||
);
|
||||
}
|
||||
|
||||
// A plain negative number is not a formula, so it must stay numeric
|
||||
// instead of being forced to text with a leading apostrophe.
|
||||
{
|
||||
const csv = generateCSV([{ id: -12, path: "-1.5" }]);
|
||||
|
||||
assertEquals(
|
||||
csv,
|
||||
"id,path\n-12,-1.5",
|
||||
"Negative numbers should stay numeric"
|
||||
);
|
||||
}
|
||||
|
||||
// A formula prefix is only dangerous at the start of a cell, so it must not
|
||||
// be added mid-value.
|
||||
{
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
// leading apostrophe is prefixed to force the cell to be read as literal text.
|
||||
const FORMULA_PREFIX = /^[=+\-@\t\r]/;
|
||||
|
||||
// A leading "-" alone is not dangerous when the rest of the value is just a
|
||||
// number: spreadsheets read -12 as a number, not a formula. Only values like
|
||||
// "-2+3+cmd|'/c calc'!A0" (a DDE payload) actually need neutralising, so
|
||||
// plain negative numbers stay numeric instead of being forced to text.
|
||||
const NEGATIVE_NUMBER = /^-\d+(\.\d+)?$/;
|
||||
|
||||
// CRLF, CR and LF each terminate a record for at least one CSV parser, so a
|
||||
// value containing them would otherwise spill across rows and forge new ones.
|
||||
// Replacing them with a literal "\n" keeps every record on a single line.
|
||||
@@ -24,7 +30,10 @@ function toCsvField(value: unknown): string {
|
||||
|
||||
// Quoting does not stop a spreadsheet from evaluating the unquoted value,
|
||||
// so the apostrophe has to be added before the field is escaped.
|
||||
const cell = FORMULA_PREFIX.test(text) ? `'${text}` : text;
|
||||
const cell =
|
||||
FORMULA_PREFIX.test(text) && !NEGATIVE_NUMBER.test(text)
|
||||
? `'${text}`
|
||||
: text;
|
||||
|
||||
if (cell.includes(",") || cell.includes('"')) {
|
||||
return `"${cell.replace(/"/g, '""')}"`;
|
||||
|
||||
Reference in New Issue
Block a user