/* * Copyright (C) 2021 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/>. */ /* global * DictionaryDataUtil */ /** * This class represents the data that is exposed to the Anki template renderer. * The public properties and data should be backwards compatible. */ class AnkiNoteData { constructor({ definition, resultOutputMode, mode, glossaryLayoutMode, compactTags, context, injectedMedia=null }, marker) { this._definition = definition; this._resultOutputMode = resultOutputMode; this._mode = mode; this._glossaryLayoutMode = glossaryLayoutMode; this._compactTags = compactTags; this._context = context; this._marker = marker; this._injectedMedia = injectedMedia; this._pitches = null; this._pitchCount = null; this._uniqueExpressions = null; this._uniqueReadings = null; this._publicContext = null; this._cloze = null; this._prepareDefinition(definition, injectedMedia, context); } get marker() { return this._marker; } set marker(value) { this._marker = value; } get definition() { return this._definition; } get uniqueExpressions() { if (this._uniqueExpressions === null) { this._uniqueExpressions = this._getUniqueExpressions(); } return this._uniqueExpressions; } get uniqueReadings() { if (this._uniqueReadings === null) { this._uniqueReadings = this._getUniqueReadings(); } return this._uniqueReadings; } get pitches() { if (this._pitches === null) { this._pitches = DictionaryDataUtil.getPitchAccentInfos(this._definition); } return this._pitches; } get pitchCount() { if (this._pitchCount === null) { this._pitchCount = this.pitches.reduce((i, v) => i + v.pitches.length, 0); } return this._pitchCount; } get group() { return this._resultOutputMode === 'group'; } get merge() { return this._resultOutputMode === 'merge'; } get modeTermKanji() { return this._mode === 'term-kanji'; } get modeTermKana() { return this._mode === 'term-kana'; } get modeKanji() { return this._mode === 'kanji'; } get compactGlossaries() { return this._glossaryLayoutMode === 'compact'; } get glossaryLayoutMode() { return this._glossaryLayoutMode; } get compactTags() { return this._compactTags; } get context() { if (this._publicContext === null) { this._publicContext = this._getPublicContext(); } return this._publicContext; } createPublic() { const self = this; return { get marker() { return self.marker; }, set marker(value) { self.marker = value; }, get definition() { return self.definition; }, get glossaryLayoutMode() { return self.glossaryLayoutMode; }, get compactTags() { return self.compactTags; }, get group() { return self.group; }, get merge() { return self.merge; }, get modeTermKanji() { return self.modeTermKanji; }, get modeTermKana() { return self.modeTermKana; }, get modeKanji() { return self.modeKanji; }, get compactGlossaries() { return self.compactGlossaries; }, get uniqueExpressions() { return self.uniqueExpressions; }, get uniqueReadings() { return self.uniqueReadings; }, get pitches() { return self.pitches; }, get pitchCount() { return self.pitchCount; }, get context() { return self.context; } }; } // Private _asObject(value) { return (typeof value === 'object' && value !== null ? value : {}); } _getUniqueExpressions() { const results = new Set(); const definition = this._definition; if (definition.type !== 'kanji') { for (const {expression} of definition.expressions) { results.add(expression); } } return [...results]; } _getUniqueReadings() { const results = new Set(); const definition = this._definition; if (definition.type !== 'kanji') { for (const {reading} of definition.expressions) { results.add(reading); } } return [...results]; } _getPublicContext() { let {documentTitle} = this._asObject(this._context); if (typeof documentTitle !== 'string') { documentTitle = ''; } return { document: { title: documentTitle } }; } _getCloze() { const {sentence} = this._asObject(this._context); let {text, offset} = this._asObject(sentence); if (typeof text !== 'string') { text = ''; } if (typeof offset !== 'number') { offset = 0; } const definition = this._definition; const source = definition.type === 'kanji' ? definition.character : definition.rawSource; return { sentence: text, prefix: text.substring(0, offset), body: text.substring(offset, offset + source.length), suffix: text.substring(offset + source.length) }; } _getClozeCached() { if (this._cloze === null) { this._cloze = this._getCloze(); } return this._cloze; } _prepareDefinition(definition, injectedMedia, context) { const { screenshotFileName=null, clipboardImageFileName=null, clipboardText=null, audioFileName=null } = this._asObject(injectedMedia); let {url} = this._asObject(context); if (typeof url !== 'string') { url = ''; } definition.screenshotFileName = screenshotFileName; definition.clipboardImageFileName = clipboardImageFileName; definition.clipboardText = clipboardText; definition.audioFileName = audioFileName; definition.url = url; Object.defineProperty(definition, 'cloze', { configurable: true, enumerable: true, get: this._getClozeCached.bind(this) }); } }