clean up and document items
This commit is contained in:
1 parent
71d31556e5
commit
8ed8758d35
7 files changed
+59
-59
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
use crate::elements::*;
|
use crate::elements::*;
|
||||||
|
|
||||||
// find the mapped attribute name
|
// map the rsx name of the attribute to the html name of the attribute and the namespace that contains it
|
||||||
pub fn attrbute_to_static_str(attr: &str) -> Option<(&'static str, Option<&'static str>)> {
|
pub fn attrbute_to_static_str(attr: &str) -> Option<(&'static str, Option<&'static str>)> {
|
||||||
NO_NAMESPACE_ATTRIBUTES
|
NO_NAMESPACE_ATTRIBUTES
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use dioxus_rsx::{
|
|||||||
};
|
};
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
use quote::{quote, ToTokens, TokenStreamExt};
|
||||||
use syn::{Expr, Ident, Result};
|
use syn::{Expr, Ident, Result};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct CapturedContextBuilder {
|
pub struct CapturedContextBuilder {
|
||||||
pub ifmted: Vec<IfmtInput>,
|
pub ifmted: Vec<IfmtInput>,
|
||||||
@@ -146,7 +145,7 @@ impl ToTokens for CapturedContextBuilder {
|
|||||||
pub struct CapturedContext<'a> {
|
pub struct CapturedContext<'a> {
|
||||||
// map of the variable name to the formated value
|
// map of the variable name to the formated value
|
||||||
pub captured: IfmtArgs,
|
pub captured: IfmtArgs,
|
||||||
// // map of the attribute name and element path to the formated value
|
// map of the attribute name and element path to the formated value
|
||||||
// pub captured_attribute_values: IfmtArgs,
|
// pub captured_attribute_values: IfmtArgs,
|
||||||
// the only thing we can update in component is the children
|
// the only thing we can update in component is the children
|
||||||
pub components: Vec<(&'static str, VNode<'a>)>,
|
pub components: Vec<(&'static str, VNode<'a>)>,
|
||||||
@@ -159,10 +158,11 @@ pub struct CapturedContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct IfmtArgs {
|
pub struct IfmtArgs {
|
||||||
// map expressions to the value string they produced
|
// All expressions that have been resolved
|
||||||
pub named_args: Vec<FormattedArg>,
|
pub named_args: Vec<FormattedArg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A formated segment that has been resolved
|
||||||
pub struct FormattedArg {
|
pub struct FormattedArg {
|
||||||
pub expr: &'static str,
|
pub expr: &'static str,
|
||||||
pub format_args: &'static str,
|
pub format_args: &'static str,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// find the mapped attribute name
|
// map the rsx name of the element to the html name of the element and the namespace that contains it
|
||||||
pub fn element_to_static_str(element: &str) -> Option<(&'static str, Option<&'static str>)> {
|
pub fn element_to_static_str(element: &str) -> Option<(&'static str, Option<&'static str>)> {
|
||||||
ELEMENTS_WITH_MAPPED_ATTRIBUTES
|
ELEMENTS_WITH_MAPPED_ATTRIBUTES
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// An error produced when interperting the rsx
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
ParseError(syn::Error),
|
ParseError(syn::Error),
|
||||||
|
|||||||
@@ -8,43 +8,39 @@ use crate::captuered_context::{CapturedContext, IfmtArgs};
|
|||||||
use crate::elements::element_to_static_str;
|
use crate::elements::element_to_static_str;
|
||||||
use crate::error::{Error, RecompileReason};
|
use crate::error::{Error, RecompileReason};
|
||||||
|
|
||||||
struct InterpertedIfmt(IfmtInput);
|
fn resolve_ifmt(ifmt: &IfmtInput, captured: &IfmtArgs) -> Result<String, Error> {
|
||||||
|
let mut result = String::new();
|
||||||
impl InterpertedIfmt {
|
for seg in &ifmt.segments {
|
||||||
fn resolve(&self, captured: &IfmtArgs) -> Result<String, Error> {
|
match seg {
|
||||||
let mut result = String::new();
|
Segment::Formatted {
|
||||||
for seg in &self.0.segments {
|
segment,
|
||||||
match seg {
|
format_args,
|
||||||
Segment::Formatted {
|
} => {
|
||||||
segment,
|
let expr = segment.to_token_stream();
|
||||||
format_args,
|
let expr: Expr = parse2(expr).unwrap();
|
||||||
} => {
|
let search = captured.named_args.iter().find(|fmted| {
|
||||||
let expr = segment.to_token_stream();
|
parse_str::<Expr>(fmted.expr).unwrap() == expr
|
||||||
let expr: Expr = parse2(expr).unwrap();
|
&& fmted.format_args == format_args
|
||||||
let search = captured.named_args.iter().find(|fmted| {
|
});
|
||||||
parse_str::<Expr>(fmted.expr).unwrap() == expr
|
match search {
|
||||||
&& fmted.format_args == format_args
|
Some(formatted) => {
|
||||||
});
|
result.push_str(&formatted.result);
|
||||||
match search {
|
}
|
||||||
Some(formatted) => {
|
None => {
|
||||||
result.push_str(&formatted.result);
|
let expr_str = segment.to_token_stream().to_string();
|
||||||
}
|
return Err(Error::RecompileRequiredError(
|
||||||
None => {
|
RecompileReason::CapturedExpression(format!(
|
||||||
let expr_str = segment.to_token_stream().to_string();
|
"could not resolve {{{}:{}}}",
|
||||||
return Err(Error::RecompileRequiredError(
|
expr_str, format_args
|
||||||
RecompileReason::CapturedExpression(format!(
|
)),
|
||||||
"could not resolve {{{}:{}}}",
|
));
|
||||||
expr_str, format_args
|
|
||||||
)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Segment::Literal(lit) => result.push_str(lit),
|
|
||||||
}
|
}
|
||||||
|
Segment::Literal(lit) => result.push_str(lit),
|
||||||
}
|
}
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build<'a>(
|
pub fn build<'a>(
|
||||||
@@ -67,10 +63,8 @@ fn build_node<'a>(
|
|||||||
let bump = factory.bump();
|
let bump = factory.bump();
|
||||||
match node {
|
match node {
|
||||||
BodyNode::Text(text) => {
|
BodyNode::Text(text) => {
|
||||||
let ifmt = InterpertedIfmt(
|
let ifmt = IfmtInput::from_str(&text.value()).map_err(|err| Error::ParseError(err))?;
|
||||||
IfmtInput::from_str(&text.value()).map_err(|err| Error::ParseError(err))?,
|
let text = bump.alloc(resolve_ifmt(&ifmt, &ctx.captured)?);
|
||||||
);
|
|
||||||
let text = bump.alloc(ifmt.resolve(&ctx.captured)?);
|
|
||||||
Ok(factory.text(format_args!("{}", text)))
|
Ok(factory.text(format_args!("{}", text)))
|
||||||
}
|
}
|
||||||
BodyNode::Element(el) => {
|
BodyNode::Element(el) => {
|
||||||
@@ -78,26 +72,22 @@ fn build_node<'a>(
|
|||||||
for attr in &el.attributes {
|
for attr in &el.attributes {
|
||||||
match &attr.attr {
|
match &attr.attr {
|
||||||
ElementAttr::AttrText { .. } | ElementAttr::CustomAttrText { .. } => {
|
ElementAttr::AttrText { .. } | ElementAttr::CustomAttrText { .. } => {
|
||||||
let (name, value): (String, InterpertedIfmt) = match &attr.attr {
|
let (name, value): (String, IfmtInput) = match &attr.attr {
|
||||||
ElementAttr::AttrText { name, value } => (
|
ElementAttr::AttrText { name, value } => (
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
InterpertedIfmt(
|
IfmtInput::from_str(&value.value())
|
||||||
IfmtInput::from_str(&value.value())
|
.map_err(|err| Error::ParseError(err))?,
|
||||||
.map_err(|err| Error::ParseError(err))?,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ElementAttr::CustomAttrText { name, value } => (
|
ElementAttr::CustomAttrText { name, value } => (
|
||||||
name.value(),
|
name.value(),
|
||||||
InterpertedIfmt(
|
IfmtInput::from_str(&value.value())
|
||||||
IfmtInput::from_str(&value.value())
|
.map_err(|err| Error::ParseError(err))?,
|
||||||
.map_err(|err| Error::ParseError(err))?,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((name, namespace)) = attrbute_to_static_str(&name) {
|
if let Some((name, namespace)) = attrbute_to_static_str(&name) {
|
||||||
let value = bump.alloc(value.resolve(&ctx.captured)?);
|
let value = bump.alloc(resolve_ifmt(&value, &ctx.captured)?);
|
||||||
attributes.push(Attribute {
|
attributes.push(Attribute {
|
||||||
name,
|
name,
|
||||||
value: AttributeValue::Text(value),
|
value: AttributeValue::Text(value),
|
||||||
@@ -188,10 +178,9 @@ fn build_node<'a>(
|
|||||||
None,
|
None,
|
||||||
)),
|
)),
|
||||||
Some(lit) => {
|
Some(lit) => {
|
||||||
let ifmt: InterpertedIfmt = InterpertedIfmt(
|
let ifmt: IfmtInput =
|
||||||
parse_str(&lit.value()).map_err(|err| Error::ParseError(err))?,
|
parse_str(&lit.value()).map_err(|err| Error::ParseError(err))?;
|
||||||
);
|
let key = bump.alloc(resolve_ifmt(&ifmt, &ctx.captured)?);
|
||||||
let key = bump.alloc(ifmt.resolve(&ctx.captured)?);
|
|
||||||
|
|
||||||
Ok(factory.raw_element(
|
Ok(factory.raw_element(
|
||||||
tag,
|
tag,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ lazy_static! {
|
|||||||
pub static ref RSX_CONTEXT: RsxContext = RsxContext::new(RsxData::default());
|
pub static ref RSX_CONTEXT: RsxContext = RsxContext::new(RsxData::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the location of the code relative to the current crate based on [std::panic::Location]
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct CodeLocation {
|
pub struct CodeLocation {
|
||||||
pub file: String,
|
pub file: String,
|
||||||
@@ -29,6 +30,7 @@ pub struct CodeLocation {
|
|||||||
pub column: u32,
|
pub column: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the resolved rsx given the origional rsx, a captured context of dynamic components, and a factory to build the resulting node
|
||||||
pub fn resolve_scope<'a>(
|
pub fn resolve_scope<'a>(
|
||||||
location: CodeLocation,
|
location: CodeLocation,
|
||||||
rsx: &'static str,
|
rsx: &'static str,
|
||||||
@@ -57,7 +59,7 @@ pub fn resolve_scope<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpert_rsx<'a, 'b>(
|
fn interpert_rsx<'a, 'b>(
|
||||||
factory: dioxus_core::NodeFactory<'a>,
|
factory: dioxus_core::NodeFactory<'a>,
|
||||||
text: &str,
|
text: &str,
|
||||||
context: captuered_context::CapturedContext<'a>,
|
context: captuered_context::CapturedContext<'a>,
|
||||||
@@ -69,6 +71,7 @@ pub fn interpert_rsx<'a, 'b>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get the code location of the code that called this function
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn get_line_num() -> CodeLocation {
|
pub fn get_line_num() -> CodeLocation {
|
||||||
let location = Location::caller();
|
let location = Location::caller();
|
||||||
@@ -79,11 +82,13 @@ pub fn get_line_num() -> CodeLocation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A handle to the rsx context with interior mutability
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RsxContext {
|
pub struct RsxContext {
|
||||||
data: RwLock<RsxData>,
|
data: RwLock<RsxData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A store of the text for the rsx macro for each call to rsx
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct RsxData {
|
pub struct RsxData {
|
||||||
pub hm: HashMap<CodeLocation, String>,
|
pub hm: HashMap<CodeLocation, String>,
|
||||||
@@ -104,6 +109,7 @@ impl RsxContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the text for an rsx call at some location
|
||||||
pub fn insert(&self, loc: CodeLocation, text: String) {
|
pub fn insert(&self, loc: CodeLocation, text: String) {
|
||||||
let mut write = self.data.write().unwrap();
|
let mut write = self.data.write().unwrap();
|
||||||
write.hm.insert(loc, text);
|
write.hm.insert(loc, text);
|
||||||
@@ -112,25 +118,29 @@ impl RsxContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self) -> RwLockReadGuard<RsxData> {
|
fn read(&self) -> RwLockReadGuard<RsxData> {
|
||||||
self.data.read().unwrap()
|
self.data.read().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_error(&self, error: Error) {
|
fn report_error(&self, error: Error) {
|
||||||
if let Some(handler) = &self.data.write().unwrap().error_handler {
|
if let Some(handler) = &self.data.write().unwrap().error_handler {
|
||||||
handler.handle_error(error)
|
handler.handle_error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the handler for errors interperting the rsx
|
||||||
pub fn set_error_handler(&self, handler: impl ErrorHandler + 'static) {
|
pub fn set_error_handler(&self, handler: impl ErrorHandler + 'static) {
|
||||||
self.data.write().unwrap().error_handler = Some(Box::new(handler));
|
self.data.write().unwrap().error_handler = Some(Box::new(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provide the scduler channel from [dioxus_code::VirtualDom::get_scheduler_channel].
|
||||||
|
/// The channel allows the interpreter to force re-rendering of the dom when the rsx is changed.
|
||||||
pub fn provide_scheduler_channel(&self, channel: UnboundedSender<SchedulerMsg>) {
|
pub fn provide_scheduler_channel(&self, channel: UnboundedSender<SchedulerMsg>) {
|
||||||
self.data.write().unwrap().scheduler_channel = Some(channel)
|
self.data.write().unwrap().scheduler_channel = Some(channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A error handler for errors reported by the rsx interperter
|
||||||
pub trait ErrorHandler: Send + Sync {
|
pub trait ErrorHandler: Send + Sync {
|
||||||
fn handle_error(&self, err: Error);
|
fn handle_error(&self, err: Error);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -65,6 +65,6 @@ pub mod prelude {
|
|||||||
#[cfg(feature = "hot_reload")]
|
#[cfg(feature = "hot_reload")]
|
||||||
pub use dioxus_rsx_interpreter::{
|
pub use dioxus_rsx_interpreter::{
|
||||||
captuered_context::{CapturedContext, FormattedArg, IfmtArgs},
|
captuered_context::{CapturedContext, FormattedArg, IfmtArgs},
|
||||||
get_line_num, interpert_rsx, resolve_scope, CodeLocation, RsxContext,
|
get_line_num, resolve_scope, CodeLocation, RsxContext,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user