summaryrefslogtreecommitdiff
path: root/ext/js/display
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2024-01-28 07:22:47 -0500
committerGitHub <noreply@github.com>2024-01-28 12:22:47 +0000
commitacc013a1a8051d34322f0f5f91d7bdecc0a18843 (patch)
tree601344b2f047f395548ddfb16a83319af10464f9 /ext/js/display
parenta51f1ab2dc675a49bfeeb08cc24b97eb8d888e4a (diff)
JapaneseUtil refactor (#555)
* Copy functions from JapaneseUtil * Remove JapaneseUtil * Update usages of JapaneseUtil functions
Diffstat (limited to 'ext/js/display')
-rw-r--r--ext/js/display/display-anki.js5
-rw-r--r--ext/js/display/display-generator.js26
-rw-r--r--ext/js/display/display.js14
-rw-r--r--ext/js/display/popup-main.js7
-rw-r--r--ext/js/display/query-parser.js40
-rw-r--r--ext/js/display/sandbox/pronunciation-generator.js24
-rw-r--r--ext/js/display/sandbox/structured-content-generator.js9
-rw-r--r--ext/js/display/search-display-controller.js4
-rw-r--r--ext/js/display/search-main.js10
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();