From dabda86259d78ee66125ebf2cff15a7619e0b5da Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 2 Apr 2021 19:09:21 -0400 Subject: Optimize template renderer (#1585) * Add renderMulti * Batch template rendering * Update tests --- ext/js/templates/template-renderer-frame-api.js | 16 ++++++++++ ext/js/templates/template-renderer-frame-main.js | 3 +- ext/js/templates/template-renderer-proxy.js | 5 ++++ ext/js/templates/template-renderer.js | 37 ++++++++++++++++++++---- 4 files changed, 55 insertions(+), 6 deletions(-) (limited to 'ext/js/templates') diff --git a/ext/js/templates/template-renderer-frame-api.js b/ext/js/templates/template-renderer-frame-api.js index 104e357b..dd6be517 100644 --- a/ext/js/templates/template-renderer-frame-api.js +++ b/ext/js/templates/template-renderer-frame-api.js @@ -20,6 +20,7 @@ class TemplateRendererFrameApi { this._templateRenderer = templateRenderer; this._windowMessageHandlers = new Map([ ['render', {async: false, handler: this._onRender.bind(this)}], + ['renderMulti', {async: false, handler: this._onRenderMulti.bind(this)}], ['getModifiedData', {async: false, handler: this._onGetModifiedData.bind(this)}] ]); } @@ -58,6 +59,10 @@ class TemplateRendererFrameApi { return this._templateRenderer.render(template, data, type); } + _onRenderMulti({items}) { + return this._serializeMulti(this._templateRenderer.renderMulti(items)); + } + _onGetModifiedData({data, type}) { const result = this._templateRenderer.getModifiedData(data, type); return this._clone(result); @@ -82,6 +87,17 @@ class TemplateRendererFrameApi { }; } + _serializeMulti(array) { + for (let i = 0, ii = array.length; i < ii; ++i) { + const value = array[i]; + const {error} = value; + if (typeof error !== 'undefined') { + value.error = this._serializeError(error); + } + } + return array; + } + _clone(value) { return JSON.parse(JSON.stringify(value)); } diff --git a/ext/js/templates/template-renderer-frame-main.js b/ext/js/templates/template-renderer-frame-main.js index 40ecf308..3d61295d 100644 --- a/ext/js/templates/template-renderer-frame-main.js +++ b/ext/js/templates/template-renderer-frame-main.js @@ -27,7 +27,8 @@ const templateRenderer = new TemplateRenderer(japaneseUtil); const ankiNoteDataCreator = new AnkiNoteDataCreator(japaneseUtil); templateRenderer.registerDataType('ankiNote', { - modifier: ({marker, commonData}) => ankiNoteDataCreator.create(marker, commonData) + modifier: ({marker, commonData}) => ankiNoteDataCreator.create(marker, commonData), + composeData: (marker, commonData) => ({marker, commonData}) }); const templateRendererFrameApi = new TemplateRendererFrameApi(templateRenderer); templateRendererFrameApi.prepare(); diff --git a/ext/js/templates/template-renderer-proxy.js b/ext/js/templates/template-renderer-proxy.js index aba45e6c..f35239cb 100644 --- a/ext/js/templates/template-renderer-proxy.js +++ b/ext/js/templates/template-renderer-proxy.js @@ -30,6 +30,11 @@ class TemplateRendererProxy { return await this._invoke('render', {template, data, type}); } + async renderMulti(items) { + await this._prepareFrame(); + return await this._invoke('renderMulti', {items}); + } + async getModifiedData(data, type) { await this._prepareFrame(); return await this._invoke('getModifiedData', {data, type}); diff --git a/ext/js/templates/template-renderer.js b/ext/js/templates/template-renderer.js index 5441528c..ed9cc41c 100644 --- a/ext/js/templates/template-renderer.js +++ b/ext/js/templates/template-renderer.js @@ -29,18 +29,39 @@ class TemplateRenderer { this._dataTypes = new Map(); } - registerDataType(name, {modifier=null}) { - this._dataTypes.set(name, {modifier}); + registerDataType(name, {modifier=null, composeData=null}) { + this._dataTypes.set(name, {modifier, composeData}); } render(template, data, type) { const instance = this._getTemplateInstance(template); - data = this._getModifiedData(data, type); + data = this._getModifiedData(data, void 0, type); return this._renderTemplate(instance, data); } + renderMulti(items) { + const results = []; + for (const {template, templateItems} of items) { + const instance = this._getTemplateInstance(template); + for (const {type, commonData, datas} of templateItems) { + for (let data of datas) { + let result; + try { + data = this._getModifiedData(data, commonData, type); + result = this._renderTemplate(instance, data); + result = {result}; + } catch (error) { + result = {error}; + } + results.push(result); + } + } + } + return results; + } + getModifiedData(data, type) { - return this._getModifiedData(data, type); + return this._getModifiedData(data, void 0, type); } // Private @@ -70,10 +91,16 @@ class TemplateRenderer { } } - _getModifiedData(data, type) { + _getModifiedData(data, commonData, type) { if (typeof type === 'string') { const typeInfo = this._dataTypes.get(type); if (typeof typeInfo !== 'undefined') { + if (typeof commonData !== 'undefined') { + const {composeData} = typeInfo; + if (typeof composeData === 'function') { + data = composeData(data, commonData); + } + } const {modifier} = typeInfo; if (typeof modifier === 'function') { data = modifier(data); -- cgit v1.2.3