aboutsummaryrefslogtreecommitdiff
path: root/ext/js/templates/template-renderer-frame-api.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/templates/template-renderer-frame-api.js')
-rw-r--r--ext/js/templates/template-renderer-frame-api.js103
1 files changed, 103 insertions, 0 deletions
diff --git a/ext/js/templates/template-renderer-frame-api.js b/ext/js/templates/template-renderer-frame-api.js
new file mode 100644
index 00000000..cd9b4232
--- /dev/null
+++ b/ext/js/templates/template-renderer-frame-api.js
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023-2024 Yomitan Authors
+ * Copyright (C) 2020-2022 Yomichan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import {createApiMap, invokeApiMapHandler} from '../core/api-map.js';
+import {parseJson} from '../core/json.js';
+
+export class TemplateRendererFrameApi {
+ /**
+ * @param {import('./template-renderer.js').TemplateRenderer} templateRenderer
+ */
+ constructor(templateRenderer) {
+ /** @type {import('./template-renderer.js').TemplateRenderer} */
+ this._templateRenderer = templateRenderer;
+ /** @type {import('template-renderer-proxy').FrontendApiMap} */
+ this._windowMessageHandlers = createApiMap([
+ ['render', this._onRender.bind(this)],
+ ['renderMulti', this._onRenderMulti.bind(this)],
+ ['getModifiedData', this._onGetModifiedData.bind(this)]
+ ]);
+ }
+
+ /**
+ * @returns {void}
+ */
+ prepare() {
+ window.addEventListener('message', this._onWindowMessage.bind(this), false);
+ this._postMessage(window.parent, 'ready', void 0, null);
+ }
+
+ // Private
+
+ /**
+ * @param {MessageEvent<import('template-renderer-proxy').FrontendMessageAny>} e
+ */
+ _onWindowMessage(e) {
+ const {source, data: {action, params, id}} = e;
+ invokeApiMapHandler(this._windowMessageHandlers, action, params, [], (response) => {
+ this._postMessage(/** @type {Window} */ (source), 'response', response, id);
+ });
+ }
+
+ /**
+ * @param {{template: string, data: import('template-renderer').PartialOrCompositeRenderData, type: import('anki-templates').RenderMode}} event
+ * @returns {import('template-renderer').RenderResult}
+ */
+ _onRender({template, data, type}) {
+ return this._templateRenderer.render(template, data, type);
+ }
+
+ /**
+ * @param {{items: import('template-renderer').RenderMultiItem[]}} event
+ * @returns {import('core').Response<import('template-renderer').RenderResult>[]}
+ */
+ _onRenderMulti({items}) {
+ return this._templateRenderer.renderMulti(items);
+ }
+
+ /**
+ * @param {{data: import('template-renderer').CompositeRenderData, type: import('anki-templates').RenderMode}} event
+ * @returns {import('anki-templates').NoteData}
+ */
+ _onGetModifiedData({data, type}) {
+ const result = this._templateRenderer.getModifiedData(data, type);
+ return this._clone(result);
+ }
+
+ /**
+ * @template [T=unknown]
+ * @param {T} value
+ * @returns {T}
+ */
+ _clone(value) {
+ return parseJson(JSON.stringify(value));
+ }
+
+ /**
+ * @template {import('template-renderer-proxy').BackendApiNames} TName
+ * @param {Window} target
+ * @param {TName} action
+ * @param {import('template-renderer-proxy').BackendApiParams<TName>} params
+ * @param {?string} id
+ */
+ _postMessage(target, action, params, id) {
+ /** @type {import('template-renderer-proxy').BackendMessageAny} */
+ const data = {action, params, id};
+ target.postMessage(data, '*');
+ }
+}