From a4e206168dee6a3293ab9d3a72a51a430e705f7c Mon Sep 17 00:00:00 2001 From: ImUrX Date: Thu, 9 Feb 2023 03:58:54 -0300 Subject: [PATCH] Add working heading extension --- guide/src/format/markdown.md | 11 ++++++++++ src/renderer/html_handlebars/hbs_renderer.rs | 21 +++++++++++++++++--- src/utils/mod.rs | 1 + 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/guide/src/format/markdown.md b/guide/src/format/markdown.md index 963a1538..82ef8360 100644 --- a/guide/src/format/markdown.md +++ b/guide/src/format/markdown.md @@ -220,3 +220,14 @@ To enable it, see the [`output.html.curly-quotes`] config option. [tables]: https://github.github.com/gfm/#tables-extension- [task list extension]: https://github.github.com/gfm/#task-list-items-extension- [`output.html.curly-quotes`]: configuration/renderers.md#html-renderer-options + +### Heading attributes { #headingattributes .class1 .class2 } + +Headings can have a custom ID and classes. This let's you maintain the same ID even if you change the heading's text, it also let's you add multiple classes in the heading. + +Example: +```md +# Example heading { #first .class1 .class2 } +``` + +This makes the level 1 heading with the content `Example heading`, ID `first`, and classes `class1` and `class2`. Note that the attributes should be space-separated. diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index ee27fd13..ce2b7137 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -789,8 +789,10 @@ fn make_data( /// Goes through the rendered HTML, making sure all header tags have /// an anchor respectively so people can link to sections directly. fn build_header_links(html: &str) -> String { - static BUILD_HEADER_LINKS: Lazy = - Lazy::new(|| Regex::new(r"(.*?)").unwrap()); + static BUILD_HEADER_LINKS: Lazy = Lazy::new(|| { + Regex::new(r#"(.*?)"#).unwrap() + }); + static IGNORE_CLASS: &'static [&str] = &["menu-title"]; let mut id_counter = HashMap::new(); @@ -800,7 +802,20 @@ fn build_header_links(html: &str) -> String { .parse() .expect("Regex should ensure we only ever get numbers here"); - insert_link_into_header(level, &caps[2], &mut id_counter) + // Ignore .menu-title because now it's getting detected by the regex. + if let Some(classes) = caps.get(3) { + for class in classes.as_str().split(" ") { + if IGNORE_CLASS.contains(&class) { + return caps[0].to_string(); + } + } + } + + insert_link_into_header( + level, + caps.get(2).map(|x| x.as_str()).unwrap_or(&caps[4]), + &mut id_counter, + ) }) .into_owned() } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 9f67deda..9156916e 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -183,6 +183,7 @@ pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_, '_> { opts.insert(Options::ENABLE_FOOTNOTES); opts.insert(Options::ENABLE_STRIKETHROUGH); opts.insert(Options::ENABLE_TASKLISTS); + opts.insert(Options::ENABLE_HEADING_ATTRIBUTES); if curly_quotes { opts.insert(Options::ENABLE_SMART_PUNCTUATION); }