From 7b081be97b207cc0a74fc277f4294895d96aeb00 Mon Sep 17 00:00:00 2001 From: ef3d0c3e Date: Fri, 2 Aug 2024 14:10:17 +0200 Subject: [PATCH] Section numbering --- src/compiler/compiler.rs | 28 +++++++++++++++++++++++ src/elements/script.rs | 2 +- src/elements/section.rs | 49 +++++++++++++++++++++++++--------------- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index 7714571..de7c04f 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -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>, reference_count: RefCell>>, // TODO: External references, i.e resolved later + + sections_counter: RefCell>, } 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> + { + // 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>(target: Target, str: S) -> String { match target { diff --git a/src/elements/script.rs b/src/elements/script.rs index 325adc4..9c64c78 100644 --- a/src/elements/script.rs +++ b/src/elements/script.rs @@ -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; diff --git a/src/elements/section.rs b/src/elements/section.rs index 60e97a9..6d2be6b 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -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 { 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::>() + .join("."); + number += " "; + } + Ok(format!( - r#"{2}"#, - self.depth, - Compiler::refname(compiler.target(), self.title.as_str()), - Compiler::sanitize(compiler.target(), self.title.as_str()) - )) - }, + r#"{number}{2}"#, + 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) {