UNPKG

@jbrowse/core

Version:

JBrowse 2 core libraries used by plugins

63 lines (62 loc) 2.51 kB
const COORD_REGEX = /^(-?\d+)(?:(?:\.\.|[-–])(-?\d+))?(\.\.|[-–])?$/; const ASSEMBLY_REGEX = /^(?:\{([^}]+)\})?(.+)/; function parseCoords(suffix, locString) { const match = COORD_REGEX.exec(suffix.replaceAll(',', '')); if (!match) { throw new Error(`could not parse range "${suffix}" on location "${locString}"`); } const [, startStr, endStr, trailing] = match; const start = +startStr; return { start, end: endStr ? +endStr : trailing ? undefined : start }; } export function parseLocStringOneBased(locString, isValidRefName) { if (!locString) { throw new Error('no location string provided, could not parse'); } let reversed = false; if (locString.endsWith('[rev]')) { reversed = true; locString = locString.slice(0, -5); } locString = locString.replaceAll(/\s/g, ''); const assemblyMatch = ASSEMBLY_REGEX.exec(locString); if (!assemblyMatch) { throw new Error(`invalid location string: "${locString}"`); } const [, assemblyName, location] = assemblyMatch; if (!assemblyName && location.startsWith('{}')) { throw new Error(`no assembly name was provided in location "${location}"`); } const lastColonIdx = location.lastIndexOf(':'); if (lastColonIdx === -1) { if (isValidRefName(location, assemblyName)) { return { assemblyName, refName: location, reversed }; } throw new Error(`Unknown feature or sequence "${location}"`); } const prefix = location.slice(0, lastColonIdx); const suffix = location.slice(lastColonIdx + 1); const prefixValid = isValidRefName(prefix, assemblyName); const locationValid = isValidRefName(location, assemblyName); if (prefixValid && locationValid) { throw new Error(`ambiguous location string: "${locString}"`); } if (locationValid) { return { assemblyName, refName: location, reversed }; } if (prefixValid) { if (!suffix) { return { assemblyName, refName: prefix, reversed }; } const coords = parseCoords(suffix, locString); return { assemblyName, refName: prefix, reversed, ...coords }; } throw new Error(`unknown reference sequence name in location "${locString}"`); } export function parseLocString(locString, isValidRefName) { const parsed = parseLocStringOneBased(locString, isValidRefName); if (typeof parsed.start === 'number') { parsed.start -= 1; } return parsed; }