Blockquotes style

This commit is contained in:
ef3d0c3e 2024-08-12 22:33:25 +02:00
parent 06fd73c9f9
commit d8fd2feefb
3 changed files with 122 additions and 31 deletions

21
Cargo.lock generated
View file

@ -59,6 +59,16 @@ dependencies = [
"syn 2.0.72",
]
[[package]]
name = "auto-registry"
version = "0.0.4"
dependencies = [
"lazy_static",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "auto_impl"
version = "1.2.0"
@ -733,6 +743,7 @@ name = "nml"
version = "0.1.0"
dependencies = [
"ariadne",
"auto-registry",
"dashmap 6.0.1",
"downcast-rs",
"getopts",
@ -743,6 +754,7 @@ dependencies = [
"mlua",
"rand 0.8.5",
"regex",
"runtime-format",
"rusqlite",
"rust-crypto",
"serde",
@ -1094,6 +1106,15 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "runtime-format"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09958d5b38bca768ede7928c767c89a08ba568144a7b61992aecae79b03c8c94"
dependencies = [
"tinyvec",
]
[[package]]
name = "rusqlite"
version = "0.31.0"

View file

@ -17,6 +17,7 @@ inherits = "release"
debug = true
[dependencies]
auto-registry = { path = "crates/auto-registry" }
ariadne = "0.4.1"
dashmap = "6.0.1"
downcast-rs = "1.2.1"
@ -32,11 +33,16 @@ rust-crypto = "0.2.36"
serde = "1.0.204"
serde_json = "1.0.120"
syntect = "5.2.0"
tokio = { version = "1.38.1", features = ["macros", "rt-multi-thread", "io-std"]}
tokio = { version = "1.38.1", features = [
"macros",
"rt-multi-thread",
"io-std",
] }
tower-lsp = "0.20.0"
unicode-segmentation = "1.11.0"
walkdir = "2.5.0"
runtime-format = "0.1.3"
[dev-dependencies]
rand = "0.8.5"

View file

@ -1,3 +1,4 @@
use core::fmt;
use std::any::Any;
use std::collections::HashMap;
use std::ops::Range;
@ -11,9 +12,13 @@ use blockquote_style::AuthorPos::Before;
use blockquote_style::BlockquoteStyle;
use regex::Match;
use regex::Regex;
use runtime_fmt::rt_format;
use runtime_format::FormatArgs;
use runtime_format::FormatError;
use runtime_format::FormatKey;
use runtime_format::FormatKeyError;
use crate::compiler::compiler::Compiler;
use crate::compiler::compiler::Target;
use crate::compiler::compiler::Target::HTML;
use crate::document::document::Document;
use crate::document::element::ContainerElement;
@ -42,6 +47,28 @@ pub struct Blockquote {
pub(self) style: Rc<blockquote_style::BlockquoteStyle>,
}
struct FmtPair<'a>(Target, &'a Blockquote);
impl FormatKey for FmtPair<'_> {
fn fmt(&self, key: &str, f: &mut fmt::Formatter<'_>) -> Result<(), FormatKeyError> {
match key {
"author" => write!(
f,
"{}",
Compiler::sanitize(self.0, self.1.author.as_ref().unwrap_or(&"".into()))
)
.map_err(FormatKeyError::Fmt),
"cite" => write!(
f,
"{}",
Compiler::sanitize(self.0, self.1.cite.as_ref().unwrap_or(&"".into()))
)
.map_err(FormatKeyError::Fmt),
_ => Err(FormatKeyError::UnknownKey),
}
}
}
impl Element for Blockquote {
fn location(&self) -> &Token { &self.location }
@ -53,34 +80,32 @@ impl Element for Blockquote {
match compiler.target() {
HTML => {
let mut result = r#"<div class="blockquote-content">"#.to_string();
let format_author = || -> Result<String, runtime_fmt::Error> {
let format_author = || -> Result<String, FormatError> {
let mut result = String::new();
if self.cite.is_some() || self.author.is_some() {
result += r#"<p class="blockquote-author">"#;
match (&self.author, &self.cite) {
(Some(author), Some(cite)) => {
result += rt_format!(
self.style.format[0].as_str(),
author,
format!("<cite>{}</cite>", Compiler::sanitize(HTML, cite)),
)?
.as_str();
let fmt_pair = FmtPair(compiler.target(), &self);
match (self.author.is_some(), self.cite.is_some()) {
(true, true) => {
let args =
FormatArgs::new(self.style.format[0].as_str(), &fmt_pair);
args.status()?;
result += args.to_string().as_str();
}
(Some(author), None) => {
result += rt_format!(
self.style.format[1].as_str(),
Compiler::sanitize(HTML, author),
)?
.as_str()
(true, false) => {
let args =
FormatArgs::new(self.style.format[1].as_str(), &fmt_pair);
args.status()?;
result += args.to_string().as_str();
}
(None, Some(cite)) => {
result += rt_format!(
self.style.format[2].as_str(),
format!("<cite>{}</cite>", Compiler::sanitize(HTML, cite)),
)?
.as_str()
(false, false) => {
let args =
FormatArgs::new(self.style.format[2].as_str(), &fmt_pair);
args.status()?;
result += args.to_string().as_str();
}
(None, None) => panic!(""),
_ => panic!(""),
}
result += "</p>";
}
@ -94,7 +119,7 @@ impl Element for Blockquote {
result += "<blockquote>";
}
if self.style.author_pos == Before {
result += format_author().as_str();
result += format_author().map_err(|err| err.to_string())?.as_str();
}
result += "<p>";
@ -103,7 +128,7 @@ impl Element for Blockquote {
}
result += "</p></blockquote>";
if self.style.author_pos == After {
result += format_author().as_str();
result += format_author().map_err(|err| err.to_string())?.as_str();
}
result += "</div>";
@ -371,9 +396,9 @@ mod blockquote_style {
Self {
author_pos: AuthorPos::After,
format: [
"A{author}, {cite}".into(),
"B{author}".into(),
"C{cite}".into(),
"{author}, {cite}".into(),
"{author}".into(),
"{cite}".into(),
],
}
}
@ -409,8 +434,7 @@ AFTER
None,
));
let parser = LangParser::default();
let state = ParserState::new(&parser, None);
let (doc, _) = parser.parse(state, source, None);
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
validate_document!(doc.content().borrow(), 0,
Paragraph { Text{ content == "BEFORE" }; };
@ -427,4 +451,44 @@ AFTER
Paragraph { Text{ content == "AFTER" }; };
);
}
#[test]
pub fn style() {
let source = Rc::new(SourceFile::with_content(
"".to_string(),
r#"
@@style.blockquote = {
"author_pos": "Before",
"format": ["{cite} by {author}", "Author: {author}", "From: {cite}"]
}
PRE
>[author=A, cite=B, url=C] Some entry
> contin**ued here
> **
AFTER
"#
.to_string(),
None,
));
let parser = LangParser::default();
let (_, state) = parser.parse(ParserState::new(&parser, None), source, None);
let style = state
.shared
.styles
.borrow()
.current(blockquote_style::STYLE_KEY)
.downcast_rc::<BlockquoteStyle>()
.unwrap();
assert_eq!(style.author_pos, Before);
assert_eq!(
style.format,
[
"{cite} by {author}".to_string(),
"Author: {author}".to_string(),
"From: {cite}".to_string()
]
);
}
}