chromium/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_table.ts

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Holds information about a braille table.
 */
import {TestImportManager} from '/common/testing/test_import_manager.js';

import {Msgs} from '../msgs.js';

export namespace BrailleTable {
  export interface Table {
    locale: string;
    dots: string;
    id: string;
    grade?: string;
    variant?: string;
    fileNames: string;
    enDisplayName?: string;
    alwaysUseEnDisplayName: boolean;
  }

  export const TABLE_PATH = 'chromevox/third_party/liblouis/tables.json';

  /**
   * Retrieves a list of all available braille tables.
   * @param callback Called asynchronously with an array of tables.
   */
  export async function getAll(callback: (tables: Table[]) => void):
      Promise<void> {
    const needsDisambiguation = new Map();
    function preprocess(tables: Table[]): Table[] {
      tables.forEach((table: Table) => {
        // Append the common definitions to all table filenames.
        table.fileNames += (',' + COMMON_DEFS_FILENAME);

        // Save all tables which have a mirroring duplicate for locale + grade.
        const key = table.locale + table.grade;
        if (!needsDisambiguation.has(key)) {
          needsDisambiguation.set(key, []);
        }

        const entry = needsDisambiguation.get(key);
        entry.push(table);
      });

      for (const entry of needsDisambiguation.values()) {
        if (entry.length > 1) {
          entry.forEach((table: Table) => table.alwaysUseEnDisplayName = true);
        }
      }

      return tables;
    }
    const url = chrome.extension.getURL(BrailleTable.TABLE_PATH);
    if (!url) {
      throw 'Invalid path: ' + BrailleTable.TABLE_PATH;
    }


    const response = await fetch(url);
    if (response.ok) {
      const tables = await response.json() as Table[];
      callback(preprocess(tables));
    }
  }

  /**
   * Finds a table in a list of tables by id.
   * @param tables tables to search in.
   * @param id id of table to find.
   * @return The found table, or null if not found.
   */
  export function forId(tables: Table[], id: string): Table|null {
    return tables.filter(table => table.id === id)[0] || null;
  }

  /**
   * Returns an uncontracted braille table corresponding to another, possibly
   * contracted, table.  If {@code table} is the lowest-grade table for its
   * locale and dot count, {@code table} itself is returned.
   * @param tables tables to search in.
   * @param table Table to match.
   * @return {!BrailleTable.Table} Corresponding uncontracted table,
   *     or {@code table} if it is uncontracted.
   */
  export function getUncontracted(tables: Table[], table: Table): Table {
    function mostUncontractedOf(current: Table, candidate: Table): Table {
      // An 8 dot table for the same language is preferred over a 6 dot table
      // even if the locales differ by region.
      if (current.dots === '6' && candidate.dots === '8' &&
          current.locale.lastIndexOf(candidate.locale, 0) === 0) {
        return candidate;
      }
      if (current.locale === candidate.locale &&
          current.dots === candidate.dots && (current.grade !== undefined) &&
          (candidate.grade !== undefined) && candidate.grade < current.grade) {
        return candidate;
      }
      return current;
    }
    return tables.reduce(mostUncontractedOf, table);
  }

  /**
   * @param table Table to get name for.
   * @return Localized display name.
   */
  export function getDisplayName(table: Table): string|undefined {
    const uiLanguage = chrome.i18n.getUILanguage().toLowerCase();
    const localeName = chrome.accessibilityPrivate.getDisplayNameForLocale(
        table.locale /* locale to be displayed */,
        uiLanguage /* locale to localize into */);

    const enDisplayName = table.enDisplayName;
    if (!localeName && !enDisplayName) {
      return;
    }

    let baseName;
    if (enDisplayName &&
        (table.alwaysUseEnDisplayName || uiLanguage.startsWith('en') ||
         !localeName)) {
      baseName = enDisplayName;
    } else {
      baseName = localeName;
    }

    if (!table.grade && !table.variant) {
      return baseName;
    } else if (table.grade && !table.variant) {
      return Msgs.getMsg(
          'braille_table_name_with_grade', [baseName, table.grade]);
    } else if (!table.grade && table.variant) {
      return Msgs.getMsg(
          'braille_table_name_with_variant', [baseName, table.variant]);
    } else {
      // TODO(b/314203187): Not null asserted, check that this is correct.
      return Msgs.getMsg(
          'braille_table_name_with_variant_and_grade',
          [baseName, table.variant!, table.grade!]);
    }
  }
}

// Local to module.
const COMMON_DEFS_FILENAME = 'cvox-common.cti';

TestImportManager.exportForTesting(['BrailleTable', BrailleTable]);