attribute_test.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. #![cfg_attr(rustfmt, rustfmt::skip)]
  2. use crate::editor::{TestBuilder, TestOp::*};
  3. use flowy_document_infra::core::{FlowyDoc, PlainDoc};
  4. use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr, RichTextDelta};
  5. use unicode_segmentation::UnicodeSegmentation;
  6. #[test]
  7. fn attributes_bold_added() {
  8. let ops = vec![
  9. Insert(0, "123456", 0),
  10. Bold(0, Interval::new(3, 5), true),
  11. AssertDocJson(
  12. 0,
  13. r#"[
  14. {"insert":"123"},
  15. {"insert":"45","attributes":{"bold":"true"}},
  16. {"insert":"6"}
  17. ]"#,
  18. ),
  19. ];
  20. TestBuilder::new().run_script::<PlainDoc>(ops);
  21. }
  22. #[test]
  23. fn attributes_bold_added_and_invert_all() {
  24. let ops = vec![
  25. Insert(0, "123", 0),
  26. Bold(0, Interval::new(0, 3), true),
  27. AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
  28. Bold(0, Interval::new(0, 3), false),
  29. AssertDocJson(0, r#"[{"insert":"123"}]"#),
  30. ];
  31. TestBuilder::new().run_script::<PlainDoc>(ops);
  32. }
  33. #[test]
  34. fn attributes_bold_added_and_invert_partial_suffix() {
  35. let ops = vec![
  36. Insert(0, "1234", 0),
  37. Bold(0, Interval::new(0, 4), true),
  38. AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
  39. Bold(0, Interval::new(2, 4), false),
  40. AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
  41. ];
  42. TestBuilder::new().run_script::<PlainDoc>(ops);
  43. }
  44. #[test]
  45. fn attributes_bold_added_and_invert_partial_suffix2() {
  46. let ops = vec![
  47. Insert(0, "1234", 0),
  48. Bold(0, Interval::new(0, 4), true),
  49. AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
  50. Bold(0, Interval::new(2, 4), false),
  51. AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
  52. Bold(0, Interval::new(2, 4), true),
  53. AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
  54. ];
  55. TestBuilder::new().run_script::<PlainDoc>(ops);
  56. }
  57. #[test]
  58. fn attributes_bold_added_with_new_line() {
  59. let ops = vec![
  60. Insert(0, "123456", 0),
  61. Bold(0, Interval::new(0, 6), true),
  62. AssertDocJson(
  63. 0,
  64. r#"[{"insert":"123456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
  65. ),
  66. Insert(0, "\n", 3),
  67. AssertDocJson(
  68. 0,
  69. r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"},{"insert":"456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
  70. ),
  71. Insert(0, "\n", 4),
  72. AssertDocJson(
  73. 0,
  74. r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n\n"},{"insert":"456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
  75. ),
  76. Insert(0, "a", 4),
  77. AssertDocJson(
  78. 0,
  79. r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\na\n"},{"insert":"456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
  80. ),
  81. ];
  82. TestBuilder::new().run_script::<FlowyDoc>(ops);
  83. }
  84. #[test]
  85. fn attributes_bold_added_and_invert_partial_prefix() {
  86. let ops = vec![
  87. Insert(0, "1234", 0),
  88. Bold(0, Interval::new(0, 4), true),
  89. AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
  90. Bold(0, Interval::new(0, 2), false),
  91. AssertDocJson(0, r#"[{"insert":"12"},{"insert":"34","attributes":{"bold":"true"}}]"#),
  92. ];
  93. TestBuilder::new().run_script::<PlainDoc>(ops);
  94. }
  95. #[test]
  96. fn attributes_bold_added_consecutive() {
  97. let ops = vec![
  98. Insert(0, "1234", 0),
  99. Bold(0, Interval::new(0, 1), true),
  100. AssertDocJson(0, r#"[{"insert":"1","attributes":{"bold":"true"}},{"insert":"234"}]"#),
  101. Bold(0, Interval::new(1, 2), true),
  102. AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
  103. ];
  104. TestBuilder::new().run_script::<PlainDoc>(ops);
  105. }
  106. #[test]
  107. fn attributes_bold_added_italic() {
  108. let ops = vec![
  109. Insert(0, "1234", 0),
  110. Bold(0, Interval::new(0, 4), true),
  111. Italic(0, Interval::new(0, 4), true),
  112. AssertDocJson(
  113. 0,
  114. r#"[{"insert":"1234","attributes":{"italic":"true","bold":"true"}},{"insert":"\n"}]"#,
  115. ),
  116. Insert(0, "5678", 4),
  117. AssertDocJson(
  118. 0,
  119. r#"[{"insert":"12345678","attributes":{"bold":"true","italic":"true"}},{"insert":"\n"}]"#,
  120. ),
  121. ];
  122. TestBuilder::new().run_script::<FlowyDoc>(ops);
  123. }
  124. #[test]
  125. fn attributes_bold_added_italic2() {
  126. let ops = vec![
  127. Insert(0, "123456", 0),
  128. Bold(0, Interval::new(0, 6), true),
  129. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  130. Italic(0, Interval::new(0, 2), true),
  131. AssertDocJson(
  132. 0,
  133. r#"[
  134. {"insert":"12","attributes":{"italic":"true","bold":"true"}},
  135. {"insert":"3456","attributes":{"bold":"true"}}]
  136. "#,
  137. ),
  138. Italic(0, Interval::new(4, 6), true),
  139. AssertDocJson(
  140. 0,
  141. r#"[
  142. {"insert":"12","attributes":{"italic":"true","bold":"true"}},
  143. {"insert":"34","attributes":{"bold":"true"}},
  144. {"insert":"56","attributes":{"italic":"true","bold":"true"}}]
  145. "#,
  146. ),
  147. ];
  148. TestBuilder::new().run_script::<PlainDoc>(ops);
  149. }
  150. #[test]
  151. fn attributes_bold_added_italic3() {
  152. let ops = vec![
  153. Insert(0, "123456789", 0),
  154. Bold(0, Interval::new(0, 5), true),
  155. Italic(0, Interval::new(0, 2), true),
  156. AssertDocJson(
  157. 0,
  158. r#"[
  159. {"insert":"12","attributes":{"bold":"true","italic":"true"}},
  160. {"insert":"345","attributes":{"bold":"true"}},{"insert":"6789"}]
  161. "#,
  162. ),
  163. Italic(0, Interval::new(2, 4), true),
  164. AssertDocJson(
  165. 0,
  166. r#"[
  167. {"insert":"1234","attributes":{"bold":"true","italic":"true"}},
  168. {"insert":"5","attributes":{"bold":"true"}},
  169. {"insert":"6789"}]
  170. "#,
  171. ),
  172. Bold(0, Interval::new(7, 9), true),
  173. AssertDocJson(
  174. 0,
  175. r#"[
  176. {"insert":"1234","attributes":{"bold":"true","italic":"true"}},
  177. {"insert":"5","attributes":{"bold":"true"}},
  178. {"insert":"67"},
  179. {"insert":"89","attributes":{"bold":"true"}}]
  180. "#,
  181. ),
  182. ];
  183. TestBuilder::new().run_script::<PlainDoc>(ops);
  184. }
  185. #[test]
  186. fn attributes_bold_added_italic_delete() {
  187. let ops = vec![
  188. Insert(0, "123456789", 0),
  189. Bold(0, Interval::new(0, 5), true),
  190. Italic(0, Interval::new(0, 2), true),
  191. AssertDocJson(
  192. 0,
  193. r#"[
  194. {"insert":"12","attributes":{"italic":"true","bold":"true"}},
  195. {"insert":"345","attributes":{"bold":"true"}},{"insert":"6789"}]
  196. "#,
  197. ),
  198. Italic(0, Interval::new(2, 4), true),
  199. AssertDocJson(
  200. 0,
  201. r#"[
  202. {"insert":"1234","attributes":{"bold":"true","italic":"true"}}
  203. ,{"insert":"5","attributes":{"bold":"true"}},{"insert":"6789"}]"#,
  204. ),
  205. Bold(0, Interval::new(7, 9), true),
  206. AssertDocJson(
  207. 0,
  208. r#"[
  209. {"insert":"1234","attributes":{"bold":"true","italic":"true"}},
  210. {"insert":"5","attributes":{"bold":"true"}},{"insert":"67"},
  211. {"insert":"89","attributes":{"bold":"true"}}]
  212. "#,
  213. ),
  214. Delete(0, Interval::new(0, 5)),
  215. AssertDocJson(0, r#"[{"insert":"67"},{"insert":"89","attributes":{"bold":"true"}}]"#),
  216. ];
  217. TestBuilder::new().run_script::<PlainDoc>(ops);
  218. }
  219. #[test]
  220. fn attributes_merge_inserted_text_with_same_attribute() {
  221. let ops = vec![
  222. InsertBold(0, "123", Interval::new(0, 3)),
  223. AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#),
  224. InsertBold(0, "456", Interval::new(3, 6)),
  225. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  226. ];
  227. TestBuilder::new().run_script::<PlainDoc>(ops);
  228. }
  229. #[test]
  230. fn attributes_compose_attr_attributes_with_attr_attributes_test() {
  231. let ops = vec![
  232. InsertBold(0, "123456", Interval::new(0, 6)),
  233. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  234. InsertBold(1, "7", Interval::new(0, 1)),
  235. AssertDocJson(1, r#"[{"insert":"7","attributes":{"bold":"true"}}]"#),
  236. Transform(0, 1),
  237. AssertDocJson(0, r#"[{"insert":"1234567","attributes":{"bold":"true"}}]"#),
  238. AssertDocJson(1, r#"[{"insert":"1234567","attributes":{"bold":"true"}}]"#),
  239. ];
  240. TestBuilder::new().run_script::<PlainDoc>(ops);
  241. }
  242. #[test]
  243. fn attributes_compose_attr_attributes_with_attr_attributes_test2() {
  244. let ops = vec![
  245. Insert(0, "123456", 0),
  246. Bold(0, Interval::new(0, 6), true),
  247. Italic(0, Interval::new(0, 2), true),
  248. Italic(0, Interval::new(4, 6), true),
  249. AssertDocJson(
  250. 0,
  251. r#"[
  252. {"insert":"12","attributes":{"bold":"true","italic":"true"}},
  253. {"insert":"34","attributes":{"bold":"true"}},
  254. {"insert":"56","attributes":{"italic":"true","bold":"true"}}]
  255. "#,
  256. ),
  257. InsertBold(1, "7", Interval::new(0, 1)),
  258. AssertDocJson(1, r#"[{"insert":"7","attributes":{"bold":"true"}}]"#),
  259. Transform(0, 1),
  260. AssertDocJson(
  261. 0,
  262. r#"[
  263. {"insert":"12","attributes":{"italic":"true","bold":"true"}},
  264. {"insert":"34","attributes":{"bold":"true"}},
  265. {"insert":"56","attributes":{"italic":"true","bold":"true"}},
  266. {"insert":"7","attributes":{"bold":"true"}}]
  267. "#,
  268. ),
  269. AssertDocJson(
  270. 1,
  271. r#"[
  272. {"insert":"12","attributes":{"italic":"true","bold":"true"}},
  273. {"insert":"34","attributes":{"bold":"true"}},
  274. {"insert":"56","attributes":{"italic":"true","bold":"true"}},
  275. {"insert":"7","attributes":{"bold":"true"}}]
  276. "#,
  277. ),
  278. ];
  279. TestBuilder::new().run_script::<PlainDoc>(ops);
  280. }
  281. #[test]
  282. fn attributes_compose_attr_attributes_with_no_attr_attributes_test() {
  283. let expected = r#"[{"insert":"123456","attributes":{"bold":"true"}},{"insert":"7"}]"#;
  284. let ops = vec![
  285. InsertBold(0, "123456", Interval::new(0, 6)),
  286. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  287. Insert(1, "7", 0),
  288. AssertDocJson(1, r#"[{"insert":"7"}]"#),
  289. Transform(0, 1),
  290. AssertDocJson(0, expected),
  291. AssertDocJson(1, expected),
  292. ];
  293. TestBuilder::new().run_script::<PlainDoc>(ops);
  294. }
  295. #[test]
  296. fn attributes_replace_heading() {
  297. let ops = vec![
  298. InsertBold(0, "123456", Interval::new(0, 6)),
  299. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  300. Delete(0, Interval::new(0, 2)),
  301. AssertDocJson(0, r#"[{"insert":"3456","attributes":{"bold":"true"}}]"#),
  302. ];
  303. TestBuilder::new().run_script::<PlainDoc>(ops);
  304. }
  305. #[test]
  306. fn attributes_replace_trailing() {
  307. let ops = vec![
  308. InsertBold(0, "123456", Interval::new(0, 6)),
  309. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  310. Delete(0, Interval::new(5, 6)),
  311. AssertDocJson(0, r#"[{"insert":"12345","attributes":{"bold":"true"}}]"#),
  312. ];
  313. TestBuilder::new().run_script::<PlainDoc>(ops);
  314. }
  315. #[test]
  316. fn attributes_replace_middle() {
  317. let ops = vec![
  318. InsertBold(0, "123456", Interval::new(0, 6)),
  319. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  320. Delete(0, Interval::new(0, 2)),
  321. AssertDocJson(0, r#"[{"insert":"3456","attributes":{"bold":"true"}}]"#),
  322. Delete(0, Interval::new(2, 4)),
  323. AssertDocJson(0, r#"[{"insert":"34","attributes":{"bold":"true"}}]"#),
  324. ];
  325. TestBuilder::new().run_script::<PlainDoc>(ops);
  326. }
  327. #[test]
  328. fn attributes_replace_all() {
  329. let ops = vec![
  330. InsertBold(0, "123456", Interval::new(0, 6)),
  331. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  332. Delete(0, Interval::new(0, 6)),
  333. AssertDocJson(0, r#"[]"#),
  334. ];
  335. TestBuilder::new().run_script::<PlainDoc>(ops);
  336. }
  337. #[test]
  338. fn attributes_replace_with_text() {
  339. let ops = vec![
  340. InsertBold(0, "123456", Interval::new(0, 6)),
  341. AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
  342. Replace(0, Interval::new(0, 3), "ab"),
  343. AssertDocJson(0, r#"[{"insert":"ab"},{"insert":"456","attributes":{"bold":"true"}}]"#),
  344. ];
  345. TestBuilder::new().run_script::<PlainDoc>(ops);
  346. }
  347. #[test]
  348. fn attributes_header_insert_newline_at_middle() {
  349. let ops = vec![
  350. Insert(0, "123456", 0),
  351. Header(0, Interval::new(0, 6), 1),
  352. AssertDocJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}}]"#),
  353. Insert(0, "\n", 3),
  354. AssertDocJson(
  355. 0,
  356. r#"[{"insert":"123"},{"insert":"\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
  357. ),
  358. ];
  359. TestBuilder::new().run_script::<FlowyDoc>(ops);
  360. }
  361. #[test]
  362. fn attributes_header_insert_double_newline_at_middle() {
  363. let ops = vec![
  364. Insert(0, "123456", 0),
  365. Header(0, Interval::new(0, 6), 1),
  366. Insert(0, "\n", 3),
  367. AssertDocJson(
  368. 0,
  369. r#"[{"insert":"123"},{"insert":"\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
  370. ),
  371. Insert(0, "\n", 4),
  372. AssertDocJson(
  373. 0,
  374. r#"[{"insert":"123"},{"insert":"\n\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
  375. ),
  376. Insert(0, "\n", 4),
  377. AssertDocJson(
  378. 0,
  379. r#"[{"insert":"123"},{"insert":"\n\n","attributes":{"header":1}},{"insert":"\n456"},{"insert":"\n","attributes":{"header":1}}]"#,
  380. ),
  381. ];
  382. TestBuilder::new().run_script::<FlowyDoc>(ops);
  383. }
  384. #[test]
  385. fn attributes_header_insert_newline_at_trailing() {
  386. let ops = vec![
  387. Insert(0, "123456", 0),
  388. Header(0, Interval::new(0, 6), 1),
  389. Insert(0, "\n", 6),
  390. AssertDocJson(
  391. 0,
  392. r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}},{"insert":"\n"}]"#,
  393. ),
  394. ];
  395. TestBuilder::new().run_script::<FlowyDoc>(ops);
  396. }
  397. #[test]
  398. fn attributes_header_insert_double_newline_at_trailing() {
  399. let ops = vec![
  400. Insert(0, "123456", 0),
  401. Header(0, Interval::new(0, 6), 1),
  402. Insert(0, "\n", 6),
  403. Insert(0, "\n", 7),
  404. AssertDocJson(
  405. 0,
  406. r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}},{"insert":"\n\n"}]"#,
  407. ),
  408. ];
  409. TestBuilder::new().run_script::<FlowyDoc>(ops);
  410. }
  411. #[test]
  412. fn attributes_link_added() {
  413. let ops = vec![
  414. Insert(0, "123456", 0),
  415. Link(0, Interval::new(0, 6), "https://appflowy.io"),
  416. AssertDocJson(
  417. 0,
  418. r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
  419. ),
  420. ];
  421. TestBuilder::new().run_script::<FlowyDoc>(ops);
  422. }
  423. #[test]
  424. fn attributes_link_format_with_bold() {
  425. let ops = vec![
  426. Insert(0, "123456", 0),
  427. Link(0, Interval::new(0, 6), "https://appflowy.io"),
  428. Bold(0, Interval::new(0, 3), true),
  429. AssertDocJson(
  430. 0,
  431. r#"[
  432. {"insert":"123","attributes":{"bold":"true","link":"https://appflowy.io"}},
  433. {"insert":"456","attributes":{"link":"https://appflowy.io"}},
  434. {"insert":"\n"}]
  435. "#,
  436. ),
  437. ];
  438. TestBuilder::new().run_script::<FlowyDoc>(ops);
  439. }
  440. #[test]
  441. fn attributes_link_insert_char_at_head() {
  442. let ops = vec![
  443. Insert(0, "123456", 0),
  444. Link(0, Interval::new(0, 6), "https://appflowy.io"),
  445. AssertDocJson(
  446. 0,
  447. r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
  448. ),
  449. Insert(0, "a", 0),
  450. AssertDocJson(
  451. 0,
  452. r#"[{"insert":"a"},{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
  453. ),
  454. ];
  455. TestBuilder::new().run_script::<FlowyDoc>(ops);
  456. }
  457. #[test]
  458. fn attributes_link_insert_char_at_middle() {
  459. let ops = vec![
  460. Insert(0, "1256", 0),
  461. Link(0, Interval::new(0, 4), "https://appflowy.io"),
  462. Insert(0, "34", 2),
  463. AssertDocJson(
  464. 0,
  465. r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
  466. ),
  467. ];
  468. TestBuilder::new().run_script::<FlowyDoc>(ops);
  469. }
  470. #[test]
  471. fn attributes_link_insert_char_at_trailing() {
  472. let ops = vec![
  473. Insert(0, "123456", 0),
  474. Link(0, Interval::new(0, 6), "https://appflowy.io"),
  475. AssertDocJson(
  476. 0,
  477. r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
  478. ),
  479. Insert(0, "a", 6),
  480. AssertDocJson(
  481. 0,
  482. r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"a\n"}]"#,
  483. ),
  484. ];
  485. TestBuilder::new().run_script::<FlowyDoc>(ops);
  486. }
  487. #[test]
  488. fn attributes_link_insert_newline_at_middle() {
  489. let ops = vec![
  490. Insert(0, "123456", 0),
  491. Link(0, Interval::new(0, 6), "https://appflowy.io"),
  492. Insert(0, NEW_LINE, 3),
  493. AssertDocJson(
  494. 0,
  495. r#"[{"insert":"123","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"},{"insert":"456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
  496. ),
  497. ];
  498. TestBuilder::new().run_script::<FlowyDoc>(ops);
  499. }
  500. #[test]
  501. fn attributes_link_auto_format() {
  502. let site = "https://appflowy.io";
  503. let ops = vec![
  504. Insert(0, site, 0),
  505. AssertDocJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
  506. Insert(0, WHITESPACE, site.len()),
  507. AssertDocJson(
  508. 0,
  509. r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io/"}},{"insert":" \n"}]"#,
  510. ),
  511. ];
  512. TestBuilder::new().run_script::<FlowyDoc>(ops);
  513. }
  514. #[test]
  515. fn attributes_link_auto_format_exist() {
  516. let site = "https://appflowy.io";
  517. let ops = vec![
  518. Insert(0, site, 0),
  519. Link(0, Interval::new(0, site.len()), site),
  520. Insert(0, WHITESPACE, site.len()),
  521. AssertDocJson(
  522. 0,
  523. r#"[{"insert":"https://appflowy.io","attributes":{"link":"https://appflowy.io/"}},{"insert":" \n"}]"#,
  524. ),
  525. ];
  526. TestBuilder::new().run_script::<FlowyDoc>(ops);
  527. }
  528. #[test]
  529. fn attributes_link_auto_format_exist2() {
  530. let site = "https://appflowy.io";
  531. let ops = vec![
  532. Insert(0, site, 0),
  533. Link(0, Interval::new(0, site.len() / 2), site),
  534. Insert(0, WHITESPACE, site.len()),
  535. AssertDocJson(
  536. 0,
  537. r#"[{"insert":"https://a","attributes":{"link":"https://appflowy.io"}},{"insert":"ppflowy.io \n"}]"#,
  538. ),
  539. ];
  540. TestBuilder::new().run_script::<FlowyDoc>(ops);
  541. }
  542. #[test]
  543. fn attributes_bullet_added() {
  544. let ops = vec![
  545. Insert(0, "12", 0),
  546. Bullet(0, Interval::new(0, 1), true),
  547. AssertDocJson(0, r#"[{"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
  548. ];
  549. TestBuilder::new().run_script::<FlowyDoc>(ops);
  550. }
  551. #[test]
  552. fn attributes_bullet_added_2() {
  553. let ops = vec![
  554. Insert(0, "1", 0),
  555. Bullet(0, Interval::new(0, 1), true),
  556. AssertDocJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
  557. Insert(0, NEW_LINE, 1),
  558. AssertDocJson(
  559. 0,
  560. r#"[{"insert":"1"},{"insert":"\n\n","attributes":{"list":"bullet"}}]"#,
  561. ),
  562. Insert(0, "2", 2),
  563. AssertDocJson(
  564. 0,
  565. r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  566. ),
  567. ];
  568. TestBuilder::new().run_script::<FlowyDoc>(ops);
  569. }
  570. #[test]
  571. fn attributes_bullet_remove_partial() {
  572. let ops = vec![
  573. Insert(0, "1", 0),
  574. Bullet(0, Interval::new(0, 1), true),
  575. Insert(0, NEW_LINE, 1),
  576. Insert(0, "2", 2),
  577. Bullet(0, Interval::new(2, 3), false),
  578. AssertDocJson(
  579. 0,
  580. r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"2\n"}]"#,
  581. ),
  582. ];
  583. TestBuilder::new().run_script::<FlowyDoc>(ops);
  584. }
  585. #[test]
  586. fn attributes_bullet_auto_exit() {
  587. let ops = vec![
  588. Insert(0, "1", 0),
  589. Bullet(0, Interval::new(0, 1), true),
  590. Insert(0, NEW_LINE, 1),
  591. Insert(0, NEW_LINE, 2),
  592. AssertDocJson(
  593. 0,
  594. r#"[{"insert":"1"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"\n"}]"#,
  595. ),
  596. ];
  597. TestBuilder::new().run_script::<FlowyDoc>(ops);
  598. }
  599. #[test]
  600. fn attributes_preserve_block_when_insert_newline_inside() {
  601. let ops = vec![
  602. Insert(0, "12", 0),
  603. Bullet(0, Interval::new(0, 2), true),
  604. Insert(0, NEW_LINE, 2),
  605. AssertDocJson(
  606. 0,
  607. r#"[{"insert":"12"},{"insert":"\n\n","attributes":{"list":"bullet"}}]"#,
  608. ),
  609. Insert(0, "34", 3),
  610. AssertDocJson(
  611. 0,
  612. r#"[
  613. {"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}},
  614. {"insert":"34"},{"insert":"\n","attributes":{"list":"bullet"}}
  615. ]"#,
  616. ),
  617. Insert(0, NEW_LINE, 3),
  618. AssertDocJson(
  619. 0,
  620. r#"[
  621. {"insert":"12"},{"insert":"\n\n","attributes":{"list":"bullet"}},
  622. {"insert":"34"},{"insert":"\n","attributes":{"list":"bullet"}}
  623. ]"#,
  624. ),
  625. Insert(0, "ab", 3),
  626. AssertDocJson(
  627. 0,
  628. r#"[
  629. {"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}},
  630. {"insert":"ab"},{"insert":"\n","attributes":{"list":"bullet"}},
  631. {"insert":"34"},{"insert":"\n","attributes":{"list":"bullet"}}
  632. ]"#,
  633. ),
  634. ];
  635. TestBuilder::new().run_script::<FlowyDoc>(ops);
  636. }
  637. #[test]
  638. fn attributes_preserve_header_format_on_merge() {
  639. let ops = vec![
  640. Insert(0, "123456", 0),
  641. Header(0, Interval::new(0, 6), 1),
  642. Insert(0, NEW_LINE, 3),
  643. AssertDocJson(
  644. 0,
  645. r#"[{"insert":"123"},{"insert":"\n","attributes":{"header":1}},{"insert":"456"},{"insert":"\n","attributes":{"header":1}}]"#,
  646. ),
  647. Delete(0, Interval::new(3, 4)),
  648. AssertDocJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}}]"#),
  649. ];
  650. TestBuilder::new().run_script::<FlowyDoc>(ops);
  651. }
  652. #[test]
  653. fn attributes_format_emoji() {
  654. let emoji_s = "👋 ";
  655. let s: FlowyStr = emoji_s.into();
  656. let len = s.count_utf16_code_units();
  657. assert_eq!(3, len);
  658. assert_eq!(2, s.graphemes(true).count());
  659. let ops = vec![
  660. Insert(0, emoji_s, 0),
  661. AssertDocJson(0, r#"[{"insert":"👋 \n"}]"#),
  662. Header(0, Interval::new(0, len), 1),
  663. AssertDocJson(
  664. 0,
  665. r#"[{"insert":"👋 "},{"insert":"\n","attributes":{"header":1}}]"#,
  666. ),
  667. ];
  668. TestBuilder::new().run_script::<FlowyDoc>(ops);
  669. }
  670. #[test]
  671. fn attributes_preserve_list_format_on_merge() {
  672. let ops = vec![
  673. Insert(0, "123456", 0),
  674. Bullet(0, Interval::new(0, 6), true),
  675. Insert(0, NEW_LINE, 3),
  676. AssertDocJson(
  677. 0,
  678. r#"[{"insert":"123"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  679. ),
  680. Delete(0, Interval::new(3, 4)),
  681. AssertDocJson(
  682. 0,
  683. r#"[{"insert":"123456"},{"insert":"\n","attributes":{"list":"bullet"}}]"#,
  684. ),
  685. ];
  686. TestBuilder::new().run_script::<FlowyDoc>(ops);
  687. }
  688. #[test]
  689. fn delta_compose() {
  690. let mut delta = RichTextDelta::from_json(r#"[{"insert":"\n"}]"#).unwrap();
  691. let deltas = vec![
  692. RichTextDelta::from_json(r#"[{"retain":1,"attributes":{"list":"unchecked"}}]"#).unwrap(),
  693. RichTextDelta::from_json(r#"[{"insert":"a"}]"#).unwrap(),
  694. RichTextDelta::from_json(r#"[{"retain":1},{"insert":"\n","attributes":{"list":"unchecked"}}]"#).unwrap(),
  695. RichTextDelta::from_json(r#"[{"retain":2},{"retain":1,"attributes":{"list":""}}]"#).unwrap(),
  696. ];
  697. for d in deltas {
  698. delta = delta.compose(&d).unwrap();
  699. }
  700. assert_eq!(
  701. delta.to_json(),
  702. r#"[{"insert":"a"},{"insert":"\n","attributes":{"list":"unchecked"}},{"insert":"\n"}]"#
  703. );
  704. let ops = vec![
  705. AssertDocJson(0, r#"[{"insert":"\n"}]"#),
  706. Insert(0, "a", 0),
  707. AssertDocJson(0, r#"[{"insert":"a\n"}]"#),
  708. Bullet(0, Interval::new(0, 1), true),
  709. AssertDocJson(0, r#"[{"insert":"a"},{"insert":"\n","attributes":{"list":"bullet"}}]"#),
  710. Insert(0, NEW_LINE, 1),
  711. AssertDocJson(
  712. 0,
  713. r#"[{"insert":"a"},{"insert":"\n\n","attributes":{"list":"bullet"}}]"#,
  714. ),
  715. Insert(0, NEW_LINE, 2),
  716. AssertDocJson(
  717. 0,
  718. r#"[{"insert":"a"},{"insert":"\n","attributes":{"list":"bullet"}},{"insert":"\n"}]"#,
  719. ),
  720. ];
  721. TestBuilder::new().run_script::<FlowyDoc>(ops);
  722. }