Allow boolean & update error for byte literals in html! (#3441)

* made byte & boolean literals accepted by html

* improved error message, outruled byte-string to HTML conversion

* update tests
This commit is contained in:
Tim Kurdov 2024-10-12 13:30:13 +01:00 committed by GitHub
parent 197e2d51bc
commit 4978b998fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 31 deletions

View File

@ -17,9 +17,19 @@ pub enum HtmlNode {
impl Parse for HtmlNode {
fn parse(input: ParseStream) -> Result<Self> {
let node = if HtmlNode::peek(input.cursor()).is_some() {
let lit: Lit = input.parse()?;
if matches!(lit, Lit::ByteStr(_) | Lit::Byte(_) | Lit::Verbatim(_)) {
return Err(syn::Error::new(lit.span(), "unsupported type"));
let lit = input.parse()?;
match lit {
Lit::ByteStr(lit) => {
return Err(syn::Error::new(
lit.span(),
"byte-strings can't be converted to HTML text
note: remove the `b` prefix or convert this to a `String`",
))
}
Lit::Verbatim(lit) => {
return Err(syn::Error::new(lit.span(), "unsupported literal"))
}
_ => (),
}
HtmlNode::Literal(Box::new(lit))
} else {

View File

@ -1,3 +1,6 @@
use std::borrow::Cow;
use std::mem::size_of;
use proc_macro2::{Span, TokenStream};
use quote::{quote_spanned, ToTokens};
use syn::spanned::Spanned;
@ -75,15 +78,19 @@ impl Stringify for LitStr {
}
}
}
impl Stringify for Lit {
fn try_into_lit(&self) -> Option<LitStr> {
let s = match self {
let mut buf = [0; size_of::<char>()];
let s: Cow<'_, str> = match self {
Lit::Str(v) => return v.try_into_lit(),
Lit::Char(v) => v.value().to_string(),
Lit::Int(v) => v.base10_digits().to_string(),
Lit::Float(v) => v.base10_digits().to_string(),
Lit::Bool(_) | Lit::ByteStr(_) | Lit::Byte(_) | Lit::Verbatim(_) => return None,
_ => unreachable!("unknown Lit"),
Lit::Char(v) => (&*v.value().encode_utf8(&mut buf)).into(),
Lit::Int(v) => v.base10_digits().into(),
Lit::Float(v) => v.base10_digits().into(),
Lit::Bool(v) => if v.value() { "true" } else { "false" }.into(),
Lit::Byte(v) => v.value().to_string().into(),
Lit::Verbatim(_) | Lit::ByteStr(_) => return None,
_ => unreachable!("unknown Lit {:?}", self),
};
Some(LitStr::new(&s, self.span()))
}
@ -91,10 +98,10 @@ impl Stringify for Lit {
fn stringify(&self) -> TokenStream {
self.try_into_lit()
.as_ref()
.map(Stringify::stringify)
.unwrap_or_else(|| stringify_at_runtime(self))
.map_or_else(|| stringify_at_runtime(self), Stringify::stringify)
}
}
impl Stringify for Expr {
fn try_into_lit(&self) -> Option<LitStr> {
if let Expr::Lit(v) = self {
@ -107,7 +114,6 @@ impl Stringify for Expr {
fn stringify(&self) -> TokenStream {
self.try_into_lit()
.as_ref()
.map(Stringify::stringify)
.unwrap_or_else(|| stringify_at_runtime(self))
.map_or_else(|| stringify_at_runtime(self), Stringify::stringify)
}
}

View File

@ -10,25 +10,15 @@ error: unexpected token, expected `}`
5 | html! { <span>{ "valid" "invalid" }</span> };
| ^^^^^^^^^
error: unsupported type
--> tests/html_macro/node-fail.rs:10:14
|
10 | html! { b'a' };
| ^^^^
error: unsupported type
error: byte-strings can't be converted to HTML text
note: remove the `b` prefix or convert this to a `String`
--> tests/html_macro/node-fail.rs:11:14
|
11 | html! { b"str" };
| ^^^^^^
error: unsupported type
--> tests/html_macro/node-fail.rs:12:22
|
12 | html! { <span>{ b'a' }</span> };
| ^^^^
error: unsupported type
error: byte-strings can't be converted to HTML text
note: remove the `b` prefix or convert this to a `String`
--> tests/html_macro/node-fail.rs:13:22
|
13 | html! { <span>{ b"str" }</span> };

View File

@ -37,12 +37,12 @@ pub struct u8;
pub struct usize;
fn main() {
_ = ::yew::html! { "" };
_ = ::yew::html! { b'b' };
_ = ::yew::html! { 'a' };
_ = ::yew::html! { "hello" };
_ = ::yew::html! { "42" };
_ = ::yew::html! { "1.234" };
_ = ::yew::html! { "true" };
_ = ::yew::html! { 42 };
_ = ::yew::html! { 1.234 };
_ = ::yew::html! { true };
_ = ::yew::html! { <span>{ "" }</span> };
_ = ::yew::html! { <span>{ 'a' }</span> };