diff options
| author | Ben Bridle <bridle.benjamin@gmail.com> | 2025-01-22 12:47:06 +1300 | 
|---|---|---|
| committer | Ben Bridle <bridle.benjamin@gmail.com> | 2025-01-22 12:55:22 +1300 | 
| commit | b511a1a64e9076a040baf3c02a1587c40d0ec172 (patch) | |
| tree | 3598712d164762cf81aa4eaf697bc434b93fcc8b | |
| parent | e9f25c69e1e37d038ab05e7a69ea961799615141 (diff) | |
| download | toaster-b511a1a64e9076a040baf3c02a1587c40d0ec172.zip | |
Remove 'appendix' from the links of appendix headings
If a heading is prefixed with 'Appendix #:', the link to that heading
will not include that prefix. This is to make it possible to rearrange
appendices in a document without breaking existing links.
| -rw-r--r-- | src/collect_files.rs | 5 | ||||
| -rw-r--r-- | src/generate_html.rs | 28 | 
2 files changed, 24 insertions, 9 deletions
| diff --git a/src/collect_files.rs b/src/collect_files.rs index 14bf0c3..de577cf 100644 --- a/src/collect_files.rs +++ b/src/collect_files.rs @@ -167,7 +167,7 @@ impl Website {                      let headings = document.blocks.iter()                          .filter_map(|block| if let Block::Heading { line, level } = block {                              let name = line.to_string(); -                            let url = make_url_safe(&name); +                            let url = make_url_safe(strip_appendix(&name));                              let level = level.to_owned();                              if !heading_set.insert(url.clone()) {                                  duplicates.insert(url.clone()); @@ -281,7 +281,8 @@ impl Website {              if page.full_url == path {                  let root = from.root();                  if let Some(heading) = heading { -                    if !page.headings.iter().any(|h| h.url == make_url_safe(heading)) { +                    let heading = make_url_safe(strip_appendix(heading)); +                    if !page.headings.iter().any(|h| h.url == heading) {                          warn!("Page {:?} contains link to nonexistent heading {heading:?} on page {path:?}", from.name());                      }                      return Some(format!("{root}{path}.{ext}#{heading}")); diff --git a/src/generate_html.rs b/src/generate_html.rs index e531854..0f520aa 100644 --- a/src/generate_html.rs +++ b/src/generate_html.rs @@ -111,10 +111,13 @@ pub fn document_to_html(document: &MarkdownDocument, page: &Page, website: &Webs      let root = page.root();      for block in &document.blocks {          match block { -            Block::Heading { level, line } => match level { -                Level::Heading1 => tag!("h1", line, format!("id='{}'", make_url_safe(&line_to_html!(line)))), -                Level::Heading2 => tag!("h2", line, format!("id='{}'", make_url_safe(&line_to_html!(line)))), -                Level::Heading3 => tag!("h3", line, format!("id='{}'", make_url_safe(&line_to_html!(line)))), +            Block::Heading { level, line } => { +                let id = make_url_safe(strip_appendix(&line_to_html!(line))); +                match level { +                    Level::Heading1 => tag!("h1", line, format!("id='{id}'")), +                    Level::Heading2 => tag!("h2", line, format!("id='{id}'")), +                    Level::Heading3 => tag!("h3", line, format!("id='{id}'")), +                }              }              Block::Paragraph(line) => tag!("p", line),              Block::Math(content) => html!("<div class='math'>{}</div>", sanitize_text(content, false)), @@ -269,8 +272,8 @@ fn line_to_html(line: &Line, page: &Page, website: &Website) -> String {                  let text = &sanitize_text(text, false); html.push_str(&format!("<span class='math'>{text}</span>")) }              Token::InternalLink(name) => {                  let (class, label, path) = match name.split_once('#') { -                    Some(("", heading)) => ("heading", heading, format!("#{heading}")), -                    Some((page, heading)) => ("page", heading, format!("{page}.html#{heading}")), +                    Some(("", heading)) => ("heading", heading, format!("#{}", strip_appendix(heading))), +                    Some((page, heading)) => ("page", heading, format!("{page}.html#{}", strip_appendix(heading))),                      _ => ("page", name.as_str(), format!("{name}.html")),                  };                  let mut path = make_url_safe(&path); @@ -287,7 +290,7 @@ fn line_to_html(line: &Line, page: &Page, website: &Website) -> String {                  }                  // Check that the heading exists.                  if class == "heading" { -                    let heading = path.strip_prefix('#').unwrap().to_string(); +                    let heading = path.strip_prefix('#').unwrap();                      if !page.headings.iter().any(|h| h.url == heading) {                          warn!("Page {from:?} contains link to nonexistent internal heading {heading:?}");                      } @@ -371,3 +374,14 @@ fn sanitize_text(text: &str, fancy: bool) -> String {      }      return output;  } + + +/// Remove a 'Appendix #: ' prefix from a string. +pub fn strip_appendix(text: &str) -> &str { +    if let Some((prefix, name)) = text.split_once(": ") { +        if prefix.starts_with("Appendix") { +            return name; +        } +    } +    return text; +} | 
