Compare commits
No commits in common. "098252794440736be008f91f979bf7207a944791" and "8489796510de0372c7b2e360aa3e42475905f5c4" have entirely different histories.
0982527944
...
8489796510
10 changed files with 128 additions and 274 deletions
74
Cargo.lock
generated
74
Cargo.lock
generated
|
@ -56,7 +56,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -67,7 +67,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -277,16 +277,6 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
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]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -399,7 +389,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -706,13 +696,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7"
|
checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"erased-serde",
|
|
||||||
"mlua-sys",
|
"mlua-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"serde",
|
|
||||||
"serde-value",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -815,15 +802,6 @@ dependencies = [
|
||||||
"pkg-config",
|
"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]]
|
[[package]]
|
||||||
name = "parking_lot_core"
|
name = "parking_lot_core"
|
||||||
version = "0.9.10"
|
version = "0.9.10"
|
||||||
|
@ -874,7 +852,7 @@ dependencies = [
|
||||||
"pest_meta",
|
"pest_meta",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -905,7 +883,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -953,9 +931,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.86"
|
version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
@ -971,9 +949,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.36"
|
version = "1.0.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -1181,16 +1159,6 @@ dependencies = [
|
||||||
"serde_derive",
|
"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]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.204"
|
version = "1.0.204"
|
||||||
|
@ -1199,7 +1167,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1221,7 +1189,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1263,9 +1231,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.72"
|
version = "2.0.53"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1323,7 +1291,7 @@ checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1403,7 +1371,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1470,7 +1438,7 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1498,7 +1466,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1510,12 +1478,6 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typeid"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
@ -1761,5 +1723,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.72",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
|
@ -25,7 +25,7 @@ graphviz-rust = "0.9.0"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
lsp-server = "0.7.6"
|
lsp-server = "0.7.6"
|
||||||
lsp-types = "0.97.0"
|
lsp-types = "0.97.0"
|
||||||
mlua = { version = "0.9.9", features = ["lua54", "vendored", "serialize"] }
|
mlua = { version = "0.9.9", features = ["lua54", "vendored"] }
|
||||||
regex = "1.10.3"
|
regex = "1.10.3"
|
||||||
rusqlite = "0.31.0"
|
rusqlite = "0.31.0"
|
||||||
rust-crypto = "0.2.36"
|
rust-crypto = "0.2.36"
|
||||||
|
|
|
@ -25,8 +25,3 @@ function make_doc(categories, title, page_title)
|
||||||
nml.variable.insert("compiler.output", page_title .. ".html")
|
nml.variable.insert("compiler.output", page_title .. ".html")
|
||||||
end
|
end
|
||||||
>@
|
>@
|
||||||
|
|
||||||
@@style.section = {
|
|
||||||
"link_pos": "Before",
|
|
||||||
"link": ["", "🔗 ", " "]
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use super::compiler::Target;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct NavEntry {
|
pub struct NavEntry {
|
||||||
pub(self) entries: Vec<(String, String, Option<String>)>,
|
pub(self) entries: Vec<(String, String)>,
|
||||||
pub(self) children: HashMap<String, NavEntry>,
|
pub(self) children: HashMap<String, NavEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ impl NavEntry {
|
||||||
depth: usize,
|
depth: usize,
|
||||||
) {
|
) {
|
||||||
// Orphans = Links
|
// Orphans = Links
|
||||||
for (title, path, _) in &entry.entries {
|
for (title, path) in &entry.entries {
|
||||||
result.push_str(
|
result.push_str(
|
||||||
format!(
|
format!(
|
||||||
r#"<li><a href="{}">{}</a></li>"#,
|
r#"<li><a href="{}">{}</a></li>"#,
|
||||||
|
@ -75,36 +75,6 @@ impl NavEntry {
|
||||||
}
|
}
|
||||||
result
|
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> {
|
pub fn create_navigation(docs: &Vec<CompiledDocument>) -> Result<NavEntry, String> {
|
||||||
|
@ -113,16 +83,12 @@ pub fn create_navigation(docs: &Vec<CompiledDocument>) -> Result<NavEntry, Strin
|
||||||
children: HashMap::new(),
|
children: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// All paths (for duplicate checking)
|
|
||||||
let mut all_paths = HashMap::new();
|
|
||||||
|
|
||||||
for doc in docs {
|
for doc in docs {
|
||||||
let cat = doc.get_variable("nav.category");
|
let cat = doc.get_variable("nav.category");
|
||||||
let subcat = doc.get_variable("nav.subcategory");
|
let subcat = doc.get_variable("nav.subcategory");
|
||||||
let title = doc
|
let title = doc
|
||||||
.get_variable("nav.title")
|
.get_variable("nav.title")
|
||||||
.or(doc.get_variable("doc.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 path = doc.get_variable("compiler.output");
|
||||||
|
|
||||||
let (title, path) = match (title, path) {
|
let (title, path) = match (title, path) {
|
||||||
|
@ -176,67 +142,8 @@ pub fn create_navigation(docs: &Vec<CompiledDocument>) -> Result<NavEntry, Strin
|
||||||
&mut nav
|
&mut nav
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find duplicates titles in current parent
|
pent.entries.push((title.clone(), path.clone()))
|
||||||
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)
|
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,13 +20,6 @@ pub trait ElementStyle: Downcast + core::fmt::Debug {
|
||||||
|
|
||||||
/// Serializes sytle into json string
|
/// Serializes sytle into json string
|
||||||
fn to_json(&self) -> 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);
|
impl_downcast!(ElementStyle);
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ pub trait StyleHolder {
|
||||||
fn styles_mut(&self) -> RefMut<'_, HashMap<String, Rc<dyn ElementStyle>>>;
|
fn styles_mut(&self) -> RefMut<'_, HashMap<String, Rc<dyn ElementStyle>>>;
|
||||||
|
|
||||||
/// Checks if a given style key is registered
|
/// Checks if a given style key is registered
|
||||||
fn is_style_registered(&self, style_key: &str) -> bool { self.styles().contains_key(style_key) }
|
fn is_registered(&self, style_key: &str) -> bool { self.styles().contains_key(style_key) }
|
||||||
|
|
||||||
/// Gets the current active style for an element
|
/// Gets the current active style for an element
|
||||||
/// NOTE: Will panic if a style is not defined for a given element
|
/// NOTE: Will panic if a style is not defined for a given element
|
||||||
|
@ -66,15 +59,6 @@ macro_rules! impl_elementstyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_json(&self) -> String { serde_json::to_string(self).unwrap() }
|
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,24 +1,16 @@
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use ariadne::Fmt;
|
use ariadne::Fmt;
|
||||||
use ariadne::Label;
|
use ariadne::Label;
|
||||||
use ariadne::Report;
|
use ariadne::Report;
|
||||||
use ariadne::ReportKind;
|
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::Captures;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::{self};
|
use crate::document::{self};
|
||||||
use crate::lua::kernel::CTX;
|
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
|
@ -66,6 +58,71 @@ impl ElemStyleRule {
|
||||||
impl Rule for ElemStyleRule {
|
impl Rule for ElemStyleRule {
|
||||||
fn name(&self) -> &'static str { "Element Style" }
|
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>)> {
|
fn next_match(&self, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||||
self.start_re
|
self.start_re
|
||||||
.find_at(cursor.source.content(), cursor.pos)
|
.find_at(cursor.source.content(), cursor.pos)
|
||||||
|
@ -107,7 +164,7 @@ impl Rule for ElemStyleRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if key exists
|
// Check if key exists
|
||||||
if !parser.is_style_registered(trimmed) {
|
if !parser.is_registered(trimmed) {
|
||||||
reports.push(
|
reports.push(
|
||||||
Report::build(ReportKind::Error, cursor.source.clone(), key.start())
|
Report::build(ReportKind::Error, cursor.source.clone(), key.start())
|
||||||
.with_message("Unknown Style Key")
|
.with_message("Unknown Style Key")
|
||||||
|
@ -183,46 +240,4 @@ impl Rule for ElemStyleRule {
|
||||||
|
|
||||||
(cursor, reports)
|
(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 {
|
Self {
|
||||||
re: [Regex::new(r"§\{(.*?)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()],
|
re: [Regex::new(r"§\{(.*)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()],
|
||||||
properties: PropertyParser{ properties: props },
|
properties: PropertyParser{ properties: props },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,17 +46,16 @@ impl Element for Section {
|
||||||
match compiler.target() {
|
match compiler.target() {
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
// Section numbering
|
// 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 numbering = compiler.section_counter(self.depth);
|
||||||
|
let number = " ".to_string()
|
||||||
let mut result = String::new();
|
+ numbering
|
||||||
for num in numbering.iter()
|
.iter()
|
||||||
{
|
.map(|n| n.to_string())
|
||||||
result = result + num.to_string().as_str() + ".";
|
.collect::<Vec<_>>()
|
||||||
}
|
.join(".")
|
||||||
result += " ";
|
.as_str();
|
||||||
|
number
|
||||||
result
|
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
@ -72,10 +71,8 @@ impl Element for Section {
|
||||||
|
|
||||||
let refname = Compiler::refname(compiler.target(), self.title.as_str());
|
let refname = Compiler::refname(compiler.target(), self.title.as_str());
|
||||||
let link = format!(
|
let link = format!(
|
||||||
"{}<a class=\"section-link\" href=\"#{refname}\">{}</a>{}",
|
"<a class=\"section-link\" href=\"#{refname}\">{}</a>",
|
||||||
Compiler::sanitize(compiler.target(), self.style.link[0].as_str()),
|
Compiler::sanitize(compiler.target(), self.style.link.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 {
|
if self.style.link_pos == SectionLinkPos::After {
|
||||||
|
@ -126,7 +123,7 @@ impl ReferenceableElement for Section {
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
"<a class=\"section-reference\" href=\"#{}\">{caption}</a>",
|
"<a class=\"section-ref\" href=\"#{}\">{caption}</a>",
|
||||||
Compiler::refname(compiler.target(), self.title.as_str())
|
Compiler::refname(compiler.target(), self.title.as_str())
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -393,14 +390,14 @@ mod section_style {
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct SectionStyle {
|
pub struct SectionStyle {
|
||||||
pub link_pos: SectionLinkPos,
|
pub link_pos: SectionLinkPos,
|
||||||
pub link: [String; 3],
|
pub link: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SectionStyle {
|
impl Default for SectionStyle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
link_pos: SectionLinkPos::Before,
|
link_pos: SectionLinkPos::After,
|
||||||
link: ["".into(), "🔗".into(), " ".into()],
|
link: "🔗".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{cell::{RefCell, RefMut}, collections::HashMap, rc::Rc};
|
use std::{cell::{RefCell, RefMut}, collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
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}};
|
use crate::{document::{document::Document, element::Element}, lua::kernel::{Kernel, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source}, state::StateHolder}};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LineCursor
|
pub struct LineCursor
|
||||||
|
@ -146,13 +146,3 @@ impl KernelHolder for LsParser
|
||||||
self.get_kernel(name.as_str()).unwrap()
|
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,13 +1,11 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::cell::RefMut;
|
|
||||||
|
|
||||||
use mlua::Lua;
|
use mlua::Lua;
|
||||||
|
|
||||||
use crate::document::document::Document;
|
use crate::{document::document::Document, parser::{parser::Parser, source::Token}};
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::source::Token;
|
|
||||||
|
|
||||||
pub struct KernelContext<'a, 'b> {
|
pub struct KernelContext<'a, 'b>
|
||||||
|
{
|
||||||
pub location: Token,
|
pub location: Token,
|
||||||
pub parser: &'a dyn Parser,
|
pub parser: &'a dyn Parser,
|
||||||
pub document: &'b dyn Document<'b>,
|
pub document: &'b dyn Document<'b>,
|
||||||
|
@ -15,11 +13,12 @@ pub struct KernelContext<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
pub static CTX: RefCell<Option<KernelContext<'static, 'static>>> = RefCell::new(None);
|
pub static CTX: RefCell<Option<KernelContext<'static, 'static>>> = RefCell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Kernel {
|
pub struct Kernel
|
||||||
|
{
|
||||||
lua: Lua,
|
lua: Lua,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,18 +26,21 @@ impl Kernel {
|
||||||
// TODO: Take parser as arg and
|
// TODO: Take parser as arg and
|
||||||
// iterate over the rules
|
// iterate over the rules
|
||||||
// to find export the bindings (if some)
|
// to find export the bindings (if some)
|
||||||
pub fn new(parser: &dyn Parser) -> Self {
|
pub fn new(parser: &dyn Parser) -> Self {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
let nml_table = lua.create_table().unwrap();
|
let nml_table = lua.create_table().unwrap();
|
||||||
|
|
||||||
for rule in parser.rules() {
|
for rule in parser.rules()
|
||||||
if let Some(bindings) = rule.lua_bindings(&lua) {
|
{
|
||||||
|
if let Some(bindings) = rule.lua_bindings(&lua)
|
||||||
|
{
|
||||||
let table = lua.create_table().unwrap();
|
let table = lua.create_table().unwrap();
|
||||||
let name = rule.name().to_lowercase().replace(' ', "_");
|
let name = rule.name().to_lowercase();
|
||||||
|
|
||||||
for (fun_name, fun) in bindings {
|
for (fun_name, fun) in bindings
|
||||||
|
{
|
||||||
table.set(fun_name, fun).unwrap();
|
table.set(fun_name, fun).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,15 +51,16 @@ impl Kernel {
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { lua }
|
Self { lua }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a procedure with a context
|
/// Runs a procedure with a context
|
||||||
///
|
///
|
||||||
/// This is the only way lua code shoule be ran, because exported
|
/// This is the only way lua code shoule be ran, because exported
|
||||||
/// functions may require the context in order to operate
|
/// 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
|
where
|
||||||
F: FnOnce(&Lua) -> T,
|
F: FnOnce(&Lua) -> T
|
||||||
{
|
{
|
||||||
CTX.set(Some(unsafe { std::mem::transmute(context) }));
|
CTX.set(Some(unsafe { std::mem::transmute(context) }));
|
||||||
let ret = f(&self.lua);
|
let ret = f(&self.lua);
|
||||||
|
@ -67,7 +70,8 @@ impl Kernel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait KernelHolder {
|
pub trait KernelHolder
|
||||||
|
{
|
||||||
fn get_kernel(&self, name: &str) -> Option<RefMut<'_, Kernel>>;
|
fn get_kernel(&self, name: &str) -> Option<RefMut<'_, Kernel>>;
|
||||||
|
|
||||||
fn insert_kernel(&self, name: String, kernel: Kernel) -> RefMut<'_, Kernel>;
|
fn insert_kernel(&self, name: String, kernel: Kernel) -> RefMut<'_, Kernel>;
|
||||||
|
|
Loading…
Reference in a new issue