pw-item-desc-parser
v1.2.0
Published
A TypeScript parser for Perfect World item descriptions with color formatting and LRU caching
Maintainers
Readme
pw-item-desc-parser
A TypeScript parser for Perfect World item descriptions with color formatting, LRU caching, and React compatibility.
Features
- 🚀 High Performance: LRU cache with configurable size limits
- 🎨 Color Formatting: Converts
^xxxxxxcolor codes to HTML with inline styles - 📝 Line Break Support: Converts
\rto<br />tags - 🔍 Search Functionality: Search through item descriptions
- ⚡ TypeScript Support: Full type definitions included
- ⚛️ React Compatible: Works seamlessly with React applications
- 📦 Bundled Data: Includes default item description file
- 🔧 Flexible: Support for custom files and configurations
Installation
npm install pw-item-desc-parserQuick Start
Basic Usage
import { ItemDescParser } from 'pw-item-desc-parser';
// Create parser instance
const parser = new ItemDescParser();
// Parse item by ID
const item = parser.parseById(10037);
console.log(item.formatted); // HTML formatted text
// Parse raw text
const rawText = '^ffcb4aUma invenção maravilhosa\\r^00ffffClique para usar';
const parsed = parser.parseDescription(rawText);
console.log(parsed.formatted);TypeScript Usage
import { ItemDescParser, ParsedDescription } from 'pw-item-desc-parser';
const parser = new ItemDescParser({
cacheSize: 2000,
encoding: 'utf16le'
});
const description: ParsedDescription | null = parser.parseById(10037);React Usage
import React, { useState, useEffect } from 'react';
import { ItemDescParser } from 'pw-item-desc-parser';
function ItemComponent({ itemId }) {
const [parser] = useState(() => new ItemDescParser());
const [description, setDescription] = useState(null);
useEffect(() => {
const desc = parser.parseById(itemId);
setDescription(desc);
}, [itemId, parser]);
if (!description) return <div>Loading...</div>;
return (
<div dangerouslySetInnerHTML={{ __html: description.formatted }} />
);
}API Reference
ItemDescParser
Main parser class for handling item descriptions.
Constructor Options
interface ParserOptions {
filePath?: string; // Path to item description file (default: bundled file)
cacheSize?: number; // Maximum cache size (default: 1000)
encoding?: string; // File encoding (default: 'utf16le')
}Methods
parseDescription(text: string): ParsedDescription
Parse raw description text with color codes and line breaks.
const result = parser.parseDescription('^ffcb4aText with color\\r^00ffffMore text');
// Returns: { text: '...', formatted: '<em style="color: #ffcb4a">Text with color</em><br /><em style="color: #00ffff">More text</em>' }parseById(id: string | number): ParsedDescription | null
Parse item description by ID. Returns null if item not found.
const item = parser.parseById(10037);
if (item) {
console.log(item.formatted);
}loadFile(filePath?: string): ItemDescriptionMap
Load and parse the entire file. Returns map of all descriptions.
const allItems = parser.loadFile();
console.log(`Loaded ${Object.keys(allItems).length} items`);searchDescriptions(searchText: string, caseSensitive?: boolean): Array<{id: string, description: ParsedDescription}>
Search through item descriptions.
const results = parser.searchDescriptions('invenção');
results.forEach(result => {
console.log(`ID ${result.id}: ${result.description.text}`);
});getAllDescriptions(): ItemDescriptionMap
Get all loaded descriptions.
clearCache(): void
Clear the LRU cache.
getCacheStats(): {size: number, maxSize: number}
Get cache statistics.
getAvailableIds(): string[]
Get array of available item IDs.
setFilePath(filePath: string): void
Set new file path (requires reload).
isLoaded(): boolean
Check if file is loaded.
Data Format
The parser expects item description files in the following format:
10037 "^ffcb4aUma invenção maravilhosa para a raça humana, \rexibindo completamente sua natureza de amante da diversão e da paz. \r^00ffffClique com o botão direito do mouse para usá-la."
10042 "^00ffffSelecione uma carruagem de cerco, use a tecla da seta para a direita para controlá-la."Color Codes
- Format:
^xxxxxxwherexxxxxxis a 6-digit hexadecimal color code - Example:
^ffcb4abecomes<em style="color: #ffcb4a">text</em>
Line Breaks
- Format:
\r - Converts to:
<br />
Performance
Benchmarks
- File Loading: ~50ms for 25,000 items
- Individual Parsing: ~0.1ms per item
- Cache Hit: ~0.01ms
- Memory Usage: ~2-5MB for full cache
Optimization Tips
- Use Cache: Enable caching for repeated access
- Batch Operations: Load file once, parse multiple items
- Search Efficiently: Use search instead of iterating through all items
- Memory Management: Clear cache when memory is limited
import { ItemDescParser } from 'pw-item-desc-parser';
// Optimized usage
const parser = new ItemDescParser({ cacheSize: 5000 });
parser.loadFile(); // Load once
// Fast repeated access
for (const id of itemIds) {
const item = parser.parseById(id); // Uses cache
}Examples
Custom File Usage
import { ItemDescParser } from 'pw-item-desc-parser';
const parser = new ItemDescParser({
filePath: './my_custom_items.txt',
cacheSize: 2000,
encoding: 'utf16le'
});
const items = parser.loadFile();Error Handling
import { ItemDescParser } from 'pw-item-desc-parser';
try {
const parser = new ItemDescParser({ filePath: './nonexistent.txt' });
const items = parser.loadFile();
} catch (error) {
console.error('Failed to load file:', error.message);
}Advanced Search
import { ItemDescParser } from 'pw-item-desc-parser';
const parser = new ItemDescParser();
parser.loadFile();
// Case-sensitive search
const results = parser.searchDescriptions('INVENÇÃO', true);
// Filter by specific criteria
const filteredResults = results.filter(result =>
result.description.text.includes('magic')
);React Integration
Custom Hook
import { useState, useEffect, useMemo } from 'react';
import { ItemDescParser } from 'pw-item-desc-parser';
function useItemParser(filePath) {
const parser = useMemo(() => new ItemDescParser({ filePath }), [filePath]);
const [isLoaded, setIsLoaded] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
try {
parser.loadFile();
setIsLoaded(true);
setError(null);
} catch (err) {
setError(err.message);
setIsLoaded(false);
}
}, [parser]);
return { parser, isLoaded, error };
}
// Usage in component
function MyComponent() {
const { parser, isLoaded, error } = useItemParser();
if (error) return <div>Error: {error}</div>;
if (!isLoaded) return <div>Loading...</div>;
const item = parser.parseById(10037);
return <div dangerouslySetInnerHTML={{ __html: item?.formatted }} />;
}TypeScript Types
interface ParsedDescription {
text: string; // Original raw text
formatted: string; // HTML formatted text
}
interface ItemDescriptionMap {
[id: string]: ParsedDescription;
}
interface ParserOptions {
filePath?: string;
cacheSize?: number;
encoding?: string;
}Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
MIT License - see LICENSE file for details.
Changelog
1.0.0
- Initial release
- TypeScript support
- LRU caching
- React compatibility
- Search functionality
- Bundled default data file
