attribute_test.rs 25 KB

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