UNPKG

@jager-ai/holy-editor

Version:

Rich text editor with Bible verse slash commands and PWA keyboard tracking, extracted from Holy Habit project

247 lines β€’ 8.86 kB
"use strict"; /** * Bible Verse Engine * * Core engine for Bible verse slash commands and API integration * Extracted from Holy Habit holy-editor-pro.js */ Object.defineProperty(exports, "__esModule", { value: true }); exports.BibleVerseEngine = void 0; const Editor_1 = require("../types/Editor"); class BibleVerseEngine { constructor(apiEndpoint, debounceMs) { this.cache = {}; this.lastInsertedRef = ''; this.lastInsertedTime = 0; this.debounceMs = 300; this.apiEndpoint = '/api/bible_verse_full.php'; if (apiEndpoint) { this.apiEndpoint = apiEndpoint; } if (debounceMs !== undefined) { this.debounceMs = debounceMs; } } /** * Get singleton instance */ static getInstance(apiEndpoint, debounceMs) { if (!BibleVerseEngine.instance) { BibleVerseEngine.instance = new BibleVerseEngine(apiEndpoint, debounceMs); } return BibleVerseEngine.instance; } /** * Parse slash commands from text */ parseSlashCommands(text) { const matches = []; for (const match of text.matchAll(BibleVerseEngine.CMD_RE)) { const ref = match[1].replace(/\u00A0/g, ''); // Remove NBSP const position = match.index || 0; if (this.isValidBibleRef(ref)) { matches.push({ ref, position, fullMatch: match[0] }); } } return matches; } /** * Validate Bible reference format (supports range verses) */ isValidBibleRef(ref) { // Format check const match = ref.match(BibleVerseEngine.BIBLE_REF_RE); if (!match) return false; const [, , , fromVerse, toVerse] = match; // Range verse validation if (toVerse) { const from = parseInt(fromVerse); const to = parseInt(toVerse); // End verse must be greater than start verse if (to < from) { return false; } // Limit range to 10 verses maximum if (to - from > 10) { console.warn('πŸ“– Range too large (max 10 verses):', ref); return false; } } // Book name validation const bookAbbr = ref.replace(/\s*\d.*$/, '').trim(); if (!BibleVerseEngine.ALL_BOOKS[bookAbbr]) { console.warn('πŸ“– Unsupported Bible book:', bookAbbr); return false; } // Duplicate prevention (debouncing) const now = Date.now(); if (ref === this.lastInsertedRef && now - this.lastInsertedTime < this.debounceMs) { console.log('πŸ“– Duplicate insertion prevented:', ref); return false; } console.log('πŸ“– Valid Bible reference:', ref); return true; } /** * Load verse from API with caching and error handling */ async loadVerse(ref) { // Check memory cache first const cachedVerse = this.cache[ref]; if (cachedVerse) { console.log('πŸ“– Loading verse from cache:', ref, cachedVerse); return cachedVerse; } // API call if not cached try { const url = `${this.apiEndpoint}?query=${encodeURIComponent(ref)}`; const response = await fetch(url, { cache: 'force-cache' }); if (!response.ok) { // Handle different error status codes await response.json().catch(() => ({})); switch (response.status) { case 404: throw new Editor_1.BibleApiError('Verse not found', 404); case 422: throw new Editor_1.BibleApiError('Invalid verse format', 422); case 500: throw new Editor_1.BibleApiError('Server error', 500); default: throw new Editor_1.BibleApiError('Network error', response.status); } } const data = await response.json(); // Handle new API response format (supports range verses) if (data.success && data.verses && data.verses.length > 0) { const verseData = { verses: data.verses, isRange: data.verses.length > 1 }; // Cache the result this.cache[ref] = verseData; console.log('πŸ“– Verse loaded successfully:', ref, verseData); return verseData; } else { console.warn('πŸ“– Verse not found:', ref); return null; } } catch (error) { if (error instanceof Editor_1.BibleApiError) { throw error; } console.error('πŸ“– Network connection error:', ref, error); throw new Editor_1.BibleApiError('Network connection failed', undefined, error); } } /** * Get book name from abbreviation */ getBookName(abbr) { return BibleVerseEngine.ALL_BOOKS[abbr]; } /** * Get all supported book abbreviations */ getSupportedBooks() { return Object.keys(BibleVerseEngine.ALL_BOOKS); } /** * Update duplicate prevention state */ updateInsertionState(ref) { this.lastInsertedRef = ref; this.lastInsertedTime = Date.now(); } /** * Clear cache */ clearCache() { this.cache = {}; console.log('πŸ“– Bible verse cache cleared'); } /** * Get cache stats */ getCacheStats() { const keys = Object.keys(this.cache); return { size: keys.length, keys }; } /** * Set API endpoint */ setApiEndpoint(endpoint) { this.apiEndpoint = endpoint; } /** * Set debounce time */ setDebounceMs(ms) { this.debounceMs = ms; } /** * Extract book abbreviation from reference */ extractBookAbbr(ref) { return ref.replace(/\s*\d.*$/, '').trim(); } /** * Check if reference is a range verse */ isRangeVerse(ref) { const match = ref.match(BibleVerseEngine.BIBLE_REF_RE); return match ? !!match[4] : false; } /** * Parse verse numbers from reference */ parseVerseNumbers(ref) { const match = ref.match(BibleVerseEngine.BIBLE_REF_RE); if (!match) return null; const [, , chapter, startVerse, endVerse] = match; return { chapter: parseInt(chapter) || 1, startVerse: parseInt(startVerse), endVerse: endVerse ? parseInt(endVerse) : undefined }; } } exports.BibleVerseEngine = BibleVerseEngine; // Bible book mappings (66 books total) BibleVerseEngine.OLD_TESTAMENT_BOOKS = { μ°½: 'μ°½μ„ΈκΈ°', 좜: 'μΆœμ• κ΅½κΈ°', 레: 'λ ˆμœ„κΈ°', λ―Ό: '민수기', μ‹ : 'μ‹ λͺ…κΈ°', 수: 'μ—¬ν˜Έμˆ˜μ•„', μ‚Ώ: '사사기', λ£»: 'λ£»κΈ°', 삼상: 'μ‚¬λ¬΄μ—˜μƒ', μ‚Όν•˜: 'μ‚¬λ¬΄μ—˜ν•˜', 왕상: '열왕기상', μ™•ν•˜: 'μ—΄μ™•κΈ°ν•˜', λŒ€μƒ: 'μ—­λŒ€μƒ', λŒ€ν•˜: 'μ—­λŒ€ν•˜', 슀: 'μ—μŠ€λΌ', 느: 'λŠν—€λ―Έμ•Ό', 에: 'μ—μŠ€λ”', μš₯: 'μš₯κΈ°', μ‹œ: 'μ‹œνŽΈ', 잠: 'μž μ–Έ', μ „: 'μ „λ„μ„œ', μ•„: 'μ•„κ°€', 사: '이사야', 렘: 'μ˜ˆλ ˆλ―Έμ•Ό', μ• : 'μ˜ˆλ ˆλ―Έμ•Όμ• κ°€', κ²”: 'μ—μŠ€κ²”', 단: 'λ‹€λ‹ˆμ—˜', 호: 'ν˜Έμ„Έμ•„', 욜: 'μš”μ—˜', μ•”: 'μ•„λͺ¨μŠ€', 옡: 'μ˜€λ°”λŒœ', 욘: 'μš”λ‚˜', λ―Έ: 'λ―Έκ°€', λ‚˜: 'λ‚˜ν›”', ν•©: 'ν•˜λ°•κ΅­', 슡: 'μŠ€λ°”λƒ', ν•™: 'ν•™κ°œ', μŠ₯: 'μŠ€κ°€λž΄', 말: '말라기' }; BibleVerseEngine.NEW_TESTAMENT_BOOKS = { 마: 'λ§ˆνƒœλ³΅μŒ', 막: 'λ§ˆκ°€λ³΅μŒ', λˆ…: 'λˆ„κ°€λ³΅μŒ', μš”: 'μš”ν•œλ³΅μŒ', ν–‰: '사도행전', 둬: 'λ‘œλ§ˆμ„œ', κ³ μ „: 'κ³ λ¦°λ„μ „μ„œ', κ³ ν›„: 'κ³ λ¦°λ„ν›„μ„œ', 갈: 'κ°ˆλΌλ””μ•„μ„œ', μ—‘: 'μ—λ² μ†Œμ„œ', 빌: 'λΉŒλ¦½λ³΄μ„œ', 골: 'κ³¨λ‘œμƒˆμ„œ', μ‚΄μ „: 'λ°μ‚΄λ‘œλ‹ˆκ°€μ „μ„œ', μ‚΄ν›„: 'λ°μ‚΄λ‘œλ‹ˆκ°€ν›„μ„œ', 딀전: 'λ””λͺ¨λ°μ „μ„œ', 딀후: 'λ””λͺ¨λ°ν›„μ„œ', λ”›: 'λ””λ„μ„œ', λͺ¬: '빌레λͺ¬μ„œ', 히: 'νžˆλΈŒλ¦¬μ„œ', μ•½: 'μ•Όκ³ λ³΄μ„œ', λ²§μ „: 'λ² λ“œλ‘œμ „μ„œ', λ²§ν›„: 'λ² λ“œλ‘œν›„μ„œ', μš”μΌ: 'μš”ν•œμΌμ„œ', μš”μ΄: 'μš”ν•œμ΄μ„œ', μš”μ‚Ό: 'μš”ν•œμ‚Όμ„œ', 유: 'μœ λ‹€μ„œ', 계: 'μš”ν•œκ³„μ‹œλ‘' }; BibleVerseEngine.ALL_BOOKS = { ...BibleVerseEngine.OLD_TESTAMENT_BOOKS, ...BibleVerseEngine.NEW_TESTAMENT_BOOKS }; // Regular expressions BibleVerseEngine.CMD_RE = /\/([^\s/]{1,24})/ug; BibleVerseEngine.BIBLE_REF_RE = /^([κ°€-힣A-Za-z]{1,6})(\d{0,3}):(\d{1,3})(?:-(\d{1,3}))?$/u; //# sourceMappingURL=BibleVerseEngine.js.map