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::RefCell;
|
||||||
use std::cell::RefMut;
|
use std::cell::RefMut;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -20,6 +21,8 @@ pub struct Compiler {
|
||||||
cache: Option<RefCell<Connection>>,
|
cache: Option<RefCell<Connection>>,
|
||||||
reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
|
reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
|
||||||
// TODO: External references, i.e resolved later
|
// TODO: External references, i.e resolved later
|
||||||
|
|
||||||
|
sections_counter: RefCell<Vec<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
|
@ -35,9 +38,34 @@ impl Compiler {
|
||||||
target,
|
target,
|
||||||
cache: cache.map(|con| RefCell::new(con)),
|
cache: cache.map(|con| RefCell::new(con)),
|
||||||
reference_count: RefCell::new(HashMap::new()),
|
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`]
|
/// Sanitizes text for a [`Target`]
|
||||||
pub fn sanitize<S: AsRef<str>>(target: Target, str: S) -> String {
|
pub fn sanitize<S: AsRef<str>>(target: Target, str: S) -> String {
|
||||||
match target {
|
match target {
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl RegexRule for ScriptRule {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::elements::link::Link;
|
use crate::elements::link::Link;
|
||||||
use crate::elements::list::ListEntry;
|
use crate::elements::list::ListEntry;
|
||||||
use crate::elements::list::ListMarker;
|
use crate::elements::list::ListMarker;
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::elements::style::Style;
|
use crate::elements::style::Style;
|
||||||
|
|
|
@ -17,6 +17,7 @@ use mlua::Error::BadArgument;
|
||||||
use mlua::Function;
|
use mlua::Function;
|
||||||
use mlua::Lua;
|
use mlua::Lua;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use section_kind::NO_NUMBER;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -38,13 +39,25 @@ impl Element for Section {
|
||||||
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
||||||
match compiler.target() {
|
match compiler.target() {
|
||||||
Target::HTML => {
|
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!(
|
Ok(format!(
|
||||||
r#"<h{0} id="{1}">{2}</h{0}>"#,
|
r#"<h{0} id="{1}">{number}{2}</h{0}>"#,
|
||||||
self.depth,
|
self.depth,
|
||||||
Compiler::refname(compiler.target(), self.title.as_str()),
|
Compiler::refname(compiler.target(), self.title.as_str()),
|
||||||
Compiler::sanitize(compiler.target(), self.title.as_str())
|
Compiler::sanitize(compiler.target(), self.title.as_str())
|
||||||
))
|
))
|
||||||
},
|
}
|
||||||
Target::LATEX => Err("Unimplemented compiler".to_string()),
|
Target::LATEX => Err("Unimplemented compiler".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,15 +149,15 @@ impl RegexRule for SectionRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
// [Optional] Reference name
|
// [Optional] Reference name
|
||||||
let section_refname = matches.get(2).map_or_else(
|
let section_refname =
|
||||||
|| None,
|
matches.get(2).map_or_else(
|
||||||
|refname| {
|
|| None,
|
||||||
// Check for duplicate reference
|
|refname| {
|
||||||
if let Some(elem_reference) = document.get_reference(refname.as_str())
|
// 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 elem = document.get_from_reference(&elem_reference).unwrap();
|
||||||
|
|
||||||
result.push(
|
result.push(
|
||||||
Report::build(ReportKind::Warning, token.source(), refname.start())
|
Report::build(ReportKind::Warning, token.source(), refname.start())
|
||||||
.with_message("Duplicate reference name")
|
.with_message("Duplicate reference name")
|
||||||
.with_label(
|
.with_label(
|
||||||
|
@ -163,10 +176,10 @@ impl RegexRule for SectionRule {
|
||||||
.with_color(parser.colors().warning))
|
.with_color(parser.colors().warning))
|
||||||
.with_note(format!("Previous reference was overwritten"))
|
.with_note(format!("Previous reference was overwritten"))
|
||||||
.finish());
|
.finish());
|
||||||
}
|
}
|
||||||
Some(refname.as_str().to_string())
|
Some(refname.as_str().to_string())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Section kind
|
// Section kind
|
||||||
let section_kind = match matches.get(3) {
|
let section_kind = match matches.get(3) {
|
||||||
|
|
Loading…
Reference in a new issue