Fix: Preserve decimal commas in numbers (e.g., 4443,445)

- Modified itemParser to detect commas between digits
- Prevents splitting money/numbers with comma decimal separators
- Example: '4443,445 gold coins' now stays as one item
- Added documentation and example for decimal comma handling
This commit is contained in:
Spicy_Marinara
2025-12-18 02:03:11 +01:00
parent 3ded104218
commit 5bc7bfe22f
+29 -14
View File
@@ -17,6 +17,7 @@ import { sanitizeItemName, MAX_ITEMS_PER_SECTION } from './security.js';
* - Strips list markers: -, •, 1., 2., etc. * - Strips list markers: -, •, 1., 2., etc.
* - Collapses newlines inside parentheses to spaces * - Collapses newlines inside parentheses to spaces
* - Only splits on commas OUTSIDE parentheses (preserves commas in descriptions) * - Only splits on commas OUTSIDE parentheses (preserves commas in descriptions)
* - Preserves commas in numbers (decimal separators like 4443,445)
* - Gracefully handles unmatched parentheses * - Gracefully handles unmatched parentheses
* *
* @param {string} itemString - Item string from AI (various formats supported) * @param {string} itemString - Item string from AI (various formats supported)
@@ -35,6 +36,10 @@ import { sanitizeItemName, MAX_ITEMS_PER_SECTION } from './security.js';
* parseItems("Potato (Cursed, Sexy, Your Mum & Dick, Etc), Sword") * parseItems("Potato (Cursed, Sexy, Your Mum & Dick, Etc), Sword")
* // → ["Potato (Cursed, Sexy, Your Mum & Dick, Etc)", "Sword"] * // → ["Potato (Cursed, Sexy, Your Mum & Dick, Etc)", "Sword"]
* *
* // Decimal commas in numbers (preserved)
* parseItems("4443,445 gold coins, Sword, 1,234,567 credits")
* // → ["4443,445 gold coins", "Sword", "1,234,567 credits"]
*
* // Markdown formatting (stripped) * // Markdown formatting (stripped)
* parseItems("**Sword** (equipped), *Shield*") // ["Sword (equipped)", "Shield"] * parseItems("**Sword** (equipped), *Shield*") // ["Sword (equipped)", "Shield"]
* *
@@ -125,7 +130,7 @@ export function parseItems(itemString) {
// STEP 5: Normalize whitespace // STEP 5: Normalize whitespace
processed = processed.replace(/\s+/g, ' '); processed = processed.replace(/\s+/g, ' ');
// STEP 6: Smart comma splitting (only split on commas OUTSIDE parentheses) // STEP 6: Smart comma splitting (only split on commas OUTSIDE parentheses and NOT in numbers)
// Also handles list markers, quotes, and security validation per-item // Also handles list markers, quotes, and security validation per-item
const items = []; const items = [];
let currentItem = ''; let currentItem = '';
@@ -146,22 +151,32 @@ export function parseItems(itemString) {
} }
currentItem += char; currentItem += char;
} else if (char === ',' && parenDepth === 0) { } else if (char === ',' && parenDepth === 0) {
// Comma outside parentheses - this is a separator // Check if this comma is between digits (decimal separator like 4443,445)
const cleaned = cleanSingleItem(currentItem); const prevChar = i > 0 ? processed[i - 1] : '';
if (cleaned) { const nextChar = i < processed.length - 1 ? processed[i + 1] : '';
// Security check: validate and sanitize item name const isDecimalComma = /\d/.test(prevChar) && /\d/.test(nextChar);
const sanitized = sanitizeItemName(cleaned);
if (sanitized) {
items.push(sanitized);
}
// DoS protection: enforce max items limit if (isDecimalComma) {
if (items.length >= MAX_ITEMS_PER_SECTION) { // This is a decimal comma, not a separator - keep it
console.warn(`[RPG Companion] Reached max items limit (${MAX_ITEMS_PER_SECTION}), truncating list`); currentItem += char;
return items; } else {
// Comma outside parentheses and not in a number - this is a separator
const cleaned = cleanSingleItem(currentItem);
if (cleaned) {
// Security check: validate and sanitize item name
const sanitized = sanitizeItemName(cleaned);
if (sanitized) {
items.push(sanitized);
}
// DoS protection: enforce max items limit
if (items.length >= MAX_ITEMS_PER_SECTION) {
console.warn(`[RPG Companion] Reached max items limit (${MAX_ITEMS_PER_SECTION}), truncating list`);
return items;
}
} }
currentItem = ''; // Start new item
} }
currentItem = ''; // Start new item
} else { } else {
currentItem += char; currentItem += char;
} }