Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions src/lib/product-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,19 @@ export function parseProductOverview(md: string): ProductOverview | null {
if (!md || !md.trim()) return null

try {
// Normalize line endings (Windows CRLF → LF)
const normalizedMd = md.replace(/\r\n/g, '\n')

// Extract product name from first # heading
const nameMatch = md.match(/^#\s+(.+)$/m)
const nameMatch = normalizedMd.match(/^#\s+(.+)$/m)
const name = nameMatch?.[1]?.trim() || 'Product Overview'

// Extract description - content between ## Description and next ##
const descMatch = md.match(/## Description\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
const descMatch = normalizedMd.match(/## Description\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
const description = descMatch?.[1]?.trim() || ''

// Extract problems - ### Problem N: Title pattern
const problemsSection = md.match(/## Problems & Solutions\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
const problemsSection = normalizedMd.match(/## Problems & Solutions\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
const problems: Problem[] = []

if (problemsSection?.[1]) {
Expand All @@ -78,7 +81,7 @@ export function parseProductOverview(md: string): ProductOverview | null {
}

// Extract features - bullet list after ## Key Features
const featuresSection = md.match(/## Key Features\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
const featuresSection = normalizedMd.match(/## Key Features\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
const features: string[] = []

if (featuresSection?.[1]) {
Expand Down Expand Up @@ -122,8 +125,11 @@ export function parseProductRoadmap(md: string): ProductRoadmap | null {
try {
const sections: Section[] = []

// Normalize line endings (Windows CRLF → LF)
const normalizedMd = md.replace(/\r\n/g, '\n')

// Match sections with pattern ### N. Title
const sectionMatches = [...md.matchAll(/### (\d+)\.\s*(.+)\n+([\s\S]*?)(?=\n### |\n## |\n#[^#]|$)/g)]
const sectionMatches = [...normalizedMd.matchAll(/### (\d+)\.\s*(.+)\n+([\s\S]*?)(?=\n### |\n## |\n#[^#]|$)/g)]

for (const match of sectionMatches) {
const order = parseInt(match[1], 10)
Expand Down