Skip to content

feat: support for custom node #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 11, 2023
Merged

Conversation

ModProg
Copy link

@ModProg ModProg commented Sep 30, 2023

fixes #11

@ModProg
Copy link
Author

ModProg commented Sep 30, 2023

@vldm

I added parse_custom next to parse_simple and made parse_simple use Infallible, sadly type defaults are not supported on functions. It might make sense to do similar for other functions in order to avoid having to specify the generic.

Trying to implement a CustomNode for this syntax as a test, I noticed that we should probably expose more helpers to help with rstml syntax:

#[derive(Debug, syn_derive::ToTokens)]
struct If {
    token_lt: Token![<],
    token_if: Token![if],
    condition: Expr,
    token_gt: Token![>],
    #[to_tokens(|tokens, val| tokens.append_all(val))]
    children: Vec<Node>,
    close_tag: atoms::CloseTag,
}
html! {
  <if condition>
      children
  </if>
};

condition should use the same parsing, OpenTag::attributes have, i.e., first split the input at > and then parse it.

children should use the same parsing as NodeElement::children, and preferable NodeElement::close_tag as well.

My idea was to add parse_simple_with_ending and parse_node_body to RecoverableContext to allow this:

fn parse_element(
    parser: &mut rstml::recoverable::RecoverableContext,
    input: syn::parse::ParseStream,
) -> Option<Self> {
    let token_lt = parser.parse_simple(input)?;
    let token_if = parser.parse_simple(input)?;
    let (condition, open_tag_end): (_, OpenTagEnd) = parser.parse_simple_with_ending(input)?;
    let (body, close_tag) = if open_tag_end.token_solidus.is_some() {
        // Passed to allow parsing of close_tag
        parser.parse_node_body(&OpenTag {
            token_lt,
            name: parse_quote!(#token_if),
            generics: Default::default(),
            attributes: Default::default(),
            end_tag: open_tag_end.clone(),
        })?
    } else {
        (Vec::new(), None)
    };
    Some(Self {
        token_lt,
        token_if,
        condition,
        open_tag_end,
        body,
        close_tag,
    })
}

@ModProg
Copy link
Author

ModProg commented Oct 1, 2023

@vldm the ci failed due to a case change in tarpaulin AFAICT, I made a separate pr for that #36, and rebased this one

@ModProg ModProg force-pushed the custom-tag-syntax branch 2 times, most recently from ea7a94a to a9aeb58 Compare October 1, 2023 10:58
@vldm
Copy link
Collaborator

vldm commented Oct 9, 2023

@ModProg Sorry, was busy in road trip. I will review pr today.

Copy link
Collaborator

@vldm vldm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work, thanks for contribution.

@ModProg
Copy link
Author

ModProg commented Oct 9, 2023

For example, using parse_simple_with_ending in If prevent user from using > (great sign, compare operator) in condition, but allows to use < which i find controversial.

This is also true for attributes, though, isn't it? It should be documented, but that seems like a weakness of the syntax in general, not just of this usage (though comparisons are probably more likely in an if than in an attribute).

@vldm
Copy link
Collaborator

vldm commented Oct 9, 2023

For example, using parse_simple_with_ending in If prevent user from using > (great sign, compare operator) in condition, but allows to use < which i find controversial.

This is also true for attributes, though, isn't it? It should be documented, but that seems like a weakness of the syntax in general, not just of this usage (though comparisons are probably more likely in an if than in an attribute).

Yes, this is true for attributes, and yes this should be documented.
But my point was about making methods public, not if implementation.

@ModProg ModProg force-pushed the custom-tag-syntax branch from a9aeb58 to 711fcfd Compare October 9, 2023 15:26
@ModProg
Copy link
Author

ModProg commented Oct 9, 2023

One consideration, currently I'm using Infallible as the pseudo-! type.

But one problem is, that that means, we need the custom to_tokens function in CustomNode and cannot use the ToTokens trait, as Infallible doesn't implement ToTokens.

We could instead use our own Never type to work around that, or keep the additional trait method as is..

@codecov-commenter
Copy link

Codecov Report

Merging #34 (f2be1ef) into main (aa9d210) will decrease coverage by 0.09%.
The diff coverage is 86.30%.

❗ Current head f2be1ef differs from pull request most recent head 1907a7a. Consider uploading reports for the commit 1907a7a to get more accurate results

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

@@            Coverage Diff             @@
##             main      #34      +/-   ##
==========================================
- Coverage   77.31%   77.23%   -0.09%     
==========================================
  Files          11       12       +1     
  Lines         692      751      +59     
==========================================
+ Hits          535      580      +45     
- Misses        157      171      +14     
Files Coverage Δ
src/config.rs 73.21% <100.00%> (+11.05%) ⬆️
src/lib.rs 42.85% <100.00%> (+17.85%) ⬆️
src/node/raw_text.rs 93.75% <100.00%> (-2.00%) ⬇️
src/parser/mod.rs 70.00% <100.00%> (-14.85%) ⬇️
src/parser/recoverable.rs 70.00% <100.00%> (+12.85%) ⬆️
src/node/mod.rs 60.86% <60.00%> (-4.99%) ⬇️
src/node/parser_ext.rs 80.00% <80.00%> (ø)
src/node/parse.rs 86.52% <82.14%> (-3.35%) ⬇️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@vldm
Copy link
Collaborator

vldm commented Oct 9, 2023

One consideration, currently I'm using Infallible as the pseudo-! type.

But one problem is, that that means, we need the custom to_tokens function in CustomNode and cannot use the ToTokens trait, as Infallible doesn't implement ToTokens.

We could instead use our own Never type to work around that, or keep the additional trait method as is..

I am think current approach with custom trait and Infallible is good enough.

I‘d rather have adapter (wrapper type, or macro) that will derive implementation from ToTokens/Parse. For those who want implementation of this trait effortlessly.

@vldm vldm enabled auto-merge October 11, 2023 09:03
@vldm
Copy link
Collaborator

vldm commented Oct 11, 2023

Awesome!

@vldm vldm added this pull request to the merge queue Oct 11, 2023
Merged via the queue into rs-tml:main with commit de04b27 Oct 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Custom punct before blocks
3 participants