From ac4c88afdc84de48f19ff0474b2be0a7ed4965dd Mon Sep 17 00:00:00 2001 From: Matthias Metelka <62722460+kleinerpirat@users.noreply.github.com> Date: Thu, 18 Aug 2022 07:48:34 +0200 Subject: [PATCH] Merge branch 'main' into color-palette --- ftl/core/editing.ftl | 1 + ftl/core/fields.ftl | 1 + proto/anki/notetypes.proto | 1 + qt/aqt/data/web/css/webview.scss | 7 +- qt/aqt/editor.py | 28 +- qt/aqt/fields.py | 5 + qt/aqt/forms/fields.ui | 76 +++--- rslib/src/notetype/fields.rs | 1 + rslib/src/notetype/schema11.rs | 9 +- sass/base.scss | 2 +- ts/components/WithTooltip.svelte | 11 - ts/editable/mathjax-element.ts | 7 + ts/editor/EditorField.svelte | 1 + ts/editor/FieldDescription.svelte | 7 +- ts/editor/NoteEditor.svelte | 22 +- ts/editor/editor-toolbar/LatexButton.svelte | 10 + .../editor-toolbar/RemoveFormatButton.svelte | 93 ++++--- .../rich-text-input/RichTextInput.svelte | 13 +- ts/editor/surround.ts | 243 +++++++++++------- ts/lib/functional.ts | 4 + 20 files changed, 337 insertions(+), 205 deletions(-) diff --git a/ftl/core/editing.ftl b/ftl/core/editing.ftl index 6e4d9086a..96e5af0e5 100644 --- a/ftl/core/editing.ftl +++ b/ftl/core/editing.ftl @@ -58,6 +58,7 @@ editing-toggle-visual-editor = Toggle Visual Editor editing-underline-text = Underline text editing-unordered-list = Unordered list editing-warning-cloze-deletions-will-not-work = Warning, cloze deletions will not work until you switch the type at the top to Cloze. +editing-toggle-mathjax-rendering = Toggle MathJax Rendering ## You don't need to translate these strings, as they will be replaced with different ones soon. diff --git a/ftl/core/fields.ftl b/ftl/core/fields.ftl index 3f8b3581f..dfcb6f3f0 100644 --- a/ftl/core/fields.ftl +++ b/ftl/core/fields.ftl @@ -10,6 +10,7 @@ fields-font = Font: fields-new-position-1 = New position (1...{ $val }): fields-notes-require-at-least-one-field = Notes require at least one field. fields-reverse-text-direction-rtl = Reverse text direction (RTL) +fields-html-by-default = Use HTML editor by default fields-size = Size: fields-sort-by-this-field-in-the = Sort by this field in the browser fields-that-field-name-is-already-used = That field name is already used. diff --git a/proto/anki/notetypes.proto b/proto/anki/notetypes.proto index 6bd9d37ab..ff9f0ee0c 100644 --- a/proto/anki/notetypes.proto +++ b/proto/anki/notetypes.proto @@ -72,6 +72,7 @@ message Notetype { string font_name = 3; uint32 font_size = 4; string description = 5; + bool plain_text = 6; bytes other = 255; } diff --git a/qt/aqt/data/web/css/webview.scss b/qt/aqt/data/web/css/webview.scss index ee0f9cd4b..71a377303 100644 --- a/qt/aqt/data/web/css/webview.scss +++ b/qt/aqt/data/web/css/webview.scss @@ -14,8 +14,8 @@ body { color: var(--text-fg); background: var(--window-bg); - margin: 1em; transition: opacity 0.5s ease-out; + margin: 2em; overscroll-behavior: none; } @@ -24,11 +24,6 @@ a { text-decoration: none; } -body { - margin: 2em; - overscroll-behavior: none; -} - h1 { margin-bottom: 0.2em; } diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index d70acb870..034353023 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -125,6 +125,7 @@ class Editor: self.card: Card | None = None self._init_links() self.setupOuter() + self.add_webview() self.setupWeb() self.setupShortcuts() gui_hooks.editor_did_init(self) @@ -139,11 +140,12 @@ class Editor: self.widget.setLayout(l) self.outerLayout = l - def setupWeb(self) -> None: + def add_webview(self) -> None: self.web = EditorWebView(self.widget, self) self.web.set_bridge_command(self.onBridgeCmd, self) self.outerLayout.addWidget(self.web, 1) + def setupWeb(self) -> None: if self.editorMode == EditorMode.ADD_CARDS: file = "note_creator" elif self.editorMode == EditorMode.BROWSER: @@ -499,6 +501,7 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too ] flds = self.note.note_type()["flds"] + plain_texts = [fld.get("plainText", False) for fld in flds] descriptions = [fld.get("description", "") for fld in flds] self.widget.show() @@ -519,14 +522,26 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too text_color = self.mw.pm.profile.get("lastTextColor", "#00f") highlight_color = self.mw.pm.profile.get("lastHighlightColor", "#00f") - js = "setFields({}); setDescriptions({}); setFonts({}); focusField({}); setNoteId({}); setColorButtons({}); setTags({}); ".format( + js = """ + setFields({}); + setPlainTexts({}); + setDescriptions({}); + setFonts({}); + focusField({}); + setNoteId({}); + setColorButtons({}); + setTags({}); + setMathjaxEnabled({}); + """.format( json.dumps(data), + json.dumps(plain_texts), json.dumps(descriptions), json.dumps(self.fonts()), json.dumps(focusTo), json.dumps(self.note.id), json.dumps([text_color, highlight_color]), json.dumps(self.note.tags), + json.dumps(self.mw.col.get_config("renderMathjax", True)), ) if self.addMode: @@ -1130,6 +1145,14 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too def insertMathjaxChemistry(self) -> None: self.web.eval("wrap('\\\\(\\\\ce{', '}\\\\)');") + def toggleMathjax(self) -> None: + self.mw.col.set_config( + "renderMathjax", not self.mw.col.get_config("renderMathjax", False) + ) + # hackily redraw the page + self.setupWeb() + self.loadNoteKeepingFocus() + # Links from HTML ###################################################################### @@ -1156,6 +1179,7 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too mathjaxInline=Editor.insertMathjaxInline, mathjaxBlock=Editor.insertMathjaxBlock, mathjaxChemistry=Editor.insertMathjaxChemistry, + toggleMathjax=Editor.toggleMathjax, ) diff --git a/qt/aqt/fields.py b/qt/aqt/fields.py index a3c25f938..7bbddfe7b 100644 --- a/qt/aqt/fields.py +++ b/qt/aqt/fields.py @@ -243,6 +243,7 @@ class FieldDialog(QDialog): f.fontSize.setValue(fld["size"]) f.sortField.setChecked(self.model["sortf"] == fld["ord"]) f.rtl.setChecked(fld["rtl"]) + f.plainTextByDefault.setChecked(fld["plainText"]) f.fieldDescription.setText(fld.get("description", "")) def saveField(self) -> None: @@ -264,6 +265,10 @@ class FieldDialog(QDialog): if fld["rtl"] != rtl: fld["rtl"] = rtl self.change_tracker.mark_basic() + plain_text = f.plainTextByDefault.isChecked() + if fld["plainText"] != plain_text: + fld["plainText"] = plain_text + self.change_tracker.mark_basic() desc = f.fieldDescription.text() if fld.get("description", "") != desc: fld["description"] = desc diff --git a/qt/aqt/forms/fields.ui b/qt/aqt/forms/fields.ui index 81f3ce3e0..cb2a04b1b 100644 --- a/qt/aqt/forms/fields.ui +++ b/qt/aqt/forms/fields.ui @@ -6,8 +6,8 @@ 0 0 - 586 - 376 + 598 + 378 @@ -84,13 +84,6 @@ - - - - fields_editing_font - - - @@ -98,13 +91,27 @@ - - - - 5 + + + + + 0 + 25 + - - 300 + + + + + + fields_editing_font + + + + + + + fields_description_placeholder @@ -115,13 +122,6 @@ - - - - fields_sort_by_this_field_in_the - - - @@ -135,20 +135,30 @@ - - - - - 0 - 25 - + + + + 5 + + + 300 - - - - fields_description_placeholder + + + + fields_sort_by_this_field_in_the + + + + + + + true + + + fields_html_by_default diff --git a/rslib/src/notetype/fields.rs b/rslib/src/notetype/fields.rs index 1b126f0cf..ca1908e3d 100644 --- a/rslib/src/notetype/fields.rs +++ b/rslib/src/notetype/fields.rs @@ -42,6 +42,7 @@ impl NoteField { config: NoteFieldConfig { sticky: false, rtl: false, + plain_text: false, font_name: "Arial".into(), font_size: 20, description: "".into(), diff --git a/rslib/src/notetype/schema11.rs b/rslib/src/notetype/schema11.rs index 5db53d56b..0fab7e560 100644 --- a/rslib/src/notetype/schema11.rs +++ b/rslib/src/notetype/schema11.rs @@ -161,7 +161,7 @@ impl From for NotetypeSchema11 { /// See [crate::deckconfig::schema11::clear_other_duplicates()]. fn clear_other_field_duplicates(other: &mut HashMap) { - for key in &["description"] { + for key in &["description", "plainText"] { other.remove(*key); } } @@ -195,6 +195,7 @@ impl From for CardRequirementSchema11 { } #[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] pub struct NoteFieldSchema11 { pub(crate) name: String, pub(crate) ord: Option, @@ -211,6 +212,9 @@ pub struct NoteFieldSchema11 { #[serde(default, deserialize_with = "default_on_invalid")] pub(crate) description: String, + #[serde(default, deserialize_with = "default_on_invalid")] + pub(crate) plain_text: bool, + #[serde(flatten)] pub(crate) other: HashMap, } @@ -222,6 +226,7 @@ impl Default for NoteFieldSchema11 { ord: None, sticky: false, rtl: false, + plain_text: false, font: "Arial".to_string(), size: 20, description: String::new(), @@ -238,6 +243,7 @@ impl From for NoteField { config: NoteFieldConfig { sticky: f.sticky, rtl: f.rtl, + plain_text: f.plain_text, font_name: f.font, font_size: f.size as u32, description: f.description, @@ -259,6 +265,7 @@ impl From for NoteFieldSchema11 { ord: p.ord.map(|o| o as u16), sticky: conf.sticky, rtl: conf.rtl, + plain_text: conf.plain_text, font: conf.font_name, size: conf.font_size as u16, description: conf.description, diff --git a/sass/base.scss b/sass/base.scss index fa5e21cf1..ab8054a6b 100644 --- a/sass/base.scss +++ b/sass/base.scss @@ -32,7 +32,7 @@ $utilities: ( flex-basis: 75%; } -* { +body { overscroll-behavior: none; } diff --git a/ts/components/WithTooltip.svelte b/ts/components/WithTooltip.svelte index 6adbb7c11..6ad68a673 100644 --- a/ts/components/WithTooltip.svelte +++ b/ts/components/WithTooltip.svelte @@ -38,17 +38,6 @@ } onDestroy(() => tooltipObject?.dispose()); - - // hack to update field description tooltips - let previousTooltip: string = tooltip; - $: if (tooltip !== previousTooltip) { - previousTooltip = tooltip; - if (tooltipObject !== undefined) { - const element: HTMLElement = tooltipObject["_element"]; - tooltipObject.dispose(); - createTooltip(element); - } - } diff --git a/ts/editable/mathjax-element.ts b/ts/editable/mathjax-element.ts index 247ccb458..1c1480e50 100644 --- a/ts/editable/mathjax-element.ts +++ b/ts/editable/mathjax-element.ts @@ -20,6 +20,10 @@ function trimBreaks(text: string): string { .replace(/\n*$/, ""); } +export const mathjaxConfig = { + enabled: true, +}; + export const Mathjax: DecoratedElementConstructor = class Mathjax extends HTMLElement implements DecoratedElement @@ -41,6 +45,9 @@ export const Mathjax: DecoratedElementConstructor = class Mathjax } static toUndecorated(stored: string): string { + if (!mathjaxConfig.enabled) { + return stored; + } return stored .replace(mathjaxBlockDelimiterPattern, (_match: string, text: string) => { const trimmed = trimBreaks(text); diff --git a/ts/editor/EditorField.svelte b/ts/editor/EditorField.svelte index 447460e10..23588ffb6 100644 --- a/ts/editor/EditorField.svelte +++ b/ts/editor/EditorField.svelte @@ -12,6 +12,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html fontFamily: string; fontSize: number; direction: "ltr" | "rtl"; + plainText: boolean; description: string; } diff --git a/ts/editor/FieldDescription.svelte b/ts/editor/FieldDescription.svelte index af2cd4270..41f2cd105 100644 --- a/ts/editor/FieldDescription.svelte +++ b/ts/editor/FieldDescription.svelte @@ -32,10 +32,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html