diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/bg/background.html | 2 | ||||
| -rw-r--r-- | ext/bg/js/backend.js | 100 | ||||
| -rw-r--r-- | ext/bg/js/settings/anki-templates-controller.js | 8 | ||||
| -rw-r--r-- | ext/bg/search.html | 3 | ||||
| -rw-r--r-- | ext/bg/settings.html | 1 | ||||
| -rw-r--r-- | ext/fg/float.html | 5 | ||||
| -rw-r--r-- | ext/mixed/js/api.js | 12 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 128 | 
8 files changed, 136 insertions, 123 deletions
| diff --git a/ext/bg/background.html b/ext/bg/background.html index 93e4b5c7..2f3fd441 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -24,7 +24,6 @@          <script src="/mixed/js/japanese.js"></script>          <script src="/bg/js/anki.js"></script> -        <script src="/bg/js/anki-note-builder.js"></script>          <script src="/bg/js/backend.js"></script>          <script src="/bg/js/mecab.js"></script>          <script src="/bg/js/audio-uri-builder.js"></script> @@ -36,7 +35,6 @@          <script src="/bg/js/options.js"></script>          <script src="/bg/js/profile-conditions.js"></script>          <script src="/bg/js/request-builder.js"></script> -        <script src="/bg/js/template-renderer.js"></script>          <script src="/bg/js/simple-dom-parser.js"></script>          <script src="/bg/js/text-source-map.js"></script>          <script src="/bg/js/translator.js"></script> diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 3d1b1544..b9be9d0a 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -17,7 +17,6 @@  /* global   * AnkiConnect - * AnkiNoteBuilder   * AudioSystem   * AudioUriBuilder   * ClipboardMonitor @@ -29,7 +28,6 @@   * OptionsUtil   * ProfileConditions   * RequestBuilder - * TemplateRenderer   * Translator   * jp   */ @@ -57,10 +55,6 @@ class Backend {              requestBuilder: this._requestBuilder,              useCache: false          }); -        this._ankiNoteBuilder = new AnkiNoteBuilder({ -            renderTemplate: this._renderTemplate.bind(this) -        }); -        this._templateRenderer = new TemplateRenderer();          this._clipboardPasteTarget = null;          this._clipboardPasteTargetInitialized = false; @@ -94,10 +88,7 @@ class Backend {              ['addAnkiNote',                  {async: true,  contentScript: true,  handler: this._onApiAddAnkiNote.bind(this)}],              ['getAnkiNoteInfo',              {async: true,  contentScript: true,  handler: this._onApiGetAnkiNoteInfo.bind(this)}],              ['injectAnkiNoteMedia',          {async: true,  contentScript: true,  handler: this._onApiInjectAnkiNoteMedia.bind(this)}], -            ['definitionAdd',                {async: true,  contentScript: true,  handler: this._onApiDefinitionAdd.bind(this)}], -            ['definitionsAddable',           {async: true,  contentScript: true,  handler: this._onApiDefinitionsAddable.bind(this)}],              ['noteView',                     {async: true,  contentScript: true,  handler: this._onApiNoteView.bind(this)}], -            ['templateRender',               {async: true,  contentScript: true,  handler: this._onApiTemplateRender.bind(this)}],              ['commandExec',                  {async: false, contentScript: true,  handler: this._onApiCommandExec.bind(this)}],              ['audioGetUri',                  {async: true,  contentScript: true,  handler: this._onApiAudioGetUri.bind(this)}],              ['screenshotGet',                {async: true,  contentScript: true,  handler: this._onApiScreenshotGet.bind(this)}], @@ -473,7 +464,11 @@ class Backend {          return results;      } -    async _onApiInjectAnkiNoteMedia({expression, reading, timestamp, audioDetails, screenshotDetails, clipboardImage}) { +    async _onApiInjectAnkiNoteMedia({expression, reading, timestamp, audioDetails, screenshotDetails, clipboardImage}, sender) { +        if (isObject(screenshotDetails)) { +            const {id: tabId, windowId} = (sender && sender.tab ? sender.tab : {}); +            screenshotDetails = Object.assign({}, screenshotDetails, {tabId, windowId}); +        }          return await this._injectAnkNoteMedia(              this._anki,              expression, @@ -485,45 +480,10 @@ class Backend {          );      } -    async _onApiDefinitionAdd({definition, mode, context, ownerFrameId, optionsContext}, sender) { -        const options = this.getOptions(optionsContext); -        const templates = this._getTemplates(options); -        const {id: tabId, windowId} = (sender && sender.tab ? sender.tab : {}); -        const note = await this._createNote(definition, mode, context, options, templates, true, {windowId, tabId, ownerFrameId}); -        return await this._onApiAddAnkiNote({note}); -    } - -    async _onApiDefinitionsAddable({definitions, modes, context, optionsContext}) { -        const options = this.getOptions(optionsContext); -        const templates = this._getTemplates(options); - -        const modeCount = modes.length; -        const {duplicateScope} = options.anki; -        const notePromises = []; -        for (const definition of definitions) { -            for (const mode of modes) { -                const notePromise = this._createNote(definition, mode, context, options, templates, false, null); -                notePromises.push(notePromise); -            } -        } -        const notes = await Promise.all(notePromises); - -        const infos = await this._onApiGetAnkiNoteInfo({notes, duplicateScope}); -        const results = []; -        for (let i = 0, ii = infos.length; i < ii; i += modeCount) { -            results.push(infos.slice(i, i + modeCount)); -        } -        return results; -    } -      async _onApiNoteView({noteId}) {          return await this._anki.guiBrowseNote(noteId);      } -    async _onApiTemplateRender({template, data, marker}) { -        return this._renderTemplate(template, data, marker); -    } -      _onApiCommandExec({command, params}) {          return this._runCommand(command, params);      } @@ -1381,10 +1341,6 @@ class Backend {          return false;      } -    async _renderTemplate(template, data, marker) { -        return await this._templateRenderer.render(template, data, marker); -    } -      _getTemplates(options) {          const templates = options.anki.fieldTemplates;          return typeof templates === 'string' ? templates : this._defaultAnkiFieldTemplates; @@ -1595,52 +1551,6 @@ class Backend {          });      } -    async _createNote(definition, mode, context, options, templates, injectMedia, screenshotTarget) { -        const { -            general: {resultOutputMode, compactGlossaries}, -            anki: {tags, duplicateScope, kanji, terms, screenshot: {format, quality}}, -            audio: {sources, customSourceUrl} -        } = options; -        const modeOptions = (mode === 'kanji') ? kanji : terms; -        const {windowId, tabId, ownerFrameId} = (isObject(screenshotTarget) ? screenshotTarget : {}); - -        if (injectMedia) { -            const fields = modeOptions.fields; -            const timestamp = Date.now(); -            const definitionExpressions = definition.expressions; -            const {expression, reading} = Array.isArray(definitionExpressions) ? definitionExpressions[0] : definition; -            const audioDetails = (mode !== 'kanji' && this._ankiNoteBuilder.containsMarker(fields, 'audio') ? {sources, customSourceUrl} : null); -            const screenshotDetails = (this._ankiNoteBuilder.containsMarker(fields, 'screenshot') ? {windowId, tabId, ownerFrameId, format, quality} : null); -            const clipboardImage = (this._ankiNoteBuilder.containsMarker(fields, 'clipboard-image')); -            const {screenshotFileName, clipboardImageFileName, audioFileName} = await this._onApiInjectAnkiNoteMedia({ -                expression, -                reading, -                timestamp, -                audioDetails, -                screenshotDetails, -                clipboardImage -            }); -            if (screenshotFileName !== null) { definition.screenshotFileName = screenshotFileName; } -            if (clipboardImageFileName !== null) { definition.clipboardImageFileName = clipboardImageFileName; } -            if (audioFileName !== null) { definition.audioFileName = audioFileName; } -        } - -        return await this._ankiNoteBuilder.createNote({ -            definition, -            mode, -            context, -            templates, -            tags, -            duplicateScope, -            resultOutputMode, -            compactGlossaries, -            modeOptions, -            audioDetails: {sources, customSourceUrl}, -            screenshotDetails: {windowId, tabId, ownerFrameId, format, quality}, -            clipboardImage: true -        }); -    } -      async _getScreenshot(windowId, tabId, ownerFrameId, format, quality) {          if (typeof windowId !== 'number') {              throw new Error('Invalid window ID'); diff --git a/ext/bg/js/settings/anki-templates-controller.js b/ext/bg/js/settings/anki-templates-controller.js index c05301df..c53e4553 100644 --- a/ext/bg/js/settings/anki-templates-controller.js +++ b/ext/bg/js/settings/anki-templates-controller.js @@ -17,6 +17,7 @@  /* global   * AnkiNoteBuilder + * TemplateRenderer   * api   */ @@ -27,6 +28,7 @@ class AnkiTemplatesController {          this._cachedDefinitionValue = null;          this._cachedDefinitionText = null;          this._defaultFieldTemplates = null; +        this._templateRenderer = new TemplateRenderer();      }      async prepare() { @@ -144,7 +146,7 @@ class AnkiTemplatesController {                  let templates = options.anki.fieldTemplates;                  if (typeof templates !== 'string') { templates = this._defaultFieldTemplates; }                  const ankiNoteBuilder = new AnkiNoteBuilder({ -                    renderTemplate: api.templateRender.bind(api) +                    renderTemplate: this._renderTemplate.bind(this)                  });                  const {general: {resultOutputMode, compactGlossaries}} = options;                  const note = await ankiNoteBuilder.createNote({ @@ -176,4 +178,8 @@ class AnkiTemplatesController {              input.classList.toggle('is-invalid', hasException);          }      } + +    async _renderTemplate(template, data, marker) { +        return await this._templateRenderer.render(template, data, marker); +    }  } diff --git a/ext/bg/search.html b/ext/bg/search.html index f18bed0d..ae117fd1 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -91,6 +91,9 @@          <script src="/mixed/js/template-handler.js"></script>          <script src="/mixed/js/text-to-speech-audio.js"></script> +        <script src="/bg/js/anki-note-builder.js"></script> +        <script src="/bg/js/template-renderer.js"></script> +          <script src="/bg/js/query-parser-generator.js"></script>          <script src="/bg/js/query-parser.js"></script>          <script src="/bg/js/clipboard-monitor.js"></script> diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 5ee23785..5e6af7f7 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -1183,6 +1183,7 @@          <script src="/bg/js/dictionary-importer.js"></script>          <script src="/bg/js/json-schema.js"></script>          <script src="/bg/js/media-utility.js"></script> +        <script src="/bg/js/template-renderer.js"></script>          <script src="/bg/js/settings/keyboard-mouse-input-field.js"></script>          <script src="/bg/js/settings/profile-conditions-ui.js"></script> diff --git a/ext/fg/float.html b/ext/fg/float.html index 725b7d8b..98e849f0 100644 --- a/ext/fg/float.html +++ b/ext/fg/float.html @@ -44,6 +44,8 @@              </div>          </div> +        <script src="/mixed/lib/handlebars.min.js"></script> +          <script src="/mixed/js/core.js"></script>          <script src="/mixed/js/yomichan.js"></script>          <script src="/mixed/js/comm.js"></script> @@ -66,6 +68,9 @@          <script src="/mixed/js/template-handler.js"></script>          <script src="/mixed/js/text-to-speech-audio.js"></script> +        <script src="/bg/js/anki-note-builder.js"></script> +        <script src="/bg/js/template-renderer.js"></script> +          <script src="/bg/js/query-parser-generator.js"></script>          <script src="/bg/js/query-parser.js"></script>          <script src="/fg/js/float.js"></script> diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index 4a1b0c11..1e7625da 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -89,22 +89,10 @@ const api = (() => {              return this._invoke('injectAnkiNoteMedia', {expression, reading, timestamp, audioDetails, screenshotDetails, clipboardImage});          } -        definitionAdd(definition, mode, context, ownerFrameId, optionsContext) { -            return this._invoke('definitionAdd', {definition, mode, context, ownerFrameId, optionsContext}); -        } - -        definitionsAddable(definitions, modes, context, optionsContext) { -            return this._invoke('definitionsAddable', {definitions, modes, context, optionsContext}); -        } -          noteView(noteId) {              return this._invoke('noteView', {noteId});          } -        templateRender(template, data, marker) { -            return this._invoke('templateRender', {data, template, marker}); -        } -          audioGetUri(source, expression, reading, details) {              return this._invoke('audioGetUri', {source, expression, reading, details});          } diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 7dd5920a..4c42a48d 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -16,6 +16,7 @@   */  /* global + * AnkiNoteBuilder   * AudioSystem   * DisplayGenerator   * DisplayHistory @@ -24,6 +25,7 @@   * MediaLoader   * PopupFactory   * QueryParser + * TemplateRenderer   * WindowScroll   * api   * dynamicLoader @@ -83,6 +85,12 @@ class Display extends EventDispatcher {          });          this._mode = null;          this._ownerFrameId = null; +        this._defaultAnkiFieldTemplates = null; +        this._defaultAnkiFieldTemplatesPromise = null; +        this._templateRenderer = new TemplateRenderer(); +        this._ankiNoteBuilder = new AnkiNoteBuilder({ +            renderTemplate: this._renderTemplate.bind(this) +        });          this.registerActions([              ['close',            () => { this.onEscape(); }], @@ -891,7 +899,8 @@ class Display extends EventDispatcher {          const modes = isTerms ? ['term-kanji', 'term-kana'] : ['kanji'];          let states;          try { -            states = await this._getDefinitionsAddable(definitions, modes); +            const noteContext = await this._getNoteContext(); +            states = await this._areDefinitionsAddable(definitions, modes, noteContext);          } catch (e) {              return;          } @@ -1054,10 +1063,8 @@ class Display extends EventDispatcher {          try {              this.setSpinnerVisible(true); -            const ownerFrameId = this._ownerFrameId; -            const optionsContext = this.getOptionsContext();              const noteContext = await this._getNoteContext(); -            const noteId = await api.definitionAdd(definition, mode, noteContext, ownerFrameId, optionsContext); +            const noteId = await this._addDefinition(definition, mode, noteContext);              if (noteId) {                  const index = this._definitions.indexOf(definition);                  const adderButton = this._adderButtonFind(index, mode); @@ -1196,15 +1203,6 @@ class Display extends EventDispatcher {          return container !== null ? container.querySelector('.action-play-audio>img') : null;      } -    async _getDefinitionsAddable(definitions, modes) { -        try { -            const noteContext = await this._getNoteContext(); -            return await api.definitionsAddable(definitions, modes, noteContext, this.getOptionsContext()); -        } catch (e) { -            return []; -        } -    } -      _indexOf(nodeList, node) {          for (let i = 0, ii = nodeList.length; i < ii; ++i) {              if (nodeList[i] === node) { @@ -1315,4 +1313,108 @@ class Display extends EventDispatcher {          this._mode = mode;          this.trigger('modeChange', {mode});      } + +    async _getTemplates(options) { +        let templates = options.anki.fieldTemplates; +        if (typeof templates === 'string') { return templates; } + +        templates = this._defaultAnkiFieldTemplates; +        if (typeof templates === 'string') { return templates; } + +        return await this._getDefaultTemplatesPromise(); +    } + +    _getDefaultTemplatesPromise() { +        if (this._defaultAnkiFieldTemplatesPromise === null) { +            this._defaultAnkiFieldTemplatesPromise = this._getDefaultTemplates(); +            this._defaultAnkiFieldTemplatesPromise.then( +                () => { this._defaultAnkiFieldTemplatesPromise = null; }, +                () => {} // NOP +            ); +        } +        return this._defaultAnkiFieldTemplatesPromise; +    } + +    async _getDefaultTemplates() { +        const value = await api.getDefaultAnkiFieldTemplates(); +        this._defaultAnkiFieldTemplates = value; +        return value; +    } + +    async _renderTemplate(template, data, marker) { +        return await this._templateRenderer.render(template, data, marker); +    } + +    async _addDefinition(definition, mode, context) { +        const options = this._options; +        const templates = await this._getTemplates(options); +        const note = await this._createNote(definition, mode, context, options, templates, true); +        return await api.addAnkiNote(note); +    } + +    async _areDefinitionsAddable(definitions, modes, context) { +        const options = this._options; +        const templates = await this._getTemplates(options); + +        const modeCount = modes.length; +        const {duplicateScope} = options.anki; +        const notePromises = []; +        for (const definition of definitions) { +            for (const mode of modes) { +                const notePromise = this._createNote(definition, mode, context, options, templates, false); +                notePromises.push(notePromise); +            } +        } +        const notes = await Promise.all(notePromises); + +        const infos = await api.getAnkiNoteInfo(notes, duplicateScope); +        const results = []; +        for (let i = 0, ii = infos.length; i < ii; i += modeCount) { +            results.push(infos.slice(i, i + modeCount)); +        } +        return results; +    } + +    async _createNote(definition, mode, context, options, templates, injectMedia) { +        const { +            general: {resultOutputMode, compactGlossaries}, +            anki: {tags, duplicateScope, kanji, terms, screenshot: {format, quality}}, +            audio: {sources, customSourceUrl} +        } = options; +        const modeOptions = (mode === 'kanji') ? kanji : terms; + +        if (injectMedia) { +            const timestamp = Date.now(); +            const ownerFrameId = this._ownerFrameId; +            const {fields} = modeOptions; +            const definitionExpressions = definition.expressions; +            const {expression, reading} = Array.isArray(definitionExpressions) ? definitionExpressions[0] : definition; +            const audioDetails = (mode !== 'kanji' && this._ankiNoteBuilder.containsMarker(fields, 'audio') ? {sources, customSourceUrl} : null); +            const screenshotDetails = (this._ankiNoteBuilder.containsMarker(fields, 'screenshot') ? {ownerFrameId, format, quality} : null); +            const clipboardImage = (this._ankiNoteBuilder.containsMarker(fields, 'clipboard-image')); +            const {screenshotFileName, clipboardImageFileName, audioFileName} = await api.injectAnkiNoteMedia( +                expression, +                reading, +                timestamp, +                audioDetails, +                screenshotDetails, +                clipboardImage +            ); +            if (screenshotFileName !== null) { definition.screenshotFileName = screenshotFileName; } +            if (clipboardImageFileName !== null) { definition.clipboardImageFileName = clipboardImageFileName; } +            if (audioFileName !== null) { definition.audioFileName = audioFileName; } +        } + +        return await this._ankiNoteBuilder.createNote({ +            definition, +            mode, +            context, +            templates, +            tags, +            duplicateScope, +            resultOutputMode, +            compactGlossaries, +            modeOptions +        }); +    }  } |