aboutsummaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2021-01-10 19:28:50 -0500
committerGitHub <noreply@github.com>2021-01-10 19:28:50 -0500
commit4ed949364564f00a8b871095d030af516fc2ed6d (patch)
tree8a7ac38887874f67f2e99187f7ab3ce29496fe51 /ext
parent25080ac82eef83fdaa921e2a8b12261130b8ac85 (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
Diffstat (limited to 'ext')
-rw-r--r--ext/bg/js/anki-note-builder.js47
-rw-r--r--ext/bg/js/settings/anki-controller.js4
-rw-r--r--ext/bg/js/settings/anki-templates-controller.js12
-rw-r--r--ext/bg/js/template-renderer-frame-api.js8
-rw-r--r--ext/bg/js/template-renderer-frame-main.js6
-rw-r--r--ext/bg/js/template-renderer-proxy.js4
-rw-r--r--ext/bg/js/template-renderer.js30
-rw-r--r--ext/mixed/js/display.js10
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);