sink.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. use dioxus_autofmt::*;
  2. use proc_macro2::TokenStream as TokenStream2;
  3. use syn::{Attribute, Meta};
  4. fn test_block(wrong: &str, right: &str) {
  5. let formatted = fmt_block(wrong).unwrap();
  6. assert_eq!(formatted, right);
  7. }
  8. fn print_block(wrong: &str) {
  9. let formatted = fmt_block(wrong).unwrap();
  10. println!("{}", formatted);
  11. }
  12. #[test]
  13. fn formats_block() {
  14. let block = r#"
  15. div {
  16. div {
  17. class: "asd",
  18. class: "asd",class: "asd",class: "asd",class: "asd",class: "asd",
  19. key: "ddd",
  20. onclick: move |_| {
  21. let blah = 120;
  22. true
  23. },
  24. blah: 123,
  25. onclick: move |_| {
  26. let blah = 120;
  27. true
  28. },
  29. onclick: move |_| {
  30. let blah = 120;
  31. true
  32. },
  33. onclick: move |_| {
  34. let blah = 120;
  35. true
  36. },
  37. div {
  38. div {
  39. "hi"
  40. }
  41. h2 {
  42. class: "asd",
  43. }
  44. }
  45. Component {}
  46. Component<Generic> {}
  47. }
  48. }
  49. "#;
  50. let formatted = fmt_block(block).unwrap();
  51. println!("{formatted}");
  52. }
  53. #[test]
  54. fn parse_comment() {
  55. let block = r#"
  56. div {
  57. adsasd: "asd", // this is a comment
  58. }
  59. "#;
  60. let parsed: TokenStream2 = syn::parse_str(block).unwrap();
  61. dbg!(parsed);
  62. }
  63. #[test]
  64. fn print_cases() {
  65. print_block(
  66. r#"
  67. div {
  68. adsasd: "asd",
  69. h1 {"asd"}
  70. div {
  71. div {
  72. "hello"
  73. }
  74. div {
  75. "goodbye"
  76. }
  77. div { class: "broccoli",
  78. div {
  79. "hi"
  80. }
  81. }
  82. div { class: "broccolibroccolibroccolibroccolibroccolibroccolibroccolibroccolibroccolibroccoli",
  83. div {
  84. "hi"
  85. }
  86. }
  87. div { class: "alksdjasd", onclick: move |_| {
  88. liberty!();
  89. },
  90. div {
  91. "hi"
  92. }
  93. }
  94. commented{
  95. // is unparalled
  96. class: "asdasd",
  97. // My genius
  98. div {
  99. "hi"
  100. }
  101. }
  102. }
  103. }
  104. "#,
  105. );
  106. }
  107. #[test]
  108. fn formats_component() {
  109. let block = r#"
  110. Component {
  111. adsasd: "asd", // this is a comment
  112. onclick: move |_| {
  113. let blah = 120;
  114. let blah = 120;
  115. },
  116. }
  117. "#;
  118. let formatted = fmt_block(block).unwrap();
  119. println!("{formatted}");
  120. }
  121. #[test]
  122. fn formats_element() {
  123. let block = r#"
  124. div {
  125. a: "1234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910",
  126. a: "123",
  127. a: "123",
  128. a: "123",
  129. a: "123",
  130. a: "123",
  131. a: "123",
  132. a: "123",
  133. a: "123",
  134. }
  135. "#;
  136. let formatted = fmt_block(block).unwrap();
  137. println!("{formatted}");
  138. }
  139. #[test]
  140. fn formats_element_short() {
  141. let block = r#"
  142. div {
  143. a: "123",
  144. a: "123",
  145. a: "123",
  146. a: "123",
  147. a: "123",
  148. a: "123",
  149. a: "123",
  150. a: "123",
  151. a: "123",
  152. }
  153. "#;
  154. let formatted = fmt_block(block).unwrap();
  155. println!("{formatted}");
  156. }
  157. #[test]
  158. fn formats_element_nested() {
  159. let block = r#"
  160. h3 {
  161. class: "mb-2 text-xl font-bold",
  162. "Invite Member"
  163. }
  164. "#;
  165. let formatted = fmt_block(block).unwrap();
  166. assert_eq!(
  167. formatted,
  168. r#"h3 { class: "mb-2 text-xl font-bold", "Invite Member" }"#
  169. );
  170. }
  171. #[test]
  172. fn formats_element_props_on_top() {
  173. let block = r#"
  174. h3 {
  175. class: "mb-2 text-xl font-bold mb-2 text-xl font-bold mb-2 text-xl font-bold mb-2 text-xl font-bold mb-2 text-xl font-bold",
  176. "Invite Member"
  177. }
  178. "#;
  179. let formatted = fmt_block(block).unwrap();
  180. println!("{formatted}");
  181. }
  182. #[test]
  183. fn formats_element_nested_no_trailing_tabs() {
  184. let block = r#"
  185. img { class: "mb-6 mx-auto h-24", src: "artemis-assets/images/friends.png", alt: "", }
  186. "#;
  187. let formatted = fmt_block(block).unwrap();
  188. assert_eq!(
  189. formatted,
  190. r#"img { class: "mb-6 mx-auto h-24", src: "artemis-assets/images/friends.png", alt: "" }"#
  191. );
  192. }
  193. #[test]
  194. fn formats_element_with_correct_indent() {
  195. let block = r###"
  196. div {
  197. a { class: "py-2 px-3 bg-indigo-500 hover:bg-indigo-600 rounded text-xs text-white", href: "#",
  198. "Send invitation"
  199. }
  200. }
  201. "###;
  202. let formatted = fmt_block(block).unwrap();
  203. println!("{formatted}");
  204. }
  205. #[test]
  206. fn small_elements_and_text_are_small() {
  207. let block = r###"
  208. a { class: "text-white",
  209. "Send invitation"
  210. }
  211. "###;
  212. let formatted = fmt_block(block).unwrap();
  213. assert_eq!(formatted, r#"a { class: "text-white", "Send invitation" }"#);
  214. }
  215. #[test]
  216. fn formats_component_man_props() {
  217. let block = r#"
  218. Component {
  219. ..MyProps {
  220. val: 123
  221. },
  222. adsasd: "asd", // this is a comment
  223. onclick: move |_| {
  224. let blah = 120;
  225. },
  226. }
  227. "#;
  228. let formatted = fmt_block(block).unwrap();
  229. println!("{formatted}");
  230. }
  231. #[test]
  232. fn formats_component_tiny() {
  233. let block = r#"
  234. Component { a: 123
  235. }
  236. "#;
  237. let formatted = fmt_block(block).unwrap();
  238. println!("{formatted}");
  239. }
  240. #[test]
  241. fn formats_exprs() {
  242. let block = r#"
  243. ul {
  244. div {}
  245. (0..10).map(|f| rsx! {
  246. li { "hi" }
  247. })
  248. div {}
  249. }
  250. "#;
  251. let formatted = fmt_block(block).unwrap();
  252. println!("{formatted}");
  253. }
  254. #[test]
  255. fn formats_exprs_neg_indent() {
  256. let block = r#"
  257. ul {
  258. (0..10).map(|f| rsx!{
  259. li {
  260. "hi"
  261. }
  262. })
  263. }
  264. "#;
  265. let formatted = fmt_block(block).unwrap();
  266. println!("{formatted}");
  267. }
  268. #[test]
  269. fn formats_exprs_handlers() {
  270. let block = r#"
  271. button {
  272. class: "flex items-center pl-3 py-3 pr-2 text-gray-500 hover:bg-indigo-50 rounded",
  273. onclick: move |evt| {
  274. show_user_menu.set(!show_user_menu.get()); evt.cancel_bubble(); },
  275. onclick: move |evt|
  276. show_user_menu.set(!show_user_menu.get()),
  277. span { class: "inline-block mr-4",
  278. icons::icon_14 {}
  279. }
  280. span { "Settings" }
  281. }
  282. "#;
  283. let formatted = fmt_block(block).unwrap();
  284. println!("{formatted}");
  285. }
  286. #[test]
  287. fn formats_complex() {
  288. let block = r#"
  289. li {
  290. Link {
  291. class: "flex items-center pl-3 py-3 pr-4 {active_class} rounded",
  292. to: "{to}",
  293. span { class: "inline-block mr-3",
  294. icons::icon_0 {}
  295. }
  296. span { "{name}" }
  297. children.is_some().then(|| rsx!{
  298. span {
  299. class: "inline-block ml-auto hover:bg-gray-500",
  300. onclick: move |evt| {
  301. // open.set(!open.get());
  302. evt.cancel_bubble();
  303. },
  304. icons::icon_8 {}
  305. }
  306. })
  307. }
  308. div {
  309. class: "px-4",
  310. is_current.then(|| rsx!{ children })
  311. // open.then(|| rsx!{ children })
  312. }
  313. }
  314. "#;
  315. let formatted = fmt_block(block).unwrap();
  316. println!("{formatted}");
  317. }
  318. #[test]
  319. fn formats_document() {
  320. let block = r#"
  321. rsx!{
  322. Component {
  323. adsasd: "asd", // this is a comment
  324. onclick: move |_| {
  325. let blah = 120;
  326. },
  327. }
  328. }
  329. "#;
  330. let formatted = fmt_file(block);
  331. println!("{formatted:?}");
  332. }
  333. #[test]
  334. fn component_path_mod_style() {
  335. let block = r#"
  336. rsx!{
  337. my::thing::Component {
  338. adsasd: "asd", // this is a comment
  339. onclick: move |_| {
  340. let blah = 120;
  341. },
  342. }
  343. }
  344. "#;
  345. let formatted = fmt_file(block);
  346. println!("{formatted:?}");
  347. }
  348. #[test]
  349. fn formats_valid_rust_src() {
  350. let src = r#"
  351. //
  352. rsx! {
  353. div {}
  354. div {
  355. h3 {"asd"
  356. }
  357. }
  358. }
  359. "#;
  360. let formatted = fmt_file(src);
  361. println!("{formatted:?}");
  362. }
  363. #[test]
  364. fn formats_valid_rust_src_with_indents() {
  365. let mut src = r#"
  366. #[inline_props]
  367. fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape) -> Element {
  368. const ICON_SIZE: u32 = 36;
  369. rsx! {
  370. div {
  371. h1 {"thing"}
  372. }
  373. }
  374. }
  375. "#
  376. .to_string();
  377. let formatted = fmt_file(&src);
  378. let block = formatted.into_iter().next().unwrap();
  379. src.replace_range(
  380. block.start - 1..block.end + 1,
  381. &format!("{{ {} }}", &block.formatted),
  382. );
  383. }
  384. #[test]
  385. fn formats_multiple_blocks() {
  386. let mut src = r#"
  387. #[inline_props]
  388. fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape) -> Element {
  389. const ICON_SIZE: u32 = 36;
  390. rsx! {
  391. div {
  392. h1 {"thing"}
  393. }
  394. }
  395. rsx! {
  396. div {
  397. Ball {
  398. a: rsx!{
  399. "asdasd"
  400. }
  401. }
  402. }
  403. }
  404. }
  405. #[inline_props]
  406. fn NavItem<'a>(cx: Scope, to: &'static str, children: Element<'a>, icon: Shape) -> Element {
  407. const ICON_SIZE: u32 = 36;
  408. rsx! {
  409. div {
  410. h1 {"thing"}
  411. }
  412. }
  413. rsx! {
  414. div {
  415. Ball {
  416. a: rsx!{
  417. "asdasd"
  418. }
  419. }
  420. }
  421. }
  422. }
  423. "#
  424. .to_string();
  425. let formatted = fmt_file(&src);
  426. dbg!(&formatted);
  427. let block = formatted.into_iter().next().unwrap();
  428. src.replace_range(
  429. block.start - 1..block.end + 1,
  430. &format!("{{ {} }}", &block.formatted),
  431. );
  432. }
  433. #[test]
  434. fn empty_blocks() {
  435. let mut src = r###"
  436. pub fn Alert(cx: Scope) -> Element {
  437. cx.render(rsx! {
  438. div { }
  439. })
  440. }
  441. "###
  442. .to_string();
  443. let formatted = fmt_file(&src);
  444. dbg!(&formatted);
  445. }