mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
add markdown flag for deck description
Needed so we can display consistently, and gradually transition over
This commit is contained in:
parent
333bbf3ee4
commit
9ce4b21935
9 changed files with 66 additions and 7 deletions
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"]:
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -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,6 +97,7 @@ 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 {
|
||||||
|
if normal.markdown_description {
|
||||||
let description = render_markdown(&normal.description);
|
let description = render_markdown(&normal.description);
|
||||||
// before allowing images, we'll need to handle relative image
|
// before allowing images, we'll need to handle relative image
|
||||||
// links on the various platforms
|
// links on the various platforms
|
||||||
|
@ -102,6 +105,9 @@ impl Deck {
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
Loading…
Reference in a new issue