Spaces:
Running
Running
| // One parser used across all tool pages. Handles: | |
| // - FASTA (headers starting with '>') | |
| // - plain newline-separated sequences | |
| // - comma-separated sequence lists | |
| // Returns a normalized list of { id, seq }. | |
| export interface ParsedSequence { | |
| id: string | |
| seq: string | |
| } | |
| const AA_RE = /[^A-Za-z]/g | |
| function cleanSeq(raw: string): string { | |
| return raw.replace(AA_RE, '').toUpperCase() | |
| } | |
| export function parseSequences(input: string): ParsedSequence[] { | |
| const text = input.trim() | |
| if (!text) return [] | |
| // FASTA path: contains at least one '>' header. | |
| if (text.includes('>')) { | |
| const out: ParsedSequence[] = [] | |
| let current: ParsedSequence | null = null | |
| for (const line of text.split(/\r?\n/)) { | |
| const trimmed = line.trim() | |
| if (!trimmed) continue | |
| if (trimmed.startsWith('>')) { | |
| if (current) out.push(current) | |
| const id = trimmed.slice(1).trim().split(/\s+/)[0] || `seq_${out.length + 1}` | |
| current = { id, seq: '' } | |
| } else if (current) { | |
| current.seq += cleanSeq(trimmed) | |
| } else { | |
| // sequence data before any header | |
| current = { id: `seq_1`, seq: cleanSeq(trimmed) } | |
| } | |
| } | |
| if (current) out.push(current) | |
| return out.filter((s) => s.seq.length > 0) | |
| } | |
| // Non-FASTA: split on commas and/or newlines. | |
| const tokens = text | |
| .split(/[,\n\r]+/) | |
| .map((t) => t.trim()) | |
| .filter(Boolean) | |
| return tokens | |
| .map((tok, i) => ({ id: `seq_${i + 1}`, seq: cleanSeq(tok) })) | |
| .filter((s) => s.seq.length > 0) | |
| } | |