add markdown flag for deck description

Needed so we can display consistently, and gradually transition over
This commit is contained in:
Damien Elmes 2021-02-09 18:46:48 +10:00
parent 333bbf3ee4
commit 9ce4b21935
9 changed files with 66 additions and 7 deletions

View file

@ -6,3 +6,5 @@ deck-config-used-by-decks =
*[other] { $decks } decks *[other] { $decks } decks
} }
deck-config-default-name = Default deck-config-default-name = Default
deck-config-description-markdown = Enable markdown+clean HTML
deck-config-description-markdown-hint = Will appear as text on Anki 2.1.40 and below.

View file

@ -867,6 +867,10 @@ table.review-log {{ {revlog_style} }}
def set_preferences(self, prefs: Preferences) -> None: def set_preferences(self, prefs: Preferences) -> None:
self._backend.set_preferences(prefs) self._backend.set_preferences(prefs)
def render_markdown(self, text: str, sanitize: bool = True) -> str:
"Not intended for public consumption at this time."
return self._backend.render_markdown(markdown=text, sanitize=sanitize)
# legacy name # legacy name
_Collection = Collection _Collection = Collection

View file

@ -236,6 +236,7 @@ class DeckConf(QDialog):
f.autoplaySounds.setChecked(c["autoplay"]) f.autoplaySounds.setChecked(c["autoplay"])
f.replayQuestion.setChecked(c.get("replayq", True)) f.replayQuestion.setChecked(c.get("replayq", True))
# description # description
f.enable_markdown.setChecked(self.deck.get("md", False))
f.desc.setPlainText(self.deck["desc"]) f.desc.setPlainText(self.deck["desc"])
gui_hooks.deck_conf_did_load_config(self, self.deck, self.conf) gui_hooks.deck_conf_did_load_config(self, self.deck, self.conf)
@ -320,6 +321,7 @@ class DeckConf(QDialog):
c["autoplay"] = f.autoplaySounds.isChecked() c["autoplay"] = f.autoplaySounds.isChecked()
c["replayq"] = f.replayQuestion.isChecked() c["replayq"] = f.replayQuestion.isChecked()
# description # description
self.deck["md"] = f.enable_markdown.isChecked()
self.deck["desc"] = f.desc.toPlainText() self.deck["desc"] = f.desc.toPlainText()
gui_hooks.deck_conf_will_save_config(self, self.deck, self.conf) gui_hooks.deck_conf_will_save_config(self, self.deck, self.conf)
self.mw.col.decks.save(self.deck) self.mw.col.decks.save(self.deck)

View file

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>623</width> <width>638</width>
<height>514</height> <height>514</height>
</rect> </rect>
</property> </property>
@ -670,6 +670,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="enable_markdown">
<property name="toolTip">
<string>DECK_CONFIG_DESCRIPTION_MARKDOWN_HINT</string>
</property>
<property name="text">
<string>DECK_CONFIG_DESCRIPTION_MARKDOWN</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QTextEdit" name="desc"/> <widget class="QTextEdit" name="desc"/>
</item> </item>

View file

@ -185,6 +185,8 @@ class Overview:
desc += " " + tr(TR.STUDYING_DELETING_THIS_DECK_FROM_THE_DECK) desc += " " + tr(TR.STUDYING_DELETING_THIS_DECK_FROM_THE_DECK)
else: else:
desc = deck.get("desc", "") desc = deck.get("desc", "")
if deck.get("md", False):
desc = self.mw.col.render_markdown(desc)
if not desc: if not desc:
return "<p>" return "<p>"
if deck["dyn"]: if deck["dyn"]:

View file

