- 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
Enhances validation to clean corrupted items at load time while preserving
valid ones, rather than discarding entire sections. Also auto-capitalizes
first letter of items for consistency.
New capability - Granular Item Cleaning:
1. **cleanItemString()** (src/utils/security.js):
- Parses item string, removes bad items, re-serializes clean ones
- Applies ALL parsing rules: markdown, sanitization, length limits
- Used at load time to clean persisted data immediately
- Returns "None" if no valid items remain
2. **Enhanced validateStoredInventory()**:
- Now cleans items within each location
- Only removes locations if ALL items are invalid
- Example: "Home": "Sword, __proto__, Shield" → "Home": "Sword, Shield"
- Example: "Bad": "__proto__, constructor" → location removed
3. **Enhanced validateInventoryStructure()** (src/core/persistence.js):
- Cleans onPerson, stored, and assets at load time
- Logs exactly what was cleaned for debugging
- Auto-saves cleaned data back to storage
Auto-Capitalization:
- Added to cleanSingleItem() in itemParser.js
- Capitalizes first letter of each item after all cleaning
- Preserves rest of case: "iPhone" → "iPhone" (not "Iphone")
- Examples: "sword" → "Sword", "3x potions" → "3x potions"
Behavior examples:
Before (threw away entire array):
- "Home": "Sword, " + "A".repeat(600) + ", Shield"
→ Entire location lost
After (granular cleaning):
- "Home": "Sword, " + "A".repeat(600) + ", Shield"
→ "Home": "Sword, AAA...(500 chars), Shield"
Before (kept corrupted data):
- onPerson: "sword, __proto__, shield"
→ Stored as-is, filtered only at render
After (cleaned at load):
- onPerson: "Sword, Shield"
→ Cleaned and saved immediately, capitalized
Benefits:
- ✓ Preserves valid items when some are corrupted
- ✓ Cleans data at source, not just at render
- ✓ Detailed logging of what was cleaned
- ✓ Consistent capitalization across all items
- ✓ Single source of truth for "valid item"
Created comprehensive security layer to protect against malicious input
and resource exhaustion attacks.
New security.js module:
- sanitizeLocationName(): Blocks __proto__, constructor, toString, etc.
- sanitizeItemName(): Enforces max length (500 chars)
- validateStoredInventory(): Validates entire stored object structure
- MAX_ITEMS_PER_SECTION: Limit of 500 items per section
Protected attack vectors:
1. Prototype pollution via location names
- Blocked: "__proto__", "constructor", "prototype", etc.
- Alert shown to user if attempted
2. DoS via extremely long names
- Location names: max 200 chars (truncated with warning)
- Item names: max 500 chars (truncated with warning)
3. DoS via massive item lists
- Max 500 items per section (truncated with warning)
Integration:
- itemParser.js: Uses sanitizeItemName() and enforces max items
- inventoryActions.js: Validates all user input before saving
- Manual location creation: blocked dangerous names
- Manual item addition: length limits enforced
Security best practices (2025):
- No regex DoS vulnerabilities (character-by-character parsing)
- Explicit hasOwnProperty checks to avoid inherited properties
- Console warnings for all security events (auditing)
- Graceful degradation (truncate, don't crash)
- Defense in depth (validation at multiple layers)
This protects against both malicious actors and accidental abuse.
Fixes two parsing issues with inventory items:
1. Items with commas in parenthetical descriptions were incorrectly
split into multiple items. For example:
"Potato (Cursed, Sexy, Your Mum & Dick, Etc)" would become 3-4
separate items instead of one.
2. AI sometimes wraps item lists in square brackets, which should be
stripped. For example:
"[Sword, Shield]" should parse as ["Sword", "Shield"]
Solution:
- Enhanced parseItems() to track parenthesis depth during parsing
- Only split on commas that are OUTSIDE parentheses
- Strip wrapping square brackets before parsing
- Commas inside parentheses are now preserved as part of the item name
- Maintains backward compatibility with existing items
Implementation:
- Pre-processing: strip wrapping brackets if present
- Two-pass parsing: first collapses newlines in parentheses (existing),
then smart comma splitting (new)
- Similar approach to existing newline handling logic
Examples:
- "Sword, Shield" → ["Sword", "Shield"] (unchanged)
- "Item (tag1, tag2), Sword" → ["Item (tag1, tag2)", "Sword"] (fixed)
- "[Sword, Shield]" → ["Sword", "Shield"] (fixed)
Fixes: Items with commas split into multiple items
Implemented comprehensive individual item management system with toggleable view modes:
- Added item parsing utilities (parseItems/serializeItems) for comma-separated strings
- Implemented list view (full-width rows) and grid view (responsive cards)
- Added view mode toggle buttons per inventory section (onPerson, stored, assets)
- View preferences persist per-section in settings
- Replaced text-based editing with add/remove item controls
- Added inline forms for adding new items (matching existing UX patterns)
- Applied theme accent color (--rpg-highlight) to all outlines and active states
- Updated all tabs (desktop/mobile/inventory subtabs) with theme-consistent styling
Technical improvements:
- Created itemParser.js utility module for item string manipulation
- Enhanced inventory rendering with conditional list/grid HTML generation
- Added switchViewMode handler with settings persistence
- Fixed [object Object] display bug with comprehensive type checking
- All buttons and items now use transparent backgrounds with theme accent borders