|
@@ -1,35 +1,56 @@
|
|
-use crate::Buffer;
|
|
|
|
|
|
+use crate::Writer;
|
|
use dioxus_rsx::*;
|
|
use dioxus_rsx::*;
|
|
use proc_macro2::Span;
|
|
use proc_macro2::Span;
|
|
-use std::{fmt::Result, fmt::Write};
|
|
|
|
-use syn::{spanned::Spanned, Expr};
|
|
|
|
|
|
+use std::{
|
|
|
|
+ fmt::Result,
|
|
|
|
+ fmt::{self, Write},
|
|
|
|
+};
|
|
|
|
+use syn::{spanned::Spanned, token::Brace, Expr};
|
|
|
|
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
enum ShortOptimization {
|
|
enum ShortOptimization {
|
|
- // Special because we want to print the closing bracket immediately
|
|
|
|
|
|
+ /// Special because we want to print the closing bracket immediately
|
|
|
|
+ ///
|
|
|
|
+ /// IE
|
|
|
|
+ /// `div {}` instead of `div { }`
|
|
Empty,
|
|
Empty,
|
|
|
|
|
|
- // Special optimization to put everything on the same line
|
|
|
|
|
|
+ /// Special optimization to put everything on the same line and add some buffer spaces
|
|
|
|
+ ///
|
|
|
|
+ /// IE
|
|
|
|
+ ///
|
|
|
|
+ /// `div { "asdasd" }` instead of a multiline variant
|
|
Oneliner,
|
|
Oneliner,
|
|
|
|
|
|
- // Optimization where children flow but props remain fixed on top
|
|
|
|
|
|
+ /// Optimization where children flow but props remain fixed on top
|
|
PropsOnTop,
|
|
PropsOnTop,
|
|
|
|
|
|
- // The noisiest optimization where everything flows
|
|
|
|
|
|
+ /// The noisiest optimization where everything flows
|
|
NoOpt,
|
|
NoOpt,
|
|
}
|
|
}
|
|
|
|
|
|
-impl Buffer {
|
|
|
|
- pub fn write_element(
|
|
|
|
- &mut self,
|
|
|
|
- Element {
|
|
|
|
|
|
+/*
|
|
|
|
+// whitespace
|
|
|
|
+div {
|
|
|
|
+ // some whitespace
|
|
|
|
+ class: "asdasd"
|
|
|
|
+
|
|
|
|
+ // whjiot
|
|
|
|
+ asdasd // whitespace
|
|
|
|
+}
|
|
|
|
+*/
|
|
|
|
+
|
|
|
|
+impl Writer {
|
|
|
|
+ pub fn write_element(&mut self, el: &Element) -> Result {
|
|
|
|
+ let Element {
|
|
name,
|
|
name,
|
|
key,
|
|
key,
|
|
attributes,
|
|
attributes,
|
|
children,
|
|
children,
|
|
_is_static,
|
|
_is_static,
|
|
- }: &Element,
|
|
|
|
- ) -> Result {
|
|
|
|
|
|
+ brace,
|
|
|
|
+ } = el;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
1. Write the tag
|
|
1. Write the tag
|
|
2. Write the key
|
|
2. Write the key
|
|
@@ -37,7 +58,7 @@ impl Buffer {
|
|
4. Write the children
|
|
4. Write the children
|
|
*/
|
|
*/
|
|
|
|
|
|
- write!(self.buf, "{name} {{")?;
|
|
|
|
|
|
+ write!(self.out, "{name} {{")?;
|
|
|
|
|
|
// decide if we have any special optimizations
|
|
// decide if we have any special optimizations
|
|
// Default with none, opt the cases in one-by-one
|
|
// Default with none, opt the cases in one-by-one
|
|
@@ -70,6 +91,9 @@ impl Buffer {
|
|
// If there's nothing at all, empty optimization
|
|
// If there's nothing at all, empty optimization
|
|
if attributes.is_empty() && children.is_empty() && key.is_none() {
|
|
if attributes.is_empty() && children.is_empty() && key.is_none() {
|
|
opt_level = ShortOptimization::Empty;
|
|
opt_level = ShortOptimization::Empty;
|
|
|
|
+
|
|
|
|
+ // Write comments if they exist
|
|
|
|
+ self.write_todo_body(brace)?;
|
|
}
|
|
}
|
|
|
|
|
|
// multiline handlers bump everything down
|
|
// multiline handlers bump everything down
|
|
@@ -80,56 +104,56 @@ impl Buffer {
|
|
match opt_level {
|
|
match opt_level {
|
|
ShortOptimization::Empty => {}
|
|
ShortOptimization::Empty => {}
|
|
ShortOptimization::Oneliner => {
|
|
ShortOptimization::Oneliner => {
|
|
- write!(self.buf, " ")?;
|
|
|
|
|
|
+ write!(self.out, " ")?;
|
|
|
|
|
|
self.write_attributes(attributes, key, true)?;
|
|
self.write_attributes(attributes, key, true)?;
|
|
|
|
|
|
if !children.is_empty() && (!attributes.is_empty() || key.is_some()) {
|
|
if !children.is_empty() && (!attributes.is_empty() || key.is_some()) {
|
|
- write!(self.buf, ", ")?;
|
|
|
|
|
|
+ write!(self.out, ", ")?;
|
|
}
|
|
}
|
|
|
|
|
|
for (id, child) in children.iter().enumerate() {
|
|
for (id, child) in children.iter().enumerate() {
|
|
self.write_ident(child)?;
|
|
self.write_ident(child)?;
|
|
if id != children.len() - 1 && children.len() > 1 {
|
|
if id != children.len() - 1 && children.len() > 1 {
|
|
- write!(self.buf, ", ")?;
|
|
|
|
|
|
+ write!(self.out, ", ")?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- write!(self.buf, " ")?;
|
|
|
|
|
|
+ write!(self.out, " ")?;
|
|
}
|
|
}
|
|
|
|
|
|
ShortOptimization::PropsOnTop => {
|
|
ShortOptimization::PropsOnTop => {
|
|
if !attributes.is_empty() || key.is_some() {
|
|
if !attributes.is_empty() || key.is_some() {
|
|
- write!(self.buf, " ")?;
|
|
|
|
|
|
+ write!(self.out, " ")?;
|
|
}
|
|
}
|
|
self.write_attributes(attributes, key, true)?;
|
|
self.write_attributes(attributes, key, true)?;
|
|
|
|
|
|
if !children.is_empty() && (!attributes.is_empty() || key.is_some()) {
|
|
if !children.is_empty() && (!attributes.is_empty() || key.is_some()) {
|
|
- write!(self.buf, ",")?;
|
|
|
|
|
|
+ write!(self.out, ",")?;
|
|
}
|
|
}
|
|
|
|
|
|
if !children.is_empty() {
|
|
if !children.is_empty() {
|
|
self.write_body_indented(children)?;
|
|
self.write_body_indented(children)?;
|
|
}
|
|
}
|
|
- self.tabbed_line()?;
|
|
|
|
|
|
+ self.out.tabbed_line()?;
|
|
}
|
|
}
|
|
|
|
|
|
ShortOptimization::NoOpt => {
|
|
ShortOptimization::NoOpt => {
|
|
self.write_attributes(attributes, key, false)?;
|
|
self.write_attributes(attributes, key, false)?;
|
|
|
|
|
|
if !children.is_empty() && (!attributes.is_empty() || key.is_some()) {
|
|
if !children.is_empty() && (!attributes.is_empty() || key.is_some()) {
|
|
- write!(self.buf, ",")?;
|
|
|
|
|
|
+ write!(self.out, ",")?;
|
|
}
|
|
}
|
|
|
|
|
|
if !children.is_empty() {
|
|
if !children.is_empty() {
|
|
self.write_body_indented(children)?;
|
|
self.write_body_indented(children)?;
|
|
}
|
|
}
|
|
|
|
|
|
- self.tabbed_line()?;
|
|
|
|
|
|
+ self.out.tabbed_line()?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- write!(self.buf, "}}")?;
|
|
|
|
|
|
+ write!(self.out, "}}")?;
|
|
|
|
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
@@ -144,39 +168,39 @@ impl Buffer {
|
|
|
|
|
|
if let Some(key) = key {
|
|
if let Some(key) = key {
|
|
if !sameline {
|
|
if !sameline {
|
|
- self.indented_tabbed_line()?;
|
|
|
|
|
|
+ self.out.indented_tabbed_line()?;
|
|
}
|
|
}
|
|
write!(
|
|
write!(
|
|
- self.buf,
|
|
|
|
|
|
+ self.out,
|
|
"key: \"{}\"",
|
|
"key: \"{}\"",
|
|
key.source.as_ref().unwrap().value()
|
|
key.source.as_ref().unwrap().value()
|
|
)?;
|
|
)?;
|
|
if !attributes.is_empty() {
|
|
if !attributes.is_empty() {
|
|
- write!(self.buf, ",")?;
|
|
|
|
|
|
+ write!(self.out, ",")?;
|
|
if sameline {
|
|
if sameline {
|
|
- write!(self.buf, " ")?;
|
|
|
|
|
|
+ write!(self.out, " ")?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
while let Some(attr) = attr_iter.next() {
|
|
while let Some(attr) = attr_iter.next() {
|
|
- self.indent += 1;
|
|
|
|
|
|
+ self.out.indent += 1;
|
|
if !sameline {
|
|
if !sameline {
|
|
self.write_comments(attr.attr.start())?;
|
|
self.write_comments(attr.attr.start())?;
|
|
}
|
|
}
|
|
- self.indent -= 1;
|
|
|
|
|
|
+ self.out.indent -= 1;
|
|
|
|
|
|
if !sameline {
|
|
if !sameline {
|
|
- self.indented_tabbed_line()?;
|
|
|
|
|
|
+ self.out.indented_tabbed_line()?;
|
|
}
|
|
}
|
|
|
|
|
|
self.write_attribute(attr)?;
|
|
self.write_attribute(attr)?;
|
|
|
|
|
|
if attr_iter.peek().is_some() {
|
|
if attr_iter.peek().is_some() {
|
|
- write!(self.buf, ",")?;
|
|
|
|
|
|
+ write!(self.out, ",")?;
|
|
|
|
|
|
if sameline {
|
|
if sameline {
|
|
- write!(self.buf, " ")?;
|
|
|
|
|
|
+ write!(self.out, " ")?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -188,19 +212,19 @@ impl Buffer {
|
|
match &attr.attr {
|
|
match &attr.attr {
|
|
ElementAttr::AttrText { name, value } => {
|
|
ElementAttr::AttrText { name, value } => {
|
|
write!(
|
|
write!(
|
|
- self.buf,
|
|
|
|
|
|
+ self.out,
|
|
"{name}: \"{value}\"",
|
|
"{name}: \"{value}\"",
|
|
value = value.source.as_ref().unwrap().value()
|
|
value = value.source.as_ref().unwrap().value()
|
|
)?;
|
|
)?;
|
|
}
|
|
}
|
|
ElementAttr::AttrExpression { name, value } => {
|
|
ElementAttr::AttrExpression { name, value } => {
|
|
let out = prettyplease::unparse_expr(value);
|
|
let out = prettyplease::unparse_expr(value);
|
|
- write!(self.buf, "{}: {}", name, out)?;
|
|
|
|
|
|
+ write!(self.out, "{}: {}", name, out)?;
|
|
}
|
|
}
|
|
|
|
|
|
ElementAttr::CustomAttrText { name, value } => {
|
|
ElementAttr::CustomAttrText { name, value } => {
|
|
write!(
|
|
write!(
|
|
- self.buf,
|
|
|
|
|
|
+ self.out,
|
|
"\"{name}\": \"{value}\"",
|
|
"\"{name}\": \"{value}\"",
|
|
name = name.value(),
|
|
name = name.value(),
|
|
value = value.source.as_ref().unwrap().value()
|
|
value = value.source.as_ref().unwrap().value()
|
|
@@ -209,7 +233,7 @@ impl Buffer {
|
|
|
|
|
|
ElementAttr::CustomAttrExpression { name, value } => {
|
|
ElementAttr::CustomAttrExpression { name, value } => {
|
|
let out = prettyplease::unparse_expr(value);
|
|
let out = prettyplease::unparse_expr(value);
|
|
- write!(self.buf, "\"{}\": {}", name.value(), out)?;
|
|
|
|
|
|
+ write!(self.out, "\"{}\": {}", name.value(), out)?;
|
|
}
|
|
}
|
|
|
|
|
|
ElementAttr::EventTokens { name, tokens } => {
|
|
ElementAttr::EventTokens { name, tokens } => {
|
|
@@ -221,17 +245,17 @@ impl Buffer {
|
|
// a one-liner for whatever reason
|
|
// a one-liner for whatever reason
|
|
// Does not need a new line
|
|
// Does not need a new line
|
|
if lines.peek().is_none() {
|
|
if lines.peek().is_none() {
|
|
- write!(self.buf, "{}: {}", name, first)?;
|
|
|
|
|
|
+ write!(self.out, "{}: {}", name, first)?;
|
|
} else {
|
|
} else {
|
|
- writeln!(self.buf, "{}: {}", name, first)?;
|
|
|
|
|
|
+ writeln!(self.out, "{}: {}", name, first)?;
|
|
|
|
|
|
while let Some(line) = lines.next() {
|
|
while let Some(line) = lines.next() {
|
|
- self.indented_tab()?;
|
|
|
|
- write!(self.buf, "{}", line)?;
|
|
|
|
|
|
+ self.out.indented_tab()?;
|
|
|
|
+ write!(self.out, "{}", line)?;
|
|
if lines.peek().is_none() {
|
|
if lines.peek().is_none() {
|
|
- write!(self.buf, "")?;
|
|
|
|
|
|
+ write!(self.out, "")?;
|
|
} else {
|
|
} else {
|
|
- writeln!(self.buf)?;
|
|
|
|
|
|
+ writeln!(self.out)?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -255,8 +279,6 @@ impl Buffer {
|
|
""
|
|
""
|
|
};
|
|
};
|
|
|
|
|
|
- // dbg!(beginning);
|
|
|
|
-
|
|
|
|
beginning.is_empty()
|
|
beginning.is_empty()
|
|
}
|
|
}
|
|
|
|
|
|
@@ -269,6 +291,10 @@ impl Buffer {
|
|
if children.is_empty() {
|
|
if children.is_empty() {
|
|
// todo: allow elements with comments but no children
|
|
// todo: allow elements with comments but no children
|
|
// like div { /* comment */ }
|
|
// like div { /* comment */ }
|
|
|
|
+ // or
|
|
|
|
+ // div {
|
|
|
|
+ // // some helpful
|
|
|
|
+ // }
|
|
return Some(0);
|
|
return Some(0);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -343,6 +369,35 @@ impl Buffer {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /// empty everything except for some comments
|
|
|
|
+ fn write_todo_body(&mut self, brace: &Brace) -> fmt::Result {
|
|
|
|
+ let span = brace.span.span();
|
|
|
|
+ let start = span.start();
|
|
|
|
+ let end = span.end();
|
|
|
|
+
|
|
|
|
+ if start.line == end.line {
|
|
|
|
+ return Ok(());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ writeln!(self.out)?;
|
|
|
|
+
|
|
|
|
+ for idx in start.line..end.line {
|
|
|
|
+ let line = &self.src[idx];
|
|
|
|
+ if line.trim().starts_with("//") {
|
|
|
|
+ for _ in 0..self.out.indent + 1 {
|
|
|
|
+ write!(self.out, " ")?
|
|
|
|
+ }
|
|
|
|
+ writeln!(self.out, "{}", line.trim()).unwrap();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for _ in 0..self.out.indent {
|
|
|
|
+ write!(self.out, " ")?
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
fn get_expr_length(expr: &Expr) -> Option<usize> {
|
|
fn get_expr_length(expr: &Expr) -> Option<usize> {
|