@ -207,11 +207,12 @@ service BackendService {
rpc FullDownload(SyncAuth) returns (Empty); rpc FullDownload(SyncAuth) returns (Empty);
rpc SyncServerMethod(SyncServerMethodIn) returns (Json); rpc SyncServerMethod(SyncServerMethodIn) returns (Json);
// translation/messages // translation/messages/text manipulation
rpc TranslateString(TranslateStringIn) returns (String); rpc TranslateString(TranslateStringIn) returns (String);
rpc FormatTimespan(FormatTimespanIn) returns (String); rpc FormatTimespan(FormatTimespanIn) returns (String);
rpc I18nResources(Empty) returns (Json); rpc I18nResources(Empty) returns (Json);
rpc RenderMarkdown(RenderMarkdownIn) returns (String);
// tags // tags
@ -303,6 +304,8 @@ message DeckCommon {
// but not currently used for anything // but not currently used for anything
int32 learning_studied = 6; int32 learning_studied = 6;
reserved 8 to 13;
bytes other = 255; bytes other = 255;
} }
@ -318,6 +321,9 @@ message NormalDeck {
uint32 extend_new = 2; uint32 extend_new = 2;
uint32 extend_review = 3; uint32 extend_review = 3;
string description = 4; string description = 4;
bool markdown_description = 5;
reserved 6 to 11;
} }
message FilteredDeck { message FilteredDeck {
@ -1245,3 +1251,8 @@ message SetConfigStringIn {
Config.String.Key key = 1; Config.String.Key key = 1;
string value = 2; string value = 2;
} }
message RenderMarkdownIn {
string markdown = 1;
bool sanitize = 2;
}

View file

@ -23,6 +23,7 @@ use crate::{
latex::{extract_latex, extract_latex_expanding_clozes, ExtractedLatex}, latex::{extract_latex, extract_latex_expanding_clozes, ExtractedLatex},
log, log,
log::default_logger, log::default_logger,
markdown::render_markdown,
media::check::MediaChecker, media::check::MediaChecker,
media::sync::MediaSyncProgress, media::sync::MediaSyncProgress,
media::MediaManager, media::MediaManager,
@ -48,7 +49,7 @@ use crate::{
SyncStage, SyncStage,
}, },
template::RenderedNode, template::RenderedNode,
text::{escape_anki_wildcards, extract_av_tags, strip_av_tags, AVTag}, text::{escape_anki_wildcards, extract_av_tags, sanitize_html_no_images, strip_av_tags, AVTag},
timestamp::TimestampSecs, timestamp::TimestampSecs,
types::Usn, types::Usn,
}; };
@ -1402,6 +1403,15 @@ impl BackendService for Backend {
.map_err(Into::into) .map_err(Into::into)
} }
fn render_markdown(&self, input: pb::RenderMarkdownIn) -> BackendResult<pb::String> {
let mut text = render_markdown(&input.markdown);
if input.sanitize {
// currently no images
text = sanitize_html_no_images(&text);
}
Ok(text.into())
}
// tags // tags
//------------------------------------------------------------------- //-------------------------------------------------------------------

View file

@ -39,6 +39,8 @@ impl Deck {
pub fn new_normal() -> Deck { pub fn new_normal() -> Deck {
let mut norm = NormalDeck::default(); let mut norm = NormalDeck::default();
norm.config_id = 1; norm.config_id = 1;
// enable in the future
// norm.markdown_description = true;
Deck { Deck {
id: DeckID(0), id: DeckID(0),
@ -95,10 +97,14 @@ impl Deck {
pub fn rendered_description(&self) -> String { pub fn rendered_description(&self) -> String {
if let DeckKind::Normal(normal) = &self.kind { if let DeckKind::Normal(normal) = &self.kind {
let description = render_markdown(&normal.description); if normal.markdown_description {
// before allowing images, we'll need to handle relative image let description = render_markdown(&normal.description);
// links on the various platforms // before allowing images, we'll need to handle relative image
sanitize_html_no_images(&description) // links on the various platforms
sanitize_html_no_images(&description)
} else {
String::new()
}
} else { } else {
String::new() String::new()
} }

View file

@ -75,6 +75,10 @@ mod dynfix {
} }
} }
fn is_false(b: &bool) -> bool {
!b
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct DeckCommonSchema11 { pub struct DeckCommonSchema11 {
#[serde(deserialize_with = "deserialize_number_from_string")] #[serde(deserialize_with = "deserialize_number_from_string")]
@ -95,6 +99,8 @@ pub struct DeckCommonSchema11 {
browser_collapsed: bool, browser_collapsed: bool,
#[serde(default)] #[serde(default)]
desc: String, desc: String,
#[serde(default, rename = "md", skip_serializing_if = "is_false")]
markdown_description: bool,
#[serde(rename = "dyn")] #[serde(rename = "dyn")]
dynamic: u8, dynamic: u8,
#[serde(flatten)] #[serde(flatten)]
@ -218,6 +224,7 @@ impl Default for NormalDeckSchema11 {
today: Default::default(), today: Default::default(),
other: Default::default(), other: Default::default(),
dynamic: 0, dynamic: 0,
markdown_description: false,
}, },
conf: 1, conf: 1,
extend_new: 0, extend_new: 0,
@ -292,6 +299,7 @@ impl From<NormalDeckSchema11> for NormalDeck {
config_id: deck.conf, config_id: deck.conf,
extend_new: deck.extend_new.max(0) as u32, extend_new: deck.extend_new.max(0) as u32,
extend_review: deck.extend_rev.max(0) as u32, extend_review: deck.extend_rev.max(0) as u32,
markdown_description: deck.common.markdown_description,
description: deck.common.desc, description: deck.common.desc,
} }
} }
@ -365,6 +373,10 @@ impl From<Deck> for DeckCommonSchema11 {
} else { } else {
0 0
}, },
markdown_description: match &deck.kind {
DeckKind::Normal(n) => n.markdown_description,
DeckKind::Filtered(_) => false,
},
desc: match deck.kind { desc: match deck.kind {
DeckKind::Normal(n) => n.description, DeckKind::Normal(n) => n.description,
DeckKind::Filtered(_) => String::new(), DeckKind::Filtered(_) => String::new(),