|
1 | 1 | import { ReleaseInfo } from '../types'; |
2 | 2 |
|
3 | 3 | export const parseHackerReleaseFile = (text: string): ReleaseInfo[] => { |
| 4 | + // 1. Clean up outer brackets (start and end) |
| 5 | + const cleanText = text.replace(/^\s*\[/, '').replace(/\]\s*$/, '').trim(); |
| 6 | + |
| 7 | + // 2. Split into lines and filter empty ones |
| 8 | + const lines = cleanText.split('\n').map(l => l.trim()).filter(l => l.length > 0); |
| 9 | + |
4 | 10 | const releases: ReleaseInfo[] = []; |
5 | 11 |
|
6 | | - // Split by brackets to isolate blocks |
7 | | - // The format is [ ...content... ] |
8 | | - // We split by ']' to get chunks, then clean up the '[' |
9 | | - const blocks = text.split(']'); |
10 | | - |
11 | | - blocks.forEach(block => { |
12 | | - // Remove opening bracket and trim whitespace |
13 | | - const cleanBlock = block.replace('[', '').trim(); |
14 | | - |
15 | | - if (!cleanBlock) return; |
| 12 | + // State variables |
| 13 | + let currentVersion: string | null = null; |
| 14 | + let currentSection: 'new' | 'release' | 'description' | null = null; |
| 15 | + |
| 16 | + // Buffers for current release data |
| 17 | + let tempNews: string[] = []; |
| 18 | + let tempEditions: string[] = []; |
| 19 | + let tempDescription: string[] = []; |
16 | 20 |
|
17 | | - // Split into lines |
18 | | - const lines = cleanBlock.split('\n').map(line => line.trim()).filter(line => line.length > 0); |
| 21 | + // Helper to push the collected data to releases array |
| 22 | + const saveCurrentRelease = () => { |
| 23 | + if (currentVersion) { |
| 24 | + releases.push({ |
| 25 | + version: currentVersion, |
| 26 | + description: tempDescription.length > 0 ? tempDescription.join(' ') : '', |
| 27 | + news: tempNews.length > 0 ? tempNews.join('\n') : '', |
| 28 | + editions: tempEditions.length > 0 ? tempEditions.join('\n') : '' |
| 29 | + }); |
| 30 | + } |
| 31 | + }; |
19 | 32 |
|
20 | | - // According to spec, the structure is roughly: |
21 | | - // Line 1: Version |
22 | | - // Line 2: Editions/Dates |
23 | | - // Line 3+: News/Changelog |
| 33 | + for (const line of lines) { |
| 34 | + // Detect start of a new version (e.g., "V4.2", "V3.0") |
| 35 | + if (/^V\d/.test(line)) { |
| 36 | + // If we were already parsing a version, save it before starting a new one |
| 37 | + saveCurrentRelease(); |
| 38 | + |
| 39 | + // Reset state for new version |
| 40 | + currentVersion = line; |
| 41 | + currentSection = null; |
| 42 | + tempNews = []; |
| 43 | + tempEditions = []; |
| 44 | + tempDescription = []; |
| 45 | + continue; |
| 46 | + } |
| 47 | + |
| 48 | + // Detect Section Headers (case insensitive, handle potential trailing colons or spaces) |
| 49 | + const lowerLine = line.toLowerCase(); |
| 50 | + |
| 51 | + if (lowerLine.startsWith('new:')) { |
| 52 | + currentSection = 'new'; |
| 53 | + continue; |
| 54 | + } |
24 | 55 |
|
25 | | - if (lines.length >= 2) { |
26 | | - const version = lines[0]; |
27 | | - const editions = lines[1]; |
28 | | - // Join the rest of the lines as the news description |
29 | | - const news = lines.slice(2).join('\n'); |
| 56 | + if (lowerLine.startsWith('release:')) { |
| 57 | + currentSection = 'release'; |
| 58 | + continue; |
| 59 | + } |
30 | 60 |
|
31 | | - releases.push({ |
32 | | - version, |
33 | | - editions, |
34 | | - news |
35 | | - }); |
| 61 | + if (lowerLine.startsWith('description:')) { |
| 62 | + currentSection = 'description'; |
| 63 | + continue; |
| 64 | + } |
| 65 | + |
| 66 | + // Detect Content Items (starting with '=') |
| 67 | + if (line.startsWith('=')) { |
| 68 | + const content = line.substring(1).trim(); // Remove '=' and whitespace |
| 69 | + |
| 70 | + if (currentSection === 'new') { |
| 71 | + tempNews.push(content); |
| 72 | + } else if (currentSection === 'release') { |
| 73 | + tempEditions.push(content); |
| 74 | + } else if (currentSection === 'description') { |
| 75 | + tempDescription.push(content); |
| 76 | + } |
36 | 77 | } |
37 | | - }); |
| 78 | + } |
| 79 | + |
| 80 | + // Don't forget to save the very last release after the loop finishes |
| 81 | + saveCurrentRelease(); |
38 | 82 |
|
39 | 83 | return releases; |
40 | 84 | }; |
0 commit comments