Section numbering
This commit is contained in:
parent
d91279c1f2
commit
7b081be97b
3 changed files with 60 additions and 19 deletions
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue