Add working heading extension

This commit is contained in:
ImUrX 2023-02-09 03:58:54 -03:00 committed by Eric Huss
parent 4f1b5eae54
commit a4e206168d
3 changed files with 30 additions and 3 deletions

View File

@ -220,3 +220,14 @@ To enable it, see the [`output.html.curly-quotes`] config option.
[tables]: https://github.github.com/gfm/#tables-extension- [tables]: https://github.github.com/gfm/#tables-extension-
[task list extension]: https://github.github.com/gfm/#task-list-items-extension- [task list extension]: https://github.github.com/gfm/#task-list-items-extension-
[`output.html.curly-quotes`]: configuration/renderers.md#html-renderer-options [`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.

View File

@ -789,8 +789,10 @@ fn make_data(
/// Goes through the rendered HTML, making sure all header tags have /// Goes through the rendered HTML, making sure all header tags have
/// an anchor respectively so people can link to sections directly. /// an anchor respectively so people can link to sections directly.
fn build_header_links(html: &str) -> String { fn build_header_links(html: &str) -> String {
static BUILD_HEADER_LINKS: Lazy<Regex> = static BUILD_HEADER_LINKS: Lazy<Regex> = Lazy::new(|| {
Lazy::new(|| Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap()); Regex::new(r#"<h(\d)(?: id="([^"]+)")?(?: class="([^"]+)")?>(.*?)</h\d>"#).unwrap()
});
static IGNORE_CLASS: &'static [&str] = &["menu-title"];
let mut id_counter = HashMap::new(); let mut id_counter = HashMap::new();
@ -800,7 +802,20 @@ fn build_header_links(html: &str) -> String {
.parse() .parse()
.expect("Regex should ensure we only ever get numbers here"); .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() .into_owned()
} }

View File

@ -183,6 +183,7 @@ pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_, '_> {
opts.insert(Options::ENABLE_FOOTNOTES); opts.insert(Options::ENABLE_FOOTNOTES);
opts.insert(Options::ENABLE_STRIKETHROUGH); opts.insert(Options::ENABLE_STRIKETHROUGH);
opts.insert(Options::ENABLE_TASKLISTS); opts.insert(Options::ENABLE_TASKLISTS);
opts.insert(Options::ENABLE_HEADING_ATTRIBUTES);
if curly_quotes { if curly_quotes {
opts.insert(Options::ENABLE_SMART_PUNCTUATION); opts.insert(Options::ENABLE_SMART_PUNCTUATION);
} }