Skip to content

Commit

Permalink
Extract binding logic (fixes #1)
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksrutins committed Jun 4, 2024
1 parent 3b0db8c commit 1b42da2
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 45 deletions.
74 changes: 74 additions & 0 deletions src/bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use kuchiki::{Attribute, ElementData, ExpandedName, NodeData};
use lazy_static::lazy_static;
use regex::{Captures, Regex};

use crate::template::TemplateContext;

pub struct BindingContext<'a> {
node: &'a NodeData,
ctx: &'a TemplateContext
}

lazy_static! {
pub static ref BIND_REGEX: Regex = Regex::new(r"[^\!]?\{\{(?P<var>.*?)\}\}").unwrap();
pub static ref LITERAL_BIND_REGEX: Regex = Regex::new(r"\!\{\{").unwrap();
}

impl<'a> BindingContext<'a> {
pub fn new(node: &'a NodeData, ctx: &'a TemplateContext) -> Self {
Self {
node, ctx
}
}

pub fn expand_attributes(&self) {
if let NodeData::Element(element) = self.node {
let mut attrs = element.attributes.borrow_mut();
for (name, value) in attrs.map.clone() {
if name.local.starts_with('[') && name.local.ends_with(']') {
attrs.map.insert(
ExpandedName::new(
"",
name.local
.clone()
.strip_prefix('[')
.unwrap()
.strip_suffix(']')
.unwrap(),
),
Attribute {
prefix: None,
value: self.ctx
.attrs
.get(&ExpandedName::new("", value.value))
.map(|attr| attr.value.clone())
.unwrap_or_default(),
},
);
}
}
}
}

pub fn expand_text(&self) {
if let NodeData::Text(text_ref) = self.node {
let mut text = text_ref.borrow_mut();
*text = BIND_REGEX
.replace_all(&text, |caps: &Captures| {
if let Some(name) = caps.get(1) {
self.ctx.attrs
.get(&ExpandedName::new("", name.as_str()))
.map(|attr| attr.value.clone())
.unwrap_or_default()
} else {
"".to_string()
}
})
.to_string();
*text = LITERAL_BIND_REGEX
.replace_all(&text, "{{")
.to_string();

}
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod config;
mod markdown;
mod server;
mod template;
mod bindings;

const BUILD_DIR: &str = "_build";

Expand Down
54 changes: 9 additions & 45 deletions src/template.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use html5ever::{local_name, ns, QualName};
use kuchiki::{traits::*, Attribute, ExpandedName, NodeData, NodeRef};
use lazy_static::lazy_static;
use regex::{Captures, Regex};
use std::{
cell::RefCell,
Expand All @@ -10,7 +11,7 @@ use std::{
rc::Rc,
};

use crate::{config::SETTINGS, markdown};
use crate::{bindings::BindingContext, config::SETTINGS, markdown};

#[derive(Clone, Debug)]
pub struct Template {
Expand Down Expand Up @@ -92,8 +93,6 @@ impl Template {
ctx: &TemplateContext,
) -> Result<(), Box<dyn Error>> {
let scripts_ref_cloned = scripts_ref.clone();
let bind_regex = Regex::new(r"[^\!]?\{\{(?P<var>.*?)\}\}").unwrap();
let literal_bind_regex = Regex::new(r"\!\{\{").unwrap();
let node = root.deref_mut();

let settings = SETTINGS.lock().unwrap();
Expand Down Expand Up @@ -152,33 +151,11 @@ impl Template {
self.expand_tree_recursive(&mut child, scripts_ref, registrar, ctx)?;
}

let binding = BindingContext::new(node.data(), ctx);
match node.data() {
NodeData::Element(el) => {
let mut attrs = el.attributes.borrow_mut();
for (name, value) in attrs.map.clone() {
if name.local.starts_with('[') && name.local.ends_with(']') {
attrs.map.insert(
ExpandedName::new(
"",
name.local
.clone()
.strip_prefix('[')
.unwrap()
.strip_suffix(']')
.unwrap(),
),
Attribute {
prefix: None,
value: ctx
.attrs
.get(&ExpandedName::new("", value.value))
.map(|attr| attr.value.clone())
.unwrap_or_default(),
},
);
}
}
drop(attrs);
binding.expand_attributes();

if el.name.local.to_string().contains('-') {
let (rendered_contents, new_scripts) = ctx
.loader
Expand Down Expand Up @@ -220,28 +197,13 @@ impl Template {
}
}
NodeData::Text(text_ref) => {
let mut text = text_ref.borrow_mut();
*text = bind_regex
.replace_all(&text, |caps: &Captures| {
if let Some(name) = caps.get(1) {
ctx.attrs
.get(&ExpandedName::new("", name.as_str()))
.map(|attr| attr.value.clone())
.unwrap_or_default()
} else {
"".to_string()
}
})
.to_string();
*text = literal_bind_regex
.replace_all(&text, "{{")
.to_string();
binding.expand_text();

if let Some(registrar) = registrar {
registrar
.borrow_mut()
.connected_scripts
.push(text.to_string());
.push(text_ref.borrow().to_string());
node.detach();
};
}
Expand Down Expand Up @@ -296,6 +258,8 @@ impl Template {
) -> Result<(NodeRef, HashMap<String, ElementRegistrar>), Box<dyn Error>> {
match &self.extends {
Some(tmpl) => {
BindingContext::new(tmpl.data(), ctx).expand_attributes();

let attrs = tmpl.as_element().unwrap().attributes.borrow();
let (contents, scripts) = self.render_basic(ctx)?;
let new_scripts = Rc::new(RefCell::new(HashMap::new()));
Expand Down

0 comments on commit 1b42da2

Please sign in to comment.