<commit_before>import type { ParseMode, Style } from '../public/core';
import type { Keybinding, KeyboardLayoutName } from '../public/options';
import type {
  Mathfield,
  InsertOptions,
  OutputFormat,
  Offset,
  Range,
  Selection,
  FindOptions,
  ApplyStyleOptions,
  ReplacementFunction,
  VirtualKeyboardInterface,
} from '../public/mathfield';

import { Atom } from '../core/atom-class';

import { loadFonts } from '../core/fonts';
import { Stylesheet, inject as injectStylesheet } from '../common/stylesheet';

import { deleteRange, getMode, isRange, ModelPrivate } from '../editor/model';
import { applyStyle } from '../editor-model/styling';
import { delegateKeyboardEvents, KeyboardDelegate } from '../editor/keyboard';
import { UndoRecord, UndoManager } from '../editor/undo';
import { updatePopoverPosition } from '../editor/popover';
import { localize as l10n } from '../editor/l10n';
import {
  HAPTIC_FEEDBACK_DURATION,
  SelectorPrivate,
  perform,
  getCommandTarget,
} from '../editor/commands';
import { find, replace } from '../editor-model/find';
import { complete } from './autocomplete';
import { requestUpdate, render } from './render';
import {
  MathfieldOptionsPrivate,
  update as updateOptions,
  getDefault as getDefaultOptions,
  get as getOptions,
  effectiveMode,
  DEFAULT_KEYBOARD_TOGGLE_GLYPH,
} from '../editor/options';
import {
  removeComposition,
  updateComposition,
} from '../editor-model/composition';
import { addRowAfter, addColumnAfter } from '../editor-model/array';
import { onTypedText, onKeystroke } from './keyboard-input';

import './commands';
import './styling';

import {
  getCaretPoint,
  getSelectionBounds,
  getSharedElement,
  releaseSharedElement,
  isValidMathfield,
  on,
  off,
  Rect,
} from './utils';

import { attachButtonHandlers } from './buttons';
import { onPointerDown, offsetFromPoint } from './pointer-input';
import { normalizeKeybindings } from '../editor/keybindings';
import {
  setKeyboardLayoutLocale,
  getActiveKeyboardLayout,
  DEFAULT_KEYBOARD_LAYOUT,
} from '../editor/keyboard-layout';

import { VirtualKeyboard } from '../editor/virtual-keyboard';

// @ts-ignore-error
import mathfieldStylesheet from '../../css/mathfield.less';
// @ts-ignore-error
import coreStylesheet from '../../css/core.less';
// @ts-ignore-error
import popoverStylesheet from '../../css/popover.less';
// @ts-ignore-error
import keystrokeCaptionStylesheet from '../../css/keystroke-caption.less';
import { range } from '../editor-model/selection-utils';
import { LatexGroupAtom } from '../core-atoms/latex';
import { parseLatex } from '../core/parser';
import { ModeEditor } from './mode-editor';
import './mode-editor-math';
import { getLatexGroupBody } from './mode-editor-latex';
import './mode-editor-text';

import { PlaceholderAtom } from '../core-atoms/placeholder';
import { VirtualKeyboardDelegate } from './remote-virtual-keyboard';

export class MathfieldPrivate implements Mathfield {
  model: ModelPrivate;
  options: Required<MathfieldOptionsPrivate>;

  dirty: boolean; // If true, need to be redrawn
  smartModeSuppressed: boolean;

  element: HTMLElement & {
    mathfield?: MathfieldPrivate;
  };

  /** @deprecated */
  readonly originalContent: string;

  keyboardDelegate: KeyboardDelegate;
  field: HTMLElement;
  fieldContent: HTMLElement;
  virtualKeyboardToggle: HTMLElement;
  ariaLiveText: HTMLElement;
  accessibleNode: HTMLElement;
  popover: HTMLElement;

  keystrokeCaptionVisible: boolean;
  keystrokeCaption: HTMLElement;

  virtualKeyboard: VirtualKeyboardInterface;

  _keybindings: Keybinding[]; // Normalized keybindings (raw ones in config)
  keyboardLayout: KeyboardLayoutName;

  keystrokeBuffer: string;
  keystrokeBufferStates: UndoRecord[];
  keystrokeBufferResetTimer: ReturnType<typeof setTimeout>;

  suggestionIndex: number;

  mode: ParseMode;
  style: Style;

  keypressSound: HTMLAudioElement;
  spacebarKeypressSound: HTMLAudioElement;
  returnKeypressSound: HTMLAudioElement;
  deleteKeypressSound: HTMLAudioElement;
  plonkSound: HTMLAudioElement;

  private readonly undoManager: UndoManager;

