1
Fork 0

Use custom header IDs if present (#40)

Co-authored-by: Jan-Erik Rediger <janerik@fnordig.de>
This commit is contained in:
Dominik Nakamura 2023-08-01 21:59:27 +09:00 committed by GitHub
parent e897dbffcc
commit 113362a944
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 20 deletions

View file

@ -140,11 +140,11 @@ fn add_toc(content: &str, cfg: &Config) -> Result<String> {
let mut current_header_level: Option<u32> = None;
let mut id_counter = HashMap::new();
let mut opts = Options::empty();
opts.insert(Options::ENABLE_TABLES);
opts.insert(Options::ENABLE_FOOTNOTES);
opts.insert(Options::ENABLE_STRIKETHROUGH);
opts.insert(Options::ENABLE_TASKLISTS);
let opts = Options::ENABLE_TABLES
| Options::ENABLE_FOOTNOTES
| Options::ENABLE_STRIKETHROUGH
| Options::ENABLE_TASKLISTS
| Options::ENABLE_HEADING_ATTRIBUTES;
let mark: Vec<Event> = Parser::new(&cfg.marker).collect();
log::trace!("Marker: {mark:?}");
@ -179,20 +179,27 @@ fn add_toc(content: &str, cfg: &Config) -> Result<String> {
current_header_level = Some(lvl as u32);
continue;
}
if let Event::End(Heading(..)) = e {
if let Event::End(Heading(_, fragment, _)) = e {
// Skip if this header is nested too deeply.
if let Some(level) = current_header_level.take() {
let header = current_header.clone();
let mut slug = mdbook::utils::normalize_id(&header);
let id_count = id_counter.entry(slug.clone()).or_insert(0);
let slug = if let Some(slug) = fragment {
// If a fragment is defined, take it as is, not trying to append an extra ID
// in case of duplicates (same behavior as mdBook)
slug.to_owned()
} else {
let mut slug = mdbook::utils::normalize_id(&header);
let id_count = id_counter.entry(slug.clone()).or_insert(0);
// Append unique ID if multiple headers with the same name exist
// to follow what mdBook does
if *id_count > 0 {
write!(slug, "-{id_count}").unwrap();
}
// Append unique ID if multiple headers with the same name exist
// to follow what mdBook does
if *id_count > 0 {
write!(slug, "-{id_count}").unwrap();
}
*id_count += 1;
*id_count += 1;
slug
};
if level <= cfg.max_level {
toc_content.push((level, header, slug));

11
tests/attributes.in.md Normal file
View file

@ -0,0 +1,11 @@
# Chapter
<!-- toc -->
# Header 1
## Header {#header-1-sub}
# Header 2
## Header {#header-2-sub .class1 .class2}

14
tests/attributes.out.md Normal file
View file

@ -0,0 +1,14 @@
# Chapter
* [Header 1](#header-1)
* [Header](#header-1-sub)
* [Header 2](#header-2)
* [Header](#header-2-sub)
# Header 1
## Header {#header-1-sub}
# Header 2
## Header {#header-2-sub .class1 .class2}

View file

@ -7,15 +7,17 @@ fn default<T: Default>() -> T {
}
fn with_marker<S: Into<String>>(marker: S) -> Config {
let mut cfg = Config::default();
cfg.marker = marker.into();
cfg
Config {
marker: marker.into(),
..Config::default()
}
}
fn with_max_level(level: u32) -> Config {
let mut cfg = Config::default();
cfg.max_level = level;
cfg
Config {
max_level: level,
..Config::default()
}
}
trait FromContent {
@ -169,3 +171,8 @@ fn empty_document() {
fn crlf() {
assert_toc!("crlf");
}
#[test]
fn attributes() {
assert_toc!("attributes");
}