diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2021-01-10 19:28:50 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-10 19:28:50 -0500 | 
| commit | 4ed949364564f00a8b871095d030af516fc2ed6d (patch) | |
| tree | 8a7ac38887874f67f2e99187f7ab3ce29496fe51 | |
| parent | 25080ac82eef83fdaa921e2a8b12261130b8ac85 (diff) | |
Refactor anki note building (#1223)
* Move TemplateRendererProxy creation into AnkiNoteBuilder
* Simplify _stringReplaceAsync
* Organize note generation
* Rename API
* Make the template rendering function more generic
| -rw-r--r-- | ext/bg/js/anki-note-builder.js | 47 | ||||
| -rw-r--r-- | ext/bg/js/settings/anki-controller.js | 4 | ||||
| -rw-r--r-- | ext/bg/js/settings/anki-templates-controller.js | 12 | ||||
| -rw-r--r-- | ext/bg/js/template-renderer-frame-api.js | 8 | ||||
| -rw-r--r-- | ext/bg/js/template-renderer-frame-main.js | 6 | ||||
| -rw-r--r-- | ext/bg/js/template-renderer-proxy.js | 4 | ||||
| -rw-r--r-- | ext/bg/js/template-renderer.js | 30 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 10 | 
8 files changed, 64 insertions, 57 deletions
| diff --git a/ext/bg/js/anki-note-builder.js b/ext/bg/js/anki-note-builder.js index ae608bed..632d9f8a 100644 --- a/ext/bg/js/anki-note-builder.js +++ b/ext/bg/js/anki-note-builder.js @@ -17,12 +17,13 @@  /* global   * DictionaryDataUtil + * TemplateRendererProxy   */  class AnkiNoteBuilder { -    constructor({renderTemplate}) { -        this._renderTemplate = renderTemplate; +    constructor(enabled) {          this._markerPattern = /\{([\w-]+)\}/g; +        this._templateRenderer = enabled ? new TemplateRendererProxy() : null;      }      async createNote({ @@ -49,22 +50,6 @@ class AnkiNoteBuilder {              duplicateScopeCheckChildren = true;          } -        const noteFields = {}; -        const note = { -            fields: noteFields, -            tags, -            deckName, -            modelName, -            options: { -                allowDuplicate: !checkForDuplicates, -                duplicateScope, -                duplicateScopeOptions: { -                    deckName: duplicateScopeDeckName, -                    checkChildren: duplicateScopeCheckChildren -                } -            } -        }; -          const data = this._createNoteData(definition, mode, context, resultOutputMode, glossaryLayoutMode, compactTags);          const formattedFieldValuePromises = [];          for (const [, fieldValue] of fields) { @@ -73,13 +58,27 @@ class AnkiNoteBuilder {          }          const formattedFieldValues = await Promise.all(formattedFieldValuePromises); +        const noteFields = {};          for (let i = 0, ii = fields.length; i < ii; ++i) {              const fieldName = fields[i][0];              const formattedFieldValue = formattedFieldValues[i];              noteFields[fieldName] = formattedFieldValue;          } -        return note; +        return { +            fields: noteFields, +            tags, +            deckName, +            modelName, +            options: { +                allowDuplicate: !checkForDuplicates, +                duplicateScope, +                duplicateScopeOptions: { +                    deckName: duplicateScopeDeckName, +                    checkChildren: duplicateScopeCheckChildren +                } +            } +        };      }      containsMarker(fields, marker) { @@ -146,7 +145,7 @@ class AnkiNoteBuilder {          });      } -    _stringReplaceAsync(str, regex, replacer) { +    async _stringReplaceAsync(str, regex, replacer) {          let match;          let index = 0;          const parts = []; @@ -155,9 +154,13 @@ class AnkiNoteBuilder {              index = regex.lastIndex;          }          if (parts.length === 0) { -            return Promise.resolve(str); +            return str;          }          parts.push(str.substring(index)); -        return Promise.all(parts).then((v) => v.join('')); +        return (await Promise.all(parts)).join(''); +    } + +    async _renderTemplate(template, data, marker) { +        return await this._templateRenderer.render(template, {data, marker}, 'ankiNote');      }  } diff --git a/ext/bg/js/settings/anki-controller.js b/ext/bg/js/settings/anki-controller.js index 4fba77a6..fbd058ee 100644 --- a/ext/bg/js/settings/anki-controller.js +++ b/ext/bg/js/settings/anki-controller.js @@ -26,9 +26,7 @@ class AnkiController {      constructor(settingsController) {          this._settingsController = settingsController;          this._ankiConnect = new AnkiConnect(); -        this._ankiNoteBuilder = new AnkiNoteBuilder({ -            renderTemplate: null -        }); +        this._ankiNoteBuilder = new AnkiNoteBuilder(false);          this._selectorObserver = new SelectorObserver({              selector: '.anki-card',              ignoreSelector: null, diff --git a/ext/bg/js/settings/anki-templates-controller.js b/ext/bg/js/settings/anki-templates-controller.js index 72f1a175..dd07c391 100644 --- a/ext/bg/js/settings/anki-templates-controller.js +++ b/ext/bg/js/settings/anki-templates-controller.js @@ -17,7 +17,6 @@  /* global   * AnkiNoteBuilder - * TemplateRendererProxy   * api   */ @@ -34,7 +33,7 @@ class AnkiTemplatesController {          this._renderFieldInput = null;          this._renderResult = null;          this._fieldTemplateResetModal = null; -        this._templateRenderer = new TemplateRendererProxy(); +        this._ankiNoteBuilder = new AnkiNoteBuilder(true);      }      async prepare() { @@ -180,11 +179,8 @@ class AnkiTemplatesController {                  };                  let templates = options.anki.fieldTemplates;                  if (typeof templates !== 'string') { templates = this._defaultFieldTemplates; } -                const ankiNoteBuilder = new AnkiNoteBuilder({ -                    renderTemplate: this._renderTemplate.bind(this) -                });                  const {general: {resultOutputMode, glossaryLayoutMode, compactTags}} = options; -                const note = await ankiNoteBuilder.createNote({ +                const note = await this._ankiNoteBuilder.createNote({                      definition,                      mode,                      context, @@ -213,8 +209,4 @@ class AnkiTemplatesController {              this._fieldTemplatesTextarea.dataset.invalid = `${hasException}`;          }      } - -    async _renderTemplate(template, data, marker) { -        return await this._templateRenderer.render(template, data, marker); -    }  } diff --git a/ext/bg/js/template-renderer-frame-api.js b/ext/bg/js/template-renderer-frame-api.js index ecdc7268..4936a2af 100644 --- a/ext/bg/js/template-renderer-frame-api.js +++ b/ext/bg/js/template-renderer-frame-api.js @@ -19,7 +19,7 @@ class TemplateRendererFrameApi {      constructor(templateRenderer) {          this._templateRenderer = templateRenderer;          this._windowMessageHandlers = new Map([ -            ['renderHandlebarsTemplate', {async: true, handler: this._onRenderHandlebarsTemplate.bind(this)}] +            ['render', {async: true, handler: this._onRender.bind(this)}]          ]);      } @@ -27,6 +27,8 @@ class TemplateRendererFrameApi {          window.addEventListener('message', this._onWindowMessage.bind(this), false);      } +    // Private +      _onWindowMessage(e) {          const {source, data: {action, params, id}} = e;          const messageHandler = this._windowMessageHandlers.get(action); @@ -51,8 +53,8 @@ class TemplateRendererFrameApi {          source.postMessage({action: `${action}.response`, params: response, id}, '*');      } -    async _onRenderHandlebarsTemplate({template, data, marker}) { -        return await this._templateRenderer.render(template, data, marker); +    async _onRender({template, data, type}) { +        return await this._templateRenderer.render(template, data, type);      }      _errorToJson(error) { diff --git a/ext/bg/js/template-renderer-frame-main.js b/ext/bg/js/template-renderer-frame-main.js index 1bd7e086..92a8095e 100644 --- a/ext/bg/js/template-renderer-frame-main.js +++ b/ext/bg/js/template-renderer-frame-main.js @@ -24,6 +24,12 @@  (() => {      const japaneseUtil = new JapaneseUtil(null);      const templateRenderer = new TemplateRenderer(japaneseUtil); +    templateRenderer.registerDataType('ankiNote', { +        modifier: ({data, marker}) => { +            data.marker = marker; +            return data; +        } +    });      const api = new TemplateRendererFrameApi(templateRenderer);      api.prepare();  })(); diff --git a/ext/bg/js/template-renderer-proxy.js b/ext/bg/js/template-renderer-proxy.js index 04b53ce7..21d45a94 100644 --- a/ext/bg/js/template-renderer-proxy.js +++ b/ext/bg/js/template-renderer-proxy.js @@ -25,9 +25,9 @@ class TemplateRendererProxy {          this._invocations = new Set();      } -    async render(template, data, marker) { +    async render(template, data, type) {          await this._prepareFrame(); -        return await this._invoke('renderHandlebarsTemplate', {template, data, marker}); +        return await this._invoke('render', {template, data, type});      }      // Private diff --git a/ext/bg/js/template-renderer.js b/ext/bg/js/template-renderer.js index c3e5470e..4bf9448e 100644 --- a/ext/bg/js/template-renderer.js +++ b/ext/bg/js/template-renderer.js @@ -26,9 +26,14 @@ class TemplateRenderer {          this._cacheMaxSize = 5;          this._helpersRegistered = false;          this._stateStack = null; +        this._dataTypes = new Map();      } -    async render(template, data, marker) { +    registerDataType(name, {modifier=null, modifierPost=null}) { +        this._dataTypes.set(name, {modifier, modifierPost}); +    } + +    async render(template, data, type) {          if (!this._helpersRegistered) {              this._registerHelpers();              this._helpersRegistered = true; @@ -42,18 +47,27 @@ class TemplateRenderer {              cache.set(template, instance);          } -        const markerPre = data.marker; -        const markerPreHas = Object.prototype.hasOwnProperty.call(data, 'marker'); +        let modifier = null; +        let modifierPost = null; +        if (typeof type === 'string') { +            const typeInfo = this._dataTypes.get(type); +            if (typeof typeInfo !== 'undefined') { +                ({modifier, modifierPost} = typeInfo); +            } +        } +          try { +            if (typeof modifier === 'function') { +                data = modifier(data); +            } +              this._stateStack = [new Map()]; -            data.marker = marker;              return instance(data).trim();          } finally {              this._stateStack = null; -            if (markerPreHas) { -                data.marker = markerPre; -            } else { -                delete data.marker; + +            if (typeof modifierPost === 'function') { +                modifierPost(data);              }          }      } diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index b43b4dca..3cb4b0e4 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -27,7 +27,6 @@   * MediaLoader   * PopupFactory   * QueryParser - * TemplateRendererProxy   * TextScanner   * WindowScroll   * api @@ -89,10 +88,7 @@ class Display extends EventDispatcher {          this._mode = null;          this._defaultAnkiFieldTemplates = null;          this._defaultAnkiFieldTemplatesPromise = null; -        this._templateRenderer = new TemplateRendererProxy(); -        this._ankiNoteBuilder = new AnkiNoteBuilder({ -            renderTemplate: this._renderTemplate.bind(this) -        }); +        this._ankiNoteBuilder = new AnkiNoteBuilder(true);          this._updateAdderButtonsPromise = Promise.resolve();          this._contentScrollElement = document.querySelector('#content-scroll');          this._contentScrollBodyElement = document.querySelector('#content-body'); @@ -1493,10 +1489,6 @@ class Display extends EventDispatcher {          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); |