From 8c68fa4d9435b562ffe23df92a2b7b620a0ed78e Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 9 Jul 2021 17:48:27 -0400 Subject: [PATCH] Anki text furigana parsing and {sentence-furigana} marker (#1814) * Add support for textFurigana media * Add readingMode parameter * Implement readingMode * Add {sentence-furigana} marker * Fallback to sentence if furigana isn't available * Update test data --- README.md | 2 + ...nki-field-templates-upgrade-v13.handlebars | 10 +++ .../default-anki-field-templates.handlebars | 10 +++ ext/js/data/anki-note-builder.js | 66 ++++++++++++++- ext/js/data/options-util.js | 1 + ext/js/display/display-anki.js | 14 +++- ext/js/display/display.js | 2 +- ext/js/pages/settings/anki-controller.js | 2 + .../settings/anki-templates-controller.js | 3 +- .../template-renderer-media-provider.js | 34 ++++---- ext/settings.html | 4 + test/data/anki-note-builder-test-results.json | 81 +++++++++++++++++++ test/test-anki-note-builder.js | 15 ++-- 13 files changed, 217 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index de6d248d..7d9c5d44 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,7 @@ Flashcard fields can be configured with the following steps: `{search-query}` | The full search query shown on the search page. `{selection-text}` | The selected text on the search page or popup. `{sentence}` | Sentence, quote, or phrase that the term appears in from the source content. + `{sentence-furigana}` | Sentence, quote, or phrase that the term appears in from the source content, with furigana added. `{tags}` | Grammar and usage tags providing information about the term (unavailable in *grouped* mode). `{url}` | Address of the web page in which the term appeared in. @@ -202,6 +203,7 @@ Flashcard fields can be configured with the following steps: `{search-query}` | The full search query shown on the search page. `{selection-text}` | The selected text on the search page or popup. `{sentence}` | Sentence, quote, or phrase that the character appears in from the source content. + `{sentence-furigana}` | Sentence, quote, or phrase that the character appears in from the source content, with furigana added. `{stroke-count}` | Number of strokes that the kanji character has. `{url}` | Address of the web page in which the kanji appeared in. diff --git a/ext/data/templates/anki-field-templates-upgrade-v13.handlebars b/ext/data/templates/anki-field-templates-upgrade-v13.handlebars index 78820b95..25007030 100644 --- a/ext/data/templates/anki-field-templates-upgrade-v13.handlebars +++ b/ext/data/templates/anki-field-templates-upgrade-v13.handlebars @@ -2,6 +2,16 @@ {{~#if (hasMedia "selectionText")}}{{#getMedia "selectionText" format="text"}}{{/getMedia}}{{/if~}} {{/inline}} +{{#*inline "sentence-furigana"}} + {{~#if definition.cloze~}} + {{~#if (hasMedia "textFurigana" definition.cloze.sentence)~}} + {{#getMedia "textFurigana" definition.cloze.sentence format="html"}}{{/getMedia}} + {{~else~}} + {{definition.cloze.sentence}} + {{~/if~}} + {{~/if~}} +{{/inline}} + {{<<<<<<<}} {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{/each}} {{=======}} diff --git a/ext/data/templates/default-anki-field-templates.handlebars b/ext/data/templates/default-anki-field-templates.handlebars index c9ee2833..cdbec87d 100644 --- a/ext/data/templates/default-anki-field-templates.handlebars +++ b/ext/data/templates/default-anki-field-templates.handlebars @@ -382,4 +382,14 @@ {{~#if (hasMedia "selectionText")}}{{#getMedia "selectionText" format="text"}}{{/getMedia}}{{/if~}} {{/inline}} +{{#*inline "sentence-furigana"}} + {{~#if definition.cloze~}} + {{~#if (hasMedia "textFurigana" definition.cloze.sentence)~}} + {{#getMedia "textFurigana" definition.cloze.sentence format="html"}}{{/getMedia}} + {{~else~}} + {{definition.cloze.sentence}} + {{~/if~}} + {{~/if~}} +{{/inline}} + {{~> (lookup . "marker") ~}} diff --git a/ext/js/data/anki-note-builder.js b/ext/js/data/anki-note-builder.js index 23dd648b..02aa7969 100644 --- a/ext/js/data/anki-note-builder.js +++ b/ext/js/data/anki-note-builder.js @@ -21,7 +21,8 @@ */ class AnkiNoteBuilder { - constructor() { + constructor({japaneseUtil}) { + this._japaneseUtil = japaneseUtil; this._markerPattern = AnkiUtil.cloneFieldMarkerPattern(true); this._templateRenderer = new TemplateRendererProxy(); this._batchedRequests = []; @@ -284,6 +285,7 @@ class AnkiNoteBuilder { let injectClipboardImage = false; let injectClipboardText = false; let injectSelectionText = false; + const textFuriganaDetails = []; const dictionaryMediaDetails = []; for (const requirement of requirements) { const {type} = requirement; @@ -293,6 +295,12 @@ class AnkiNoteBuilder { case 'clipboardImage': injectClipboardImage = true; break; case 'clipboardText': injectClipboardText = true; break; case 'selectionText': injectSelectionText = true; break; + case 'textFurigana': + { + const {text, readingMode} = requirement; + textFuriganaDetails.push({text, readingMode}); + } + break; case 'dictionaryMedia': { const {dictionary, path} = requirement; @@ -323,6 +331,14 @@ class AnkiNoteBuilder { } } } + let textFuriganaPromise = null; + if (textFuriganaDetails.length > 0) { + const textParsingOptions = mediaOptions.textParsing; + if (typeof textParsingOptions === 'object' && textParsingOptions !== null) { + const {optionsContext, scanLength} = textParsingOptions; + textFuriganaPromise = this._getTextFurigana(textFuriganaDetails, optionsContext, scanLength); + } + } // Inject media const selectionText = injectSelectionText ? this._getSelectionText() : null; @@ -335,6 +351,7 @@ class AnkiNoteBuilder { dictionaryMediaDetails ); const {audioFileName, screenshotFileName, clipboardImageFileName, clipboardText, dictionaryMedia: dictionaryMediaArray, errors} = injectedMedia; + const textFurigana = textFuriganaPromise !== null ? await textFuriganaPromise : []; // Format results const dictionaryMedia = {}; @@ -353,6 +370,7 @@ class AnkiNoteBuilder { clipboardImage: (typeof clipboardImageFileName === 'string' ? {fileName: clipboardImageFileName} : null), clipboardText: (typeof clipboardText === 'string' ? {text: clipboardText} : null), selectionText: (typeof selectionText === 'string' ? {text: selectionText} : null), + textFurigana, dictionaryMedia }; return {media, errors}; @@ -361,4 +379,50 @@ class AnkiNoteBuilder { _getSelectionText() { return document.getSelection().toString(); } + + async _getTextFurigana(entries, optionsContext, scanLength) { + const results = []; + for (const {text, readingMode} of entries) { + const parseResults = await yomichan.api.parseText(text, optionsContext, scanLength, true, false); + let data = null; + for (const {source, content} of parseResults) { + if (source !== 'scanning-parser') { continue; } + data = content; + break; + } + if (data !== null) { + const html = this._createFuriganaHtml(data, readingMode); + results.push({text, readingMode, details: {html}}); + } + } + return results; + } + + _createFuriganaHtml(data, readingMode) { + let result = ''; + for (const term of data) { + result += ''; + for (const {text, reading} of term) { + if (reading.length > 0) { + const reading2 = this._convertReading(reading, readingMode); + result += `${text}${reading2}`; + } else { + result += text; + } + } + result += ''; + } + return result; + } + + _convertReading(reading, readingMode) { + switch (readingMode) { + case 'hiragana': + return this._japaneseUtil.convertKatakanaToHiragana(reading); + case 'katakana': + return this._japaneseUtil.convertHiraganaToKatakana(reading); + default: + return reading; + } + } } diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index 3d36fc2e..36630e2f 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -855,6 +855,7 @@ class OptionsUtil { // Handlebars templates updated to use formatGlossary. // Handlebars templates updated to use new media format. // Added {selection-text} field marker. + // Added {sentence-furigana} field marker. await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v13.handlebars'); return options; } diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js index 114a9d13..235149ad 100644 --- a/ext/js/display/display-anki.js +++ b/ext/js/display/display-anki.js @@ -22,11 +22,11 @@ */ class DisplayAnki { - constructor(display) { + constructor(display, japaneseUtil) { this._display = display; this._ankiFieldTemplates = null; this._ankiFieldTemplatesDefault = null; - this._ankiNoteBuilder = new AnkiNoteBuilder(); + this._ankiNoteBuilder = new AnkiNoteBuilder({japaneseUtil}); this._ankiNoteNotification = null; this._ankiNoteNotificationEventListeners = null; this._ankiTagNotification = null; @@ -44,6 +44,7 @@ class DisplayAnki { this._duplicateScope = 'collection'; this._screenshotFormat = 'png'; this._screenshotQuality = 100; + this._scanLength = 10; this._noteTags = []; this._modeOptions = new Map(); this._dictionaryEntryTypeModeMap = new Map([ @@ -141,7 +142,8 @@ class DisplayAnki { _onOptionsUpdated({options}) { const { general: {resultOutputMode, glossaryLayoutMode, compactTags}, - anki: {tags, duplicateScope, suspendNewCards, checkForDuplicates, displayTags, kanji, terms, screenshot: {format, quality}} + anki: {tags, duplicateScope, suspendNewCards, checkForDuplicates, displayTags, kanji, terms, screenshot: {format, quality}}, + scanning: {length: scanLength} } = options; this._checkForDuplicates = checkForDuplicates; @@ -153,6 +155,7 @@ class DisplayAnki { this._duplicateScope = duplicateScope; this._screenshotFormat = format; this._screenshotQuality = quality; + this._scanLength = scanLength; this._noteTags = [...tags]; this._modeOptions.clear(); this._modeOptions.set('kanji', kanji); @@ -526,6 +529,7 @@ class DisplayAnki { const contentOrigin = this._display.getContentOrigin(); const details = this._ankiNoteBuilder.getDictionaryEntryDetailsForNote(dictionaryEntry); const audioDetails = (details.type === 'term' ? this._display.getAnkiNoteMediaAudioDetails(details.term, details.reading) : null); + const optionsContext = this._display.getOptionsContext(); const {note, errors, requirements: outputRequirements} = await this._ankiNoteBuilder.createNote({ dictionaryEntry, @@ -547,6 +551,10 @@ class DisplayAnki { format: this._screenshotFormat, quality: this._screenshotQuality, contentOrigin + }, + textParsing: { + optionsContext, + scanLength: this._scanLength } }, requirements diff --git a/ext/js/display/display.js b/ext/js/display/display.js index d79cc7e2..12486a72 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -110,7 +110,7 @@ class Display extends EventDispatcher { this._queryPostProcessor = null; this._optionToggleHotkeyHandler = new OptionToggleHotkeyHandler(this); this._elementOverflowController = new ElementOverflowController(); - this._displayAnki = new DisplayAnki(this); + this._displayAnki = new DisplayAnki(this, japaneseUtil); this._hotkeyHandler.registerActions([ ['close', () => { this._onHotkeyClose(); }], diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js index b98de1b6..c0f7f626 100644 --- a/ext/js/pages/settings/anki-controller.js +++ b/ext/js/pages/settings/anki-controller.js @@ -104,6 +104,7 @@ class AnkiController { 'search-query', 'selection-text', 'sentence', + 'sentence-furigana', 'tags', 'url' ]; @@ -123,6 +124,7 @@ class AnkiController { 'screenshot', 'search-query', 'selection-text', + 'sentence-furigana', 'sentence', 'stroke-count', 'tags', diff --git a/ext/js/pages/settings/anki-templates-controller.js b/ext/js/pages/settings/anki-templates-controller.js index aa565bad..ad2790ca 100644 --- a/ext/js/pages/settings/anki-templates-controller.js +++ b/ext/js/pages/settings/anki-templates-controller.js @@ -17,6 +17,7 @@ /* global * AnkiNoteBuilder + * JapaneseUtil */ class AnkiTemplatesController { @@ -32,7 +33,7 @@ class AnkiTemplatesController { this._renderFieldInput = null; this._renderResult = null; this._fieldTemplateResetModal = null; - this._ankiNoteBuilder = new AnkiNoteBuilder(); + this._ankiNoteBuilder = new AnkiNoteBuilder({japaneseUtil: new JapaneseUtil(null)}); } async prepare() { diff --git a/ext/js/templates/template-renderer-media-provider.js b/ext/js/templates/template-renderer-media-provider.js index 4fd40c67..604b5331 100644 --- a/ext/js/templates/template-renderer-media-provider.js +++ b/ext/js/templates/template-renderer-media-provider.js @@ -54,21 +54,7 @@ class TemplateRendererMediaProvider { } _getFormattedValue(data, format) { - switch (format) { - case 'fileName': - { - const {fileName} = data; - if (typeof fileName === 'string') { return fileName; } - } - break; - case 'text': - { - const {text} = data; - if (typeof text === 'string') { return text; } - } - break; - } - return null; + return Object.prototype.hasOwnProperty.call(data, format) ? data[format] : null; } _getMediaData(media, args, namedArgs) { @@ -79,6 +65,7 @@ class TemplateRendererMediaProvider { case 'clipboardImage': return this._getSimpleMediaData(media, 'clipboardImage'); case 'clipboardText': return this._getSimpleMediaData(media, 'clipboardText'); case 'selectionText': return this._getSimpleMediaData(media, 'selectionText'); + case 'textFurigana': return this._getTextFurigana(media, args[1], namedArgs); case 'dictionaryMedia': return this._getDictionaryMedia(media, args[1], namedArgs); default: return null; } @@ -114,4 +101,21 @@ class TemplateRendererMediaProvider { }); return null; } + + _getTextFurigana(media, text, namedArgs) { + const {readingMode=null} = namedArgs; + const {textFurigana} = media; + if (Array.isArray(textFurigana)) { + for (const entry of textFurigana) { + if (entry.text !== text || entry.readingMode !== readingMode) { continue; } + return entry.details; + } + } + this._addRequirement({ + type: 'textFurigana', + text, + readingMode + }); + return null; + } } diff --git a/ext/settings.html b/ext/settings.html index a8c8149b..0144ddd3 100644 --- a/ext/settings.html +++ b/ext/settings.html @@ -2867,6 +2867,10 @@ {sentence} Sentence, quote, or phrase that the term or kanji appears in from the source content. + + {sentence-furigana} + Sentence, quote, or phrase that the term or kanji appears in from the source content, with furigana added. + {url} Address of the web page in which the term or kanji appeared in. diff --git a/test/data/anki-note-builder-test-results.json b/test/data/anki-note-builder-test-results.json index a8a7b08a..c10e28a8 100644 --- a/test/data/anki-note-builder-test-results.json +++ b/test/data/anki-note-builder-test-results.json @@ -18,6 +18,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "stroke-count": "Stroke count: Unknown", "tags": "", "url": "url:" @@ -43,6 +44,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix込cloze-suffix", + "sentence-furigana": "cloze-prefix込cloze-suffix", "stroke-count": "Stroke count: Unknown", "tags": "", "url": "url:" @@ -82,6 +84,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "n", "url": "url:" }, @@ -111,6 +114,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -145,6 +149,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", + "sentence-furigana": "cloze-prefix打つcloze-suffix", "tags": "vt", "url": "url:" }, @@ -174,6 +179,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", + "sentence-furigana": "cloze-prefix打つcloze-suffix", "tags": "vt", "url": "url:" }, @@ -203,6 +209,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", + "sentence-furigana": "cloze-prefix打つcloze-suffix", "tags": "vt", "url": "url:" }, @@ -232,6 +239,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打つcloze-suffix", + "sentence-furigana": "cloze-prefix打つcloze-suffix", "tags": "vt", "url": "url:" }, @@ -261,6 +269,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "n", "url": "url:" }, @@ -290,6 +299,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -324,6 +334,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -353,6 +364,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -382,6 +394,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -411,6 +424,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -440,6 +454,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -469,6 +484,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -498,6 +514,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -527,6 +544,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -556,6 +574,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "n", "url": "url:" }, @@ -585,6 +604,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -619,6 +639,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix画像cloze-suffix", + "sentence-furigana": "cloze-prefix画像cloze-suffix", "tags": "n", "url": "url:" } @@ -653,6 +674,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixだcloze-suffix", + "sentence-furigana": "cloze-prefixだcloze-suffix", "tags": "n", "url": "url:" } @@ -687,6 +709,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixダースcloze-suffix", + "sentence-furigana": "cloze-prefixダースcloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -721,6 +744,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうつcloze-suffix", + "sentence-furigana": "cloze-prefixうつcloze-suffix", "tags": "vt", "url": "url:" }, @@ -750,6 +774,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうつcloze-suffix", + "sentence-furigana": "cloze-prefixうつcloze-suffix", "tags": "vt", "url": "url:" } @@ -784,6 +809,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixぶつcloze-suffix", + "sentence-furigana": "cloze-prefixぶつcloze-suffix", "tags": "vt", "url": "url:" }, @@ -813,6 +839,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixぶつcloze-suffix", + "sentence-furigana": "cloze-prefixぶつcloze-suffix", "tags": "vt", "url": "url:" } @@ -847,6 +874,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうちこむcloze-suffix", + "sentence-furigana": "cloze-prefixうちこむcloze-suffix", "tags": "vt", "url": "url:" }, @@ -876,6 +904,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうちこむcloze-suffix", + "sentence-furigana": "cloze-prefixうちこむcloze-suffix", "tags": "vt", "url": "url:" }, @@ -905,6 +934,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうちcloze-suffix", + "sentence-furigana": "cloze-prefixうちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -934,6 +964,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうちcloze-suffix", + "sentence-furigana": "cloze-prefixうちcloze-suffix", "tags": "vt", "url": "url:" } @@ -968,6 +999,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixぶちこむcloze-suffix", + "sentence-furigana": "cloze-prefixぶちこむcloze-suffix", "tags": "vt", "url": "url:" }, @@ -997,6 +1029,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixぶちこむcloze-suffix", + "sentence-furigana": "cloze-prefixぶちこむcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1026,6 +1059,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixぶちcloze-suffix", + "sentence-furigana": "cloze-prefixぶちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1055,6 +1089,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixぶちcloze-suffix", + "sentence-furigana": "cloze-prefixぶちcloze-suffix", "tags": "vt", "url": "url:" } @@ -1089,6 +1124,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixがぞうcloze-suffix", + "sentence-furigana": "cloze-prefixがぞうcloze-suffix", "tags": "n", "url": "url:" } @@ -1135,6 +1171,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1164,6 +1201,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1193,6 +1231,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1222,6 +1261,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1251,6 +1291,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "n", "url": "url:" }, @@ -1280,6 +1321,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -1314,6 +1356,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込むcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1343,6 +1386,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1372,6 +1416,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "n", "url": "url:" }, @@ -1401,6 +1446,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -1435,6 +1481,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1464,6 +1511,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1493,6 +1541,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1522,6 +1571,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ち込んでいませんでしたcloze-suffix", + "sentence-furigana": "cloze-prefix打ち込んでいませんでしたcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1551,6 +1601,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1580,6 +1631,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1609,6 +1661,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1638,6 +1691,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打ちcloze-suffix", + "sentence-furigana": "cloze-prefix打ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1667,6 +1721,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "n", "url": "url:" }, @@ -1696,6 +1751,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -1730,6 +1786,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1759,6 +1816,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1788,6 +1846,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1817,6 +1876,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ち込(こ)むcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ち込(こ)むcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1846,6 +1906,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1875,6 +1936,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1904,6 +1966,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1933,6 +1996,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打(う)ちcloze-suffix", + "sentence-furigana": "cloze-prefix打(う)ちcloze-suffix", "tags": "vt", "url": "url:" }, @@ -1962,6 +2026,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "n", "url": "url:" }, @@ -1991,6 +2056,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix打cloze-suffix", + "sentence-furigana": "cloze-prefix打cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -2025,6 +2091,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2054,6 +2121,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2083,6 +2151,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2112,6 +2181,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)(込)(む)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2141,6 +2211,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2170,6 +2241,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2199,6 +2271,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2228,6 +2301,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)(ち)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)(ち)cloze-suffix", "tags": "vt", "url": "url:" }, @@ -2257,6 +2331,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)cloze-suffix", "tags": "n", "url": "url:" }, @@ -2286,6 +2361,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefix(打)cloze-suffix", + "sentence-furigana": "cloze-prefix(打)cloze-suffix", "tags": "abbr, n", "url": "url:" } @@ -2320,6 +2396,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixtestcloze-suffix", + "sentence-furigana": "cloze-prefixtestcloze-suffix", "tags": "vt", "url": "url:" } @@ -2354,6 +2431,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixつtestcloze-suffix", + "sentence-furigana": "cloze-prefixつtestcloze-suffix", "tags": "n", "url": "url:" } @@ -2388,6 +2466,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixtestましたcloze-suffix", + "sentence-furigana": "cloze-prefixtestましたcloze-suffix", "tags": "vt", "url": "url:" } @@ -2422,6 +2501,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうちこむcloze-suffix", + "sentence-furigana": "cloze-prefixうちこむcloze-suffix", "tags": "vt", "url": "url:" }, @@ -2451,6 +2531,7 @@ "search-query": "fullQuery", "selection-text": "", "sentence": "cloze-prefixうちcloze-suffix", + "sentence-furigana": "cloze-prefixうちcloze-suffix", "tags": "vt", "url": "url:" } diff --git a/test/test-anki-note-builder.js b/test/test-anki-note-builder.js index af9cd061..c7d91325 100644 --- a/test/test-anki-note-builder.js +++ b/test/test-anki-note-builder.js @@ -128,7 +128,7 @@ async function createVM() { } vm.set({TemplateRendererProxy}); - return {vm, AnkiNoteBuilder}; + return {vm, AnkiNoteBuilder, JapaneseUtil}; } function getFieldMarkers(type) { @@ -160,6 +160,7 @@ function getFieldMarkers(type) { 'search-query', 'selection-text', 'sentence', + 'sentence-furigana', 'tags', 'url' ]; @@ -180,6 +181,7 @@ function getFieldMarkers(type) { 'search-query', 'selection-text', 'sentence', + 'sentence-furigana', 'stroke-count', 'tags', 'url' @@ -189,13 +191,14 @@ function getFieldMarkers(type) { } } -async function getRenderResults(dictionaryEntries, type, mode, template, AnkiNoteBuilder, write) { +async function getRenderResults(dictionaryEntries, type, mode, template, AnkiNoteBuilder, JapaneseUtil, write) { const markers = getFieldMarkers(type); const fields = []; for (const marker of markers) { fields.push([marker, `{${marker}}`]); } + const japaneseUtil = new JapaneseUtil(null); const clozePrefix = 'cloze-prefix'; const clozeSuffix = 'cloze-suffix'; const results = []; @@ -211,7 +214,7 @@ async function getRenderResults(dictionaryEntries, type, mode, template, AnkiNot } break; } - const ankiNoteBuilder = new AnkiNoteBuilder(); + const ankiNoteBuilder = new AnkiNoteBuilder({japaneseUtil}); const context = { url: 'url:', sentence: { @@ -250,7 +253,7 @@ async function getRenderResults(dictionaryEntries, type, mode, template, AnkiNot async function main() { const write = (process.argv[2] === '--write'); - const {vm, AnkiNoteBuilder} = await createVM(); + const {vm, AnkiNoteBuilder, JapaneseUtil} = await createVM(); const testInputsFilePath = path.join(__dirname, 'data', 'translator-test-inputs.json'); const {optionsPresets, tests} = JSON.parse(fs.readFileSync(testInputsFilePath, {encoding: 'utf8'})); @@ -270,7 +273,7 @@ async function main() { const {name, mode, text} = test; const options = vm.buildOptions(optionsPresets, test.options); const {dictionaryEntries} = clone(await vm.translator.findTerms(mode, text, options)); - const results = mode !== 'simple' ? clone(await getRenderResults(dictionaryEntries, 'terms', mode, template, AnkiNoteBuilder, write)) : null; + const results = mode !== 'simple' ? clone(await getRenderResults(dictionaryEntries, 'terms', mode, template, AnkiNoteBuilder, JapaneseUtil, write)) : null; actualResults1.push({name, results}); if (!write) { assert.deepStrictEqual(results, expected1.results); @@ -282,7 +285,7 @@ async function main() { const {name, text} = test; const options = vm.buildOptions(optionsPresets, test.options); const dictionaryEntries = clone(await vm.translator.findKanji(text, options)); - const results = clone(await getRenderResults(dictionaryEntries, 'kanji', null, template, AnkiNoteBuilder, write)); + const results = clone(await getRenderResults(dictionaryEntries, 'kanji', null, template, AnkiNoteBuilder, JapaneseUtil, write)); actualResults1.push({name, results}); if (!write) { assert.deepStrictEqual(results, expected1.results);