Skip to content

Commit

Permalink
feat: rsx parser
Browse files Browse the repository at this point in the history
  • Loading branch information
mrchantey committed Jan 14, 2025
1 parent 77b1d59 commit ac8293c
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 177 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ rustc-ice*
target
tests/assert.rs
tests/expect.rs
index.html
# crates/sweet_site/src/out
1 change: 1 addition & 0 deletions crates/sweet_core/src/rsx/hydrate_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct HydratedBlock {
/// The index of the part in the node
/// ie for `hello {name}` the part index would be 1
pub part_index: usize,
pub initial_value: String,
}


Expand Down
10 changes: 7 additions & 3 deletions crates/sweet_core/src/rsx/rsx_parts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ use crate::prelude::*;
use std::path::PathBuf;


/// All information required to hydrate an rsx! macro.
#[derive(Debug)]
/// Information for a particular rsx! macro.
/// This is not the final parse step, we need another pass to
/// build the component tree and reassign attributes.
// #[derive(Debug)]
pub struct RsxParts {
pub hydrate_item: Hydrated,
pub events: Vec<HydratedEvent>,
// the initial value of blocks
pub blocks: Vec<String>,
pub html: PathOrInline,
}

Expand Down
3 changes: 3 additions & 0 deletions crates/sweet_parse/src/reconciler/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod reconciler;
#[allow(unused_imports)]
pub use self::reconciler::*;
75 changes: 75 additions & 0 deletions crates/sweet_parse/src/reconciler/reconciler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@



/// Encoding for text and blocks.
/// The 'nodes' provided by rstml are not real, ie text, rawtext and block nodes will
/// be mashed into a single text node. We need to track the position of the block nodes
/// in the original string so it can be split up again by the renderer.
/// The format is like so
///
/// child_index - first-block-index , first-block-length , second-block-index , second-block-length . child_index2 etc
///
/// ## Example
/// ```html
/// <div>the 10th <bold>value</bold> was 9</div>
/// ```
/// Output:
/// 0-4,2.2-5,1
///
///








/// Interim encoding for block positions.
/// each block is a double: child index, start index
/// # Note:
/// Raw text nodes are trimmed
fn encode_text_block_positions<C>(children: &Vec<Node<C>>) -> String {
let mut encoded = String::new();
let mut child_index = 0;
let mut text_index = 0;
for child in children {
match child {
Node::RawText(t) => {
text_index += t.to_string_best().len();
}
Node::Text(t) => {
text_index += t.value_string().len();
}
Node::Block(_) => {
encoded.push_str(&format!("{},{},", child_index, text_index));
}
_ => {
if text_node_end(child) {
child_index += 1;
text_index = 0;
continue;
}
}
}
}
if encoded.len() > 0 {
encoded.pop();
}
encoded
}
/// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#value
fn text_node_end<C>(child: &Node<C>) -> bool {
match child {
Node::Comment(_) => true,
Node::Doctype(_) => true,
// rsx fragment, not DOCUMENT_FRAGMENT
Node::Fragment(_) => false,
Node::Element(_) => true,
Node::Block(_) => false,
Node::Text(_) => false,
Node::RawText(_) => false,
Node::Custom(_) => todo!("is the custom node virtual or a html node?"),
}
}
3 changes: 0 additions & 3 deletions crates/sweet_parse/src/rsx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ pub use self::parse_rstml::*;
pub mod rsx_file_visitor;
#[allow(unused_imports)]
pub use self::rsx_file_visitor::*;
pub mod rsx_parts_tokens;
#[allow(unused_imports)]
pub use self::rsx_parts_tokens::*;
pub mod rsx_plugin;
#[allow(unused_imports)]
pub use self::rsx_plugin::*;
Expand Down
2 changes: 1 addition & 1 deletion crates/sweet_parse/src/rsx/parse_rstml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn _join_html_and_rust(
WalkNodesOutput {
// collected_elements,
errors: diagnostics,
html_string,
html: html_string,
// dynamic_attributes,
rust_blocks: values,
..
Expand Down
4 changes: 2 additions & 2 deletions crates/sweet_parse/src/rsx/rsx_file_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ use syn::ExprMacro;
pub struct RsxFileVisitor<'a, P> {
plugin: &'a mut P,
/// The rsx macros found in the function
macros: Vec<RsxPartsTokens>,
macros: Vec<WalkNodesOutput>,
/// Errors that occurred while parsing the rsx macro
errors: Vec<syn::Error>,
}

pub struct RsxFileVisitorOut {
pub macros: Vec<RsxPartsTokens>,
pub macros: Vec<WalkNodesOutput>,
pub errors: Vec<syn::Error>,
}

Expand Down
85 changes: 0 additions & 85 deletions crates/sweet_parse/src/rsx/rsx_parts_tokens.rs

This file was deleted.

21 changes: 10 additions & 11 deletions crates/sweet_parse/src/rsx/rsx_plugin.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::RsxFileVisitor;
use super::RsxFileVisitorOut;
use super::RsxPartsTokens;
use super::WalkNodesOutput;
use proc_macro2::TokenStream;
use rstml::node::CustomNode;
use rstml::node::KeyedAttribute;
use rstml::node::NodeBlock;
use rstml::node::NodeElement;
use syn::visit_mut::VisitMut;
use syn::Expr;
Expand All @@ -17,24 +17,22 @@ pub trait RsxPlugin: Sized {
/// Called when visiting an rsx [Expr::Macro],
/// passed as an [Expr] so that the macro can be replaced.
/// see [macro_or_err] for an easy map.
fn visit_rsx(&mut self, item: &mut Expr) -> syn::Result<RsxPartsTokens>;
fn visit_rsx(&mut self, item: &mut Expr) -> syn::Result<WalkNodesOutput>;

fn visit_block(&mut self, block: &NodeBlock, output: &mut WalkNodesOutput);
fn visit_event(
&mut self,
item: &KeyedAttribute,
output: &mut WalkNodesOutput,
) -> syn::Result<()>;
);

/// Opportunity to mutate an element before attributes and children are visited.
/// Opportunity to view children, useful for text node block encoding
#[allow(unused_variables)]
fn visit_element<C: CustomNode>(
&mut self,
el: &mut NodeElement<C>,
el: &NodeElement<C>,
output: &mut WalkNodesOutput,
) -> syn::Result<()> {
Ok(())
}

);

/// specify the identifier that will be parsed
fn macro_ident() -> &'static str { "rsx" }
Expand All @@ -58,9 +56,10 @@ pub trait RsxPlugin: Sized {
fn parse_tokens(
&mut self,
tokens: TokenStream,
) -> syn::Result<RsxPartsTokens> {
) -> syn::Result<(Expr, WalkNodesOutput)> {
let mut expr: Expr = syn::parse2(tokens)?;
self.visit_rsx(&mut expr)
let output = self.visit_rsx(&mut expr)?;
Ok((expr, output))
}
}

Expand Down
Loading

0 comments on commit ac8293c

Please sign in to comment.