فهرست منبع

fix autoformatting raw strings

Evan Almloff 2 سال پیش
والد
کامیت
d9e0b9a918

+ 3 - 1
packages/autofmt/src/buffer.rs

@@ -8,6 +8,8 @@ use std::fmt::{Result, Write};
 
 use dioxus_rsx::IfmtInput;
 
+use crate::write_ifmt;
+
 /// The output buffer that tracks indent and string
 #[derive(Debug, Default)]
 pub struct Buffer {
@@ -48,7 +50,7 @@ impl Buffer {
     }
 
     pub fn write_text(&mut self, text: &IfmtInput) -> Result {
-        write!(self.buf, "\"{}\"", text.source.as_ref().unwrap().value())
+        write_ifmt(text, &mut self.buf)
     }
 }
 

+ 4 - 4
packages/autofmt/src/component.rs

@@ -1,4 +1,4 @@
-use crate::{writer::Location, Writer};
+use crate::{ifmt_to_string, writer::Location, Writer};
 use dioxus_rsx::*;
 use quote::ToTokens;
 use std::fmt::{Result, Write};
@@ -170,9 +170,9 @@ impl Writer<'_> {
                 ContentField::Formatted(s) => {
                     write!(
                         self.out,
-                        "{}: \"{}\"",
+                        "{}: {}",
                         name,
-                        s.source.as_ref().unwrap().value()
+                        s.source.as_ref().unwrap().to_token_stream()
                     )?;
                 }
                 ContentField::OnHandlerRaw(exp) => {
@@ -215,7 +215,7 @@ impl Writer<'_> {
         let attr_len = fields
             .iter()
             .map(|field| match &field.content {
-                ContentField::Formatted(s) => s.source.as_ref().unwrap().value().len() ,
+                ContentField::Formatted(s) => ifmt_to_string(s).len() ,
                 ContentField::OnHandlerRaw(exp) | ContentField::ManExpr(exp) => {
                     let formatted = prettyplease::unparse_expr(exp);
                     let len = if formatted.contains('\n') {

+ 11 - 18
packages/autofmt/src/element.rs

@@ -1,6 +1,7 @@
-use crate::Writer;
+use crate::{ifmt_to_string, Writer};
 use dioxus_rsx::*;
 use proc_macro2::Span;
+use quote::ToTokens;
 use std::{
     fmt::Result,
     fmt::{self, Write},
@@ -175,11 +176,7 @@ impl Writer<'_> {
             if !sameline {
                 self.out.indented_tabbed_line()?;
             }
-            write!(
-                self.out,
-                "key: \"{}\"",
-                key.source.as_ref().unwrap().value()
-            )?;
+            write!(self.out, "key: {}", ifmt_to_string(key))?;
             if !attributes.is_empty() {
                 write!(self.out, ",")?;
                 if sameline {
@@ -216,11 +213,7 @@ impl Writer<'_> {
     fn write_attribute(&mut self, attr: &ElementAttrNamed) -> Result {
         match &attr.attr {
             ElementAttr::AttrText { name, value } => {
-                write!(
-                    self.out,
-                    "{name}: \"{value}\"",
-                    value = value.source.as_ref().unwrap().value()
-                )?;
+                write!(self.out, "{name}: {value}", value = ifmt_to_string(value))?;
             }
             ElementAttr::AttrExpression { name, value } => {
                 let out = prettyplease::unparse_expr(value);
@@ -230,15 +223,15 @@ impl Writer<'_> {
             ElementAttr::CustomAttrText { name, value } => {
                 write!(
                     self.out,
-                    "\"{name}\": \"{value}\"",
-                    name = name.value(),
-                    value = value.source.as_ref().unwrap().value()
+                    "{name}: {value}",
+                    name = name.to_token_stream(),
+                    value = ifmt_to_string(value)
                 )?;
             }
 
             ElementAttr::CustomAttrExpression { name, value } => {
                 let out = prettyplease::unparse_expr(value);
-                write!(self.out, "\"{}\": {}", name.value(), out)?;
+                write!(self.out, "{}: {}", name.to_token_stream(), out)?;
             }
 
             ElementAttr::EventTokens { name, tokens } => {
@@ -315,7 +308,7 @@ impl Writer<'_> {
         }
 
         match children {
-            [BodyNode::Text(ref text)] => Some(text.source.as_ref().unwrap().value().len()),
+            [BodyNode::Text(ref text)] => Some(ifmt_to_string(text).len()),
             [BodyNode::Component(ref comp)] => {
                 let attr_len = self.field_len(&comp.fields, &comp.manual_props);
 
@@ -338,7 +331,7 @@ impl Writer<'_> {
 
                 if el.children.len() == 1 {
                     if let BodyNode::Text(ref text) = el.children[0] {
-                        let value = text.source.as_ref().unwrap().value();
+                        let value = ifmt_to_string(text);
 
                         if value.len() + el.name.to_string().len() + attr_len < 80 {
                             return Some(value.len() + el.name.to_string().len() + attr_len);
@@ -356,7 +349,7 @@ impl Writer<'_> {
                     match item {
                         BodyNode::Component(_) | BodyNode::Element(_) => return None,
                         BodyNode::Text(text) => {
-                            total_count += text.source.as_ref().unwrap().value().len()
+                            total_count += ifmt_to_string(text).len();
                         }
                         BodyNode::RawExpr(expr) => match get_expr_length(expr) {
                             Some(len) => total_count += len,

+ 25 - 3
packages/autofmt/src/lib.rs

@@ -1,7 +1,10 @@
+use std::fmt::{Display, Write};
+
 use crate::writer::*;
 use collect_macros::byte_offset;
-use dioxus_rsx::{BodyNode, CallBody};
+use dioxus_rsx::{BodyNode, CallBody, IfmtInput};
 use proc_macro2::LineColumn;
+use quote::ToTokens;
 use syn::{ExprMacro, MacroDelimiter};
 
 mod buffer;
@@ -130,8 +133,6 @@ pub fn write_block_out(body: CallBody) -> Option<String> {
 }
 
 fn write_body(buf: &mut Writer, body: &CallBody) {
-    use std::fmt::Write;
-
     if buf.is_short_children(&body.roots).is_some() {
         // write all the indents with spaces and commas between
         for idx in 0..body.roots.len() - 1 {
@@ -208,3 +209,24 @@ pub fn apply_formats(input: &str, blocks: Vec<FormattedBlock>) -> String {
 
     out
 }
+
+struct DisplayIfmt<'a>(&'a IfmtInput);
+
+impl Display for DisplayIfmt<'_> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let inner_tokens = self.0.source.as_ref().unwrap().to_token_stream();
+        inner_tokens.fmt(f)
+    }
+}
+
+pub(crate) fn ifmt_to_string(input: &IfmtInput) -> String {
+    let mut buf = String::new();
+    let display = DisplayIfmt(input);
+    write!(&mut buf, "{}", display).unwrap();
+    buf
+}
+
+pub(crate) fn write_ifmt(input: &IfmtInput, writable: &mut impl Write) -> std::fmt::Result {
+    let display = DisplayIfmt(input);
+    write!(writable, "{}", display)
+}

+ 4 - 3
packages/autofmt/src/writer.rs

@@ -8,6 +8,7 @@ use std::{
 use syn::{spanned::Spanned, Expr, ExprIf};
 
 use crate::buffer::Buffer;
+use crate::ifmt_to_string;
 
 #[derive(Debug)]
 pub struct Writer<'a> {
@@ -147,16 +148,16 @@ impl<'a> Writer<'a> {
 
             total += match &attr.attr {
                 ElementAttr::AttrText { value, name } => {
-                    value.source.as_ref().unwrap().value().len() + name.span().line_length() + 6
+                    ifmt_to_string(value).len() + name.span().line_length() + 6
                 }
                 ElementAttr::AttrExpression { name, value } => {
                     value.span().line_length() + name.span().line_length() + 6
                 }
                 ElementAttr::CustomAttrText { value, name } => {
-                    value.source.as_ref().unwrap().value().len() + name.value().len() + 6
+                    ifmt_to_string(value).len() + name.to_token_stream().to_string().len() + 6
                 }
                 ElementAttr::CustomAttrExpression { name, value } => {
-                    name.value().len() + value.span().line_length() + 6
+                    name.to_token_stream().to_string().len() + value.span().line_length() + 6
                 }
                 ElementAttr::EventTokens { tokens, name } => {
                     let location = Location::new(tokens.span().start());

+ 21 - 17
packages/autofmt/tests/samples.rs

@@ -4,8 +4,8 @@ macro_rules! twoway {
 
             // doc attrs
             $( #[doc = $doc:expr] )*
-            $name:ident
-        ),*
+            $name:ident,
+        )*
     ) => {
         $(
             $( #[doc = $doc] )*
@@ -14,6 +14,9 @@ macro_rules! twoway {
                 let src = include_str!(concat!("./samples/", stringify!($name), ".rsx"));
                 let formatted = dioxus_autofmt::fmt_file(src);
                 let out = dioxus_autofmt::apply_formats(src, formatted);
+                // normalize line endings
+                let out = out.replace("\r", "");
+                let src = src.replace("\r", "");
                 pretty_assertions::assert_eq!(&src, &out);
             }
         )*
@@ -21,24 +24,25 @@ macro_rules! twoway {
 }
 
 twoway![
-    simple,
-    comments,
     attributes,
-    manual_props,
-    complex,
-    tiny,
-    tinynoopt,
-    long,
-    key,
-    multirsx,
+    collapse_expr,
+    comments,
     commentshard,
+    complex,
     emoji,
-    messy_indent,
-    long_exprs,
     ifchain_forloop,
-    t2,
-    reallylong,
     immediate_expr,
-    collapse_expr,
-    trailing_expr
+    key,
+    long_exprs,
+    long,
+    manual_props,
+    messy_indent,
+    multirsx,
+    raw_strings,
+    reallylong,
+    simple,
+    t2,
+    tiny,
+    tinynoopt,
+    trailing_expr,
 ];

+ 3 - 1
packages/autofmt/tests/samples/complex.rsx

@@ -13,7 +13,9 @@ rsx! {
 
     // Complex nesting with handlers
     li {
-        Link { class: "flex items-center pl-3 py-3 pr-4 {active_class} rounded", to: "{to}",
+        Link {
+            class: "flex items-center pl-3 py-3 pr-4 {active_class} rounded",
+            to: "{to}",
             span { class: "inline-block mr-3", icons::icon_0 {} }
             span { "{name}" }
             children.is_some().then(|| rsx! {

+ 12 - 0
packages/autofmt/tests/samples/raw_strings.rsx

@@ -0,0 +1,12 @@
+rsx! {
+    // Raw text strings
+    button { r#"Click me"#, r##"Click me"##, r######"Click me"######, r#"dynamic {1}"# }
+
+    // Raw attribute strings
+    div {
+        width: r#"10px"#,
+        height: r##"{10}px"##,
+        "raw-attr": r###"raw-attr"###,
+        "raw-attr2": r###"{100}"###
+    }
+}

+ 5 - 0
packages/autofmt/tests/wrong.rs

@@ -6,6 +6,11 @@ macro_rules! twoway {
             let src_wrong = include_str!(concat!("./wrong/", $val, ".wrong.rsx"));
             let formatted = dioxus_autofmt::fmt_file(src_wrong);
             let out = dioxus_autofmt::apply_formats(src_wrong, formatted);
+
+            // normalize line endings
+            let out = out.replace("\r", "");
+            let src_right = src_right.replace("\r", "");
+
             pretty_assertions::assert_eq!(&src_right, &out);
         }
     };