this repo has no description
at main 6428 lines 194 kB view raw
1open Odoc_parser 2 3type sexp = Sexplib0.Sexp.t = Atom of string | List of sexp list 4 5module Location_to_sexp = struct 6 let point : Loc.point -> sexp = 7 fun { line; column } -> 8 List [ Atom (string_of_int line); Atom (string_of_int column) ] 9 10 let span : Loc.span -> sexp = 11 fun { file; start; end_ } -> List [ Atom file; point start; point end_ ] 12 13 let at : ('a Loc.with_location -> sexp) -> 'a Loc.with_location -> sexp = 14 fun f ({ location; _ } as v) -> List [ span location; f v ] 15end 16 17let error err = Atom (Odoc_parser.Warning.to_string err) 18 19module Ast_to_sexp = struct 20 (* let at = Location_to_sexp.at *) 21 type at = { 22 at : 'a. ('a Loc.with_location -> sexp) -> 'a Loc.with_location -> sexp; 23 } 24 25 let loc_at = { at = Location_to_sexp.at } 26 let str s = Atom s 27 let str_at s = Atom s.Loc.value 28 let opt f s = match s with Some s -> List [ f s ] | None -> List [] 29 30 let style : Ast.style -> sexp = function 31 | `Bold -> Atom "bold" 32 | `Italic -> Atom "italic" 33 | `Emphasis -> Atom "emphasis" 34 | `Superscript -> Atom "superscript" 35 | `Subscript -> Atom "subscript" 36 37 let alignment : Ast.alignment option -> sexp = function 38 | Some `Left -> Atom "left" 39 | Some `Center -> Atom "center" 40 | Some `Right -> Atom "right" 41 | None -> Atom "default" 42 43 let reference_kind : Ast.reference_kind -> sexp = function 44 | `Simple -> Atom "simple" 45 | `With_text -> Atom "with_text" 46 47 let media : Ast.media -> sexp = function 48 | `Image -> Atom "image" 49 | `Video -> Atom "video" 50 | `Audio -> Atom "audio" 51 52 let rec inline_element at : Ast.inline_element Loc.with_location -> sexp = 53 fun v -> 54 match v.value with 55 | `Space _ -> Atom "space" 56 | `Word w -> List [ Atom "word"; Atom w ] 57 | `Code_span c -> List [ Atom "code_span"; Atom c ] 58 | `Raw_markup (target, s) -> 59 List [ Atom "raw_markup"; opt str target; Atom s ] 60 | `Math_span s -> List [ Atom "math_span"; Atom s ] 61 | `Styled (s, es) -> 62 List [ style s; List (List.map (at.at (inline_element at)) es) ] 63 | `Reference (kind, r, es) -> 64 List 65 [ 66 reference_kind kind; 67 at.at str_at r; 68 List (List.map (at.at (inline_element at)) es); 69 ] 70 | `Link (u, es) -> 71 List [ str u; List (List.map (at.at (inline_element at)) es) ] 72 73 let code_block_tags at tags = 74 let code_block_tag t = 75 match t with 76 | `Tag s -> List [ Atom "tag"; at.at str_at s ] 77 | `Binding (key, value) -> 78 List [ Atom "binding"; at.at str_at key; at.at str_at value ] 79 in 80 List (List.map code_block_tag tags) 81 82 let code_block_lang at { Ast.language; tags } = 83 List [ at.at str_at language; code_block_tags at tags ] 84 85 let media_href = 86 fun v -> 87 match v.Loc.value with 88 | `Reference href -> List [ Atom "Reference"; Atom href ] 89 | `Link href -> List [ Atom "Link"; Atom href ] 90 91 let rec nestable_block_element at : 92 Ast.nestable_block_element Loc.with_location -> sexp = 93 fun v -> 94 match v.value with 95 | `Paragraph es -> 96 List 97 [ Atom "paragraph"; List (List.map (at.at (inline_element at)) es) ] 98 | `Math_block s -> List [ Atom "math_block"; Atom s ] 99 | `Code_block { Ast.meta = None; content; output = None; _ } -> 100 let trimmed_content, warnings = 101 Odoc_parser.codeblock_content v.location content.value 102 in 103 let warnings = 104 if warnings = [] then [] 105 else [ List (Atom "Warnings" :: List.map error warnings) ] 106 in 107 let content = Loc.at content.location trimmed_content in 108 List ([ Atom "code_block"; at.at str_at content ] @ warnings) 109 | `Code_block { meta = Some meta; content; output = None; _ } -> 110 let trimmed_content, warnings = 111 Odoc_parser.codeblock_content v.location content.value 112 in 113 let warnings = 114 if warnings = [] then [] 115 else [ List (Atom "Warnings" :: List.map error warnings) ] 116 in 117 let content = Loc.at content.location trimmed_content in 118 List 119 ([ Atom "code_block"; code_block_lang at meta; at.at str_at content ] 120 @ warnings) 121 | `Code_block 122 { 123 meta = Some meta; 124 content; 125 output = Some output (* ; outer_location *); 126 _; 127 } -> 128 let trimmed_content, warnings = 129 Odoc_parser.codeblock_content v.location content.value 130 in 131 let warnings = 132 if warnings = [] then [] 133 else [ List (Atom "Warnings" :: List.map error warnings) ] 134 in 135 let content = Loc.at content.location trimmed_content in 136 List 137 ([ 138 Atom "code_block"; 139 code_block_lang at meta; 140 at.at str_at content; 141 List (List.map (nestable_block_element at) output); 142 ] 143 @ warnings) 144 | `Code_block { meta = None; content = _; output = Some _output; _ } -> 145 List [ Atom "code_block_err" ] 146 | `Verbatim t -> 147 let trimmed_content, warnings = 148 Odoc_parser.verbatim_content v.location t 149 in 150 let warnings = 151 if warnings = [] then [] 152 else [ List (Atom "Warnings" :: List.map error warnings) ] 153 in 154 List ([ Atom "verbatim"; Atom trimmed_content ] @ warnings) 155 | `Modules ps -> List [ Atom "modules"; List (List.map (at.at str_at) ps) ] 156 | `List (kind, weight, items) -> 157 let kind = 158 match kind with `Unordered -> "unordered" | `Ordered -> "ordered" 159 in 160 let weight = 161 match weight with `Light -> "light" | `Heavy -> "heavy" 162 in 163 let items = 164 items 165 |> List.map (fun item -> 166 List (List.map (at.at (nestable_block_element at)) item)) 167 |> fun items -> List items 168 in 169 List [ Atom kind; Atom weight; items ] 170 | `Table ((grid, align), s) -> 171 let syntax = function `Light -> "light" | `Heavy -> "heavy" in 172 let kind = function `Header -> "header" | `Data -> "data" in 173 let map name x f = List [ Atom name; List (List.map f x) ] in 174 let alignment = 175 match align with 176 | None -> List [ Atom "align"; Atom "no alignment" ] 177 | Some align -> map "align" align @@ alignment 178 in 179 List 180 [ 181 Atom "table"; 182 List [ Atom "syntax"; Atom (syntax s) ]; 183 ( map "grid" grid @@ fun row -> 184 map "row" row @@ fun (cell, k) -> 185 map (kind k) cell @@ at.at (nestable_block_element at) ); 186 alignment; 187 ] 188 | `Media (kind, href, c, m) -> 189 List [ reference_kind kind; at.at media_href href; Atom c; media m ] 190 191 let tag at : Ast.tag -> sexp = function 192 | `Author s -> List [ Atom "@author"; Atom s ] 193 | `Deprecated es -> 194 List 195 (Atom "@deprecated" :: List.map (at.at (nestable_block_element at)) es) 196 | `Param (s, es) -> 197 List 198 ([ Atom "@param"; Atom s ] 199 @ List.map (at.at (nestable_block_element at)) es) 200 | `Raise (s, es) -> 201 List 202 ([ Atom "@raise"; Atom s ] 203 @ List.map (at.at (nestable_block_element at)) es) 204 | `Return es -> 205 List (Atom "@return" :: List.map (at.at (nestable_block_element at)) es) 206 | `Children_order es -> 207 List 208 (Atom "@children_order" 209 :: List.map (at.at (nestable_block_element at)) es) 210 | `Toc_status es -> 211 List 212 (Atom "@toc_status" :: List.map (at.at (nestable_block_element at)) es) 213 | `Order_category es -> 214 List 215 (Atom "@order_category" 216 :: List.map (at.at (nestable_block_element at)) es) 217 | `Short_title es -> 218 List 219 (Atom "@short_title" 220 :: List.map (at.at (nestable_block_element at)) es) 221 | `See (kind, s, es) -> 222 let kind = 223 match kind with 224 | `Url -> "url" 225 | `File -> "file" 226 | `Document -> "document" 227 in 228 List 229 ([ Atom "@see"; Atom kind; Atom s ] 230 @ List.map (at.at (nestable_block_element at)) es) 231 | `Since s -> List [ Atom "@since"; Atom s ] 232 | `Before (s, es) -> 233 List 234 ([ Atom "@before"; Atom s ] 235 @ List.map (at.at (nestable_block_element at)) es) 236 | `Version s -> List [ Atom "@version"; Atom s ] 237 | `Canonical p -> List [ Atom "@canonical"; at.at str_at p ] 238 | `Inline -> Atom "@inline" 239 | `Open -> Atom "@open" 240 | `Closed -> Atom "@closed" 241 | `Hidden -> Atom "@hidden" 242 | `Custom (s, es) -> 243 List 244 ([ Atom "@custom"; Atom s ] 245 @ List.map (at.at (nestable_block_element at)) es) 246 247 let block_element at : Ast.block_element Loc.with_location -> sexp = function 248 | { value = #Ast.nestable_block_element; _ } as e -> 249 nestable_block_element at e 250 | { value = `Heading (level, label, es); _ } -> 251 let label = List [ Atom "label"; opt str label ] in 252 let level = string_of_int level in 253 List 254 [ Atom level; label; List (List.map (at.at (inline_element at)) es) ] 255 | { value = `Tag t; _ } -> tag at t 256 257 let docs at : Ast.t -> sexp = 258 fun f -> List (List.map (at.at (block_element at)) f) 259end 260 261let parser_output formatter v = 262 let ast, warnings = Odoc_parser.(ast v, warnings v) in 263 let value = Ast_to_sexp.(docs loc_at ast) in 264 let warnings = List (List.map error warnings) in 265 let output = 266 List [ List [ Atom "output"; value ]; List [ Atom "warnings"; warnings ] ] 267 in 268 Sexplib0.Sexp.pp_hum formatter output; 269 Format.pp_print_flush formatter () 270 271let test ?(location = { Loc.line = 1; column = 0 }) str = 272 let dummy_filename = "f.ml" in 273 let location = 274 { 275 Lexing.pos_fname = dummy_filename; 276 pos_lnum = location.line; 277 pos_bol = 0; 278 pos_cnum = location.column; 279 } 280 in 281 let ast = Odoc_parser.parse_comment ~location ~text:str in 282 Format.printf "%a" parser_output ast 283 284[@@@ocaml.warning "-32"] 285 286let%expect_test _ = 287 let module Trivial = struct 288 let empty = 289 test ""; 290 [%expect "((output ()) (warnings ()))"] 291 292 let space = 293 test " "; 294 [%expect "((output ()) (warnings ()))"] 295 296 let two_spaces = 297 test " "; 298 [%expect "((output ()) (warnings ()))"] 299 300 let tab = 301 test "\t"; 302 [%expect "((output ()) (warnings ()))"] 303 304 let mixed_space = 305 test " \t \t"; 306 [%expect "((output ()) (warnings ()))"] 307 308 let newline = 309 test "\n"; 310 [%expect "((output ()) (warnings ()))"] 311 312 let blank_line = 313 test "\n\n"; 314 [%expect "((output ()) (warnings ()))"] 315 316 let cf_lf = 317 test "\r\n"; 318 [%expect "((output ()) (warnings ()))"] 319 end in 320 () 321 322let%expect_test _ = 323 let module One_paragraph = struct 324 let word = 325 test "foo"; 326 [%expect 327 {| 328 ((output 329 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))))) 330 (warnings ())) |}] 331 332 let two_words = 333 test "foo bar"; 334 [%expect 335 {| 336 ((output 337 (((f.ml (1 0) (1 7)) 338 (paragraph 339 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space) 340 ((f.ml (1 4) (1 7)) (word bar))))))) 341 (warnings ())) |}] 342 343 let two_words = 344 test "foo bar"; 345 [%expect 346 {| 347 ((output 348 (((f.ml (1 0) (1 7)) 349 (paragraph 350 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space) 351 ((f.ml (1 4) (1 7)) (word bar))))))) 352 (warnings ())) |}] 353 354 let two_spaces = 355 test "foo bar"; 356 [%expect 357 {| 358 ((output 359 (((f.ml (1 0) (1 8)) 360 (paragraph 361 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 5)) space) 362 ((f.ml (1 5) (1 8)) (word bar))))))) 363 (warnings ())) |}] 364 365 let mixed_space = 366 test "foo \t \t bar"; 367 [%expect 368 {| 369 ((output 370 (((f.ml (1 0) (1 11)) 371 (paragraph 372 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 8)) space) 373 ((f.ml (1 8) (1 11)) (word bar))))))) 374 (warnings ())) |}] 375 376 let two_lines = 377 test "foo\n"; 378 [%expect 379 {| 380 ((output 381 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))))) 382 (warnings ())) |}] 383 384 let two_lines_cr_lf = 385 test "foo\r\nbar"; 386 [%expect 387 {| 388 ((output 389 (((f.ml (1 0) (2 3)) 390 (paragraph 391 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (2 0)) space) 392 ((f.ml (2 0) (2 3)) (word bar))))))) 393 (warnings ())) |}] 394 395 let leading_space = 396 test " foo"; 397 [%expect 398 {| 399 ((output 400 (((f.ml (1 1) (1 4)) (paragraph (((f.ml (1 1) (1 4)) (word foo))))))) 401 (warnings ())) |}] 402 403 let trailing_space = 404 test "foo "; 405 [%expect 406 {| 407 ((output 408 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))))) 409 (warnings ())) |}] 410 411 let leading_space_on_line = 412 test "foo\n bar"; 413 [%expect 414 {| 415 ((output 416 (((f.ml (1 0) (2 4)) 417 (paragraph 418 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (2 1)) space) 419 ((f.ml (2 1) (2 4)) (word bar))))))) 420 (warnings ())) |}] 421 422 let trailing_space_on_line = 423 test "foo \nbar"; 424 [%expect 425 {| 426 ((output 427 (((f.ml (1 0) (2 3)) 428 (paragraph 429 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (2 0)) space) 430 ((f.ml (2 0) (2 3)) (word bar))))))) 431 (warnings ())) |}] 432 433 let leading_tab_on_line = 434 test "foo\n\tbar"; 435 [%expect 436 {| 437 ((output 438 (((f.ml (1 0) (2 4)) 439 (paragraph 440 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (2 1)) space) 441 ((f.ml (2 1) (2 4)) (word bar))))))) 442 (warnings ())) |}] 443 444 let trailing_tab_on_line = 445 test "foo\t\nbar"; 446 [%expect 447 {| 448 ((output 449 (((f.ml (1 0) (2 3)) 450 (paragraph 451 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (2 0)) space) 452 ((f.ml (2 0) (2 3)) (word bar))))))) 453 (warnings ())) |}] 454 455 let email = 456 test "foo@bar.com"; 457 [%expect 458 {| 459 ((output 460 (((f.ml (1 0) (1 11)) 461 (paragraph (((f.ml (1 0) (1 11)) (word foo@bar.com))))))) 462 (warnings ())) |}] 463 end in 464 () 465 466let%expect_test _ = 467 let module Two_paragraphs = struct 468 let basic = 469 test "foo\n\nbar"; 470 [%expect 471 {| 472 ((output 473 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 474 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word bar))))))) 475 (warnings ())) |}] 476 477 let leading_space = 478 test "foo \n\nbar"; 479 [%expect 480 {| 481 ((output 482 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 483 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word bar))))))) 484 (warnings ())) |}] 485 486 let trailing_space = 487 test "foo\n\n bar"; 488 [%expect 489 {| 490 ((output 491 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 492 ((f.ml (3 1) (3 4)) (paragraph (((f.ml (3 1) (3 4)) (word bar))))))) 493 (warnings ())) |}] 494 495 let cr_lf = 496 test "foo\r\n\r\nbar"; 497 [%expect 498 {| 499 ((output 500 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 501 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word bar))))))) 502 (warnings ())) |}] 503 504 let mixed_cr_lf = 505 test "foo\n\r\nbar"; 506 [%expect 507 {| 508 ((output 509 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 510 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word bar))))))) 511 (warnings ())) |}] 512 end in 513 () 514 515let%expect_test _ = 516 let module Plus_minus_bar_words = struct 517 let minus_in_word = 518 test "foo-bar"; 519 [%expect 520 {| 521 ((output 522 (((f.ml (1 0) (1 7)) (paragraph (((f.ml (1 0) (1 7)) (word foo-bar))))))) 523 (warnings ())) |}] 524 525 let minus_as_word = 526 test "foo -"; 527 [%expect 528 {| 529 ((output 530 (((f.ml (1 0) (1 5)) 531 (paragraph 532 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space) 533 ((f.ml (1 4) (1 5)) (word -))))))) 534 (warnings ())) |}] 535 536 let plus_in_word = 537 test "foo+bar"; 538 [%expect 539 {| 540 ((output 541 (((f.ml (1 0) (1 7)) (paragraph (((f.ml (1 0) (1 7)) (word foo+bar))))))) 542 (warnings ())) |}] 543 544 let plus_as_word = 545 test "foo +"; 546 [%expect 547 {| 548 ((output 549 (((f.ml (1 0) (1 5)) 550 (paragraph 551 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space) 552 ((f.ml (1 4) (1 5)) (word +))))))) 553 (warnings ())) |}] 554 555 let bar_in_word = 556 test "foo|bar"; 557 [%expect 558 {| 559 ((output 560 (((f.ml (1 0) (1 7)) 561 (paragraph 562 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) (word |)) 563 ((f.ml (1 4) (1 7)) (word bar))))))) 564 (warnings ())) |}] 565 566 let escaped_bar_in_word = 567 test "foo\\|bar"; 568 [%expect 569 {| 570 ((output 571 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word "foo\\|bar"))))))) 572 (warnings ())) |}] 573 574 let bar_as_word = 575 test "foo |"; 576 [%expect 577 {| 578 ((output 579 (((f.ml (1 0) (1 5)) 580 (paragraph 581 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space) 582 ((f.ml (1 4) (1 5)) (word |))))))) 583 (warnings ())) |}] 584 585 let negative_number = 586 test "-3.14 -1337"; 587 [%expect 588 {| 589 ((output 590 (((f.ml (1 0) (1 11)) 591 (paragraph 592 (((f.ml (1 0) (1 5)) (word -3.14)) ((f.ml (1 5) (1 6)) space) 593 ((f.ml (1 6) (1 11)) (word -1337))))))) 594 (warnings ())) |}] 595 596 let n_em_dash = 597 test "-- ---"; 598 [%expect 599 {| 600 ((output 601 (((f.ml (1 0) (1 6)) 602 (paragraph 603 (((f.ml (1 0) (1 2)) (word --)) ((f.ml (1 2) (1 3)) space) 604 ((f.ml (1 3) (1 6)) (word ---))))))) 605 (warnings ())) |}] 606 607 let minus_at = 608 test "-@"; 609 [%expect 610 {| 611 ((output (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word -@))))))) 612 (warnings ())) |}] 613 614 let at_minus = 615 test "-@-"; 616 [%expect 617 {| 618 ((output 619 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word -@-))))))) 620 (warnings ())) |}] 621 622 let option = 623 test "--option"; 624 [%expect 625 {| 626 ((output 627 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word --option))))))) 628 (warnings ())) |}] 629 end in 630 () 631 632let%expect_test _ = 633 let module Escape_sequence = struct 634 let left_brace = 635 test "\\{"; 636 [%expect 637 {| 638 ((output (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word {))))))) 639 (warnings ())) |}] 640 641 let left_brace_in_word = 642 test "foo\\{bar"; 643 [%expect 644 {| 645 ((output 646 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word foo{bar))))))) 647 (warnings ())) |}] 648 649 let right_brace = 650 test "\\}"; 651 [%expect 652 {| 653 ((output (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word }))))))) 654 (warnings ())) |}] 655 656 let right_brace_in_word = 657 test "foo\\{bar"; 658 [%expect 659 {| 660 ((output 661 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word foo{bar))))))) 662 (warnings ())) |}] 663 664 let left_bracket = 665 test "\\["; 666 [%expect 667 {| 668 ((output (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word [))))))) 669 (warnings ())) |}] 670 671 let left_bracket_in_word = 672 test "foo\\[bar"; 673 [%expect 674 {| 675 ((output 676 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word foo[bar))))))) 677 (warnings ())) |}] 678 679 let right_bracket = 680 test "\\]"; 681 [%expect 682 {| 683 ((output (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word ]))))))) 684 (warnings ())) |}] 685 686 let right_bracket_in_word = 687 test "foo\\]bar"; 688 [%expect 689 {| 690 ((output 691 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word foo]bar))))))) 692 (warnings ())) |}] 693 694 let at = 695 test "@"; 696 [%expect 697 {| 698 ((output (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word @))))))) 699 (warnings ( "File \"f.ml\", line 1, characters 0-1:\ 700 \nStray '@'."))) |}] 701 702 let not_a_tag = 703 test "\\@author"; 704 [%expect 705 {| 706 ((output 707 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word @author))))))) 708 (warnings ())) |}] 709 710 let at_in_word = 711 test "foo\\@bar"; 712 [%expect 713 {| 714 ((output 715 (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (word foo@bar))))))) 716 (warnings ())) |}] 717 718 let trailing_backslash = 719 test "foo\\"; 720 [%expect 721 {| 722 ((output 723 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (word "foo\\"))))))) 724 (warnings ())) |}] 725 726 let none_escape = 727 test "foo\\bar"; 728 [%expect 729 {| 730 ((output 731 (((f.ml (1 0) (1 7)) (paragraph (((f.ml (1 0) (1 7)) (word "foo\\bar"))))))) 732 (warnings ())) |}] 733 734 let backslash_not_escaped = 735 test "foo\\\\{bar"; 736 [%expect 737 {| 738 ((output 739 (((f.ml (1 0) (1 9)) (paragraph (((f.ml (1 0) (1 9)) (word "foo\\{bar"))))))) 740 (warnings ())) |}] 741 742 let single_backslash = 743 test "\\"; 744 [%expect 745 {| 746 ((output 747 (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word "\\"))))))) 748 (warnings ())) |}] 749 750 let escape_minus = 751 test "\\{- foo"; 752 [%expect 753 {| 754 ((output 755 (((f.ml (1 0) (1 7)) 756 (paragraph 757 (((f.ml (1 0) (1 3)) (word {-)) ((f.ml (1 3) (1 4)) space) 758 ((f.ml (1 4) (1 7)) (word foo))))))) 759 (warnings ())) |}] 760 761 let escape_plus = 762 test "\\{+ foo"; 763 [%expect 764 {| 765 ((output 766 (((f.ml (1 0) (1 7)) 767 (paragraph 768 (((f.ml (1 0) (1 3)) (word {+)) ((f.ml (1 3) (1 4)) space) 769 ((f.ml (1 4) (1 7)) (word foo))))))) 770 (warnings ())) |}] 771 772 let minus_escape = 773 test "-\\{"; 774 [%expect 775 {| 776 ((output (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word -{))))))) 777 (warnings ())) |}] 778 779 let plus_escape = 780 test "+\\{"; 781 [%expect 782 {| 783 ((output (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word +{))))))) 784 (warnings ())) |}] 785 786 let escape_at = 787 test "\\{@author"; 788 [%expect 789 {| 790 ((output 791 (((f.ml (1 0) (1 9)) (paragraph (((f.ml (1 0) (1 9)) (word {@author))))))) 792 (warnings ())) |}] 793 794 let two = 795 test "\\{\\}"; 796 [%expect 797 {| 798 ((output (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (word {}))))))) 799 (warnings ())) |}] 800 end in 801 () 802 803let%expect_test _ = 804 let module Code_span = struct 805 let basic = 806 test "[foo]"; 807 [%expect 808 {| 809 ((output 810 (((f.ml (1 0) (1 5)) (paragraph (((f.ml (1 0) (1 5)) (code_span foo))))))) 811 (warnings ())) |}] 812 813 let empty = 814 test "[]"; 815 [%expect 816 {| 817 ((output 818 (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (code_span ""))))))) 819 (warnings ())) |}] 820 821 let list = 822 test "[[]]"; 823 [%expect 824 {| 825 ((output 826 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (code_span []))))))) 827 (warnings ())) |}] 828 (* TODO The next two error messages are particularly unintuitive. *) 829 830 let unbalanced_list = 831 test "[[]"; 832 [%expect 833 {| 834 ((output 835 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (code_span []))))))) 836 (warnings 837 ( "File \"f.ml\", line 1, characters 3-3:\ 838 \nEnd of text is not allowed in '[...]' (code)."))) |}] 839 840 let no_markup = 841 test "[{b"; 842 [%expect 843 {| 844 ((output 845 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (code_span {b))))))) 846 (warnings 847 ( "File \"f.ml\", line 1, characters 3-3:\ 848 \nEnd of text is not allowed in '[...]' (code)."))) |}] 849 850 let few_escapes = 851 test "[\\{]"; 852 [%expect 853 {| 854 ((output 855 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (code_span "\\{"))))))) 856 (warnings ())) |}] 857 858 let escaped_right_bracket = 859 test "[\\]]"; 860 [%expect 861 {| 862 ((output 863 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (code_span ]))))))) 864 (warnings ())) |}] 865 866 let escaped_left_bracket = 867 test "[\\[]"; 868 [%expect 869 {| 870 ((output 871 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (code_span [))))))) 872 (warnings ())) |}] 873 874 let whitespace_preserved = 875 test "[ foo bar ]"; 876 [%expect 877 {| 878 ((output 879 (((f.ml (1 0) (1 11)) 880 (paragraph (((f.ml (1 0) (1 11)) (code_span " foo bar "))))))) 881 (warnings ())) |}] 882 883 let no_new_lines = 884 test "[foo\nbar]"; 885 [%expect 886 {| 887 ((output 888 (((f.ml (1 0) (2 4)) 889 (paragraph (((f.ml (1 0) (2 4)) (code_span "foo bar"))))))) 890 (warnings ())) |}] 891 892 let cr_lf_preserved = 893 test "[foo\r\nbar]"; 894 [%expect 895 {| 896 ((output 897 (((f.ml (1 0) (2 4)) 898 (paragraph (((f.ml (1 0) (2 4)) (code_span "foo bar"))))))) 899 (warnings ())) |}] 900 901 let no_double_new_line = 902 test "[foo\r\n\r\nbar]"; 903 [%expect 904 {| 905 ((output 906 (((f.ml (1 0) (3 4)) 907 (paragraph (((f.ml (1 0) (3 4)) (code_span "foo bar"))))))) 908 (warnings 909 ( "File \"f.ml\", line 1, character 4 to line 3, character 0:\ 910 \nBlank line is not allowed in '[...]' (code)."))) |}] 911 912 let no_double_crlf = 913 test "[foo\r\n\r\nbar]"; 914 [%expect 915 {| 916 ((output 917 (((f.ml (1 0) (3 4)) 918 (paragraph (((f.ml (1 0) (3 4)) (code_span "foo bar"))))))) 919 (warnings 920 ( "File \"f.ml\", line 1, character 4 to line 3, character 0:\ 921 \nBlank line is not allowed in '[...]' (code)."))) |}] 922 923 let not_merged = 924 test "[foo][bar]"; 925 [%expect 926 {| 927 ((output 928 (((f.ml (1 0) (1 10)) 929 (paragraph 930 (((f.ml (1 0) (1 5)) (code_span foo)) 931 ((f.ml (1 5) (1 10)) (code_span bar))))))) 932 (warnings ())) |}] 933 934 let explicit_space = 935 test "[foo] [bar]"; 936 [%expect 937 {| 938 ((output 939 (((f.ml (1 0) (1 11)) 940 (paragraph 941 (((f.ml (1 0) (1 5)) (code_span foo)) ((f.ml (1 5) (1 6)) space) 942 ((f.ml (1 6) (1 11)) (code_span bar))))))) 943 (warnings ())) |}] 944 945 let untermindated = 946 test "[foo"; 947 [%expect 948 {| 949 ((output 950 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (code_span foo))))))) 951 (warnings 952 ( "File \"f.ml\", line 1, characters 4-4:\ 953 \nEnd of text is not allowed in '[...]' (code)."))) |}] 954 end in 955 () 956 957let%expect_test _ = 958 let module Bold = struct 959 let basic = 960 test "{b foo}"; 961 [%expect 962 {| 963 ((output 964 (((f.ml (1 0) (1 7)) 965 (paragraph 966 (((f.ml (1 0) (1 7)) (bold (((f.ml (1 3) (1 6)) (word foo)))))))))) 967 (warnings ())) |}] 968 969 let extra_leading_whitespace = 970 test "{b \t foo}"; 971 [%expect 972 {| 973 ((output 974 (((f.ml (1 0) (1 10)) 975 (paragraph 976 (((f.ml (1 0) (1 10)) (bold (((f.ml (1 6) (1 9)) (word foo)))))))))) 977 (warnings ())) |}] 978 979 let leading_newline = 980 test "{b\nfoo}"; 981 [%expect 982 {| 983 ((output 984 (((f.ml (1 0) (2 4)) 985 (paragraph 986 (((f.ml (1 0) (2 4)) (bold (((f.ml (2 0) (2 3)) (word foo)))))))))) 987 (warnings ())) |}] 988 989 let leading_cr_lf = 990 test "{b\r\nfoo}"; 991 [%expect 992 {| 993 ((output 994 (((f.ml (1 0) (2 4)) 995 (paragraph 996 (((f.ml (1 0) (2 4)) (bold (((f.ml (2 0) (2 3)) (word foo)))))))))) 997 (warnings ())) |}] 998 999 let leading_newline_and_whitespace = 1000 test "{b\n foo}"; 1001 [%expect 1002 {| 1003 ((output 1004 (((f.ml (1 0) (2 5)) 1005 (paragraph 1006 (((f.ml (1 0) (2 5)) (bold (((f.ml (2 1) (2 4)) (word foo)))))))))) 1007 (warnings ())) |}] 1008 1009 let no_leading_whitespace = 1010 test "{bfoo}"; 1011 [%expect 1012 {| 1013 ((output 1014 (((f.ml (1 0) (1 6)) 1015 (paragraph 1016 (((f.ml (1 0) (1 6)) (bold (((f.ml (1 2) (1 5)) (word foo)))))))))) 1017 (warnings 1018 ( "File \"f.ml\", line 1, characters 0-2:\ 1019 \n'{b' should be followed by space, a tab, or a new line."))) |}] 1020 1021 let trailing_whitespace = 1022 test "{b foo }"; 1023 [%expect 1024 {| 1025 ((output 1026 (((f.ml (1 0) (1 8)) 1027 (paragraph 1028 (((f.ml (1 0) (1 8)) (bold (((f.ml (1 3) (1 6)) (word foo)))))))))) 1029 (warnings ())) |}] 1030 1031 let trailing_newline = 1032 test "{b foo\n}"; 1033 [%expect 1034 {| 1035 ((output 1036 (((f.ml (1 0) (2 1)) 1037 (paragraph 1038 (((f.ml (1 0) (2 1)) (bold (((f.ml (1 3) (1 6)) (word foo)))))))))) 1039 (warnings ())) |}] 1040 1041 let trailing_cr_lf = 1042 test "{b foo\r\n}"; 1043 [%expect 1044 {| 1045 ((output 1046 (((f.ml (1 0) (2 1)) 1047 (paragraph 1048 (((f.ml (1 0) (2 1)) (bold (((f.ml (1 3) (1 6)) (word foo)))))))))) 1049 (warnings ())) |}] 1050 1051 let two_words = 1052 test "{b foo bar}"; 1053 [%expect 1054 {| 1055 ((output 1056 (((f.ml (1 0) (1 11)) 1057 (paragraph 1058 (((f.ml (1 0) (1 11)) 1059 (bold 1060 (((f.ml (1 3) (1 6)) (word foo)) ((f.ml (1 6) (1 7)) space) 1061 ((f.ml (1 7) (1 10)) (word bar)))))))))) 1062 (warnings ())) |}] 1063 1064 let not_merged = 1065 test "{b foo}{b bar}"; 1066 [%expect 1067 {| 1068 ((output 1069 (((f.ml (1 0) (1 14)) 1070 (paragraph 1071 (((f.ml (1 0) (1 7)) (bold (((f.ml (1 3) (1 6)) (word foo))))) 1072 ((f.ml (1 7) (1 14)) (bold (((f.ml (1 10) (1 13)) (word bar)))))))))) 1073 (warnings ())) |}] 1074 1075 let nested = 1076 test "{b foo{b bar}}"; 1077 [%expect 1078 {| 1079 ((output 1080 (((f.ml (1 0) (1 14)) 1081 (paragraph 1082 (((f.ml (1 0) (1 14)) 1083 (bold 1084 (((f.ml (1 3) (1 6)) (word foo)) 1085 ((f.ml (1 6) (1 13)) (bold (((f.ml (1 9) (1 12)) (word bar))))))))))))) 1086 (warnings ())) |}] 1087 1088 let newline = 1089 test "{b foo\nbar}"; 1090 [%expect 1091 {| 1092 ((output 1093 (((f.ml (1 0) (2 4)) 1094 (paragraph 1095 (((f.ml (1 0) (2 4)) 1096 (bold 1097 (((f.ml (1 3) (1 6)) (word foo)) ((f.ml (1 6) (2 0)) space) 1098 ((f.ml (2 0) (2 3)) (word bar)))))))))) 1099 (warnings ())) |}] 1100 1101 let cr_lf = 1102 test "{b foo\r\nbar}"; 1103 [%expect 1104 {| 1105 ((output 1106 (((f.ml (1 0) (2 4)) 1107 (paragraph 1108 (((f.ml (1 0) (2 4)) 1109 (bold 1110 (((f.ml (1 3) (1 6)) (word foo)) ((f.ml (1 6) (2 0)) space) 1111 ((f.ml (2 0) (2 3)) (word bar)))))))))) 1112 (warnings ())) |}] 1113 1114 let minus = 1115 test "{b -}"; 1116 [%expect 1117 {| 1118 ((output 1119 (((f.ml (1 0) (1 5)) 1120 (paragraph (((f.ml (1 0) (1 5)) (bold (((f.ml (1 3) (1 4)) (word -)))))))))) 1121 (warnings ())) |}] 1122 1123 let minus_list_item = 1124 test "{b foo\n - bar}"; 1125 [%expect 1126 {| 1127 ((output 1128 (((f.ml (1 0) (2 7)) 1129 (paragraph 1130 (((f.ml (1 0) (2 7)) 1131 (bold 1132 (((f.ml (1 3) (1 6)) (word foo)) ((f.ml (1 6) (2 1)) space) 1133 ((f.ml (2 1) (2 2)) (word -)) ((f.ml (2 2) (2 3)) space) 1134 ((f.ml (2 3) (2 6)) (word bar)))))))))) 1135 (warnings 1136 ( "File \"f.ml\", line 2, characters 1-2:\ 1137 \n'-' (bulleted list item) is not allowed in '{b ...}' (boldface text).\ 1138 \nSuggestion: move '-' so it isn't the first thing on the line."))) |}] 1139 1140 let plus_list_item = 1141 test "{b foo\n + bar}"; 1142 [%expect 1143 {| 1144 ((output 1145 (((f.ml (1 0) (2 7)) 1146 (paragraph 1147 (((f.ml (1 0) (2 7)) 1148 (bold 1149 (((f.ml (1 3) (1 6)) (word foo)) ((f.ml (1 6) (2 1)) space) 1150 ((f.ml (2 1) (2 2)) (word +)) ((f.ml (2 2) (2 3)) space) 1151 ((f.ml (2 3) (2 6)) (word bar)))))))))) 1152 (warnings 1153 ( "File \"f.ml\", line 2, characters 1-2:\ 1154 \n'+' (numbered list item) is not allowed in '{b ...}' (boldface text).\ 1155 \nSuggestion: move '+' so it isn't the first thing on the line."))) |}] 1156 1157 let immediate_minus_list_item = 1158 test "{b\n- foo}"; 1159 [%expect 1160 {| 1161 ((output 1162 (((f.ml (1 0) (2 6)) 1163 (paragraph 1164 (((f.ml (1 0) (2 6)) 1165 (bold 1166 (((f.ml (2 0) (2 1)) (word -)) ((f.ml (2 1) (2 2)) space) 1167 ((f.ml (2 2) (2 5)) (word foo)))))))))) 1168 (warnings 1169 ( "File \"f.ml\", line 2, characters 0-1:\ 1170 \n'-' (bulleted list item) is not allowed in '{b ...}' (boldface text).\ 1171 \nSuggestion: move '-' so it isn't the first thing on the line."))) |}] 1172 1173 let immediate_plus_list_item = 1174 test "{b\n+ foo}"; 1175 [%expect 1176 {| 1177 ((output 1178 (((f.ml (1 0) (2 6)) 1179 (paragraph 1180 (((f.ml (1 0) (2 6)) 1181 (bold 1182 (((f.ml (2 0) (2 1)) (word +)) ((f.ml (2 1) (2 2)) space) 1183 ((f.ml (2 2) (2 5)) (word foo)))))))))) 1184 (warnings 1185 ( "File \"f.ml\", line 2, characters 0-1:\ 1186 \n'+' (numbered list item) is not allowed in '{b ...}' (boldface text).\ 1187 \nSuggestion: move '+' so it isn't the first thing on the line."))) |}] 1188 1189 let blank_line = 1190 test "{b foo\n\nbar}"; 1191 [%expect 1192 {| 1193 ((output 1194 (((f.ml (1 0) (3 4)) 1195 (paragraph 1196 (((f.ml (1 0) (3 4)) 1197 (bold 1198 (((f.ml (1 3) (1 6)) (word foo)) ((f.ml (2 0) (2 0)) space) 1199 ((f.ml (3 0) (3 3)) (word bar)))))))))) 1200 (warnings 1201 ( "File \"f.ml\", line 2, characters 0-0:\ 1202 \nBlank line is not allowed in '{b ...}' (boldface text)."))) |}] 1203 1204 let immediate_blank_line = 1205 test "{b"; 1206 [%expect 1207 {| 1208 ((output (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (bold ()))))))) 1209 (warnings 1210 ( "File \"f.ml\", line 1, characters 0-2:\ 1211 \n'{b' should be followed by space, a tab, or a new line." 1212 "File \"f.ml\", line 1, characters 2-2:\ 1213 \nEnd of text is not allowed in '{b ...}' (boldface text)." 1214 "File \"f.ml\", line 1, characters 0-2:\ 1215 \n'{b ...}' (boldface text) should not be empty."))) |}] 1216 1217 let end_of_comment = 1218 test "{b foo"; 1219 [%expect 1220 {| 1221 ((output 1222 (((f.ml (1 0) (1 6)) 1223 (paragraph 1224 (((f.ml (1 0) (1 6)) (bold (((f.ml (1 3) (1 6)) (word foo)))))))))) 1225 (warnings 1226 ( "File \"f.ml\", line 1, characters 6-6:\ 1227 \nEnd of text is not allowed in '{b ...}' (boldface text)."))) |}] 1228 1229 let nested_code_block = 1230 test "{b {[foo]}"; 1231 [%expect 1232 {| 1233 ((output 1234 (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (bold ()))))) 1235 ((f.ml (1 3) (1 10)) (code_block ((f.ml (1 5) (1 8)) foo))))) 1236 (warnings 1237 ( "File \"f.ml\", line 1, characters 3-10:\ 1238 \n'{[...]}' (code block) is not allowed in '{b ...}' (boldface text)." 1239 "File \"f.ml\", line 1, characters 0-2:\ 1240 \n'{b ...}' (boldface text) should not be empty." 1241 "File \"f.ml\", line 1, characters 3-10:\ 1242 \n'{[...]}' (code block) should begin on its own line."))) |}] 1243 1244 let degenerate = 1245 test "{b}"; 1246 [%expect 1247 {| 1248 ((output (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (bold ()))))))) 1249 (warnings 1250 ( "File \"f.ml\", line 1, characters 0-3:\ 1251 \n'{b ...}' (boldface text) should not be empty."))) |}] 1252 1253 let empty = 1254 test "{b }"; 1255 [%expect 1256 {| 1257 ((output (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (bold ()))))))) 1258 (warnings 1259 ( "File \"f.ml\", line 1, characters 0-4:\ 1260 \n'{b ...}' (boldface text) should not be empty."))) |}] 1261 end in 1262 () 1263 1264let%expect_test _ = 1265 let module Italic = struct 1266 let basic = 1267 test "{i foo}"; 1268 [%expect 1269 {| 1270 ((output 1271 (((f.ml (1 0) (1 7)) 1272 (paragraph 1273 (((f.ml (1 0) (1 7)) (italic (((f.ml (1 3) (1 6)) (word foo)))))))))) 1274 (warnings ())) |}] 1275 1276 let extra_leading_whitespace = 1277 test "{i \t foo}"; 1278 [%expect 1279 {| 1280 ((output 1281 (((f.ml (1 0) (1 10)) 1282 (paragraph 1283 (((f.ml (1 0) (1 10)) (italic (((f.ml (1 6) (1 9)) (word foo)))))))))) 1284 (warnings ())) |}] 1285 1286 let leading_newline = 1287 test "{i\nfoo}"; 1288 [%expect 1289 {| 1290 ((output 1291 (((f.ml (1 0) (2 4)) 1292 (paragraph 1293 (((f.ml (1 0) (2 4)) (italic (((f.ml (2 0) (2 3)) (word foo)))))))))) 1294 (warnings ())) |}] 1295 1296 let leading_newline_and_whitespace = 1297 test "{i\n foo}"; 1298 [%expect 1299 {| 1300 ((output 1301 (((f.ml (1 0) (2 5)) 1302 (paragraph 1303 (((f.ml (1 0) (2 5)) (italic (((f.ml (2 1) (2 4)) (word foo)))))))))) 1304 (warnings ())) |}] 1305 end in 1306 () 1307 1308let%expect_test _ = 1309 let module Emphasis = struct 1310 let basic = 1311 test "{e foo}"; 1312 [%expect 1313 {| 1314 ((output 1315 (((f.ml (1 0) (1 7)) 1316 (paragraph 1317 (((f.ml (1 0) (1 7)) (emphasis (((f.ml (1 3) (1 6)) (word foo)))))))))) 1318 (warnings ())) |}] 1319 1320 let extra_leading_whitespace = 1321 test "{e \t foo}"; 1322 [%expect 1323 {| 1324 ((output 1325 (((f.ml (1 0) (1 10)) 1326 (paragraph 1327 (((f.ml (1 0) (1 10)) (emphasis (((f.ml (1 6) (1 9)) (word foo)))))))))) 1328 (warnings ())) |}] 1329 1330 let leading_newline = 1331 test "{e\nfoo}"; 1332 [%expect 1333 {| 1334 ((output 1335 (((f.ml (1 0) (2 4)) 1336 (paragraph 1337 (((f.ml (1 0) (2 4)) (emphasis (((f.ml (2 0) (2 3)) (word foo)))))))))) 1338 (warnings ())) |}] 1339 1340 let leading_newline_and_whitespace = 1341 test "{e\n foo}"; 1342 [%expect 1343 {| 1344 ((output 1345 (((f.ml (1 0) (2 5)) 1346 (paragraph 1347 (((f.ml (1 0) (2 5)) (emphasis (((f.ml (2 1) (2 4)) (word foo)))))))))) 1348 (warnings ())) |}] 1349 end in 1350 () 1351 1352let%expect_test _ = 1353 let module Superscript = struct 1354 let basic = 1355 test "{^ foo}"; 1356 [%expect 1357 {| 1358 ((output 1359 (((f.ml (1 0) (1 7)) 1360 (paragraph 1361 (((f.ml (1 0) (1 7)) (superscript (((f.ml (1 3) (1 6)) (word foo)))))))))) 1362 (warnings ())) |}] 1363 1364 let extra_leading_whitespace = 1365 test "{^ \t foo}"; 1366 [%expect 1367 {| 1368 ((output 1369 (((f.ml (1 0) (1 10)) 1370 (paragraph 1371 (((f.ml (1 0) (1 10)) (superscript (((f.ml (1 6) (1 9)) (word foo)))))))))) 1372 (warnings ())) |}] 1373 1374 let leading_newline = 1375 test "{^\nfoo}"; 1376 [%expect 1377 {| 1378 ((output 1379 (((f.ml (1 0) (2 4)) 1380 (paragraph 1381 (((f.ml (1 0) (2 4)) (superscript (((f.ml (2 0) (2 3)) (word foo)))))))))) 1382 (warnings ())) |}] 1383 1384 let leading_cr_lf = 1385 test "{^\r\nfoo}"; 1386 [%expect 1387 {| 1388 ((output 1389 (((f.ml (1 0) (2 4)) 1390 (paragraph 1391 (((f.ml (1 0) (2 4)) (superscript (((f.ml (2 0) (2 3)) (word foo)))))))))) 1392 (warnings ())) |}] 1393 1394 let leading_newline_and_whitespace = 1395 test "{^\n foo}"; 1396 [%expect 1397 {| 1398 ((output 1399 (((f.ml (1 0) (2 5)) 1400 (paragraph 1401 (((f.ml (1 0) (2 5)) (superscript (((f.ml (2 1) (2 4)) (word foo)))))))))) 1402 (warnings ())) |}] 1403 1404 let no_whitespace = 1405 test "{^foo}"; 1406 [%expect 1407 {| 1408 ((output 1409 (((f.ml (1 0) (1 6)) 1410 (paragraph 1411 (((f.ml (1 0) (1 6)) (superscript (((f.ml (1 2) (1 5)) (word foo)))))))))) 1412 (warnings ())) |}] 1413 1414 let degenerate = 1415 test "{^}"; 1416 [%expect 1417 {| 1418 ((output 1419 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (superscript ()))))))) 1420 (warnings 1421 ( "File \"f.ml\", line 1, characters 0-3:\ 1422 \n'{^...}' (superscript) should not be empty."))) |}] 1423 1424 let empty = 1425 test "{^ }"; 1426 [%expect 1427 {| 1428 ((output 1429 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (superscript ()))))))) 1430 (warnings 1431 ( "File \"f.ml\", line 1, characters 0-4:\ 1432 \n'{^...}' (superscript) should not be empty."))) |}] 1433 end in 1434 () 1435 1436let%expect_test _ = 1437 let module Subscript = struct 1438 let basic = 1439 test "{_ foo}"; 1440 [%expect 1441 {| 1442 ((output 1443 (((f.ml (1 0) (1 7)) 1444 (paragraph 1445 (((f.ml (1 0) (1 7)) (subscript (((f.ml (1 3) (1 6)) (word foo)))))))))) 1446 (warnings ())) |}] 1447 1448 let extra_leading_whitespace = 1449 test "{_ \t foo}"; 1450 [%expect 1451 {| 1452 ((output 1453 (((f.ml (1 0) (1 10)) 1454 (paragraph 1455 (((f.ml (1 0) (1 10)) (subscript (((f.ml (1 6) (1 9)) (word foo)))))))))) 1456 (warnings ())) |}] 1457 1458 let leading_newline = 1459 test "{_\nfoo}"; 1460 [%expect 1461 {| 1462 ((output 1463 (((f.ml (1 0) (2 4)) 1464 (paragraph 1465 (((f.ml (1 0) (2 4)) (subscript (((f.ml (2 0) (2 3)) (word foo)))))))))) 1466 (warnings ())) |}] 1467 1468 let leading_newline_and_whitespace = 1469 test "{_\n foo}"; 1470 [%expect 1471 {| 1472 ((output 1473 (((f.ml (1 0) (2 5)) 1474 (paragraph 1475 (((f.ml (1 0) (2 5)) (subscript (((f.ml (2 1) (2 4)) (word foo)))))))))) 1476 (warnings ())) |}] 1477 1478 let no_whitespace = 1479 test "{_foo}"; 1480 [%expect 1481 {| 1482 ((output 1483 (((f.ml (1 0) (1 6)) 1484 (paragraph 1485 (((f.ml (1 0) (1 6)) (subscript (((f.ml (1 2) (1 5)) (word foo)))))))))) 1486 (warnings ())) |}] 1487 1488 let v_verbose = 1489 test "{_uv}"; 1490 [%expect 1491 {| 1492 ((output 1493 (((f.ml (1 0) (1 5)) 1494 (paragraph 1495 (((f.ml (1 0) (1 5)) (subscript (((f.ml (1 2) (1 4)) (word uv)))))))))) 1496 (warnings ())) |}] 1497 end in 1498 () 1499 1500let%expect_test _ = 1501 let module Simple_reference = struct 1502 let basic = 1503 test "{!foo}"; 1504 [%expect 1505 {| 1506 ((output 1507 (((f.ml (1 0) (1 6)) 1508 (paragraph (((f.ml (1 0) (1 6)) (simple ((f.ml (1 2) (1 6)) foo) ()))))))) 1509 (warnings ())) |}] 1510 1511 let leading_whitespace = 1512 test "{! foo}"; 1513 [%expect 1514 {| 1515 ((output 1516 (((f.ml (1 0) (1 7)) 1517 (paragraph 1518 (((f.ml (1 0) (1 7)) (simple ((f.ml (1 2) (1 7)) " foo") ()))))))) 1519 (warnings ())) |}] 1520 1521 let trailing_whitespace = 1522 test "{!foo }"; 1523 [%expect 1524 {| 1525 ((output 1526 (((f.ml (1 0) (1 7)) 1527 (paragraph 1528 (((f.ml (1 0) (1 7)) (simple ((f.ml (1 2) (1 7)) "foo ") ()))))))) 1529 (warnings ())) |}] 1530 1531 let adjacent_word_leading = 1532 test "bar{!foo}"; 1533 [%expect 1534 {| 1535 ((output 1536 (((f.ml (1 0) (1 9)) 1537 (paragraph 1538 (((f.ml (1 0) (1 3)) (word bar)) 1539 ((f.ml (1 3) (1 9)) (simple ((f.ml (1 5) (1 9)) foo) ()))))))) 1540 (warnings ())) |}] 1541 1542 let explicit_leading_space = 1543 test "bar {!foo}"; 1544 [%expect 1545 {| 1546 ((output 1547 (((f.ml (1 0) (1 10)) 1548 (paragraph 1549 (((f.ml (1 0) (1 3)) (word bar)) ((f.ml (1 3) (1 4)) space) 1550 ((f.ml (1 4) (1 10)) (simple ((f.ml (1 6) (1 10)) foo) ()))))))) 1551 (warnings ())) |}] 1552 1553 let adjacent_word_trailing = 1554 test "{!foo}bar"; 1555 [%expect 1556 {| 1557 ((output 1558 (((f.ml (1 0) (1 9)) 1559 (paragraph 1560 (((f.ml (1 0) (1 6)) (simple ((f.ml (1 2) (1 6)) foo) ())) 1561 ((f.ml (1 6) (1 9)) (word bar))))))) 1562 (warnings ())) |}] 1563 1564 let explicit_trailing_space = 1565 test "{!foo} bar"; 1566 [%expect 1567 {| 1568 ((output 1569 (((f.ml (1 0) (1 10)) 1570 (paragraph 1571 (((f.ml (1 0) (1 6)) (simple ((f.ml (1 2) (1 6)) foo) ())) 1572 ((f.ml (1 6) (1 7)) space) ((f.ml (1 7) (1 10)) (word bar))))))) 1573 (warnings ())) |}] 1574 1575 let kind = 1576 test "{!val:foo}"; 1577 [%expect 1578 {| 1579 ((output 1580 (((f.ml (1 0) (1 10)) 1581 (paragraph 1582 (((f.ml (1 0) (1 10)) (simple ((f.ml (1 2) (1 10)) val:foo) ()))))))) 1583 (warnings ())) |}] 1584 1585 let empty = 1586 test "{!}"; 1587 [%expect 1588 {| 1589 ((output 1590 (((f.ml (1 0) (1 3)) 1591 (paragraph (((f.ml (1 0) (1 3)) (simple ((f.ml (1 2) (1 3)) "") ()))))))) 1592 (warnings ())) |}] 1593 1594 let whitespace_only = 1595 test "{! }"; 1596 [%expect 1597 {| 1598 ((output 1599 (((f.ml (1 0) (1 4)) 1600 (paragraph (((f.ml (1 0) (1 4)) (simple ((f.ml (1 2) (1 4)) " ") ()))))))) 1601 (warnings ())) |}] 1602 1603 let internal_whitespace = 1604 test "{!( * )}"; 1605 [%expect 1606 {| 1607 ((output 1608 (((f.ml (1 0) (1 8)) 1609 (paragraph 1610 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) "( * )") ()))))))) 1611 (warnings ())) |}] 1612 1613 (* TODO Limiting the character combinations allowed will make it easier to 1614 catch expressions accidentally written inside references. This can also 1615 be caught by a good resolver and resolver error messages. *) 1616 (* t "expression" *) 1617 let unterminated = 1618 test "{!foo"; 1619 [%expect 1620 {| 1621 ((output 1622 (((f.ml (1 0) (1 5)) 1623 (paragraph (((f.ml (1 0) (1 5)) (simple ((f.ml (1 2) (1 5)) foo) ()))))))) 1624 (warnings 1625 ( "File \"f.ml\", line 1, characters 0-5:\ 1626 \nOpen bracket '{!' is never closed."))) |}] 1627 1628 let empty_kind = 1629 test "{!:foo}"; 1630 [%expect 1631 {| 1632 ((output 1633 (((f.ml (1 0) (1 7)) 1634 (paragraph (((f.ml (1 0) (1 7)) (simple ((f.ml (1 2) (1 7)) :foo) ()))))))) 1635 (warnings ())) |}] 1636 1637 let whitespace_kind = 1638 test "{! :foo}"; 1639 [%expect 1640 {| 1641 ((output 1642 (((f.ml (1 0) (1 8)) 1643 (paragraph 1644 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) " :foo") ()))))))) 1645 (warnings ())) |}] 1646 1647 let with_kind_but_empty = 1648 test "{!val:}"; 1649 [%expect 1650 {| 1651 ((output 1652 (((f.ml (1 0) (1 7)) 1653 (paragraph (((f.ml (1 0) (1 7)) (simple ((f.ml (1 2) (1 7)) val:) ()))))))) 1654 (warnings ())) |}] 1655 1656 let with_kind_but_whitespace = 1657 test "{!val: }"; 1658 [%expect 1659 {| 1660 ((output 1661 (((f.ml (1 0) (1 8)) 1662 (paragraph 1663 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) "val: ") ()))))))) 1664 (warnings ())) |}] 1665 1666 let leading_whitespace_in_kind = 1667 test "{! val:foo}"; 1668 [%expect 1669 {| 1670 ((output 1671 (((f.ml (1 0) (1 11)) 1672 (paragraph 1673 (((f.ml (1 0) (1 11)) (simple ((f.ml (1 2) (1 11)) " val:foo") ()))))))) 1674 (warnings ())) |}] 1675 1676 let internal_whitespace_in_kind = 1677 test "{!va l:foo}"; 1678 [%expect 1679 {| 1680 ((output 1681 (((f.ml (1 0) (1 11)) 1682 (paragraph 1683 (((f.ml (1 0) (1 11)) (simple ((f.ml (1 2) (1 11)) "va l:foo") ()))))))) 1684 (warnings ())) |}] 1685 1686 let internal_whitespace_in_referent = 1687 test "{!val:( * )}"; 1688 [%expect 1689 {| 1690 ((output 1691 (((f.ml (1 0) (1 12)) 1692 (paragraph 1693 (((f.ml (1 0) (1 12)) (simple ((f.ml (1 2) (1 12)) "val:( * )") ()))))))) 1694 (warnings ())) |}] 1695 1696 let two_colons = 1697 test "{!val:foo:bar}"; 1698 [%expect 1699 {| 1700 ((output 1701 (((f.ml (1 0) (1 14)) 1702 (paragraph 1703 (((f.ml (1 0) (1 14)) (simple ((f.ml (1 2) (1 14)) val:foo:bar) ()))))))) 1704 (warnings ())) |}] 1705 1706 let space_before_colon = 1707 test "{!val :foo}"; 1708 [%expect 1709 {| 1710 ((output 1711 (((f.ml (1 0) (1 11)) 1712 (paragraph 1713 (((f.ml (1 0) (1 11)) (simple ((f.ml (1 2) (1 11)) "val :foo") ()))))))) 1714 (warnings ())) |}] 1715 1716 let space_after_colon = 1717 test "{!val: foo}"; 1718 [%expect 1719 {| 1720 ((output 1721 (((f.ml (1 0) (1 11)) 1722 (paragraph 1723 (((f.ml (1 0) (1 11)) (simple ((f.ml (1 2) (1 11)) "val: foo") ()))))))) 1724 (warnings ())) |}] 1725 1726 let unterminated_after_kind = 1727 test "{!val:foo"; 1728 [%expect 1729 {| 1730 ((output 1731 (((f.ml (1 0) (1 9)) 1732 (paragraph 1733 (((f.ml (1 0) (1 9)) (simple ((f.ml (1 2) (1 9)) val:foo) ()))))))) 1734 (warnings 1735 ( "File \"f.ml\", line 1, characters 0-9:\ 1736 \nOpen bracket '{!' is never closed."))) |}] 1737 1738 let operator = 1739 test "{!(>>=)}"; 1740 [%expect 1741 {| 1742 ((output 1743 (((f.ml (1 0) (1 8)) 1744 (paragraph 1745 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) "(>>=)") ()))))))) 1746 (warnings ())) |}] 1747 1748 let operator_with_dash = 1749 test "{!(@->)}"; 1750 [%expect 1751 {| 1752 ((output 1753 (((f.ml (1 0) (1 8)) 1754 (paragraph 1755 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) "(@->)") ()))))))) 1756 (warnings ())) |}] 1757 1758 let operator_with_dot = 1759 test "{!(*.)}"; 1760 [%expect 1761 {| 1762 ((output 1763 (((f.ml (1 0) (1 7)) 1764 (paragraph 1765 (((f.ml (1 0) (1 7)) (simple ((f.ml (1 2) (1 7)) "(*.)") ()))))))) 1766 (warnings ())) |}] 1767 1768 let operator_with_colon = 1769 test "{!(>::)}"; 1770 [%expect 1771 {| 1772 ((output 1773 (((f.ml (1 0) (1 8)) 1774 (paragraph 1775 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) "(>::)") ()))))))) 1776 (warnings ())) |}] 1777 1778 let operator_with_curly_braces = 1779 test "{!(.*{})}"; 1780 [%expect 1781 {| 1782 ((output 1783 (((f.ml (1 0) (1 9)) 1784 (paragraph 1785 (((f.ml (1 0) (1 9)) (simple ((f.ml (1 2) (1 9)) "(.*{})") ()))))))) 1786 (warnings ())) |}] 1787 1788 let quotes_with_dash = 1789 test "{!\"my-name\"}"; 1790 [%expect 1791 {| 1792 ((output 1793 (((f.ml (1 0) (1 12)) 1794 (paragraph 1795 (((f.ml (1 0) (1 12)) (simple ((f.ml (1 2) (1 12)) "\"my-name\"") ()))))))) 1796 (warnings ())) |}] 1797 1798 let quotes_with_curly_braces = 1799 test "{!\"}\"}"; 1800 [%expect 1801 {| 1802 ((output 1803 (((f.ml (1 0) (1 6)) 1804 (paragraph 1805 (((f.ml (1 0) (1 6)) (simple ((f.ml (1 2) (1 6)) "\"}\"") ()))))))) 1806 (warnings ())) |}] 1807 1808 let operator_with_curly_braces = 1809 test "{!( } )}"; 1810 [%expect 1811 {| 1812 ((output 1813 (((f.ml (1 0) (1 8)) 1814 (paragraph 1815 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) "( } )") ()))))))) 1816 (warnings ())) |}] 1817 1818 let operator_unbalanced = 1819 test "{!(.*()}"; 1820 [%expect 1821 {| 1822 ((output 1823 (((f.ml (1 0) (1 8)) 1824 (paragraph 1825 (((f.ml (1 0) (1 8)) (simple ((f.ml (1 2) (1 8)) "(.*()}") ()))))))) 1826 (warnings 1827 ( "File \"f.ml\", line 1, characters 2-8:\ 1828 \nOpen bracket '(' is never closed."))) |}] 1829 1830 let operator_eof = 1831 test "{!(.*()"; 1832 [%expect 1833 {| 1834 ((output 1835 (((f.ml (1 0) (1 7)) 1836 (paragraph 1837 (((f.ml (1 0) (1 7)) (simple ((f.ml (1 2) (1 7)) "(.*()") ()))))))) 1838 (warnings 1839 ( "File \"f.ml\", line 1, characters 2-7:\ 1840 \nOpen bracket '(' is never closed."))) |}] 1841 end in 1842 () 1843 1844let%expect_test _ = 1845 let module Reference_with_text = struct 1846 let basic = 1847 test "{{!foo} bar}"; 1848 [%expect 1849 {| 1850 ((output 1851 (((f.ml (1 0) (1 12)) 1852 (paragraph 1853 (((f.ml (1 0) (1 12)) 1854 (with_text ((f.ml (1 3) (1 7)) foo) 1855 (((f.ml (1 8) (1 11)) (word bar)))))))))) 1856 (warnings ())) |}] 1857 1858 let degenerate = 1859 test "{{!foo}}"; 1860 [%expect 1861 {| 1862 ((output 1863 (((f.ml (1 0) (1 8)) 1864 (paragraph 1865 (((f.ml (1 0) (1 8)) (with_text ((f.ml (1 3) (1 7)) foo) ()))))))) 1866 (warnings 1867 ( "File \"f.ml\", line 1, characters 0-8:\ 1868 \n'{{!...} ...}' (cross-reference) should not be empty."))) |}] 1869 1870 let empty = 1871 test "{{!foo} }"; 1872 [%expect 1873 {| 1874 ((output 1875 (((f.ml (1 0) (1 9)) 1876 (paragraph 1877 (((f.ml (1 0) (1 9)) (with_text ((f.ml (1 3) (1 7)) foo) ()))))))) 1878 (warnings 1879 ( "File \"f.ml\", line 1, characters 0-9:\ 1880 \n'{{!...} ...}' (cross-reference) should not be empty."))) |}] 1881 1882 let nested_markup = 1883 test "{{!foo} {b bar}}"; 1884 [%expect 1885 {| 1886 ((output 1887 (((f.ml (1 0) (1 16)) 1888 (paragraph 1889 (((f.ml (1 0) (1 16)) 1890 (with_text ((f.ml (1 3) (1 7)) foo) 1891 (((f.ml (1 8) (1 15)) (bold (((f.ml (1 11) (1 14)) (word bar))))))))))))) 1892 (warnings ())) |}] 1893 1894 let in_markup = 1895 test "{e {{!foo} bar}}"; 1896 [%expect 1897 {| 1898 ((output 1899 (((f.ml (1 0) (1 16)) 1900 (paragraph 1901 (((f.ml (1 0) (1 16)) 1902 (emphasis 1903 (((f.ml (1 3) (1 15)) 1904 (with_text ((f.ml (1 6) (1 10)) foo) 1905 (((f.ml (1 11) (1 14)) (word bar))))))))))))) 1906 (warnings ())) |}] 1907 1908 let no_separating_space = 1909 test "{{!foo}bar}"; 1910 [%expect 1911 {| 1912 ((output 1913 (((f.ml (1 0) (1 11)) 1914 (paragraph 1915 (((f.ml (1 0) (1 11)) 1916 (with_text ((f.ml (1 3) (1 7)) foo) 1917 (((f.ml (1 7) (1 10)) (word bar)))))))))) 1918 (warnings ())) |}] 1919 1920 let kind = 1921 test "{{!val:foo} bar}"; 1922 [%expect 1923 {| 1924 ((output 1925 (((f.ml (1 0) (1 16)) 1926 (paragraph 1927 (((f.ml (1 0) (1 16)) 1928 (with_text ((f.ml (1 3) (1 11)) val:foo) 1929 (((f.ml (1 12) (1 15)) (word bar)))))))))) 1930 (warnings ())) |}] 1931 1932 let nested_reference = 1933 test "{{!foo} {!bar}}"; 1934 [%expect 1935 {| 1936 ((output 1937 (((f.ml (1 0) (1 15)) 1938 (paragraph 1939 (((f.ml (1 0) (1 15)) 1940 (with_text ((f.ml (1 3) (1 7)) foo) 1941 (((f.ml (1 8) (1 14)) (simple ((f.ml (1 10) (1 14)) bar) ())))))))))) 1942 (warnings ())) |}] 1943 1944 let nested_empty = 1945 test "{{!foo} {{!bar}}}"; 1946 [%expect 1947 {| 1948 ((output 1949 (((f.ml (1 0) (1 17)) 1950 (paragraph 1951 (((f.ml (1 0) (1 17)) 1952 (with_text ((f.ml (1 3) (1 7)) foo) 1953 (((f.ml (1 8) (1 16)) (with_text ((f.ml (1 11) (1 15)) bar) ())))))))))) 1954 (warnings 1955 ( "File \"f.ml\", line 1, characters 8-16:\ 1956 \n'{{!...} ...}' (cross-reference) should not be empty."))) |}] 1957 1958 let nested_through_emphasis = 1959 test "{{!foo} {e {{!bar} baz}}}"; 1960 [%expect 1961 {| 1962 ((output 1963 (((f.ml (1 0) (1 25)) 1964 (paragraph 1965 (((f.ml (1 0) (1 25)) 1966 (with_text ((f.ml (1 3) (1 7)) foo) 1967 (((f.ml (1 8) (1 24)) 1968 (emphasis 1969 (((f.ml (1 11) (1 23)) 1970 (with_text ((f.ml (1 14) (1 18)) bar) 1971 (((f.ml (1 19) (1 22)) (word baz)))))))))))))))) 1972 (warnings ())) |}] 1973 1974 let simple_through_emphasis = 1975 test "{{!foo} {e {!bar}}}"; 1976 [%expect 1977 {| 1978 ((output 1979 (((f.ml (1 0) (1 19)) 1980 (paragraph 1981 (((f.ml (1 0) (1 19)) 1982 (with_text ((f.ml (1 3) (1 7)) foo) 1983 (((f.ml (1 8) (1 18)) 1984 (emphasis 1985 (((f.ml (1 11) (1 17)) (simple ((f.ml (1 13) (1 17)) bar) ()))))))))))))) 1986 (warnings ())) |}] 1987 1988 let empty_target = 1989 test "{{!} foo}"; 1990 [%expect 1991 {| 1992 ((output 1993 (((f.ml (1 0) (1 9)) 1994 (paragraph 1995 (((f.ml (1 0) (1 9)) 1996 (with_text ((f.ml (1 3) (1 4)) "") (((f.ml (1 5) (1 8)) (word foo)))))))))) 1997 (warnings ())) |}] 1998 1999 let whitespace_only_in_target = 2000 test "{{! } foo}"; 2001 [%expect 2002 {| 2003 ((output 2004 (((f.ml (1 0) (1 10)) 2005 (paragraph 2006 (((f.ml (1 0) (1 10)) 2007 (with_text ((f.ml (1 3) (1 5)) " ") (((f.ml (1 6) (1 9)) (word foo)))))))))) 2008 (warnings ())) |}] 2009 2010 let internal_whitespace = 2011 test "{{!( * )} baz}"; 2012 [%expect 2013 {| 2014 ((output 2015 (((f.ml (1 0) (1 14)) 2016 (paragraph 2017 (((f.ml (1 0) (1 14)) 2018 (with_text ((f.ml (1 3) (1 9)) "( * )") 2019 (((f.ml (1 10) (1 13)) (word baz)))))))))) 2020 (warnings ())) |}] 2021 2022 let unterminated = 2023 test "{{!foo"; 2024 [%expect 2025 {| 2026 ((output 2027 (((f.ml (1 0) (1 6)) 2028 (paragraph 2029 (((f.ml (1 0) (1 6)) (with_text ((f.ml (1 3) (1 6)) foo) ()))))))) 2030 (warnings 2031 ( "File \"f.ml\", line 1, characters 0-6:\ 2032 \nOpen bracket '{{!' is never closed." 2033 "File \"f.ml\", line 1, characters 6-6:\ 2034 \nEnd of text is not allowed in '{{!...} ...}' (cross-reference)." 2035 "File \"f.ml\", line 1, characters 0-6:\ 2036 \n'{{!...} ...}' (cross-reference) should not be empty."))) |}] 2037 2038 let unterminated_content = 2039 test "{{!foo} bar"; 2040 [%expect 2041 {| 2042 ((output 2043 (((f.ml (1 0) (1 11)) 2044 (paragraph 2045 (((f.ml (1 0) (1 11)) 2046 (with_text ((f.ml (1 3) (1 7)) foo) 2047 (((f.ml (1 8) (1 11)) (word bar)))))))))) 2048 (warnings 2049 ( "File \"f.ml\", line 1, characters 11-11:\ 2050 \nEnd of text is not allowed in '{{!...} ...}' (cross-reference)."))) |}] 2051 end in 2052 () 2053 2054let%expect_test _ = 2055 let module Medias = struct 2056 let basic_simple = 2057 test 2058 "{image!foo}\n\n\ 2059 {audio!foo}\n\n\ 2060 {video!foo}\n\n\ 2061 {image:foo}\n\n\ 2062 {audio:foo}\n\n\ 2063 {video:foo}"; 2064 [%expect 2065 {| 2066 ((output 2067 (((f.ml (1 0) (1 11)) 2068 (simple ((f.ml (1 7) (1 10)) (Reference foo)) "" image)) 2069 ((f.ml (3 0) (3 11)) 2070 (simple ((f.ml (3 7) (3 10)) (Reference foo)) "" audio)) 2071 ((f.ml (5 0) (5 11)) 2072 (simple ((f.ml (5 7) (5 10)) (Reference foo)) "" video)) 2073 ((f.ml (7 0) (7 11)) (simple ((f.ml (7 7) (7 10)) (Link foo)) "" image)) 2074 ((f.ml (9 0) (9 11)) (simple ((f.ml (9 7) (9 10)) (Link foo)) "" audio)) 2075 ((f.ml (11 0) (11 11)) 2076 (simple ((f.ml (11 7) (11 10)) (Link foo)) "" video)))) 2077 (warnings ())) |}] 2078 2079 let basic = 2080 test 2081 "{{image!foo}bar}\n\n\ 2082 {{audio!foo}bar}\n\n\ 2083 {{video!foo}bar}\n\n\ 2084 {{image:foo}bar}\n\n\ 2085 {{audio:foo}bar}\n\n\ 2086 {{video:foo}bar}"; 2087 [%expect 2088 {| 2089 ((output 2090 (((f.ml (1 0) (1 16)) 2091 (simple ((f.ml (1 8) (1 12)) (Reference foo)) bar image)) 2092 ((f.ml (3 0) (3 16)) 2093 (simple ((f.ml (3 8) (3 12)) (Reference foo)) bar audio)) 2094 ((f.ml (5 0) (5 16)) 2095 (simple ((f.ml (5 8) (5 12)) (Reference foo)) bar video)) 2096 ((f.ml (7 0) (7 16)) (simple ((f.ml (7 8) (7 12)) (Link foo)) bar image)) 2097 ((f.ml (9 0) (9 16)) (simple ((f.ml (9 8) (9 12)) (Link foo)) bar audio)) 2098 ((f.ml (11 0) (11 16)) 2099 (simple ((f.ml (11 8) (11 12)) (Link foo)) bar video)))) 2100 (warnings ())) |}] 2101 2102 let empty = 2103 test "{{image!foo}}"; 2104 [%expect 2105 {| 2106 ((output 2107 (((f.ml (1 0) (1 13)) 2108 (simple ((f.ml (1 8) (1 12)) (Reference foo)) "" image)))) 2109 (warnings 2110 ( "File \"f.ml\", line 1, characters 11-12:\ 2111 \n'{{image!...} ...}' (image-reference) should not be empty."))) |}] 2112 2113 let whitespace = 2114 test "{{image!foo} }"; 2115 [%expect 2116 {| 2117 ((output 2118 (((f.ml (1 0) (1 16)) 2119 (simple ((f.ml (1 8) (1 12)) (Reference foo)) "" image)))) 2120 (warnings 2121 ( "File \"f.ml\", line 1, characters 11-15:\ 2122 \n'{{image!...} ...}' (image-reference) should not be empty."))) |}] 2123 2124 let trimming = 2125 test "{{image!foo} hello }"; 2126 [%expect 2127 {| 2128 ((output 2129 (((f.ml (1 0) (1 27)) 2130 (simple ((f.ml (1 8) (1 12)) (Reference foo)) hello image)))) 2131 (warnings ())) |}] 2132 2133 let nested_markup_is_uninterpreted = 2134 test "{{image!foo}{b bar}}"; 2135 [%expect 2136 {| 2137 ((output 2138 (((f.ml (1 0) (1 20)) 2139 (simple ((f.ml (1 8) (1 12)) (Reference foo)) "{b bar}" image)))) 2140 (warnings ())) |}] 2141 2142 let in_markup = 2143 test "{ul {li {{image!foo}bar}}}"; 2144 [%expect 2145 {| 2146 ((output 2147 (((f.ml (1 0) (1 26)) 2148 (unordered heavy 2149 ((((f.ml (1 8) (1 24)) 2150 (simple ((f.ml (1 16) (1 20)) (Reference foo)) bar image)))))))) 2151 (warnings ())) |}] 2152 2153 let unterminated_image = 2154 test "{{image!foo"; 2155 [%expect 2156 {| 2157 ((output 2158 (((f.ml (1 0) (1 11)) 2159 (simple ((f.ml (1 8) (1 10)) (Reference foo)) "" image)))) 2160 (warnings 2161 ( "File \"f.ml\", line 1, characters 0-11:\ 2162 \nOpen bracket '{{image!' is never closed." 2163 "File \"f.ml\", line 1, characters 11-11:\ 2164 \nEnd of text is not allowed in '{{image!...} ...}' (image-reference)." 2165 "File \"f.ml\", line 1, characters 11-10:\ 2166 \n'{{image!...} ...}' (image-reference) should not be empty."))) |}] 2167 2168 let unterminated_image_simple = 2169 test "{image!foo"; 2170 [%expect 2171 {| 2172 ((output 2173 (((f.ml (1 0) (1 10)) 2174 (simple ((f.ml (1 7) (1 9)) (Reference foo)) "" image)))) 2175 (warnings 2176 ( "File \"f.ml\", line 1, characters 0-10:\ 2177 \nOpen bracket '{image!' is never closed."))) |}] 2178 2179 let unterminated_video = 2180 test "{{video!foo"; 2181 [%expect 2182 {| 2183 ((output 2184 (((f.ml (1 0) (1 11)) 2185 (simple ((f.ml (1 8) (1 10)) (Reference foo)) "" video)))) 2186 (warnings 2187 ( "File \"f.ml\", line 1, characters 0-11:\ 2188 \nOpen bracket '{{video!' is never closed." 2189 "File \"f.ml\", line 1, characters 11-11:\ 2190 \nEnd of text is not allowed in '{{video!...} ...}' (video-reference)." 2191 "File \"f.ml\", line 1, characters 11-10:\ 2192 \n'{{video!...} ...}' (video-reference) should not be empty."))) |}] 2193 2194 let unterminated_video_simple = 2195 test "{video!foo"; 2196 [%expect 2197 {| 2198 ((output 2199 (((f.ml (1 0) (1 10)) 2200 (simple ((f.ml (1 7) (1 9)) (Reference foo)) "" video)))) 2201 (warnings 2202 ( "File \"f.ml\", line 1, characters 0-10:\ 2203 \nOpen bracket '{video!' is never closed."))) |}] 2204 2205 let unterminated_audio = 2206 test "{{audio!foo"; 2207 [%expect 2208 {| 2209 ((output 2210 (((f.ml (1 0) (1 11)) 2211 (simple ((f.ml (1 8) (1 10)) (Reference foo)) "" audio)))) 2212 (warnings 2213 ( "File \"f.ml\", line 1, characters 0-11:\ 2214 \nOpen bracket '{{audio!' is never closed." 2215 "File \"f.ml\", line 1, characters 11-11:\ 2216 \nEnd of text is not allowed in '{{audio!...} ...}' (audio-reference)." 2217 "File \"f.ml\", line 1, characters 11-10:\ 2218 \n'{{audio!...} ...}' (audio-reference) should not be empty."))) |}] 2219 2220 let unterminated_audio_simple = 2221 test "{audio!foo"; 2222 [%expect 2223 {| 2224 ((output 2225 (((f.ml (1 0) (1 10)) 2226 (simple ((f.ml (1 7) (1 9)) (Reference foo)) "" audio)))) 2227 (warnings 2228 ( "File \"f.ml\", line 1, characters 0-10:\ 2229 \nOpen bracket '{audio!' is never closed."))) |}] 2230 2231 let unterminated_content = 2232 test "{{image!foo} bar"; 2233 [%expect 2234 {| 2235 ((output 2236 (((f.ml (1 0) (1 16)) 2237 (simple ((f.ml (1 8) (1 11)) (Reference foo)) bar image)))) 2238 (warnings 2239 ( "File \"f.ml\", line 1, characters 16-16:\ 2240 \nEnd of text is not allowed in '{{image!...} ...}' (image-reference)."))) |}] 2241 2242 let newline_in_content = 2243 test "{{image!foo} bar \n baz}"; 2244 [%expect 2245 {| 2246 ((output 2247 (((f.ml (1 0) (2 5)) 2248 (simple ((f.ml (1 8) (2 -6)) (Reference foo)) "bar baz" image)))) 2249 (warnings ())) |}] 2250 end in 2251 () 2252 2253let%expect_test _ = 2254 let module Link = struct 2255 let basic = 2256 test "{{:foo} bar}"; 2257 [%expect 2258 {| 2259 ((output 2260 (((f.ml (1 0) (1 12)) 2261 (paragraph 2262 (((f.ml (1 0) (1 12)) (foo (((f.ml (1 8) (1 11)) (word bar)))))))))) 2263 (warnings ())) |}] 2264 2265 let nested_markup = 2266 test "{{:foo} {b bar}}"; 2267 [%expect 2268 {| 2269 ((output 2270 (((f.ml (1 0) (1 16)) 2271 (paragraph 2272 (((f.ml (1 0) (1 16)) 2273 (foo 2274 (((f.ml (1 8) (1 15)) (bold (((f.ml (1 11) (1 14)) (word bar))))))))))))) 2275 (warnings ())) |}] 2276 2277 let in_markup = 2278 test "{e {{:foo} bar}}"; 2279 [%expect 2280 {| 2281 ((output 2282 (((f.ml (1 0) (1 16)) 2283 (paragraph 2284 (((f.ml (1 0) (1 16)) 2285 (emphasis 2286 (((f.ml (1 3) (1 15)) (foo (((f.ml (1 11) (1 14)) (word bar))))))))))))) 2287 (warnings ())) |}] 2288 2289 let no_separating_space = 2290 test "{{:foo}bar}"; 2291 [%expect 2292 {| 2293 ((output 2294 (((f.ml (1 0) (1 11)) 2295 (paragraph 2296 (((f.ml (1 0) (1 11)) (foo (((f.ml (1 7) (1 10)) (word bar)))))))))) 2297 (warnings ())) |}] 2298 2299 let nested_link = 2300 test "{{:foo} {{:bar} baz}}"; 2301 [%expect 2302 {| 2303 ((output 2304 (((f.ml (1 0) (1 21)) 2305 (paragraph 2306 (((f.ml (1 0) (1 21)) 2307 (foo 2308 (((f.ml (1 8) (1 20)) (bar (((f.ml (1 16) (1 19)) (word baz))))))))))))) 2309 (warnings ())) |}] 2310 2311 let nested_through_emphasis = 2312 test "{{:foo} {e {{:bar} baz}}}"; 2313 [%expect 2314 {| 2315 ((output 2316 (((f.ml (1 0) (1 25)) 2317 (paragraph 2318 (((f.ml (1 0) (1 25)) 2319 (foo 2320 (((f.ml (1 8) (1 24)) 2321 (emphasis 2322 (((f.ml (1 11) (1 23)) (bar (((f.ml (1 19) (1 22)) (word baz)))))))))))))))) 2323 (warnings ())) |}] 2324 2325 let reference_through_emphasis = 2326 test "{{:foo} {e {!bar}}}"; 2327 [%expect 2328 {| 2329 ((output 2330 (((f.ml (1 0) (1 19)) 2331 (paragraph 2332 (((f.ml (1 0) (1 19)) 2333 (foo 2334 (((f.ml (1 8) (1 18)) 2335 (emphasis 2336 (((f.ml (1 11) (1 17)) (simple ((f.ml (1 13) (1 17)) bar) ()))))))))))))) 2337 (warnings ())) |}] 2338 2339 let nested_in_reference = 2340 test "{{!foo} {e {{:bar} baz}}}"; 2341 [%expect 2342 {| 2343 ((output 2344 (((f.ml (1 0) (1 25)) 2345 (paragraph 2346 (((f.ml (1 0) (1 25)) 2347 (with_text ((f.ml (1 3) (1 7)) foo) 2348 (((f.ml (1 8) (1 24)) 2349 (emphasis 2350 (((f.ml (1 11) (1 23)) (bar (((f.ml (1 19) (1 22)) (word baz)))))))))))))))) 2351 (warnings ())) |}] 2352 2353 let empty_target = 2354 test "{{:} foo}"; 2355 [%expect 2356 {| 2357 ((output 2358 (((f.ml (1 0) (1 9)) 2359 (paragraph (((f.ml (1 0) (1 9)) ("" (((f.ml (1 5) (1 8)) (word foo)))))))))) 2360 (warnings 2361 ( "File \"f.ml\", line 1, characters 0-4:\ 2362 \n'{{:...} ...}' (external link) should not be empty."))) |}] 2363 2364 let whitespace_only_in_target = 2365 test "{{: } foo}"; 2366 [%expect 2367 {| 2368 ((output 2369 (((f.ml (1 0) (1 10)) 2370 (paragraph 2371 (((f.ml (1 0) (1 10)) ("" (((f.ml (1 6) (1 9)) (word foo)))))))))) 2372 (warnings 2373 ( "File \"f.ml\", line 1, characters 0-5:\ 2374 \n'{{:...} ...}' (external link) should not be empty."))) |}] 2375 2376 let empty = 2377 test "{{:foo}}"; 2378 [%expect 2379 {| 2380 ((output (((f.ml (1 0) (1 8)) (paragraph (((f.ml (1 0) (1 8)) (foo ()))))))) 2381 (warnings ())) |}] 2382 2383 let internal_whitespace = 2384 test "{{:foo bar} baz}"; 2385 [%expect 2386 {| 2387 ((output 2388 (((f.ml (1 0) (1 16)) 2389 (paragraph 2390 (((f.ml (1 0) (1 16)) ("foo bar" (((f.ml (1 12) (1 15)) (word baz)))))))))) 2391 (warnings ())) |}] 2392 2393 let unterminated = 2394 test "{{:foo"; 2395 [%expect 2396 {| 2397 ((output (((f.ml (1 0) (1 6)) (paragraph (((f.ml (1 0) (1 6)) (foo ()))))))) 2398 (warnings 2399 ( "File \"f.ml\", line 1, characters 0-6:\ 2400 \nOpen bracket '{{:' is never closed." 2401 "File \"f.ml\", line 1, characters 6-6:\ 2402 \nEnd of text is not allowed in '{{:...} ...}' (external link)."))) |}] 2403 2404 let single_braces = 2405 test "{:foo}"; 2406 [%expect 2407 {| 2408 ((output (((f.ml (1 0) (1 6)) (paragraph (((f.ml (1 0) (1 6)) (foo ()))))))) 2409 (warnings ())) |}] 2410 2411 let unterminated_single_braces = 2412 test "{:foo"; 2413 [%expect 2414 {| 2415 ((output (((f.ml (1 0) (1 5)) (paragraph (((f.ml (1 0) (1 5)) (foo ()))))))) 2416 (warnings 2417 ( "File \"f.ml\", line 1, characters 0-5:\ 2418 \nOpen bracket '{:' is never closed."))) |}] 2419 2420 let empty_single_braces = 2421 test "{:}"; 2422 [%expect 2423 {| 2424 ((output (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) ("" ()))))))) 2425 (warnings 2426 ( "File \"f.ml\", line 1, characters 0-3:\ 2427 \n'{:...} (external link)' should not be empty."))) |}] 2428 2429 let single_braces_whitespace_only = 2430 test "{: }"; 2431 [%expect 2432 {| 2433 ((output (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) ("" ()))))))) 2434 (warnings 2435 ( "File \"f.ml\", line 1, characters 0-4:\ 2436 \n'{:...} (external link)' should not be empty."))) |}] 2437 end in 2438 () 2439 2440let%expect_test _ = 2441 let module Module_list = struct 2442 let basic = 2443 test "{!modules:Foo}"; 2444 [%expect 2445 {| 2446 ((output (((f.ml (1 0) (1 14)) (modules (((f.ml (1 0) (1 14)) Foo)))))) 2447 (warnings ())) |}] 2448 2449 let two = 2450 test "{!modules:Foo Bar}"; 2451 [%expect 2452 {| 2453 ((output 2454 (((f.ml (1 0) (1 18)) 2455 (modules (((f.ml (1 0) (1 18)) Foo) ((f.ml (1 0) (1 18)) Bar)))))) 2456 (warnings ())) |}] 2457 2458 let extra_whitespace = 2459 test "{!modules: Foo Bar }"; 2460 [%expect 2461 {| 2462 ((output 2463 (((f.ml (1 0) (1 21)) 2464 (modules (((f.ml (1 0) (1 21)) Foo) ((f.ml (1 0) (1 21)) Bar)))))) 2465 (warnings ())) |}] 2466 2467 let newline = 2468 test "{!modules:Foo\nBar}"; 2469 [%expect 2470 {| 2471 ((output 2472 (((f.ml (1 0) (2 4)) 2473 (modules (((f.ml (1 0) (2 4)) Foo) ((f.ml (1 0) (2 4)) Bar)))))) 2474 (warnings ())) |}] 2475 2476 let cr_lf = 2477 test "{!modules:Foo\r\nBar}"; 2478 [%expect 2479 {| 2480 ((output 2481 (((f.ml (1 0) (2 4)) 2482 (modules (((f.ml (1 0) (2 4)) Foo) ((f.ml (1 0) (2 4)) Bar)))))) 2483 (warnings ())) |}] 2484 2485 let empty = 2486 test "{!modules:}"; 2487 [%expect 2488 {| 2489 ((output (((f.ml (1 0) (1 11)) (modules ())))) 2490 (warnings 2491 ( "File \"f.ml\", line 1, characters 0-11:\ 2492 \n'{!modules ...}' should not be empty."))) |}] 2493 2494 let whitespace_only = 2495 test "{!modules: }"; 2496 [%expect 2497 {| 2498 ((output (((f.ml (1 0) (1 12)) (modules ())))) 2499 (warnings 2500 ( "File \"f.ml\", line 1, characters 0-12:\ 2501 \n'{!modules ...}' should not be empty."))) |}] 2502 2503 let unterminated = 2504 test "{!modules:"; 2505 [%expect 2506 {| 2507 ((output (((f.ml (1 0) (1 10)) (modules ())))) 2508 (warnings 2509 ( "File \"f.ml\", line 1, characters 10-10:\ 2510 \nEnd of text is not allowed in '{!modules ...}'." 2511 "File \"f.ml\", line 1, characters 0-10:\ 2512 \n'{!modules ...}' should not be empty."))) |}] 2513 2514 let in_paragraph = 2515 test "foo {!modules:Foo}"; 2516 [%expect 2517 {| 2518 ((output 2519 (((f.ml (1 0) (1 4)) 2520 (paragraph (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space)))) 2521 ((f.ml (1 4) (1 18)) (modules (((f.ml (1 4) (1 18)) Foo)))))) 2522 (warnings 2523 ( "File \"f.ml\", line 1, characters 4-18:\ 2524 \n'{!modules ...}' should begin on its own line."))) |}] 2525 2526 let followed_by_word = 2527 test "{!modules:Foo} foo"; 2528 [%expect 2529 {| 2530 ((output 2531 (((f.ml (1 0) (1 14)) (modules (((f.ml (1 0) (1 14)) Foo)))) 2532 ((f.ml (1 15) (1 18)) (paragraph (((f.ml (1 15) (1 18)) (word foo))))))) 2533 (warnings 2534 ( "File \"f.ml\", line 1, characters 15-18:\ 2535 \nParagraph should begin on its own line."))) |}] 2536 2537 let in_list = 2538 test "- {!modules:Foo}"; 2539 [%expect 2540 {| 2541 ((output 2542 (((f.ml (1 0) (1 16)) 2543 (unordered light 2544 ((((f.ml (1 2) (1 16)) (modules (((f.ml (1 2) (1 16)) Foo)))))))))) 2545 (warnings ())) |}] 2546 end in 2547 () 2548 2549let%expect_test _ = 2550 let module Code_block = struct 2551 let basic = 2552 test "{[foo]}"; 2553 [%expect 2554 {| 2555 ((output (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))))) 2556 (warnings ())) |}] 2557 2558 let empty = 2559 test "{[]}"; 2560 [%expect 2561 {| 2562 ((output (((f.ml (1 0) (1 4)) (code_block ((f.ml (1 2) (1 2)) ""))))) 2563 (warnings 2564 ( "File \"f.ml\", line 1, characters 0-4:\ 2565 \n'{[...]}' (code block) should not be empty."))) |}] 2566 2567 let whitespace_only = 2568 test "{[ ]}"; 2569 [%expect 2570 {| 2571 ((output (((f.ml (1 0) (1 5)) (code_block ((f.ml (1 2) (1 3)) " "))))) 2572 (warnings ())) 2573 |}] 2574 2575 let blank_line_only = 2576 test "{[\n \n]}"; 2577 [%expect 2578 {| 2579 ((output (((f.ml (1 0) (3 2)) (code_block ((f.ml (1 2) (3 0)) " "))))) 2580 (warnings ())) 2581 |}] 2582 2583 let whitespace = 2584 test "{[foo bar]}"; 2585 [%expect 2586 {| 2587 ((output (((f.ml (1 0) (1 11)) (code_block ((f.ml (1 2) (1 9)) "foo bar"))))) 2588 (warnings ())) |}] 2589 2590 let newline = 2591 test "{[foo\nbar]}"; 2592 [%expect 2593 {| 2594 ((output 2595 (((f.ml (1 0) (2 5)) (code_block ((f.ml (1 2) (2 3)) "foo\ 2596 \nbar"))))) 2597 (warnings ())) 2598 |}] 2599 2600 let cr_lf = 2601 test "{[foo\r\nbar]}"; 2602 [%expect 2603 {| 2604 ((output 2605 (((f.ml (1 0) (2 5)) (code_block ((f.ml (1 2) (2 3)) "foo\r\ 2606 \nbar"))))) 2607 (warnings ())) 2608 |}] 2609 2610 let blank_line = 2611 test "{[foo\n\nbar]}"; 2612 [%expect 2613 {| 2614 ((output 2615 (((f.ml (1 0) (3 5)) (code_block ((f.ml (1 2) (3 3)) "foo\ 2616 \n\ 2617 \nbar"))))) 2618 (warnings ())) 2619 |}] 2620 2621 let leading_whitespace = 2622 test "{[ foo]}"; 2623 [%expect 2624 {| 2625 ((output (((f.ml (1 0) (1 8)) (code_block ((f.ml (1 2) (1 6)) " foo"))))) 2626 (warnings ())) 2627 |}] 2628 2629 let leading_whitespace_two = 2630 test "{[ foo\n bar]}"; 2631 [%expect 2632 {| 2633 ((output 2634 (((f.ml (1 0) (2 6)) (code_block ((f.ml (1 2) (2 4)) " foo\ 2635 \n bar"))))) 2636 (warnings ())) 2637 |}] 2638 2639 let leading_whitespace_two_cr_lf = 2640 test "{[ foo\r\n bar]}"; 2641 [%expect 2642 {| 2643 ((output 2644 (((f.ml (1 0) (2 6)) (code_block ((f.ml (1 2) (2 4)) " foo\r\ 2645 \n bar"))))) 2646 (warnings ())) 2647 |}] 2648 2649 let leading_whitespace_two_different_indent = 2650 test "{[ foo\n bar]}"; 2651 [%expect 2652 {| 2653 ((output 2654 (((f.ml (1 0) (2 8)) (code_block ((f.ml (1 2) (2 6)) " foo\ 2655 \n bar"))))) 2656 (warnings ())) 2657 |}] 2658 2659 let leading_whitespace_two_different_indent_rev = 2660 test "{[ foo\n bar]}"; 2661 [%expect 2662 {| 2663 ((output 2664 (((f.ml (1 0) (2 6)) (code_block ((f.ml (1 2) (2 4)) " foo\ 2665 \n bar"))))) 2666 (warnings ())) 2667 |}] 2668 2669 let leading_whitespace_two_different_indent_reloc = 2670 test "{[ foo\n bar]}"; 2671 [%expect 2672 {| 2673 ((output 2674 (((f.ml (1 0) (2 11)) 2675 (code_block ((f.ml (1 2) (2 9)) " foo\ 2676 \n bar"))))) 2677 (warnings ())) 2678 |}] 2679 2680 let leading_whitespace_with_empty_line = 2681 test "{[ foo\n\n bar]}"; 2682 [%expect 2683 {| 2684 ((output 2685 (((f.ml (1 0) (3 6)) (code_block ((f.ml (1 2) (3 4)) " foo\ 2686 \n\ 2687 \n bar"))))) 2688 (warnings ())) 2689 |}] 2690 2691 let leading_whitespace_with_whitespace_line_short = 2692 test "{[ foo\n \n bar]}"; 2693 [%expect 2694 {| 2695 ((output 2696 (((f.ml (1 0) (3 7)) 2697 (code_block ((f.ml (1 2) (3 5)) " foo\ 2698 \n \ 2699 \n bar"))))) 2700 (warnings ())) 2701 |}] 2702 2703 let leading_whitespace_with_whitespace_line_long = 2704 test "{[ foo\n \n bar]}"; 2705 [%expect 2706 {| 2707 ((output 2708 (((f.ml (1 0) (3 6)) 2709 (code_block ((f.ml (1 2) (3 4)) " foo\ 2710 \n \ 2711 \n bar"))))) 2712 (warnings ())) 2713 |}] 2714 2715 let leading_whitespace_leading_newline = 2716 test "{[\n foo\n bar\n]}"; 2717 [%expect 2718 {| 2719 ((output 2720 (((f.ml (1 0) (4 2)) (code_block ((f.ml (1 2) (4 0)) " foo\ 2721 \n bar"))))) 2722 (warnings ())) 2723 |}] 2724 2725 let leading_tab = 2726 test "{[\tfoo]}"; 2727 [%expect 2728 {| 2729 ((output (((f.ml (1 0) (1 8)) (code_block ((f.ml (1 2) (1 6)) "\tfoo"))))) 2730 (warnings ())) 2731 |}] 2732 2733 let leading_tab_two = 2734 test "{[\tfoo\n\tbar]}"; 2735 [%expect 2736 {| 2737 ((output 2738 (((f.ml (1 0) (2 6)) (code_block ((f.ml (1 2) (2 4)) "\tfoo\ 2739 \n\tbar"))))) 2740 (warnings ())) 2741 |}] 2742 2743 let leading_tab_two_different_indent = 2744 test "{[\tfoo\n\t\tbar]}"; 2745 [%expect 2746 {| 2747 ((output 2748 (((f.ml (1 0) (2 7)) (code_block ((f.ml (1 2) (2 5)) "\tfoo\ 2749 \n\t\tbar"))))) 2750 (warnings ())) 2751 |}] 2752 2753 let leading_newline = 2754 test "{[\nfoo]}"; 2755 [%expect 2756 {| 2757 ((output (((f.ml (1 0) (2 5)) (code_block ((f.ml (1 2) (2 3)) foo))))) 2758 (warnings ())) 2759 |}] 2760 2761 let leading_cr_lf = 2762 test "{[\r\nfoo]}"; 2763 [%expect 2764 {| 2765 ((output (((f.ml (1 0) (2 5)) (code_block ((f.ml (1 2) (2 3)) foo))))) 2766 (warnings ())) 2767 |}] 2768 2769 let leading_newlines = 2770 test "{[\n\nfoo]}"; 2771 [%expect 2772 {| 2773 ((output (((f.ml (1 0) (3 5)) (code_block ((f.ml (1 2) (3 3)) "\ 2774 \nfoo"))))) 2775 (warnings ())) 2776 |}] 2777 2778 let leading_newline_with_space = 2779 test "{[\n foo]}"; 2780 [%expect 2781 {| 2782 ((output (((f.ml (1 0) (2 6)) (code_block ((f.ml (1 2) (2 4)) " foo"))))) 2783 (warnings ())) 2784 |}] 2785 2786 let leading_newline_with_trash = 2787 test "{[ \nfoo]}"; 2788 [%expect 2789 {| 2790 ((output (((f.ml (1 0) (2 5)) (code_block ((f.ml (1 2) (2 3)) foo))))) 2791 (warnings ())) 2792 |}] 2793 2794 let nested_opener = 2795 test "{[{[]}"; 2796 [%expect 2797 {| 2798 ((output (((f.ml (1 0) (1 6)) (code_block ((f.ml (1 2) (1 4)) {[))))) 2799 (warnings ())) |}] 2800 2801 let nested_closer = 2802 test "{[foo]}]}"; 2803 [%expect 2804 {| 2805 ((output (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))))) 2806 (warnings ())) |}] 2807 2808 let nested_bracket = 2809 test "{[]]}"; 2810 [%expect 2811 {| 2812 ((output (((f.ml (1 0) (1 5)) (code_block ((f.ml (1 2) (1 3)) ]))))) 2813 (warnings ())) 2814 |}] 2815 2816 let two_nested_brackets = 2817 test "{[]]]}"; 2818 [%expect 2819 {| 2820 ((output (((f.ml (1 0) (1 6)) (code_block ((f.ml (1 2) (1 4)) ]]))))) 2821 (warnings ())) |}] 2822 2823 let nested_brackets_in_text = 2824 test "{[foo]]bar]}"; 2825 [%expect 2826 {| 2827 ((output (((f.ml (1 0) (1 12)) (code_block ((f.ml (1 2) (1 10)) foo]]bar))))) 2828 (warnings ())) |}] 2829 2830 let trailing_whitespace = 2831 test "{[foo ]}"; 2832 [%expect 2833 {| 2834 ((output (((f.ml (1 0) (1 8)) (code_block ((f.ml (1 2) (1 6)) "foo "))))) 2835 (warnings ())) 2836 |}] 2837 2838 let trailing_tab = 2839 test "{[foo\t]}"; 2840 [%expect 2841 {| 2842 ((output (((f.ml (1 0) (1 8)) (code_block ((f.ml (1 2) (1 6)) "foo\t"))))) 2843 (warnings ())) 2844 |}] 2845 2846 let trailing_newline = 2847 test "{[foo\n]}"; 2848 [%expect 2849 {| 2850 ((output (((f.ml (1 0) (2 2)) (code_block ((f.ml (1 2) (2 0)) foo))))) 2851 (warnings ())) 2852 |}] 2853 2854 let trailing_cr_lf = 2855 test "{[foo\r\n]}"; 2856 [%expect 2857 {| 2858 ((output (((f.ml (1 0) (2 2)) (code_block ((f.ml (1 2) (2 0)) "foo\r"))))) 2859 (warnings ())) 2860 |}] 2861 2862 let trailing_newlines = 2863 test "{[foo\n\n]}"; 2864 [%expect 2865 {| 2866 ((output (((f.ml (1 0) (3 2)) (code_block ((f.ml (1 2) (3 0)) "foo\n"))))) 2867 (warnings ())) 2868 |}] 2869 2870 let preceded_by_whitespace = 2871 test "{[foo]}"; 2872 [%expect 2873 {| 2874 ((output (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))))) 2875 (warnings ())) |}] 2876 2877 let followed_by_whitespace = 2878 test "{[foo]}"; 2879 [%expect 2880 {| 2881 ((output (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))))) 2882 (warnings ())) |}] 2883 2884 let two_on_one_line = 2885 test "{[foo]} {[bar]}"; 2886 [%expect 2887 {| 2888 ((output 2889 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 2890 ((f.ml (1 8) (1 15)) (code_block ((f.ml (1 10) (1 13)) bar))))) 2891 (warnings 2892 ( "File \"f.ml\", line 1, characters 8-15:\ 2893 \n'{[...]}' (code block) should begin on its own line."))) |}] 2894 2895 let two = 2896 test "{[foo]}\n{[bar]}"; 2897 [%expect 2898 {| 2899 ((output 2900 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 2901 ((f.ml (2 0) (2 7)) (code_block ((f.ml (2 2) (2 5)) bar))))) 2902 (warnings ())) |}] 2903 2904 let two_with_blank_line = 2905 test "{[foo]}\n\n{[bar]}"; 2906 [%expect 2907 {| 2908 ((output 2909 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 2910 ((f.ml (3 0) (3 7)) (code_block ((f.ml (3 2) (3 5)) bar))))) 2911 (warnings ())) |}] 2912 2913 let followed_by_words = 2914 test "{[foo]} bar"; 2915 [%expect 2916 {| 2917 ((output 2918 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 2919 ((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word bar))))))) 2920 (warnings 2921 ( "File \"f.ml\", line 1, characters 8-11:\ 2922 \nParagraph should begin on its own line."))) |}] 2923 2924 let preceded_by_words = 2925 test "foo {[bar]}"; 2926 [%expect 2927 {| 2928 ((output 2929 (((f.ml (1 0) (1 4)) 2930 (paragraph (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space)))) 2931 ((f.ml (1 4) (1 11)) (code_block ((f.ml (1 6) (1 9)) bar))))) 2932 (warnings 2933 ( "File \"f.ml\", line 1, characters 4-11:\ 2934 \n'{[...]}' (code block) should begin on its own line."))) |}] 2935 2936 let preceded_by_paragraph = 2937 test "foo\n{[bar]}"; 2938 [%expect 2939 {| 2940 ((output 2941 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 2942 ((f.ml (2 0) (2 7)) (code_block ((f.ml (2 2) (2 5)) bar))))) 2943 (warnings ())) |}] 2944 2945 let followed_by_paragraph = 2946 test "{[foo]}\nbar"; 2947 [%expect 2948 {| 2949 ((output 2950 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 2951 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word bar))))))) 2952 (warnings ())) |}] 2953 2954 let unterminated = 2955 test "{[foo"; 2956 [%expect 2957 {| 2958 ((output (((f.ml (1 0) (1 5)) (code_block ((f.ml (1 2) (1 5)) foo))))) 2959 (warnings 2960 ( "File \"f.ml\", line 1, characters 0-5:\ 2961 \nMissing end of code block.\ 2962 \nSuggestion: add ']}'."))) |}] 2963 2964 let unterminated_bracket = 2965 test "{[foo]"; 2966 [%expect 2967 {| 2968 ((output (((f.ml (1 0) (1 6)) (code_block ((f.ml (1 2) (1 6)) foo]))))) 2969 (warnings 2970 ( "File \"f.ml\", line 1, characters 0-6:\ 2971 \nMissing end of code block.\ 2972 \nSuggestion: add ']}'."))) |}] 2973 2974 let trailing_cr = 2975 test "{[foo\r]}"; 2976 [%expect 2977 {| 2978 ((output (((f.ml (1 0) (1 8)) (code_block ((f.ml (1 2) (1 6)) "foo\r"))))) 2979 (warnings ())) 2980 |}] 2981 2982 let comment = 2983 test "{[(* foo *)\nlet bar = ()]}"; 2984 [%expect 2985 {| 2986 ((output 2987 (((f.ml (1 0) (2 14)) 2988 (code_block ((f.ml (1 2) (2 12)) "(* foo *)\ 2989 \nlet bar = ()"))))) 2990 (warnings ())) 2991 |}] 2992 2993 let docstring = 2994 test "{[(** foo *)\nlet bar = ()]}"; 2995 [%expect 2996 {| 2997 ((output 2998 (((f.ml (1 0) (2 14)) 2999 (code_block ((f.ml (1 2) (2 12)) "(** foo *)\ 3000 \nlet bar = ()"))))) 3001 (warnings ())) 3002 |}] 3003 3004 let docstring_with_code_block = 3005 test "{[(** {[foo]} *)\nlet bar = ()]}"; 3006 [%expect 3007 {| 3008 ((output 3009 (((f.ml (1 0) (1 13)) (code_block ((f.ml (1 2) (1 11)) "(** {[foo"))) 3010 ((f.ml (1 14) (2 12)) 3011 (paragraph 3012 (((f.ml (1 14) (1 16)) (word "*)")) ((f.ml (1 16) (2 0)) space) 3013 ((f.ml (2 0) (2 3)) (word let)) ((f.ml (2 3) (2 4)) space) 3014 ((f.ml (2 4) (2 7)) (word bar)) ((f.ml (2 7) (2 8)) space) 3015 ((f.ml (2 8) (2 9)) (word =)) ((f.ml (2 9) (2 10)) space) 3016 ((f.ml (2 10) (2 12)) (word "()"))))))) 3017 (warnings 3018 ( "File \"f.ml\", line 1, characters 14-16:\ 3019 \nParagraph should begin on its own line."))) |}] 3020 3021 let code_block_with_meta = 3022 test "{@ocaml env=f1 version>=4.06 [code goes here]}"; 3023 [%expect 3024 {| 3025 ((output 3026 (((f.ml (1 0) (1 46)) 3027 (code_block 3028 (((f.ml (1 2) (1 7)) ocaml) 3029 ((binding ((f.ml (1 8) (1 11)) env) ((f.ml (1 12) (1 14)) f1)) 3030 (binding ((f.ml (1 15) (1 23)) version>) ((f.ml (1 24) (1 28)) 4.06)))) 3031 ((f.ml (1 30) (1 44)) "code goes here"))))) 3032 (warnings ())) 3033 |}] 3034 3035 let code_block_with_output = 3036 test "{delim@ocaml[foo]delim[output {b foo}]}"; 3037 [%expect 3038 {| 3039 ((output 3040 (((f.ml (1 0) (1 39)) 3041 (code_block (((f.ml (1 7) (1 12)) ocaml) ()) ((f.ml (1 13) (1 16)) foo) 3042 ((paragraph 3043 (((f.ml (1 23) (1 29)) (word output)) ((f.ml (1 29) (1 30)) space) 3044 ((f.ml (1 30) (1 37)) (bold (((f.ml (1 33) (1 36)) (word foo)))))))))))) 3045 (warnings ())) 3046 |}] 3047 3048 let delimited_code_block_with_meta_and_output = 3049 test "{delim@ocaml env=f1 version>=4.06 [foo]delim[output {b foo}]}"; 3050 [%expect 3051 {| 3052 ((output 3053 (((f.ml (1 0) (1 61)) 3054 (code_block 3055 (((f.ml (1 7) (1 12)) ocaml) 3056 ((binding ((f.ml (1 13) (1 16)) env) ((f.ml (1 17) (1 19)) f1)) 3057 (binding ((f.ml (1 20) (1 28)) version>) ((f.ml (1 29) (1 33)) 4.06)))) 3058 ((f.ml (1 35) (1 38)) foo) 3059 ((paragraph 3060 (((f.ml (1 45) (1 51)) (word output)) ((f.ml (1 51) (1 52)) space) 3061 ((f.ml (1 52) (1 59)) (bold (((f.ml (1 55) (1 58)) (word foo)))))))))))) 3062 (warnings ())) 3063 |}] 3064 3065 (* Code block contains ']['. *) 3066 let code_block_with_output_without_delim = 3067 test "{[foo][output {b foo}]}"; 3068 [%expect 3069 {| 3070 ((output 3071 (((f.ml (1 0) (1 23)) 3072 (code_block ((f.ml (1 2) (1 21)) "foo][output {b foo}"))))) 3073 (warnings ())) 3074 |}] 3075 3076 (* Code block contains ']['. *) 3077 let code_block_with_output_and_lang_without_delim = 3078 test "{@ocaml[foo][output {b foo}]}"; 3079 [%expect 3080 {| 3081 ((output 3082 (((f.ml (1 0) (1 29)) 3083 (code_block (((f.ml (1 2) (1 7)) ocaml) ()) 3084 ((f.ml (1 8) (1 27)) "foo][output {b foo}"))))) 3085 (warnings ())) 3086 |}] 3087 3088 let code_block_with_output_unexpected_delim = 3089 test "{[foo]unexpected[output {b foo}]}"; 3090 [%expect 3091 {| 3092 ((output 3093 (((f.ml (1 0) (1 33)) 3094 (code_block ((f.ml (1 2) (1 31)) "foo]unexpected[output {b foo}"))))) 3095 (warnings ())) 3096 |}] 3097 3098 let code_block_with_output_lang_unexpected_delim = 3099 test "{@ocaml[foo]unexpected[output {b foo}]}"; 3100 [%expect 3101 {| 3102 ((output 3103 (((f.ml (1 0) (1 39)) 3104 (code_block (((f.ml (1 2) (1 7)) ocaml) ()) 3105 ((f.ml (1 8) (1 37)) "foo]unexpected[output {b foo}"))))) 3106 (warnings ())) 3107 |}] 3108 3109 let code_block_with_output_wrong_delim = 3110 test "{delim@ocaml[foo]wrong[output {b foo}]delim}"; 3111 [%expect 3112 {| 3113 ((output 3114 (((f.ml (1 0) (1 44)) 3115 (code_block (((f.ml (1 7) (1 12)) ocaml) ()) 3116 ((f.ml (1 13) (1 37)) "foo]wrong[output {b foo}"))))) 3117 (warnings ())) 3118 |}] 3119 3120 let code_block_empty_meta = 3121 test "{@[code goes here]}"; 3122 [%expect 3123 {| 3124 ((output 3125 (((f.ml (1 0) (1 19)) (code_block ((f.ml (1 3) (1 17)) "code goes here"))))) 3126 (warnings 3127 ( "File \"f.ml\", line 1, characters 0-3:\ 3128 \n'{@' should be followed by a language tag.\ 3129 \nSuggestion: try '{[ ... ]}' or '{@ocaml[ ... ]}'."))) 3130 |}] 3131 3132 let unterminated_code_block_with_meta = 3133 test "{@meta[foo"; 3134 [%expect 3135 {| 3136 ((output 3137 (((f.ml (1 0) (1 10)) 3138 (code_block (((f.ml (1 2) (1 6)) meta) ()) ((f.ml (1 7) (1 10)) foo))))) 3139 (warnings 3140 ( "File \"f.ml\", line 1, characters 0-10:\ 3141 \nMissing end of code block.\ 3142 \nSuggestion: add ']}'."))) 3143 |}] 3144 3145 let unterminated_code_block_with_meta = 3146 test "{@met"; 3147 [%expect 3148 {| 3149 ((output 3150 (((f.ml (1 0) (1 5)) 3151 (code_block (((f.ml (1 2) (1 5)) met) ()) ((f.ml (1 5) (1 5)) ""))))) 3152 (warnings 3153 ( "File \"f.ml\", line 1, characters 0-5:\ 3154 \nMissing end of code block.\ 3155 \nSuggestion: try '{@ocaml[ ... ]}'." 3156 "File \"f.ml\", line 1, characters 0-5:\ 3157 \n'{[...]}' (code block) should not be empty."))) 3158 |}] 3159 3160 let newlines_after_langtag = 3161 test "{@ocaml\n[ code ]}"; 3162 [%expect 3163 {| 3164 ((output 3165 (((f.ml (1 0) (2 9)) 3166 (code_block (((f.ml (1 2) (1 7)) ocaml) ()) 3167 ((f.ml (2 1) (2 7)) " code "))))) 3168 (warnings ())) 3169 |}] 3170 3171 let newlines_after_meta = 3172 test "{@ocaml kind=toplevel\n[ code ]}"; 3173 [%expect 3174 {| 3175 ((output 3176 (((f.ml (1 0) (2 9)) 3177 (code_block 3178 (((f.ml (1 2) (1 7)) ocaml) 3179 ((binding ((f.ml (1 8) (1 12)) kind) ((f.ml (1 13) (1 21)) toplevel)))) 3180 ((f.ml (2 1) (2 7)) " code "))))) 3181 (warnings ())) 3182 |}] 3183 3184 let spaces_after_meta = 3185 test "{@ocaml kind=toplevel [ code ]}"; 3186 [%expect 3187 {| 3188 ((output 3189 (((f.ml (1 0) (1 31)) 3190 (code_block 3191 (((f.ml (1 2) (1 7)) ocaml) 3192 ((binding ((f.ml (1 8) (1 12)) kind) ((f.ml (1 13) (1 21)) toplevel)))) 3193 ((f.ml (1 23) (1 29)) " code "))))) 3194 (warnings ())) 3195 |}] 3196 3197 let spaces_and_newline_after_meta = 3198 test "{@ocaml kind=toplevel \n [ code ]}"; 3199 [%expect 3200 {| 3201 ((output 3202 (((f.ml (1 0) (2 11)) 3203 (code_block 3204 (((f.ml (1 2) (1 7)) ocaml) 3205 ((binding ((f.ml (1 8) (1 12)) kind) ((f.ml (1 13) (1 21)) toplevel)))) 3206 ((f.ml (2 3) (2 9)) " code "))))) 3207 (warnings ())) 3208 |}] 3209 3210 let newlines_inside_meta = 3211 test "{@ocaml kind=toplevel\nenv=e1[ code ]}"; 3212 [%expect 3213 {| 3214 ((output 3215 (((f.ml (1 0) (2 15)) 3216 (code_block 3217 (((f.ml (1 2) (1 7)) ocaml) 3218 ((binding ((f.ml (1 8) (1 12)) kind) ((f.ml (1 13) (1 21)) toplevel)) 3219 (binding ((f.ml (2 0) (2 3)) env) ((f.ml (2 4) (2 6)) e1)))) 3220 ((f.ml (2 7) (2 13)) " code "))))) 3221 (warnings ())) 3222 |}] 3223 3224 let newlines_between_meta = 3225 test "{@ocaml\nkind=toplevel[ code ]}"; 3226 [%expect 3227 {| 3228 ((output 3229 (((f.ml (1 0) (2 22)) 3230 (code_block 3231 (((f.ml (1 2) (1 7)) ocaml) 3232 ((binding ((f.ml (2 0) (2 4)) kind) ((f.ml (2 5) (2 13)) toplevel)))) 3233 ((f.ml (2 14) (2 20)) " code "))))) 3234 (warnings ())) 3235 |}] 3236 3237 let empty_key = 3238 test "{@ocaml =foo [ code ]}"; 3239 [%expect 3240 {| 3241 ((output 3242 (((f.ml (1 0) (1 22)) 3243 (code_block (((f.ml (1 2) (1 7)) ocaml) ()) 3244 ((f.ml (1 14) (1 20)) " code "))))) 3245 (warnings 3246 ( "File \"f.ml\", line 1, characters 8-9:\ 3247 \nInvalid character in code block metadata tag '='." 3248 "File \"f.ml\", line 1, characters 9-10:\ 3249 \nInvalid character in code block metadata tag 'f'."))) 3250 |}] 3251 3252 let no_escape_without_quotes = 3253 test {|{@ocaml \n\t\b=hello [ code ]}|}; 3254 [%expect 3255 {| 3256 ((output 3257 (((f.ml (1 0) (1 30)) 3258 (code_block 3259 (((f.ml (1 2) (1 7)) ocaml) 3260 ((binding ((f.ml (1 8) (1 14)) "\\n\\t\\b") 3261 ((f.ml (1 15) (1 20)) hello)))) 3262 ((f.ml (1 22) (1 28)) " code "))))) 3263 (warnings ())) 3264 |}] 3265 3266 let escape_within_quotes = 3267 test {|{@ocaml "\065"=hello [ code ]}|}; 3268 [%expect 3269 {| 3270 ((output 3271 (((f.ml (1 0) (1 30)) 3272 (code_block 3273 (((f.ml (1 2) (1 7)) ocaml) 3274 ((binding ((f.ml (1 8) (1 14)) A) ((f.ml (1 15) (1 20)) hello)))) 3275 ((f.ml (1 22) (1 28)) " code "))))) 3276 (warnings ())) 3277 |}] 3278 3279 let langtag_non_word = 3280 test "{@ocaml,top[ code ]}"; 3281 [%expect 3282 {| 3283 ((output 3284 (((f.ml (1 0) (1 20)) 3285 (code_block (((f.ml (1 2) (1 7)) ocaml) ()) 3286 ((f.ml (1 12) (1 18)) " code "))))) 3287 (warnings 3288 ( "File \"f.ml\", line 1, characters 7-8:\ 3289 \nInvalid character in code block metadata tag ','."))) 3290 |}] 3291 3292 let delimited_code_block = 3293 test "{delim@ocaml[ all{}[2[{{]doo}}]]'''(* ]} ]delim}"; 3294 [%expect 3295 {| 3296 ((output 3297 (((f.ml (1 0) (1 48)) 3298 (code_block (((f.ml (1 7) (1 12)) ocaml) ()) 3299 ((f.ml (1 13) (1 41)) " all{}[2[{{]doo}}]]'''(* ]} "))))) 3300 (warnings ())) 3301 |}] 3302 3303 let code_block_with_output = 3304 test 3305 {|{delim@ocaml[ let x = ]delim[ {err@mdx-error[ here's the error ]} ]err} 3306 ]delim}|}; 3307 [%expect 3308 {| 3309 ((output 3310 (((f.ml (1 0) (2 15)) 3311 (code_block (((f.ml (1 7) (1 12)) ocaml) ()) 3312 ((f.ml (1 13) (1 22)) " let x = ") 3313 ((code_block (((f.ml (1 35) (1 44)) mdx-error) ()) 3314 ((f.ml (1 45) (1 66)) " here's the error ]} ")) 3315 (paragraph 3316 (((f.ml (2 8) (2 9)) (word ])) ((f.ml (2 9) (2 14)) (word delim))))))))) 3317 (warnings 3318 ( "File \"f.ml\", line 2, characters 8-9:\ 3319 \nUnpaired ']' (end of code).\ 3320 \nSuggestion: try '\\]'."))) 3321 |}] 3322 3323 let delimited_code_block_with_output = 3324 test "{delim@ocaml[ foo ]delim[ ]}"; 3325 [%expect 3326 {| 3327 ((output 3328 (((f.ml (1 0) (1 28)) 3329 (code_block (((f.ml (1 7) (1 12)) ocaml) ()) 3330 ((f.ml (1 13) (1 18)) " foo ") ())))) 3331 (warnings ())) 3332 |}] 3333 3334 (** {3 Code block indentation} 3335 3336 Code blocks strip some whitespace from the content of a multiline code 3337 block. We test that here, as well as warnings related to that. 3338 3339 Let's test warnings first. When the indentation is less than the 3340 identation of the opening bracket, we warn. *) 3341 3342 let too_few_indentation = 3343 test {| 3344 {[ 3345 foo 3346 ]}|}; 3347 [%expect 3348 {| 3349 ((output 3350 (((f.ml (2 3) (4 3)) 3351 (code_block ((f.ml (2 5) (4 1)) foo) 3352 (Warnings 3353 "File \"f.ml\", line 2, character 3 to line 4, character 3:\ 3354 \nCode blocks should be indented at the opening `{`."))))) 3355 (warnings ())) 3356 |}] 3357 3358 let multiline_without_newline = 3359 test {| 3360 {[ foo 3361 ]}|}; 3362 [%expect 3363 {| 3364 ((output (((f.ml (2 3) (3 3)) (code_block ((f.ml (2 5) (3 1)) " foo"))))) 3365 (warnings ())) 3366 |}] 3367 3368 let everything_is_wrong = 3369 test {| 3370 {[ foo 3371 bar ]}|}; 3372 [%expect 3373 {| 3374 ((output 3375 (((f.ml (2 3) (3 8)) 3376 (code_block ((f.ml (2 5) (3 6)) " foo\ 3377 \nbar ") 3378 (Warnings 3379 "File \"f.ml\", line 2, character 3 to line 3, character 8:\ 3380 \nCode blocks should be indented at the opening `{`."))))) 3381 (warnings ())) 3382 |}] 3383 3384 let all_good_multiline = 3385 test {| 3386 {[ 3387 foo 3388 ]}|}; 3389 [%expect 3390 {| 3391 ((output (((f.ml (2 3) (4 3)) (code_block ((f.ml (2 5) (4 1)) foo))))) 3392 (warnings ())) 3393 |}] 3394 3395 let all_good_single_line = 3396 test {| {[ foo ]} |}; 3397 [%expect 3398 {| 3399 ((output (((f.ml (1 1) (1 10)) (code_block ((f.ml (1 3) (1 8)) " foo "))))) 3400 (warnings ())) 3401 |}] 3402 3403 (** Let's now test that the correct amount of whitespace is removed. *) 3404 3405 let descending_stair = 3406 test {| 3407 {[ 3408 foo 3409 bar 3410 baz 3411 ]}|}; 3412 [%expect 3413 {| 3414 ((output 3415 (((f.ml (2 3) (6 3)) 3416 (code_block ((f.ml (2 5) (6 1)) "foo\ 3417 \n bar\ 3418 \n baz"))))) 3419 (warnings ())) 3420 |}] 3421 3422 let ascending_stair = 3423 test {| 3424 {[ 3425 baz 3426 bar 3427 foo 3428 ]}|}; 3429 [%expect 3430 {| 3431 ((output 3432 (((f.ml (2 3) (6 3)) 3433 (code_block ((f.ml (2 5) (6 1)) " baz\ 3434 \n bar\ 3435 \nfoo"))))) 3436 (warnings ())) 3437 |}] 3438 3439 let indented_after_opening_fence = 3440 test {| 3441 {[ 3442 baz 3443 bar 3444 foo 3445 ]}|}; 3446 [%expect 3447 {| 3448 ((output 3449 (((f.ml (2 3) (6 3)) 3450 (code_block ((f.ml (2 5) (6 1)) " baz\ 3451 \n bar\ 3452 \n foo"))))) 3453 (warnings ())) 3454 |}] 3455 3456 let indentation_warning_case = 3457 test {| 3458 {[ 3459 baz 3460 bar 3461 foo 3462 ]}|}; 3463 [%expect 3464 {| 3465 ((output 3466 (((f.ml (2 3) (6 3)) 3467 (code_block ((f.ml (2 5) (6 1)) " baz\ 3468 \nbar\ 3469 \n foo") 3470 (Warnings 3471 "File \"f.ml\", line 2, character 3 to line 6, character 3:\ 3472 \nCode blocks should be indented at the opening `{`."))))) 3473 (warnings ())) 3474 |}] 3475 3476 (** {3 Metadata tags} 3477 3478 Code blocks have a metadata field, with bindings and simple tags. *) 3479 3480 let lots_of_tags = 3481 test 3482 {|{@ocaml env=f1 version=4.06 "tag with several words" "binding with"=singleword also="other case" "everything has"="multiple words" [foo]}|}; 3483 [%expect 3484 {| 3485 ((output 3486 (((f.ml (1 0) (1 137)) 3487 (code_block 3488 (((f.ml (1 2) (1 7)) ocaml) 3489 ((binding ((f.ml (1 8) (1 11)) env) ((f.ml (1 12) (1 14)) f1)) 3490 (binding ((f.ml (1 15) (1 22)) version) ((f.ml (1 23) (1 27)) 4.06)) 3491 (tag ((f.ml (1 28) (1 52)) "tag with several words")) 3492 (binding ((f.ml (1 53) (1 67)) "binding with") 3493 ((f.ml (1 68) (1 78)) singleword)) 3494 (binding ((f.ml (1 79) (1 83)) also) 3495 ((f.ml (1 84) (1 96)) "other case")) 3496 (binding ((f.ml (1 97) (1 113)) "everything has") 3497 ((f.ml (1 114) (1 130)) "multiple words")))) 3498 ((f.ml (1 132) (1 135)) foo))))) 3499 (warnings ())) 3500 |}] 3501 3502 let lots_of_tags_with_newlines = 3503 test 3504 {|{@ocaml 3505 env=f1 3506 version=4.06 3507 single_tag 3508 "tag with several words" 3509 "binding with"=singleword 3510 also="other case" 3511 "everything has"="multiple words" 3512 [foo]}|}; 3513 [%expect 3514 {| 3515 ((output 3516 (((f.ml (1 0) (9 15)) 3517 (code_block 3518 (((f.ml (1 2) (1 7)) ocaml) 3519 ((binding ((f.ml (2 9) (2 12)) env) ((f.ml (2 13) (2 15)) f1)) 3520 (binding ((f.ml (3 9) (3 16)) version) ((f.ml (3 17) (3 21)) 4.06)) 3521 (tag ((f.ml (4 9) (4 19)) single_tag)) 3522 (tag ((f.ml (5 9) (5 33)) "tag with several words")) 3523 (binding ((f.ml (6 9) (6 23)) "binding with") 3524 ((f.ml (6 24) (6 34)) singleword)) 3525 (binding ((f.ml (7 9) (7 13)) also) 3526 ((f.ml (7 14) (7 26)) "other case")) 3527 (binding ((f.ml (8 9) (8 25)) "everything has") 3528 ((f.ml (8 26) (8 42)) "multiple words")))) 3529 ((f.ml (9 10) (9 13)) foo))))) 3530 (warnings ())) 3531 |}] 3532 3533 let escaping1 = 3534 test {|{@ocaml "\""="\"" [foo]}|}; 3535 [%expect 3536 {| 3537 ((output 3538 (((f.ml (1 0) (1 24)) 3539 (code_block 3540 (((f.ml (1 2) (1 7)) ocaml) 3541 ((binding ((f.ml (1 8) (1 12)) "\"") ((f.ml (1 13) (1 17)) "\"")))) 3542 ((f.ml (1 19) (1 22)) foo))))) 3543 (warnings ())) 3544 |}] 3545 3546 let escaping2 = 3547 test {|{@ocaml \"=\" [foo]}|}; 3548 [%expect 3549 {| 3550 ((output 3551 (((f.ml (1 0) (1 20)) 3552 (code_block (((f.ml (1 2) (1 7)) ocaml) ()) ((f.ml (1 15) (1 18)) foo))))) 3553 (warnings 3554 ( "File \"f.ml\", line 1, characters 9-10:\ 3555 \nInvalid character in code block metadata tag '\"'."))) 3556 |}] 3557 3558 let two_slashes_are_required = 3559 test {|{@ocaml "\\" [foo]}|}; 3560 [%expect 3561 {| 3562 ((output 3563 (((f.ml (1 0) (1 19)) 3564 (code_block 3565 (((f.ml (1 2) (1 7)) ocaml) ((tag ((f.ml (1 8) (1 12)) "\\")))) 3566 ((f.ml (1 14) (1 17)) foo))))) 3567 (warnings ())) 3568 |}] 3569 3570 let escaped_char_are_allowed_but_warn = 3571 test {| 3572 {@ocaml "\a\b\c" [foo]}|}; 3573 [%expect 3574 {| 3575 ((output 3576 (((f.ml (2 5) (2 28)) 3577 (code_block 3578 (((f.ml (2 7) (2 12)) ocaml) ((tag ((f.ml (2 13) (2 21)) "a\bc")))) 3579 ((f.ml (2 23) (2 26)) foo))))) 3580 (warnings 3581 ( "File \"f.ml\", line 2, characters 14-16:\ 3582 \nThe 'a' character should not be escaped.\ 3583 \nSuggestion: Remove \\." 3584 "File \"f.ml\", line 2, characters 18-20:\ 3585 \nThe 'c' character should not be escaped.\ 3586 \nSuggestion: Remove \\."))) 3587 |}] 3588 3589 let escaped_char_are_allowed_but_warn2 = 3590 test {| 3591 {@ocaml "\a\b\c"="\x\y\z" [foo]}|}; 3592 [%expect 3593 {| 3594 ((output 3595 (((f.ml (2 5) (2 37)) 3596 (code_block 3597 (((f.ml (2 7) (2 12)) ocaml) 3598 ((binding ((f.ml (2 13) (2 21)) "a\bc") ((f.ml (2 22) (2 30)) xyz)))) 3599 ((f.ml (2 32) (2 35)) foo))))) 3600 (warnings 3601 ( "File \"f.ml\", line 2, characters 14-16:\ 3602 \nThe 'a' character should not be escaped.\ 3603 \nSuggestion: Remove \\." 3604 "File \"f.ml\", line 2, characters 18-20:\ 3605 \nThe 'c' character should not be escaped.\ 3606 \nSuggestion: Remove \\." 3607 "File \"f.ml\", line 2, characters 23-25:\ 3608 \nThe 'x' character should not be escaped.\ 3609 \nSuggestion: Remove \\." 3610 "File \"f.ml\", line 2, characters 25-27:\ 3611 \nThe 'y' character should not be escaped.\ 3612 \nSuggestion: Remove \\." 3613 "File \"f.ml\", line 2, characters 27-29:\ 3614 \nThe 'z' character should not be escaped.\ 3615 \nSuggestion: Remove \\."))) 3616 |}] 3617 end in 3618 () 3619 3620let%expect_test _ = 3621 let module Verbatim = struct 3622 let basic = 3623 test "{v foo v}"; 3624 [%expect 3625 {| ((output (((f.ml (1 0) (1 9)) (verbatim foo)))) (warnings ())) |}] 3626 3627 let empty = 3628 test "{v v}"; 3629 [%expect 3630 {| 3631 ((output (((f.ml (1 0) (1 5)) (verbatim "")))) 3632 (warnings 3633 ( "File \"f.ml\", line 1, characters 0-5:\ 3634 \n'{v ... v}' (verbatim text) should not be empty."))) |}] 3635 3636 let degenerate = 3637 test "{vv}"; 3638 [%expect 3639 {| 3640 ((output (((f.ml (1 0) (1 4)) (verbatim v})))) 3641 (warnings 3642 ( "File \"f.ml\", line 1, characters 2-4:\ 3643 \n'v}' should be preceded by whitespace." 3644 "File \"f.ml\", line 1, characters 0-2:\ 3645 \n'{v' should be followed by whitespace."))) |}] 3646 3647 let whitespace_only = 3648 test "{v v}"; 3649 [%expect 3650 {| 3651 ((output (((f.ml (1 0) (1 6)) (verbatim "")))) 3652 (warnings 3653 ( "File \"f.ml\", line 1, characters 0-6:\ 3654 \n'{v ... v}' (verbatim text) should not be empty."))) |}] 3655 3656 let blank_line_only = 3657 test "{v\n \nv}"; 3658 [%expect 3659 {| ((output (((f.ml (1 0) (3 2)) (verbatim " ")))) (warnings ())) |}] 3660 3661 let no_leading_whitespace = 3662 test "{vfoo v}"; 3663 [%expect 3664 {| 3665 ((output (((f.ml (1 0) (1 8)) (verbatim foo)))) 3666 (warnings 3667 ( "File \"f.ml\", line 1, characters 0-2:\ 3668 \n'{v' should be followed by whitespace."))) |}] 3669 3670 let no_trailing_whitespace = 3671 test "{v foov}"; 3672 [%expect 3673 {| 3674 ((output (((f.ml (1 0) (1 8)) (verbatim foov})))) 3675 (warnings 3676 ( "File \"f.ml\", line 1, characters 6-8:\ 3677 \n'v}' should be preceded by whitespace."))) |}] 3678 3679 let multiple_leading_whitespace = 3680 test "{v foo v}"; 3681 [%expect 3682 {| ((output (((f.ml (1 0) (1 10)) (verbatim " foo")))) (warnings ())) |}] 3683 3684 let multiple_trailing_whitespace = 3685 test "{v foo v}"; 3686 [%expect 3687 {| ((output (((f.ml (1 0) (1 10)) (verbatim "foo ")))) (warnings ())) |}] 3688 3689 let leading_tab = 3690 test "{v\tfoo v}"; 3691 [%expect 3692 {| ((output (((f.ml (1 0) (1 9)) (verbatim "\tfoo")))) (warnings ())) |}] 3693 3694 let leading_newline = 3695 test "{v\nfoo v}"; 3696 [%expect 3697 {| ((output (((f.ml (1 0) (2 6)) (verbatim foo)))) (warnings ())) |}] 3698 3699 let leading_cr_lf = 3700 test "{v\r\nfoo v}"; 3701 [%expect 3702 {| ((output (((f.ml (1 0) (2 6)) (verbatim foo)))) (warnings ())) |}] 3703 3704 let trailing_tab = 3705 test "{v foo\tv}"; 3706 [%expect 3707 {| ((output (((f.ml (1 0) (1 9)) (verbatim "foo\t")))) (warnings ())) |}] 3708 3709 let trailing_newline = 3710 test "{v foo\nv}"; 3711 [%expect 3712 {| ((output (((f.ml (1 0) (2 2)) (verbatim foo)))) (warnings ())) |}] 3713 3714 let trailing_cr_lf = 3715 test "{v foo\r\nv}"; 3716 [%expect 3717 {| ((output (((f.ml (1 0) (2 2)) (verbatim "foo\r")))) (warnings ())) |}] 3718 3719 let internal_whitespace = 3720 test "{v foo bar v}"; 3721 [%expect 3722 {| ((output (((f.ml (1 0) (1 13)) (verbatim "foo bar")))) (warnings ())) |}] 3723 3724 let newline = 3725 test "{v foo\nbar v}"; 3726 [%expect 3727 {| 3728 ((output (((f.ml (1 0) (2 6)) (verbatim "foo\ 3729 \nbar")))) (warnings ())) 3730 |}] 3731 3732 let cr_lf = 3733 test "{v foo\r\nbar v}"; 3734 [%expect 3735 {| 3736 ((output (((f.ml (1 0) (2 6)) (verbatim "foo\r\ 3737 \nbar")))) (warnings ())) 3738 |}] 3739 3740 let blank_line = 3741 test "{v foo\n\nbar v}"; 3742 [%expect 3743 {| 3744 ((output (((f.ml (1 0) (3 6)) (verbatim "foo\ 3745 \n\ 3746 \nbar")))) (warnings ())) 3747 |}] 3748 3749 let leading_newlines = 3750 test "{v\n\nfoo v}"; 3751 [%expect 3752 {| 3753 ((output (((f.ml (1 0) (3 6)) (verbatim "\ 3754 \nfoo")))) (warnings ())) 3755 |}] 3756 3757 let leading_newline_with_space = 3758 test "{v\n foo v}"; 3759 [%expect 3760 {| ((output (((f.ml (1 0) (2 7)) (verbatim " foo")))) (warnings ())) |}] 3761 3762 let leading_newline_with_trash = 3763 test "{v \nfoo v}"; 3764 [%expect 3765 {| ((output (((f.ml (1 0) (2 6)) (verbatim foo)))) (warnings ())) |}] 3766 3767 let nested_opener = 3768 test "{v {v v}"; 3769 [%expect 3770 {| ((output (((f.ml (1 0) (1 8)) (verbatim {v)))) (warnings ())) |}] 3771 3772 let nested_closer = 3773 test "{v foo v} v}"; 3774 [%expect 3775 {| 3776 ((output 3777 (((f.ml (1 0) (1 9)) (verbatim foo)) 3778 ((f.ml (1 10) (1 11)) (paragraph (((f.ml (1 10) (1 11)) (word v))))) 3779 ((f.ml (1 11) (1 12)) (paragraph (((f.ml (1 11) (1 12)) (word }))))))) 3780 (warnings 3781 ( "File \"f.ml\", line 1, characters 10-11:\ 3782 \nParagraph should begin on its own line." 3783 "File \"f.ml\", line 1, characters 11-12:\ 3784 \nUnpaired '}' (end of markup).\ 3785 \nSuggestion: try '\\}'."))) |}] 3786 3787 let nested_closer_with_word = 3788 test "{v {dev} v}"; 3789 [%expect 3790 {| ((output (((f.ml (1 0) (1 11)) (verbatim {dev})))) (warnings ())) |}] 3791 3792 let nested_v = 3793 test "{v v v}"; 3794 [%expect 3795 {| ((output (((f.ml (1 0) (1 7)) (verbatim v)))) (warnings ())) |}] 3796 3797 let two_nested_vs = 3798 test "{v vv v}"; 3799 [%expect 3800 {| ((output (((f.ml (1 0) (1 8)) (verbatim vv)))) (warnings ())) |}] 3801 3802 let nested_v_at_end = 3803 test "{v vv}"; 3804 [%expect 3805 {| 3806 ((output (((f.ml (1 0) (1 6)) (verbatim vv})))) 3807 (warnings 3808 ( "File \"f.ml\", line 1, characters 4-6:\ 3809 \n'v}' should be preceded by whitespace."))) |}] 3810 3811 let two_nested_vs_at_end = 3812 test "{v vvv}"; 3813 [%expect 3814 {| 3815 ((output (((f.ml (1 0) (1 7)) (verbatim vvv})))) 3816 (warnings 3817 ( "File \"f.ml\", line 1, characters 5-7:\ 3818 \n'v}' should be preceded by whitespace."))) |}] 3819 3820 let nested_vs_in_text = 3821 test "{v foovvbar v}"; 3822 [%expect 3823 {| ((output (((f.ml (1 0) (1 14)) (verbatim foovvbar)))) (warnings ())) |}] 3824 3825 let trailing_newlines = 3826 test "{v foo\n\nv}"; 3827 [%expect 3828 {| ((output (((f.ml (1 0) (3 2)) (verbatim "foo\n")))) (warnings ())) |}] 3829 3830 let preceded_by_whitespace = 3831 test "{v foo v}"; 3832 [%expect 3833 {| ((output (((f.ml (1 0) (1 9)) (verbatim foo)))) (warnings ())) |}] 3834 3835 let followed_by_whitespace = 3836 test "{v foo v}"; 3837 [%expect 3838 {| ((output (((f.ml (1 0) (1 9)) (verbatim foo)))) (warnings ())) |}] 3839 3840 let two_on_one_line = 3841 test "{v foo v} {v bar v}"; 3842 [%expect 3843 {| 3844 ((output 3845 (((f.ml (1 0) (1 9)) (verbatim foo)) ((f.ml (1 10) (1 19)) (verbatim bar)))) 3846 (warnings 3847 ( "File \"f.ml\", line 1, characters 10-19:\ 3848 \n'{v ... v}' (verbatim text) should begin on its own line."))) |}] 3849 3850 let two = 3851 test "{v foo v}\n{v bar v}"; 3852 [%expect 3853 {| 3854 ((output 3855 (((f.ml (1 0) (1 9)) (verbatim foo)) ((f.ml (2 0) (2 9)) (verbatim bar)))) 3856 (warnings ())) |}] 3857 3858 let two_with_blank_line = 3859 test "{v foo v}\n\n{v bar v}"; 3860 [%expect 3861 {| 3862 ((output 3863 (((f.ml (1 0) (1 9)) (verbatim foo)) ((f.ml (3 0) (3 9)) (verbatim bar)))) 3864 (warnings ())) |}] 3865 3866 let followed_by_words = 3867 test "{v foo v} bar"; 3868 [%expect 3869 {| 3870 ((output 3871 (((f.ml (1 0) (1 9)) (verbatim foo)) 3872 ((f.ml (1 10) (1 13)) (paragraph (((f.ml (1 10) (1 13)) (word bar))))))) 3873 (warnings 3874 ( "File \"f.ml\", line 1, characters 10-13:\ 3875 \nParagraph should begin on its own line."))) |}] 3876 3877 let preceded_by_words = 3878 test "foo {v bar v}"; 3879 [%expect 3880 {| 3881 ((output 3882 (((f.ml (1 0) (1 4)) 3883 (paragraph (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) space)))) 3884 ((f.ml (1 4) (1 13)) (verbatim bar)))) 3885 (warnings 3886 ( "File \"f.ml\", line 1, characters 4-13:\ 3887 \n'{v ... v}' (verbatim text) should begin on its own line."))) |}] 3888 3889 let preceded_by_paragraph = 3890 test "foo\n{v bar v}"; 3891 [%expect 3892 {| 3893 ((output 3894 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 3895 ((f.ml (2 0) (2 9)) (verbatim bar)))) 3896 (warnings ())) |}] 3897 3898 let followed_by_paragraph = 3899 test "{v foo v}\nbar"; 3900 [%expect 3901 {| 3902 ((output 3903 (((f.ml (1 0) (1 9)) (verbatim foo)) 3904 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word bar))))))) 3905 (warnings ())) |}] 3906 3907 let unterminated = 3908 test "{v foo"; 3909 [%expect 3910 {| 3911 ((output (((f.ml (1 0) (1 6)) (verbatim foo)))) 3912 (warnings 3913 ( "File \"f.ml\", line 1, characters 6-6:\ 3914 \nEnd of text is not allowed in '{v ... v}' (verbatim text)."))) |}] 3915 3916 let unterminated_v = 3917 test "{v foo v"; 3918 [%expect 3919 {| 3920 ((output (((f.ml (1 0) (1 8)) (verbatim "foo v")))) 3921 (warnings 3922 ( "File \"f.ml\", line 1, characters 8-8:\ 3923 \nEnd of text is not allowed in '{v ... v}' (verbatim text)."))) |}] 3924 3925 let unterminated_empty = 3926 test "{v"; 3927 [%expect 3928 {| 3929 ((output (((f.ml (1 0) (1 2)) (verbatim "")))) 3930 (warnings 3931 ( "File \"f.ml\", line 1, characters 2-2:\ 3932 \nEnd of text is not allowed in '{v ... v}' (verbatim text)." 3933 "File \"f.ml\", line 1, characters 0-2:\ 3934 \n'{v ... v}' (verbatim text) should not be empty."))) |}] 3935 3936 let unterminated_whitespace = 3937 test "{v"; 3938 [%expect 3939 {| 3940 ((output (((f.ml (1 0) (1 2)) (verbatim "")))) 3941 (warnings 3942 ( "File \"f.ml\", line 1, characters 2-2:\ 3943 \nEnd of text is not allowed in '{v ... v}' (verbatim text)." 3944 "File \"f.ml\", line 1, characters 0-2:\ 3945 \n'{v ... v}' (verbatim text) should not be empty."))) |}] 3946 3947 let unterminated_whitespace_2 = 3948 test "{v"; 3949 [%expect 3950 {| 3951 ((output (((f.ml (1 0) (1 2)) (verbatim "")))) 3952 (warnings 3953 ( "File \"f.ml\", line 1, characters 2-2:\ 3954 \nEnd of text is not allowed in '{v ... v}' (verbatim text)." 3955 "File \"f.ml\", line 1, characters 0-2:\ 3956 \n'{v ... v}' (verbatim text) should not be empty."))) |}] 3957 3958 let trailing_cr = 3959 test "{v foo\rv}"; 3960 [%expect 3961 {| ((output (((f.ml (1 0) (1 9)) (verbatim "foo\r")))) (warnings ())) |}] 3962 3963 (** {3 Verbatim indentation} 3964 3965 Verbatims work as code blocks. We test that here. *) 3966 3967 let too_few_indentation = 3968 test {| 3969 {v 3970 foo 3971 v}|}; 3972 [%expect 3973 {| 3974 ((output 3975 (((f.ml (2 3) (4 3)) 3976 (verbatim foo 3977 (Warnings 3978 "File \"f.ml\", line 2, character 3 to line 4, character 3:\ 3979 \nVerbatims should be indented at the opening `{`."))))) 3980 (warnings ())) 3981 |}] 3982 3983 let multiline_without_newline = 3984 test {| 3985 {v foo 3986 v}|}; 3987 [%expect 3988 {| ((output (((f.ml (2 3) (3 3)) (verbatim foo)))) (warnings ())) |}] 3989 3990 let everything_is_wrong = 3991 test {| 3992 {[ foo 3993 bar ]}|}; 3994 [%expect 3995 {| 3996 ((output 3997 (((f.ml (2 3) (3 8)) 3998 (code_block ((f.ml (2 5) (3 6)) " foo\ 3999 \nbar ") 4000 (Warnings 4001 "File \"f.ml\", line 2, character 3 to line 3, character 8:\ 4002 \nCode blocks should be indented at the opening `{`."))))) 4003 (warnings ())) 4004 |}] 4005 4006 let all_good_multiline = 4007 test {| 4008 {v 4009 foo 4010 v}|}; 4011 [%expect 4012 {| ((output (((f.ml (2 3) (4 3)) (verbatim foo)))) (warnings ())) |}] 4013 4014 let all_good_single_line = 4015 test {| {v foo v} |}; 4016 [%expect 4017 {| ((output (((f.ml (1 1) (1 10)) (verbatim foo)))) (warnings ())) |}] 4018 4019 (** Let's now test that the correct amount of whitespace is removed. *) 4020 4021 let descending_stair = 4022 test {| 4023 {v 4024 foo 4025 bar 4026 baz 4027 v}|}; 4028 [%expect 4029 {| 4030 ((output (((f.ml (2 3) (6 3)) (verbatim "foo\ 4031 \n bar\ 4032 \n baz")))) 4033 (warnings ())) 4034 |}] 4035 4036 let ascending_stair = 4037 test {| 4038 {v 4039 baz 4040 bar 4041 foo 4042 v}|}; 4043 [%expect 4044 {| 4045 ((output (((f.ml (2 3) (6 3)) (verbatim " baz\ 4046 \n bar\ 4047 \nfoo")))) 4048 (warnings ())) 4049 |}] 4050 4051 let indented_after_opening_fence = 4052 test {| 4053 {v 4054 baz 4055 bar 4056 foo 4057 v}|}; 4058 [%expect 4059 {| 4060 ((output (((f.ml (2 3) (6 3)) (verbatim " baz\ 4061 \n bar\ 4062 \n foo")))) 4063 (warnings ())) 4064 |}] 4065 4066 let indentation_warning_case = 4067 test {| 4068 {v 4069 baz 4070 bar 4071 foo 4072 v}|}; 4073 [%expect 4074 {| 4075 ((output 4076 (((f.ml (2 3) (6 3)) 4077 (verbatim " baz\ 4078 \nbar\ 4079 \n foo" 4080 (Warnings 4081 "File \"f.ml\", line 2, character 3 to line 6, character 3:\ 4082 \nVerbatims should be indented at the opening `{`."))))) 4083 (warnings ())) 4084 |}] 4085 end in 4086 () 4087 4088let%expect_test _ = 4089 let module Shorthand_list = struct 4090 let basic = 4091 test "- foo"; 4092 [%expect 4093 {| 4094 ((output 4095 (((f.ml (1 0) (1 5)) 4096 (unordered light 4097 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))))) 4098 (warnings ())) |}] 4099 4100 let multiple_items = 4101 test "- foo\n- bar"; 4102 [%expect 4103 {| 4104 ((output 4105 (((f.ml (1 0) (2 5)) 4106 (unordered light 4107 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo)))))) 4108 (((f.ml (2 2) (2 5)) (paragraph (((f.ml (2 2) (2 5)) (word bar))))))))))) 4109 (warnings ())) |}] 4110 4111 let two_lists = 4112 test "- foo\n\n- bar"; 4113 [%expect 4114 {| 4115 ((output 4116 (((f.ml (1 0) (1 5)) 4117 (unordered light 4118 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))) 4119 ((f.ml (3 0) (3 5)) 4120 (unordered light 4121 ((((f.ml (3 2) (3 5)) (paragraph (((f.ml (3 2) (3 5)) (word bar))))))))))) 4122 (warnings ())) |}] 4123 4124 let ordered = 4125 test "+ foo"; 4126 [%expect 4127 {| 4128 ((output 4129 (((f.ml (1 0) (1 5)) 4130 (ordered light 4131 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))))) 4132 (warnings ())) |}] 4133 4134 let leading_whitespace = 4135 test "- foo"; 4136 [%expect 4137 {| 4138 ((output 4139 (((f.ml (1 0) (1 5)) 4140 (unordered light 4141 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))))) 4142 (warnings ())) |}] 4143 4144 let trailing_whitespace = 4145 test "- foo"; 4146 [%expect 4147 {| 4148 ((output 4149 (((f.ml (1 0) (1 5)) 4150 (unordered light 4151 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))))) 4152 (warnings ())) |}] 4153 4154 let bullet_in_line = 4155 test "- foo - bar"; 4156 [%expect 4157 {| 4158 ((output 4159 (((f.ml (1 0) (1 11)) 4160 (unordered light 4161 ((((f.ml (1 2) (1 11)) 4162 (paragraph 4163 (((f.ml (1 2) (1 5)) (word foo)) ((f.ml (1 5) (1 6)) space) 4164 ((f.ml (1 6) (1 7)) (word -)) ((f.ml (1 7) (1 8)) space) 4165 ((f.ml (1 8) (1 11)) (word bar))))))))))) 4166 (warnings ())) |}] 4167 4168 let bullet_in_line_immediately = 4169 test "- - foo"; 4170 [%expect 4171 {| 4172 ((output 4173 (((f.ml (1 0) (1 7)) 4174 (unordered light 4175 (() 4176 (((f.ml (1 4) (1 7)) (paragraph (((f.ml (1 4) (1 7)) (word foo))))))))))) 4177 (warnings 4178 ( "File \"f.ml\", line 1, characters 2-3:\ 4179 \n'-' (bulleted list item) should begin on its own line." 4180 "File \"f.ml\", line 1, characters 0-1:\ 4181 \n'-' (bulleted list item) should not be empty."))) |}] 4182 4183 let code_block = 4184 test "- {[foo]}"; 4185 [%expect 4186 {| 4187 ((output 4188 (((f.ml (1 0) (1 9)) 4189 (unordered light 4190 ((((f.ml (1 2) (1 9)) (code_block ((f.ml (1 4) (1 7)) foo))))))))) 4191 (warnings ())) |}] 4192 4193 let verbatim = 4194 test "- {v foo v}"; 4195 [%expect 4196 {| 4197 ((output 4198 (((f.ml (1 0) (1 11)) 4199 (unordered light ((((f.ml (1 2) (1 11)) (verbatim foo)))))))) 4200 (warnings ())) |}] 4201 4202 let multiple_blocks = 4203 test "- foo\n{[bar]}"; 4204 [%expect 4205 {| 4206 ((output 4207 (((f.ml (1 0) (2 7)) 4208 (unordered light 4209 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))) 4210 ((f.ml (2 0) (2 7)) (code_block ((f.ml (2 2) (2 5)) bar))))))))) 4211 (warnings ())) |}] 4212 4213 let followed_by_code_block = 4214 test "- foo\n\n{[bar]}"; 4215 [%expect 4216 {| 4217 ((output 4218 (((f.ml (1 0) (1 5)) 4219 (unordered light 4220 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))) 4221 ((f.ml (3 0) (3 7)) (code_block ((f.ml (3 2) (3 5)) bar))))) 4222 (warnings ())) |}] 4223 4224 let different_kinds = 4225 test "- foo\n+ bar"; 4226 [%expect 4227 {| 4228 ((output 4229 (((f.ml (1 0) (1 5)) 4230 (unordered light 4231 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))) 4232 ((f.ml (2 0) (2 5)) 4233 (ordered light 4234 ((((f.ml (2 2) (2 5)) (paragraph (((f.ml (2 2) (2 5)) (word bar))))))))))) 4235 (warnings ())) |}] 4236 4237 let no_content = 4238 test "-"; 4239 [%expect 4240 {| 4241 ((output (((f.ml (1 0) (1 1)) (unordered light (()))))) 4242 (warnings 4243 ( "File \"f.ml\", line 1, characters 0-1:\ 4244 \n'-' (bulleted list item) should not be empty."))) |}] 4245 4246 let immediate_newline = 4247 test "-\nfoo"; 4248 [%expect 4249 {| 4250 ((output 4251 (((f.ml (1 0) (2 3)) 4252 (unordered light 4253 ((((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))))))) 4254 (warnings ())) |}] 4255 4256 let immediate_blank_line = 4257 test "-\n\nfoo"; 4258 [%expect 4259 {| 4260 ((output 4261 (((f.ml (1 0) (1 1)) (unordered light (()))) 4262 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word foo))))))) 4263 (warnings 4264 ( "File \"f.ml\", line 1, characters 0-1:\ 4265 \n'-' (bulleted list item) should not be empty."))) |}] 4266 4267 let immediate_markup = 4268 test "-{b foo}"; 4269 [%expect 4270 {| 4271 ((output 4272 (((f.ml (1 0) (1 8)) 4273 (unordered light 4274 ((((f.ml (1 1) (1 8)) 4275 (paragraph 4276 (((f.ml (1 1) (1 8)) (bold (((f.ml (1 4) (1 7)) (word foo)))))))))))))) 4277 (warnings ())) |}] 4278 4279 let after_code_block = 4280 test "{[foo]} - bar"; 4281 [%expect 4282 {| 4283 ((output 4284 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 4285 ((f.ml (1 8) (1 13)) 4286 (unordered light 4287 ((((f.ml (1 10) (1 13)) (paragraph (((f.ml (1 10) (1 13)) (word bar))))))))))) 4288 (warnings 4289 ( "File \"f.ml\", line 1, characters 8-9:\ 4290 \n'-' (bulleted list item) should begin on its own line."))) |}] 4291 end in 4292 () 4293 4294let%expect_test _ = 4295 let module Explicit_list = struct 4296 let basic = 4297 test "{ul {li foo}}"; 4298 [%expect 4299 {| 4300 ((output 4301 (((f.ml (1 0) (1 13)) 4302 (unordered heavy 4303 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))))))) 4304 (warnings ())) |}] 4305 4306 let ordered = 4307 test "{ol {li foo}}"; 4308 [%expect 4309 {| 4310 ((output 4311 (((f.ml (1 0) (1 13)) 4312 (ordered heavy 4313 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))))))) 4314 (warnings ())) |}] 4315 4316 let two_items = 4317 test "{ul {li foo} {li bar}}"; 4318 [%expect 4319 {| 4320 ((output 4321 (((f.ml (1 0) (1 22)) 4322 (unordered heavy 4323 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo)))))) 4324 (((f.ml (1 17) (1 20)) (paragraph (((f.ml (1 17) (1 20)) (word bar))))))))))) 4325 (warnings ())) |}] 4326 4327 let items_on_separate_lines = 4328 test "{ul {li foo}\n{li bar}}"; 4329 [%expect 4330 {| 4331 ((output 4332 (((f.ml (1 0) (2 9)) 4333 (unordered heavy 4334 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo)))))) 4335 (((f.ml (2 4) (2 7)) (paragraph (((f.ml (2 4) (2 7)) (word bar))))))))))) 4336 (warnings ())) |}] 4337 4338 let blank_line = 4339 test "{ul {li foo}\n\n{li bar}}"; 4340 [%expect 4341 {| 4342 ((output 4343 (((f.ml (1 0) (3 9)) 4344 (unordered heavy 4345 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo)))))) 4346 (((f.ml (3 4) (3 7)) (paragraph (((f.ml (3 4) (3 7)) (word bar))))))))))) 4347 (warnings ())) |}] 4348 4349 let blank_line_in_item = 4350 test "{ul {li foo\n\nbar}}"; 4351 [%expect 4352 {| 4353 ((output 4354 (((f.ml (1 0) (3 5)) 4355 (unordered heavy 4356 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))) 4357 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word bar))))))))))) 4358 (warnings ())) |}] 4359 4360 let junk = 4361 test "{ul foo}"; 4362 [%expect 4363 {| 4364 ((output (((f.ml (1 0) (1 8)) (unordered heavy ())))) 4365 (warnings 4366 ( "File \"f.ml\", line 1, characters 4-7:\ 4367 \n'foo' is not allowed in '{ul ...}' (bulleted list).\ 4368 \nSuggestion: move 'foo' into a list item, '{li ...}' or '{- ...}'." 4369 "File \"f.ml\", line 1, characters 0-3:\ 4370 \n'{ul ...}' (bulleted list) should not be empty."))) |}] 4371 4372 let junk_with_no_whitespace = 4373 test "{ulfoo}"; 4374 [%expect 4375 {| 4376 ((output (((f.ml (1 0) (1 7)) (unordered heavy ())))) 4377 (warnings 4378 ( "File \"f.ml\", line 1, characters 3-6:\ 4379 \n'foo' is not allowed in '{ul ...}' (bulleted list).\ 4380 \nSuggestion: move 'foo' into a list item, '{li ...}' or '{- ...}'." 4381 "File \"f.ml\", line 1, characters 0-3:\ 4382 \n'{ul ...}' (bulleted list) should not be empty."))) |}] 4383 4384 let empty = 4385 test "{ul}"; 4386 [%expect 4387 {| 4388 ((output (((f.ml (1 0) (1 4)) (unordered heavy ())))) 4389 (warnings 4390 ( "File \"f.ml\", line 1, characters 0-3:\ 4391 \n'{ul ...}' (bulleted list) should not be empty."))) |}] 4392 4393 let unterminated_list = 4394 test "{ul"; 4395 [%expect 4396 {| 4397 ((output (((f.ml (1 0) (1 3)) (unordered heavy ())))) 4398 (warnings 4399 ( "File \"f.ml\", line 1, characters 3-3:\ 4400 \nEnd of text is not allowed in '{ul ...}' (bulleted list).\ 4401 \nSuggestion: add '}'." 4402 "File \"f.ml\", line 1, characters 0-3:\ 4403 \n'{ul ...}' (bulleted list) should not be empty."))) |}] 4404 4405 let no_whitespace = 4406 test "{ul{li foo}}"; 4407 [%expect 4408 {| 4409 ((output 4410 (((f.ml (1 0) (1 12)) 4411 (unordered heavy 4412 ((((f.ml (1 7) (1 10)) (paragraph (((f.ml (1 7) (1 10)) (word foo))))))))))) 4413 (warnings ())) |}] 4414 4415 let whitespace_at_end_of_item = 4416 test "{ul {li foo\n\n\n}}"; 4417 [%expect 4418 {| 4419 ((output 4420 (((f.ml (1 0) (4 2)) 4421 (unordered heavy 4422 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))))))) 4423 (warnings ())) |}] 4424 4425 let unterminated_li_syntax = 4426 test "{ul {li foo"; 4427 [%expect 4428 {| 4429 ((output 4430 (((f.ml (1 0) (1 11)) 4431 (unordered heavy 4432 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))))))) 4433 (warnings 4434 ( "File \"f.ml\", line 1, characters 11-11:\ 4435 \nEnd of text is not allowed in '{li ...}' (list item).\ 4436 \nSuggestion: add '}'." 4437 "File \"f.ml\", line 1, characters 11-11:\ 4438 \nEnd of text is not allowed in '{ul ...}' (bulleted list).\ 4439 \nSuggestion: add '}'."))) |}] 4440 4441 let unterminated_left_curly_brace = 4442 test "{ul {- foo"; 4443 [%expect 4444 {| 4445 ((output 4446 (((f.ml (1 0) (1 10)) 4447 (unordered heavy 4448 ((((f.ml (1 7) (1 10)) (paragraph (((f.ml (1 7) (1 10)) (word foo))))))))))) 4449 (warnings 4450 ( "File \"f.ml\", line 1, characters 10-10:\ 4451 \nEnd of text is not allowed in '{- ...}' (list item).\ 4452 \nSuggestion: add '}'." 4453 "File \"f.ml\", line 1, characters 10-10:\ 4454 \nEnd of text is not allowed in '{ul ...}' (bulleted list).\ 4455 \nSuggestion: add '}'."))) |}] 4456 4457 let empty_li_styntax = 4458 test "{ul {li }}"; 4459 [%expect 4460 {| 4461 ((output (((f.ml (1 0) (1 10)) (unordered heavy (()))))) 4462 (warnings 4463 ( "File \"f.ml\", line 1, characters 4-7:\ 4464 \n'{li ...}' (list item) should not be empty."))) |}] 4465 4466 let empty_left_curly_brace = 4467 test "{ul {- }}"; 4468 [%expect 4469 {| 4470 ((output (((f.ml (1 0) (1 9)) (unordered heavy (()))))) 4471 (warnings 4472 ( "File \"f.ml\", line 1, characters 4-6:\ 4473 \n'{- ...}' (list item) should not be empty."))) |}] 4474 4475 let li_syntax_without_whitespace = 4476 test "{ul {lifoo}}"; 4477 [%expect 4478 {| 4479 ((output 4480 (((f.ml (1 0) (1 12)) 4481 (unordered heavy 4482 ((((f.ml (1 7) (1 10)) (paragraph (((f.ml (1 7) (1 10)) (word foo))))))))))) 4483 (warnings 4484 ( "File \"f.ml\", line 1, characters 4-7:\ 4485 \n'{li ...}' should be followed by space, a tab, or a new line."))) |}] 4486 4487 let li_syntax_followed_by_newline = 4488 test "{ul {li\nfoo}}"; 4489 [%expect 4490 {| 4491 ((output 4492 (((f.ml (1 0) (2 5)) 4493 (unordered heavy 4494 ((((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))))))) 4495 (warnings ())) |}] 4496 4497 let li_syntax_followed_by_cr_lf = 4498 test "{ul {li\r\nfoo}}"; 4499 [%expect 4500 {| 4501 ((output 4502 (((f.ml (1 0) (2 5)) 4503 (unordered heavy 4504 ((((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))))))) 4505 (warnings ())) |}] 4506 4507 let li_syntax_followed_by_blank_line = 4508 test "{ul {li\n\nfoo}}"; 4509 [%expect 4510 {| 4511 ((output 4512 (((f.ml (1 0) (3 5)) 4513 (unordered heavy 4514 ((((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word foo))))))))))) 4515 (warnings ())) |}] 4516 4517 let left_curly_brace_without_whitespace = 4518 test "{ul {-foo}}"; 4519 [%expect 4520 {| 4521 ((output 4522 (((f.ml (1 0) (1 11)) 4523 (unordered heavy 4524 ((((f.ml (1 6) (1 9)) (paragraph (((f.ml (1 6) (1 9)) (word foo))))))))))) 4525 (warnings ())) |}] 4526 4527 let mixed_list_items = 4528 test "{ul {li foo} {- bar}}"; 4529 [%expect 4530 {| 4531 ((output 4532 (((f.ml (1 0) (1 21)) 4533 (unordered heavy 4534 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo)))))) 4535 (((f.ml (1 16) (1 19)) (paragraph (((f.ml (1 16) (1 19)) (word bar))))))))))) 4536 (warnings ())) |}] 4537 4538 let nested = 4539 test "{ul {li {ul {li foo}}}}"; 4540 [%expect 4541 {| 4542 ((output 4543 (((f.ml (1 0) (1 23)) 4544 (unordered heavy 4545 ((((f.ml (1 8) (1 21)) 4546 (unordered heavy 4547 ((((f.ml (1 16) (1 19)) 4548 (paragraph (((f.ml (1 16) (1 19)) (word foo))))))))))))))) 4549 (warnings ())) |}] 4550 4551 let shorthand_in_explicit = 4552 test "{ul {li - foo\n- bar}}"; 4553 [%expect 4554 {| 4555 ((output 4556 (((f.ml (1 0) (2 7)) 4557 (unordered heavy 4558 ((((f.ml (1 8) (2 5)) 4559 (unordered light 4560 ((((f.ml (1 10) (1 13)) 4561 (paragraph (((f.ml (1 10) (1 13)) (word foo)))))) 4562 (((f.ml (2 2) (2 5)) (paragraph (((f.ml (2 2) (2 5)) (word bar))))))))))))))) 4563 (warnings ())) |}] 4564 4565 let explicit_in_shorthand = 4566 test "- {ul {li foo}}"; 4567 [%expect 4568 {| 4569 ((output 4570 (((f.ml (1 0) (1 15)) 4571 (unordered light 4572 ((((f.ml (1 2) (1 15)) 4573 (unordered heavy 4574 ((((f.ml (1 10) (1 13)) 4575 (paragraph (((f.ml (1 10) (1 13)) (word foo))))))))))))))) 4576 (warnings ())) |}] 4577 4578 let bare_li_syntax = 4579 test "{li foo}"; 4580 [%expect 4581 {| 4582 ((output 4583 (((f.ml (1 4) (1 7)) (paragraph (((f.ml (1 4) (1 7)) (word foo))))) 4584 ((f.ml (1 7) (1 8)) (paragraph (((f.ml (1 7) (1 8)) (word }))))))) 4585 (warnings 4586 ( "File \"f.ml\", line 1, characters 0-3:\ 4587 \n'{li ...}' (list item) is not allowed in top-level text.\ 4588 \nSuggestion: move '{li ...}' into '{ul ...}' (bulleted list), or use '-' (bulleted list item)." 4589 "File \"f.ml\", line 1, characters 7-8:\ 4590 \nUnpaired '}' (end of markup).\ 4591 \nSuggestion: try '\\}'."))) |}] 4592 4593 let bare_left_curly_brace = 4594 test "{- foo"; 4595 [%expect 4596 {| 4597 ((output 4598 (((f.ml (1 3) (1 6)) (paragraph (((f.ml (1 3) (1 6)) (word foo))))))) 4599 (warnings 4600 ( "File \"f.ml\", line 1, characters 0-2:\ 4601 \n'{- ...}' (list item) is not allowed in top-level text.\ 4602 \nSuggestion: move '{- ...}' into '{ul ...}' (bulleted list), or use '-' (bulleted list item)."))) |}] 4603 4604 let after_code_block = 4605 test "{[foo]} {ul {li bar}}"; 4606 [%expect 4607 {| 4608 ((output 4609 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 4610 ((f.ml (1 8) (1 21)) 4611 (unordered heavy 4612 ((((f.ml (1 16) (1 19)) (paragraph (((f.ml (1 16) (1 19)) (word bar))))))))))) 4613 (warnings 4614 ( "File \"f.ml\", line 1, characters 8-11:\ 4615 \n'{ul ...}' (bulleted list) should begin on its own line."))) |}] 4616 end in 4617 () 4618 4619let%expect_test _ = 4620 let module Deprecated = struct 4621 let basic = 4622 test "@deprecated"; 4623 [%expect 4624 {| ((output (((f.ml (1 0) (1 11)) (@deprecated)))) (warnings ())) |}] 4625 4626 let words = 4627 test "@deprecated foo bar"; 4628 [%expect 4629 {| 4630 ((output 4631 (((f.ml (1 0) (1 19)) 4632 (@deprecated 4633 ((f.ml (1 12) (1 19)) 4634 (paragraph 4635 (((f.ml (1 12) (1 15)) (word foo)) ((f.ml (1 15) (1 16)) space) 4636 ((f.ml (1 16) (1 19)) (word bar))))))))) 4637 (warnings ())) |}] 4638 4639 let multiline = 4640 test "@deprecated foo\nbar"; 4641 [%expect 4642 {| 4643 ((output 4644 (((f.ml (1 0) (2 3)) 4645 (@deprecated 4646 ((f.ml (1 12) (2 3)) 4647 (paragraph 4648 (((f.ml (1 12) (1 15)) (word foo)) ((f.ml (1 15) (2 0)) space) 4649 ((f.ml (2 0) (2 3)) (word bar))))))))) 4650 (warnings ())) |}] 4651 4652 let paragraphs = 4653 test "@deprecated foo\n\nbar"; 4654 [%expect 4655 {| 4656 ((output 4657 (((f.ml (1 0) (1 15)) 4658 (@deprecated 4659 ((f.ml (1 12) (1 15)) (paragraph (((f.ml (1 12) (1 15)) (word foo))))))) 4660 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word bar))))))) 4661 (warnings ())) |}] 4662 4663 let whitespace_only = 4664 test "@deprecated"; 4665 [%expect 4666 {| ((output (((f.ml (1 0) (1 11)) (@deprecated)))) (warnings ())) |}] 4667 4668 let immediate_newline = 4669 test "@deprecated\nfoo"; 4670 [%expect 4671 {| 4672 ((output 4673 (((f.ml (1 0) (2 3)) 4674 (@deprecated 4675 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))))) 4676 (warnings ())) |}] 4677 4678 let immediate_cr_lf = 4679 test "@deprecated\r\nfoo"; 4680 [%expect 4681 {| 4682 ((output 4683 (((f.ml (1 0) (2 3)) 4684 (@deprecated 4685 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))))) 4686 (warnings ())) |}] 4687 4688 let immediate_blank_line = 4689 test "@deprecated\n\nfoo"; 4690 [%expect 4691 {| 4692 ((output 4693 (((f.ml (1 0) (1 11)) (@deprecated)) 4694 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word foo))))))) 4695 (warnings ())) |}] 4696 4697 let extra_whitespace = 4698 test "@deprecated foo"; 4699 [%expect 4700 {| 4701 ((output 4702 (((f.ml (1 0) (1 16)) 4703 (@deprecated 4704 ((f.ml (1 13) (1 16)) (paragraph (((f.ml (1 13) (1 16)) (word foo))))))))) 4705 (warnings ())) |}] 4706 4707 let followed_by_deprecated = 4708 test "@deprecated foo\n@deprecated bar"; 4709 [%expect 4710 {| 4711 ((output 4712 (((f.ml (1 0) (1 15)) 4713 (@deprecated 4714 ((f.ml (1 12) (1 15)) (paragraph (((f.ml (1 12) (1 15)) (word foo))))))) 4715 ((f.ml (2 0) (2 15)) 4716 (@deprecated 4717 ((f.ml (2 12) (2 15)) (paragraph (((f.ml (2 12) (2 15)) (word bar))))))))) 4718 (warnings ())) |}] 4719 4720 let followed_by_deprecated_cr_lf = 4721 test "@deprecated foo\r\n@deprecated bar"; 4722 [%expect 4723 {| 4724 ((output 4725 (((f.ml (1 0) (1 15)) 4726 (@deprecated 4727 ((f.ml (1 12) (1 15)) (paragraph (((f.ml (1 12) (1 15)) (word foo))))))) 4728 ((f.ml (2 0) (2 15)) 4729 (@deprecated 4730 ((f.ml (2 12) (2 15)) (paragraph (((f.ml (2 12) (2 15)) (word bar))))))))) 4731 (warnings ())) |}] 4732 4733 let nested_in_self = 4734 test "@deprecated foo @deprecated bar"; 4735 [%expect 4736 {| 4737 ((output 4738 (((f.ml (1 0) (1 31)) 4739 (@deprecated 4740 ((f.ml (1 12) (1 16)) 4741 (paragraph 4742 (((f.ml (1 12) (1 15)) (word foo)) ((f.ml (1 15) (1 16)) space)))) 4743 ((f.ml (1 16) (1 27)) 4744 (paragraph (((f.ml (1 16) (1 27)) (word @deprecated))))) 4745 ((f.ml (1 28) (1 31)) (paragraph (((f.ml (1 28) (1 31)) (word bar))))))))) 4746 (warnings 4747 ( "File \"f.ml\", line 1, characters 16-27:\ 4748 \n'@deprecated' is not allowed in '@deprecated'.\ 4749 \nSuggestion: move '@deprecated' outside of any other markup."))) |}] 4750 4751 let nested_in_self_at_start = 4752 test "@deprecated @deprecated foo"; 4753 [%expect 4754 {| 4755 ((output 4756 (((f.ml (1 0) (1 27)) 4757 (@deprecated 4758 ((f.ml (1 12) (1 23)) 4759 (paragraph (((f.ml (1 12) (1 23)) (word @deprecated))))) 4760 ((f.ml (1 24) (1 27)) (paragraph (((f.ml (1 24) (1 27)) (word foo))))))))) 4761 (warnings 4762 ( "File \"f.ml\", line 1, characters 12-23:\ 4763 \n'@deprecated' is not allowed in '@deprecated'.\ 4764 \nSuggestion: move '@deprecated' outside of any other markup."))) |}] 4765 4766 let preceded_by_paragraph = 4767 test "foo\n@deprecated"; 4768 [%expect 4769 {| 4770 ((output 4771 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 4772 ((f.ml (2 0) (2 11)) (@deprecated)))) 4773 (warnings ())) |}] 4774 4775 let preceded_by_shorthand_list = 4776 test "- foo\n@deprecated"; 4777 [%expect 4778 {| 4779 ((output 4780 (((f.ml (1 0) (1 5)) 4781 (unordered light 4782 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))) 4783 ((f.ml (2 0) (2 11)) (@deprecated)))) 4784 (warnings ())) |}] 4785 4786 let with_shorthand_list = 4787 test "@deprecated - foo"; 4788 [%expect 4789 {| 4790 ((output 4791 (((f.ml (1 0) (1 17)) 4792 (@deprecated 4793 ((f.ml (1 12) (1 17)) 4794 (unordered light 4795 ((((f.ml (1 14) (1 17)) 4796 (paragraph (((f.ml (1 14) (1 17)) (word foo))))))))))))) 4797 (warnings ())) |}] 4798 4799 let with_shorthand_list_double_item = 4800 test "@deprecated - foo\n- bar"; 4801 [%expect 4802 {| 4803 ((output 4804 (((f.ml (1 0) (2 5)) 4805 (@deprecated 4806 ((f.ml (1 12) (2 5)) 4807 (unordered light 4808 ((((f.ml (1 14) (1 17)) 4809 (paragraph (((f.ml (1 14) (1 17)) (word foo)))))) 4810 (((f.ml (2 2) (2 5)) (paragraph (((f.ml (2 2) (2 5)) (word bar))))))))))))) 4811 (warnings ())) |}] 4812 4813 let double_implicitly_ended = 4814 test "@deprecated - foo\n- bar\n\nNew paragraph"; 4815 [%expect 4816 {| 4817 ((output 4818 (((f.ml (1 0) (2 5)) 4819 (@deprecated 4820 ((f.ml (1 12) (2 5)) 4821 (unordered light 4822 ((((f.ml (1 14) (1 17)) 4823 (paragraph (((f.ml (1 14) (1 17)) (word foo)))))) 4824 (((f.ml (2 2) (2 5)) (paragraph (((f.ml (2 2) (2 5)) (word bar))))))))))) 4825 ((f.ml (4 0) (4 13)) 4826 (paragraph 4827 (((f.ml (4 0) (4 3)) (word New)) ((f.ml (4 3) (4 4)) space) 4828 ((f.ml (4 4) (4 13)) (word paragraph))))))) 4829 (warnings ())) |}] 4830 4831 let with_shorthand_list_after_newline = 4832 test "@deprecated\n- foo"; 4833 [%expect 4834 {| 4835 ((output 4836 (((f.ml (1 0) (2 5)) 4837 (@deprecated 4838 ((f.ml (2 0) (2 5)) 4839 (unordered light 4840 ((((f.ml (2 2) (2 5)) (paragraph (((f.ml (2 2) (2 5)) (word foo))))))))))))) 4841 (warnings ())) |}] 4842 4843 let prefix = 4844 test "@deprecatedfoo"; 4845 [%expect 4846 {| ((output (((f.ml (1 0) (1 14)) (@custom deprecatedfoo)))) (warnings ())) |}] 4847 4848 let after_code_block = 4849 test "{[foo]} @deprecated"; 4850 [%expect 4851 {| 4852 ((output 4853 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 4854 ((f.ml (1 8) (1 19)) (@deprecated)))) 4855 (warnings 4856 ( "File \"f.ml\", line 1, characters 8-19:\ 4857 \n'@deprecated' should begin on its own line."))) |}] 4858 4859 let followed_by_section = 4860 test "@deprecated foo\n{2 Bar}"; 4861 [%expect 4862 {| 4863 ((output 4864 (((f.ml (1 0) (1 15)) 4865 (@deprecated 4866 ((f.ml (1 12) (1 15)) (paragraph (((f.ml (1 12) (1 15)) (word foo))))))) 4867 ((f.ml (2 0) (2 7)) (2 (label ()) (((f.ml (2 3) (2 6)) (word Bar))))))) 4868 (warnings ())) |}] 4869 end in 4870 () 4871 4872let%expect_test _ = 4873 let module Param = struct 4874 let basic = 4875 test "@param foo"; 4876 [%expect 4877 {| ((output (((f.ml (1 0) (1 10)) (@param foo)))) (warnings ())) |}] 4878 4879 let bare = 4880 test "@param"; 4881 [%expect 4882 {| 4883 ((output (((f.ml (1 0) (1 6)) (@param "")))) 4884 (warnings 4885 ( "File \"f.ml\", line 1, characters 0-6:\ 4886 \n'@param' expects parameter name on the same line."))) |}] 4887 4888 let bare_with_whitespace = 4889 test "@param"; 4890 [%expect 4891 {| 4892 ((output (((f.ml (1 0) (1 6)) (@param "")))) 4893 (warnings 4894 ( "File \"f.ml\", line 1, characters 0-6:\ 4895 \n'@param' expects parameter name on the same line."))) |}] 4896 4897 let immediate_newline = 4898 test "@param\nfoo"; 4899 [%expect 4900 {| 4901 ((output 4902 (((f.ml (1 0) (2 3)) 4903 (@param "" 4904 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))))) 4905 (warnings 4906 ( "File \"f.ml\", line 1, characters 0-6:\ 4907 \n'@param' expects parameter name on the same line."))) |}] 4908 4909 let followed_by_whitespace = 4910 test "@param foo"; 4911 [%expect 4912 {| ((output (((f.ml (1 0) (1 10)) (@param foo)))) (warnings ())) |}] 4913 4914 let extra_whitespace = 4915 test "@param foo"; 4916 [%expect 4917 {| ((output (((f.ml (1 0) (1 11)) (@param foo)))) (warnings ())) |}] 4918 4919 let words = 4920 test "@param foo bar baz"; 4921 [%expect 4922 {| 4923 ((output 4924 (((f.ml (1 0) (1 18)) 4925 (@param foo 4926 ((f.ml (1 11) (1 18)) 4927 (paragraph 4928 (((f.ml (1 11) (1 14)) (word bar)) ((f.ml (1 14) (1 15)) space) 4929 ((f.ml (1 15) (1 18)) (word baz))))))))) 4930 (warnings ())) |}] 4931 4932 let multiline = 4933 test "@param foo\nbar\nbaz"; 4934 [%expect 4935 {| 4936 ((output 4937 (((f.ml (1 0) (3 3)) 4938 (@param foo 4939 ((f.ml (2 0) (3 3)) 4940 (paragraph 4941 (((f.ml (2 0) (2 3)) (word bar)) ((f.ml (2 3) (3 0)) space) 4942 ((f.ml (3 0) (3 3)) (word baz))))))))) 4943 (warnings ())) |}] 4944 4945 let paragraphs = 4946 test "@param foo bar\n\nbaz"; 4947 [%expect 4948 {| 4949 ((output 4950 (((f.ml (1 0) (1 14)) 4951 (@param foo 4952 ((f.ml (1 11) (1 14)) (paragraph (((f.ml (1 11) (1 14)) (word bar))))))) 4953 ((f.ml (3 0) (3 3)) (paragraph (((f.ml (3 0) (3 3)) (word baz))))))) 4954 (warnings ())) |}] 4955 4956 let two = 4957 test "@param foo\n@param bar"; 4958 [%expect 4959 {| 4960 ((output 4961 (((f.ml (1 0) (1 10)) (@param foo)) ((f.ml (2 0) (2 10)) (@param bar)))) 4962 (warnings ())) |}] 4963 4964 let nested = 4965 test "@param foo @param bar"; 4966 [%expect 4967 {| 4968 ((output 4969 (((f.ml (1 0) (1 21)) 4970 (@param foo 4971 ((f.ml (1 11) (1 21)) 4972 (paragraph 4973 (((f.ml (1 11) (1 21)) (word @param)) ((f.ml (1 11) (1 21)) space) 4974 ((f.ml (1 11) (1 21)) (word bar))))))))) 4975 (warnings 4976 ( "File \"f.ml\", line 1, characters 11-21:\ 4977 \n'@param' is not allowed in '@param'.\ 4978 \nSuggestion: move '@param' outside of any other markup."))) |}] 4979 4980 let preceded_by_paragraph = 4981 test "foo\n@param bar"; 4982 [%expect 4983 {| 4984 ((output 4985 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 4986 ((f.ml (2 0) (2 10)) (@param bar)))) 4987 (warnings ())) |}] 4988 4989 let prefix = 4990 test "@paramfoo"; 4991 [%expect 4992 {| ((output (((f.ml (1 0) (1 9)) (@custom paramfoo)))) (warnings ())) |}] 4993 4994 let after_code_block = 4995 test "{[foo]} @param foo"; 4996 [%expect 4997 {| 4998 ((output 4999 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 5000 ((f.ml (1 8) (1 18)) (@param foo)))) 5001 (warnings 5002 ( "File \"f.ml\", line 1, characters 8-18:\ 5003 \n'@param' should begin on its own line."))) |}] 5004 end in 5005 () 5006 5007let%expect_test _ = 5008 let module Raise = struct 5009 let basic = 5010 test "@raise Foo"; 5011 [%expect 5012 {| ((output (((f.ml (1 0) (1 10)) (@raise Foo)))) (warnings ())) |}] 5013 5014 let bare = 5015 test "@raise"; 5016 [%expect 5017 {| 5018 ((output (((f.ml (1 0) (1 6)) (@raise "")))) 5019 (warnings 5020 ( "File \"f.ml\", line 1, characters 0-6:\ 5021 \n'@raise' expects exception constructor on the same line."))) |}] 5022 5023 let words = 5024 test "@raise foo bar baz"; 5025 [%expect 5026 {| 5027 ((output 5028 (((f.ml (1 0) (1 18)) 5029 (@raise foo 5030 ((f.ml (1 11) (1 18)) 5031 (paragraph 5032 (((f.ml (1 11) (1 14)) (word bar)) ((f.ml (1 14) (1 15)) space) 5033 ((f.ml (1 15) (1 18)) (word baz))))))))) 5034 (warnings ())) |}] 5035 5036 let prefix = 5037 test "@raisefoo"; 5038 [%expect 5039 {| ((output (((f.ml (1 0) (1 9)) (@custom raisefoo)))) (warnings ())) |}] 5040 end in 5041 () 5042 5043let%expect_test _ = 5044 let module Return = struct 5045 let basic = 5046 test "@return"; 5047 [%expect {| ((output (((f.ml (1 0) (1 7)) (@return)))) (warnings ())) |}] 5048 5049 let words = 5050 test "@return foo bar"; 5051 [%expect 5052 {| 5053 ((output 5054 (((f.ml (1 0) (1 15)) 5055 (@return 5056 ((f.ml (1 8) (1 15)) 5057 (paragraph 5058 (((f.ml (1 8) (1 11)) (word foo)) ((f.ml (1 11) (1 12)) space) 5059 ((f.ml (1 12) (1 15)) (word bar))))))))) 5060 (warnings ())) |}] 5061 5062 let prefix = 5063 test "@returnfoo"; 5064 [%expect 5065 {| ((output (((f.ml (1 0) (1 10)) (@custom returnfoo)))) (warnings ())) |}] 5066 end in 5067 () 5068 5069let%expect_test _ = 5070 let module See = struct 5071 let url = 5072 test "@see <foo>"; 5073 [%expect 5074 {| ((output (((f.ml (1 0) (1 10)) (@see url foo)))) (warnings ())) |}] 5075 5076 let file = 5077 test "@see 'foo'"; 5078 [%expect 5079 {| ((output (((f.ml (1 0) (1 10)) (@see file foo)))) (warnings ())) |}] 5080 5081 let document = 5082 test "@see \"foo\""; 5083 [%expect 5084 {| ((output (((f.ml (1 0) (1 10)) (@see document foo)))) (warnings ())) |}] 5085 5086 let bare = 5087 test "@see"; 5088 [%expect 5089 {| 5090 ((output 5091 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (word @see))))))) 5092 (warnings 5093 ( "File \"f.ml\", line 1, characters 0-4:\ 5094 \n'@see' should be followed by <url>, 'file', or \"document title\"."))) |}] 5095 5096 let unterminated_url = 5097 test "@see <foo"; 5098 [%expect 5099 {| 5100 ((output 5101 (((f.ml (1 0) (1 9)) 5102 (paragraph 5103 (((f.ml (1 0) (1 4)) (word @see)) ((f.ml (1 4) (1 5)) space) 5104 ((f.ml (1 5) (1 9)) (word <foo))))))) 5105 (warnings 5106 ( "File \"f.ml\", line 1, characters 0-4:\ 5107 \n'@see' should be followed by <url>, 'file', or \"document title\"."))) |}] 5108 5109 let unterminated_file = 5110 test "@see 'foo"; 5111 [%expect 5112 {| 5113 ((output 5114 (((f.ml (1 0) (1 9)) 5115 (paragraph 5116 (((f.ml (1 0) (1 4)) (word @see)) ((f.ml (1 4) (1 5)) space) 5117 ((f.ml (1 5) (1 9)) (word 'foo))))))) 5118 (warnings 5119 ( "File \"f.ml\", line 1, characters 0-4:\ 5120 \n'@see' should be followed by <url>, 'file', or \"document title\"."))) |}] 5121 5122 let unterminated_document = 5123 test "@see foo"; 5124 [%expect 5125 {| 5126 ((output 5127 (((f.ml (1 0) (1 8)) 5128 (paragraph 5129 (((f.ml (1 0) (1 4)) (word @see)) ((f.ml (1 4) (1 5)) space) 5130 ((f.ml (1 5) (1 8)) (word foo))))))) 5131 (warnings 5132 ( "File \"f.ml\", line 1, characters 0-4:\ 5133 \n'@see' should be followed by <url>, 'file', or \"document title\"."))) |}] 5134 5135 let no_space = 5136 test "@see<foo>"; 5137 [%expect 5138 {| ((output (((f.ml (1 0) (1 9)) (@see url foo)))) (warnings ())) |}] 5139 5140 let words = 5141 test "@see <foo> bar"; 5142 [%expect 5143 {| 5144 ((output 5145 (((f.ml (1 0) (1 14)) 5146 (@see url foo 5147 ((f.ml (1 11) (1 14)) (paragraph (((f.ml (1 11) (1 14)) (word bar))))))))) 5148 (warnings ())) |}] 5149 5150 let prefix = 5151 test "@seefoo"; 5152 [%expect 5153 {| ((output (((f.ml (1 0) (1 7)) (@custom seefoo)))) (warnings ())) |}] 5154 5155 let after_code_block = 5156 test "{[foo]} @see <foo>"; 5157 [%expect 5158 {| 5159 ((output 5160 (((f.ml (1 0) (1 7)) (code_block ((f.ml (1 2) (1 5)) foo))) 5161 ((f.ml (1 8) (1 18)) (@see url foo)))) 5162 (warnings 5163 ( "File \"f.ml\", line 1, characters 8-18:\ 5164 \n'@see' should begin on its own line."))) |}] 5165 5166 let url_attempted_nested_closer = 5167 test "@see <foo>bar>"; 5168 [%expect 5169 {| 5170 ((output 5171 (((f.ml (1 0) (1 14)) 5172 (@see url foo 5173 ((f.ml (1 10) (1 14)) (paragraph (((f.ml (1 10) (1 14)) (word bar>))))))))) 5174 (warnings ())) |}] 5175 5176 let file_attempted_nested_closer = 5177 test "@see 'foo'bar'"; 5178 [%expect 5179 {| 5180 ((output 5181 (((f.ml (1 0) (1 14)) 5182 (@see file foo 5183 ((f.ml (1 10) (1 14)) (paragraph (((f.ml (1 10) (1 14)) (word bar'))))))))) 5184 (warnings ())) |}] 5185 5186 let document_attempted_nested_closer = 5187 test "@see \"foo\"bar\""; 5188 [%expect 5189 {| 5190 ((output 5191 (((f.ml (1 0) (1 14)) 5192 (@see document foo 5193 ((f.ml (1 10) (1 14)) 5194 (paragraph (((f.ml (1 10) (1 14)) (word "bar\""))))))))) 5195 (warnings ())) |}] 5196 end in 5197 () 5198 5199let%expect_test _ = 5200 let module Since = struct 5201 let basic = 5202 test "@since foo"; 5203 [%expect 5204 {| ((output (((f.ml (1 0) (1 10)) (@since foo)))) (warnings ())) |}] 5205 5206 let bare = 5207 test "@since"; 5208 [%expect 5209 {| 5210 ((output (((f.ml (1 0) (1 6)) (@since "")))) 5211 (warnings 5212 ( "File \"f.ml\", line 1, characters 0-6:\ 5213 \n'@since' should not be empty."))) |}] 5214 5215 let prefix = 5216 test "@sincefoo"; 5217 [%expect 5218 {| ((output (((f.ml (1 0) (1 9)) (@custom sincefoo)))) (warnings ())) |}] 5219 5220 let with_whitespace = 5221 test "@since foo bar"; 5222 [%expect 5223 {| ((output (((f.ml (1 0) (1 14)) (@since "foo bar")))) (warnings ())) |}] 5224 5225 let leading_whitespace = 5226 test "@since foo"; 5227 [%expect 5228 {| ((output (((f.ml (1 0) (1 11)) (@since foo)))) (warnings ())) |}] 5229 5230 let trailing_whitespace = 5231 test "@since foo"; 5232 [%expect 5233 {| ((output (((f.ml (1 0) (1 10)) (@since foo)))) (warnings ())) |}] 5234 5235 let whitespace_only = 5236 test "@since"; 5237 [%expect 5238 {| 5239 ((output (((f.ml (1 0) (1 6)) (@since "")))) 5240 (warnings 5241 ( "File \"f.ml\", line 1, characters 0-6:\ 5242 \n'@since' should not be empty."))) |}] 5243 end in 5244 () 5245 5246let%expect_test _ = 5247 let module Before = struct 5248 let basic = 5249 test "@before Foo"; 5250 [%expect 5251 {| ((output (((f.ml (1 0) (1 11)) (@before Foo)))) (warnings ())) |}] 5252 5253 let bare = 5254 test "@before"; 5255 [%expect 5256 {| 5257 ((output (((f.ml (1 0) (1 7)) (@before "")))) 5258 (warnings 5259 ( "File \"f.ml\", line 1, characters 0-7:\ 5260 \n'@before' expects version number on the same line."))) |}] 5261 5262 let words = 5263 test "@before foo bar baz"; 5264 [%expect 5265 {| 5266 ((output 5267 (((f.ml (1 0) (1 19)) 5268 (@before foo 5269 ((f.ml (1 12) (1 19)) 5270 (paragraph 5271 (((f.ml (1 12) (1 15)) (word bar)) ((f.ml (1 15) (1 16)) space) 5272 ((f.ml (1 16) (1 19)) (word baz))))))))) 5273 (warnings ())) |}] 5274 5275 let prefix = 5276 test "@beforefoo"; 5277 [%expect 5278 {| ((output (((f.ml (1 0) (1 10)) (@custom beforefoo)))) (warnings ())) |}] 5279 end in 5280 () 5281 5282let%expect_test _ = 5283 let module Version = struct 5284 let basic = 5285 test "@version foo"; 5286 [%expect 5287 {| ((output (((f.ml (1 0) (1 12)) (@version foo)))) (warnings ())) |}] 5288 5289 let bare = 5290 test "@version"; 5291 [%expect 5292 {| 5293 ((output (((f.ml (1 0) (1 8)) (@version "")))) 5294 (warnings 5295 ( "File \"f.ml\", line 1, characters 0-8:\ 5296 \n'@version' should not be empty."))) |}] 5297 5298 let prefix = 5299 test "@versionfoo"; 5300 [%expect 5301 {| ((output (((f.ml (1 0) (1 11)) (@custom versionfoo)))) (warnings ())) |}] 5302 5303 let with_whitespace = 5304 test "@version foo bar"; 5305 [%expect 5306 {| ((output (((f.ml (1 0) (1 16)) (@version "foo bar")))) (warnings ())) |}] 5307 5308 let leading_whitespace = 5309 test "@version foo"; 5310 [%expect 5311 {| ((output (((f.ml (1 0) (1 13)) (@version foo)))) (warnings ())) |}] 5312 5313 let trailing_whitespace = 5314 test "@version foo"; 5315 [%expect 5316 {| ((output (((f.ml (1 0) (1 12)) (@version foo)))) (warnings ())) |}] 5317 5318 let whitespace_only = 5319 test "@version"; 5320 [%expect 5321 {| 5322 ((output (((f.ml (1 0) (1 8)) (@version "")))) 5323 (warnings 5324 ( "File \"f.ml\", line 1, characters 0-8:\ 5325 \n'@version' should not be empty."))) |}] 5326 end in 5327 () 5328 5329let%expect_test _ = 5330 let module Canonical = struct 5331 let basic = 5332 test "@canonical Foo"; 5333 [%expect 5334 {| 5335 ((output (((f.ml (1 0) (1 14)) (@canonical ((f.ml (1 11) (1 14)) Foo))))) 5336 (warnings ())) |}] 5337 5338 let empty = 5339 test "@canonical"; 5340 [%expect 5341 {| 5342 ((output (((f.ml (1 0) (1 10)) (@canonical ((f.ml (1 11) (1 10)) ""))))) 5343 (warnings 5344 ( "File \"f.ml\", line 1, characters 0-10:\ 5345 \n'@canonical' should not be empty."))) |}] 5346 5347 let whitespace_only = 5348 test "@canonical"; 5349 [%expect 5350 {| 5351 ((output (((f.ml (1 0) (1 10)) (@canonical ((f.ml (1 11) (1 10)) ""))))) 5352 (warnings 5353 ( "File \"f.ml\", line 1, characters 0-10:\ 5354 \n'@canonical' should not be empty."))) |}] 5355 5356 let extra_whitespace = 5357 test "@canonical Foo"; 5358 [%expect 5359 {| 5360 ((output (((f.ml (1 0) (1 15)) (@canonical ((f.ml (1 11) (1 15)) Foo))))) 5361 (warnings ())) |}] 5362 5363 let prefix = 5364 test "@canonicalfoo"; 5365 [%expect 5366 {| ((output (((f.ml (1 0) (1 13)) (@custom canonicalfoo)))) (warnings ())) |}] 5367 5368 (* TODO This should probably be an error of some kind, as Foo Bar is not a 5369 valid module path. *) 5370 let with_whitespace = 5371 test "@canonical Foo Bar"; 5372 [%expect 5373 {| 5374 ((output 5375 (((f.ml (1 0) (1 18)) (@canonical ((f.ml (1 11) (1 18)) "Foo Bar"))))) 5376 (warnings ())) |}] 5377 end in 5378 () 5379 5380let%expect_test _ = 5381 let module Inline = struct 5382 let basic = 5383 test "@inline"; 5384 [%expect {| ((output (((f.ml (1 0) (1 7)) @inline))) (warnings ())) |}] 5385 5386 let prefix = 5387 test "@inlinefoo"; 5388 [%expect 5389 {| ((output (((f.ml (1 0) (1 10)) (@custom inlinefoo)))) (warnings ())) |}] 5390 5391 let extra_whitespace = 5392 test "@inline"; 5393 [%expect {| ((output (((f.ml (1 0) (1 7)) @inline))) (warnings ())) |}] 5394 5395 let followed_by_junk = 5396 test "@inline foo"; 5397 [%expect 5398 {| 5399 ((output 5400 (((f.ml (1 0) (1 7)) @inline) 5401 ((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))) 5402 (warnings 5403 ( "File \"f.ml\", line 1, characters 8-11:\ 5404 \nParagraph should begin on its own line."))) |}] 5405 5406 let followed_by_paragraph = 5407 test "@inline\nfoo"; 5408 [%expect 5409 {| 5410 ((output 5411 (((f.ml (1 0) (1 7)) @inline) 5412 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))) 5413 (warnings ())) |}] 5414 5415 let followed_by_tag = 5416 test "@inline\n@deprecated"; 5417 [%expect 5418 {| 5419 ((output (((f.ml (1 0) (1 7)) @inline) ((f.ml (2 0) (2 11)) (@deprecated)))) 5420 (warnings ())) |}] 5421 5422 let with_list = 5423 test "@inline - foo"; 5424 [%expect 5425 {| 5426 ((output 5427 (((f.ml (1 0) (1 7)) @inline) 5428 ((f.ml (1 8) (1 13)) 5429 (unordered light 5430 ((((f.ml (1 10) (1 13)) (paragraph (((f.ml (1 10) (1 13)) (word foo))))))))))) 5431 (warnings 5432 ( "File \"f.ml\", line 1, characters 8-9:\ 5433 \n'-' (bulleted list item) should begin on its own line."))) |}] 5434 end in 5435 () 5436 5437let%expect_test _ = 5438 let module Open = struct 5439 let basic = 5440 test "@open"; 5441 [%expect {| ((output (((f.ml (1 0) (1 5)) @open))) (warnings ())) |}] 5442 5443 let prefix = 5444 test "@openfoo"; 5445 [%expect 5446 {| ((output (((f.ml (1 0) (1 8)) (@custom openfoo)))) (warnings ())) |}] 5447 5448 let extra_whitespace = 5449 test "@open"; 5450 [%expect {| ((output (((f.ml (1 0) (1 5)) @open))) (warnings ())) |}] 5451 5452 let followed_by_junk = 5453 test "@open foo"; 5454 [%expect 5455 {| 5456 ((output 5457 (((f.ml (1 0) (1 5)) @open) 5458 ((f.ml (1 6) (1 9)) (paragraph (((f.ml (1 6) (1 9)) (word foo))))))) 5459 (warnings 5460 ( "File \"f.ml\", line 1, characters 6-9:\ 5461 \nParagraph should begin on its own line."))) |}] 5462 5463 let followed_by_paragraph = 5464 test "@open\nfoo"; 5465 [%expect 5466 {| 5467 ((output 5468 (((f.ml (1 0) (1 5)) @open) 5469 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))) 5470 (warnings ())) |}] 5471 5472 let followed_by_tag = 5473 test "@open\n@deprecated"; 5474 [%expect 5475 {| 5476 ((output (((f.ml (1 0) (1 5)) @open) ((f.ml (2 0) (2 11)) (@deprecated)))) 5477 (warnings ())) |}] 5478 5479 let with_list = 5480 test "@open - foo"; 5481 [%expect 5482 {| 5483 ((output 5484 (((f.ml (1 0) (1 5)) @open) 5485 ((f.ml (1 6) (1 11)) 5486 (unordered light 5487 ((((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))))))) 5488 (warnings 5489 ( "File \"f.ml\", line 1, characters 6-7:\ 5490 \n'-' (bulleted list item) should begin on its own line."))) |}] 5491 end in 5492 () 5493 5494let%expect_test _ = 5495 let module Closed = struct 5496 let basic = 5497 test "@closed"; 5498 [%expect {| ((output (((f.ml (1 0) (1 7)) @closed))) (warnings ())) |}] 5499 5500 let prefix = 5501 test "@closedfoo"; 5502 [%expect 5503 {| ((output (((f.ml (1 0) (1 10)) (@custom closedfoo)))) (warnings ())) |}] 5504 5505 let extra_whitespace = 5506 test "@closed"; 5507 [%expect {| ((output (((f.ml (1 0) (1 7)) @closed))) (warnings ())) |}] 5508 5509 let followed_by_junk = 5510 test "@closed foo"; 5511 [%expect 5512 {| 5513 ((output 5514 (((f.ml (1 0) (1 7)) @closed) 5515 ((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))) 5516 (warnings 5517 ( "File \"f.ml\", line 1, characters 8-11:\ 5518 \nParagraph should begin on its own line."))) |}] 5519 5520 let followed_by_paragraph = 5521 test "@closed\nfoo"; 5522 [%expect 5523 {| 5524 ((output 5525 (((f.ml (1 0) (1 7)) @closed) 5526 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))) 5527 (warnings ())) |}] 5528 5529 let followed_by_tag = 5530 test "@closed\n@deprecated"; 5531 [%expect 5532 {| 5533 ((output (((f.ml (1 0) (1 7)) @closed) ((f.ml (2 0) (2 11)) (@deprecated)))) 5534 (warnings ())) |}] 5535 5536 let with_list = 5537 test "@closed - foo"; 5538 [%expect 5539 {| 5540 ((output 5541 (((f.ml (1 0) (1 7)) @closed) 5542 ((f.ml (1 8) (1 13)) 5543 (unordered light 5544 ((((f.ml (1 10) (1 13)) (paragraph (((f.ml (1 10) (1 13)) (word foo))))))))))) 5545 (warnings 5546 ( "File \"f.ml\", line 1, characters 8-9:\ 5547 \n'-' (bulleted list item) should begin on its own line."))) |}] 5548 end in 5549 () 5550 5551let%expect_test _ = 5552 let module Hidden = struct 5553 let basic = 5554 test "@hidden"; 5555 [%expect {| ((output (((f.ml (1 0) (1 7)) @hidden))) (warnings ())) |}] 5556 5557 let prefix = 5558 test "@hiddenfoo"; 5559 [%expect 5560 {| ((output (((f.ml (1 0) (1 10)) (@custom hiddenfoo)))) (warnings ())) |}] 5561 5562 let extra_whitespace = 5563 test "@hidden"; 5564 [%expect {| ((output (((f.ml (1 0) (1 7)) @hidden))) (warnings ())) |}] 5565 5566 let followed_by_junk = 5567 test "@hidden foo"; 5568 [%expect 5569 {| 5570 ((output 5571 (((f.ml (1 0) (1 7)) @hidden) 5572 ((f.ml (1 8) (1 11)) (paragraph (((f.ml (1 8) (1 11)) (word foo))))))) 5573 (warnings 5574 ( "File \"f.ml\", line 1, characters 8-11:\ 5575 \nParagraph should begin on its own line."))) |}] 5576 5577 let followed_by_paragraph = 5578 test "@hidden\nfoo"; 5579 [%expect 5580 {| 5581 ((output 5582 (((f.ml (1 0) (1 7)) @hidden) 5583 ((f.ml (2 0) (2 3)) (paragraph (((f.ml (2 0) (2 3)) (word foo))))))) 5584 (warnings ())) |}] 5585 5586 let followed_by_tag = 5587 test "@hidden\n@deprecated"; 5588 [%expect 5589 {| 5590 ((output (((f.ml (1 0) (1 7)) @hidden) ((f.ml (2 0) (2 11)) (@deprecated)))) 5591 (warnings ())) |}] 5592 5593 let with_list = 5594 test "@hidden - foo"; 5595 [%expect 5596 {| 5597 ((output 5598 (((f.ml (1 0) (1 7)) @hidden) 5599 ((f.ml (1 8) (1 13)) 5600 (unordered light 5601 ((((f.ml (1 10) (1 13)) (paragraph (((f.ml (1 10) (1 13)) (word foo))))))))))) 5602 (warnings 5603 ( "File \"f.ml\", line 1, characters 8-9:\ 5604 \n'-' (bulleted list item) should begin on its own line."))) |}] 5605 end in 5606 () 5607 5608let%expect_test _ = 5609 let module Bad_markup = struct 5610 let left_brace = 5611 test "{"; 5612 [%expect 5613 {| 5614 ((output (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word {))))))) 5615 (warnings 5616 ( "File \"f.ml\", line 1, characters 0-1:\ 5617 \n'{': bad markup.\ 5618 \nSuggestion: escape the brace with '\\{'."))) |}] 5619 5620 let left_brace_with_letter = 5621 test "{g"; 5622 [%expect 5623 {| 5624 ((output 5625 (((f.ml (1 0) (1 2)) 5626 (paragraph (((f.ml (1 0) (1 1)) (word {)) ((f.ml (1 1) (1 2)) (word g))))))) 5627 (warnings 5628 ( "File \"f.ml\", line 1, characters 0-1:\ 5629 \n'{': bad markup.\ 5630 \nSuggestion: escape the brace with '\\{'."))) |}] 5631 5632 let left_brace_with_letters = 5633 test "{gg"; 5634 [%expect 5635 {| 5636 ((output 5637 (((f.ml (1 0) (1 3)) 5638 (paragraph 5639 (((f.ml (1 0) (1 1)) (word {)) ((f.ml (1 1) (1 3)) (word gg))))))) 5640 (warnings 5641 ( "File \"f.ml\", line 1, characters 0-1:\ 5642 \n'{': bad markup.\ 5643 \nSuggestion: escape the brace with '\\{'."))) |}] 5644 5645 let empty_braces = 5646 test "{}"; 5647 [%expect 5648 {| 5649 ((output 5650 (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word {))))) 5651 ((f.ml (1 1) (1 2)) (paragraph (((f.ml (1 1) (1 2)) (word }))))))) 5652 (warnings 5653 ( "File \"f.ml\", line 1, characters 0-1:\ 5654 \n'{': bad markup.\ 5655 \nSuggestion: escape the brace with '\\{'." 5656 "File \"f.ml\", line 1, characters 1-2:\ 5657 \nUnpaired '}' (end of markup).\ 5658 \nSuggestion: try '\\}'."))) |}] 5659 5660 let left_space = 5661 test "{ foo}"; 5662 [%expect 5663 {| 5664 ((output 5665 (((f.ml (1 0) (1 6)) (paragraph (((f.ml (1 0) (1 6)) (code_span " foo"))))))) 5666 (warnings 5667 ( "File \"f.ml\", line 1, characters 0-6:\ 5668 \n'{ foo}': bad markup.\ 5669 \nSuggestion: did you mean '{! foo}' or '[ foo]'?"))) |}] 5670 5671 let left_spaces = 5672 test "{ foo}"; 5673 [%expect 5674 {| 5675 ((output 5676 (((f.ml (1 0) (1 7)) 5677 (paragraph (((f.ml (1 0) (1 7)) (code_span " foo"))))))) 5678 (warnings 5679 ( "File \"f.ml\", line 1, characters 0-7:\ 5680 \n'{ foo}': bad markup.\ 5681 \nSuggestion: did you mean '{! foo}' or '[ foo]'?"))) |}] 5682 5683 let left_space_eof = 5684 test "{"; 5685 [%expect 5686 {| 5687 ((output (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word {))))))) 5688 (warnings 5689 ( "File \"f.ml\", line 1, characters 0-1:\ 5690 \n'{': bad markup.\ 5691 \nSuggestion: escape the brace with '\\{'."))) |}] 5692 5693 let braces_instead_of_brackets = 5694 test "{foo}"; 5695 [%expect 5696 {| 5697 ((output 5698 (((f.ml (1 0) (1 5)) (paragraph (((f.ml (1 0) (1 5)) (code_span foo))))))) 5699 (warnings 5700 ( "File \"f.ml\", line 1, characters 0-5:\ 5701 \n'{foo}': bad markup.\ 5702 \nSuggestion: did you mean '{!foo}' or '[foo]'?"))) |}] 5703 5704 let right_brace = 5705 test "}"; 5706 [%expect 5707 {| 5708 ((output (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word }))))))) 5709 (warnings 5710 ( "File \"f.ml\", line 1, characters 0-1:\ 5711 \nUnpaired '}' (end of markup).\ 5712 \nSuggestion: try '\\}'."))) |}] 5713 5714 let right_brace_in_paragraph = 5715 test "foo}"; 5716 [%expect 5717 {| 5718 ((output 5719 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 5720 ((f.ml (1 3) (1 4)) (paragraph (((f.ml (1 3) (1 4)) (word }))))))) 5721 (warnings 5722 ( "File \"f.ml\", line 1, characters 3-4:\ 5723 \nUnpaired '}' (end of markup).\ 5724 \nSuggestion: try '\\}'."))) |}] 5725 5726 let multiple_right_brace = 5727 test "foo } bar } baz"; 5728 [%expect 5729 {| 5730 ((output 5731 (((f.ml (1 0) (1 3)) (paragraph (((f.ml (1 0) (1 3)) (word foo))))) 5732 ((f.ml (1 4) (1 5)) (paragraph (((f.ml (1 4) (1 5)) (word }))))) 5733 ((f.ml (1 6) (1 9)) (paragraph (((f.ml (1 6) (1 9)) (word bar))))) 5734 ((f.ml (1 10) (1 11)) (paragraph (((f.ml (1 10) (1 11)) (word }))))) 5735 ((f.ml (1 12) (1 15)) (paragraph (((f.ml (1 12) (1 15)) (word baz))))))) 5736 (warnings 5737 ( "File \"f.ml\", line 1, characters 4-5:\ 5738 \nUnpaired '}' (end of markup).\ 5739 \nSuggestion: try '\\}'." 5740 "File \"f.ml\", line 1, characters 10-11:\ 5741 \nUnpaired '}' (end of markup).\ 5742 \nSuggestion: try '\\}'."))) |}] 5743 5744 let right_brace_in_list_item = 5745 test "- foo}"; 5746 [%expect 5747 {| 5748 ((output 5749 (((f.ml (1 0) (1 5)) 5750 (unordered light 5751 ((((f.ml (1 2) (1 5)) (paragraph (((f.ml (1 2) (1 5)) (word foo))))))))) 5752 ((f.ml (1 5) (1 6)) (paragraph (((f.ml (1 5) (1 6)) (word }))))))) 5753 (warnings 5754 ( "File \"f.ml\", line 1, characters 5-6:\ 5755 \nUnpaired '}' (end of markup).\ 5756 \nSuggestion: try '\\}'."))) |}] 5757 5758 let right_brace_in_code_span = 5759 test "[foo}]"; 5760 [%expect 5761 {| 5762 ((output 5763 (((f.ml (1 0) (1 6)) (paragraph (((f.ml (1 0) (1 6)) (code_span foo}))))))) 5764 (warnings ())) |}] 5765 5766 let right_brace_in_code_block = 5767 test "{[foo}]}"; 5768 [%expect 5769 {| 5770 ((output (((f.ml (1 0) (1 8)) (code_block ((f.ml (1 2) (1 6)) foo}))))) 5771 (warnings ())) |}] 5772 5773 let right_brace_in_verbatim_text = 5774 test "{v foo} v}"; 5775 [%expect 5776 {| ((output (((f.ml (1 0) (1 10)) (verbatim foo})))) (warnings ())) |}] 5777 5778 let right_brace_in_author = 5779 test "@author Foo}"; 5780 [%expect 5781 {| ((output (((f.ml (1 0) (1 12)) (@author Foo})))) (warnings ())) |}] 5782 5783 let right_brace_in_deprecated = 5784 test "@deprecated }"; 5785 [%expect 5786 {| 5787 ((output 5788 (((f.ml (1 0) (1 11)) (@deprecated)) 5789 ((f.ml (1 12) (1 13)) (paragraph (((f.ml (1 12) (1 13)) (word }))))))) 5790 (warnings 5791 ( "File \"f.ml\", line 1, characters 12-13:\ 5792 \nUnpaired '}' (end of markup).\ 5793 \nSuggestion: try '\\}'."))) |}] 5794 5795 let right_bracket = 5796 test "]"; 5797 [%expect 5798 {| 5799 ((output (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word ]))))))) 5800 (warnings 5801 ( "File \"f.ml\", line 1, characters 0-1:\ 5802 \nUnpaired ']' (end of code).\ 5803 \nSuggestion: try '\\]'."))) |}] 5804 5805 let right_bracket_in_paragraph = 5806 test "foo]"; 5807 [%expect 5808 {| 5809 ((output 5810 (((f.ml (1 0) (1 4)) 5811 (paragraph 5812 (((f.ml (1 0) (1 3)) (word foo)) ((f.ml (1 3) (1 4)) (word ]))))))) 5813 (warnings 5814 ( "File \"f.ml\", line 1, characters 3-4:\ 5815 \nUnpaired ']' (end of code).\ 5816 \nSuggestion: try '\\]'."))) |}] 5817 5818 let right_bracket_in_shorthand_list = 5819 test "- foo]"; 5820 [%expect 5821 {| 5822 ((output 5823 (((f.ml (1 0) (1 6)) 5824 (unordered light 5825 ((((f.ml (1 2) (1 6)) 5826 (paragraph 5827 (((f.ml (1 2) (1 5)) (word foo)) ((f.ml (1 5) (1 6)) (word ]))))))))))) 5828 (warnings 5829 ( "File \"f.ml\", line 1, characters 5-6:\ 5830 \nUnpaired ']' (end of code).\ 5831 \nSuggestion: try '\\]'."))) |}] 5832 5833 let right_bracket_in_code_span = 5834 test "[]]"; 5835 [%expect 5836 {| 5837 ((output 5838 (((f.ml (1 0) (1 3)) 5839 (paragraph 5840 (((f.ml (1 0) (1 2)) (code_span "")) ((f.ml (1 2) (1 3)) (word ]))))))) 5841 (warnings 5842 ( "File \"f.ml\", line 1, characters 2-3:\ 5843 \nUnpaired ']' (end of code).\ 5844 \nSuggestion: try '\\]'."))) |}] 5845 5846 let right_bracket_in_style = 5847 test "{b]}"; 5848 [%expect 5849 {| 5850 ((output (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (bold ()))))))) 5851 (warnings 5852 ( "File \"f.ml\", line 1, characters 0-2:\ 5853 \n'{b' should be followed by space, a tab, or a new line." 5854 "File \"f.ml\", line 1, characters 2-4:\ 5855 \n']}' is not allowed in '{b ...}' (boldface text)." 5856 "File \"f.ml\", line 1, characters 0-2:\ 5857 \n'{b ...}' (boldface text) should not be empty."))) |}] 5858 5859 let right_bracket_in_verbatim = 5860 test "{v ] v}"; 5861 [%expect 5862 {| ((output (((f.ml (1 0) (1 7)) (verbatim ])))) (warnings ())) |}] 5863 5864 let right_bracket_in_list = 5865 test "{ul ]}"; 5866 [%expect 5867 {| 5868 ((output (((f.ml (1 0) (1 6)) (unordered heavy ())))) 5869 (warnings 5870 ( "File \"f.ml\", line 1, characters 4-6:\ 5871 \n']}' is not allowed in '{ul ...}' (bulleted list).\ 5872 \nSuggestion: move ']}' into a list item, '{li ...}' or '{- ...}'." 5873 "File \"f.ml\", line 1, characters 6-6:\ 5874 \nEnd of text is not allowed in '{ul ...}' (bulleted list).\ 5875 \nSuggestion: add '}'." 5876 "File \"f.ml\", line 1, characters 0-3:\ 5877 \n'{ul ...}' (bulleted list) should not be empty."))) |}] 5878 5879 let right_bracket_in_list_item = 5880 test "{ul {li ]}}"; 5881 [%expect 5882 {| 5883 ((output (((f.ml (1 0) (1 11)) (unordered heavy (()))))) 5884 (warnings 5885 ( "File \"f.ml\", line 1, characters 4-7:\ 5886 \n'{li ...}' (list item) should not be empty." 5887 "File \"f.ml\", line 1, characters 11-11:\ 5888 \nEnd of text is not allowed in '{ul ...}' (bulleted list).\ 5889 \nSuggestion: add '}'."))) |}] 5890 5891 let right_bracket_in_heading = 5892 test "{2 ]}"; 5893 [%expect 5894 {| 5895 ((output (((f.ml (1 0) (1 2)) (2 (label ()) ())))) 5896 (warnings 5897 ( "File \"f.ml\", line 1, characters 3-5:\ 5898 \n']}' is not allowed in '{2 ...}' (section heading)." 5899 "File \"f.ml\", line 1, characters 0-2:\ 5900 \n'{2 ...}' (section heading) should not be empty."))) |}] 5901 5902 let right_bracket_in_author = 5903 test "@author Foo]"; 5904 [%expect 5905 {| ((output (((f.ml (1 0) (1 12)) (@author Foo])))) (warnings ())) |}] 5906 5907 let at = 5908 test "@"; 5909 [%expect 5910 {| 5911 ((output (((f.ml (1 0) (1 1)) (paragraph (((f.ml (1 0) (1 1)) (word @))))))) 5912 (warnings ( "File \"f.ml\", line 1, characters 0-1:\ 5913 \nStray '@'."))) |}] 5914 5915 let cr = 5916 test ""; 5917 [%expect {| ((output ()) (warnings ())) |}] 5918 end in 5919 () 5920 5921let%expect_test _ = 5922 let module Utf_8 = struct 5923 let lambda = 5924 test "\xce\xbb"; 5925 [%expect 5926 {| 5927 ((output 5928 (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word "\206\187"))))))) 5929 (warnings ())) |}] 5930 5931 let words = 5932 test "\xce\xbb \xce\xbb"; 5933 [%expect 5934 {| 5935 ((output 5936 (((f.ml (1 0) (1 5)) 5937 (paragraph 5938 (((f.ml (1 0) (1 2)) (word "\206\187")) ((f.ml (1 2) (1 3)) space) 5939 ((f.ml (1 3) (1 5)) (word "\206\187"))))))) 5940 (warnings ())) |}] 5941 5942 let no_validation = 5943 test "Î"; 5944 [%expect 5945 {| 5946 ((output 5947 (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word "\195\142"))))))) 5948 (warnings ())) |}] 5949 5950 let escapes = 5951 test "\xce\xbb\\}"; 5952 [%expect 5953 {| 5954 ((output 5955 (((f.ml (1 0) (1 4)) (paragraph (((f.ml (1 0) (1 4)) (word "\206\187}"))))))) 5956 (warnings ())) |}] 5957 5958 let newline = 5959 test "\xce\xbb \n \xce\xbb"; 5960 [%expect 5961 {| 5962 ((output 5963 (((f.ml (1 0) (2 3)) 5964 (paragraph 5965 (((f.ml (1 0) (1 2)) (word "\206\187")) ((f.ml (1 2) (2 1)) space) 5966 ((f.ml (2 1) (2 3)) (word "\206\187"))))))) 5967 (warnings ())) |}] 5968 5969 let paragraphs = 5970 test "\xce\xbb \n\n \xce\xbb"; 5971 [%expect 5972 {| 5973 ((output 5974 (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word "\206\187"))))) 5975 ((f.ml (3 1) (3 3)) (paragraph (((f.ml (3 1) (3 3)) (word "\206\187"))))))) 5976 (warnings ())) |}] 5977 5978 let code_span = 5979 test "[\xce\xbb]"; 5980 [%expect 5981 {| 5982 ((output 5983 (((f.ml (1 0) (1 4)) 5984 (paragraph (((f.ml (1 0) (1 4)) (code_span "\206\187"))))))) 5985 (warnings ())) |}] 5986 5987 let minus = 5988 test "\xce\xbb-\xce\xbb"; 5989 [%expect 5990 {| 5991 ((output 5992 (((f.ml (1 0) (1 5)) 5993 (paragraph (((f.ml (1 0) (1 5)) (word "\206\187-\206\187"))))))) 5994 (warnings ())) |}] 5995 5996 let shorthand_list = 5997 test "- \xce\xbb"; 5998 [%expect 5999 {| 6000 ((output 6001 (((f.ml (1 0) (1 4)) 6002 (unordered light 6003 ((((f.ml (1 2) (1 4)) 6004 (paragraph (((f.ml (1 2) (1 4)) (word "\206\187"))))))))))) 6005 (warnings ())) |}] 6006 6007 let styled = 6008 test "{b \xce\xbb}"; 6009 [%expect 6010 {| 6011 ((output 6012 (((f.ml (1 0) (1 6)) 6013 (paragraph 6014 (((f.ml (1 0) (1 6)) (bold (((f.ml (1 3) (1 5)) (word "\206\187")))))))))) 6015 (warnings ())) |}] 6016 6017 let reference_target = 6018 test "{!\xce\xbb}"; 6019 [%expect 6020 {| 6021 ((output 6022 (((f.ml (1 0) (1 5)) 6023 (paragraph 6024 (((f.ml (1 0) (1 5)) (simple ((f.ml (1 2) (1 5)) "\206\187") ()))))))) 6025 (warnings ())) |}] 6026 6027 let code_block = 6028 test "{[\xce\xbb]}"; 6029 [%expect 6030 {| 6031 ((output (((f.ml (1 0) (1 6)) (code_block ((f.ml (1 2) (1 4)) "\206\187"))))) 6032 (warnings ())) |}] 6033 6034 let verbatim = 6035 test "{v \xce\xbb v}"; 6036 [%expect 6037 {| ((output (((f.ml (1 0) (1 8)) (verbatim "\206\187")))) (warnings ())) |}] 6038 6039 let label = 6040 test "{2:\xce\xbb Bar}"; 6041 [%expect 6042 {| 6043 ((output 6044 (((f.ml (1 0) (1 10)) 6045 (2 (label ("\206\187")) (((f.ml (1 6) (1 9)) (word Bar))))))) 6046 (warnings ())) |}] 6047 6048 let author = 6049 test "@author \xce\xbb"; 6050 [%expect 6051 {| ((output (((f.ml (1 0) (1 10)) (@author "\206\187")))) (warnings ())) |}] 6052 6053 let param = 6054 test "@param \xce\xbb"; 6055 [%expect 6056 {| ((output (((f.ml (1 0) (1 9)) (@param "\206\187")))) (warnings ())) |}] 6057 6058 let raise = 6059 test "@raise \xce\xbb"; 6060 [%expect 6061 {| ((output (((f.ml (1 0) (1 9)) (@raise "\206\187")))) (warnings ())) |}] 6062 6063 let see = 6064 test "@see <\xce\xbb>"; 6065 [%expect 6066 {| ((output (((f.ml (1 0) (1 9)) (@see url "\206\187")))) (warnings ())) |}] 6067 6068 let since = 6069 test "@since \xce\xbb"; 6070 [%expect 6071 {| ((output (((f.ml (1 0) (1 9)) (@since "\206\187")))) (warnings ())) |}] 6072 6073 let before = 6074 test "@before \xce\xbb"; 6075 [%expect 6076 {| ((output (((f.ml (1 0) (1 10)) (@before "\206\187")))) (warnings ())) |}] 6077 6078 let version = 6079 test "@version \xce\xbb"; 6080 [%expect 6081 {| ((output (((f.ml (1 0) (1 11)) (@version "\206\187")))) (warnings ())) |}] 6082 6083 let right_brace = 6084 test "\xce\xbb}"; 6085 [%expect 6086 {| 6087 ((output 6088 (((f.ml (1 0) (1 2)) (paragraph (((f.ml (1 0) (1 2)) (word "\206\187"))))) 6089 ((f.ml (1 2) (1 3)) (paragraph (((f.ml (1 2) (1 3)) (word }))))))) 6090 (warnings 6091 ( "File \"f.ml\", line 1, characters 2-3:\ 6092 \nUnpaired '}' (end of markup).\ 6093 \nSuggestion: try '\\}'."))) |}] 6094 end in 6095 () 6096 6097let%expect_test _ = 6098 let module Comment_location = struct 6099 let error_on_first_line = 6100 test "@foo"; 6101 [%expect 6102 {| ((output (((f.ml (1 0) (1 4)) (@custom foo)))) (warnings ())) |}] 6103 6104 let error_on_second_line = 6105 test " \n @foo"; 6106 [%expect 6107 {| ((output (((f.ml (2 2) (2 6)) (@custom foo)))) (warnings ())) |}] 6108 end in 6109 () 6110 6111let%expect_test _ = 6112 let module Unsupported = struct 6113 (* test "index list" 6114 "{!indexlist}" 6115 (Ok []); *) 6116 6117 let left_alignment = 6118 test "{L foo}"; 6119 [%expect 6120 {| 6121 ((output 6122 (((f.ml (1 0) (1 7)) (paragraph (((f.ml (1 3) (1 6)) (word foo))))))) 6123 (warnings 6124 ( "File \"f.ml\", line 1, characters 0-7:\ 6125 \n'{L ...}' (left alignment) should not be used because it has no effect."))) |}] 6126 6127 let center_alignment = 6128 test "{C foo}"; 6129 [%expect 6130 {| 6131 ((output 6132 (((f.ml (1 0) (1 7)) (paragraph (((f.ml (1 3) (1 6)) (word foo))))))) 6133 (warnings 6134 ( "File \"f.ml\", line 1, characters 0-7:\ 6135 \n'{C ...}' (center alignment) should not be used because it has no effect."))) |}] 6136 6137 let right_alignment = 6138 test "{R foo}"; 6139 [%expect 6140 {| 6141 ((output 6142 (((f.ml (1 0) (1 7)) (paragraph (((f.ml (1 3) (1 6)) (word foo))))))) 6143 (warnings 6144 ( "File \"f.ml\", line 1, characters 0-7:\ 6145 \n'{R ...}' (right alignment) should not be used because it has no effect."))) |}] 6146 6147 let custom_style = 6148 test "{c foo}"; 6149 [%expect 6150 {| 6151 ((output 6152 (((f.ml (1 0) (1 7)) 6153 (paragraph (((f.ml (1 0) (1 7)) (code_span "c foo"))))))) 6154 (warnings 6155 ( "File \"f.ml\", line 1, characters 0-7:\ 6156 \n'{c foo}': bad markup.\ 6157 \nSuggestion: did you mean '{!c foo}' or '[c foo]'?"))) |}] 6158 6159 let custom_tag = 6160 test "@custom"; 6161 [%expect 6162 {| ((output (((f.ml (1 0) (1 7)) (@custom custom)))) (warnings ())) |}] 6163 6164 let custom_tag_with_dot = 6165 test "@foo.bar"; 6166 [%expect 6167 {| ((output (((f.ml (1 0) (1 8)) (@custom foo.bar)))) (warnings ())) |}] 6168 6169 let custom_tag_with_multiple_dots = 6170 test "@callout.box.large"; 6171 [%expect 6172 {| ((output (((f.ml (1 0) (1 18)) (@custom callout.box.large)))) (warnings ())) |}] 6173 6174 let custom_tag_with_underscore = 6175 test "@foo_bar"; 6176 [%expect 6177 {| ((output (((f.ml (1 0) (1 8)) (@custom foo_bar)))) (warnings ())) |}] 6178 6179 let custom_tag_with_number = 6180 test "@rfc2616"; 6181 [%expect 6182 {| ((output (((f.ml (1 0) (1 8)) (@custom rfc2616)))) (warnings ())) |}] 6183 6184 let custom_tag_with_content = 6185 test "@foo.bar This is the content"; 6186 [%expect 6187 {| 6188 ((output 6189 (((f.ml (1 0) (1 28)) 6190 (@custom foo.bar 6191 ((f.ml (1 9) (1 28)) 6192 (paragraph 6193 (((f.ml (1 9) (1 13)) (word This)) ((f.ml (1 13) (1 14)) space) 6194 ((f.ml (1 14) (1 16)) (word is)) ((f.ml (1 16) (1 17)) space) 6195 ((f.ml (1 17) (1 20)) (word the)) ((f.ml (1 20) (1 21)) space) 6196 ((f.ml (1 21) (1 28)) (word content))))))))) 6197 (warnings ())) 6198 |}] 6199 6200 let custom_tag_trailing_dot = 6201 test "@foo. bar"; 6202 [%expect 6203 {| 6204 ((output 6205 (((f.ml (1 0) (1 9)) 6206 (@custom foo. 6207 ((f.ml (1 6) (1 9)) (paragraph (((f.ml (1 6) (1 9)) (word bar))))))))) 6208 (warnings ())) |}] 6209 6210 let custom_reference_kind = 6211 test "{!custom:foo}"; 6212 [%expect 6213 {| 6214 ((output 6215 (((f.ml (1 0) (1 13)) 6216 (paragraph 6217 (((f.ml (1 0) (1 13)) (simple ((f.ml (1 2) (1 13)) custom:foo) ()))))))) 6218 (warnings ())) |}] 6219 6220 let html_tag = 6221 test "<b>foo</b>"; 6222 [%expect 6223 {| 6224 ((output 6225 (((f.ml (1 0) (1 10)) 6226 (paragraph (((f.ml (1 0) (1 10)) (word <b>foo</b>))))))) 6227 (warnings ())) |}] 6228 end in 6229 () 6230 6231let%expect_test _ = 6232 let module Locations = struct 6233 (* test "index list" 6234 "{!indexlist}" 6235 (Ok []); *) 6236 6237 let lexing_pos_to_sexp : Lexing.position -> sexp = 6238 fun v -> 6239 List 6240 [ 6241 List [ Atom "pos_fname"; Atom v.pos_fname ]; 6242 List [ Atom "pos_bol"; Atom (string_of_int v.pos_bol) ]; 6243 List [ Atom "pos_lnum"; Atom (string_of_int v.pos_lnum) ]; 6244 List [ Atom "pos_cnum"; Atom (string_of_int v.pos_cnum) ]; 6245 ] 6246 6247 let parser_output formatter pv = 6248 let ast, warnings = Odoc_parser.(ast pv, warnings pv) in 6249 let at conv v = 6250 let { Loc.start; end_; _ } = Loc.location v in 6251 let v' = v |> conv in 6252 let start' = 6253 Odoc_parser.position_of_point pv start |> lexing_pos_to_sexp 6254 in 6255 let start'' = Location_to_sexp.point start in 6256 let end' = 6257 Odoc_parser.position_of_point pv end_ |> lexing_pos_to_sexp 6258 in 6259 let end'' = Location_to_sexp.point end_ in 6260 List 6261 [ 6262 List [ Atom "start"; start' ]; 6263 List [ Atom "start_loc"; start'' ]; 6264 List [ Atom "end"; end' ]; 6265 List [ Atom "end_loc"; end'' ]; 6266 List [ Atom "value"; v' ]; 6267 ] 6268 in 6269 let sexp = Ast_to_sexp.(docs { at } ast) in 6270 let warnings = List (List.map error warnings) in 6271 let output = 6272 List 6273 [ List [ Atom "output"; sexp ]; List [ Atom "warnings"; warnings ] ] 6274 in 6275 Sexplib0.Sexp.pp_hum formatter output; 6276 Format.pp_print_flush formatter () 6277 6278 let test 6279 ?(location = 6280 Lexing.{ pos_bol = 0; pos_cnum = 0; pos_lnum = 1; pos_fname = "none" }) 6281 text = 6282 let ast = Odoc_parser.parse_comment ~location ~text in 6283 Format.printf "%a" parser_output ast 6284 6285 let non_offset_location = 6286 test "one\n two\n three"; 6287 [%expect 6288 {| 6289 ((output 6290 (((start ((pos_fname none) (pos_bol 0) (pos_lnum 1) (pos_cnum 0))) 6291 (start_loc (1 0)) 6292 (end ((pos_fname none) (pos_bol 9) (pos_lnum 3) (pos_cnum 16))) 6293 (end_loc (3 7)) 6294 (value 6295 (paragraph 6296 (((start ((pos_fname none) (pos_bol 0) (pos_lnum 1) (pos_cnum 0))) 6297 (start_loc (1 0)) 6298 (end ((pos_fname none) (pos_bol 0) (pos_lnum 1) (pos_cnum 3))) 6299 (end_loc (1 3)) (value (word one))) 6300 ((start ((pos_fname none) (pos_bol 0) (pos_lnum 1) (pos_cnum 3))) 6301 (start_loc (1 3)) 6302 (end ((pos_fname none) (pos_bol 4) (pos_lnum 2) (pos_cnum 5))) 6303 (end_loc (2 1)) (value space)) 6304 ((start ((pos_fname none) (pos_bol 4) (pos_lnum 2) (pos_cnum 5))) 6305 (start_loc (2 1)) 6306 (end ((pos_fname none) (pos_bol 4) (pos_lnum 2) (pos_cnum 8))) 6307 (end_loc (2 4)) (value (word two))) 6308 ((start ((pos_fname none) (pos_bol 4) (pos_lnum 2) (pos_cnum 8))) 6309 (start_loc (2 4)) 6310 (end ((pos_fname none) (pos_bol 9) (pos_lnum 3) (pos_cnum 11))) 6311 (end_loc (3 2)) (value space)) 6312 ((start ((pos_fname none) (pos_bol 9) (pos_lnum 3) (pos_cnum 11))) 6313 (start_loc (3 2)) 6314 (end ((pos_fname none) (pos_bol 9) (pos_lnum 3) (pos_cnum 16))) 6315 (end_loc (3 7)) (value (word three))))))))) 6316 (warnings ())) |}] 6317 6318 let offset_location = 6319 test 6320 ~location: 6321 Lexing. 6322 { pos_bol = 10; pos_cnum = 20; pos_lnum = 2; pos_fname = "none" } 6323 "one\n two\n three"; 6324 [%expect 6325 {| 6326 ((output 6327 (((start ((pos_fname none) (pos_bol 10) (pos_lnum 2) (pos_cnum 20))) 6328 (start_loc (2 10)) 6329 (end ((pos_fname none) (pos_bol 29) (pos_lnum 4) (pos_cnum 36))) 6330 (end_loc (4 7)) 6331 (value 6332 (paragraph 6333 (((start ((pos_fname none) (pos_bol 10) (pos_lnum 2) (pos_cnum 20))) 6334 (start_loc (2 10)) 6335 (end ((pos_fname none) (pos_bol 10) (pos_lnum 2) (pos_cnum 23))) 6336 (end_loc (2 13)) (value (word one))) 6337 ((start ((pos_fname none) (pos_bol 10) (pos_lnum 2) (pos_cnum 23))) 6338 (start_loc (2 13)) 6339 (end ((pos_fname none) (pos_bol 24) (pos_lnum 3) (pos_cnum 25))) 6340 (end_loc (3 1)) (value space)) 6341 ((start ((pos_fname none) (pos_bol 24) (pos_lnum 3) (pos_cnum 25))) 6342 (start_loc (3 1)) 6343 (end ((pos_fname none) (pos_bol 24) (pos_lnum 3) (pos_cnum 28))) 6344 (end_loc (3 4)) (value (word two))) 6345 ((start ((pos_fname none) (pos_bol 24) (pos_lnum 3) (pos_cnum 28))) 6346 (start_loc (3 4)) 6347 (end ((pos_fname none) (pos_bol 29) (pos_lnum 4) (pos_cnum 31))) 6348 (end_loc (4 2)) (value space)) 6349 ((start ((pos_fname none) (pos_bol 29) (pos_lnum 4) (pos_cnum 31))) 6350 (start_loc (4 2)) 6351 (end ((pos_fname none) (pos_bol 29) (pos_lnum 4) (pos_cnum 36))) 6352 (end_loc (4 7)) (value (word three))))))))) 6353 (warnings ())) |}] 6354 end in 6355 () 6356 6357let%expect_test _ = 6358 let module Math = struct 6359 let block = 6360 test "{math \\sum_{i=0}^n x^i%}"; 6361 [%expect 6362 {| 6363 ((output (((f.ml (1 0) (1 24)) (math_block "\\sum_{i=0}^n x^i%")))) 6364 (warnings ())) |}] 6365 6366 let complex_block = 6367 test 6368 {|{math 6369 \alpha(x)=\left\{ 6370 \begin{array}{ll} % beginning of the array 6371 x \% 4\\ % some variable modulo 4 6372 \frac{1}{1+e^{-kx}}\\ % something else 6373 \frac{e^x-e^{-x}}{e^x+e^{-x}} % another action 6374 \end{array} % end of the array 6375 \right. 6376 }|}; 6377 [%expect 6378 {| 6379 ((output 6380 (((f.ml (1 0) (9 7)) 6381 (math_block 6382 " \\alpha(x)=\\left\\{\ 6383 \n \\begin{array}{ll} % beginning of the array\ 6384 \n x \\% 4\\\\ % some variable modulo 4\ 6385 \n \\frac{1}{1+e^{-kx}}\\\\ % something else\ 6386 \n \\frac{e^x-e^{-x}}{e^x+e^{-x}} % another action\ 6387 \n \\end{array} % end of the array\ 6388 \n \\right.\ 6389 \n ")))) 6390 (warnings ())) |}] 6391 6392 let inline = 6393 test "{m x + 4}"; 6394 [%expect 6395 {| 6396 ((output 6397 (((f.ml (1 0) (1 9)) 6398 (paragraph (((f.ml (1 0) (1 9)) (math_span "x + 4"))))))) 6399 (warnings ())) |}] 6400 6401 let inline_nested = 6402 test "{m \\sub_{i=0}^n x^i}"; 6403 [%expect 6404 {| 6405 ((output 6406 (((f.ml (1 0) (1 20)) 6407 (paragraph (((f.ml (1 0) (1 20)) (math_span "\\sub_{i=0}^n x^i"))))))) 6408 (warnings ())) |}] 6409 6410 let inline_false_nesting = 6411 test "{m \\{ \\mathbb{only_left}}"; 6412 [%expect 6413 {| 6414 ((output 6415 (((f.ml (1 0) (1 25)) 6416 (paragraph (((f.ml (1 0) (1 25)) (math_span "\\{ \\mathbb{only_left}"))))))) 6417 (warnings ())) |}] 6418 6419 let inline_false_terminator = 6420 test "{m \\mathbb{only_left}\\}}"; 6421 [%expect 6422 {| 6423 ((output 6424 (((f.ml (1 0) (1 24)) 6425 (paragraph (((f.ml (1 0) (1 24)) (math_span "\\mathbb{only_left}\\}"))))))) 6426 (warnings ())) |}] 6427 end in 6428 ()