Add language to Item::CodeBlock in markdown

This commit is contained in:
Héctor Ramón Jiménez 2025-02-05 01:33:16 +01:00
parent f8c71a20a9
commit c7711e59ab
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
2 changed files with 31 additions and 17 deletions

View file

@ -6,8 +6,8 @@ use iced::highlighter;
use iced::task; use iced::task;
use iced::time::{self, milliseconds, Instant}; use iced::time::{self, milliseconds, Instant};
use iced::widget::{ use iced::widget::{
self, button, center_x, horizontal_space, hover, image, markdown, pop, self, button, center_x, container, horizontal_space, hover, image,
right, row, scrollable, text_editor, toggler, markdown, pop, right, row, scrollable, text_editor, toggler,
}; };
use iced::window; use iced::window;
use iced::{Animation, Element, Fill, Font, Subscription, Task, Theme}; use iced::{Animation, Element, Fill, Font, Subscription, Task, Theme};
@ -294,20 +294,22 @@ impl<'a> markdown::Viewer<'a, Message> for CustomViewer<'a> {
fn code_block( fn code_block(
&self, &self,
settings: markdown::Settings, settings: markdown::Settings,
_language: Option<&'a str>,
code: &'a str, code: &'a str,
lines: &'a [markdown::Text], lines: &'a [markdown::Text],
) -> Element<'a, Message> { ) -> Element<'a, Message> {
let code_block = let code_block =
markdown::code_block(settings, code, lines, Message::LinkClicked); markdown::code_block(settings, lines, Message::LinkClicked);
let copy = button(icon::copy().size(12))
.padding(2)
.on_press_with(|| Message::Copy(code.to_owned()))
.style(button::text);
hover( hover(
code_block, code_block,
right( right(container(copy).style(container::dark))
button(icon::copy().size(12)) .padding(settings.spacing / 2),
.padding(settings.spacing / 2)
.on_press_with(|| Message::Copy(code.to_owned()))
.style(button::text),
),
) )
} }
} }

View file

@ -184,6 +184,8 @@ pub enum Item {
/// ///
/// You can enable the `highlighter` feature for syntax highlighting. /// You can enable the `highlighter` feature for syntax highlighting.
CodeBlock { CodeBlock {
/// The language of the code block, if any.
language: Option<String>,
/// The raw code of the code block. /// The raw code of the code block.
code: String, code: String,
/// The styled lines of text in the code block. /// The styled lines of text in the code block.
@ -464,6 +466,7 @@ fn parse_with<'a>(
let mut spans = Vec::new(); let mut spans = Vec::new();
let mut code = String::new(); let mut code = String::new();
let mut code_language = None;
let mut code_lines = Vec::new(); let mut code_lines = Vec::new();
let mut strong = false; let mut strong = false;
let mut emphasis = false; let mut emphasis = false;
@ -603,7 +606,7 @@ fn parse_with<'a>(
None None
} }
pulldown_cmark::Tag::CodeBlock( pulldown_cmark::Tag::CodeBlock(
pulldown_cmark::CodeBlockKind::Fenced(_language), pulldown_cmark::CodeBlockKind::Fenced(language),
) if !metadata && !table => { ) if !metadata && !table => {
#[cfg(feature = "highlighter")] #[cfg(feature = "highlighter")]
{ {
@ -613,9 +616,9 @@ fn parse_with<'a>(
.highlighter .highlighter
.take() .take()
.filter(|highlighter| { .filter(|highlighter| {
highlighter.language == _language.as_ref() highlighter.language == language.as_ref()
}) })
.unwrap_or_else(|| Highlighter::new(&_language)); .unwrap_or_else(|| Highlighter::new(&language));
highlighter.prepare(); highlighter.prepare();
@ -623,6 +626,9 @@ fn parse_with<'a>(
}); });
} }
code_language =
(!language.is_empty()).then(|| language.into_string());
let prev = if spans.is_empty() { let prev = if spans.is_empty() {
None None
} else { } else {
@ -734,6 +740,7 @@ fn parse_with<'a>(
state.borrow_mut(), state.borrow_mut(),
&mut stack, &mut stack,
Item::CodeBlock { Item::CodeBlock {
language: code_language.take(),
code: mem::take(&mut code), code: mem::take(&mut code),
lines: code_lines.drain(..).collect(), lines: code_lines.drain(..).collect(),
}, },
@ -1029,9 +1036,11 @@ where
viewer.heading(settings, level, text, index) viewer.heading(settings, level, text, index)
} }
Item::Paragraph(text) => viewer.paragraph(settings, text), Item::Paragraph(text) => viewer.paragraph(settings, text),
Item::CodeBlock { code, lines } => { Item::CodeBlock {
viewer.code_block(settings, code, lines) language,
} code,
lines,
} => viewer.code_block(settings, language.as_deref(), code, lines),
Item::List { start: None, items } => { Item::List { start: None, items } => {
viewer.unordered_list(settings, items) viewer.unordered_list(settings, items)
} }
@ -1171,7 +1180,6 @@ where
/// Displays a code block using the default look. /// Displays a code block using the default look.
pub fn code_block<'a, Message, Theme, Renderer>( pub fn code_block<'a, Message, Theme, Renderer>(
settings: Settings, settings: Settings,
_code: &'a str,
lines: &'a [Text], lines: &'a [Text],
on_link_click: impl Fn(Url) -> Message + Clone + 'a, on_link_click: impl Fn(Url) -> Message + Clone + 'a,
) -> Element<'a, Message, Theme, Renderer> ) -> Element<'a, Message, Theme, Renderer>
@ -1266,10 +1274,14 @@ where
fn code_block( fn code_block(
&self, &self,
settings: Settings, settings: Settings,
language: Option<&'a str>,
code: &'a str, code: &'a str,
lines: &'a [Text], lines: &'a [Text],
) -> Element<'a, Message, Theme, Renderer> { ) -> Element<'a, Message, Theme, Renderer> {
code_block(settings, code, lines, Self::on_link_click) let _language = language;
let _code = code;
code_block(settings, lines, Self::on_link_click)
} }
/// Displays an unordered list. /// Displays an unordered list.