Skip to content

Commit 081af9f

Browse files
committed
Add html callback function
Closes lampsitter#73
1 parent 73ac543 commit 081af9f

File tree

6 files changed

+113
-5
lines changed

6 files changed

+113
-5
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Added
66

77
- Callback function `render_math_fn` for custom math rendering
8+
- Callback function `render_html_fn` for custom html rendering
89

910
### Fixed
1011

egui_commonmark/examples/html.rs

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//! Add `light` or `dark` to the end of the command to specify theme. Default
2+
//! is light. `cargo r --example html -- dark`
3+
4+
use eframe::egui;
5+
use egui_commonmark::*;
6+
use std::cell::RefCell;
7+
use std::rc::Rc;
8+
9+
struct App {
10+
cache: CommonMarkCache,
11+
/// To avoid id collisions
12+
counter: Rc<RefCell<usize>>,
13+
}
14+
15+
impl eframe::App for App {
16+
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
17+
*self.counter.as_ref().borrow_mut() = 0;
18+
19+
egui::CentralPanel::default().show(ctx, |ui| {
20+
egui::ScrollArea::vertical().show(ui, |ui| {
21+
CommonMarkViewer::new()
22+
.render_html_fn({
23+
let counter = Rc::clone(&self.counter);
24+
Some(&move |ui, html| {
25+
// For simplicity lets just hide the content regardless of what kind of
26+
// node it is.
27+
ui.collapsing(
28+
format!("Collapsed {}", counter.as_ref().borrow()),
29+
|ui| {
30+
ui.label(html);
31+
},
32+
);
33+
34+
*counter.as_ref().borrow_mut() += 1;
35+
})
36+
})
37+
.show(ui, &mut self.cache, EXAMPLE_TEXT);
38+
});
39+
});
40+
}
41+
}
42+
43+
fn main() -> eframe::Result {
44+
let mut args = std::env::args();
45+
args.next();
46+
47+
eframe::run_native(
48+
"Markdown viewer",
49+
eframe::NativeOptions::default(),
50+
Box::new(move |cc| {
51+
if let Some(theme) = args.next() {
52+
if theme == "light" {
53+
cc.egui_ctx.set_theme(egui::Theme::Light);
54+
} else if theme == "dark" {
55+
cc.egui_ctx.set_theme(egui::Theme::Dark);
56+
}
57+
}
58+
59+
cc.egui_ctx.style_mut(|style| {
60+
// Show the url of a hyperlink on hover
61+
style.url_in_tooltip = true;
62+
});
63+
64+
Ok(Box::new(App {
65+
cache: CommonMarkCache::default(),
66+
counter: Rc::new(RefCell::new(0)),
67+
}))
68+
}),
69+
)
70+
}
71+
72+
const EXAMPLE_TEXT: &str = r#"
73+
# Customized rendering using html
74+
<p>
75+
some text
76+
</p>
77+
78+
<p>
79+
some text 2
80+
</p>
81+
"#;

egui_commonmark/src/lib.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,15 @@ impl<'f> CommonMarkViewer<'f> {
209209
/// );
210210
/// }));
211211
/// ```
212-
pub fn render_math_fn(mut self, math_fn: Option<&'f RenderMathFn>) -> Self {
213-
self.options.math_fn = math_fn;
212+
pub fn render_math_fn(mut self, func: Option<&'f RenderMathFn>) -> Self {
213+
self.options.math_fn = func;
214+
self
215+
}
216+
217+
/// Allows custom handling of html. Enabling this will disable plain text rendering
218+
/// of html blocks. Nodes are included in the provided text
219+
pub fn render_html_fn(mut self, func: Option<&'f RenderHtmlFn>) -> Self {
220+
self.options.html_fn = func;
214221
self
215222
}
216223

egui_commonmark/src/parsers/pulldown.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ pub struct CommonMarkViewerInternal {
7272
image: Option<Image>,
7373
line: Newline,
7474
code_block: Option<CodeBlock>,
75+
76+
/// Only populated if the html_fn option has been set
77+
html_block: String,
7578
is_list_item: bool,
7679
def_list: DefinitionList,
7780
is_table: bool,
@@ -96,6 +99,7 @@ impl CommonMarkViewerInternal {
9699
is_list_item: false,
97100
def_list: Default::default(),
98101
code_block: None,
102+
html_block: String::new(),
99103
is_table: false,
100104
is_blockquote: false,
101105
checkbox_events: Vec::new(),
@@ -520,8 +524,13 @@ impl CommonMarkViewerInternal {
520524
pulldown_cmark::Event::InlineHtml(text) => {
521525
self.event_text(text, ui);
522526
}
523-
pulldown_cmark::Event::Html(node) => {
524-
self.event_text(node, ui);
527+
528+
pulldown_cmark::Event::Html(text) => {
529+
if options.html_fn.is_some() {
530+
self.html_block.push_str(&text);
531+
} else {
532+
self.event_text(text, ui);
533+
}
525534
}
526535
pulldown_cmark::Event::FootnoteReference(footnote) => {
527536
footnote_start(ui, &footnote);
@@ -755,7 +764,13 @@ impl CommonMarkViewerInternal {
755764
image.end(ui, options);
756765
}
757766
}
758-
pulldown_cmark::TagEnd::HtmlBlock => {}
767+
pulldown_cmark::TagEnd::HtmlBlock => {
768+
if let Some(html_fn) = options.html_fn {
769+
html_fn(ui, &self.html_block);
770+
self.html_block.clear();
771+
}
772+
}
773+
759774
pulldown_cmark::TagEnd::MetadataBlock(_) => {}
760775

761776
pulldown_cmark::TagEnd::DefinitionList => self.line.try_insert_end(ui),

egui_commonmark_backend/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ pub use misc::CommonMarkCache;
2828

2929
/// Takes [`egui::Ui`], the math text to be rendered and whether it is inline
3030
pub type RenderMathFn = dyn Fn(&mut egui::Ui, &str, bool);
31+
/// Takes [`egui::Ui`] and the html text to be rendered/used
32+
pub type RenderHtmlFn = dyn Fn(&mut egui::Ui, &str);

egui_commonmark_backend/src/misc.rs

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub struct CommonMarkOptions<'f> {
3232
/// Whether to present a mutable ui for things like checkboxes
3333
pub mutable: bool,
3434
pub math_fn: Option<&'f crate::RenderMathFn>,
35+
pub html_fn: Option<&'f crate::RenderHtmlFn>,
3536
}
3637

3738
impl<'f> std::fmt::Debug for CommonMarkOptions<'f> {
@@ -74,6 +75,7 @@ impl Default for CommonMarkOptions<'_> {
7475
alerts: AlertBundle::gfm(),
7576
mutable: false,
7677
math_fn: None,
78+
html_fn: None,
7779
}
7880
}
7981
}

0 commit comments

Comments
 (0)