summaryrefslogtreecommitdiff
path: root/ext/js/display
diff options
context:
space:
mode:
authorStefanVukovic99 <stefanvukovic44@gmail.com>2024-06-20 19:27:02 +0200
committerGitHub <noreply@github.com>2024-06-20 17:27:02 +0000
commitd2c930a94d6e445053bcb5e5bb629851165425fc (patch)
tree94ff7034e7d3ab36ed663f353aeb5486bd294d1c /ext/js/display
parent1a866b3997310a04fc146b91eb47a59a3f049589 (diff)
support css file in dictionaries (#1080)
* get styles in db * get styles in settings * use styles * fix test * scope * fix comma separated * escape dict name in css selector * g regex * get styles in anki * fix tests * more specificity * whitespace * test importing * test handlebars * add styles to glossary-first
Diffstat (limited to 'ext/js/display')
-rw-r--r--ext/js/display/display-anki.js21
-rw-r--r--ext/js/display/display.js38
2 files changed, 56 insertions, 3 deletions
diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js
index fa82a7b6..68a6654c 100644
--- a/ext/js/display/display-anki.js
+++ b/ext/js/display/display-anki.js
@@ -91,6 +91,8 @@ export class DisplayAnki {
this._noteTags = [];
/** @type {Map<import('display-anki').CreateMode, import('settings').AnkiNoteOptions>} */
this._modeOptions = new Map();
+ /** @type {import('settings').DictionariesOptions} */
+ this._dictionaries = [];
/** @type {Map<import('dictionary').DictionaryEntryType, import('display-anki').CreateMode[]>} */
this._dictionaryEntryTypeModeMap = new Map([
['kanji', ['kanji']],
@@ -147,6 +149,7 @@ export class DisplayAnki {
glossaryLayoutMode: this._glossaryLayoutMode,
compactTags: this._compactTags,
marker: 'test',
+ dictionaryStylesMap: this._getDictionaryStylesMap(),
});
} catch (e) {
ankiNoteDataException = e;
@@ -191,6 +194,7 @@ export class DisplayAnki {
_onOptionsUpdated({options}) {
const {
general: {resultOutputMode, glossaryLayoutMode, compactTags},
+ dictionaries,
anki: {
tags,
duplicateScope,
@@ -227,6 +231,7 @@ export class DisplayAnki {
this._modeOptions.set('kanji', kanji);
this._modeOptions.set('term-kanji', terms);
this._modeOptions.set('term-kana', terms);
+ this._dictionaries = dictionaries;
void this._updateAnkiFieldTemplates(options);
}
@@ -808,6 +813,7 @@ export class DisplayAnki {
const details = this._ankiNoteBuilder.getDictionaryEntryDetailsForNote(dictionaryEntry);
const audioDetails = this._getAnkiNoteMediaAudioDetails(details);
const optionsContext = this._display.getOptionsContext();
+ const dictionaryStylesMap = this._getDictionaryStylesMap();
const {note, errors, requirements: outputRequirements} = await this._ankiNoteBuilder.createNote({
dictionaryEntry,
@@ -836,11 +842,26 @@ export class DisplayAnki {
},
},
requirements,
+ dictionaryStylesMap,
});
return {note, errors, requirements: outputRequirements};
}
/**
+ * @returns {Map<string, string>}
+ */
+ _getDictionaryStylesMap() {
+ const styleMap = new Map();
+ for (const dictionary of this._dictionaries) {
+ const {name, styles} = dictionary;
+ if (typeof styles === 'string') {
+ styleMap.set(name, styles);
+ }
+ }
+ return styleMap;
+ }
+
+ /**
* @param {boolean} isTerms
* @returns {import('display-anki').CreateMode[]}
*/
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index 6b3838e5..ebd11e0a 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -1152,7 +1152,7 @@ export class Display extends EventDispatcher {
*/
_setTheme(options) {
const {general} = options;
- const {popupTheme} = general;
+ const {popupTheme, popupOuterTheme} = general;
/** @type {string} */
let pageType = this._pageType;
try {
@@ -1169,10 +1169,42 @@ export class Display extends EventDispatcher {
log.error(e);
}
this._themeController.theme = popupTheme;
- this._themeController.outerTheme = general.popupOuterTheme;
+ this._themeController.outerTheme = popupOuterTheme;
this._themeController.siteOverride = pageType === 'search' || pageType === 'popupPreview';
this._themeController.updateTheme();
- this.setCustomCss(general.customPopupCss);
+ const customCss = this._getCustomCss(options);
+ this.setCustomCss(customCss);
+ }
+
+ /**
+ * @param {import('settings').ProfileOptions} options
+ * @returns {string}
+ */
+ _getCustomCss(options) {
+ const {general: {customPopupCss}, dictionaries} = options;
+ let customCss = customPopupCss;
+ for (const {name, enabled, styles = ''} of dictionaries) {
+ if (enabled) {
+ customCss += '\n' + this._addScopeToCss(styles, name);
+ }
+ }
+ this.setCustomCss(customCss);
+ return customCss;
+ }
+
+ /**
+ * @param {string} css
+ * @param {string} dictionaryTitle
+ * @returns {string}
+ */
+ _addScopeToCss(css, dictionaryTitle) {
+ const escapedTitle = dictionaryTitle
+ .replace(/\\/g, '\\\\')
+ .replace(/"/g, '\\"');
+
+ const regex = /([^\r\n,{}]+)(\s*[,{])/g;
+ const replacement = `[data-dictionary="${escapedTitle}"] $1$2`;
+ return css.replace(regex, replacement);
}
/**