Skip to content

Commit

Permalink
Merge #546
Browse files Browse the repository at this point in the history
546: Support dashed custom tag names r=jstarry a=jstarry

Fixes #193

Co-authored-by: Justin Starry <jstarry@users.noreply.github.com>
  • Loading branch information
bors[bot] and jstarry committed Jul 31, 2019
2 parents 7311cf0 + f2e0f48 commit af9d05b
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 170 deletions.
4 changes: 2 additions & 2 deletions crates/macro/src/html_tree/html_block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::html_iterable::HtmlIterable;
use super::html_node::HtmlNode;
use crate::Peek;
use crate::PeekValue;
use proc_macro2::Delimiter;
use quote::{quote, quote_spanned, ToTokens};
use syn::braced;
Expand All @@ -18,7 +18,7 @@ enum BlockContent {
Iterable(HtmlIterable),
}

impl Peek<()> for HtmlBlock {
impl PeekValue<()> for HtmlBlock {
fn peek(cursor: Cursor) -> Option<()> {
cursor.group(Delimiter::Brace).map(|_| ())
}
Expand Down
6 changes: 3 additions & 3 deletions crates/macro/src/html_tree/html_component.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::HtmlProp;
use super::HtmlPropSuffix;
use crate::Peek;
use crate::PeekValue;
use boolinator::Boolinator;
use proc_macro2::Span;
use quote::{quote, quote_spanned, ToTokens};
Expand All @@ -12,7 +12,7 @@ use syn::{Ident, Token, Type};

pub struct HtmlComponent(HtmlComponentInner);

impl Peek<()> for HtmlComponent {
impl PeekValue<()> for HtmlComponent {
fn peek(cursor: Cursor) -> Option<()> {
let (punct, cursor) = cursor.punct()?;
(punct.as_char() == '<').as_option()?;
Expand Down Expand Up @@ -214,7 +214,7 @@ enum Props {
With(WithProps),
}

impl Peek<PropType> for Props {
impl PeekValue<PropType> for Props {
fn peek(cursor: Cursor) -> Option<PropType> {
let (ident, _) = cursor.ident()?;
let prop_type = if ident.to_string() == "with" {
Expand Down
86 changes: 86 additions & 0 deletions crates/macro/src/html_tree/html_dashed_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use crate::Peek;
use boolinator::Boolinator;
use proc_macro2::Ident;
use proc_macro2::Span;
use quote::{quote, ToTokens};
use std::fmt;
use syn::buffer::Cursor;
use syn::parse::{Parse, ParseStream, Result as ParseResult};
use syn::Token;

#[derive(PartialEq)]
pub struct HtmlDashedName {
pub name: Ident,
pub extended: Vec<(Token![-], Ident)>,
}

impl HtmlDashedName {
pub fn new(name: Ident) -> Self {
HtmlDashedName {
name,
extended: Vec::new(),
}
}
}

impl fmt::Display for HtmlDashedName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)?;
for (_, ident) in &self.extended {
write!(f, "-{}", ident)?;
}
Ok(())
}
}

impl Peek<'_, Self> for HtmlDashedName {
fn peek(cursor: Cursor) -> Option<(Self, Cursor)> {
let (name, cursor) = cursor.ident()?;
(name.to_string().to_lowercase() == name.to_string()).as_option()?;

let mut extended = Vec::new();
let mut cursor = cursor;
loop {
if let Some((punct, p_cursor)) = cursor.punct() {
if punct.as_char() == '-' {
let (ident, i_cursor) = p_cursor.ident()?;
cursor = i_cursor;
extended.push((Token![-](Span::call_site()), ident));
continue;
}
}
break;
}

Some((HtmlDashedName { name, extended }, cursor))
}
}

impl Parse for HtmlDashedName {
fn parse(input: ParseStream) -> ParseResult<Self> {
let name = if let Ok(token) = input.parse::<Token![type]>() {
Ident::new("type", token.span).into()
} else if let Ok(token) = input.parse::<Token![for]>() {
Ident::new("for", token.span).into()
} else {
input.parse::<Ident>()?.into()
};

let mut extended = Vec::new();
while input.peek(Token![-]) {
extended.push((input.parse::<Token![-]>()?, input.parse::<Ident>()?));
}

Ok(HtmlDashedName { name, extended })
}
}

impl ToTokens for HtmlDashedName {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let HtmlDashedName { name, extended } = self;
let dashes = extended.iter().map(|(dash, _)| quote! {#dash});
let idents = extended.iter().map(|(_, ident)| quote! {#ident});
let extended = quote! { #(#dashes#idents)* };
tokens.extend(quote! {#name#extended});
}
}
4 changes: 2 additions & 2 deletions crates/macro/src/html_tree/html_iterable.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Peek;
use crate::PeekValue;
use boolinator::Boolinator;
use proc_macro2::TokenStream;
use quote::{quote_spanned, ToTokens};
Expand All @@ -9,7 +9,7 @@ use syn::{Expr, Token};

pub struct HtmlIterable(Expr);

impl Peek<()> for HtmlIterable {
impl PeekValue<()> for HtmlIterable {
fn peek(cursor: Cursor) -> Option<()> {
let (ident, _) = cursor.ident()?;
(ident.to_string() == "for").as_option()
Expand Down
8 changes: 4 additions & 4 deletions crates/macro/src/html_tree/html_list.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::HtmlTree;
use crate::Peek;
use crate::PeekValue;
use boolinator::Boolinator;
use quote::{quote, ToTokens};
use syn::buffer::Cursor;
Expand All @@ -8,7 +8,7 @@ use syn::Token;

pub struct HtmlList(pub Vec<HtmlTree>);

impl Peek<()> for HtmlList {
impl PeekValue<()> for HtmlList {
fn peek(cursor: Cursor) -> Option<()> {
HtmlListOpen::peek(cursor)
.or_else(|| HtmlListClose::peek(cursor))
Expand Down Expand Up @@ -88,7 +88,7 @@ struct HtmlListOpen {
gt: Token![>],
}

impl Peek<()> for HtmlListOpen {
impl PeekValue<()> for HtmlListOpen {
fn peek(cursor: Cursor) -> Option<()> {
let (punct, cursor) = cursor.punct()?;
(punct.as_char() == '<').as_option()?;
Expand Down Expand Up @@ -120,7 +120,7 @@ struct HtmlListClose {
gt: Token![>],
}

impl Peek<()> for HtmlListClose {
impl PeekValue<()> for HtmlListClose {
fn peek(cursor: Cursor) -> Option<()> {
let (punct, cursor) = cursor.punct()?;
(punct.as_char() == '<').as_option()?;
Expand Down
4 changes: 2 additions & 2 deletions crates/macro/src/html_tree/html_node.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Peek;
use crate::PeekValue;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::buffer::Cursor;
Expand All @@ -25,7 +25,7 @@ impl Parse for HtmlNode {
}
}

impl Peek<()> for HtmlNode {
impl PeekValue<()> for HtmlNode {
fn peek(cursor: Cursor) -> Option<()> {
cursor.literal().map(|_| ()).or_else(|| {
let (ident, _) = cursor.ident()?;
Expand Down
76 changes: 8 additions & 68 deletions crates/macro/src/html_tree/html_prop.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use crate::Peek;
use crate::html_tree::HtmlDashedName as HtmlPropLabel;
use crate::{Peek, PeekValue};
use boolinator::Boolinator;
use proc_macro::TokenStream;
use proc_macro2::{Ident, TokenTree};
use quote::{quote, ToTokens};
use std::fmt;
use proc_macro2::TokenTree;
use syn::buffer::Cursor;
use syn::parse::{Parse, ParseStream, Result as ParseResult};
use syn::{Expr, Token};
Expand All @@ -13,17 +12,11 @@ pub struct HtmlProp {
pub value: Expr,
}

impl Peek<()> for HtmlProp {
fn peek(mut cursor: Cursor) -> Option<()> {
loop {
let (_, c) = cursor.ident()?;
let (punct, c) = c.punct()?;
if punct.as_char() == '-' {
cursor = c;
continue;
}
return (punct.as_char() == '=').as_option();
}
impl PeekValue<()> for HtmlProp {
fn peek(cursor: Cursor) -> Option<()> {
let (_, cursor) = HtmlPropLabel::peek(cursor)?;
let (punct, _) = cursor.punct()?;
return (punct.as_char() == '=').as_option();
}
}

Expand Down Expand Up @@ -87,56 +80,3 @@ impl Parse for HtmlPropSuffix {
Ok(HtmlPropSuffix { div, gt, stream })
}
}

pub struct HtmlPropLabel {
pub name: Ident,
pub extended: Vec<(Token![-], Ident)>,
}

impl HtmlPropLabel {
pub fn new(name: Ident) -> Self {
HtmlPropLabel {
name,
extended: Vec::new(),
}
}
}

impl fmt::Display for HtmlPropLabel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)?;
for (_, ident) in &self.extended {
write!(f, "-{}", ident)?;
}
Ok(())
}
}

impl Parse for HtmlPropLabel {
fn parse(input: ParseStream) -> ParseResult<Self> {
let name = if let Ok(token) = input.parse::<Token![type]>() {
Ident::new("type", token.span).into()
} else if let Ok(token) = input.parse::<Token![for]>() {
Ident::new("for", token.span).into()
} else {
input.parse::<Ident>()?.into()
};

let mut extended = Vec::new();
while input.peek(Token![-]) {
extended.push((input.parse::<Token![-]>()?, input.parse::<Ident>()?));
}

Ok(HtmlPropLabel { name, extended })
}
}

impl ToTokens for HtmlPropLabel {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let HtmlPropLabel { name, extended } = self;
let dashes = extended.iter().map(|(dash, _)| quote! {#dash});
let idents = extended.iter().map(|(_, ident)| quote! {#ident});
let extended = quote! { #(#dashes#idents)* };
tokens.extend(quote! {#name#extended});
}
}
Loading

0 comments on commit af9d05b

Please sign in to comment.