diff --git a/dragon-item-parser/src/item.ts b/dragon-item-parser/src/item.ts index b860de5..1c13199 100644 --- a/dragon-item-parser/src/item.ts +++ b/dragon-item-parser/src/item.ts @@ -506,53 +506,98 @@ function parseEffects(description: string): ItemEffect[] { for (const line of lines) { if (!line) continue - // Check for passive tag - const passiveMatch = line.match(/([^<]*)<\/passive>/i) + // Check for passive tag at the START of the line (effect header) + // Only treat as a new effect if the line starts with the tag or the tag is the only content + const passiveMatch = line.match(/^([^<]*)<\/passive>(.*)$/i) if (passiveMatch) { + const remainingContent = passiveMatch[2].trim() + // If there's content after the tag on the same line, it's part of description + // If the tag is the only content, this is just an effect header + if (!remainingContent) { + // This is an effect header line - start a new effect + if (currentEffect) { + effects.push(currentEffect) + } + currentEffect = { + type: 'passive', + name: passiveMatch[1].trim(), + description: [], + isUnique: false + } + continue + } + // If there's content after, check if it looks like a description (not just a label) + // For now, treat lines starting with passive tag as new effects if (currentEffect) { effects.push(currentEffect) } - // Remove the passive tag from the line before parsing description - const lineWithoutTag = line.replace(/[^<]*<\/passive>/i, '').trim() currentEffect = { type: 'passive', name: passiveMatch[1].trim(), - description: parseTextSegments(lineWithoutTag), + description: parseTextSegments(remainingContent), isUnique: false } continue } - // Check for active tag - const activeMatch = line.match(/([^<]*)<\/active>/i) + // Check for active tag at the START of the line + const activeMatch = line.match(/^([^<]*)<\/active>(.*)$/i) if (activeMatch) { + const remainingContent = activeMatch[2].trim() + // Skip lines that are just "ACTIVE" labels (like "(0s)" cooldown indicators) + const effectName = activeMatch[1].trim() + if (effectName.toUpperCase() === 'ACTIVE' && remainingContent.match(/^\([^)]*\)\s*$/)) { + // This is just a cooldown label, skip it + continue + } + + if (!remainingContent) { + // This is an effect header line - start a new effect + if (currentEffect) { + effects.push(currentEffect) + } + currentEffect = { + type: 'active', + name: effectName, + description: [], + isUnique: false + } + continue + } + // If there's content after, it's the description if (currentEffect) { effects.push(currentEffect) } - // Remove the active tag from the line before parsing description - const lineWithoutTag = line.replace(/[^<]*<\/active>/i, '').trim() currentEffect = { type: 'active', - name: activeMatch[1].trim(), - description: parseTextSegments(lineWithoutTag), + name: effectName, + description: parseTextSegments(remainingContent), isUnique: false } continue } - // Check for unique tag - const uniqueMatch = line.match(/([^<]*)<\/unique>/i) + // Check for unique tag at the START of the line + const uniqueMatch = line.match(/^([^<]*)<\/unique>(.*)$/i) if (uniqueMatch) { + const remainingContent = uniqueMatch[2].trim() if (currentEffect) { effects.push(currentEffect) } - // Remove the unique tag from the line before parsing description - const lineWithoutTag = line.replace(/[^<]*<\/unique>/i, '').trim() - currentEffect = { - type: 'unique', - name: uniqueMatch[1].trim() || undefined, - description: parseTextSegments(lineWithoutTag), - isUnique: true + if (!remainingContent) { + currentEffect = { + type: 'unique', + name: uniqueMatch[1].trim() || undefined, + description: [], + isUnique: true + } + } else { + currentEffect = { + type: 'unique', + name: uniqueMatch[1].trim() || undefined, + description: parseTextSegments(remainingContent), + isUnique: true + } } continue }