(text, name)
| 768 | } |
| 769 | |
| 770 | function parseTxtPalette(text, name) { |
| 771 | const lines = text.split(/\r?\n/); |
| 772 | const colors = []; |
| 773 | for (const line of lines) { |
| 774 | const trimmed = line.trim(); |
| 775 | if (!trimmed || trimmed.startsWith('#') && trimmed.length <= 1) continue; |
| 776 | |
| 777 | // Try hex |
| 778 | const rgb = hexToRgb(trimmed); |
| 779 | if (rgb) { |
| 780 | colors.push(rgb); |
| 781 | continue; |
| 782 | } |
| 783 | |
| 784 | // Try rgb(R, G, B) |
| 785 | const rgbMatch = trimmed.match(/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/i); |
| 786 | if (rgbMatch) { |
| 787 | colors.push([ |
| 788 | Math.min(255, Math.max(0, parseInt(rgbMatch[1]))), |
| 789 | Math.min(255, Math.max(0, parseInt(rgbMatch[2]))), |
| 790 | Math.min(255, Math.max(0, parseInt(rgbMatch[3]))), |
| 791 | ]); |
| 792 | continue; |
| 793 | } |
| 794 | |
| 795 | // Try R, G, B (comma-separated) |
| 796 | const parts = trimmed.split(',').map(s => s.trim()); |
| 797 | if (parts.length >= 3) { |
| 798 | const r = Math.min(255, Math.max(0, parseInt(parts[0], 10) || 0)); |
| 799 | const g = Math.min(255, Math.max(0, parseInt(parts[1], 10) || 0)); |
| 800 | const b = Math.min(255, Math.max(0, parseInt(parts[2], 10) || 0)); |
| 801 | colors.push([r, g, b]); |
| 802 | } |
| 803 | } |
| 804 | if (colors.length < 2) throw new Error('Palette must contain at least 2 colors'); |
| 805 | return { id: name.replace(/\.[^.]+$/, ''), displayName: name.replace(/\.[^.]+$/, ''), colors }; |
| 806 | } |
| 807 | |
| 808 | function parsePaletteFile(filename, text) { |
| 809 | const ext = filename.split('.').pop().toLowerCase(); |
no test coverage detected