Section numbering

This commit is contained in:
ef3d0c3e 2024-08-02 14:10:17 +02:00
parent d91279c1f2
commit 7b081be97b
3 changed files with 60 additions and 19 deletions

View file

@ -1,3 +1,4 @@
use std::cell::Ref;
use std::cell::RefCell;
use std::cell::RefMut;
use std::collections::HashMap;
@ -20,6 +21,8 @@ pub struct Compiler {
cache: Option<RefCell<Connection>>,
reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
// TODO: External references, i.e resolved later
sections_counter: RefCell<Vec<usize>>,
}
impl Compiler {
@ -35,9 +38,34 @@ impl Compiler {
target,
cache: cache.map(|con| RefCell::new(con)),
reference_count: RefCell::new(HashMap::new()),
sections_counter: RefCell::new(vec![]),
}
}
/// Gets the section counter for a given depth
/// This function modifies the section counter
pub fn section_counter(&self, depth: usize) -> Ref<'_, Vec<usize>>
{
// Increment current counter
if self.sections_counter.borrow().len() == depth {
self.sections_counter.borrow_mut().last_mut()
.map(|id| *id += 1);
return Ref::map(self.sections_counter.borrow(), |b| &*b);
}
// Close
while self.sections_counter.borrow().len() > depth {
self.sections_counter.borrow_mut().pop();
}
// Open
while self.sections_counter.borrow().len() < depth {
self.sections_counter.borrow_mut().push(1);
}
Ref::map(self.sections_counter.borrow(), |b| &*b)
}
/// Sanitizes text for a [`Target`]
pub fn sanitize<S: AsRef<str>>(target: Target, str: S) -> String {
match target {

View file

@ -282,7 +282,7 @@ impl RegexRule for ScriptRule {
mod tests {
use super::*;
use crate::elements::link::Link;
use crate::elements::list::ListEntry;
use crate::elements::list::ListEntry;
use crate::elements::list::ListMarker;
use crate::elements::paragraph::Paragraph;
use crate::elements::style::Style;

View file

@ -17,6 +17,7 @@ use mlua::Error::BadArgument;
use mlua::Function;
use mlua::Lua;
use regex::Regex;
use section_kind::NO_NUMBER;
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
@ -38,13 +39,25 @@ impl Element for Section {
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
match compiler.target() {
Target::HTML => {
let mut number = String::new();
if (self.kind & NO_NUMBER) != NO_NUMBER {
let numbering = compiler.section_counter(self.depth);
number = numbering
.iter()
.map(|n| n.to_string())
.collect::<Vec<_>>()
.join(".");
number += " ";
}
Ok(format!(
r#"<h{0} id="{1}">{2}</h{0}>"#,
self.depth,
Compiler::refname(compiler.target(), self.title.as_str()),
Compiler::sanitize(compiler.target(), self.title.as_str())
))
},
r#"<h{0} id="{1}">{number}{2}</h{0}>"#,
self.depth,
Compiler::refname(compiler.target(), self.title.as_str()),
Compiler::sanitize(compiler.target(), self.title.as_str())
))
}
Target::LATEX => Err("Unimplemented compiler".to_string()),
}
}
@ -136,15 +149,15 @@ impl RegexRule for SectionRule {
};
// [Optional] Reference name
let section_refname = matches.get(2).map_or_else(
|| None,
|refname| {
// Check for duplicate reference
if let Some(elem_reference) = document.get_reference(refname.as_str())
{
let elem = document.get_from_reference(&elem_reference).unwrap();
let section_refname =
matches.get(2).map_or_else(
|| None,
|refname| {
// Check for duplicate reference
if let Some(elem_reference) = document.get_reference(refname.as_str()) {
let elem = document.get_from_reference(&elem_reference).unwrap();
result.push(
result.push(
Report::build(ReportKind::Warning, token.source(), refname.start())
.with_message("Duplicate reference name")
.with_label(
@ -163,10 +176,10 @@ impl RegexRule for SectionRule {
.with_color(parser.colors().warning))
.with_note(format!("Previous reference was overwritten"))
.finish());
}
Some(refname.as_str().to_string())
},
);
}
Some(refname.as_str().to_string())
},
);
// Section kind
let section_kind = match matches.get(3) {