Compare commits
2 commits
8489796510
...
0982527944
Author | SHA1 | Date | |
---|---|---|---|
0982527944 | |||
90cf691737 |
10 changed files with 274 additions and 128 deletions
74
Cargo.lock
generated
74
Cargo.lock
generated
|
@ -56,7 +56,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -67,7 +67,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -277,6 +277,16 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.9"
|
||||
|
@ -389,7 +399,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -696,10 +706,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"erased-serde",
|
||||
"mlua-sys",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde-value",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -802,6 +815,15 @@ dependencies = [
|
|||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.10"
|
||||
|
@ -852,7 +874,7 @@ dependencies = [
|
|||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -883,7 +905,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -931,9 +953,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.79"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -949,9 +971,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -1159,6 +1181,16 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-value"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||
dependencies = [
|
||||
"ordered-float",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.204"
|
||||
|
@ -1167,7 +1199,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1189,7 +1221,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1231,9 +1263,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.53"
|
||||
version = "2.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1291,7 +1323,7 @@ checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1371,7 +1403,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1438,7 +1470,7 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1466,7 +1498,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1478,6 +1510,12 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
|
@ -1723,5 +1761,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
|
|
@ -25,7 +25,7 @@ graphviz-rust = "0.9.0"
|
|||
lazy_static = "1.5.0"
|
||||
lsp-server = "0.7.6"
|
||||
lsp-types = "0.97.0"
|
||||
mlua = { version = "0.9.9", features = ["lua54", "vendored"] }
|
||||
mlua = { version = "0.9.9", features = ["lua54", "vendored", "serialize"] }
|
||||
regex = "1.10.3"
|
||||
rusqlite = "0.31.0"
|
||||
rust-crypto = "0.2.36"
|
||||
|
|
|
@ -25,3 +25,8 @@ function make_doc(categories, title, page_title)
|
|||
nml.variable.insert("compiler.output", page_title .. ".html")
|
||||
end
|
||||
>@
|
||||
|
||||
@@style.section = {
|
||||
"link_pos": "Before",
|
||||
"link": ["", "🔗 ", " "]
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use super::compiler::Target;
|
|||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NavEntry {
|
||||
pub(self) entries: Vec<(String, String)>,
|
||||
pub(self) entries: Vec<(String, String, Option<String>)>,
|
||||
pub(self) children: HashMap<String, NavEntry>,
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ impl NavEntry {
|
|||
depth: usize,
|
||||
) {
|
||||
// Orphans = Links
|
||||
for (title, path) in &entry.entries {
|
||||
for (title, path, _) in &entry.entries {
|
||||
result.push_str(
|
||||
format!(
|
||||
r#"<li><a href="{}">{}</a></li>"#,
|
||||
|
@ -75,6 +75,36 @@ impl NavEntry {
|
|||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Gets the insert index of the entry inside an already sorted entry list
|
||||
fn sort_entry(
|
||||
title: &String,
|
||||
previous: &Option<String>,
|
||||
entries: &Vec<(String, String, Option<String>)>,
|
||||
) -> usize {
|
||||
let mut insert_at = 0;
|
||||
if let Some(previous) = &previous
|
||||
// Using sort key
|
||||
{
|
||||
for (i, (ent_title, _, _)) in entries.iter().enumerate() {
|
||||
if ent_title == previous {
|
||||
insert_at = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then sort alphabetically
|
||||
for (ent_title, _, ent_previous) in entries.iter().skip(insert_at) {
|
||||
if (previous.is_some() && ent_previous != previous) || ent_title > title {
|
||||
break;
|
||||
}
|
||||
|
||||
insert_at += 1;
|
||||
}
|
||||
|
||||
insert_at
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_navigation(docs: &Vec<CompiledDocument>) -> Result<NavEntry, String> {
|
||||
|
@ -83,12 +113,16 @@ pub fn create_navigation(docs: &Vec<CompiledDocument>) -> Result<NavEntry, Strin
|
|||
children: HashMap::new(),
|
||||
};
|
||||
|
||||
// All paths (for duplicate checking)
|
||||
let mut all_paths = HashMap::new();
|
||||
|
||||
for doc in docs {
|
||||
let cat = doc.get_variable("nav.category");
|
||||
let subcat = doc.get_variable("nav.subcategory");
|
||||
let title = doc
|
||||
.get_variable("nav.title")
|
||||
.or(doc.get_variable("doc.title"));
|
||||
let previous = doc.get_variable("nav.previous").map(|s| s.clone());
|
||||
let path = doc.get_variable("compiler.output");
|
||||
|
||||
let (title, path) = match (title, path) {
|
||||
|
@ -142,8 +176,67 @@ pub fn create_navigation(docs: &Vec<CompiledDocument>) -> Result<NavEntry, Strin
|
|||
&mut nav
|
||||
};
|
||||
|
||||
pent.entries.push((title.clone(), path.clone()))
|
||||
// Find duplicates titles in current parent
|
||||
for (ent_title, _, _) in &pent.entries {
|
||||
if ent_title == title {
|
||||
return Err(format!(
|
||||
"Conflicting entry title `{title}` for entries with the same parent: ({})",
|
||||
pent.entries
|
||||
.iter()
|
||||
.map(|(title, _, _)| title.clone())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Find duplicate paths
|
||||
if let Some(dup_title) = all_paths.get(path) {
|
||||
return Err(format!("Conflicting paths: `{path}`. Previously used for entry: `{dup_title}`, conflicting use in `{title}`"));
|
||||
}
|
||||
all_paths.insert(path.clone(), title.clone());
|
||||
|
||||
pent.entries.insert(
|
||||
NavEntry::sort_entry(title, &previous, &pent.entries),
|
||||
(title.clone(), path.clone(), previous),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(nav)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn sort() {
|
||||
let entries: Vec<(String, String, Option<String>)> = vec![
|
||||
("Root".into(), "".into(), None),
|
||||
("First".into(), "".into(), Some("Root".into())),
|
||||
("1".into(), "".into(), Some("First".into())),
|
||||
("2".into(), "".into(), Some("First".into())),
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
NavEntry::sort_entry(&"E".into(), &Some("Root".into()), &entries),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
NavEntry::sort_entry(&"G".into(), &Some("Root".into()), &entries),
|
||||
2
|
||||
);
|
||||
// Orphans
|
||||
assert_eq!(NavEntry::sort_entry(&"Q".into(), &None, &entries), 0);
|
||||
assert_eq!(NavEntry::sort_entry(&"S".into(), &None, &entries), 4);
|
||||
|
||||
assert_eq!(
|
||||
NavEntry::sort_entry(&"1.1".into(), &Some("First".into()), &entries),
|
||||
3
|
||||
);
|
||||
assert_eq!(
|
||||
NavEntry::sort_entry(&"2.1".into(), &Some("First".into()), &entries),
|
||||
4
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,13 @@ pub trait ElementStyle: Downcast + core::fmt::Debug {
|
|||
|
||||
/// Serializes sytle into json string
|
||||
fn to_json(&self) -> String;
|
||||
|
||||
/// Attempts to deserialize lua table into a new style
|
||||
fn from_lua(
|
||||
&self,
|
||||
lua: &mlua::Lua,
|
||||
value: mlua::Value,
|
||||
) -> Result<Rc<dyn ElementStyle>, mlua::Error>;
|
||||
}
|
||||
impl_downcast!(ElementStyle);
|
||||
|
||||
|
@ -31,7 +38,7 @@ pub trait StyleHolder {
|
|||
fn styles_mut(&self) -> RefMut<'_, HashMap<String, Rc<dyn ElementStyle>>>;
|
||||
|
||||
/// Checks if a given style key is registered
|
||||
fn is_registered(&self, style_key: &str) -> bool { self.styles().contains_key(style_key) }
|
||||
fn is_style_registered(&self, style_key: &str) -> bool { self.styles().contains_key(style_key) }
|
||||
|
||||
/// Gets the current active style for an element
|
||||
/// NOTE: Will panic if a style is not defined for a given element
|
||||
|
@ -59,6 +66,15 @@ macro_rules! impl_elementstyle {
|
|||
}
|
||||
|
||||
fn to_json(&self) -> String { serde_json::to_string(self).unwrap() }
|
||||
|
||||
fn from_lua(
|
||||
&self,
|
||||
lua: &mlua::Lua,
|
||||
value: mlua::Value,
|
||||
) -> Result<std::rc::Rc<dyn ElementStyle>, mlua::Error> {
|
||||
mlua::LuaSerdeExt::from_value::<$t>(lua, value)
|
||||
.map(|obj| std::rc::Rc::new(obj) as std::rc::Rc<dyn ElementStyle>)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
use std::any::Any;
|
||||
use std::ops::Range;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ariadne::Fmt;
|
||||
use ariadne::Label;
|
||||
use ariadne::Report;
|
||||
use ariadne::ReportKind;
|
||||
use mlua::Error::BadArgument;
|
||||
use mlua::Function;
|
||||
use mlua::Lua;
|
||||
use mlua::LuaSerdeExt;
|
||||
use mlua::Table;
|
||||
use mlua::Value;
|
||||
use regex::Captures;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::document::document::Document;
|
||||
use crate::document::{self};
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::rule::Rule;
|
||||
|
@ -58,71 +66,6 @@ impl ElemStyleRule {
|
|||
impl Rule for ElemStyleRule {
|
||||
fn name(&self) -> &'static str { "Element Style" }
|
||||
|
||||
/*
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_: usize,
|
||||
parser: &dyn Parser,
|
||||
_document: &'a dyn Document,
|
||||
token: Token,
|
||||
matches: Captures,
|
||||
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||
let mut reports = vec![];
|
||||
|
||||
|
||||
// Get value
|
||||
let new_style = if let Some(value) = matches.get(2) {
|
||||
let value_str = match VariableRule::validate_value(value.as_str()) {
|
||||
Err(err) => {
|
||||
reports.push(
|
||||
Report::build(ReportKind::Error, token.source(), value.start())
|
||||
.with_message("Invalid Style Value")
|
||||
.with_label(
|
||||
Label::new((token.source(), value.range()))
|
||||
.with_message(format!(
|
||||
"Value `{}` is not allowed: {err}",
|
||||
value.as_str().fg(parser.colors().highlight)
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
return reports;
|
||||
}
|
||||
Ok(value) => value,
|
||||
};
|
||||
|
||||
// Attempt to serialize
|
||||
match style.from_json(value_str.as_str()) {
|
||||
Err(err) => {
|
||||
reports.push(
|
||||
Report::build(ReportKind::Error, token.source(), value.start())
|
||||
.with_message("Invalid Style Value")
|
||||
.with_label(
|
||||
Label::new((token.source(), value.range()))
|
||||
.with_message(format!(
|
||||
"Failed to serialize `{}` into style with key `{}`: {err}",
|
||||
value_str.fg(parser.colors().highlight),
|
||||
style.key().fg(parser.colors().info)
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
return reports;
|
||||
}
|
||||
Ok(style) => style,
|
||||
}
|
||||
} else {
|
||||
panic!("Unknown error")
|
||||
};
|
||||
|
||||
parser.set_style(new_style);
|
||||
|
||||
reports
|
||||
}
|
||||
*/
|
||||
|
||||
fn next_match(&self, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
self.start_re
|
||||
.find_at(cursor.source.content(), cursor.pos)
|
||||
|
@ -164,7 +107,7 @@ impl Rule for ElemStyleRule {
|
|||
}
|
||||
|
||||
// Check if key exists
|
||||
if !parser.is_registered(trimmed) {
|
||||
if !parser.is_style_registered(trimmed) {
|
||||
reports.push(
|
||||
Report::build(ReportKind::Error, cursor.source.clone(), key.start())
|
||||
.with_message("Unknown Style Key")
|
||||
|
@ -240,4 +183,46 @@ impl Rule for ElemStyleRule {
|
|||
|
||||
(cursor, reports)
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||
let mut bindings = vec![];
|
||||
|
||||
bindings.push((
|
||||
"set".to_string(),
|
||||
lua.create_function(|lua, (style_key, new_style): (String, Value)| {
|
||||
let mut result = Ok(());
|
||||
CTX.with_borrow(|ctx| {
|
||||
ctx.as_ref().map(|ctx| {
|
||||
if !ctx.parser.is_style_registered(style_key.as_str()) {
|
||||
result = Err(BadArgument {
|
||||
to: Some("set".to_string()),
|
||||
pos: 1,
|
||||
name: Some("style_key".to_string()),
|
||||
cause: Arc::new(mlua::Error::external(format!(
|
||||
"Unable to find style with key: {style_key}"
|
||||
))),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let style = ctx.parser.current_style(style_key.as_str());
|
||||
let new_style = match style.from_lua(lua, new_style) {
|
||||
Err(err) => {
|
||||
result = Err(err);
|
||||
return;
|
||||
}
|
||||
Ok(new_style) => new_style,
|
||||
};
|
||||
|
||||
ctx.parser.set_current_style(new_style);
|
||||
})
|
||||
});
|
||||
|
||||
result
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
Some(bindings)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ impl ReferenceRule {
|
|||
),
|
||||
);
|
||||
Self {
|
||||
re: [Regex::new(r"§\{(.*)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()],
|
||||
re: [Regex::new(r"§\{(.*?)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()],
|
||||
properties: PropertyParser{ properties: props },
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,16 +46,17 @@ impl Element for Section {
|
|||
match compiler.target() {
|
||||
Target::HTML => {
|
||||
// Section numbering
|
||||
let number = if (self.kind & section_kind::NO_NUMBER) == section_kind::NO_NUMBER {
|
||||
let number = if (self.kind & section_kind::NO_NUMBER) != section_kind::NO_NUMBER {
|
||||
let numbering = compiler.section_counter(self.depth);
|
||||
let number = " ".to_string()
|
||||
+ numbering
|
||||
.iter()
|
||||
.map(|n| n.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(".")
|
||||
.as_str();
|
||||
number
|
||||
|
||||
let mut result = String::new();
|
||||
for num in numbering.iter()
|
||||
{
|
||||
result = result + num.to_string().as_str() + ".";
|
||||
}
|
||||
result += " ";
|
||||
|
||||
result
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
@ -71,8 +72,10 @@ impl Element for Section {
|
|||
|
||||
let refname = Compiler::refname(compiler.target(), self.title.as_str());
|
||||
let link = format!(
|
||||
"<a class=\"section-link\" href=\"#{refname}\">{}</a>",
|
||||
Compiler::sanitize(compiler.target(), self.style.link.as_str())
|
||||
"{}<a class=\"section-link\" href=\"#{refname}\">{}</a>{}",
|
||||
Compiler::sanitize(compiler.target(), self.style.link[0].as_str()),
|
||||
Compiler::sanitize(compiler.target(), self.style.link[1].as_str()),
|
||||
Compiler::sanitize(compiler.target(), self.style.link[2].as_str())
|
||||
);
|
||||
|
||||
if self.style.link_pos == SectionLinkPos::After {
|
||||
|
@ -123,7 +126,7 @@ impl ReferenceableElement for Section {
|
|||
);
|
||||
|
||||
Ok(format!(
|
||||
"<a class=\"section-ref\" href=\"#{}\">{caption}</a>",
|
||||
"<a class=\"section-reference\" href=\"#{}\">{caption}</a>",
|
||||
Compiler::refname(compiler.target(), self.title.as_str())
|
||||
))
|
||||
}
|
||||
|
@ -390,14 +393,14 @@ mod section_style {
|
|||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SectionStyle {
|
||||
pub link_pos: SectionLinkPos,
|
||||
pub link: String,
|
||||
pub link: [String; 3],
|
||||
}
|
||||
|
||||
impl Default for SectionStyle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
link_pos: SectionLinkPos::After,
|
||||
link: "🔗".to_string(),
|
||||
link_pos: SectionLinkPos::Before,
|
||||
link: ["".into(), "🔗".into(), " ".into()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{cell::{RefCell, RefMut}, collections::HashMap, rc::Rc};
|
||||
|
||||
use crate::{document::{document::Document, element::Element}, lua::kernel::{Kernel, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source}, state::StateHolder}};
|
||||
use crate::{document::{document::Document, element::Element, style::{ElementStyle, StyleHolder}}, lua::kernel::{Kernel, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source}, state::StateHolder}};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LineCursor
|
||||
|
@ -146,3 +146,13 @@ impl KernelHolder for LsParser
|
|||
self.get_kernel(name.as_str()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl StyleHolder for LsParser {
|
||||
fn styles(&self) -> std::cell::Ref<'_, HashMap<String, Rc<dyn ElementStyle>>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn styles_mut(&self) -> RefMut<'_, HashMap<String, Rc<dyn ElementStyle>>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::cell::{RefCell, RefMut};
|
||||
use std::cell::RefCell;
|
||||
use std::cell::RefMut;
|
||||
|
||||
use mlua::Lua;
|
||||
|
||||
use crate::{document::document::Document, parser::{parser::Parser, source::Token}};
|
||||
use crate::document::document::Document;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::source::Token;
|
||||
|
||||
pub struct KernelContext<'a, 'b>
|
||||
{
|
||||
pub struct KernelContext<'a, 'b> {
|
||||
pub location: Token,
|
||||
pub parser: &'a dyn Parser,
|
||||
pub document: &'b dyn Document<'b>,
|
||||
|
@ -17,8 +19,7 @@ thread_local! {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Kernel
|
||||
{
|
||||
pub struct Kernel {
|
||||
lua: Lua,
|
||||
}
|
||||
|
||||
|
@ -32,15 +33,12 @@ impl Kernel {
|
|||
{
|
||||
let nml_table = lua.create_table().unwrap();
|
||||
|
||||
for rule in parser.rules()
|
||||
{
|
||||
if let Some(bindings) = rule.lua_bindings(&lua)
|
||||
{
|
||||
for rule in parser.rules() {
|
||||
if let Some(bindings) = rule.lua_bindings(&lua) {
|
||||
let table = lua.create_table().unwrap();
|
||||
let name = rule.name().to_lowercase();
|
||||
let name = rule.name().to_lowercase().replace(' ', "_");
|
||||
|
||||
for (fun_name, fun) in bindings
|
||||
{
|
||||
for (fun_name, fun) in bindings {
|
||||
table.set(fun_name, fun).unwrap();
|
||||
}
|
||||
|
||||
|
@ -57,10 +55,9 @@ impl Kernel {
|
|||
///
|
||||
/// This is the only way lua code shoule be ran, because exported
|
||||
/// functions may require the context in order to operate
|
||||
pub fn run_with_context<T, F>(&self, context: KernelContext, f: F)
|
||||
-> T
|
||||
pub fn run_with_context<T, F>(&self, context: KernelContext, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&Lua) -> T
|
||||
F: FnOnce(&Lua) -> T,
|
||||
{
|
||||
CTX.set(Some(unsafe { std::mem::transmute(context) }));
|
||||
let ret = f(&self.lua);
|
||||
|
@ -70,8 +67,7 @@ impl Kernel {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait KernelHolder
|
||||
{
|
||||
pub trait KernelHolder {
|
||||
fn get_kernel(&self, name: &str) -> Option<RefMut<'_, Kernel>>;
|
||||
|
||||
fn insert_kernel(&self, name: String, kernel: Kernel) -> RefMut<'_, Kernel>;
|
||||
|
|
Loading…
Reference in a new issue