summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/collect_files.rs30
-rw-r--r--src/generate_html.rs26
2 files changed, 40 insertions, 16 deletions
diff --git a/src/collect_files.rs b/src/collect_files.rs
index cb785fc..30dcb98 100644
--- a/src/collect_files.rs
+++ b/src/collect_files.rs
@@ -33,6 +33,7 @@ pub struct Heading {
pub name: String,
pub url: String,
pub level: Level,
+ pub block_id: usize,
}
pub struct StaticItem {
@@ -199,23 +200,44 @@ impl Website {
"md" => {
let markdown = std::fs::read_to_string(&source_path).unwrap();
let document = MarkdownDocument::from_str(&markdown);
+ // Collect headings, check for duplicates.
let mut heading_set = HashSet::new();
let mut duplicates = HashSet::new();
- let headings = document.blocks.iter()
- .filter_map(|block| if let Block::Heading { line, level } = block {
+ let mut headings: Vec<_> = document.blocks.iter().enumerate()
+ .filter_map(|(block_id, block)| if let Block::Heading { line, level } = block {
let name = line.to_string();
let url = make_url_safe(strip_appendix(&name));
let level = level.to_owned();
if !heading_set.insert(url.clone()) {
duplicates.insert(url.clone());
}
- Some(Heading { name, url, level })
+ Some(Heading { name, url, level, block_id })
} else {
None
}).collect();
+
+ // Namespace any duplicate headings to the parent h1 heading.
+ let mut parent_url = String::new();
+ for heading in &mut headings {
+ if let Level::Heading1 = heading.level {
+ parent_url = heading.url.clone();
+ }
+ if duplicates.contains(&heading.url) {
+ heading.url = format!("{parent_url}-{}", heading.url);
+ }
+ }
+ // Check for duplicates again, and warn if any.
+ heading_set.clear();
+ duplicates.clear();
+ for heading in &headings {
+ if !heading_set.insert(heading.url.clone()) {
+ duplicates.insert(heading.url.clone());
+ }
+ }
for url in duplicates {
warn!("Page {full_name:?} contains multiple headings with ID \"#{url}\"");
}
+
if name_url == "+index" {
if parents.is_empty() {
// This is the index file for the whole site.
@@ -351,7 +373,7 @@ impl Website {
if !path.starts_with('/') {
path = format!("{}{path}", from.parent_url());
}
- let path = make_url_safe(&collapse_path(&path));
+ path = make_url_safe(&collapse_path(&path));
// Find page with this path in website.
for page in &self.pages {
diff --git a/src/generate_html.rs b/src/generate_html.rs
index 33158a5..306892b 100644
--- a/src/generate_html.rs
+++ b/src/generate_html.rs
@@ -28,12 +28,10 @@ pub fn generate_html(page: &Page, website: &Website) -> String {
None => String::new(),
};
let toc = get_table_of_contents(page);
- let toc_main = if page.headings.len() > 3 {
+ let toc_main = if page.headings.len() >= 3 {
format!("<details><summary></summary>\n{toc}</details>\n")
} else { String::new() };
- let toc_side = if page.headings.len() > 3 {
- format!("<div>{toc}</div>\n")
- } else { String::new() };
+ let toc_side = format!("<div>{toc}</div>\n");
let main = document_to_html(page, website); let main = main.trim();
format!("\
@@ -45,7 +43,8 @@ pub fn generate_html(page: &Page, website: &Website) -> String {
{head}
</head>
<body>
-<nav id='toc-side'>
+<nav id='outline' class='hidden'>
+<h1></h1>
{toc_side}
</nav>
<div id='page'>
@@ -107,9 +106,6 @@ pub fn get_html_head(page: &Page, website: &Website) -> String {
pub fn get_table_of_contents(page: &Page) -> String {
- if page.headings.len() < 3 {
- return String::new();
- }
let mut toc = String::from("<ul>\n");
let site_name = sanitize_text(&page.name, true);
toc.push_str(&format!("<li class='l1'><a href='#title'>{site_name}</a></li>\n"));
@@ -146,21 +142,27 @@ pub fn document_to_html(page: &Page, website: &Website) -> String {
($t:expr,$f:expr) => {{ html!("<{}>", $t); $f; html!("</{}>", $t); }}; }
wrap!("article",
- for block in &page.document.blocks {
+ for (i, block) in page.document.blocks.iter().enumerate() {
match block {
Block::Heading { level, line } => {
if let Level::Heading1 = level {
html!("</article>");
html!("<article>");
+ // html!("<nav class='return'><a href='#'></a></nav>");
+ };
+ // Find namespaced heading ID from headings list.
+ let url = match page.headings.iter().find(|h| h.block_id == i) {
+ Some(heading) => heading.url.clone(),
+ None => unreachable!("Couldn't find heading in headings list"),
};
- let id = make_url_safe(strip_appendix(&line.to_string()));
+ // let url = make_url_safe(strip_appendix(&line.to_string()));
let heading_tag = match level {
Level::Heading1 => "h1",
Level::Heading2 => "h2",
Level::Heading3 => "h3",
};
- wrap!(heading_tag, format!("id='{id}'"), {
- tag!("a", line, format!("href='#{id}'"));
+ wrap!(heading_tag, format!("id='{url}'"), {
+ tag!("a", line, format!("href='#{url}'"));
});
}
Block::Paragraph(line) => tag!("p", line),