diff --git a/ext/bg/js/audio-downloader.js b/ext/bg/js/audio-downloader.js index 8dd5d10f..1a3428e1 100644 --- a/ext/bg/js/audio-downloader.js +++ b/ext/bg/js/audio-downloader.js @@ -17,11 +17,11 @@ /* global * SimpleDOMParser - * jp */ class AudioDownloader { - constructor({requestBuilder}) { + constructor({japaneseUtil, requestBuilder}) { + this._japaneseUtil = japaneseUtil; this._requestBuilder = requestBuilder; this._getInfoHandlers = new Map([ ['jpod101', this._getInfoJpod101.bind(this)], @@ -89,7 +89,7 @@ class AudioDownloader { let kana = reading; let kanji = expression; - if (!kana && jp.isStringEntirelyKana(kanji)) { + if (!kana && this._japaneseUtil.isStringEntirelyKana(kanji)) { kana = kanji; kanji = null; } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 6ff4e3f7..f9c308e5 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -22,6 +22,7 @@ * ClipboardReader * DictionaryDatabase * Environment + * JapaneseUtil * JsonSchemaValidator * Mecab * MediaUtility @@ -30,14 +31,18 @@ * ProfileConditions * RequestBuilder * Translator - * jp + * wanakana */ class Backend { constructor() { + this._japaneseUtil = new JapaneseUtil(wanakana); this._environment = new Environment(); this._dictionaryDatabase = new DictionaryDatabase(); - this._translator = new Translator(this._dictionaryDatabase); + this._translator = new Translator({ + japaneseUtil: this._japaneseUtil, + database: this._dictionaryDatabase + }); this._anki = new AnkiConnect(); this._mecab = new Mecab(); this._mediaUtility = new MediaUtility(); @@ -48,6 +53,7 @@ class Backend { mediaUtility: this._mediaUtility }); this._clipboardMonitor = new ClipboardMonitor({ + japaneseUtil: this._japaneseUtil, clipboardReader: this._clipboardReader }); this._options = null; @@ -57,6 +63,7 @@ class Backend { this._defaultAnkiFieldTemplates = null; this._requestBuilder = new RequestBuilder(); this._audioDownloader = new AudioDownloader({ + japaneseUtil: this._japaneseUtil, requestBuilder: this._requestBuilder }); this._optionsUtil = new OptionsUtil(); @@ -952,6 +959,7 @@ class Backend { } async _textParseScanning(text, options) { + const jp = this._japaneseUtil; const {scanning: {length: scanningLength}, parsing: {readingMode}} = options; const findTermsOptions = this._getTranslatorFindTermsOptions({wildcard: null}, options); const results = []; @@ -981,6 +989,7 @@ class Backend { } async _textParseMecab(text, options) { + const jp = this._japaneseUtil; const {parsing: {readingMode}} = options; const results = []; const rawResults = await this._mecab.parseText(text); diff --git a/ext/bg/js/clipboard-monitor.js b/ext/bg/js/clipboard-monitor.js index 4d980e11..5be6d373 100644 --- a/ext/bg/js/clipboard-monitor.js +++ b/ext/bg/js/clipboard-monitor.js @@ -15,18 +15,15 @@ * along with this program. If not, see . */ -/* global - * jp - */ - class ClipboardMonitor extends EventDispatcher { - constructor({clipboardReader}) { + constructor({japaneseUtil, clipboardReader}) { super(); + this._japaneseUtil = japaneseUtil; + this._clipboardReader = clipboardReader; this._timerId = null; this._timerToken = null; this._interval = 250; this._previousText = null; - this._clipboardReader = clipboardReader; } start() { @@ -53,7 +50,7 @@ class ClipboardMonitor extends EventDispatcher { text !== this._previousText ) { this._previousText = text; - if (jp.isStringPartiallyJapanese(text)) { + if (this._japaneseUtil.isStringPartiallyJapanese(text)) { this.trigger('change', {text}); } } diff --git a/ext/bg/js/search-main.js b/ext/bg/js/search-main.js index 07130631..f98028b3 100644 --- a/ext/bg/js/search-main.js +++ b/ext/bg/js/search-main.js @@ -17,7 +17,9 @@ /* global * DisplaySearch + * JapaneseUtil * api + * wanakana */ (async () => { @@ -25,7 +27,8 @@ api.forwardLogsToBackend(); await yomichan.backendReady(); - const displaySearch = new DisplaySearch(); + const japaneseUtil = new JapaneseUtil(wanakana); + const displaySearch = new DisplaySearch(japaneseUtil); await displaySearch.prepare(); document.documentElement.dataset.loaded = 'true'; diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index effa31bc..d99e76e0 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -24,8 +24,8 @@ */ class DisplaySearch extends Display { - constructor() { - super('search'); + constructor(japaneseUtil) { + super('search', japaneseUtil); this._searchButton = document.querySelector('#search-button'); this._queryInput = document.querySelector('#search-textbox'); this._introElement = document.querySelector('#intro'); @@ -38,6 +38,7 @@ class DisplaySearch extends Display { this._introAnimationTimer = null; this._clipboardMonitorEnabled = false; this._clipboardMonitor = new ClipboardMonitor({ + japaneseUtil, clipboardReader: { getText: async () => (await api.clipboardGet()) } @@ -129,7 +130,7 @@ class DisplaySearch extends Display { postProcessQuery(query) { if (this._wanakanaEnabled) { try { - query = wanakana.toKana(query); + query = this._japaneseUtil.convertToKana(query); } catch (e) { // NOP } diff --git a/ext/bg/js/settings/pitch-accents-preview-main.js b/ext/bg/js/settings/pitch-accents-preview-main.js index 59e5b194..23814089 100644 --- a/ext/bg/js/settings/pitch-accents-preview-main.js +++ b/ext/bg/js/settings/pitch-accents-preview-main.js @@ -21,7 +21,10 @@ (async () => { try { - const displayGenerator = new DisplayGenerator({mediaLoader: null}); + const displayGenerator = new DisplayGenerator({ + japaneseUtil: null, + mediaLoader: null + }); await displayGenerator.prepare(); displayGenerator.preparePitchAccents(); } catch (e) { diff --git a/ext/bg/js/template-renderer-frame-main.js b/ext/bg/js/template-renderer-frame-main.js index 7d3e1493..171028a3 100644 --- a/ext/bg/js/template-renderer-frame-main.js +++ b/ext/bg/js/template-renderer-frame-main.js @@ -16,12 +16,14 @@ */ /* globals + * JapaneseUtil * TemplateRenderer * TemplateRendererFrameApi */ (() => { - const templateRenderer = new TemplateRenderer(); + const japaneseUtil = new JapaneseUtil(null); + const templateRenderer = new TemplateRenderer(japaneseUtil); const api = new TemplateRendererFrameApi(templateRenderer); api.prepare(); })(); diff --git a/ext/bg/js/template-renderer.js b/ext/bg/js/template-renderer.js index c1995acd..6a76a4e6 100644 --- a/ext/bg/js/template-renderer.js +++ b/ext/bg/js/template-renderer.js @@ -17,11 +17,11 @@ /* global * Handlebars - * jp */ class TemplateRenderer { - constructor() { + constructor(japaneseUtil) { + this._japaneseUtil = japaneseUtil; this._cache = new Map(); this._cacheMaxSize = 5; this._helpersRegistered = false; @@ -119,7 +119,7 @@ class TemplateRenderer { _furigana(context, ...args) { const {expression, reading} = this._getFuriganaExpressionAndReading(context, ...args); - const segs = jp.distributeFurigana(expression, reading); + const segs = this._japaneseUtil.distributeFurigana(expression, reading); let result = ''; for (const seg of segs) { @@ -135,7 +135,7 @@ class TemplateRenderer { _furiganaPlain(context, ...args) { const {expression, reading} = this._getFuriganaExpressionAndReading(context, ...args); - const segs = jp.distributeFurigana(expression, reading); + const segs = this._japaneseUtil.distributeFurigana(expression, reading); let result = ''; for (const seg of segs) { @@ -161,6 +161,7 @@ class TemplateRenderer { } _kanjiLinks(context, options) { + const jp = this._japaneseUtil; let result = ''; for (const c of options.fn(context)) { if (jp.isCodePointKanji(c.codePointAt(0))) { @@ -385,10 +386,10 @@ class TemplateRenderer { } _isMoraPitchHigh(context, index, position) { - return jp.isMoraPitchHigh(index, position); + return this._japaneseUtil.isMoraPitchHigh(index, position); } _getKanaMorae(context, text) { - return jp.getKanaMorae(`${text}`); + return this._japaneseUtil.getKanaMorae(`${text}`); } } diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 45d7f17a..f577d0e1 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -18,7 +18,6 @@ /* global * Deinflector * TextSourceMap - * jp */ /** @@ -29,7 +28,8 @@ class Translator { * Creates a new Translator instance. * @param database An instance of DictionaryDatabase. */ - constructor(database) { + constructor({japaneseUtil, database}) { + this._japaneseUtil = japaneseUtil; this._database = database; this._deinflector = null; this._tagCache = new Map(); @@ -318,6 +318,7 @@ class Translator { collapseEmphaticOptions ]; + const jp = this._japaneseUtil; const deinflections = []; const used = new Set(); for (const [halfWidth, numeric, alphabetic, katakana, hiragana, [collapseEmphatic, collapseEmphaticFull]] of this._getArrayVariants(textOptionVariantArray)) { @@ -846,6 +847,7 @@ class Translator { return text; } + const jp = this._japaneseUtil; let newText = ''; for (const c of text) { if (!jp.isCodePointJapanese(c.codePointAt(0))) { @@ -1031,7 +1033,7 @@ class Translator { this._sortTags(definitionTagsExpanded); this._sortTags(termTagsExpanded); - const furiganaSegments = jp.distributeFurigana(expression, reading); + const furiganaSegments = this._japaneseUtil.distributeFurigana(expression, reading); const termDetailsList = [this._createTermDetails(sourceTerm, expression, reading, furiganaSegments, termTagsExpanded)]; const sourceTermExactMatchCount = (sourceTerm === expression ? 1 : 0); diff --git a/ext/fg/js/float-main.js b/ext/fg/js/float-main.js index 6b4daebb..a8554867 100644 --- a/ext/fg/js/float-main.js +++ b/ext/fg/js/float-main.js @@ -17,6 +17,7 @@ /* global * Display + * JapaneseUtil * api */ @@ -25,7 +26,8 @@ api.forwardLogsToBackend(); await yomichan.backendReady(); - const display = new Display('popup'); + const japaneseUtil = new JapaneseUtil(null); + const display = new Display('popup', japaneseUtil); await display.prepare(); display.initializeState(); diff --git a/ext/mixed/js/display-generator.js b/ext/mixed/js/display-generator.js index 63140330..82f6199b 100644 --- a/ext/mixed/js/display-generator.js +++ b/ext/mixed/js/display-generator.js @@ -19,11 +19,11 @@ * DictionaryDataUtil * HtmlTemplateCollection * api - * jp */ class DisplayGenerator { - constructor({mediaLoader}) { + constructor({japaneseUtil, mediaLoader}) { + this._japaneseUtil = japaneseUtil; this._mediaLoader = mediaLoader; this._templates = null; this._termPitchAccentStaticTemplateIsSetup = false; @@ -354,6 +354,7 @@ class DisplayGenerator { } _createPitch(details) { + const jp = this._japaneseUtil; const {reading, position, tags, exclusiveExpressions, exclusiveReadings} = details; const morae = jp.getKanaMorae(reading); @@ -417,6 +418,7 @@ class DisplayGenerator { } _populatePitchGraph(svg, position, morae) { + const jp = this._japaneseUtil; const svgns = svg.getAttribute('xmlns'); const ii = morae.length; svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`); @@ -475,6 +477,7 @@ class DisplayGenerator { } _appendKanjiLinks(container, text) { + const jp = this._japaneseUtil; let part = ''; for (const c of text) { if (jp.isCodePointKanji(c.codePointAt(0))) { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index f3aead44..b9daa9a0 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -34,9 +34,10 @@ */ class Display extends EventDispatcher { - constructor(pageType) { + constructor(pageType, japaneseUtil) { super(); this._pageType = pageType; + this._japaneseUtil = japaneseUtil; this._container = document.querySelector('#definitions'); this._definitions = []; this._optionsContext = {depth: 0, url: window.location.href}; @@ -53,7 +54,10 @@ class Display extends EventDispatcher { this._autoPlayAudioTimer = null; this._autoPlayAudioDelay = 400; this._mediaLoader = new MediaLoader(); - this._displayGenerator = new DisplayGenerator({mediaLoader: this._mediaLoader}); + this._displayGenerator = new DisplayGenerator({ + japaneseUtil, + mediaLoader: this._mediaLoader + }); this._hotkeys = new Map(); this._actions = new Map(); this._messageHandlers = new Map(); @@ -177,6 +181,10 @@ class Display extends EventDispatcher { return this._mode; } + get japaneseUtil() { + return this._japaneseUtil; + } + async prepare() { // State setup const {documentElement} = document; diff --git a/ext/mixed/js/japanese.js b/ext/mixed/js/japanese.js index 2177ceee..4bd0dc65 100644 --- a/ext/mixed/js/japanese.js +++ b/ext/mixed/js/japanese.js @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -const jp = (() => { +const JapaneseUtil = (() => { const ITERATION_MARK_CODE_POINT = 0x3005; const HIRAGANA_SMALL_TSU_CODE_POINT = 0x3063; const KATAKANA_SMALL_TSU_CODE_POINT = 0x30c3; @@ -179,19 +179,8 @@ const jp = (() => { } } - function getWanakana() { - try { - if (typeof wanakana !== 'undefined') { - // eslint-disable-next-line no-undef - return wanakana; - } - } catch (e) { - // NOP - } - return null; - } - + // eslint-disable-next-line no-shadow class JapaneseUtil { constructor(wanakana=null) { this._wanakana = wanakana; @@ -258,6 +247,10 @@ const jp = (() => { // Conversion functions + convertToKana(text) { + return this._getWanakana().toKana(text); + } + convertKatakanaToHiragana(text) { let result = ''; const offset = (HIRAGANA_CONVERSION_RANGE[0] - KATAKANA_CONVERSION_RANGE[0]); @@ -591,5 +584,5 @@ const jp = (() => { } - return new JapaneseUtil(getWanakana()); + return JapaneseUtil; })(); diff --git a/test/test-japanese.js b/test/test-japanese.js index e70698da..97d613fe 100644 --- a/test/test-japanese.js +++ b/test/test-japanese.js @@ -25,8 +25,8 @@ vm.execute([ 'mixed/js/japanese.js', 'bg/js/text-source-map.js' ]); -const jp = vm.get('jp'); -const TextSourceMap = vm.get('TextSourceMap'); +const [JapaneseUtil, TextSourceMap, wanakana] = vm.get(['JapaneseUtil', 'TextSourceMap', 'wanakana']); +const jp = new JapaneseUtil(wanakana); function testIsCodePointKanji() {