/** @typedef {'https://' | 'http://' | ''} NavigationUrlPrefix */ /** * 네비게이션 URL 접두사 옵션 * @type {Array<{ value: NavigationUrlPrefix, label: string }>} */ export const navigationUrlPrefixOptions = [ { value: 'https://', label: 'https://' }, { value: 'http://', label: 'http://' }, { value: '', label: '내부 경로 (/)' } ] /** * 저장된 URL을 접두사와 본문으로 분리한다. * @param {string} url - 저장된 URL * @returns {{ prefix: NavigationUrlPrefix, body: string }} 접두사와 본문 */ export const splitNavigationUrl = (url) => { const trimmed = String(url || '').trim() if (!trimmed) { return { prefix: 'https://', body: '' } } if (trimmed === '#') { return { prefix: '', body: '#' } } if (trimmed.startsWith('/') && !trimmed.startsWith('//')) { return { prefix: '', body: trimmed } } if (trimmed.startsWith('http://')) { return { prefix: 'http://', body: trimmed.slice('http://'.length) } } if (trimmed.startsWith('https://')) { return { prefix: 'https://', body: trimmed.slice('https://'.length) } } if (trimmed.startsWith('//')) { return { prefix: 'https://', body: trimmed.slice('//'.length) } } return { prefix: 'https://', body: trimmed } } /** * 접두사와 본문을 저장용 URL로 합친다. * @param {NavigationUrlPrefix|string} prefix - URL 접두사 * @param {string} body - 호스트·경로 또는 내부 경로 * @returns {string} 합쳐진 URL */ export const composeNavigationUrl = (prefix, body) => { const input = String(body || '').trim() if (!input) { return '' } if (input === '#') { return '#' } const normalizedPrefix = String(prefix || '') if (!normalizedPrefix) { if (input.startsWith('/')) { return input } return `/${input.replace(/^\/+/, '')}` } const withoutProto = input.replace(/^https?:\/\//i, '').replace(/^\/+/, '') if (!withoutProto) { return '' } return `${normalizedPrefix}${withoutProto}` } /** * 네비게이션 URL을 저장용 형식으로 정규화한다. * @param {string} rawUrl - 입력 URL * @returns {string} 정규화된 URL */ export const normalizeNavigationUrl = (rawUrl) => { const trimmed = String(rawUrl || '').trim() if (!trimmed || trimmed === '#') { return trimmed } if (trimmed.startsWith('/') && !trimmed.startsWith('//')) { return trimmed } if (trimmed.startsWith('//')) { return `https:${trimmed}` } if (/^https?:\/\//i.test(trimmed)) { return trimmed } return `https://${trimmed.replace(/^\/+/, '')}` } /** * 저장 가능한 네비게이션 URL인지 확인한다. * @param {string} url - URL * @returns {boolean} 유효 여부 */ export const isValidNavigationUrl = (url) => /^(\/|https?:\/\/|#)/.test(String(url || '').trim())