All files / mutxt-react/src/translit TranslitService.ts

57.14% Statements 24/42
26.31% Branches 5/19
62.5% Functions 5/8
62.16% Lines 23/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 891x 1x 1x                   1x   5x     5x         5x     5x         5x 5x 5x 5x 5x         6x 6x 5x 5x 5x                 5x 5x 5x 5x         1x                                                        
import {rsync} from '@jsonjoy.com/ui';
import {CompiledScheme} from './Matcher';
import {defaultSchemes, schemeMap} from './schemes';
import type {TranslitScheme} from './types';
 
/**
 * Headless translit service. Owns:
 *
 * - the registry of available schemes
 * - the active scheme id (`null` = mode off)
 * - a cache of compiled schemes
 */
export class TranslitService {
  /** Active scheme id, or null when mode is off. */
  public readonly active = rsync.val<string | null>(null);
 
  /** Last-used scheme id (so a no-arg toggle can restore the last selection). */
  public readonly lastUsed = rsync.val<string | null>(null);
 
  /** Registry of all schemes available to this service. */
  public readonly schemes: Map<string, TranslitScheme>;
 
  private readonly _compiled = new Map<string, CompiledScheme>();
 
  constructor(schemes: Iterable<TranslitScheme> = defaultSchemes) {
    this.schemes = schemeMap(schemes);
  }
 
  /** Lazy-compile and cache. */
  public compile(scheme: TranslitScheme): CompiledScheme {
    const cached = this._compiled.get(scheme.id);
    Iif (cached) return cached;
    const c = new CompiledScheme(scheme);
    this._compiled.set(scheme.id, c);
    return c;
  }
 
  /** The currently active compiled scheme, or null. */
  public activeScheme(): CompiledScheme | null {
    const id = this.active.value;
    if (!id) return null;
    const scheme = this.schemes.get(id);
    Iif (!scheme) return null;
    return this.compile(scheme);
  }
 
  public list(): TranslitScheme[] {
    return Array.from(this.schemes.values());
  }
 
  /** Switch on with a specific scheme. */
  public on(id: string): boolean {
    Iif (!this.schemes.has(id)) return false;
    this.lastUsed.set(id);
    this.active.set(id);
    return true;
  }
 
  /** Switch off. */
  public off(): void {
    this.active.set(null);
  }
 
  /** Toggle the mode. With no arg: flip current state, restoring `lastUsed`
   * if turning on. With an id: switch to that scheme. */
  public toggle(id?: string): void {
    if (id) {
      if (this.active.value === id) {
        this.off();
        return;
      }
      this.on(id);
      return;
    }
    if (this.active.value) {
      this.off();
      return;
    }
    const restore = this.lastUsed.value ?? this.list()[0]?.id;
    if (restore) this.on(restore);
  }
 
  /** Add a custom scheme to the registry. */
  public register(scheme: TranslitScheme): void {
    this.schemes.set(scheme.id, scheme);
    this._compiled.delete(scheme.id);
  }
}