  private blurred: boolean;
  // The value of the mathfield when it is focussed.
  // If this value is different when the field is blured
  // the `onCommit` listener is triggered
  private valueOnFocus: string;
  private eventHandlingInProgress = '';
  private readonly stylesheets: Stylesheet[] = [];
  private resizeTimer: number; // Timer handle

  _atomBoundsCache: Map<string, Rect>;

  /**
   * To create a mathfield, you would typically use {@linkcode makeMathField | MathLive.makeMathField()}
   * instead of invoking directly this constructor.
   *
   *
   * @param element - The DOM element that this mathfield is attached to.
   * Note that `element.mathfield` is this object.
   */
  constructor(
    element: HTMLElement & { mathfield?: MathfieldPrivate },
    options: Partial<MathfieldOptionsPrivate>
  ) {
    // Setup default config options
    this.options = updateOptions(getDefaultOptions(), {
      plonkSound: 'plonk.wav',
      keypressSound: {
        spacebar: 'keypress-spacebar.wav',
        return: 'keypress-return.wav',
        delete: 'keypress-delete.wav',
        default: 'keypress-standard.wav',
      },
      ...options,
    });

    // The virtual keyboard can be either attached to this mathfield
    // or a delegate that mirrors a global virtual keyboard attached
    // to the document. This is useful for example when using
    // mathfield in iframes so that all the mathfields share the keyboard
    // at the document level (rather than having one in each iframe)
    this.virtualKeyboard = options.useSharedVirtualKeyboard
      ? new VirtualKeyboardDelegate({
          targetOrigin: this.options.sharedVirtualKeyboardTargetOrigin,
          focus: () => this.focus(),
          blur: () => this.blur(),
          executeCommand: (command) => this.executeCommand(command),
          originValidator: this.options.originValidator,
        })
      : new VirtualKeyboard(this.options, {
          executeCommand: (command) => this.executeCommand(command),
        });

    this.plonkSound = this.options.plonkSound as HTMLAudioElement;
    if (
      typeof this.options.keypressSound !== 'string' &&
      !(this.options.keypressSound instanceof HTMLAudioElement)
    ) {
      this.keypressSound = this.options.keypressSound
        .default as HTMLAudioElement;
      this.spacebarKeypressSound = this.options.keypressSound
        .spacebar as HTMLAudioElement;
      this.returnKeypressSound = this.options.keypressSound<commit_msg>feat: if the mathfield is readonly, do not preload the sounds<commit_after>import type { ParseMode, Style } from '../public/core';
import type { Keybinding, KeyboardLayoutName } from '../public/options';
import type {
  Mathfield,
  InsertOptions,
  OutputFormat,
  Offset,
  Range,
  Selection,
  FindOptions,
  ApplyStyleOptions,
  ReplacementFunction,
  VirtualKeyboardInterface,
} from '../public/mathfield';

import { Atom } from '../core/atom-class';

import { loadFonts } from '../core/fonts';
import { Stylesheet, inject as injectStylesheet } from '../common/stylesheet';

import { deleteRange, getMode, isRange, ModelPrivate } from '../editor/model';
import { applyStyle } from '../editor-model/styling';
import { delegateKeyboardEvents, KeyboardDelegate } from '../editor/keyboard';
import { UndoRecord, UndoManager } from '../editor/undo';
import { updatePopoverPosition } from '../editor/popover';
import { localize as l10n } from '../editor/l10n';
import {
  HAPTIC_FEEDBACK_DURATION,
  SelectorPrivate,
  perform,
  getCommandTarget,
} from '../editor/commands';
import { find, replace } from '../editor-model/find';
import { complete } from './autocomplete';
import { requestUpdate, render } from './render';
import {
  MathfieldOptionsPrivate,
  update as updateOptions,
  getDefault as getDefaultOptions,
  get as getOptions,
  effectiveMode,
  DEFAULT_KEYBOARD_TOGGLE_GLYPH,
} from '../editor/options';
import {
  removeComposition,
  updateComposition,
} from '../editor-model/composition';
import { addRowAfter, addColumnAfter } from '../editor-model/array';
import { onTypedText, onKeystroke } from './keyboard-input';

import './commands';
import './styling';

import {
  getCaretPoint,
  getSelectionBounds,
  getSharedElement,
  releaseSharedElement,
  isValidMathfield,
  on,
  off,
  Rect,
} from './utils';

import { attachButtonHandlers } from './buttons';
import { onPointerDown, offsetFromPoint } from './pointer-input';
import { normalizeKeybindings } from '../editor/keybindings';
import {
  setKeyboardLayoutLocale,
  getActiveKeyboardLayout,
  DEFAULT_KEYBOARD_LAYOUT,
} from '../editor/keyboard-layout';

import { VirtualKeyboard } from '../editor/virtual-keyboard';

// @ts-ignore-error
import mathfieldStylesheet from '../../css/mathfield.less';
// @ts-ignore-error
import coreStylesheet from '../../css/core.less';
// @ts-ignore-error
import popoverStylesheet from '../../css/popover.less';
// @ts-ignore-error
import keystrokeCaptionStylesheet from '../../css/keystroke-caption.less';
import { range } from '../editor-model/selection-utils';
import { LatexGroupAtom } from '../core-atoms/latex';
import { parseLatex } from '../core/parser';
import { ModeEditor } from './mode-editor';
import './mode-editor-math';
import { getLatexGroupBody } from './mode-editor-latex';
import './mode-editor-text';

import { PlaceholderAtom } from '../core-atoms/placeholder';
import { VirtualKeyboardDelegate } from './remote-virtual-keyboard';

export class MathfieldPrivate implements Mathfield {
  model: ModelPrivate;
  options: Required<MathfieldOptionsPrivate>;

  dirty: boolean; // If true, need to be redrawn
  smartModeSuppressed: boolean;

  element: HTMLElement & {
    mathfield?: MathfieldPrivate;
  };

  /** @deprecated */
  readonly originalContent: string;

  keyboardDelegate: KeyboardDelegate;
  field: HTMLElement;
  fieldContent: HTMLElement;
  virtualKeyboardToggle: HTMLElement;
  ariaLiveText: HTMLElement;
  accessibleNode: HTMLElement;
  popover: HTMLElement;

  keystrokeCaptionVisible: boolean;
  keystrokeCaption: HTMLElement;

  virtualKeyboard: VirtualKeyboardInterface;

  _keybindings: Keybinding[]; // Normalized keybindings (raw ones in config)
  keyboardLayout: KeyboardLayoutName;

  keystrokeBuffer: string;
  keystrokeBufferStates: UndoRecord[];
  keystrokeBufferResetTimer: ReturnType<typeof setTimeout>;

  suggestionIndex: number;

  mode: ParseMode;
  style: Style;

  keypressSound: HTMLAudioElement;
  spacebarKeypressSound: HTMLAudioElement;
  returnKeypressSound: HTMLAudioElement;
  deleteKeypressSound: HTMLAudioElement;
  plonkSound: HTMLAudioElement;

  private readonly undoManager: UndoManager;

  private blurred: boolean;
  // The value of the mathfield when it is focussed.
  // If this value is different when the field is blured
  // the `onCommit` listener is triggered
  private valueOnFocus: string;
  private eventHandlingInProgress = '';
  private readonly stylesheets: Stylesheet[] = [];
  private resizeTimer: number; // Timer handle

  _atomBoundsCache: Map<string, Rect>;

  /**
   * To create a mathfield, you would typically use {@linkcode makeMathField | MathLive.makeMathField()}
   * instead of invoking directly this constructor.
   *
   *
   * @param element - The DOM element that this mathfield is attached to.
   * Note that `element.mathfield` is this object.
   */
  constructor(
    element: HTMLElement & { mathfield?: MathfieldPrivate },
    options: Partial<MathfieldOptionsPrivate>
  ) {
    // Setup default config options
    this.options = updateOptions(
      getDefaultOptions(),
      options.readOnly
        ? options
        : {
            plonkSound: 'plonk.wav',
            keypressSound: {
              spacebar: 'keypress-spacebar.wav',
              return: 'keypress-return.wav',
              delete: 'keypress-delete.wav',
              default: 'keypress-standard.wav',
            },
            ...options,
          }
    );

    // The virtual keyboard can be either attached to this mathfield
    // or a delegate that mirrors a global virtual keyboard attached
    // to the document. This is useful for example when using
    // mathfield in iframes so that all the mathfields share the keyboard
    // at the document level (rather than having one in each iframe)
    this.virtualKeyboard = options.useSharedVirtualKeyboard
      ? new VirtualKeyboardDelegate({
          targetOrigin: this.options.sharedVirtualKeyboardTargetOrigin,
          focus: () => this.focus(),
          blur: () => this.blur(),
          executeCommand: (command) => this.executeCommand(command),
          originValidator: this.options.originValidator,
        })
      : new VirtualKeyboard(this.options, {
          executeCommand: (command) => this.executeCommand(command),
        });

    this.plonkSound = this.options.plonkSound as HTMLAudioElement;
    if (
      typeof this.options.keypressSound !== 'string' &&
      !(this.options.keypressSound instanceof HTMLAudioElement)
    ) {
      this.keypressSound = this.options.keypressSound
        .default as HTMLAudioElement;
      this.spacebarKeypressSound = this.options.keypressSound
        .spacebar as HTMLAudioElement;
      this.returnKeypressSound = this.options.keypressSound
{'fraction_non_alphanumeric': 0.11352241263189404, 'fraction_numerical': 0.0005986679637805882, 'mean_word_length': 3.7660485021398005, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5888407', 'n_tokens_mistral': 3788, 'n_tokens_neox': 3784, 'n_words': 1002}