diff options
Diffstat (limited to 'ext/js/data')
| -rw-r--r-- | ext/js/data/anki-note-builder.js | 66 | ||||
| -rw-r--r-- | ext/js/data/options-util.js | 1 | 
2 files changed, 66 insertions, 1 deletions
| 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 += '<span class="term">'; +            for (const {text, reading} of term) { +                if (reading.length > 0) { +                    const reading2 = this._convertReading(reading, readingMode); +                    result += `<ruby>${text}<rt>${reading2}</rt></ruby>`; +                } else { +                    result += text; +                } +            } +            result += '</span>'; +        } +        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;      } |