diff options
Diffstat (limited to 'ext/js/display')
| -rw-r--r-- | ext/js/display/display-anki.js | 5 | ||||
| -rw-r--r-- | ext/js/display/display-generator.js | 26 | ||||
| -rw-r--r-- | ext/js/display/display.js | 14 | ||||
| -rw-r--r-- | ext/js/display/popup-main.js | 7 | ||||
| -rw-r--r-- | ext/js/display/query-parser.js | 40 | ||||
| -rw-r--r-- | ext/js/display/sandbox/pronunciation-generator.js | 24 | ||||
| -rw-r--r-- | ext/js/display/sandbox/structured-content-generator.js | 9 | ||||
| -rw-r--r-- | ext/js/display/search-display-controller.js | 4 | ||||
| -rw-r--r-- | ext/js/display/search-main.js | 10 | 
9 files changed, 63 insertions, 76 deletions
| diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js index c51ddfa2..5433142d 100644 --- a/ext/js/display/display-anki.js +++ b/ext/js/display/display-anki.js @@ -30,9 +30,8 @@ export class DisplayAnki {      /**       * @param {import('./display.js').Display} display       * @param {import('./display-audio.js').DisplayAudio} displayAudio -     * @param {import('../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil       */ -    constructor(display, displayAudio, japaneseUtil) { +    constructor(display, displayAudio) {          /** @type {import('./display.js').Display} */          this._display = display;          /** @type {import('./display-audio.js').DisplayAudio} */ @@ -42,7 +41,7 @@ export class DisplayAnki {          /** @type {?string} */          this._ankiFieldTemplatesDefault = null;          /** @type {AnkiNoteBuilder} */ -        this._ankiNoteBuilder = new AnkiNoteBuilder(japaneseUtil, new TemplateRendererProxy()); +        this._ankiNoteBuilder = new AnkiNoteBuilder(new TemplateRendererProxy());          /** @type {?import('./display-notification.js').DisplayNotification} */          this._errorNotification = null;          /** @type {?EventListenerCollection} */ diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index 7bf13b77..eef58bb0 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -16,10 +16,11 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ -import {isObject} from '../core/utilities.js';  import {ExtensionError} from '../core/extension-error.js'; +import {isObject} from '../core/utilities.js';  import {DictionaryDataUtil} from '../dictionary/dictionary-data-util.js';  import {HtmlTemplateCollection} from '../dom/html-template-collection.js'; +import {distributeFurigana, getKanaMorae, getPitchCategory, isCodePointKanji, isStringPartiallyJapanese} from '../language/japanese.js';  import {yomitan} from '../yomitan.js';  import {PronunciationGenerator} from './sandbox/pronunciation-generator.js';  import {StructuredContentGenerator} from './sandbox/structured-content-generator.js'; @@ -28,9 +29,7 @@ export class DisplayGenerator {      /**       * @param {import('display').DisplayGeneratorConstructorDetails} details       */ -    constructor({japaneseUtil, contentManager, hotkeyHelpController = null}) { -        /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ -        this._japaneseUtil = japaneseUtil; +    constructor({contentManager, hotkeyHelpController = null}) {          /** @type {import('./display-content-manager.js').DisplayContentManager} */          this._contentManager = contentManager;          /** @type {?import('../input/hotkey-help-controller.js').HotkeyHelpController} */ @@ -38,9 +37,9 @@ export class DisplayGenerator {          /** @type {HtmlTemplateCollection} */          this._templates = new HtmlTemplateCollection();          /** @type {StructuredContentGenerator} */ -        this._structuredContentGenerator = new StructuredContentGenerator(this._contentManager, japaneseUtil, document); +        this._structuredContentGenerator = new StructuredContentGenerator(this._contentManager, document);          /** @type {PronunciationGenerator} */ -        this._pronunciationGenerator = new PronunciationGenerator(japaneseUtil); +        this._pronunciationGenerator = new PronunciationGenerator();      }      /** */ @@ -725,11 +724,9 @@ export class DisplayGenerator {       * @returns {HTMLElement}       */      _createPronunciationPitchAccent(pitchAccent, details) { -        const jp = this._japaneseUtil; -          const {position, nasalPositions, devoicePositions, tags} = pitchAccent;          const {reading, exclusiveTerms, exclusiveReadings} = details; -        const morae = jp.getKanaMorae(reading); +        const morae = getKanaMorae(reading);          const node = this._instantiate('pronunciation'); @@ -912,10 +909,9 @@ export class DisplayGenerator {       * @param {string} text       */      _appendKanjiLinks(container, text) { -        const jp = this._japaneseUtil;          let part = '';          for (const c of text) { -            if (jp.isCodePointKanji(/** @type {number} */ (c.codePointAt(0)))) { +            if (isCodePointKanji(/** @type {number} */ (c.codePointAt(0)))) {                  if (part.length > 0) {                      container.appendChild(document.createTextNode(part));                      part = ''; @@ -969,7 +965,7 @@ export class DisplayGenerator {       */      _appendFurigana(container, term, reading, addText) {          container.lang = 'ja'; -        const segments = this._japaneseUtil.distributeFurigana(term, reading); +        const segments = distributeFurigana(term, reading);          for (const {text, reading: furigana} of segments) {              if (furigana) {                  const ruby = document.createElement('ruby'); @@ -1000,7 +996,7 @@ export class DisplayGenerator {      _setTextContent(node, value, language) {          if (typeof language === 'string') {              node.lang = language; -        } else if (this._japaneseUtil.isStringPartiallyJapanese(value)) { +        } else if (isStringPartiallyJapanese(value)) {              node.lang = 'ja';          } @@ -1017,7 +1013,7 @@ export class DisplayGenerator {          // cause the text to not copy correctly.          if (typeof language === 'string') {              node.lang = language; -        } else if (this._japaneseUtil.isStringPartiallyJapanese(value)) { +        } else if (isStringPartiallyJapanese(value)) {              node.lang = 'ja';          } @@ -1051,7 +1047,7 @@ export class DisplayGenerator {              if (termPronunciation.headwordIndex !== headwordIndex) { continue; }              for (const pronunciation of termPronunciation.pronunciations) {                  if (pronunciation.type !== 'pitch-accent') { continue; } -                const category = this._japaneseUtil.getPitchCategory(reading, pronunciation.position, isVerbOrAdjective); +                const category = getPitchCategory(reading, pronunciation.position, isVerbOrAdjective);                  if (category !== null) {                      categories.add(category);                  } diff --git a/ext/js/display/display.js b/ext/js/display/display.js index 689481f4..cff87309 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -48,11 +48,10 @@ export class Display extends EventDispatcher {       * @param {number|undefined} tabId       * @param {number|undefined} frameId       * @param {import('display').DisplayPageType} pageType -     * @param {import('../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil       * @param {import('../dom/document-focus-controller.js').DocumentFocusController} documentFocusController       * @param {import('../input/hotkey-handler.js').HotkeyHandler} hotkeyHandler       */ -    constructor(tabId, frameId, pageType, japaneseUtil, documentFocusController, hotkeyHandler) { +    constructor(tabId, frameId, pageType, documentFocusController, hotkeyHandler) {          super();          /** @type {number|undefined} */          this._tabId = tabId; @@ -60,8 +59,6 @@ export class Display extends EventDispatcher {          this._frameId = frameId;          /** @type {import('display').DisplayPageType} */          this._pageType = pageType; -        /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ -        this._japaneseUtil = japaneseUtil;          /** @type {import('../dom/document-focus-controller.js').DocumentFocusController} */          this._documentFocusController = documentFocusController;          /** @type {import('../input/hotkey-handler.js').HotkeyHandler} */ @@ -90,7 +87,6 @@ export class Display extends EventDispatcher {          this._hotkeyHelpController = new HotkeyHelpController();          /** @type {DisplayGenerator} */          this._displayGenerator = new DisplayGenerator({ -            japaneseUtil,              contentManager: this._contentManager,              hotkeyHelpController: this._hotkeyHelpController          }); @@ -132,8 +128,7 @@ export class Display extends EventDispatcher {          this._queryParserContainer = querySelectorNotNull(document, '#query-parser-container');          /** @type {QueryParser} */          this._queryParser = new QueryParser({ -            getSearchContext: this._getSearchContext.bind(this), -            japaneseUtil +            getSearchContext: this._getSearchContext.bind(this)          });          /** @type {HTMLElement} */          this._contentScrollElement = querySelectorNotNull(document, '#content-scroll'); @@ -240,11 +235,6 @@ export class Display extends EventDispatcher {          this._updateQueryParser();      } -    /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ -    get japaneseUtil() { -        return this._japaneseUtil; -    } -      /** @type {number} */      get depth() {          return this._depth; diff --git a/ext/js/display/popup-main.js b/ext/js/display/popup-main.js index d4f622f2..870e039e 100644 --- a/ext/js/display/popup-main.js +++ b/ext/js/display/popup-main.js @@ -19,7 +19,6 @@  import {log} from '../core/logger.js';  import {DocumentFocusController} from '../dom/document-focus-controller.js';  import {HotkeyHandler} from '../input/hotkey-handler.js'; -import {JapaneseUtil} from '../language/sandbox/japanese-util.js';  import {yomitan} from '../yomitan.js';  import {DisplayAnki} from './display-anki.js';  import {DisplayAudio} from './display-audio.js'; @@ -37,18 +36,16 @@ async function main() {          const {tabId, frameId} = await yomitan.api.frameInformationGet(); -        const japaneseUtil = new JapaneseUtil(null); -          const hotkeyHandler = new HotkeyHandler();          hotkeyHandler.prepare(); -        const display = new Display(tabId, frameId, 'popup', japaneseUtil, documentFocusController, hotkeyHandler); +        const display = new Display(tabId, frameId, 'popup', documentFocusController, hotkeyHandler);          await display.prepare();          const displayAudio = new DisplayAudio(display);          displayAudio.prepare(); -        const displayAnki = new DisplayAnki(display, displayAudio, japaneseUtil); +        const displayAnki = new DisplayAnki(display, displayAudio);          displayAnki.prepare();          const displayProfileSelection = new DisplayProfileSelection(display); diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js index e129e1be..eb053f38 100644 --- a/ext/js/display/query-parser.js +++ b/ext/js/display/query-parser.js @@ -19,6 +19,7 @@  import {EventDispatcher} from '../core/event-dispatcher.js';  import {log} from '../core/logger.js';  import {querySelectorNotNull} from '../dom/query-selector.js'; +import {convertHiraganaToKatakana, convertKatakanaToHiragana, isStringEntirelyKana} from '../language/japanese.js';  import {TextScanner} from '../language/text-scanner.js';  import {yomitan} from '../yomitan.js'; @@ -29,12 +30,10 @@ export class QueryParser extends EventDispatcher {      /**       * @param {import('display').QueryParserConstructorDetails} details       */ -    constructor({getSearchContext, japaneseUtil}) { +    constructor({getSearchContext}) {          super();          /** @type {import('display').GetSearchContextCallback} */          this._getSearchContext = getSearchContext; -        /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ -        this._japaneseUtil = japaneseUtil;          /** @type {string} */          this._text = '';          /** @type {?import('core').TokenObject} */ @@ -65,6 +64,10 @@ export class QueryParser extends EventDispatcher {              searchKanji: false,              searchOnClick: true          }); +        /** @type {?(import('../language/japanese-wanakana.js'))} */ +        this._japaneseWanakanaModule = null; +        /** @type {?Promise<import('../language/japanese-wanakana.js')>} */ +        this._japaneseWanakanaModuleImport = null;      }      /** @type {string} */ @@ -93,7 +96,7 @@ export class QueryParser extends EventDispatcher {              this._queryParser.dataset.termSpacing = `${termSpacing}`;          }          if (typeof readingMode === 'string') { -            this._readingMode = readingMode; +            this._setReadingMode(readingMode);          }          if (typeof useInternalParser === 'boolean') {              this._useInternalParser = useInternalParser; @@ -346,15 +349,15 @@ export class QueryParser extends EventDispatcher {      _convertReading(term, reading) {          switch (this._readingMode) {              case 'hiragana': -                return this._japaneseUtil.convertKatakanaToHiragana(reading); +                return convertKatakanaToHiragana(reading);              case 'katakana': -                return this._japaneseUtil.convertHiraganaToKatakana(reading); +                return convertHiraganaToKatakana(reading);              case 'romaji': -                if (this._japaneseUtil.convertToRomajiSupported()) { +                if (this._japaneseWanakanaModule !== null) {                      if (reading.length > 0) { -                        return this._japaneseUtil.convertToRomaji(reading); -                    } else if (this._japaneseUtil.isStringEntirelyKana(term)) { -                        return this._japaneseUtil.convertToRomaji(term); +                        return this._japaneseWanakanaModule.convertToRomaji(reading); +                    } else if (isStringEntirelyKana(term)) { +                        return this._japaneseWanakanaModule.convertToRomaji(term);                      }                  }                  return reading; @@ -398,4 +401,21 @@ export class QueryParser extends EventDispatcher {              node = node.parentNode;          }      } + +    /** +     * @param {import('settings').ParsingReadingMode} value +     */ +    _setReadingMode(value) { +        this._readingMode = value; +        if (value === 'romaji') { +            this._loadJapaneseWanakanaModule(); +        } +    } + +    /** */ +    _loadJapaneseWanakanaModule() { +        if (this._japaneseWanakanaModuleImport !== null) { return; } +        this._japaneseWanakanaModuleImport = import('../language/japanese-wanakana.js'); +        this._japaneseWanakanaModuleImport.then((value) => { this._japaneseWanakanaModule = value; }); +    }  } diff --git a/ext/js/display/sandbox/pronunciation-generator.js b/ext/js/display/sandbox/pronunciation-generator.js index cfcf82a1..45631e74 100644 --- a/ext/js/display/sandbox/pronunciation-generator.js +++ b/ext/js/display/sandbox/pronunciation-generator.js @@ -16,15 +16,9 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ -export class PronunciationGenerator { -    /** -     * @param {import('../../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil -     */ -    constructor(japaneseUtil) { -        /** @type {import('../../language/sandbox/japanese-util.js').JapaneseUtil} */ -        this._japaneseUtil = japaneseUtil; -    } +import {getKanaDiacriticInfo, isMoraPitchHigh} from '../../language/japanese.js'; +export class PronunciationGenerator {      /**       * @param {string[]} morae       * @param {number} downstepPosition @@ -33,7 +27,6 @@ export class PronunciationGenerator {       * @returns {HTMLSpanElement}       */      createPronunciationText(morae, downstepPosition, nasalPositions, devoicePositions) { -        const jp = this._japaneseUtil;          const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null;          const devoicePositionsSet = devoicePositions.length > 0 ? new Set(devoicePositions) : null;          const container = document.createElement('span'); @@ -41,8 +34,8 @@ export class PronunciationGenerator {          for (let i = 0, ii = morae.length; i < ii; ++i) {              const i1 = i + 1;              const mora = morae[i]; -            const highPitch = jp.isMoraPitchHigh(i, downstepPosition); -            const highPitchNext = jp.isMoraPitchHigh(i1, downstepPosition); +            const highPitch = isMoraPitchHigh(i, downstepPosition); +            const highPitchNext = isMoraPitchHigh(i1, downstepPosition);              const nasal = nasalPositionsSet !== null && nasalPositionsSet.has(i1);              const devoice = devoicePositionsSet !== null && devoicePositionsSet.has(i1); @@ -76,7 +69,7 @@ export class PronunciationGenerator {                  const n2 = characterNodes[0];                  const character = /** @type {string} */ (n2.textContent); -                const characterInfo = jp.getKanaDiacriticInfo(character); +                const characterInfo = getKanaDiacriticInfo(character);                  if (characterInfo !== null) {                      n1.dataset.originalText = mora;                      n2.dataset.originalText = character; @@ -111,7 +104,6 @@ export class PronunciationGenerator {       * @returns {SVGSVGElement}       */      createPronunciationGraph(morae, downstepPosition) { -        const jp = this._japaneseUtil;          const ii = morae.length;          const svgns = 'http://www.w3.org/2000/svg'; @@ -131,8 +123,8 @@ export class PronunciationGenerator {          const pathPoints = [];          for (let i = 0; i < ii; ++i) { -            const highPitch = jp.isMoraPitchHigh(i, downstepPosition); -            const highPitchNext = jp.isMoraPitchHigh(i + 1, downstepPosition); +            const highPitch = isMoraPitchHigh(i, downstepPosition); +            const highPitchNext = isMoraPitchHigh(i + 1, downstepPosition);              const x = i * 50 + 25;              const y = highPitch ? 25 : 75;              if (highPitch && !highPitchNext) { @@ -148,7 +140,7 @@ export class PronunciationGenerator {          pathPoints.splice(0, ii - 1);          { -            const highPitch = jp.isMoraPitchHigh(ii, downstepPosition); +            const highPitch = isMoraPitchHigh(ii, downstepPosition);              const x = ii * 50 + 25;              const y = highPitch ? 25 : 75;              this._addGraphTriangle(svg, svgns, x, y); diff --git a/ext/js/display/sandbox/structured-content-generator.js b/ext/js/display/sandbox/structured-content-generator.js index ee86a7f4..60bf0ee5 100644 --- a/ext/js/display/sandbox/structured-content-generator.js +++ b/ext/js/display/sandbox/structured-content-generator.js @@ -16,17 +16,16 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ +import {isStringPartiallyJapanese} from '../../language/japanese.js'; +  export class StructuredContentGenerator {      /**       * @param {import('../../display/display-content-manager.js').DisplayContentManager|import('../../templates/sandbox/anki-template-renderer-content-manager.js').AnkiTemplateRendererContentManager} contentManager -     * @param {import('../../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil       * @param {Document} document       */ -    constructor(contentManager, japaneseUtil, document) { +    constructor(contentManager, document) {          /** @type {import('../../display/display-content-manager.js').DisplayContentManager|import('../../templates/sandbox/anki-template-renderer-content-manager.js').AnkiTemplateRendererContentManager} */          this._contentManager = contentManager; -        /** @type {import('../../language/sandbox/japanese-util.js').JapaneseUtil} */ -        this._japaneseUtil = japaneseUtil;          /** @type {Document} */          this._document = document;      } @@ -164,7 +163,7 @@ export class StructuredContentGenerator {          if (typeof content === 'string') {              if (content.length > 0) {                  container.appendChild(this._createTextNode(content)); -                if (language === null && this._japaneseUtil.isStringPartiallyJapanese(content)) { +                if (language === null && isStringPartiallyJapanese(content)) {                      container.lang = 'ja';                  }              } diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index 594a80aa..ff4340c1 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -29,10 +29,9 @@ export class SearchDisplayController {       * @param {number|undefined} frameId       * @param {import('./display.js').Display} display       * @param {import('./display-audio.js').DisplayAudio} displayAudio -     * @param {import('../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil       * @param {import('./search-persistent-state-controller.js').SearchPersistentStateController} searchPersistentStateController       */ -    constructor(tabId, frameId, display, displayAudio, japaneseUtil, searchPersistentStateController) { +    constructor(tabId, frameId, display, displayAudio, searchPersistentStateController) {          /** @type {number|undefined} */          this._tabId = tabId;          /** @type {number|undefined} */ @@ -71,7 +70,6 @@ export class SearchDisplayController {          this._clipboardMonitorEnabled = false;          /** @type {ClipboardMonitor} */          this._clipboardMonitor = new ClipboardMonitor({ -            japaneseUtil,              clipboardReader: {                  getText: yomitan.api.clipboardGet.bind(yomitan.api)              } diff --git a/ext/js/display/search-main.js b/ext/js/display/search-main.js index 3cdd1f25..dedad163 100644 --- a/ext/js/display/search-main.js +++ b/ext/js/display/search-main.js @@ -16,11 +16,9 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ -import * as wanakana from '../../lib/wanakana.js';  import {log} from '../core/logger.js';  import {DocumentFocusController} from '../dom/document-focus-controller.js';  import {HotkeyHandler} from '../input/hotkey-handler.js'; -import {JapaneseUtil} from '../language/sandbox/japanese-util.js';  import {yomitan} from '../yomitan.js';  import {DisplayAnki} from './display-anki.js';  import {DisplayAudio} from './display-audio.js'; @@ -45,21 +43,19 @@ async function main() {          const {tabId, frameId} = await yomitan.api.frameInformationGet(); -        const japaneseUtil = new JapaneseUtil(wanakana); -          const hotkeyHandler = new HotkeyHandler();          hotkeyHandler.prepare(); -        const display = new Display(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler); +        const display = new Display(tabId, frameId, 'search', documentFocusController, hotkeyHandler);          await display.prepare();          const displayAudio = new DisplayAudio(display);          displayAudio.prepare(); -        const displayAnki = new DisplayAnki(display, displayAudio, japaneseUtil); +        const displayAnki = new DisplayAnki(display, displayAudio);          displayAnki.prepare(); -        const searchDisplayController = new SearchDisplayController(tabId, frameId, display, displayAudio, japaneseUtil, searchPersistentStateController); +        const searchDisplayController = new SearchDisplayController(tabId, frameId, display, displayAudio, searchPersistentStateController);          await searchDisplayController.prepare();          display.initializeState(); |