Update dictionary entry terminology (#1592)
* Update terminology * Update terminology in display.js * Update terminology in display-audio.js * Update terminology in text-scanner.js * Update terminology in backend.js * Update terminology in mecab.js * Update terminology in audio-downloader.js * Update terminology in translator-vm.js * Update terminology in dictionary-data-util.js * Update terminology in dictionary-database.js * Update terminology in japanese-util.js * Change/upgrade {expression} to {term} * Update terminology in test-japanese.js * Update terminology in test-database.js * Update terminology in anki-templates-controller.js * Update terminology in anki-note-builder.js * Update terminology in backend.js * Update terminology in text-scanner.js * Update terminology in display.js * Update terminology in display.js
This commit is contained in:
parent
b8bedd5185
commit
e14b52ef84
@ -105,10 +105,10 @@ class TranslatorVM extends DatabaseVM {
|
|||||||
this._ankiNoteDataCreator = new AnkiNoteDataCreator(this._japaneseUtil);
|
this._ankiNoteDataCreator = new AnkiNoteDataCreator(this._japaneseUtil);
|
||||||
}
|
}
|
||||||
|
|
||||||
createTestAnkiNoteData(definition, mode) {
|
createTestAnkiNoteData(dictionaryEntry, mode) {
|
||||||
const marker = '{marker}';
|
const marker = '{marker}';
|
||||||
const data = {
|
const data = {
|
||||||
definition,
|
dictionaryEntry,
|
||||||
resultOutputMode: mode,
|
resultOutputMode: mode,
|
||||||
mode: 'mode',
|
mode: 'mode',
|
||||||
glossaryLayoutMode: 'default',
|
glossaryLayoutMode: 'default',
|
||||||
|
@ -257,7 +257,7 @@ class Frontend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSearched({type, definitions, sentence, inputInfo: {eventType, passive, detail}, textSource, optionsContext, detail: {documentTitle}, error}) {
|
_onSearched({type, dictionaryEntries, sentence, inputInfo: {eventType, passive, detail}, textSource, optionsContext, detail: {documentTitle}, error}) {
|
||||||
const scanningOptions = this._options.scanning;
|
const scanningOptions = this._options.scanning;
|
||||||
|
|
||||||
if (error !== null) {
|
if (error !== null) {
|
||||||
@ -275,7 +275,7 @@ class Frontend {
|
|||||||
const focus2 = detail.focus;
|
const focus2 = detail.focus;
|
||||||
if (typeof focus2 === 'boolean') { focus = focus2; }
|
if (typeof focus2 === 'boolean') { focus = focus2; }
|
||||||
}
|
}
|
||||||
this._showContent(textSource, focus, definitions, type, sentence, documentTitle, optionsContext);
|
this._showContent(textSource, focus, dictionaryEntries, type, sentence, documentTitle, optionsContext);
|
||||||
} else {
|
} else {
|
||||||
if (scanningOptions.autoHideResults) {
|
if (scanningOptions.autoHideResults) {
|
||||||
this._clearSelectionDelayed(scanningOptions.hideDelay, false);
|
this._clearSelectionDelayed(scanningOptions.hideDelay, false);
|
||||||
@ -505,7 +505,7 @@ class Frontend {
|
|||||||
this._showPopupContent(textSource, null);
|
this._showPopupContent(textSource, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
_showContent(textSource, focus, definitions, type, sentence, documentTitle, optionsContext) {
|
_showContent(textSource, focus, dictionaryEntries, type, sentence, documentTitle, optionsContext) {
|
||||||
const query = textSource.text();
|
const query = textSource.text();
|
||||||
const {url} = optionsContext;
|
const {url} = optionsContext;
|
||||||
const details = {
|
const details = {
|
||||||
@ -524,7 +524,7 @@ class Frontend {
|
|||||||
documentTitle
|
documentTitle
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
definitions,
|
dictionaryEntries,
|
||||||
contentOrigin: {
|
contentOrigin: {
|
||||||
tabId: this._tabId,
|
tabId: this._tabId,
|
||||||
frameId: this._frameId
|
frameId: this._frameId
|
||||||
|
@ -101,7 +101,7 @@ class Backend {
|
|||||||
['noteView', {async: true, contentScript: true, handler: this._onApiNoteView.bind(this)}],
|
['noteView', {async: true, contentScript: true, handler: this._onApiNoteView.bind(this)}],
|
||||||
['suspendAnkiCardsForNote', {async: true, contentScript: true, handler: this._onApiSuspendAnkiCardsForNote.bind(this)}],
|
['suspendAnkiCardsForNote', {async: true, contentScript: true, handler: this._onApiSuspendAnkiCardsForNote.bind(this)}],
|
||||||
['commandExec', {async: false, contentScript: true, handler: this._onApiCommandExec.bind(this)}],
|
['commandExec', {async: false, contentScript: true, handler: this._onApiCommandExec.bind(this)}],
|
||||||
['getExpressionAudioInfoList', {async: true, contentScript: true, handler: this._onApiGetExpressionAudioInfoList.bind(this)}],
|
['getTermAudioInfoList', {async: true, contentScript: true, handler: this._onApiGetTermAudioInfoList.bind(this)}],
|
||||||
['sendMessageToFrame', {async: false, contentScript: true, handler: this._onApiSendMessageToFrame.bind(this)}],
|
['sendMessageToFrame', {async: false, contentScript: true, handler: this._onApiSendMessageToFrame.bind(this)}],
|
||||||
['broadcastTab', {async: false, contentScript: true, handler: this._onApiBroadcastTab.bind(this)}],
|
['broadcastTab', {async: false, contentScript: true, handler: this._onApiBroadcastTab.bind(this)}],
|
||||||
['frameInformationGet', {async: true, contentScript: true, handler: this._onApiFrameInformationGet.bind(this)}],
|
['frameInformationGet', {async: true, contentScript: true, handler: this._onApiFrameInformationGet.bind(this)}],
|
||||||
@ -405,9 +405,9 @@ class Backend {
|
|||||||
const options = this._getProfileOptions(optionsContext);
|
const options = this._getProfileOptions(optionsContext);
|
||||||
const {general: {maxResults}} = options;
|
const {general: {maxResults}} = options;
|
||||||
const findKanjiOptions = this._getTranslatorFindKanjiOptions(options);
|
const findKanjiOptions = this._getTranslatorFindKanjiOptions(options);
|
||||||
const definitions = await this._translator.findKanji(text, findKanjiOptions);
|
const dictionaryEntries = await this._translator.findKanji(text, findKanjiOptions);
|
||||||
definitions.splice(maxResults);
|
dictionaryEntries.splice(maxResults);
|
||||||
return definitions;
|
return dictionaryEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onApiTermsFind({text, details, optionsContext}) {
|
async _onApiTermsFind({text, details, optionsContext}) {
|
||||||
@ -416,7 +416,7 @@ class Backend {
|
|||||||
const findTermsOptions = this._getTranslatorFindTermsOptions(details, options);
|
const findTermsOptions = this._getTranslatorFindTermsOptions(details, options);
|
||||||
const {dictionaryEntries, originalTextLength} = await this._translator.findTerms(mode, text, findTermsOptions);
|
const {dictionaryEntries, originalTextLength} = await this._translator.findTerms(mode, text, findTermsOptions);
|
||||||
dictionaryEntries.splice(maxResults);
|
dictionaryEntries.splice(maxResults);
|
||||||
return {length: originalTextLength, definitions: dictionaryEntries};
|
return {dictionaryEntries, originalTextLength};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onApiTextParse({text, optionsContext}) {
|
async _onApiTextParse({text, optionsContext}) {
|
||||||
@ -518,8 +518,8 @@ class Backend {
|
|||||||
return this._runCommand(command, params);
|
return this._runCommand(command, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onApiGetExpressionAudioInfoList({source, expression, reading, details}) {
|
async _onApiGetTermAudioInfoList({source, term, reading, details}) {
|
||||||
return await this._audioDownloader.getExpressionAudioInfoList(source, expression, reading, details);
|
return await this._audioDownloader.getTermAudioInfoList(source, term, reading, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onApiSendMessageToFrame({frameId: targetFrameId, action, params}, sender) {
|
_onApiSendMessageToFrame({frameId: targetFrameId, action, params}, sender) {
|
||||||
@ -1100,17 +1100,17 @@ class Backend {
|
|||||||
for (const {name, lines} of parseTextResults) {
|
for (const {name, lines} of parseTextResults) {
|
||||||
const result = [];
|
const result = [];
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
for (const {expression, reading, source} of line) {
|
for (const {term, reading, source} of line) {
|
||||||
const term = [];
|
const termParts = [];
|
||||||
for (const {text: text2, furigana} of jp.distributeFuriganaInflected(
|
for (const {text: text2, furigana} of jp.distributeFuriganaInflected(
|
||||||
expression.length > 0 ? expression : source,
|
term.length > 0 ? term : source,
|
||||||
jp.convertKatakanaToHiragana(reading),
|
jp.convertKatakanaToHiragana(reading),
|
||||||
source
|
source
|
||||||
)) {
|
)) {
|
||||||
const reading2 = jp.convertReading(text2, furigana, readingMode);
|
const reading2 = jp.convertReading(text2, furigana, readingMode);
|
||||||
term.push({text: text2, reading: reading2});
|
termParts.push({text: text2, reading: reading2});
|
||||||
}
|
}
|
||||||
result.push(term);
|
result.push(termParts);
|
||||||
}
|
}
|
||||||
result.push([{text: '\n', reading: ''}]);
|
result.push([{text: '\n', reading: ''}]);
|
||||||
}
|
}
|
||||||
@ -1742,7 +1742,7 @@ class Backend {
|
|||||||
let data;
|
let data;
|
||||||
let contentType;
|
let contentType;
|
||||||
try {
|
try {
|
||||||
({data, contentType} = await this._audioDownloader.downloadExpressionAudio(
|
({data, contentType} = await this._audioDownloader.downloadTermAudio(
|
||||||
sources,
|
sources,
|
||||||
preferredAudioIndex,
|
preferredAudioIndex,
|
||||||
term,
|
term,
|
||||||
|
@ -68,8 +68,8 @@ class API {
|
|||||||
return this._invoke('suspendAnkiCardsForNote', {noteId});
|
return this._invoke('suspendAnkiCardsForNote', {noteId});
|
||||||
}
|
}
|
||||||
|
|
||||||
getExpressionAudioInfoList(source, expression, reading, details) {
|
getTermAudioInfoList(source, term, reading, details) {
|
||||||
return this._invoke('getExpressionAudioInfoList', {source, expression, reading, details});
|
return this._invoke('getTermAudioInfoList', {source, term, reading, details});
|
||||||
}
|
}
|
||||||
|
|
||||||
commandExec(command, params) {
|
commandExec(command, params) {
|
||||||
|
@ -108,7 +108,7 @@ class Mecab {
|
|||||||
* {
|
* {
|
||||||
* name: (string),
|
* name: (string),
|
||||||
* lines: [
|
* lines: [
|
||||||
* {expression: (string), reading: (string), source: (string)},
|
* {term: (string), reading: (string), source: (string)},
|
||||||
* ...
|
* ...
|
||||||
* ]
|
* ]
|
||||||
* },
|
* },
|
||||||
@ -172,11 +172,11 @@ class Mecab {
|
|||||||
const lines = [];
|
const lines = [];
|
||||||
for (const rawLine of rawLines) {
|
for (const rawLine of rawLines) {
|
||||||
const line = [];
|
const line = [];
|
||||||
for (let {expression, reading, source} of rawLine) {
|
for (let {expression: term, reading, source} of rawLine) {
|
||||||
if (typeof expression !== 'string') { expression = ''; }
|
if (typeof term !== 'string') { term = ''; }
|
||||||
if (typeof reading !== 'string') { reading = ''; }
|
if (typeof reading !== 'string') { reading = ''; }
|
||||||
if (typeof source !== 'string') { source = ''; }
|
if (typeof source !== 'string') { source = ''; }
|
||||||
line.push({expression, reading, source});
|
line.push({term, reading, source});
|
||||||
}
|
}
|
||||||
lines.push(line);
|
lines.push(line);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class AnkiNoteBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createNote({
|
async createNote({
|
||||||
definition,
|
dictionaryEntry,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
template,
|
template,
|
||||||
@ -53,7 +53,7 @@ class AnkiNoteBuilder {
|
|||||||
duplicateScopeCheckChildren = true;
|
duplicateScopeCheckChildren = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const commonData = this._createData(definition, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia);
|
const commonData = this._createData(dictionaryEntry, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia);
|
||||||
const formattedFieldValuePromises = [];
|
const formattedFieldValuePromises = [];
|
||||||
for (const [, fieldValue] of fields) {
|
for (const [, fieldValue] of fields) {
|
||||||
const formattedFieldValuePromise = this._formatField(fieldValue, commonData, template, errors);
|
const formattedFieldValuePromise = this._formatField(fieldValue, commonData, template, errors);
|
||||||
@ -85,7 +85,7 @@ class AnkiNoteBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRenderingData({
|
async getRenderingData({
|
||||||
definition,
|
dictionaryEntry,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
resultOutputMode='split',
|
resultOutputMode='split',
|
||||||
@ -94,15 +94,15 @@ class AnkiNoteBuilder {
|
|||||||
injectedMedia=null,
|
injectedMedia=null,
|
||||||
marker=null
|
marker=null
|
||||||
}) {
|
}) {
|
||||||
const commonData = this._createData(definition, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia);
|
const commonData = this._createData(dictionaryEntry, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia);
|
||||||
return await this._templateRenderer.getModifiedData({marker, commonData}, 'ankiNote');
|
return await this._templateRenderer.getModifiedData({marker, commonData}, 'ankiNote');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
_createData(definition, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia) {
|
_createData(dictionaryEntry, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia) {
|
||||||
return {
|
return {
|
||||||
definition,
|
dictionaryEntry,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
resultOutputMode,
|
resultOutputMode,
|
||||||
|
@ -38,7 +38,7 @@ class AnkiNoteDataCreator {
|
|||||||
* @returns An object used for rendering Anki templates.
|
* @returns An object used for rendering Anki templates.
|
||||||
*/
|
*/
|
||||||
create(marker, {
|
create(marker, {
|
||||||
definition: dictionaryEntry,
|
dictionaryEntry,
|
||||||
resultOutputMode,
|
resultOutputMode,
|
||||||
mode,
|
mode,
|
||||||
glossaryLayoutMode,
|
glossaryLayoutMode,
|
||||||
|
@ -791,12 +791,20 @@ class OptionsUtil {
|
|||||||
_updateVersion11(options) {
|
_updateVersion11(options) {
|
||||||
// Version 11 changes:
|
// Version 11 changes:
|
||||||
// Changed dictionaries to an array.
|
// Changed dictionaries to an array.
|
||||||
|
// Changed audio.customSourceUrl's {expression} marker to {term}.
|
||||||
|
const customSourceUrlPattern = /\{expression\}/g;
|
||||||
for (const profile of options.profiles) {
|
for (const profile of options.profiles) {
|
||||||
const dictionariesNew = [];
|
const dictionariesNew = [];
|
||||||
for (const [name, {priority, enabled, allowSecondarySearches, definitionsCollapsible}] of Object.entries(profile.options.dictionaries)) {
|
for (const [name, {priority, enabled, allowSecondarySearches, definitionsCollapsible}] of Object.entries(profile.options.dictionaries)) {
|
||||||
dictionariesNew.push({name, priority, enabled, allowSecondarySearches, definitionsCollapsible});
|
dictionariesNew.push({name, priority, enabled, allowSecondarySearches, definitionsCollapsible});
|
||||||
}
|
}
|
||||||
profile.options.dictionaries = dictionariesNew;
|
profile.options.dictionaries = dictionariesNew;
|
||||||
|
|
||||||
|
let {customSourceUrl} = profile.options.audio;
|
||||||
|
if (typeof customSourceUrl === 'string') {
|
||||||
|
customSourceUrl = customSourceUrl.replace(customSourceUrlPattern, '{term}');
|
||||||
|
}
|
||||||
|
profile.options.audio.customSourceUrl = customSourceUrl;
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
@ -58,12 +58,12 @@ class DisplayAudio {
|
|||||||
this._eventListeners.removeAllEventListeners();
|
this._eventListeners.removeAllEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
setupEntry(entry, definitionIndex) {
|
setupEntry(entry, dictionaryEntryIndex) {
|
||||||
for (const button of entry.querySelectorAll('.action-play-audio')) {
|
for (const button of entry.querySelectorAll('.action-play-audio')) {
|
||||||
const expressionIndex = this._getAudioPlayButtonExpressionIndex(button);
|
const headwordIndex = this._getAudioPlayButtonHeadwordIndex(button);
|
||||||
this._eventListeners.addEventListener(button, 'click', this._onAudioPlayButtonClick.bind(this, definitionIndex, expressionIndex), false);
|
this._eventListeners.addEventListener(button, 'click', this._onAudioPlayButtonClick.bind(this, dictionaryEntryIndex, headwordIndex), false);
|
||||||
this._eventListeners.addEventListener(button, 'contextmenu', this._onAudioPlayButtonContextMenu.bind(this, definitionIndex, expressionIndex), false);
|
this._eventListeners.addEventListener(button, 'contextmenu', this._onAudioPlayButtonContextMenu.bind(this, dictionaryEntryIndex, headwordIndex), false);
|
||||||
this._eventListeners.addEventListener(button, 'menuClose', this._onAudioPlayMenuCloseClick.bind(this, definitionIndex, expressionIndex), false);
|
this._eventListeners.addEventListener(button, 'menuClose', this._onAudioPlayMenuCloseClick.bind(this, dictionaryEntryIndex, headwordIndex), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,11 +73,11 @@ class DisplayAudio {
|
|||||||
|
|
||||||
this.clearAutoPlayTimer();
|
this.clearAutoPlayTimer();
|
||||||
|
|
||||||
const definitions = this._display.definitions;
|
const {dictionaryEntries} = this._display;
|
||||||
if (definitions.length === 0) { return; }
|
if (dictionaryEntries.length === 0) { return; }
|
||||||
|
|
||||||
const firstDefinition = definitions[0];
|
const firstDictionaryEntries = dictionaryEntries[0];
|
||||||
if (firstDefinition.type === 'kanji') { return; }
|
if (firstDictionaryEntries.type === 'kanji') { return; }
|
||||||
|
|
||||||
const callback = () => {
|
const callback = () => {
|
||||||
this._autoPlayAudioTimer = null;
|
this._autoPlayAudioTimer = null;
|
||||||
@ -103,18 +103,18 @@ class DisplayAudio {
|
|||||||
this._audioPlaying = null;
|
this._audioPlaying = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async playAudio(definitionIndex, expressionIndex, sources=null, sourceDetailsMap=null) {
|
async playAudio(dictionaryEntryIndex, headwordIndex, sources=null, sourceDetailsMap=null) {
|
||||||
this.stopAudio();
|
this.stopAudio();
|
||||||
this.clearAutoPlayTimer();
|
this.clearAutoPlayTimer();
|
||||||
|
|
||||||
const expressionReading = this._getExpressionAndReading(definitionIndex, expressionIndex);
|
const headword = this._getHeadword(dictionaryEntryIndex, headwordIndex);
|
||||||
if (expressionReading === null) {
|
if (headword === null) {
|
||||||
return {audio: null, source: null, valid: false};
|
return {audio: null, source: null, valid: false};
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttons = this._getAudioPlayButtons(definitionIndex, expressionIndex);
|
const buttons = this._getAudioPlayButtons(dictionaryEntryIndex, headwordIndex);
|
||||||
|
|
||||||
const {expression, reading} = expressionReading;
|
const {term, reading} = headword;
|
||||||
const audioOptions = this._getAudioOptions();
|
const audioOptions = this._getAudioOptions();
|
||||||
const {textToSpeechVoice, customSourceUrl, customSourceType, volume} = audioOptions;
|
const {textToSpeechVoice, customSourceUrl, customSourceType, volume} = audioOptions;
|
||||||
if (!Array.isArray(sources)) {
|
if (!Array.isArray(sources)) {
|
||||||
@ -131,7 +131,7 @@ class DisplayAudio {
|
|||||||
let audio;
|
let audio;
|
||||||
let title;
|
let title;
|
||||||
let source = null;
|
let source = null;
|
||||||
const info = await this._createExpressionAudio(sources, sourceDetailsMap, expression, reading, {textToSpeechVoice, customSourceUrl, customSourceType});
|
const info = await this._createTermAudio(sources, sourceDetailsMap, term, reading, {textToSpeechVoice, customSourceUrl, customSourceType});
|
||||||
const valid = (info !== null);
|
const valid = (info !== null);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
({audio, source} = info);
|
({audio, source} = info);
|
||||||
@ -146,7 +146,7 @@ class DisplayAudio {
|
|||||||
this.stopAudio();
|
this.stopAudio();
|
||||||
|
|
||||||
// Update details
|
// Update details
|
||||||
const potentialAvailableAudioCount = this._getPotentialAvailableAudioCount(expression, reading);
|
const potentialAvailableAudioCount = this._getPotentialAvailableAudioCount(term, reading);
|
||||||
for (const button of buttons) {
|
for (const button of buttons) {
|
||||||
const titleDefault = button.dataset.titleDefault || '';
|
const titleDefault = button.dataset.titleDefault || '';
|
||||||
button.title = `${titleDefault}\n${title}`;
|
button.title = `${titleDefault}\n${title}`;
|
||||||
@ -174,48 +174,48 @@ class DisplayAudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPrimaryCardAudio(expression, reading) {
|
getPrimaryCardAudio(term, reading) {
|
||||||
const cacheEntry = this._getCacheItem(expression, reading, false);
|
const cacheEntry = this._getCacheItem(term, reading, false);
|
||||||
const primaryCardAudio = typeof cacheEntry !== 'undefined' ? cacheEntry.primaryCardAudio : null;
|
const primaryCardAudio = typeof cacheEntry !== 'undefined' ? cacheEntry.primaryCardAudio : null;
|
||||||
return primaryCardAudio;
|
return primaryCardAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
_onAudioPlayButtonClick(definitionIndex, expressionIndex, e) {
|
_onAudioPlayButtonClick(dictionaryEntryIndex, headwordIndex, e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
this._showAudioMenu(e.currentTarget, definitionIndex, expressionIndex);
|
this._showAudioMenu(e.currentTarget, dictionaryEntryIndex, headwordIndex);
|
||||||
} else {
|
} else {
|
||||||
this.playAudio(definitionIndex, expressionIndex);
|
this.playAudio(dictionaryEntryIndex, headwordIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAudioPlayButtonContextMenu(definitionIndex, expressionIndex, e) {
|
_onAudioPlayButtonContextMenu(dictionaryEntryIndex, headwordIndex, e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
this._showAudioMenu(e.currentTarget, definitionIndex, expressionIndex);
|
this._showAudioMenu(e.currentTarget, dictionaryEntryIndex, headwordIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAudioPlayMenuCloseClick(definitionIndex, expressionIndex, e) {
|
_onAudioPlayMenuCloseClick(dictionaryEntryIndex, headwordIndex, e) {
|
||||||
const {detail: {action, item, menu, shiftKey}} = e;
|
const {detail: {action, item, menu, shiftKey}} = e;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'playAudioFromSource':
|
case 'playAudioFromSource':
|
||||||
if (shiftKey) {
|
if (shiftKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
this._playAudioFromSource(definitionIndex, expressionIndex, item);
|
this._playAudioFromSource(dictionaryEntryIndex, headwordIndex, item);
|
||||||
break;
|
break;
|
||||||
case 'setPrimaryAudio':
|
case 'setPrimaryAudio':
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this._setPrimaryAudio(definitionIndex, expressionIndex, item, menu, true);
|
this._setPrimaryAudio(dictionaryEntryIndex, headwordIndex, item, menu, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCacheItem(expression, reading, create) {
|
_getCacheItem(term, reading, create) {
|
||||||
const key = this._getExpressionReadingKey(expression, reading);
|
const key = this._getTermReadingKey(term, reading);
|
||||||
let cacheEntry = this._cache.get(key);
|
let cacheEntry = this._cache.get(key);
|
||||||
if (typeof cacheEntry === 'undefined' && create) {
|
if (typeof cacheEntry === 'undefined' && create) {
|
||||||
cacheEntry = {
|
cacheEntry = {
|
||||||
@ -242,7 +242,7 @@ class DisplayAudio {
|
|||||||
return {source, index, hasIndex};
|
return {source, index, hasIndex};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _playAudioFromSource(definitionIndex, expressionIndex, item) {
|
async _playAudioFromSource(dictionaryEntryIndex, headwordIndex, item) {
|
||||||
const sourceInfo = this._getMenuItemSourceInfo(item);
|
const sourceInfo = this._getMenuItemSourceInfo(item);
|
||||||
if (sourceInfo === null) { return; }
|
if (sourceInfo === null) { return; }
|
||||||
|
|
||||||
@ -251,61 +251,61 @@ class DisplayAudio {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const token = this._entriesToken;
|
const token = this._entriesToken;
|
||||||
const {valid} = await this.playAudio(definitionIndex, expressionIndex, [source], sourceDetailsMap);
|
const {valid} = await this.playAudio(dictionaryEntryIndex, headwordIndex, [source], sourceDetailsMap);
|
||||||
if (valid && token === this._entriesToken) {
|
if (valid && token === this._entriesToken) {
|
||||||
this._setPrimaryAudio(definitionIndex, expressionIndex, item, null, false);
|
this._setPrimaryAudio(dictionaryEntryIndex, headwordIndex, item, null, false);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// NOP
|
// NOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setPrimaryAudio(definitionIndex, expressionIndex, item, menu, canToggleOff) {
|
_setPrimaryAudio(dictionaryEntryIndex, headwordIndex, item, menu, canToggleOff) {
|
||||||
const sourceInfo = this._getMenuItemSourceInfo(item);
|
const sourceInfo = this._getMenuItemSourceInfo(item);
|
||||||
if (sourceInfo === null) { return; }
|
if (sourceInfo === null) { return; }
|
||||||
|
|
||||||
const {source, index} = sourceInfo;
|
const {source, index} = sourceInfo;
|
||||||
if (!this._sourceIsDownloadable(source)) { return; }
|
if (!this._sourceIsDownloadable(source)) { return; }
|
||||||
|
|
||||||
const expressionReading = this._getExpressionAndReading(definitionIndex, expressionIndex);
|
const headword = this._getHeadword(dictionaryEntryIndex, headwordIndex);
|
||||||
if (expressionReading === null) { return; }
|
if (headword === null) { return; }
|
||||||
|
|
||||||
const {expression, reading} = expressionReading;
|
const {term, reading} = headword;
|
||||||
const cacheEntry = this._getCacheItem(expression, reading, true);
|
const cacheEntry = this._getCacheItem(term, reading, true);
|
||||||
|
|
||||||
let {primaryCardAudio} = cacheEntry;
|
let {primaryCardAudio} = cacheEntry;
|
||||||
primaryCardAudio = (!canToggleOff || primaryCardAudio === null || primaryCardAudio.source !== source || primaryCardAudio.index !== index) ? {source, index} : null;
|
primaryCardAudio = (!canToggleOff || primaryCardAudio === null || primaryCardAudio.source !== source || primaryCardAudio.index !== index) ? {source, index} : null;
|
||||||
cacheEntry.primaryCardAudio = primaryCardAudio;
|
cacheEntry.primaryCardAudio = primaryCardAudio;
|
||||||
|
|
||||||
if (menu !== null) {
|
if (menu !== null) {
|
||||||
this._updateMenuPrimaryCardAudio(menu.bodyNode, expression, reading);
|
this._updateMenuPrimaryCardAudio(menu.bodyNode, term, reading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getAudioPlayButtonExpressionIndex(button) {
|
_getAudioPlayButtonHeadwordIndex(button) {
|
||||||
const expressionNode = button.closest('.expression');
|
const headwordNode = button.closest('.expression');
|
||||||
if (expressionNode !== null) {
|
if (headwordNode !== null) {
|
||||||
const expressionIndex = parseInt(expressionNode.dataset.index, 10);
|
const headwordIndex = parseInt(headwordNode.dataset.index, 10);
|
||||||
if (Number.isFinite(expressionIndex)) { return expressionIndex; }
|
if (Number.isFinite(headwordIndex)) { return headwordIndex; }
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getAudioPlayButtons(definitionIndex, expressionIndex) {
|
_getAudioPlayButtons(dictionaryEntryIndex, headwordIndex) {
|
||||||
const results = [];
|
const results = [];
|
||||||
const {definitionNodes} = this._display;
|
const {dictionaryEntryNodes} = this._display;
|
||||||
if (definitionIndex >= 0 && definitionIndex < definitionNodes.length) {
|
if (dictionaryEntryIndex >= 0 && dictionaryEntryIndex < dictionaryEntryNodes.length) {
|
||||||
const node = definitionNodes[definitionIndex];
|
const node = dictionaryEntryNodes[dictionaryEntryIndex];
|
||||||
const button1 = (expressionIndex === 0 ? node.querySelector('.action-play-audio') : null);
|
const button1 = (headwordIndex === 0 ? node.querySelector('.action-play-audio') : null);
|
||||||
const button2 = node.querySelector(`.expression:nth-of-type(${expressionIndex + 1}) .action-play-audio`);
|
const button2 = node.querySelector(`.expression:nth-of-type(${headwordIndex + 1}) .action-play-audio`);
|
||||||
if (button1 !== null) { results.push(button1); }
|
if (button1 !== null) { results.push(button1); }
|
||||||
if (button2 !== null) { results.push(button2); }
|
if (button2 !== null) { results.push(button2); }
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _createExpressionAudio(sources, sourceDetailsMap, expression, reading, details) {
|
async _createTermAudio(sources, sourceDetailsMap, term, reading, details) {
|
||||||
const {sourceMap} = this._getCacheItem(expression, reading, true);
|
const {sourceMap} = this._getCacheItem(term, reading, true);
|
||||||
|
|
||||||
for (let i = 0, ii = sources.length; i < ii; ++i) {
|
for (let i = 0, ii = sources.length; i < ii; ++i) {
|
||||||
const source = sources[i];
|
const source = sources[i];
|
||||||
@ -314,7 +314,7 @@ class DisplayAudio {
|
|||||||
let infoListPromise;
|
let infoListPromise;
|
||||||
let sourceInfo = sourceMap.get(source);
|
let sourceInfo = sourceMap.get(source);
|
||||||
if (typeof sourceInfo === 'undefined') {
|
if (typeof sourceInfo === 'undefined') {
|
||||||
infoListPromise = this._getExpressionAudioInfoList(source, expression, reading, details);
|
infoListPromise = this._getTermAudioInfoList(source, term, reading, details);
|
||||||
sourceInfo = {infoListPromise, infoList: null};
|
sourceInfo = {infoListPromise, infoList: null};
|
||||||
sourceMap.set(source, sourceInfo);
|
sourceMap.set(source, sourceInfo);
|
||||||
cacheUpdated = true;
|
cacheUpdated = true;
|
||||||
@ -393,27 +393,26 @@ class DisplayAudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getExpressionAudioInfoList(source, expression, reading, details) {
|
async _getTermAudioInfoList(source, term, reading, details) {
|
||||||
const infoList = await yomichan.api.getExpressionAudioInfoList(source, expression, reading, details);
|
const infoList = await yomichan.api.getTermAudioInfoList(source, term, reading, details);
|
||||||
return infoList.map((info) => ({info, audioPromise: null, audioResolved: false, audio: null}));
|
return infoList.map((info) => ({info, audioPromise: null, audioResolved: false, audio: null}));
|
||||||
}
|
}
|
||||||
|
|
||||||
_getExpressionAndReading(definitionIndex, expressionIndex) {
|
_getHeadword(dictionaryEntryIndex, headwordIndex) {
|
||||||
const {definitions} = this._display;
|
const {dictionaryEntries} = this._display;
|
||||||
if (definitionIndex < 0 || definitionIndex >= definitions.length) { return null; }
|
if (dictionaryEntryIndex < 0 || dictionaryEntryIndex >= dictionaryEntries.length) { return null; }
|
||||||
|
|
||||||
const definition = definitions[definitionIndex];
|
const dictionaryEntry = dictionaryEntries[dictionaryEntryIndex];
|
||||||
if (definition.type === 'kanji') { return null; }
|
if (dictionaryEntry.type === 'kanji') { return null; }
|
||||||
|
|
||||||
const {headwords} = definition;
|
const {headwords} = dictionaryEntry;
|
||||||
if (expressionIndex < 0 || expressionIndex >= headwords.length) { return null; }
|
if (headwordIndex < 0 || headwordIndex >= headwords.length) { return null; }
|
||||||
|
|
||||||
const {term, reading} = headwords[expressionIndex];
|
return headwords[headwordIndex];
|
||||||
return {expression: term, reading};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_getExpressionReadingKey(expression, reading) {
|
_getTermReadingKey(term, reading) {
|
||||||
return JSON.stringify([expression, reading]);
|
return JSON.stringify([term, reading]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getAudioOptions() {
|
_getAudioOptions() {
|
||||||
@ -460,8 +459,8 @@ class DisplayAudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getPotentialAvailableAudioCount(expression, reading) {
|
_getPotentialAvailableAudioCount(term, reading) {
|
||||||
const cacheEntry = this._getCacheItem(expression, reading, false);
|
const cacheEntry = this._getCacheItem(term, reading, false);
|
||||||
if (typeof cacheEntry === 'undefined') { return null; }
|
if (typeof cacheEntry === 'undefined') { return null; }
|
||||||
|
|
||||||
const {sourceMap} = cacheEntry;
|
const {sourceMap} = cacheEntry;
|
||||||
@ -477,12 +476,12 @@ class DisplayAudio {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
_showAudioMenu(button, definitionIndex, expressionIndex) {
|
_showAudioMenu(button, dictionaryEntryIndex, headwordIndex) {
|
||||||
const expressionReading = this._getExpressionAndReading(definitionIndex, expressionIndex);
|
const headword = this._getHeadword(dictionaryEntryIndex, headwordIndex);
|
||||||
if (expressionReading === null) { return; }
|
if (headword === null) { return; }
|
||||||
|
|
||||||
const {expression, reading} = expressionReading;
|
const {term, reading} = headword;
|
||||||
const popupMenu = this._createMenu(button, expression, reading);
|
const popupMenu = this._createMenu(button, term, reading);
|
||||||
this._openMenus.add(popupMenu);
|
this._openMenus.add(popupMenu);
|
||||||
popupMenu.prepare();
|
popupMenu.prepare();
|
||||||
popupMenu.on('close', this._onPopupMenuClose.bind(this));
|
popupMenu.on('close', this._onPopupMenuClose.bind(this));
|
||||||
@ -550,31 +549,31 @@ class DisplayAudio {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createMenu(sourceButton, expression, reading) {
|
_createMenu(sourceButton, term, reading) {
|
||||||
// Create menu
|
// Create menu
|
||||||
const menuContainerNode = this._display.displayGenerator.instantiateTemplate('audio-button-popup-menu');
|
const menuContainerNode = this._display.displayGenerator.instantiateTemplate('audio-button-popup-menu');
|
||||||
const menuBodyNode = menuContainerNode.querySelector('.popup-menu-body');
|
const menuBodyNode = menuContainerNode.querySelector('.popup-menu-body');
|
||||||
menuContainerNode.dataset.expression = expression;
|
menuContainerNode.dataset.term = term;
|
||||||
menuContainerNode.dataset.reading = reading;
|
menuContainerNode.dataset.reading = reading;
|
||||||
|
|
||||||
// Set up items based on options and cache data
|
// Set up items based on options and cache data
|
||||||
this._createMenuItems(menuContainerNode, menuBodyNode, expression, reading);
|
this._createMenuItems(menuContainerNode, menuBodyNode, term, reading);
|
||||||
|
|
||||||
// Update primary card audio display
|
// Update primary card audio display
|
||||||
this._updateMenuPrimaryCardAudio(menuBodyNode, expression, reading);
|
this._updateMenuPrimaryCardAudio(menuBodyNode, term, reading);
|
||||||
|
|
||||||
// Create popup menu
|
// Create popup menu
|
||||||
this._menuContainer.appendChild(menuContainerNode);
|
this._menuContainer.appendChild(menuContainerNode);
|
||||||
return new PopupMenu(sourceButton, menuContainerNode);
|
return new PopupMenu(sourceButton, menuContainerNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_createMenuItems(menuContainerNode, menuItemContainer, expression, reading) {
|
_createMenuItems(menuContainerNode, menuItemContainer, term, reading) {
|
||||||
const sources = this._getAudioSources(this._getAudioOptions());
|
const sources = this._getAudioSources(this._getAudioOptions());
|
||||||
const {displayGenerator} = this._display;
|
const {displayGenerator} = this._display;
|
||||||
let showIcons = false;
|
let showIcons = false;
|
||||||
const currentItems = [...menuItemContainer.children];
|
const currentItems = [...menuItemContainer.children];
|
||||||
for (const {source, displayName, isInOptions, downloadable} of sources) {
|
for (const {source, displayName, isInOptions, downloadable} of sources) {
|
||||||
const entries = this._getMenuItemEntries(source, expression, reading);
|
const entries = this._getMenuItemEntries(source, term, reading);
|
||||||
for (let i = 0, ii = entries.length; i < ii; ++i) {
|
for (let i = 0, ii = entries.length; i < ii; ++i) {
|
||||||
const {valid, index, name} = entries[i];
|
const {valid, index, name} = entries[i];
|
||||||
let node = this._getOrCreateMenuItem(currentItems, source, index);
|
let node = this._getOrCreateMenuItem(currentItems, source, index);
|
||||||
@ -632,8 +631,8 @@ class DisplayAudio {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getMenuItemEntries(source, expression, reading) {
|
_getMenuItemEntries(source, term, reading) {
|
||||||
const cacheEntry = this._getCacheItem(expression, reading, false);
|
const cacheEntry = this._getCacheItem(term, reading, false);
|
||||||
if (typeof cacheEntry !== 'undefined') {
|
if (typeof cacheEntry !== 'undefined') {
|
||||||
const {sourceMap} = cacheEntry;
|
const {sourceMap} = cacheEntry;
|
||||||
const sourceInfo = sourceMap.get(source);
|
const sourceInfo = sourceMap.get(source);
|
||||||
@ -659,8 +658,8 @@ class DisplayAudio {
|
|||||||
return [{valid: null, index: null, name: null}];
|
return [{valid: null, index: null, name: null}];
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateMenuPrimaryCardAudio(menuBodyNode, expression, reading) {
|
_updateMenuPrimaryCardAudio(menuBodyNode, term, reading) {
|
||||||
const primaryCardAudio = this.getPrimaryCardAudio(expression, reading);
|
const primaryCardAudio = this.getPrimaryCardAudio(term, reading);
|
||||||
const {source: primaryCardAudioSource, index: primaryCardAudioIndex} = (primaryCardAudio !== null ? primaryCardAudio : {source: null, index: -1});
|
const {source: primaryCardAudioSource, index: primaryCardAudioIndex} = (primaryCardAudio !== null ? primaryCardAudio : {source: null, index: -1});
|
||||||
|
|
||||||
const itemGroups = menuBodyNode.querySelectorAll('.popup-menu-item-group');
|
const itemGroups = menuBodyNode.querySelectorAll('.popup-menu-item-group');
|
||||||
@ -683,8 +682,8 @@ class DisplayAudio {
|
|||||||
_updateOpenMenu() {
|
_updateOpenMenu() {
|
||||||
for (const menu of this._openMenus) {
|
for (const menu of this._openMenus) {
|
||||||
const menuContainerNode = menu.containerNode;
|
const menuContainerNode = menu.containerNode;
|
||||||
const {expression, reading} = menuContainerNode.dataset;
|
const {term, reading} = menuContainerNode.dataset;
|
||||||
this._createMenuItems(menuContainerNode, menu.bodyNode, expression, reading);
|
this._createMenuItems(menuContainerNode, menu.bodyNode, term, reading);
|
||||||
menu.updatePosition();
|
menu.updatePosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,56 +50,56 @@ class DisplayGenerator {
|
|||||||
document.head.appendChild(t);
|
document.head.appendChild(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
createTermEntry(details) {
|
createTermEntry(dictionaryEntry) {
|
||||||
const node = this._templates.instantiate('term-entry');
|
const node = this._templates.instantiate('term-entry');
|
||||||
|
|
||||||
const expressionsContainer = node.querySelector('.expression-list');
|
const headwordsContainer = node.querySelector('.expression-list');
|
||||||
const reasonsContainer = node.querySelector('.inflection-list');
|
const inflectionsContainer = node.querySelector('.inflection-list');
|
||||||
const pitchesContainer = node.querySelector('.pitch-accent-group-list');
|
const pitchesContainer = node.querySelector('.pitch-accent-group-list');
|
||||||
const frequencyGroupListContainer = node.querySelector('.frequency-group-list');
|
const frequencyGroupListContainer = node.querySelector('.frequency-group-list');
|
||||||
const definitionsContainer = node.querySelector('.definition-list');
|
const definitionsContainer = node.querySelector('.definition-list');
|
||||||
const termTagsContainer = node.querySelector('.expression-list-tag-list');
|
const termTagsContainer = node.querySelector('.expression-list-tag-list');
|
||||||
|
|
||||||
const {headwords: expressions, type, inflections: reasons, definitions, frequencies, pronunciations} = details;
|
const {headwords, type, inflections, definitions, frequencies, pronunciations} = dictionaryEntry;
|
||||||
const pitches = DictionaryDataUtil.getPitchAccentInfos(details);
|
const pitches = DictionaryDataUtil.getPitchAccentInfos(dictionaryEntry);
|
||||||
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
|
const pitchCount = pitches.reduce((i, v) => i + v.pitches.length, 0);
|
||||||
const groupedFrequencies = DictionaryDataUtil.groupTermFrequencies(details);
|
const groupedFrequencies = DictionaryDataUtil.groupTermFrequencies(dictionaryEntry);
|
||||||
const termTags = DictionaryDataUtil.groupTermTags(details);
|
const termTags = DictionaryDataUtil.groupTermTags(dictionaryEntry);
|
||||||
|
|
||||||
const uniqueExpressions = new Set();
|
const uniqueTerms = new Set();
|
||||||
const uniqueReadings = new Set();
|
const uniqueReadings = new Set();
|
||||||
for (const {term: expression, reading} of expressions) {
|
for (const {term, reading} of headwords) {
|
||||||
uniqueExpressions.add(expression);
|
uniqueTerms.add(term);
|
||||||
uniqueReadings.add(reading);
|
uniqueReadings.add(reading);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.dataset.format = type;
|
node.dataset.format = type;
|
||||||
node.dataset.expressionCount = `${expressions.length}`;
|
node.dataset.expressionCount = `${headwords.length}`;
|
||||||
node.dataset.definitionCount = `${definitions.length}`;
|
node.dataset.definitionCount = `${definitions.length}`;
|
||||||
node.dataset.pitchAccentDictionaryCount = `${pitches.length}`;
|
node.dataset.pitchAccentDictionaryCount = `${pitches.length}`;
|
||||||
node.dataset.pitchAccentCount = `${pitchCount}`;
|
node.dataset.pitchAccentCount = `${pitchCount}`;
|
||||||
node.dataset.uniqueExpressionCount = `${uniqueExpressions.size}`;
|
node.dataset.uniqueExpressionCount = `${uniqueTerms.size}`;
|
||||||
node.dataset.uniqueReadingCount = `${uniqueReadings.size}`;
|
node.dataset.uniqueReadingCount = `${uniqueReadings.size}`;
|
||||||
node.dataset.frequencyCount = `${frequencies.length}`;
|
node.dataset.frequencyCount = `${frequencies.length}`;
|
||||||
node.dataset.groupedFrequencyCount = `${groupedFrequencies.length}`;
|
node.dataset.groupedFrequencyCount = `${groupedFrequencies.length}`;
|
||||||
|
|
||||||
for (let i = 0, ii = expressions.length; i < ii; ++i) {
|
for (let i = 0, ii = headwords.length; i < ii; ++i) {
|
||||||
const node2 = this._createTermExpression(expressions[i], i, pronunciations);
|
const node2 = this._createTermHeadword(headwords[i], i, pronunciations);
|
||||||
node2.dataset.index = `${i}`;
|
node2.dataset.index = `${i}`;
|
||||||
expressionsContainer.appendChild(node2);
|
headwordsContainer.appendChild(node2);
|
||||||
}
|
}
|
||||||
expressionsContainer.dataset.count = `${expressions.length}`;
|
headwordsContainer.dataset.count = `${headwords.length}`;
|
||||||
|
|
||||||
this._appendMultiple(reasonsContainer, this._createTermReason.bind(this), reasons);
|
this._appendMultiple(inflectionsContainer, this._createTermInflection.bind(this), inflections);
|
||||||
this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, false);
|
this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, false);
|
||||||
this._appendMultiple(pitchesContainer, this._createPitches.bind(this), pitches);
|
this._appendMultiple(pitchesContainer, this._createPitches.bind(this), pitches);
|
||||||
this._appendMultiple(termTagsContainer, this._createTermTag.bind(this), termTags, expressions.length);
|
this._appendMultiple(termTagsContainer, this._createTermTag.bind(this), termTags, headwords.length);
|
||||||
|
|
||||||
for (const expression of uniqueExpressions) {
|
for (const term of uniqueTerms) {
|
||||||
termTagsContainer.appendChild(this._createSearchTag(expression));
|
termTagsContainer.appendChild(this._createSearchTag(term));
|
||||||
}
|
}
|
||||||
for (const reading of uniqueReadings) {
|
for (const reading of uniqueReadings) {
|
||||||
if (uniqueExpressions.has(reading)) { continue; }
|
if (uniqueTerms.has(reading)) { continue; }
|
||||||
termTagsContainer.appendChild(this._createSearchTag(reading));
|
termTagsContainer.appendChild(this._createSearchTag(reading));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ class DisplayGenerator {
|
|||||||
dictionaryTag.name = dictionary;
|
dictionaryTag.name = dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
const node2 = this._createTermDefinitionItem(definition, dictionaryTag, expressions, uniqueExpressions, uniqueReadings);
|
const node2 = this._createTermDefinition(definition, dictionaryTag, headwords, uniqueTerms, uniqueReadings);
|
||||||
node2.dataset.index = `${i}`;
|
node2.dataset.index = `${i}`;
|
||||||
definitionsContainer.appendChild(node2);
|
definitionsContainer.appendChild(node2);
|
||||||
}
|
}
|
||||||
@ -126,13 +126,13 @@ class DisplayGenerator {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
createKanjiEntry(details) {
|
createKanjiEntry(dictionaryEntry) {
|
||||||
const node = this._templates.instantiate('kanji-entry');
|
const node = this._templates.instantiate('kanji-entry');
|
||||||
|
|
||||||
const glyphContainer = node.querySelector('.kanji-glyph');
|
const glyphContainer = node.querySelector('.kanji-glyph');
|
||||||
const frequencyGroupListContainer = node.querySelector('.frequency-group-list');
|
const frequencyGroupListContainer = node.querySelector('.frequency-group-list');
|
||||||
const tagContainer = node.querySelector('.kanji-tag-list');
|
const tagContainer = node.querySelector('.kanji-tag-list');
|
||||||
const glossaryContainer = node.querySelector('.kanji-glossary-list');
|
const definitionsContainer = node.querySelector('.kanji-glossary-list');
|
||||||
const chineseReadingsContainer = node.querySelector('.kanji-readings-chinese');
|
const chineseReadingsContainer = node.querySelector('.kanji-readings-chinese');
|
||||||
const japaneseReadingsContainer = node.querySelector('.kanji-readings-japanese');
|
const japaneseReadingsContainer = node.querySelector('.kanji-readings-japanese');
|
||||||
const statisticsContainer = node.querySelector('.kanji-statistics');
|
const statisticsContainer = node.querySelector('.kanji-statistics');
|
||||||
@ -140,21 +140,21 @@ class DisplayGenerator {
|
|||||||
const codepointsContainer = node.querySelector('.kanji-codepoints');
|
const codepointsContainer = node.querySelector('.kanji-codepoints');
|
||||||
const dictionaryIndicesContainer = node.querySelector('.kanji-dictionary-indices');
|
const dictionaryIndicesContainer = node.querySelector('.kanji-dictionary-indices');
|
||||||
|
|
||||||
this._setTextContent(glyphContainer, details.character, 'ja');
|
this._setTextContent(glyphContainer, dictionaryEntry.character, 'ja');
|
||||||
const groupedFrequencies = DictionaryDataUtil.groupKanjiFrequencies(details.frequencies);
|
const groupedFrequencies = DictionaryDataUtil.groupKanjiFrequencies(dictionaryEntry.frequencies);
|
||||||
|
|
||||||
const dictionaryTag = this._createDictionaryTag(details.dictionary);
|
const dictionaryTag = this._createDictionaryTag(dictionaryEntry.dictionary);
|
||||||
|
|
||||||
this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, true);
|
this._appendMultiple(frequencyGroupListContainer, this._createFrequencyGroup.bind(this), groupedFrequencies, true);
|
||||||
this._appendMultiple(tagContainer, this._createTag.bind(this), [...details.tags, dictionaryTag]);
|
this._appendMultiple(tagContainer, this._createTag.bind(this), [...dictionaryEntry.tags, dictionaryTag]);
|
||||||
this._appendMultiple(glossaryContainer, this._createKanjiGlossaryItem.bind(this), details.definitions);
|
this._appendMultiple(definitionsContainer, this._createKanjiDefinition.bind(this), dictionaryEntry.definitions);
|
||||||
this._appendMultiple(chineseReadingsContainer, this._createKanjiReading.bind(this), details.onyomi);
|
this._appendMultiple(chineseReadingsContainer, this._createKanjiReading.bind(this), dictionaryEntry.onyomi);
|
||||||
this._appendMultiple(japaneseReadingsContainer, this._createKanjiReading.bind(this), details.kunyomi);
|
this._appendMultiple(japaneseReadingsContainer, this._createKanjiReading.bind(this), dictionaryEntry.kunyomi);
|
||||||
|
|
||||||
statisticsContainer.appendChild(this._createKanjiInfoTable(details.stats.misc));
|
statisticsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.misc));
|
||||||
classificationsContainer.appendChild(this._createKanjiInfoTable(details.stats.class));
|
classificationsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.class));
|
||||||
codepointsContainer.appendChild(this._createKanjiInfoTable(details.stats.code));
|
codepointsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.code));
|
||||||
dictionaryIndicesContainer.appendChild(this._createKanjiInfoTable(details.stats.index));
|
dictionaryIndicesContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.index));
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -235,20 +235,20 @@ class DisplayGenerator {
|
|||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
_createTermExpression(headword, headwordIndex, pronunciations) {
|
_createTermHeadword(headword, headwordIndex, pronunciations) {
|
||||||
const {term: expression, reading, tags: termTags} = headword;
|
const {term, reading, tags} = headword;
|
||||||
|
|
||||||
const searchQueries = [];
|
const searchQueries = [];
|
||||||
if (expression) { searchQueries.push(expression); }
|
if (term) { searchQueries.push(term); }
|
||||||
if (reading) { searchQueries.push(reading); }
|
if (reading) { searchQueries.push(reading); }
|
||||||
|
|
||||||
const node = this._templates.instantiate('expression');
|
const node = this._templates.instantiate('expression');
|
||||||
|
|
||||||
const expressionContainer = node.querySelector('.expression-text');
|
const termContainer = node.querySelector('.expression-text');
|
||||||
const tagContainer = node.querySelector('.expression-tag-list');
|
const tagContainer = node.querySelector('.expression-tag-list');
|
||||||
|
|
||||||
node.dataset.readingIsSame = `${reading === expression}`;
|
node.dataset.readingIsSame = `${reading === term}`;
|
||||||
node.dataset.frequency = DictionaryDataUtil.getTermFrequency(termTags);
|
node.dataset.frequency = DictionaryDataUtil.getTermFrequency(tags);
|
||||||
|
|
||||||
const {wordClasses} = headword;
|
const {wordClasses} = headword;
|
||||||
const pitchAccentCategories = this._getPitchAccentCategories(reading, pronunciations, wordClasses, headwordIndex);
|
const pitchAccentCategories = this._getPitchAccentCategories(reading, pronunciations, wordClasses, headwordIndex);
|
||||||
@ -261,61 +261,61 @@ class DisplayGenerator {
|
|||||||
|
|
||||||
this._setTextContent(node.querySelector('.expression-reading'), reading);
|
this._setTextContent(node.querySelector('.expression-reading'), reading);
|
||||||
|
|
||||||
this._appendFurigana(expressionContainer, expression, reading, this._appendKanjiLinks.bind(this));
|
this._appendFurigana(termContainer, term, reading, this._appendKanjiLinks.bind(this));
|
||||||
this._appendMultiple(tagContainer, this._createTag.bind(this), termTags);
|
this._appendMultiple(tagContainer, this._createTag.bind(this), tags);
|
||||||
this._appendMultiple(tagContainer, this._createSearchTag.bind(this), searchQueries);
|
this._appendMultiple(tagContainer, this._createSearchTag.bind(this), searchQueries);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermReason(reason) {
|
_createTermInflection(inflection) {
|
||||||
const fragment = this._templates.instantiateFragment('inflection');
|
const fragment = this._templates.instantiateFragment('inflection');
|
||||||
const node = fragment.querySelector('.inflection');
|
const node = fragment.querySelector('.inflection');
|
||||||
this._setTextContent(node, reason);
|
this._setTextContent(node, inflection);
|
||||||
node.dataset.reason = reason;
|
node.dataset.reason = inflection;
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermDefinitionItem(details, dictionaryTag, headwords, uniqueTerms, uniqueReadings) {
|
_createTermDefinition(definition, dictionaryTag, headwords, uniqueTerms, uniqueReadings) {
|
||||||
const {dictionary, tags, headwordIndices, entries} = details;
|
const {dictionary, tags, headwordIndices, entries} = definition;
|
||||||
const disambiguations = DictionaryDataUtil.getDisambiguations(headwords, headwordIndices, uniqueTerms, uniqueReadings);
|
const disambiguations = DictionaryDataUtil.getDisambiguations(headwords, headwordIndices, uniqueTerms, uniqueReadings);
|
||||||
|
|
||||||
const node = this._templates.instantiate('definition-item');
|
const node = this._templates.instantiate('definition-item');
|
||||||
|
|
||||||
const tagListContainer = node.querySelector('.definition-tag-list');
|
const tagListContainer = node.querySelector('.definition-tag-list');
|
||||||
const onlyListContainer = node.querySelector('.definition-disambiguation-list');
|
const onlyListContainer = node.querySelector('.definition-disambiguation-list');
|
||||||
const glossaryContainer = node.querySelector('.glossary-list');
|
const entriesContainer = node.querySelector('.glossary-list');
|
||||||
|
|
||||||
node.dataset.dictionary = dictionary;
|
node.dataset.dictionary = dictionary;
|
||||||
|
|
||||||
this._appendMultiple(tagListContainer, this._createTag.bind(this), [...tags, dictionaryTag]);
|
this._appendMultiple(tagListContainer, this._createTag.bind(this), [...tags, dictionaryTag]);
|
||||||
this._appendMultiple(onlyListContainer, this._createTermDisambiguation.bind(this), disambiguations);
|
this._appendMultiple(onlyListContainer, this._createTermDisambiguation.bind(this), disambiguations);
|
||||||
this._appendMultiple(glossaryContainer, this._createTermGlossaryItem.bind(this), entries, dictionary);
|
this._appendMultiple(entriesContainer, this._createTermDefinitionEntry.bind(this), entries, dictionary);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermGlossaryItem(glossary, dictionary) {
|
_createTermDefinitionEntry(entry, dictionary) {
|
||||||
if (typeof glossary === 'string') {
|
if (typeof entry === 'string') {
|
||||||
return this._createTermGlossaryItemText(glossary);
|
return this._createTermDefinitionEntryText(entry);
|
||||||
} else if (typeof glossary === 'object' && glossary !== null) {
|
} else if (typeof entry === 'object' && entry !== null) {
|
||||||
switch (glossary.type) {
|
switch (entry.type) {
|
||||||
case 'image':
|
case 'image':
|
||||||
return this._createTermGlossaryItemImage(glossary, dictionary);
|
return this._createTermDefinitionEntryImage(entry, dictionary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermGlossaryItemText(glossary) {
|
_createTermDefinitionEntryText(text) {
|
||||||
const node = this._templates.instantiate('glossary-item');
|
const node = this._templates.instantiate('glossary-item');
|
||||||
const container = node.querySelector('.glossary');
|
const container = node.querySelector('.glossary');
|
||||||
this._setMultilineTextContent(container, glossary);
|
this._setMultilineTextContent(container, text);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermGlossaryItemImage(data, dictionary) {
|
_createTermDefinitionEntryImage(data, dictionary) {
|
||||||
const {path, width, height, preferredWidth, preferredHeight, title, description, pixelated} = data;
|
const {path, width, height, preferredWidth, preferredHeight, title, description, pixelated} = data;
|
||||||
|
|
||||||
const usedWidth = (
|
const usedWidth = (
|
||||||
@ -391,10 +391,10 @@ class DisplayGenerator {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createKanjiGlossaryItem(glossary) {
|
_createKanjiDefinition(text) {
|
||||||
const node = this._templates.instantiate('kanji-glossary-item');
|
const node = this._templates.instantiate('kanji-glossary-item');
|
||||||
const container = node.querySelector('.kanji-glossary');
|
const container = node.querySelector('.kanji-glossary');
|
||||||
this._setMultilineTextContent(container, glossary);
|
this._setMultilineTextContent(container, text);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,8 +431,8 @@ class DisplayGenerator {
|
|||||||
return this._templates.instantiate('kanji-info-table-empty');
|
return this._templates.instantiate('kanji-info-table-empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTag(details) {
|
_createTag(tag) {
|
||||||
const {content, name, category, redundant} = details;
|
const {content, name, category, redundant} = tag;
|
||||||
const node = this._templates.instantiate('tag');
|
const node = this._templates.instantiate('tag');
|
||||||
|
|
||||||
const inner = node.querySelector('.tag-label-content');
|
const inner = node.querySelector('.tag-label-content');
|
||||||
@ -448,8 +448,8 @@ class DisplayGenerator {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermTag(details, totalHeadwordCount) {
|
_createTermTag(tagInfo, totalHeadwordCount) {
|
||||||
const {tag, headwordIndices} = details;
|
const {tag, headwordIndices} = tagInfo;
|
||||||
const node = this._createTag(tag);
|
const node = this._createTag(tag);
|
||||||
node.dataset.headwords = headwordIndices.join(' ');
|
node.dataset.headwords = headwordIndices.join(' ');
|
||||||
node.dataset.totalExpressionCount = `${totalHeadwordCount}`;
|
node.dataset.totalExpressionCount = `${totalHeadwordCount}`;
|
||||||
@ -547,10 +547,10 @@ class DisplayGenerator {
|
|||||||
|
|
||||||
_createPitchAccentDisambiguations(container, exclusiveTerms, exclusiveReadings) {
|
_createPitchAccentDisambiguations(container, exclusiveTerms, exclusiveReadings) {
|
||||||
const templateName = 'pitch-accent-disambiguation';
|
const templateName = 'pitch-accent-disambiguation';
|
||||||
for (const exclusiveExpression of exclusiveTerms) {
|
for (const term of exclusiveTerms) {
|
||||||
const node = this._templates.instantiate(templateName);
|
const node = this._templates.instantiate(templateName);
|
||||||
node.dataset.type = 'expression';
|
node.dataset.type = 'expression';
|
||||||
this._setTextContent(node, exclusiveExpression, 'ja');
|
this._setTextContent(node, term, 'ja');
|
||||||
container.appendChild(node);
|
container.appendChild(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,9 +712,9 @@ class DisplayGenerator {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
_appendFurigana(container, expression, reading, addText) {
|
_appendFurigana(container, term, reading, addText) {
|
||||||
container.lang = 'ja';
|
container.lang = 'ja';
|
||||||
const segments = this._japaneseUtil.distributeFurigana(expression, reading);
|
const segments = this._japaneseUtil.distributeFurigana(term, reading);
|
||||||
for (const {text, furigana} of segments) {
|
for (const {text, furigana} of segments) {
|
||||||
if (furigana) {
|
if (furigana) {
|
||||||
const ruby = document.createElement('ruby');
|
const ruby = document.createElement('ruby');
|
||||||
|
@ -47,8 +47,8 @@ class Display extends EventDispatcher {
|
|||||||
this._documentFocusController = documentFocusController;
|
this._documentFocusController = documentFocusController;
|
||||||
this._hotkeyHandler = hotkeyHandler;
|
this._hotkeyHandler = hotkeyHandler;
|
||||||
this._container = document.querySelector('#definitions');
|
this._container = document.querySelector('#definitions');
|
||||||
this._definitions = [];
|
this._dictionaryEntries = [];
|
||||||
this._definitionNodes = [];
|
this._dictionaryEntryNodes = [];
|
||||||
this._optionsContext = {depth: 0, url: window.location.href};
|
this._optionsContext = {depth: 0, url: window.location.href};
|
||||||
this._options = null;
|
this._options = null;
|
||||||
this._index = 0;
|
this._index = 0;
|
||||||
@ -107,7 +107,7 @@ class Display extends EventDispatcher {
|
|||||||
this._frameEndpoint = (pageType === 'popup' ? new FrameEndpoint() : null);
|
this._frameEndpoint = (pageType === 'popup' ? new FrameEndpoint() : null);
|
||||||
this._browser = null;
|
this._browser = null;
|
||||||
this._copyTextarea = null;
|
this._copyTextarea = null;
|
||||||
this._definitionTextScanner = null;
|
this._contentTextScanner = null;
|
||||||
this._tagNotification = null;
|
this._tagNotification = null;
|
||||||
this._footerNotificationContainer = document.querySelector('#content-footer');
|
this._footerNotificationContainer = document.querySelector('#content-footer');
|
||||||
this._displayAudio = new DisplayAudio(this);
|
this._displayAudio = new DisplayAudio(this);
|
||||||
@ -121,14 +121,14 @@ class Display extends EventDispatcher {
|
|||||||
['close', () => { this._onHotkeyClose(); }],
|
['close', () => { this._onHotkeyClose(); }],
|
||||||
['nextEntry', this._onHotkeyActionMoveRelative.bind(this, 1)],
|
['nextEntry', this._onHotkeyActionMoveRelative.bind(this, 1)],
|
||||||
['previousEntry', this._onHotkeyActionMoveRelative.bind(this, -1)],
|
['previousEntry', this._onHotkeyActionMoveRelative.bind(this, -1)],
|
||||||
['lastEntry', () => { this._focusEntry(this._definitions.length - 1, true); }],
|
['lastEntry', () => { this._focusEntry(this._dictionaryEntries.length - 1, true); }],
|
||||||
['firstEntry', () => { this._focusEntry(0, true); }],
|
['firstEntry', () => { this._focusEntry(0, true); }],
|
||||||
['historyBackward', () => { this._sourceTermView(); }],
|
['historyBackward', () => { this._sourceTermView(); }],
|
||||||
['historyForward', () => { this._nextTermView(); }],
|
['historyForward', () => { this._nextTermView(); }],
|
||||||
['addNoteKanji', () => { this._tryAddAnkiNoteForSelectedDefinition('kanji'); }],
|
['addNoteKanji', () => { this._tryAddAnkiNoteForSelectedEntry('kanji'); }],
|
||||||
['addNoteTermKanji', () => { this._tryAddAnkiNoteForSelectedDefinition('term-kanji'); }],
|
['addNoteTermKanji', () => { this._tryAddAnkiNoteForSelectedEntry('term-kanji'); }],
|
||||||
['addNoteTermKana', () => { this._tryAddAnkiNoteForSelectedDefinition('term-kana'); }],
|
['addNoteTermKana', () => { this._tryAddAnkiNoteForSelectedEntry('term-kana'); }],
|
||||||
['viewNote', () => { this._tryViewAnkiNoteForSelectedDefinition(); }],
|
['viewNote', () => { this._tryViewAnkiNoteForSelectedEntry(); }],
|
||||||
['playAudio', () => { this._playAudioCurrent(); }],
|
['playAudio', () => { this._playAudioCurrent(); }],
|
||||||
['playAudioFromSource', this._onHotkeyActionPlayAudioFromSource.bind(this)],
|
['playAudioFromSource', this._onHotkeyActionPlayAudioFromSource.bind(this)],
|
||||||
['copyHostSelection', () => this._copyHostSelection()],
|
['copyHostSelection', () => this._copyHostSelection()],
|
||||||
@ -181,12 +181,12 @@ class Display extends EventDispatcher {
|
|||||||
return this._hotkeyHandler;
|
return this._hotkeyHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
get definitions() {
|
get dictionaryEntries() {
|
||||||
return this._definitions;
|
return this._dictionaryEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
get definitionNodes() {
|
get dictionaryEntryNodes() {
|
||||||
return this._definitionNodes;
|
return this._dictionaryEntryNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
get progressIndicatorVisible() {
|
get progressIndicatorVisible() {
|
||||||
@ -327,7 +327,7 @@ class Display extends EventDispatcher {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this._updateNestedFrontend(options);
|
this._updateNestedFrontend(options);
|
||||||
this._updateDefinitionTextScanner(options);
|
this._updateContentTextScanner(options);
|
||||||
|
|
||||||
this.trigger('optionsUpdated', {options});
|
this.trigger('optionsUpdated', {options});
|
||||||
}
|
}
|
||||||
@ -434,7 +434,7 @@ class Display extends EventDispatcher {
|
|||||||
params: this._createSearchParams(type, query, false),
|
params: this._createSearchParams(type, query, false),
|
||||||
state,
|
state,
|
||||||
content: {
|
content: {
|
||||||
definitions: null,
|
dictionaryEntries: null,
|
||||||
contentOrigin: this.getContentOrigin()
|
contentOrigin: this.getContentOrigin()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -536,8 +536,8 @@ class Display extends EventDispatcher {
|
|||||||
this._displayAudio.cleanupEntries();
|
this._displayAudio.cleanupEntries();
|
||||||
this._hideTagNotification(false);
|
this._hideTagNotification(false);
|
||||||
this._hideAnkiNoteErrors(false);
|
this._hideAnkiNoteErrors(false);
|
||||||
this._definitions = [];
|
this._dictionaryEntries = [];
|
||||||
this._definitionNodes = [];
|
this._dictionaryEntryNodes = [];
|
||||||
this._elementOverflowController.clearElements();
|
this._elementOverflowController.clearElements();
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
@ -606,7 +606,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onQueryParserSearch({type, definitions, sentence, inputInfo: {eventType}, textSource, optionsContext}) {
|
_onQueryParserSearch({type, dictionaryEntries, sentence, inputInfo: {eventType}, textSource, optionsContext}) {
|
||||||
const query = textSource.text();
|
const query = textSource.text();
|
||||||
const historyState = this._history.state;
|
const historyState = this._history.state;
|
||||||
const history = (
|
const history = (
|
||||||
@ -624,7 +624,7 @@ class Display extends EventDispatcher {
|
|||||||
cause: 'queryParser'
|
cause: 'queryParser'
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
definitions,
|
dictionaryEntries,
|
||||||
contentOrigin: this.getContentOrigin()
|
contentOrigin: this.getContentOrigin()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -693,7 +693,7 @@ class Display extends EventDispatcher {
|
|||||||
if (typeof documentTitle !== 'string') { documentTitle = document.title; }
|
if (typeof documentTitle !== 'string') { documentTitle = document.title; }
|
||||||
const optionsContext = this.getOptionsContext();
|
const optionsContext = this.getOptionsContext();
|
||||||
const query = e.currentTarget.textContent;
|
const query = e.currentTarget.textContent;
|
||||||
const definitions = await yomichan.api.kanjiFind(query, optionsContext);
|
const dictionaryEntries = await yomichan.api.kanjiFind(query, optionsContext);
|
||||||
const details = {
|
const details = {
|
||||||
focus: false,
|
focus: false,
|
||||||
history: true,
|
history: true,
|
||||||
@ -706,7 +706,7 @@ class Display extends EventDispatcher {
|
|||||||
documentTitle
|
documentTitle
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
definitions,
|
dictionaryEntries,
|
||||||
contentOrigin: this.getContentOrigin()
|
contentOrigin: this.getContentOrigin()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -719,7 +719,7 @@ class Display extends EventDispatcher {
|
|||||||
_onNoteAdd(e) {
|
_onNoteAdd(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const link = e.currentTarget;
|
const link = e.currentTarget;
|
||||||
const index = this._getClosestDefinitionIndex(link);
|
const index = this._getClosestDictionaryEntryIndex(link);
|
||||||
this._addAnkiNote(index, link.dataset.mode);
|
this._addAnkiNote(index, link.dataset.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,8 +756,8 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
_onDebugLogClick(e) {
|
_onDebugLogClick(e) {
|
||||||
const link = e.currentTarget;
|
const link = e.currentTarget;
|
||||||
const index = this._getClosestDefinitionIndex(link);
|
const index = this._getClosestDictionaryEntryIndex(link);
|
||||||
this._logDefinitionData(index);
|
this._logDictionaryEntryData(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDocumentElementMouseUp(e) {
|
_onDocumentElementMouseUp(e) {
|
||||||
@ -814,8 +814,8 @@ class Display extends EventDispatcher {
|
|||||||
this._tagNotification = new DisplayNotification(this._footerNotificationContainer, node);
|
this._tagNotification = new DisplayNotification(this._footerNotificationContainer, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = this._getClosestDefinitionIndex(tagNode);
|
const index = this._getClosestDictionaryEntryIndex(tagNode);
|
||||||
const dictionaryEntry = (index >= 0 && index < this._definitions.length ? this._definitions[index] : null);
|
const dictionaryEntry = (index >= 0 && index < this._dictionaryEntries.length ? this._dictionaryEntries[index] : null);
|
||||||
|
|
||||||
const content = this._displayGenerator.createTagFooterNotificationDetails(tagNode, dictionaryEntry);
|
const content = this._displayGenerator.createTagFooterNotificationDetails(tagNode, dictionaryEntry);
|
||||||
this._tagNotification.setContent(content);
|
this._tagNotification.setContent(content);
|
||||||
@ -850,7 +850,7 @@ class Display extends EventDispatcher {
|
|||||||
document.documentElement.dataset.theme = themeName;
|
document.documentElement.dataset.theme = themeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _findDefinitions(isTerms, source, wildcardsEnabled, optionsContext) {
|
async _findDictionaryEntries(isTerms, source, wildcardsEnabled, optionsContext) {
|
||||||
if (isTerms) {
|
if (isTerms) {
|
||||||
const findDetails = {};
|
const findDetails = {};
|
||||||
if (wildcardsEnabled) {
|
if (wildcardsEnabled) {
|
||||||
@ -865,11 +865,11 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {definitions} = await yomichan.api.termsFind(source, findDetails, optionsContext);
|
const {dictionaryEntries} = await yomichan.api.termsFind(source, findDetails, optionsContext);
|
||||||
return definitions;
|
return dictionaryEntries;
|
||||||
} else {
|
} else {
|
||||||
const definitions = await yomichan.api.kanjiFind(source, optionsContext);
|
const dictionaryEntries = await yomichan.api.kanjiFind(source, optionsContext);
|
||||||
return definitions;
|
return dictionaryEntries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,11 +901,11 @@ class Display extends EventDispatcher {
|
|||||||
this._setFullQuery(queryFull);
|
this._setFullQuery(queryFull);
|
||||||
this._setTitleText(query);
|
this._setTitleText(query);
|
||||||
|
|
||||||
let {definitions} = content;
|
let {dictionaryEntries} = content;
|
||||||
if (!Array.isArray(definitions)) {
|
if (!Array.isArray(dictionaryEntries)) {
|
||||||
definitions = lookup && query.length > 0 ? await this._findDefinitions(isTerms, query, wildcardsEnabled, optionsContext) : [];
|
dictionaryEntries = lookup && query.length > 0 ? await this._findDictionaryEntries(isTerms, query, wildcardsEnabled, optionsContext) : [];
|
||||||
if (this._setContentToken !== token) { return; }
|
if (this._setContentToken !== token) { return; }
|
||||||
content.definitions = definitions;
|
content.dictionaryEntries = dictionaryEntries;
|
||||||
changeHistory = true;
|
changeHistory = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -940,28 +940,28 @@ class Display extends EventDispatcher {
|
|||||||
eventArgs.content = content;
|
eventArgs.content = content;
|
||||||
this.trigger('contentUpdating', eventArgs);
|
this.trigger('contentUpdating', eventArgs);
|
||||||
|
|
||||||
this._definitions = definitions;
|
this._dictionaryEntries = dictionaryEntries;
|
||||||
|
|
||||||
this._updateNavigation(this._history.hasPrevious(), this._history.hasNext());
|
this._updateNavigation(this._history.hasPrevious(), this._history.hasNext());
|
||||||
this._setNoContentVisible(definitions.length === 0 && lookup);
|
this._setNoContentVisible(dictionaryEntries.length === 0 && lookup);
|
||||||
|
|
||||||
const container = this._container;
|
const container = this._container;
|
||||||
container.textContent = '';
|
container.textContent = '';
|
||||||
|
|
||||||
for (let i = 0, ii = definitions.length; i < ii; ++i) {
|
for (let i = 0, ii = dictionaryEntries.length; i < ii; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
await promiseTimeout(1);
|
await promiseTimeout(1);
|
||||||
if (this._setContentToken !== token) { return; }
|
if (this._setContentToken !== token) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
const definition = definitions[i];
|
const dictionaryEntry = dictionaryEntries[i];
|
||||||
const entry = (
|
const entry = (
|
||||||
isTerms ?
|
isTerms ?
|
||||||
this._displayGenerator.createTermEntry(definition) :
|
this._displayGenerator.createTermEntry(dictionaryEntry) :
|
||||||
this._displayGenerator.createKanjiEntry(definition)
|
this._displayGenerator.createKanjiEntry(dictionaryEntry)
|
||||||
);
|
);
|
||||||
entry.dataset.index = `${i}`;
|
entry.dataset.index = `${i}`;
|
||||||
this._definitionNodes.push(entry);
|
this._dictionaryEntryNodes.push(entry);
|
||||||
this._addEntryEventListeners(entry);
|
this._addEntryEventListeners(entry);
|
||||||
this._displayAudio.setupEntry(entry, i);
|
this._displayAudio.setupEntry(entry, i);
|
||||||
container.appendChild(entry);
|
container.appendChild(entry);
|
||||||
@ -982,7 +982,7 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
this._displayAudio.setupEntriesComplete();
|
this._displayAudio.setupEntriesComplete();
|
||||||
|
|
||||||
this._updateAdderButtons(token, isTerms, definitions);
|
this._updateAdderButtons(token, isTerms, dictionaryEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
_setContentExtensionUnloaded() {
|
_setContentExtensionUnloaded() {
|
||||||
@ -1069,7 +1069,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _updateAdderButtons(token, isTerms, definitions) {
|
async _updateAdderButtons(token, isTerms, dictionaryEntries) {
|
||||||
await this._updateAdderButtonsPromise;
|
await this._updateAdderButtonsPromise;
|
||||||
if (this._setContentToken !== token) { return; }
|
if (this._setContentToken !== token) { return; }
|
||||||
|
|
||||||
@ -1082,7 +1082,7 @@ class Display extends EventDispatcher {
|
|||||||
try {
|
try {
|
||||||
const noteContext = this._getNoteContext();
|
const noteContext = this._getNoteContext();
|
||||||
const {checkForDuplicates} = this._options.anki;
|
const {checkForDuplicates} = this._options.anki;
|
||||||
states = await this._areDefinitionsAddable(definitions, modes, noteContext, checkForDuplicates ? null : true);
|
states = await this._areDictionaryEntriesAddable(dictionaryEntries, modes, noteContext, checkForDuplicates ? null : true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1136,7 +1136,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_focusEntry(index, smooth) {
|
_focusEntry(index, smooth) {
|
||||||
index = Math.max(Math.min(index, this._definitions.length - 1), 0);
|
index = Math.max(Math.min(index, this._dictionaryEntries.length - 1), 0);
|
||||||
|
|
||||||
const entry = this._entrySetCurrent(index);
|
const entry = this._entrySetCurrent(index);
|
||||||
let target = index === 0 || entry === null ? 0 : this._getElementTop(entry);
|
let target = index === 0 || entry === null ? 0 : this._getElementTop(entry);
|
||||||
@ -1158,12 +1158,12 @@ class Display extends EventDispatcher {
|
|||||||
if (offsetSign === 0) { return false; }
|
if (offsetSign === 0) { return false; }
|
||||||
|
|
||||||
let index = this._index;
|
let index = this._index;
|
||||||
const definitionCount = this._definitions.length;
|
const dictionaryEntryCount = this._dictionaryEntries.length;
|
||||||
if (index < 0 || index >= definitionCount) { return false; }
|
if (index < 0 || index >= dictionaryEntryCount) { return false; }
|
||||||
|
|
||||||
const {dictionary} = this._definitions[index];
|
const {dictionary} = this._dictionaryEntries[index];
|
||||||
for (let indexNext = index + offsetSign; indexNext >= 0 && indexNext < definitionCount; indexNext += offsetSign) {
|
for (let indexNext = index + offsetSign; indexNext >= 0 && indexNext < dictionaryEntryCount; indexNext += offsetSign) {
|
||||||
const {dictionaryNames} = this._definitions[indexNext];
|
const {dictionaryNames} = this._dictionaryEntries[indexNext];
|
||||||
if (dictionaryNames.length > 1 || !dictionaryNames.includes(dictionary)) {
|
if (dictionaryNames.length > 1 || !dictionaryNames.includes(dictionary)) {
|
||||||
offset -= offsetSign;
|
offset -= offsetSign;
|
||||||
if (Math.sign(offsetSign) !== offset) {
|
if (Math.sign(offsetSign) !== offset) {
|
||||||
@ -1195,22 +1195,22 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_tryAddAnkiNoteForSelectedDefinition(mode) {
|
_tryAddAnkiNoteForSelectedEntry(mode) {
|
||||||
this._addAnkiNote(this._index, mode);
|
this._addAnkiNote(this._index, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_tryViewAnkiNoteForSelectedDefinition() {
|
_tryViewAnkiNoteForSelectedEntry() {
|
||||||
const button = this._viewerButtonFind(this._index);
|
const button = this._viewerButtonFind(this._index);
|
||||||
if (button !== null && !button.disabled) {
|
if (button !== null && !button.disabled) {
|
||||||
yomichan.api.noteView(button.dataset.noteId);
|
yomichan.api.noteView(button.dataset.noteId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _addAnkiNote(definitionIndex, mode) {
|
async _addAnkiNote(dictionaryEntryIndex, mode) {
|
||||||
if (definitionIndex < 0 || definitionIndex >= this._definitions.length) { return; }
|
if (dictionaryEntryIndex < 0 || dictionaryEntryIndex >= this._dictionaryEntries.length) { return; }
|
||||||
const definition = this._definitions[definitionIndex];
|
const dictionaryEntry = this._dictionaryEntries[dictionaryEntryIndex];
|
||||||
|
|
||||||
const button = this._adderButtonFind(definitionIndex, mode);
|
const button = this._adderButtonFind(dictionaryEntryIndex, mode);
|
||||||
if (button === null || button.disabled) { return; }
|
if (button === null || button.disabled) { return; }
|
||||||
|
|
||||||
this._hideAnkiNoteErrors(true);
|
this._hideAnkiNoteErrors(true);
|
||||||
@ -1220,7 +1220,7 @@ class Display extends EventDispatcher {
|
|||||||
try {
|
try {
|
||||||
const {anki: {suspendNewCards}} = this._options;
|
const {anki: {suspendNewCards}} = this._options;
|
||||||
const noteContext = this._getNoteContext();
|
const noteContext = this._getNoteContext();
|
||||||
const note = await this._createNote(definition, mode, noteContext, true, errors);
|
const note = await this._createNote(dictionaryEntry, mode, noteContext, true, errors);
|
||||||
|
|
||||||
let noteId = null;
|
let noteId = null;
|
||||||
let addNoteOkay = false;
|
let addNoteOkay = false;
|
||||||
@ -1244,7 +1244,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
this._viewerButtonShow(definitionIndex, noteId);
|
this._viewerButtonShow(dictionaryEntryIndex, noteId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -1293,7 +1293,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getEntry(index) {
|
_getEntry(index) {
|
||||||
const entries = this._definitionNodes;
|
const entries = this._dictionaryEntryNodes;
|
||||||
return index >= 0 && index < entries.length ? entries[index] : null;
|
return index >= 0 && index < entries.length ? entries[index] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1304,7 +1304,7 @@ class Display extends EventDispatcher {
|
|||||||
return {text, offset};
|
return {text, offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
_getClosestDefinitionIndex(element) {
|
_getClosestDictionaryEntryIndex(element) {
|
||||||
return this._getClosestIndex(element, '.entry');
|
return this._getClosestIndex(element, '.entry');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1424,12 +1424,12 @@ class Display extends EventDispatcher {
|
|||||||
return templates;
|
return templates;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _areDefinitionsAddable(definitions, modes, context, forceCanAddValue) {
|
async _areDictionaryEntriesAddable(dictionaryEntries, modes, context, forceCanAddValue) {
|
||||||
const modeCount = modes.length;
|
const modeCount = modes.length;
|
||||||
const notePromises = [];
|
const notePromises = [];
|
||||||
for (const definition of definitions) {
|
for (const dictionaryEntry of dictionaryEntries) {
|
||||||
for (const mode of modes) {
|
for (const mode of modes) {
|
||||||
const notePromise = this._createNote(definition, mode, context, false, null);
|
const notePromise = this._createNote(dictionaryEntry, mode, context, false, null);
|
||||||
notePromises.push(notePromise);
|
notePromises.push(notePromise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1461,7 +1461,7 @@ class Display extends EventDispatcher {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _createNote(definition, mode, context, injectMedia, errors) {
|
async _createNote(dictionaryEntry, mode, context, injectMedia, errors) {
|
||||||
const options = this._options;
|
const options = this._options;
|
||||||
const template = this._ankiFieldTemplates;
|
const template = this._ankiFieldTemplates;
|
||||||
const {
|
const {
|
||||||
@ -1476,7 +1476,7 @@ class Display extends EventDispatcher {
|
|||||||
let injectedMedia = null;
|
let injectedMedia = null;
|
||||||
if (injectMedia) {
|
if (injectMedia) {
|
||||||
let errors2;
|
let errors2;
|
||||||
({result: injectedMedia, errors: errors2} = await this._injectAnkiNoteMedia(definition, options, fields));
|
({result: injectedMedia, errors: errors2} = await this._injectAnkiNoteMedia(dictionaryEntry, options, fields));
|
||||||
if (Array.isArray(errors)) {
|
if (Array.isArray(errors)) {
|
||||||
for (const error of errors2) {
|
for (const error of errors2) {
|
||||||
errors.push(deserializeError(error));
|
errors.push(deserializeError(error));
|
||||||
@ -1485,7 +1485,7 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await this._ankiNoteBuilder.createNote({
|
return await this._ankiNoteBuilder.createNote({
|
||||||
definition,
|
dictionaryEntry,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
template,
|
template,
|
||||||
@ -1503,7 +1503,7 @@ class Display extends EventDispatcher {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _injectAnkiNoteMedia(definition, options, fields) {
|
async _injectAnkiNoteMedia(dictionaryEntry, options, fields) {
|
||||||
const {
|
const {
|
||||||
anki: {screenshot: {format, quality}},
|
anki: {screenshot: {format, quality}},
|
||||||
audio: {sources, customSourceUrl, customSourceType}
|
audio: {sources, customSourceUrl, customSourceType}
|
||||||
@ -1511,11 +1511,11 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
|
|
||||||
const definitionDetails = this._getDefinitionDetailsForNote(definition);
|
const dictionaryEntryDetails = this._getDictionaryEntryDetailsForNote(dictionaryEntry);
|
||||||
|
|
||||||
let audioDetails = null;
|
let audioDetails = null;
|
||||||
if (definitionDetails.type !== 'kanji' && AnkiUtil.fieldsObjectContainsMarker(fields, 'audio')) {
|
if (dictionaryEntryDetails.type !== 'kanji' && AnkiUtil.fieldsObjectContainsMarker(fields, 'audio')) {
|
||||||
const primaryCardAudio = this._displayAudio.getPrimaryCardAudio(definitionDetails.term, definitionDetails.reading);
|
const primaryCardAudio = this._displayAudio.getPrimaryCardAudio(dictionaryEntryDetails.term, dictionaryEntryDetails.reading);
|
||||||
let preferredAudioIndex = null;
|
let preferredAudioIndex = null;
|
||||||
let sources2 = sources;
|
let sources2 = sources;
|
||||||
if (primaryCardAudio !== null) {
|
if (primaryCardAudio !== null) {
|
||||||
@ -1534,14 +1534,14 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
return await yomichan.api.injectAnkiNoteMedia(
|
return await yomichan.api.injectAnkiNoteMedia(
|
||||||
timestamp,
|
timestamp,
|
||||||
definitionDetails,
|
dictionaryEntryDetails,
|
||||||
audioDetails,
|
audioDetails,
|
||||||
screenshotDetails,
|
screenshotDetails,
|
||||||
clipboardDetails
|
clipboardDetails
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getDefinitionDetailsForNote(dictionaryEntry) {
|
_getDictionaryEntryDetailsForNote(dictionaryEntry) {
|
||||||
const {type} = dictionaryEntry;
|
const {type} = dictionaryEntry;
|
||||||
if (type === 'kanji') {
|
if (type === 'kanji') {
|
||||||
const {character} = dictionaryEntry;
|
const {character} = dictionaryEntry;
|
||||||
@ -1710,16 +1710,16 @@ class Display extends EventDispatcher {
|
|||||||
this._addMultipleEventListeners(entry, '.tag-label', 'click', this._onTagClick.bind(this));
|
this._addMultipleEventListeners(entry, '.tag-label', 'click', this._onTagClick.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateDefinitionTextScanner(options) {
|
_updateContentTextScanner(options) {
|
||||||
if (!options.scanning.enablePopupSearch) {
|
if (!options.scanning.enablePopupSearch) {
|
||||||
if (this._definitionTextScanner !== null) {
|
if (this._contentTextScanner !== null) {
|
||||||
this._definitionTextScanner.setEnabled(false);
|
this._contentTextScanner.setEnabled(false);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._definitionTextScanner === null) {
|
if (this._contentTextScanner === null) {
|
||||||
this._definitionTextScanner = new TextScanner({
|
this._contentTextScanner = new TextScanner({
|
||||||
node: window,
|
node: window,
|
||||||
getSearchContext: this._getSearchContext.bind(this),
|
getSearchContext: this._getSearchContext.bind(this),
|
||||||
documentUtil: this._documentUtil,
|
documentUtil: this._documentUtil,
|
||||||
@ -1728,14 +1728,14 @@ class Display extends EventDispatcher {
|
|||||||
searchOnClick: true,
|
searchOnClick: true,
|
||||||
searchOnClickOnly: true
|
searchOnClickOnly: true
|
||||||
});
|
});
|
||||||
this._definitionTextScanner.includeSelector = '.click-scannable,.click-scannable *';
|
this._contentTextScanner.includeSelector = '.click-scannable,.click-scannable *';
|
||||||
this._definitionTextScanner.excludeSelector = '.scan-disable,.scan-disable *';
|
this._contentTextScanner.excludeSelector = '.scan-disable,.scan-disable *';
|
||||||
this._definitionTextScanner.prepare();
|
this._contentTextScanner.prepare();
|
||||||
this._definitionTextScanner.on('searched', this._onDefinitionTextScannerSearched.bind(this));
|
this._contentTextScanner.on('searched', this._onContentTextScannerSearched.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
const {scanning: scanningOptions, sentenceParsing: sentenceParsingOptions} = options;
|
const {scanning: scanningOptions, sentenceParsing: sentenceParsingOptions} = options;
|
||||||
this._definitionTextScanner.setOptions({
|
this._contentTextScanner.setOptions({
|
||||||
inputs: [{
|
inputs: [{
|
||||||
include: 'mouse0',
|
include: 'mouse0',
|
||||||
exclude: '',
|
exclude: '',
|
||||||
@ -1761,10 +1761,10 @@ class Display extends EventDispatcher {
|
|||||||
sentenceParsingOptions
|
sentenceParsingOptions
|
||||||
});
|
});
|
||||||
|
|
||||||
this._definitionTextScanner.setEnabled(true);
|
this._contentTextScanner.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDefinitionTextScannerSearched({type, definitions, sentence, textSource, optionsContext, error}) {
|
_onContentTextScannerSearched({type, dictionaryEntries, sentence, textSource, optionsContext, error}) {
|
||||||
if (error !== null && !yomichan.isExtensionUnloaded) {
|
if (error !== null && !yomichan.isExtensionUnloaded) {
|
||||||
log.error(error);
|
log.error(error);
|
||||||
}
|
}
|
||||||
@ -1790,11 +1790,11 @@ class Display extends EventDispatcher {
|
|||||||
documentTitle
|
documentTitle
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
definitions,
|
dictionaryEntries,
|
||||||
contentOrigin: this.getContentOrigin()
|
contentOrigin: this.getContentOrigin()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this._definitionTextScanner.clearSelection(true);
|
this._contentTextScanner.clearSelection(true);
|
||||||
this.setContent(details);
|
this.setContent(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1865,16 +1865,16 @@ class Display extends EventDispatcher {
|
|||||||
return typeof queryPostProcessor === 'function' ? queryPostProcessor(query) : query;
|
return typeof queryPostProcessor === 'function' ? queryPostProcessor(query) : query;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _logDefinitionData(index) {
|
async _logDictionaryEntryData(index) {
|
||||||
if (index < 0 || index >= this._definitions.length) { return; }
|
if (index < 0 || index >= this._dictionaryEntries.length) { return; }
|
||||||
const dictionaryEntry = this._definitions[index];
|
const dictionaryEntry = this._dictionaryEntries[index];
|
||||||
let ankiNoteData;
|
let ankiNoteData;
|
||||||
let ankiNoteDataException;
|
let ankiNoteDataException;
|
||||||
try {
|
try {
|
||||||
const context = this._getNoteContext();
|
const context = this._getNoteContext();
|
||||||
const {general: {resultOutputMode, glossaryLayoutMode, compactTags}} = this._options;
|
const {general: {resultOutputMode, glossaryLayoutMode, compactTags}} = this._options;
|
||||||
ankiNoteData = await this._ankiNoteBuilder.getRenderingData({
|
ankiNoteData = await this._ankiNoteBuilder.getRenderingData({
|
||||||
definition: dictionaryEntry,
|
dictionaryEntry,
|
||||||
mode: 'test',
|
mode: 'test',
|
||||||
context,
|
context,
|
||||||
resultOutputMode,
|
resultOutputMode,
|
||||||
|
@ -361,7 +361,7 @@ class SearchDisplayController {
|
|||||||
documentTitle
|
documentTitle
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
definitions: null,
|
dictionaryEntries: null,
|
||||||
animate,
|
animate,
|
||||||
contentOrigin: {
|
contentOrigin: {
|
||||||
tabId: this.tabId,
|
tabId: this.tabId,
|
||||||
|
@ -93,10 +93,10 @@ class DictionaryDataUtil {
|
|||||||
static getPitchAccentInfos(dictionaryEntry) {
|
static getPitchAccentInfos(dictionaryEntry) {
|
||||||
const {headwords, pronunciations} = dictionaryEntry;
|
const {headwords, pronunciations} = dictionaryEntry;
|
||||||
|
|
||||||
const allExpressions = new Set();
|
const allTerms = new Set();
|
||||||
const allReadings = new Set();
|
const allReadings = new Set();
|
||||||
for (const {term, reading} of headwords) {
|
for (const {term, reading} of headwords) {
|
||||||
allExpressions.add(term);
|
allTerms.add(term);
|
||||||
allReadings.add(reading);
|
allReadings.add(reading);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,8 +129,8 @@ class DictionaryDataUtil {
|
|||||||
for (const dictionaryPitchAccentInfoList of pitchAccentInfoMap.values()) {
|
for (const dictionaryPitchAccentInfoList of pitchAccentInfoMap.values()) {
|
||||||
for (const pitchAccentInfo of dictionaryPitchAccentInfoList) {
|
for (const pitchAccentInfo of dictionaryPitchAccentInfoList) {
|
||||||
const {terms, reading, exclusiveTerms, exclusiveReadings} = pitchAccentInfo;
|
const {terms, reading, exclusiveTerms, exclusiveReadings} = pitchAccentInfo;
|
||||||
if (!this._areSetsEqual(terms, allExpressions)) {
|
if (!this._areSetsEqual(terms, allTerms)) {
|
||||||
exclusiveTerms.push(...this._getSetIntersection(terms, allExpressions));
|
exclusiveTerms.push(...this._getSetIntersection(terms, allTerms));
|
||||||
}
|
}
|
||||||
if (multipleReadings) {
|
if (multipleReadings) {
|
||||||
exclusiveReadings.push(reading);
|
exclusiveReadings.push(reading);
|
||||||
|
@ -26,7 +26,7 @@ class DictionaryDatabase {
|
|||||||
this._schemas = new Map();
|
this._schemas = new Map();
|
||||||
this._createOnlyQuery1 = (item) => IDBKeyRange.only(item);
|
this._createOnlyQuery1 = (item) => IDBKeyRange.only(item);
|
||||||
this._createOnlyQuery2 = (item) => IDBKeyRange.only(item.query);
|
this._createOnlyQuery2 = (item) => IDBKeyRange.only(item.query);
|
||||||
this._createOnlyQuery3 = (item) => IDBKeyRange.only(item.expression);
|
this._createOnlyQuery3 = (item) => IDBKeyRange.only(item.term);
|
||||||
this._createOnlyQuery4 = (item) => IDBKeyRange.only(item.path);
|
this._createOnlyQuery4 = (item) => IDBKeyRange.only(item.path);
|
||||||
this._createBoundQuery1 = (item) => IDBKeyRange.bound(item, `${item}\uffff`, false, false);
|
this._createBoundQuery1 = (item) => IDBKeyRange.bound(item, `${item}\uffff`, false, false);
|
||||||
this._createBoundQuery2 = (item) => { item = stringReverse(item); return IDBKeyRange.bound(item, `${item}\uffff`, false, false); };
|
this._createBoundQuery2 = (item) => { item = stringReverse(item); return IDBKeyRange.bound(item, `${item}\uffff`, false, false); };
|
||||||
@ -387,7 +387,7 @@ class DictionaryDatabase {
|
|||||||
_createTerm(row, index) {
|
_createTerm(row, index) {
|
||||||
return {
|
return {
|
||||||
index,
|
index,
|
||||||
expression: row.expression,
|
term: row.expression,
|
||||||
reading: row.reading,
|
reading: row.reading,
|
||||||
definitionTags: this._splitField(row.definitionTags || row.tags || ''),
|
definitionTags: this._splitField(row.definitionTags || row.tags || ''),
|
||||||
termTags: this._splitField(row.termTags || ''),
|
termTags: this._splitField(row.termTags || ''),
|
||||||
@ -413,8 +413,8 @@ class DictionaryDatabase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTermMeta({expression, mode, data, dictionary}, index) {
|
_createTermMeta({expression: term, mode, data, dictionary}, index) {
|
||||||
return {expression, mode, data, dictionary, index};
|
return {term, mode, data, dictionary, index};
|
||||||
}
|
}
|
||||||
|
|
||||||
_createKanjiMeta({character, mode, data, dictionary}, index) {
|
_createKanjiMeta({character, mode, data, dictionary}, index) {
|
||||||
|
@ -315,7 +315,7 @@ const JapaneseUtil = (() => {
|
|||||||
return wanakana.toRomaji(text);
|
return wanakana.toRomaji(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
convertReading(expression, reading, readingMode) {
|
convertReading(term, reading, readingMode) {
|
||||||
switch (readingMode) {
|
switch (readingMode) {
|
||||||
case 'hiragana':
|
case 'hiragana':
|
||||||
return this.convertKatakanaToHiragana(reading);
|
return this.convertKatakanaToHiragana(reading);
|
||||||
@ -325,8 +325,8 @@ const JapaneseUtil = (() => {
|
|||||||
if (reading) {
|
if (reading) {
|
||||||
return this.convertToRomaji(reading);
|
return this.convertToRomaji(reading);
|
||||||
} else {
|
} else {
|
||||||
if (this.isStringEntirelyKana(expression)) {
|
if (this.isStringEntirelyKana(term)) {
|
||||||
return this.convertToRomaji(expression);
|
return this.convertToRomaji(term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reading;
|
return reading;
|
||||||
@ -429,16 +429,16 @@ const JapaneseUtil = (() => {
|
|||||||
|
|
||||||
// Furigana distribution
|
// Furigana distribution
|
||||||
|
|
||||||
distributeFurigana(expression, reading) {
|
distributeFurigana(term, reading) {
|
||||||
if (reading === expression) {
|
if (reading === term) {
|
||||||
// Same
|
// Same
|
||||||
return [this._createFuriganaSegment(expression, '')];
|
return [this._createFuriganaSegment(term, '')];
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups = [];
|
const groups = [];
|
||||||
let groupPre = null;
|
let groupPre = null;
|
||||||
let isKanaPre = null;
|
let isKanaPre = null;
|
||||||
for (const c of expression) {
|
for (const c of term) {
|
||||||
const codePoint = c.codePointAt(0);
|
const codePoint = c.codePointAt(0);
|
||||||
const isKana = !(this.isCodePointKanji(codePoint) || codePoint === ITERATION_MARK_CODE_POINT);
|
const isKana = !(this.isCodePointKanji(codePoint) || codePoint === ITERATION_MARK_CODE_POINT);
|
||||||
if (isKana === isKanaPre) {
|
if (isKana === isKanaPre) {
|
||||||
@ -462,18 +462,18 @@ const JapaneseUtil = (() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fallback
|
// Fallback
|
||||||
return [this._createFuriganaSegment(expression, reading)];
|
return [this._createFuriganaSegment(term, reading)];
|
||||||
}
|
}
|
||||||
|
|
||||||
distributeFuriganaInflected(expression, reading, source) {
|
distributeFuriganaInflected(term, reading, source) {
|
||||||
const expressionNormalized = this.convertKatakanaToHiragana(expression);
|
const termNormalized = this.convertKatakanaToHiragana(term);
|
||||||
const readingNormalized = this.convertKatakanaToHiragana(reading);
|
const readingNormalized = this.convertKatakanaToHiragana(reading);
|
||||||
const sourceNormalized = this.convertKatakanaToHiragana(source);
|
const sourceNormalized = this.convertKatakanaToHiragana(source);
|
||||||
|
|
||||||
let mainText = expression;
|
let mainText = term;
|
||||||
let stemLength = this._getStemLength(expressionNormalized, sourceNormalized);
|
let stemLength = this._getStemLength(termNormalized, sourceNormalized);
|
||||||
|
|
||||||
// Check if source is derived from the reading instead of the expression
|
// Check if source is derived from the reading instead of the term
|
||||||
const readingStemLength = this._getStemLength(readingNormalized, sourceNormalized);
|
const readingStemLength = this._getStemLength(readingNormalized, sourceNormalized);
|
||||||
if (readingStemLength > 0 && readingStemLength >= stemLength) {
|
if (readingStemLength > 0 && readingStemLength >= stemLength) {
|
||||||
mainText = reading;
|
mainText = reading;
|
||||||
|
@ -304,7 +304,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _search(textSource, searchTerms, searchKanji, inputInfo) {
|
async _search(textSource, searchTerms, searchKanji, inputInfo) {
|
||||||
let definitions = null;
|
let dictionaryEntries = null;
|
||||||
let sentence = null;
|
let sentence = null;
|
||||||
let type = null;
|
let type = null;
|
||||||
let error = null;
|
let error = null;
|
||||||
@ -322,13 +322,13 @@ class TextScanner extends EventDispatcher {
|
|||||||
|
|
||||||
searched = true;
|
searched = true;
|
||||||
|
|
||||||
const result = await this._findDefinitions(textSource, searchTerms, searchKanji, optionsContext);
|
const result = await this._findDictionaryEntries(textSource, searchTerms, searchKanji, optionsContext);
|
||||||
if (result !== null) {
|
if (result !== null) {
|
||||||
({definitions, sentence, type} = result);
|
({dictionaryEntries, sentence, type} = result);
|
||||||
this._inputInfoCurrent = inputInfo;
|
this._inputInfoCurrent = inputInfo;
|
||||||
this.setCurrentTextSource(textSource);
|
this.setCurrentTextSource(textSource);
|
||||||
} else if (textSource instanceof TextSourceElement && await this._hasJapanese(textSource.fullContent)) {
|
} else if (textSource instanceof TextSourceElement && await this._hasJapanese(textSource.fullContent)) {
|
||||||
definitions = [];
|
dictionaryEntries = [];
|
||||||
sentence = {sentence: '', offset: 0};
|
sentence = {sentence: '', offset: 0};
|
||||||
type = 'terms';
|
type = 'terms';
|
||||||
this._inputInfoCurrent = inputInfo;
|
this._inputInfoCurrent = inputInfo;
|
||||||
@ -343,7 +343,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
const results = {
|
const results = {
|
||||||
textScanner: this,
|
textScanner: this,
|
||||||
type,
|
type,
|
||||||
definitions,
|
dictionaryEntries,
|
||||||
sentence,
|
sentence,
|
||||||
inputInfo,
|
inputInfo,
|
||||||
textSource,
|
textSource,
|
||||||
@ -804,22 +804,22 @@ class TextScanner extends EventDispatcher {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _findDefinitions(textSource, searchTerms, searchKanji, optionsContext) {
|
async _findDictionaryEntries(textSource, searchTerms, searchKanji, optionsContext) {
|
||||||
if (textSource === null) {
|
if (textSource === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (searchTerms) {
|
if (searchTerms) {
|
||||||
const results = await this._findTerms(textSource, optionsContext);
|
const results = await this._findTermDictionaryEntries(textSource, optionsContext);
|
||||||
if (results !== null) { return results; }
|
if (results !== null) { return results; }
|
||||||
}
|
}
|
||||||
if (searchKanji) {
|
if (searchKanji) {
|
||||||
const results = await this._findKanji(textSource, optionsContext);
|
const results = await this._findKanjiDictionaryEntries(textSource, optionsContext);
|
||||||
if (results !== null) { return results; }
|
if (results !== null) { return results; }
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _findTerms(textSource, optionsContext) {
|
async _findTermDictionaryEntries(textSource, optionsContext) {
|
||||||
const scanLength = this._scanLength;
|
const scanLength = this._scanLength;
|
||||||
const sentenceScanExtent = this._sentenceScanExtent;
|
const sentenceScanExtent = this._sentenceScanExtent;
|
||||||
const sentenceTerminatorMap = this._sentenceTerminatorMap;
|
const sentenceTerminatorMap = this._sentenceTerminatorMap;
|
||||||
@ -829,10 +829,10 @@ class TextScanner extends EventDispatcher {
|
|||||||
const searchText = this.getTextSourceContent(textSource, scanLength, layoutAwareScan);
|
const searchText = this.getTextSourceContent(textSource, scanLength, layoutAwareScan);
|
||||||
if (searchText.length === 0) { return null; }
|
if (searchText.length === 0) { return null; }
|
||||||
|
|
||||||
const {definitions, length} = await yomichan.api.termsFind(searchText, {}, optionsContext);
|
const {dictionaryEntries, originalTextLength} = await yomichan.api.termsFind(searchText, {}, optionsContext);
|
||||||
if (definitions.length === 0) { return null; }
|
if (dictionaryEntries.length === 0) { return null; }
|
||||||
|
|
||||||
textSource.setEndOffset(length, layoutAwareScan);
|
textSource.setEndOffset(originalTextLength, layoutAwareScan);
|
||||||
const sentence = this._documentUtil.extractSentence(
|
const sentence = this._documentUtil.extractSentence(
|
||||||
textSource,
|
textSource,
|
||||||
layoutAwareScan,
|
layoutAwareScan,
|
||||||
@ -842,10 +842,10 @@ class TextScanner extends EventDispatcher {
|
|||||||
sentenceBackwardQuoteMap
|
sentenceBackwardQuoteMap
|
||||||
);
|
);
|
||||||
|
|
||||||
return {definitions, sentence, type: 'terms'};
|
return {dictionaryEntries, sentence, type: 'terms'};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _findKanji(textSource, optionsContext) {
|
async _findKanjiDictionaryEntries(textSource, optionsContext) {
|
||||||
const sentenceScanExtent = this._sentenceScanExtent;
|
const sentenceScanExtent = this._sentenceScanExtent;
|
||||||
const sentenceTerminatorMap = this._sentenceTerminatorMap;
|
const sentenceTerminatorMap = this._sentenceTerminatorMap;
|
||||||
const sentenceForwardQuoteMap = this._sentenceForwardQuoteMap;
|
const sentenceForwardQuoteMap = this._sentenceForwardQuoteMap;
|
||||||
@ -854,8 +854,8 @@ class TextScanner extends EventDispatcher {
|
|||||||
const searchText = this.getTextSourceContent(textSource, 1, layoutAwareScan);
|
const searchText = this.getTextSourceContent(textSource, 1, layoutAwareScan);
|
||||||
if (searchText.length === 0) { return null; }
|
if (searchText.length === 0) { return null; }
|
||||||
|
|
||||||
const definitions = await yomichan.api.kanjiFind(searchText, optionsContext);
|
const dictionaryEntries = await yomichan.api.kanjiFind(searchText, optionsContext);
|
||||||
if (definitions.length === 0) { return null; }
|
if (dictionaryEntries.length === 0) { return null; }
|
||||||
|
|
||||||
textSource.setEndOffset(1, layoutAwareScan);
|
textSource.setEndOffset(1, layoutAwareScan);
|
||||||
const sentence = this._documentUtil.extractSentence(
|
const sentence = this._documentUtil.extractSentence(
|
||||||
@ -867,7 +867,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
sentenceBackwardQuoteMap
|
sentenceBackwardQuoteMap
|
||||||
);
|
);
|
||||||
|
|
||||||
return {definitions, sentence, type: 'kanji'};
|
return {dictionaryEntries, sentence, type: 'kanji'};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _searchAt(x, y, inputInfo) {
|
async _searchAt(x, y, inputInfo) {
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
class Translator {
|
class Translator {
|
||||||
/**
|
/**
|
||||||
* Creates a new Translator instance.
|
* Creates a new Translator instance.
|
||||||
|
* @param japaneseUtil An instance of JapaneseUtil.
|
||||||
* @param database An instance of DictionaryDatabase.
|
* @param database An instance of DictionaryDatabase.
|
||||||
*/
|
*/
|
||||||
constructor({japaneseUtil, database}) {
|
constructor({japaneseUtil, database}) {
|
||||||
@ -396,8 +397,8 @@ class Translator {
|
|||||||
const {id} = databaseEntry;
|
const {id} = databaseEntry;
|
||||||
if (ids.has(id)) { continue; }
|
if (ids.has(id)) { continue; }
|
||||||
|
|
||||||
const sourceText = databaseEntry.expression;
|
const {term} = databaseEntry;
|
||||||
const dictionaryEntry = this._createTermDictionaryEntryFromDatabaseEntry(databaseEntry, sourceText, sourceText, sourceText, [], false, enabledDictionaryMap);
|
const dictionaryEntry = this._createTermDictionaryEntryFromDatabaseEntry(databaseEntry, term, term, term, [], false, enabledDictionaryMap);
|
||||||
dictionaryEntries.push(dictionaryEntry);
|
dictionaryEntries.push(dictionaryEntry);
|
||||||
ids.add(id);
|
ids.add(id);
|
||||||
ungroupedDictionaryEntriesMap.delete(id);
|
ungroupedDictionaryEntriesMap.delete(id);
|
||||||
@ -426,13 +427,13 @@ class Translator {
|
|||||||
target.groups.push(group);
|
target.groups.push(group);
|
||||||
if (!dictionaryEntry.isPrimary && !target.searchSecondary) {
|
if (!dictionaryEntry.isPrimary && !target.searchSecondary) {
|
||||||
target.searchSecondary = true;
|
target.searchSecondary = true;
|
||||||
termList.push({expression: term, reading});
|
termList.push({term, reading});
|
||||||
targetList.push(target);
|
targetList.push(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group unsequenced dictionary entries with sequenced entries that have a matching [expression, reading].
|
// Group unsequenced dictionary entries with sequenced entries that have a matching [term, reading].
|
||||||
for (const [id, dictionaryEntry] of ungroupedDictionaryEntriesMap.entries()) {
|
for (const [id, dictionaryEntry] of ungroupedDictionaryEntriesMap.entries()) {
|
||||||
const {term, reading} = dictionaryEntry.headwords[0];
|
const {term, reading} = dictionaryEntry.headwords[0];
|
||||||
const key = this._createMapKey([term, reading]);
|
const key = this._createMapKey([term, reading]);
|
||||||
@ -457,7 +458,7 @@ class Translator {
|
|||||||
|
|
||||||
for (const databaseEntry of databaseEntries) {
|
for (const databaseEntry of databaseEntries) {
|
||||||
const {index, id} = databaseEntry;
|
const {index, id} = databaseEntry;
|
||||||
const sourceText = termList[index].expression;
|
const sourceText = termList[index].term;
|
||||||
const target = targetList[index];
|
const target = targetList[index];
|
||||||
for (const {ids, dictionaryEntries} of target.groups) {
|
for (const {ids, dictionaryEntries} of target.groups) {
|
||||||
if (ids.has(id)) { continue; }
|
if (ids.has(id)) { continue; }
|
||||||
@ -959,10 +960,10 @@ class Translator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createTermDictionaryEntryFromDatabaseEntry(databaseEntry, originalText, transformedText, deinflectedText, reasons, isPrimary, enabledDictionaryMap) {
|
_createTermDictionaryEntryFromDatabaseEntry(databaseEntry, originalText, transformedText, deinflectedText, reasons, isPrimary, enabledDictionaryMap) {
|
||||||
const {expression, reading: rawReading, definitionTags, termTags, glossary, score, dictionary, id, sequence, rules} = databaseEntry;
|
const {term, reading: rawReading, definitionTags, termTags, glossary, score, dictionary, id, sequence, rules} = databaseEntry;
|
||||||
const reading = (rawReading.length > 0 ? rawReading : expression);
|
const reading = (rawReading.length > 0 ? rawReading : term);
|
||||||
const {index: dictionaryIndex, priority: dictionaryPriority} = this._getDictionaryOrder(dictionary, enabledDictionaryMap);
|
const {index: dictionaryIndex, priority: dictionaryPriority} = this._getDictionaryOrder(dictionary, enabledDictionaryMap);
|
||||||
const sourceTermExactMatchCount = (isPrimary && deinflectedText === expression ? 1 : 0);
|
const sourceTermExactMatchCount = (isPrimary && deinflectedText === term ? 1 : 0);
|
||||||
const source = this._createSource(originalText, transformedText, deinflectedText, isPrimary);
|
const source = this._createSource(originalText, transformedText, deinflectedText, isPrimary);
|
||||||
const maxTransformedTextLength = transformedText.length;
|
const maxTransformedTextLength = transformedText.length;
|
||||||
|
|
||||||
@ -982,7 +983,7 @@ class Translator {
|
|||||||
dictionaryPriority,
|
dictionaryPriority,
|
||||||
sourceTermExactMatchCount,
|
sourceTermExactMatchCount,
|
||||||
maxTransformedTextLength,
|
maxTransformedTextLength,
|
||||||
[this._createTermHeadword(0, expression, reading, [source], headwordTagGroups, rules)],
|
[this._createTermHeadword(0, term, reading, [source], headwordTagGroups, rules)],
|
||||||
[this._createTermDefinition(0, [0], dictionary, definitionTagGroups, glossary)]
|
[this._createTermDefinition(0, [0], dictionary, definitionTagGroups, glossary)]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1204,7 +1205,7 @@ class Translator {
|
|||||||
i = v2.score - v1.score;
|
i = v2.score - v1.score;
|
||||||
if (i !== 0) { return i; }
|
if (i !== 0) { return i; }
|
||||||
|
|
||||||
// Sort by expression text
|
// Sort by headword term text
|
||||||
const headwords1 = v1.headwords;
|
const headwords1 = v1.headwords;
|
||||||
const headwords2 = v2.headwords;
|
const headwords2 = v2.headwords;
|
||||||
for (let j = 0, jj = Math.min(headwords1.length, headwords2.length); j < jj; ++j) {
|
for (let j = 0, jj = Math.min(headwords1.length, headwords2.length); j < jj; ++j) {
|
||||||
@ -1277,7 +1278,7 @@ class Translator {
|
|||||||
let i = v2.dictionaryPriority - v1.dictionaryPriority;
|
let i = v2.dictionaryPriority - v1.dictionaryPriority;
|
||||||
if (i !== 0) { return i; }
|
if (i !== 0) { return i; }
|
||||||
|
|
||||||
// Sory by expression order
|
// Sory by headword order
|
||||||
i = v1.headwordIndex - v2.headwordIndex;
|
i = v1.headwordIndex - v2.headwordIndex;
|
||||||
if (i !== 0) { return i; }
|
if (i !== 0) { return i; }
|
||||||
|
|
||||||
|
@ -37,11 +37,11 @@ class AudioDownloader {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getExpressionAudioInfoList(source, expression, reading, details) {
|
async getTermAudioInfoList(source, term, reading, details) {
|
||||||
const handler = this._getInfoHandlers.get(source);
|
const handler = this._getInfoHandlers.get(source);
|
||||||
if (typeof handler === 'function') {
|
if (typeof handler === 'function') {
|
||||||
try {
|
try {
|
||||||
return await handler(expression, reading, details);
|
return await handler(term, reading, details);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// NOP
|
// NOP
|
||||||
}
|
}
|
||||||
@ -49,9 +49,9 @@ class AudioDownloader {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadExpressionAudio(sources, preferredAudioIndex, expression, reading, details) {
|
async downloadTermAudio(sources, preferredAudioIndex, term, reading, details) {
|
||||||
for (const source of sources) {
|
for (const source of sources) {
|
||||||
let infoList = await this.getExpressionAudioInfoList(source, expression, reading, details);
|
let infoList = await this.getTermAudioInfoList(source, term, reading, details);
|
||||||
if (typeof preferredAudioIndex === 'number') {
|
if (typeof preferredAudioIndex === 'number') {
|
||||||
infoList = (preferredAudioIndex >= 0 && preferredAudioIndex < infoList.length ? [infoList[preferredAudioIndex]] : []);
|
infoList = (preferredAudioIndex >= 0 && preferredAudioIndex < infoList.length ? [infoList[preferredAudioIndex]] : []);
|
||||||
}
|
}
|
||||||
@ -77,15 +77,15 @@ class AudioDownloader {
|
|||||||
return new URL(url, base).href;
|
return new URL(url, base).href;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getInfoJpod101(expression, reading) {
|
async _getInfoJpod101(term, reading) {
|
||||||
if (reading === expression && this._japaneseUtil.isStringEntirelyKana(expression)) {
|
if (reading === term && this._japaneseUtil.isStringEntirelyKana(term)) {
|
||||||
reading = expression;
|
reading = term;
|
||||||
expression = null;
|
term = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (expression) {
|
if (term) {
|
||||||
params.set('kanji', expression);
|
params.set('kanji', term);
|
||||||
}
|
}
|
||||||
if (reading) {
|
if (reading) {
|
||||||
params.set('kana', reading);
|
params.set('kana', reading);
|
||||||
@ -95,12 +95,12 @@ class AudioDownloader {
|
|||||||
return [{type: 'url', url}];
|
return [{type: 'url', url}];
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getInfoJpod101Alternate(expression, reading) {
|
async _getInfoJpod101Alternate(term, reading) {
|
||||||
const fetchUrl = 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post';
|
const fetchUrl = 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post';
|
||||||
const data = new URLSearchParams({
|
const data = new URLSearchParams({
|
||||||
post: 'dictionary_reference',
|
post: 'dictionary_reference',
|
||||||
match_type: 'exact',
|
match_type: 'exact',
|
||||||
search_query: expression,
|
search_query: term,
|
||||||
vulgar: 'true'
|
vulgar: 'true'
|
||||||
});
|
});
|
||||||
const response = await this._requestBuilder.fetchAnonymous(fetchUrl, {
|
const response = await this._requestBuilder.fetchAnonymous(fetchUrl, {
|
||||||
@ -133,7 +133,7 @@ class AudioDownloader {
|
|||||||
if (htmlReadings.length === 0) { continue; }
|
if (htmlReadings.length === 0) { continue; }
|
||||||
|
|
||||||
const htmlReading = dom.getTextContent(htmlReadings[0]);
|
const htmlReading = dom.getTextContent(htmlReadings[0]);
|
||||||
if (htmlReading && (reading === expression || reading === htmlReading)) {
|
if (htmlReading && (reading === term || reading === htmlReading)) {
|
||||||
url = this._normalizeUrl(url, response.url);
|
url = this._normalizeUrl(url, response.url);
|
||||||
return [{type: 'url', url}];
|
return [{type: 'url', url}];
|
||||||
}
|
}
|
||||||
@ -145,8 +145,8 @@ class AudioDownloader {
|
|||||||
throw new Error('Failed to find audio URL');
|
throw new Error('Failed to find audio URL');
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getInfoJisho(expression, reading) {
|
async _getInfoJisho(term, reading) {
|
||||||
const fetchUrl = `https://jisho.org/search/${expression}`;
|
const fetchUrl = `https://jisho.org/search/${term}`;
|
||||||
const response = await this._requestBuilder.fetchAnonymous(fetchUrl, {
|
const response = await this._requestBuilder.fetchAnonymous(fetchUrl, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
mode: 'cors',
|
mode: 'cors',
|
||||||
@ -159,7 +159,7 @@ class AudioDownloader {
|
|||||||
|
|
||||||
const dom = this._createSimpleDOMParser(responseText);
|
const dom = this._createSimpleDOMParser(responseText);
|
||||||
try {
|
try {
|
||||||
const audio = dom.getElementById(`audio_${expression}:${reading}`);
|
const audio = dom.getElementById(`audio_${term}:${reading}`);
|
||||||
if (audio !== null) {
|
if (audio !== null) {
|
||||||
const source = dom.getElementByTagName('source', audio);
|
const source = dom.getElementByTagName('source', audio);
|
||||||
if (source !== null) {
|
if (source !== null) {
|
||||||
@ -177,25 +177,25 @@ class AudioDownloader {
|
|||||||
throw new Error('Failed to find audio URL');
|
throw new Error('Failed to find audio URL');
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getInfoTextToSpeech(expression, reading, {textToSpeechVoice}) {
|
async _getInfoTextToSpeech(term, reading, {textToSpeechVoice}) {
|
||||||
if (!textToSpeechVoice) {
|
if (!textToSpeechVoice) {
|
||||||
throw new Error('No voice');
|
throw new Error('No voice');
|
||||||
}
|
}
|
||||||
return [{type: 'tts', text: expression, voice: textToSpeechVoice}];
|
return [{type: 'tts', text: term, voice: textToSpeechVoice}];
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getInfoTextToSpeechReading(expression, reading, {textToSpeechVoice}) {
|
async _getInfoTextToSpeechReading(term, reading, {textToSpeechVoice}) {
|
||||||
if (!textToSpeechVoice) {
|
if (!textToSpeechVoice) {
|
||||||
throw new Error('No voice');
|
throw new Error('No voice');
|
||||||
}
|
}
|
||||||
return [{type: 'tts', text: reading || expression, voice: textToSpeechVoice}];
|
return [{type: 'tts', text: reading, voice: textToSpeechVoice}];
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getInfoCustom(expression, reading, {customSourceUrl, customSourceType}) {
|
async _getInfoCustom(term, reading, {customSourceUrl, customSourceType}) {
|
||||||
if (typeof customSourceUrl !== 'string') {
|
if (typeof customSourceUrl !== 'string') {
|
||||||
throw new Error('No custom URL defined');
|
throw new Error('No custom URL defined');
|
||||||
}
|
}
|
||||||
const data = {expression, reading};
|
const data = {term, reading};
|
||||||
const url = customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (Object.prototype.hasOwnProperty.call(data, m1) ? `${data[m1]}` : m0));
|
const url = customSourceUrl.replace(/\{([^}]*)\}/g, (m0, m1) => (Object.prototype.hasOwnProperty.call(data, m1) ? `${data[m1]}` : m0));
|
||||||
|
|
||||||
switch (customSourceType) {
|
switch (customSourceType) {
|
||||||
|
@ -24,8 +24,8 @@ class AnkiTemplatesController {
|
|||||||
this._settingsController = settingsController;
|
this._settingsController = settingsController;
|
||||||
this._modalController = modalController;
|
this._modalController = modalController;
|
||||||
this._ankiController = ankiController;
|
this._ankiController = ankiController;
|
||||||
this._cachedDefinitionValue = null;
|
this._cachedDictionaryEntryValue = null;
|
||||||
this._cachedDefinitionText = null;
|
this._cachedDictionaryEntryText = null;
|
||||||
this._defaultFieldTemplates = null;
|
this._defaultFieldTemplates = null;
|
||||||
this._fieldTemplatesTextarea = null;
|
this._fieldTemplatesTextarea = null;
|
||||||
this._compileResultInfo = null;
|
this._compileResultInfo = null;
|
||||||
@ -114,7 +114,7 @@ class AnkiTemplatesController {
|
|||||||
const field = this._renderFieldInput.value;
|
const field = this._renderFieldInput.value;
|
||||||
const infoNode = this._renderResult;
|
const infoNode = this._renderResult;
|
||||||
infoNode.hidden = true;
|
infoNode.hidden = true;
|
||||||
this._cachedDefinitionText = null;
|
this._cachedDictionaryEntryText = null;
|
||||||
this._validate(infoNode, field, 'term-kanji', true, false);
|
this._validate(infoNode, field, 'term-kanji', true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,15 +132,18 @@ class AnkiTemplatesController {
|
|||||||
input.dispatchEvent(new Event('change'));
|
input.dispatchEvent(new Event('change'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getDefinition(text, optionsContext) {
|
async _getDictionaryEntry(text, optionsContext) {
|
||||||
if (this._cachedDefinitionText !== text) {
|
if (this._cachedDictionaryEntryText !== text) {
|
||||||
const {definitions} = await yomichan.api.termsFind(text, {}, optionsContext);
|
const {dictionaryEntries} = await yomichan.api.termsFind(text, {}, optionsContext);
|
||||||
if (definitions.length === 0) { return null; }
|
if (dictionaryEntries.length === 0) { return null; }
|
||||||
|
|
||||||
this._cachedDefinitionValue = definitions[0];
|
this._cachedDictionaryEntryValue = dictionaryEntries[0];
|
||||||
this._cachedDefinitionText = text;
|
this._cachedDictionaryEntryText = text;
|
||||||
}
|
}
|
||||||
return this._cachedDefinitionValue;
|
return {
|
||||||
|
dictionaryEntry: this._cachedDictionaryEntryValue,
|
||||||
|
text: this._cachedDictionaryEntryText
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _validate(infoNode, field, mode, showSuccessResult, invalidateInput) {
|
async _validate(infoNode, field, mode, showSuccessResult, invalidateInput) {
|
||||||
@ -149,19 +152,22 @@ class AnkiTemplatesController {
|
|||||||
let result = `No definition found for ${text}`;
|
let result = `No definition found for ${text}`;
|
||||||
try {
|
try {
|
||||||
const optionsContext = this._settingsController.getOptionsContext();
|
const optionsContext = this._settingsController.getOptionsContext();
|
||||||
const definition = await this._getDefinition(text, optionsContext);
|
const {dictionaryEntry, text: sentenceText} = await this._getDictionaryEntry(text, optionsContext);
|
||||||
if (definition !== null) {
|
if (dictionaryEntry !== null) {
|
||||||
const options = await this._settingsController.getOptions();
|
const options = await this._settingsController.getOptions();
|
||||||
const context = {
|
const context = {
|
||||||
url: window.location.href,
|
url: window.location.href,
|
||||||
sentence: {text: definition.rawSource, offset: 0},
|
sentence: {
|
||||||
|
text: sentenceText,
|
||||||
|
offset: 0
|
||||||
|
},
|
||||||
documentTitle: document.title
|
documentTitle: document.title
|
||||||
};
|
};
|
||||||
let template = options.anki.fieldTemplates;
|
let template = options.anki.fieldTemplates;
|
||||||
if (typeof template !== 'string') { template = this._defaultFieldTemplates; }
|
if (typeof template !== 'string') { template = this._defaultFieldTemplates; }
|
||||||
const {general: {resultOutputMode, glossaryLayoutMode, compactTags}} = options;
|
const {general: {resultOutputMode, glossaryLayoutMode, compactTags}} = options;
|
||||||
const note = await this._ankiNoteBuilder.createNote({
|
const note = await this._ankiNoteBuilder.createNote({
|
||||||
definition,
|
dictionaryEntry,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
template,
|
template,
|
||||||
|
@ -2315,8 +2315,8 @@
|
|||||||
<div class="settings-item-children more" hidden>
|
<div class="settings-item-children more" hidden>
|
||||||
<p>
|
<p>
|
||||||
The <em>URL</em> property specifies the URL format used for fetching audio clips in <em>Custom</em> mode.
|
The <em>URL</em> property specifies the URL format used for fetching audio clips in <em>Custom</em> mode.
|
||||||
The replacement tags <code data-select-on-click="">{expression}</code> and <code data-select-on-click="">{reading}</code> can be used to specify which
|
The replacement tags <code data-select-on-click="">{term}</code> and <code data-select-on-click="">{reading}</code> can be used to specify which
|
||||||
expression and reading is being looked up.<br>
|
term and reading is being looked up.<br>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The <em>Type</em> property specifies how the URL is handled when looking up audio:
|
The <em>Type</em> property specifies how the URL is handled when looking up audio:
|
||||||
@ -2331,7 +2331,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Example URL: <a data-select-on-click="">http://localhost/audio.mp3?expression={expression}&reading={reading}</a>
|
Example URL: <a data-select-on-click="">http://localhost/audio.mp3?term={term}&reading={reading}</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a class="more-toggle" data-parent-distance="3">Less…</a>
|
<a class="more-toggle" data-parent-distance="3">Less…</a>
|
||||||
|
@ -171,7 +171,7 @@ async function getRenderResults(dictionaryEntries, type, mode, template, AnkiNot
|
|||||||
};
|
};
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const noteFields = (await ankiNoteBuilder.createNote({
|
const noteFields = (await ankiNoteBuilder.createNote({
|
||||||
definition: dictionaryEntry,
|
dictionaryEntry,
|
||||||
mode: null,
|
mode: null,
|
||||||
context,
|
context,
|
||||||
template,
|
template,
|
||||||
|
@ -41,12 +41,12 @@ function createTestDictionaryArchive(dictionary, dictionaryName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function countTermsWithExpression(terms, expression) {
|
function countDictionaryDatabaseEntriesWithTerm(dictionaryDatabaseEntries, term) {
|
||||||
return terms.reduce((i, v) => (i + (v.expression === expression ? 1 : 0)), 0);
|
return dictionaryDatabaseEntries.reduce((i, v) => (i + (v.term === term ? 1 : 0)), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function countTermsWithReading(terms, reading) {
|
function countDictionaryDatabaseEntriesWithReading(dictionaryDatabaseEntries, reading) {
|
||||||
return terms.reduce((i, v) => (i + (v.reading === reading ? 1 : 0)), 0);
|
return dictionaryDatabaseEntries.reduce((i, v) => (i + (v.reading === reading ? 1 : 0)), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function countMetasWithMode(metas, mode) {
|
function countMetasWithMode(metas, mode) {
|
||||||
@ -212,7 +212,7 @@ async function testFindTermsBulkTest1(database, titles) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 32,
|
total: 32,
|
||||||
expressions: [
|
terms: [
|
||||||
['打', 2],
|
['打', 2],
|
||||||
['打つ', 17],
|
['打つ', 17],
|
||||||
['打ち込む', 13]
|
['打ち込む', 13]
|
||||||
@ -236,7 +236,7 @@ async function testFindTermsBulkTest1(database, titles) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 0,
|
total: 0,
|
||||||
expressions: [],
|
terms: [],
|
||||||
readings: []
|
readings: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -249,7 +249,7 @@ async function testFindTermsBulkTest1(database, titles) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 13,
|
total: 13,
|
||||||
expressions: [
|
terms: [
|
||||||
['打ち込む', 13]
|
['打ち込む', 13]
|
||||||
],
|
],
|
||||||
readings: [
|
readings: [
|
||||||
@ -267,7 +267,7 @@ async function testFindTermsBulkTest1(database, titles) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 0,
|
total: 0,
|
||||||
expressions: [],
|
terms: [],
|
||||||
readings: []
|
readings: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,11 +277,11 @@ async function testFindTermsBulkTest1(database, titles) {
|
|||||||
for (const {termList, wildcard} of inputs) {
|
for (const {termList, wildcard} of inputs) {
|
||||||
const results = await database.findTermsBulk(termList, titles, wildcard);
|
const results = await database.findTermsBulk(termList, titles, wildcard);
|
||||||
assert.strictEqual(results.length, expectedResults.total);
|
assert.strictEqual(results.length, expectedResults.total);
|
||||||
for (const [expression, count] of expectedResults.expressions) {
|
for (const [term, count] of expectedResults.terms) {
|
||||||
assert.strictEqual(countTermsWithExpression(results, expression), count);
|
assert.strictEqual(countDictionaryDatabaseEntriesWithTerm(results, term), count);
|
||||||
}
|
}
|
||||||
for (const [reading, count] of expectedResults.readings) {
|
for (const [reading, count] of expectedResults.readings) {
|
||||||
assert.strictEqual(countTermsWithReading(results, reading), count);
|
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,15 +293,15 @@ async function testTindTermsExactBulk1(database, titles) {
|
|||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
termList: [
|
termList: [
|
||||||
{expression: '打', reading: 'だ'},
|
{term: '打', reading: 'だ'},
|
||||||
{expression: '打つ', reading: 'うつ'},
|
{term: '打つ', reading: 'うつ'},
|
||||||
{expression: '打ち込む', reading: 'うちこむ'}
|
{term: '打ち込む', reading: 'うちこむ'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 25,
|
total: 25,
|
||||||
expressions: [
|
terms: [
|
||||||
['打', 1],
|
['打', 1],
|
||||||
['打つ', 15],
|
['打つ', 15],
|
||||||
['打ち込む', 9]
|
['打ち込む', 9]
|
||||||
@ -317,15 +317,15 @@ async function testTindTermsExactBulk1(database, titles) {
|
|||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
termList: [
|
termList: [
|
||||||
{expression: '打', reading: 'だ?'},
|
{term: '打', reading: 'だ?'},
|
||||||
{expression: '打つ', reading: 'うつ?'},
|
{term: '打つ', reading: 'うつ?'},
|
||||||
{expression: '打ち込む', reading: 'うちこむ?'}
|
{term: '打ち込む', reading: 'うちこむ?'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 0,
|
total: 0,
|
||||||
expressions: [],
|
terms: [],
|
||||||
readings: []
|
readings: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -333,14 +333,14 @@ async function testTindTermsExactBulk1(database, titles) {
|
|||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
termList: [
|
termList: [
|
||||||
{expression: '打つ', reading: 'うつ'},
|
{term: '打つ', reading: 'うつ'},
|
||||||
{expression: '打つ', reading: 'ぶつ'}
|
{term: '打つ', reading: 'ぶつ'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 17,
|
total: 17,
|
||||||
expressions: [
|
terms: [
|
||||||
['打つ', 17]
|
['打つ', 17]
|
||||||
],
|
],
|
||||||
readings: [
|
readings: [
|
||||||
@ -353,13 +353,13 @@ async function testTindTermsExactBulk1(database, titles) {
|
|||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
termList: [
|
termList: [
|
||||||
{expression: '打つ', reading: 'うちこむ'}
|
{term: '打つ', reading: 'うちこむ'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 0,
|
total: 0,
|
||||||
expressions: [],
|
terms: [],
|
||||||
readings: []
|
readings: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -371,7 +371,7 @@ async function testTindTermsExactBulk1(database, titles) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 0,
|
total: 0,
|
||||||
expressions: [],
|
terms: [],
|
||||||
readings: []
|
readings: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -381,11 +381,11 @@ async function testTindTermsExactBulk1(database, titles) {
|
|||||||
for (const {termList} of inputs) {
|
for (const {termList} of inputs) {
|
||||||
const results = await database.findTermsExactBulk(termList, titles);
|
const results = await database.findTermsExactBulk(termList, titles);
|
||||||
assert.strictEqual(results.length, expectedResults.total);
|
assert.strictEqual(results.length, expectedResults.total);
|
||||||
for (const [expression, count] of expectedResults.expressions) {
|
for (const [term, count] of expectedResults.terms) {
|
||||||
assert.strictEqual(countTermsWithExpression(results, expression), count);
|
assert.strictEqual(countDictionaryDatabaseEntriesWithTerm(results, term), count);
|
||||||
}
|
}
|
||||||
for (const [reading, count] of expectedResults.readings) {
|
for (const [reading, count] of expectedResults.readings) {
|
||||||
assert.strictEqual(countTermsWithReading(results, reading), count);
|
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,7 +401,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 33,
|
total: 33,
|
||||||
expressions: [
|
terms: [
|
||||||
['打', 2],
|
['打', 2],
|
||||||
['打つ', 17],
|
['打つ', 17],
|
||||||
['打ち込む', 13],
|
['打ち込む', 13],
|
||||||
@ -426,7 +426,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 1,
|
total: 1,
|
||||||
expressions: [
|
terms: [
|
||||||
['打', 1]
|
['打', 1]
|
||||||
],
|
],
|
||||||
readings: [
|
readings: [
|
||||||
@ -442,7 +442,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 1,
|
total: 1,
|
||||||
expressions: [
|
terms: [
|
||||||
['打', 1]
|
['打', 1]
|
||||||
],
|
],
|
||||||
readings: [
|
readings: [
|
||||||
@ -458,7 +458,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 17,
|
total: 17,
|
||||||
expressions: [
|
terms: [
|
||||||
['打つ', 17]
|
['打つ', 17]
|
||||||
],
|
],
|
||||||
readings: [
|
readings: [
|
||||||
@ -475,7 +475,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 13,
|
total: 13,
|
||||||
expressions: [
|
terms: [
|
||||||
['打ち込む', 13]
|
['打ち込む', 13]
|
||||||
],
|
],
|
||||||
readings: [
|
readings: [
|
||||||
@ -492,7 +492,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 1,
|
total: 1,
|
||||||
expressions: [
|
terms: [
|
||||||
['画像', 1]
|
['画像', 1]
|
||||||
],
|
],
|
||||||
readings: [
|
readings: [
|
||||||
@ -508,7 +508,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 0,
|
total: 0,
|
||||||
expressions: [],
|
terms: [],
|
||||||
readings: []
|
readings: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -520,7 +520,7 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
],
|
],
|
||||||
expectedResults: {
|
expectedResults: {
|
||||||
total: 0,
|
total: 0,
|
||||||
expressions: [],
|
terms: [],
|
||||||
readings: []
|
readings: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -530,11 +530,11 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|||||||
for (const {sequenceList} of inputs) {
|
for (const {sequenceList} of inputs) {
|
||||||
const results = await database.findTermsBySequenceBulk(sequenceList.map((query) => ({query, dictionary: mainDictionary})));
|
const results = await database.findTermsBySequenceBulk(sequenceList.map((query) => ({query, dictionary: mainDictionary})));
|
||||||
assert.strictEqual(results.length, expectedResults.total);
|
assert.strictEqual(results.length, expectedResults.total);
|
||||||
for (const [expression, count] of expectedResults.expressions) {
|
for (const [term, count] of expectedResults.terms) {
|
||||||
assert.strictEqual(countTermsWithExpression(results, expression), count);
|
assert.strictEqual(countDictionaryDatabaseEntriesWithTerm(results, term), count);
|
||||||
}
|
}
|
||||||
for (const [reading, count] of expectedResults.readings) {
|
for (const [reading, count] of expectedResults.readings) {
|
||||||
assert.strictEqual(countTermsWithReading(results, reading), count);
|
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -781,7 +781,7 @@ async function testDatabase2() {
|
|||||||
// Error: not prepared
|
// Error: not prepared
|
||||||
await assert.rejects(async () => await dictionaryDatabase.deleteDictionary(title, {rate: 1000}, () => {}));
|
await assert.rejects(async () => await dictionaryDatabase.deleteDictionary(title, {rate: 1000}, () => {}));
|
||||||
await assert.rejects(async () => await dictionaryDatabase.findTermsBulk(['?'], titles, null));
|
await assert.rejects(async () => await dictionaryDatabase.findTermsBulk(['?'], titles, null));
|
||||||
await assert.rejects(async () => await dictionaryDatabase.findTermsExactBulk([{expression: '?', reading: '?'}], titles));
|
await assert.rejects(async () => await dictionaryDatabase.findTermsExactBulk([{term: '?', reading: '?'}], titles));
|
||||||
await assert.rejects(async () => await dictionaryDatabase.findTermsBySequenceBulk([{query: 1, dictionary: title}]));
|
await assert.rejects(async () => await dictionaryDatabase.findTermsBySequenceBulk([{query: 1, dictionary: title}]));
|
||||||
await assert.rejects(async () => await dictionaryDatabase.findTermMetaBulk(['?'], titles));
|
await assert.rejects(async () => await dictionaryDatabase.findTermMetaBulk(['?'], titles));
|
||||||
await assert.rejects(async () => await dictionaryDatabase.findTermMetaBulk(['?'], titles));
|
await assert.rejects(async () => await dictionaryDatabase.findTermMetaBulk(['?'], titles));
|
||||||
|
@ -199,7 +199,7 @@ function testConvertReading() {
|
|||||||
[['ありがとう', '', 'none'], ''],
|
[['ありがとう', '', 'none'], ''],
|
||||||
[['ありがとう', '', 'default'], ''],
|
[['ありがとう', '', 'default'], ''],
|
||||||
|
|
||||||
// Cases with falsy readings and kanji expressions
|
// Cases with falsy readings and kanji terms
|
||||||
|
|
||||||
[['有り難う', '', 'hiragana'], ''],
|
[['有り難う', '', 'hiragana'], ''],
|
||||||
[['有り難う', '', 'katakana'], ''],
|
[['有り難う', '', 'katakana'], ''],
|
||||||
@ -208,8 +208,8 @@ function testConvertReading() {
|
|||||||
[['有り難う', '', 'default'], '']
|
[['有り難う', '', 'default'], '']
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const [[expression, reading, readingMode], expected] of data) {
|
for (const [[term, reading, readingMode], expected] of data) {
|
||||||
assert.strictEqual(jp.convertReading(expression, reading, readingMode), expected);
|
assert.strictEqual(jp.convertReading(term, reading, readingMode), expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,7 +708,7 @@ function testDistributeFurigana() {
|
|||||||
{text: 'る', furigana: 'ル'}
|
{text: 'る', furigana: 'ル'}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
// Reading starts with expression, but has remainder characters
|
// Reading starts with term, but has remainder characters
|
||||||
[
|
[
|
||||||
['シック', 'シック・ビルしょうこうぐん'],
|
['シック', 'シック・ビルしょうこうぐん'],
|
||||||
[
|
[
|
||||||
@ -717,8 +717,8 @@ function testDistributeFurigana() {
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const [[expression, reading], expected] of data) {
|
for (const [[term, reading], expected] of data) {
|
||||||
const actual = jp.distributeFurigana(expression, reading);
|
const actual = jp.distributeFurigana(term, reading);
|
||||||
vm.assert.deepStrictEqual(actual, expected);
|
vm.assert.deepStrictEqual(actual, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -766,8 +766,8 @@ function testDistributeFuriganaInflected() {
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const [[expression, reading, source], expected] of data) {
|
for (const [[term, reading, source], expected] of data) {
|
||||||
const actual = jp.distributeFuriganaInflected(expression, reading, source);
|
const actual = jp.distributeFuriganaInflected(term, reading, source);
|
||||||
vm.assert.deepStrictEqual(actual, expected);
|
vm.assert.deepStrictEqual(actual, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ function createProfileOptionsTestData1() {
|
|||||||
sources: ['jpod101'],
|
sources: ['jpod101'],
|
||||||
volume: 100,
|
volume: 100,
|
||||||
autoPlay: false,
|
autoPlay: false,
|
||||||
customSourceUrl: '',
|
customSourceUrl: 'http://localhost/audio.mp3?term={expression}&reading={reading}',
|
||||||
textToSpeechVoice: ''
|
textToSpeechVoice: ''
|
||||||
},
|
},
|
||||||
scanning: {
|
scanning: {
|
||||||
@ -309,7 +309,7 @@ function createProfileOptionsUpdatedTestData1() {
|
|||||||
sources: ['jpod101'],
|
sources: ['jpod101'],
|
||||||
volume: 100,
|
volume: 100,
|
||||||
autoPlay: false,
|
autoPlay: false,
|
||||||
customSourceUrl: '',
|
customSourceUrl: 'http://localhost/audio.mp3?term={term}&reading={reading}',
|
||||||
customSourceType: 'audio',
|
customSourceType: 'audio',
|
||||||
textToSpeechVoice: ''
|
textToSpeechVoice: ''
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user