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); |