fix(core): address white-box review feedback
- Fix unicode surrogate pairs and emoji slicing via Array.from in ORP calculator - Add slot smoothing constraint to pivot element to prevent horizontal jitter - Implement adaptive timestamp compensation and visibilitychange auto-pause - Slim storage layer by updating only STORE_META on progress changes with memory fallback - Align EPUB chapter indices to token array indices instead of raw character offsets - Support standalone emoji tokens via Extended_Pictographic regex - Code-split JSZip via dynamic import to optimize initial bundle size Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* Optimal Recognition Point (ORP) Calculation for Spritz RSVP Reading.
|
||||
* Fixates the eye at ~30%-35% into the word where human ocular fixation naturally rests.
|
||||
* Uses unicode-safe code point segmentation (Array.from) to eliminate surrogate pair
|
||||
* and emoji splitting defects.
|
||||
*/
|
||||
|
||||
const CJK_REGEX = /[一-龥-ヿ가-]/;
|
||||
@@ -15,9 +17,11 @@ export function isCJKWord(word: string): boolean {
|
||||
|
||||
/**
|
||||
* Calculates the 0-based index of the ORP character in cleanWord.
|
||||
* Based on unicode code-point length (Array.from(cleanWord).length).
|
||||
*/
|
||||
export function calculateOrpIndex(cleanWord: string): number {
|
||||
const len = cleanWord.length;
|
||||
const chars = Array.from(cleanWord);
|
||||
const len = chars.length;
|
||||
if (len <= 1) return 0;
|
||||
|
||||
if (isCJKWord(cleanWord)) {
|
||||
@@ -45,6 +49,7 @@ export interface SplitWord {
|
||||
/**
|
||||
* Splits a token into prefix, pivot (ORP character), and suffix.
|
||||
* Handles leading punctuation (e.g. "“", "《", "(") and trailing punctuation.
|
||||
* Operates purely on unicode code points to prevent corrupting surrogate pairs.
|
||||
*/
|
||||
export function splitOrp(
|
||||
coreWord: string,
|
||||
@@ -60,10 +65,11 @@ export function splitOrp(
|
||||
};
|
||||
}
|
||||
|
||||
const chars = Array.from(coreWord);
|
||||
const orpIndex = calculateOrpIndex(coreWord);
|
||||
const prefix = leadingPunct + coreWord.slice(0, orpIndex);
|
||||
const pivot = coreWord[orpIndex] || '';
|
||||
const suffix = coreWord.slice(orpIndex + 1) + trailingPunct;
|
||||
const prefix = leadingPunct + chars.slice(0, orpIndex).join('');
|
||||
const pivot = chars[orpIndex] || '';
|
||||
const suffix = chars.slice(orpIndex + 1).join('') + trailingPunct;
|
||||
|
||||
return {
|
||||
prefix,
|
||||
|
||||
Reference in New Issue
Block a user