True clean start with src folder
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
export interface ExtractedItem {
|
||||
id: string;
|
||||
description: string;
|
||||
quantity: string;
|
||||
}
|
||||
|
||||
export function parseCSV(text: string): string[][] {
|
||||
const rows: string[][] = [];
|
||||
let currentRow: string[] = [];
|
||||
let currentCell = '';
|
||||
let inQuotes = false;
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const char = text[i];
|
||||
const nextChar = text[i + 1];
|
||||
|
||||
if (char === '"') {
|
||||
if (inQuotes && nextChar === '"') {
|
||||
currentCell += '"';
|
||||
i++;
|
||||
} else if (!inQuotes) {
|
||||
inQuotes = true;
|
||||
} else {
|
||||
const isClosing = nextChar === ',' || nextChar === '\r' || nextChar === '\n' || nextChar === undefined;
|
||||
if (isClosing) {
|
||||
inQuotes = false;
|
||||
} else {
|
||||
currentCell += '"';
|
||||
}
|
||||
}
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
currentRow.push(currentCell);
|
||||
currentCell = '';
|
||||
} else if ((char === '\r' || char === '\n') && !inQuotes) {
|
||||
if (currentCell || currentRow.length > 0) currentRow.push(currentCell);
|
||||
if (currentRow.length > 0) rows.push(currentRow);
|
||||
currentRow = [];
|
||||
currentCell = '';
|
||||
if (char === '\r' && nextChar === '\n') i++;
|
||||
} else {
|
||||
currentCell += char;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentCell || currentRow.length > 0) {
|
||||
currentRow.push(currentCell);
|
||||
rows.push(currentRow);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
export interface ExtractionResult {
|
||||
items: ExtractedItem[];
|
||||
ignored: string[][];
|
||||
}
|
||||
|
||||
export function extractItemsFromCSV(csvText: string): ExtractionResult {
|
||||
const rows = parseCSV(csvText);
|
||||
const extractedItems: ExtractedItem[] = [];
|
||||
const ignored: string[][] = [];
|
||||
|
||||
const regexInline = /^Item\s*:\s*([\s\S]*?)\s*\(\s*([\d,.]+)\s*\).*$/i;
|
||||
|
||||
rows.forEach(row => {
|
||||
let matched = false;
|
||||
row.forEach((cell, index) => {
|
||||
if (cell && typeof cell === 'string' && cell.trim().toLowerCase().startsWith('item')) {
|
||||
const cellContent = cell.trim();
|
||||
const match = cellContent.match(regexInline);
|
||||
|
||||
if (match) {
|
||||
let desc = match[1].trim().replace(/,\s*$/, '').trim();
|
||||
|
||||
extractedItems.push({
|
||||
id: crypto.randomUUID(),
|
||||
description: desc,
|
||||
quantity: match[2].trim()
|
||||
});
|
||||
matched = true;
|
||||
} else {
|
||||
let description = cellContent.replace(/^Item\s*:\s*/i, '').trim().replace(/,\s*$/, '').trim();
|
||||
|
||||
let quantity = '';
|
||||
if (index + 1 < row.length) {
|
||||
const nextCell = row[index + 1];
|
||||
if (nextCell) {
|
||||
const nextCellStr = nextCell.toString().trim();
|
||||
const qtyMatch = nextCellStr.match(/[\d,.]+/);
|
||||
if (qtyMatch) {
|
||||
quantity = qtyMatch[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extractedItems.push({
|
||||
id: crypto.randomUUID(),
|
||||
description,
|
||||
quantity: quantity || ""
|
||||
});
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!matched) {
|
||||
// Check if row is not just empty strings
|
||||
if (row.some(cell => cell.trim() !== '')) {
|
||||
ignored.push(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { items: extractedItems, ignored };
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,87 @@
|
||||
export interface ExtractedItem {
|
||||
id: string;
|
||||
description: string;
|
||||
quantity: string;
|
||||
}
|
||||
|
||||
export interface ExtractionResult {
|
||||
items: ExtractedItem[];
|
||||
ignored: string[][];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses raw XML text into a 2D array of strings based on <LINE> and <CELL> tags.
|
||||
*/
|
||||
export function parseXML(text: string): string[][] {
|
||||
const rows: string[][] = [];
|
||||
const lines = text.split('</LINE>');
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line.includes('<LINE>')) continue;
|
||||
|
||||
// Extract content inside <LINE> ... </LINE>
|
||||
const lineContent = line.substring(line.indexOf('<LINE>') + 6);
|
||||
const cells = lineContent.split('</CELL>');
|
||||
const currentRow: string[] = [];
|
||||
|
||||
for (const cell of cells) {
|
||||
if (!cell.includes('<CELL')) continue;
|
||||
|
||||
// Extract content inside <CELL ...> ... </CELL>
|
||||
const cellContent = cell.substring(cell.indexOf('>') + 1);
|
||||
currentRow.push(cellContent.trim());
|
||||
}
|
||||
|
||||
if (currentRow.length > 0) {
|
||||
rows.push(currentRow);
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts items from the parsed XML grid, matching the CSV parser's output structure.
|
||||
*/
|
||||
export function extractItemsFromXML(xmlText: string): ExtractionResult {
|
||||
const rows = parseXML(xmlText);
|
||||
const extractedItems: ExtractedItem[] = [];
|
||||
const ignored: string[][] = [];
|
||||
|
||||
rows.forEach(row => {
|
||||
let matched = false;
|
||||
|
||||
// Valid data lines in the provided XML have at least 8 columns.
|
||||
// Index 6 maps to "Item", Index 7 maps to "Order" (Quantity)
|
||||
if (row.length >= 8) {
|
||||
const itemDesc = row[6];
|
||||
const quantityStr = row[7];
|
||||
|
||||
// Filter out the header row ('Item') and empty/layout spacer rows ('.')
|
||||
if (itemDesc && quantityStr && itemDesc !== 'Item' && itemDesc !== '.') {
|
||||
const qtyMatch = quantityStr.match(/[\d,.]+/);
|
||||
|
||||
if (qtyMatch) {
|
||||
// Remove trailing commas, identically to the CSV parser logic
|
||||
const desc = itemDesc.replace(/,\s*$/, '').trim();
|
||||
|
||||
extractedItems.push({
|
||||
id: crypto.randomUUID(),
|
||||
description: desc,
|
||||
quantity: qtyMatch[0]
|
||||
});
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
// Check if row is not just empty strings, mimicking original logic
|
||||
if (row.some(cell => cell !== '')) {
|
||||
ignored.push(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { items: extractedItems, ignored };
|
||||
}
|
||||
Reference in New Issue
Block a user