Rust library to generate static websites

Compare changes

Choose any two refs to compare.

+867 -479
+1 -1
.github/workflows/benchmark.yaml
··· 41 41 uses: actions/setup-node@v4 42 42 with: 43 43 node-version: latest 44 - cache: 'pnpm' 44 + cache: "pnpm" 45 45 46 46 - name: Install dependencies 47 47 run: pnpm install
+4 -4
.github/workflows/ci.yaml
··· 38 38 uses: actions/setup-node@v4 39 39 with: 40 40 node-version: latest 41 - cache: 'pnpm' 41 + cache: "pnpm" 42 42 43 43 - name: Install dependencies 44 44 run: pnpm install ··· 66 66 uses: actions/setup-node@v4 67 67 with: 68 68 node-version: latest 69 - cache: 'pnpm' 69 + cache: "pnpm" 70 70 71 71 - name: Install dependencies 72 72 run: pnpm install ··· 94 94 uses: actions/setup-node@v4 95 95 with: 96 96 node-version: latest 97 - cache: 'pnpm' 97 + cache: "pnpm" 98 98 99 99 - name: Install dependencies 100 100 run: pnpm install ··· 126 126 uses: actions/setup-node@v4 127 127 with: 128 128 node-version: latest 129 - cache: 'pnpm' 129 + cache: "pnpm" 130 130 131 131 - name: Install dependencies 132 132 run: pnpm install
+1 -1
.github/workflows/release.yml
··· 30 30 uses: actions/setup-node@v4 31 31 with: 32 32 node-version: latest 33 - cache: 'pnpm' 33 + cache: "pnpm" 34 34 35 35 - name: Install dependencies 36 36 run: pnpm install
+5
.sampo/changesets/valorous-earl-louhi.md
··· 1 + --- 2 + cargo/maudit: patch 3 + --- 4 + 5 + Make placeholders function return Result so that errors can be handled, if need to
+1 -1
.sampo/config.toml
··· 1 1 [packages] 2 2 linked = [["maudit", "maudit-macros"]] 3 - ignore = ["benchmarks/*", "examples/*", "maudit-website", "root"] 3 + ignore = ["benchmarks/*", "examples/*", "maudit-website", "root", "e2e/fixtures/*"]
+2 -6
.vscode/extensions.json
··· 1 1 { 2 - "recommendations": [ 3 - "oxc.oxc-vscode", 4 - "TypeScriptTeam.native-preview", 5 - "rust-lang.rust-analyzer" 6 - ] 7 - } 2 + "recommendations": ["oxc.oxc-vscode", "TypeScriptTeam.native-preview", "rust-lang.rust-analyzer"] 3 + }
+14 -14
.vscode/settings.json
··· 1 1 { 2 - "typescript.experimental.useTsgo": true, 3 - "editor.defaultFormatter": "oxc.oxc-vscode", 4 - "oxc.typeAware": true, 5 - "oxc.fixKind": "safe_fix", 6 - "oxc.unusedDisableDirectives": "deny", 7 - "[rust]": { 8 - "editor.defaultFormatter": "rust-lang.rust-analyzer" 9 - }, 10 - "editor.codeActionsOnSave": { 11 - "source.fixAll.oxc": "explicit" 12 - }, 13 - "biome.enabled": false, 14 - "css.lint.unknownAtRules": "ignore", 15 - } 2 + "typescript.experimental.useTsgo": true, 3 + "editor.defaultFormatter": "oxc.oxc-vscode", 4 + "oxc.typeAware": true, 5 + "oxc.fixKind": "safe_fix", 6 + "oxc.unusedDisableDirectives": "deny", 7 + "[rust]": { 8 + "editor.defaultFormatter": "rust-lang.rust-analyzer" 9 + }, 10 + "editor.codeActionsOnSave": { 11 + "source.fixAll.oxc": "explicit" 12 + }, 13 + "biome.enabled": false, 14 + "css.lint.unknownAtRules": "ignore" 15 + }
+354 -330
Cargo.lock
··· 409 409 ] 410 410 411 411 [[package]] 412 - name = "brk-file-id" 413 - version = "0.2.3" 414 - source = "registry+https://github.com/rust-lang/crates.io-index" 415 - checksum = "4c1950d399f52e1f5094028ce390381e75649cf4409fca898047005a6dad3afd" 416 - dependencies = [ 417 - "windows-sys 0.60.2", 418 - ] 419 - 420 - [[package]] 421 - name = "brk-notify" 422 - version = "8.2.1" 423 - source = "registry+https://github.com/rust-lang/crates.io-index" 424 - checksum = "ca1c0159b584e64e5dda5bcd1a773435514aeabbcf5b1afc194381b465d8fa01" 425 - dependencies = [ 426 - "bitflags 2.10.0", 427 - "brk-notify-types", 428 - "fsevent-sys", 429 - "inotify", 430 - "kqueue", 431 - "libc", 432 - "log", 433 - "mio 1.1.1", 434 - "walkdir", 435 - "windows-sys 0.60.2", 436 - ] 437 - 438 - [[package]] 439 - name = "brk-notify-debouncer-full" 440 - version = "0.6.1" 441 - source = "registry+https://github.com/rust-lang/crates.io-index" 442 - checksum = "36157ad4fe408d3958da182e0d56a2928eddb098649a241efcc9e1fe9076dc96" 443 - dependencies = [ 444 - "brk-file-id", 445 - "brk-notify", 446 - "brk-notify-types", 447 - "log", 448 - "walkdir", 449 - ] 450 - 451 - [[package]] 452 - name = "brk-notify-types" 453 - version = "2.0.1" 454 - source = "registry+https://github.com/rust-lang/crates.io-index" 455 - checksum = "91ff3e445e42475fba5e0cfaed51345f491e479b9f2069f29875f434a5327913" 456 - 457 - [[package]] 458 412 name = "brk_rolldown" 459 - version = "0.2.3" 413 + version = "0.8.0" 460 414 source = "registry+https://github.com/rust-lang/crates.io-index" 461 - checksum = "76d5237104ef0c275a1c50354392a7edb45fc736998479530c231d811a0a38e0" 415 + checksum = "1c59974a49863697b5583a3292bcbe05cffb068a0ddda317b5f09ac01880b675" 462 416 dependencies = [ 463 417 "anyhow", 464 418 "append-only-vec", 465 419 "arcstr", 466 420 "bitflags 2.10.0", 467 - "brk-notify", 468 421 "brk_rolldown_common", 469 - "brk_rolldown_debug", 422 + "brk_rolldown_dev_common", 423 + "brk_rolldown_devtools", 470 424 "brk_rolldown_ecmascript", 471 425 "brk_rolldown_ecmascript_utils", 472 426 "brk_rolldown_error", ··· 475 429 "brk_rolldown_plugin_chunk_import_map", 476 430 "brk_rolldown_plugin_data_uri", 477 431 "brk_rolldown_plugin_hmr", 432 + "brk_rolldown_plugin_lazy_compilation", 478 433 "brk_rolldown_plugin_oxc_runtime", 479 434 "brk_rolldown_resolver", 480 435 "brk_rolldown_sourcemap", 481 436 "brk_rolldown_std_utils", 482 437 "brk_rolldown_tracing", 483 438 "brk_rolldown_utils", 484 - "brk_rolldown_watcher", 485 439 "brk_string_wizard", 486 440 "commondir", 487 441 "css-module-lexer", 488 - "derive_more", 489 - "dunce", 490 442 "futures", 491 443 "indexmap", 492 444 "itertools", 493 445 "itoa", 446 + "json-escape-simd", 494 447 "memchr", 495 448 "oxc", 496 449 "oxc_allocator", ··· 499 452 "oxc_traverse", 500 453 "petgraph", 501 454 "rayon", 455 + "rolldown-notify", 502 456 "rustc-hash", 503 457 "serde", 504 458 "serde_json", ··· 511 465 512 466 [[package]] 513 467 name = "brk_rolldown_common" 514 - version = "0.2.3" 468 + version = "0.8.0" 515 469 source = "registry+https://github.com/rust-lang/crates.io-index" 516 - checksum = "80d4461576c24766fdea280ce888e6d8dc36f50161e2615fd6a698511d623f36" 470 + checksum = "315da1c9e3a7ea47ce60339177eea8e2ad6e1019aa26b7d15a0d0aef0e42d886" 517 471 dependencies = [ 518 472 "anyhow", 519 473 "arcstr", ··· 542 496 ] 543 497 544 498 [[package]] 545 - name = "brk_rolldown_debug" 546 - version = "0.2.3" 499 + name = "brk_rolldown_dev_common" 500 + version = "0.8.0" 501 + source = "registry+https://github.com/rust-lang/crates.io-index" 502 + checksum = "40f4e0044871873810d136770d070acab9d80c9a2d0f65ff1caae778be55f01b" 503 + dependencies = [ 504 + "brk_rolldown_common", 505 + "brk_rolldown_error", 506 + "derive_more", 507 + ] 508 + 509 + [[package]] 510 + name = "brk_rolldown_devtools" 511 + version = "0.8.0" 547 512 source = "registry+https://github.com/rust-lang/crates.io-index" 548 - checksum = "e6d03984d81260c4d9d068431eda178b59a3eaf539d67d1cc6cd2b0dc28140d5" 513 + checksum = "7ca26431eb07e95ba3c65860b0a76be6d17cd2992d7da114ae0286c63ee527a5" 549 514 dependencies = [ 550 515 "blake3", 551 - "brk_rolldown_debug_action", 516 + "brk_rolldown_devtools_action", 552 517 "dashmap", 553 518 "rustc-hash", 554 519 "serde", ··· 558 523 ] 559 524 560 525 [[package]] 561 - name = "brk_rolldown_debug_action" 562 - version = "0.2.3" 526 + name = "brk_rolldown_devtools_action" 527 + version = "0.8.0" 563 528 source = "registry+https://github.com/rust-lang/crates.io-index" 564 - checksum = "e03dc81df86ed78c962fb675bc4d3ecf5988ec8813dddc41701b3c496e29514b" 529 + checksum = "83b4530239d43ee51d96151c31884c747d0e7aa7ee5fe12ba673854f3bde1460" 565 530 dependencies = [ 566 531 "serde", 567 532 "ts-rs", ··· 569 534 570 535 [[package]] 571 536 name = "brk_rolldown_ecmascript" 572 - version = "0.2.3" 537 + version = "0.8.0" 573 538 source = "registry+https://github.com/rust-lang/crates.io-index" 574 - checksum = "4c5f433cfd8f7d5b9a054422770e7477a24c398493e8cd42e15f712dbda9d280" 539 + checksum = "e658a6dd55cfa2d7b8747d7515efb3703da2172d65fde07068b92d9e1f7b0df6" 575 540 dependencies = [ 576 541 "arcstr", 577 542 "brk_rolldown_error", ··· 582 547 583 548 [[package]] 584 549 name = "brk_rolldown_ecmascript_utils" 585 - version = "0.2.3" 550 + version = "0.8.0" 586 551 source = "registry+https://github.com/rust-lang/crates.io-index" 587 - checksum = "4358a13b70a7a647f61ba95caae66e6c747b10d5cba784e6c38636b2011267a0" 552 + checksum = "06a4d59d600016843aa502a7fbe2778598fe92f934a87d9f7aeb20d840fcadf9" 588 553 dependencies = [ 589 554 "brk_rolldown_common", 555 + "brk_rolldown_utils", 590 556 "oxc", 591 557 "smallvec", 592 558 ] 593 559 594 560 [[package]] 595 561 name = "brk_rolldown_error" 596 - version = "0.2.3" 562 + version = "0.8.0" 597 563 source = "registry+https://github.com/rust-lang/crates.io-index" 598 - checksum = "fd9a2e23e1e5dfbfacfaa01fd6adbb05511233ca7c128dde3f4b38d74de0a3b9" 564 + checksum = "a1f96089242b4a06e9cb66e9425246c1ca15afb1dd05390b6e9d08016bb11421" 599 565 dependencies = [ 600 566 "anyhow", 601 567 "arcstr", 602 568 "bitflags 2.10.0", 603 - "brk_rolldown_utils", 604 569 "derive_more", 605 570 "heck", 606 571 "oxc", ··· 613 578 614 579 [[package]] 615 580 name = "brk_rolldown_fs" 616 - version = "0.2.3" 581 + version = "0.8.0" 617 582 source = "registry+https://github.com/rust-lang/crates.io-index" 618 - checksum = "c9ef43d8e0f263b04febb3972ddbb95792abf510c74b4df9a7849786bd557acb" 583 + checksum = "9af54a43116ab3a78777337bf779c8fa784cf3ac495e3429c16bd3b49fc8b351" 619 584 dependencies = [ 620 585 "oxc_resolver", 621 586 "vfs", ··· 623 588 624 589 [[package]] 625 590 name = "brk_rolldown_plugin" 626 - version = "0.2.3" 591 + version = "0.8.0" 627 592 source = "registry+https://github.com/rust-lang/crates.io-index" 628 - checksum = "79b87d794281878edb320543a514a6d25b47d4f78a2744b674a19db01e10c0d2" 593 + checksum = "82aa5428ad77c0b581e98ab0c0a774e66682c8a21c9b25b58c632931ae11cf6c" 629 594 dependencies = [ 630 595 "anyhow", 631 596 "arcstr", 632 597 "async-trait", 633 598 "bitflags 2.10.0", 634 599 "brk_rolldown_common", 635 - "brk_rolldown_debug", 600 + "brk_rolldown_devtools", 636 601 "brk_rolldown_ecmascript", 637 602 "brk_rolldown_error", 638 603 "brk_rolldown_resolver", ··· 641 606 "brk_string_wizard", 642 607 "dashmap", 643 608 "derive_more", 609 + "nodejs-built-in-modules", 644 610 "oxc_index", 645 611 "rustc-hash", 646 612 "serde", ··· 653 619 654 620 [[package]] 655 621 name = "brk_rolldown_plugin_chunk_import_map" 656 - version = "0.2.3" 622 + version = "0.8.0" 657 623 source = "registry+https://github.com/rust-lang/crates.io-index" 658 - checksum = "17b70821f39dc678e05d16e75e7549b90acdd6f87d408b42120e586850ee6014" 624 + checksum = "f0b84c39707298c248ffafaf2e66cf55e847b8dffa7d67a34af0a7646b965d47" 659 625 dependencies = [ 660 626 "arcstr", 661 627 "brk_rolldown_common", ··· 668 634 669 635 [[package]] 670 636 name = "brk_rolldown_plugin_data_uri" 671 - version = "0.2.3" 637 + version = "0.8.0" 672 638 source = "registry+https://github.com/rust-lang/crates.io-index" 673 - checksum = "d1012b5c731c4c1e21169997a115d6273f6cc10d01726eb58509fa58dec39aa7" 639 + checksum = "9a767b657b6d5911a296164bf219949463a275a48a717d88736c98857565104c" 674 640 dependencies = [ 675 641 "arcstr", 676 642 "base64-simd", ··· 683 649 684 650 [[package]] 685 651 name = "brk_rolldown_plugin_hmr" 686 - version = "0.2.3" 652 + version = "0.8.0" 653 + source = "registry+https://github.com/rust-lang/crates.io-index" 654 + checksum = "da3a79c3092a390ea4a447bdf4963feeefe8dca32c4d59b113ca9d0317d1fd99" 655 + dependencies = [ 656 + "arcstr", 657 + "brk_rolldown_common", 658 + "brk_rolldown_plugin", 659 + "oxc", 660 + ] 661 + 662 + [[package]] 663 + name = "brk_rolldown_plugin_lazy_compilation" 664 + version = "0.8.0" 687 665 source = "registry+https://github.com/rust-lang/crates.io-index" 688 - checksum = "94bf2c1f5735ad763df8805d47fbb04af7bd622be89abac7339e04415b3a69a9" 666 + checksum = "d6e1ca134fde27ea05ce0b743a1b37c908342c6449353ec966e3bbb4a383c1c9" 689 667 dependencies = [ 668 + "anyhow", 690 669 "arcstr", 691 670 "brk_rolldown_common", 692 671 "brk_rolldown_plugin", 672 + "brk_rolldown_utils", 693 673 "oxc", 694 674 ] 695 675 696 676 [[package]] 697 677 name = "brk_rolldown_plugin_oxc_runtime" 698 - version = "0.2.3" 678 + version = "0.8.0" 699 679 source = "registry+https://github.com/rust-lang/crates.io-index" 700 - checksum = "7631bc3c34d8c95ed2fdcc10fd53e761fec6509b2f7804cbde800ca813e8c32d" 680 + checksum = "5127d5c297804b583958eb562f9aab0dbd837536dbec6bd1abfa484c0f379ebe" 701 681 dependencies = [ 702 682 "arcstr", 703 683 "brk_rolldown_plugin", ··· 706 686 ] 707 687 708 688 [[package]] 689 + name = "brk_rolldown_plugin_replace" 690 + version = "0.8.0" 691 + source = "registry+https://github.com/rust-lang/crates.io-index" 692 + checksum = "6331fe3dfe7740a111ca37c3cf26f3633f9a10bdfdc92854656573632474e954" 693 + dependencies = [ 694 + "anyhow", 695 + "brk_rolldown_plugin", 696 + "brk_string_wizard", 697 + "oxc", 698 + "regex", 699 + "regress", 700 + "rustc-hash", 701 + ] 702 + 703 + [[package]] 709 704 name = "brk_rolldown_resolver" 710 - version = "0.2.3" 705 + version = "0.8.0" 711 706 source = "registry+https://github.com/rust-lang/crates.io-index" 712 - checksum = "7c08ca0eac64956b1b81af47f360a7c2107292475efe4e04605a20257753fde5" 707 + checksum = "f37c2fdb7fd680a137bc6f16f6c1bfbf49fd3d8177939ed7aedf3fb62b0cf8bb" 713 708 dependencies = [ 709 + "anyhow", 714 710 "arcstr", 715 711 "brk_rolldown_common", 716 712 "brk_rolldown_fs", ··· 723 719 724 720 [[package]] 725 721 name = "brk_rolldown_sourcemap" 726 - version = "0.2.3" 722 + version = "0.8.0" 727 723 source = "registry+https://github.com/rust-lang/crates.io-index" 728 - checksum = "63859586276da70f2f8239ca558a0fc6f047fdea2c6856cca9c5056cd6a8963a" 724 + checksum = "6cdc7d8f4f2161dcd1f61ca1929cf1ef2328280cddb41bdba5a510064a83fa8e" 729 725 dependencies = [ 730 726 "brk_rolldown_utils", 731 727 "memchr", ··· 736 732 737 733 [[package]] 738 734 name = "brk_rolldown_std_utils" 739 - version = "0.2.3" 735 + version = "0.8.0" 740 736 source = "registry+https://github.com/rust-lang/crates.io-index" 741 - checksum = "754a91681b732fdc7e0118f8f356e1f7428b66ce00339688a1c2e8591b98edb2" 737 + checksum = "004f589ea02774a6ca2641ad375123c001abda5403896ed3b21ef7614925aef4" 742 738 dependencies = [ 743 739 "regex", 744 740 ] 745 741 746 742 [[package]] 747 743 name = "brk_rolldown_tracing" 748 - version = "0.2.3" 744 + version = "0.8.0" 749 745 source = "registry+https://github.com/rust-lang/crates.io-index" 750 - checksum = "da33c2b40ddb7390f299fa7ff7bd74d2ecd80dd57ad2a4cdef131412605090c4" 746 + checksum = "6c64033001d5a5efe984f762b2ee51c968d05310d1a8de53e71cce91d1af1b0c" 751 747 dependencies = [ 752 748 "tracing", 753 749 "tracing-chrome", ··· 756 752 757 753 [[package]] 758 754 name = "brk_rolldown_utils" 759 - version = "0.2.3" 755 + version = "0.8.0" 760 756 source = "registry+https://github.com/rust-lang/crates.io-index" 761 - checksum = "aeb807d38d854c3f71c7640b31961da59de3bff3f9498b79e31570debaf74a4f" 757 + checksum = "4040e087114fe7c502a3f4f592e03b78e50515c36b3c9c3f7adcf227326eea65" 762 758 dependencies = [ 763 759 "anyhow", 764 760 "arcstr", 765 761 "async-scoped", 766 762 "base-encode", 767 763 "base64-simd", 764 + "brk_rolldown_error", 768 765 "brk_rolldown_std_utils", 769 766 "cow-utils", 770 767 "dashmap", ··· 793 790 ] 794 791 795 792 [[package]] 796 - name = "brk_rolldown_watcher" 797 - version = "0.2.3" 798 - source = "registry+https://github.com/rust-lang/crates.io-index" 799 - checksum = "cac059d6804c44336f882a87d568bc866cb6fbf8ecd5a083aaf0a310230a2909" 800 - dependencies = [ 801 - "brk-notify", 802 - "brk-notify-debouncer-full", 803 - "brk_rolldown_error", 804 - ] 805 - 806 - [[package]] 807 793 name = "brk_string_wizard" 808 - version = "0.2.3" 794 + version = "0.8.0" 809 795 source = "registry+https://github.com/rust-lang/crates.io-index" 810 - checksum = "b7117e64fd4da49fe64dcebbbd8f4e490b1c07fdf99e4c22e2cefa0e130da480" 796 + checksum = "1340aa44bcaf15d553ee4bd9e07864102ea99ea5bccf8918ea898de760af7183" 811 797 dependencies = [ 812 798 "memchr", 813 799 "oxc_index", 814 800 "oxc_sourcemap", 801 + "regex", 815 802 "rustc-hash", 816 803 "serde", 817 804 ] ··· 824 811 825 812 [[package]] 826 813 name = "bumpalo" 827 - version = "3.19.0" 814 + version = "3.19.1" 828 815 source = "registry+https://github.com/rust-lang/crates.io-index" 829 - checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 816 + checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" 830 817 dependencies = [ 831 818 "allocator-api2", 832 819 ] ··· 1004 991 dependencies = [ 1005 992 "anyhow", 1006 993 "bincode", 1007 - "colored", 994 + "colored 2.2.0", 1008 995 "glob", 1009 996 "libc", 1010 997 "nix", ··· 1077 1064 ] 1078 1065 1079 1066 [[package]] 1067 + name = "colored" 1068 + version = "3.1.1" 1069 + source = "registry+https://github.com/rust-lang/crates.io-index" 1070 + checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" 1071 + dependencies = [ 1072 + "windows-sys 0.61.2", 1073 + ] 1074 + 1075 + [[package]] 1080 1076 name = "commondir" 1081 1077 version = "1.0.0" 1082 1078 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1205 1201 1206 1202 [[package]] 1207 1203 name = "crossterm" 1208 - version = "0.25.0" 1204 + version = "0.29.0" 1209 1205 source = "registry+https://github.com/rust-lang/crates.io-index" 1210 - checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 1206 + checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" 1211 1207 dependencies = [ 1212 - "bitflags 1.3.2", 1208 + "bitflags 2.10.0", 1213 1209 "crossterm_winapi", 1214 - "libc", 1215 - "mio 0.8.11", 1210 + "derive_more", 1211 + "document-features", 1212 + "mio", 1216 1213 "parking_lot", 1214 + "rustix", 1217 1215 "signal-hook", 1218 1216 "signal-hook-mio", 1219 1217 "winapi", ··· 1433 1431 ] 1434 1432 1435 1433 [[package]] 1434 + name = "document-features" 1435 + version = "0.2.12" 1436 + source = "registry+https://github.com/rust-lang/crates.io-index" 1437 + checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" 1438 + dependencies = [ 1439 + "litrs", 1440 + ] 1441 + 1442 + [[package]] 1436 1443 name = "dragonbox_ecma" 1437 1444 version = "0.0.5" 1438 1445 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1454 1461 ] 1455 1462 1456 1463 [[package]] 1457 - name = "dunce" 1458 - version = "1.0.5" 1459 - source = "registry+https://github.com/rust-lang/crates.io-index" 1460 - checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" 1461 - 1462 - [[package]] 1463 1464 name = "dyn-clone" 1464 1465 version = "1.0.20" 1465 1466 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1661 1662 checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" 1662 1663 1663 1664 [[package]] 1665 + name = "fixtures-hot-reload" 1666 + version = "0.1.0" 1667 + dependencies = [ 1668 + "maud", 1669 + "maudit", 1670 + ] 1671 + 1672 + [[package]] 1673 + name = "fixtures-prefetch-prerender" 1674 + version = "0.1.0" 1675 + dependencies = [ 1676 + "maud", 1677 + "maudit", 1678 + ] 1679 + 1680 + [[package]] 1664 1681 name = "flate2" 1665 1682 version = "1.1.8" 1666 1683 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1672 1689 ] 1673 1690 1674 1691 [[package]] 1692 + name = "float-cmp" 1693 + version = "0.10.0" 1694 + source = "registry+https://github.com/rust-lang/crates.io-index" 1695 + checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" 1696 + dependencies = [ 1697 + "num-traits", 1698 + ] 1699 + 1700 + [[package]] 1675 1701 name = "fnv" 1676 1702 version = "1.0.7" 1677 1703 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1812 1838 ] 1813 1839 1814 1840 [[package]] 1815 - name = "fxhash" 1816 - version = "0.2.1" 1817 - source = "registry+https://github.com/rust-lang/crates.io-index" 1818 - checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 1819 - dependencies = [ 1820 - "byteorder", 1821 - ] 1822 - 1823 - [[package]] 1824 1841 name = "generic-array" 1825 1842 version = "0.14.7" 1826 1843 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1836 1853 source = "registry+https://github.com/rust-lang/crates.io-index" 1837 1854 checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" 1838 1855 dependencies = [ 1839 - "unicode-width 0.2.2", 1856 + "unicode-width", 1840 1857 ] 1841 1858 1842 1859 [[package]] ··· 1899 1916 "cfg-if", 1900 1917 "crunchy", 1901 1918 "zerocopy", 1919 + ] 1920 + 1921 + [[package]] 1922 + name = "halfbrown" 1923 + version = "0.4.0" 1924 + source = "registry+https://github.com/rust-lang/crates.io-index" 1925 + checksum = "0c7ed2f2edad8a14c8186b847909a41fbb9c3eafa44f88bd891114ed5019da09" 1926 + dependencies = [ 1927 + "hashbrown 0.16.1", 1902 1928 ] 1903 1929 1904 1930 [[package]] ··· 2237 2263 2238 2264 [[package]] 2239 2265 name = "inquire" 2240 - version = "0.7.5" 2266 + version = "0.9.2" 2241 2267 source = "registry+https://github.com/rust-lang/crates.io-index" 2242 - checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a" 2268 + checksum = "ae51d5da01ce7039024fbdec477767c102c454dbdb09d4e2a432ece705b1b25d" 2243 2269 dependencies = [ 2244 2270 "bitflags 2.10.0", 2245 2271 "crossterm", 2246 2272 "dyn-clone", 2247 2273 "fuzzy-matcher", 2248 - "fxhash", 2249 - "newline-converter", 2250 - "once_cell", 2251 2274 "unicode-segmentation", 2252 - "unicode-width 0.1.14", 2275 + "unicode-width", 2253 2276 ] 2254 2277 2255 2278 [[package]] ··· 2330 2353 2331 2354 [[package]] 2332 2355 name = "json-escape-simd" 2333 - version = "1.1.0" 2356 + version = "3.0.1" 2334 2357 source = "registry+https://github.com/rust-lang/crates.io-index" 2335 - checksum = "2a1f7d5786a4cb0f4e0f862b562a0e085b5bfa23a4f0dc05e7b823ed4e4d791f" 2336 - dependencies = [ 2337 - "anyhow", 2338 - ] 2358 + checksum = "a3c2a6c0b4b5637c41719973ef40c6a1cf564f9db6958350de6193fbee9c23f5" 2339 2359 2340 2360 [[package]] 2341 2361 name = "json-strip-comments" ··· 2452 2472 checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" 2453 2473 2454 2474 [[package]] 2475 + name = "litrs" 2476 + version = "1.0.0" 2477 + source = "registry+https://github.com/rust-lang/crates.io-index" 2478 + checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" 2479 + 2480 + [[package]] 2455 2481 name = "local-ip-address" 2456 2482 version = "0.6.9" 2457 2483 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2548 2574 dependencies = [ 2549 2575 "base64", 2550 2576 "brk_rolldown", 2577 + "brk_rolldown_plugin_replace", 2551 2578 "chrono", 2552 - "colored", 2579 + "colored 3.1.1", 2553 2580 "env_logger", 2554 2581 "glob", 2555 2582 "image", ··· 2583 2610 "cargo_metadata", 2584 2611 "chrono", 2585 2612 "clap", 2586 - "colored", 2613 + "colored 3.1.1", 2587 2614 "flate2", 2588 2615 "futures", 2589 2616 "inquire", ··· 2597 2624 "tar", 2598 2625 "tokio", 2599 2626 "tokio-util", 2600 - "toml_edit 0.22.27", 2627 + "toml_edit 0.24.0+spec-1.1.0", 2601 2628 "tower-http", 2602 2629 "tracing", 2603 2630 "tracing-subscriber", ··· 2747 2774 2748 2775 [[package]] 2749 2776 name = "mio" 2750 - version = "0.8.11" 2751 - source = "registry+https://github.com/rust-lang/crates.io-index" 2752 - checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 2753 - dependencies = [ 2754 - "libc", 2755 - "log", 2756 - "wasi", 2757 - "windows-sys 0.48.0", 2758 - ] 2759 - 2760 - [[package]] 2761 - name = "mio" 2762 2777 version = "1.1.1" 2763 2778 source = "registry+https://github.com/rust-lang/crates.io-index" 2764 2779 checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" ··· 2815 2830 checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 2816 2831 2817 2832 [[package]] 2818 - name = "newline-converter" 2819 - version = "0.3.0" 2820 - source = "registry+https://github.com/rust-lang/crates.io-index" 2821 - checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f" 2822 - dependencies = [ 2823 - "unicode-segmentation", 2824 - ] 2825 - 2826 - [[package]] 2827 2833 name = "nibble_vec" 2828 2834 version = "0.1.0" 2829 2835 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2883 2889 "kqueue", 2884 2890 "libc", 2885 2891 "log", 2886 - "mio 1.1.1", 2892 + "mio", 2887 2893 "notify-types", 2888 2894 "walkdir", 2889 2895 "windows-sys 0.60.2", ··· 2891 2897 2892 2898 [[package]] 2893 2899 name = "notify-debouncer-full" 2894 - version = "0.6.0" 2900 + version = "0.7.0" 2895 2901 source = "registry+https://github.com/rust-lang/crates.io-index" 2896 - checksum = "375bd3a138be7bfeff3480e4a623df4cbfb55b79df617c055cd810ba466fa078" 2902 + checksum = "c02b49179cfebc9932238d04d6079912d26de0379328872846118a0fa0dbb302" 2897 2903 dependencies = [ 2898 2904 "file-id", 2899 2905 "log", ··· 2975 2981 ] 2976 2982 2977 2983 [[package]] 2984 + name = "objc2-core-foundation" 2985 + version = "0.3.2" 2986 + source = "registry+https://github.com/rust-lang/crates.io-index" 2987 + checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" 2988 + dependencies = [ 2989 + "bitflags 2.10.0", 2990 + ] 2991 + 2992 + [[package]] 2993 + name = "objc2-core-services" 2994 + version = "0.3.2" 2995 + source = "registry+https://github.com/rust-lang/crates.io-index" 2996 + checksum = "583300ad934cba24ff5292aee751ecc070f7ca6b39a574cc21b7b5e588e06a0b" 2997 + dependencies = [ 2998 + "libc", 2999 + "objc2-core-foundation", 3000 + ] 3001 + 3002 + [[package]] 2978 3003 name = "once_cell" 2979 3004 version = "1.21.3" 2980 3005 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3055 3080 3056 3081 [[package]] 3057 3082 name = "oxc" 3058 - version = "0.92.0" 3083 + version = "0.108.0" 3059 3084 source = "registry+https://github.com/rust-lang/crates.io-index" 3060 - checksum = "514174b0464005dd95e873f5236089949ab77c79cc8a8e9352721f06d45a0b8d" 3085 + checksum = "88bc240e07b45f0d2746e56db4eab367eb68252c454f1a1fa34b5cbe85ff71f8" 3061 3086 dependencies = [ 3062 3087 "oxc_allocator", 3063 3088 "oxc_ast", ··· 3105 3130 "textwrap", 3106 3131 "thiserror 2.0.18", 3107 3132 "unicode-segmentation", 3108 - "unicode-width 0.2.2", 3133 + "unicode-width", 3109 3134 ] 3110 3135 3111 3136 [[package]] ··· 3121 3146 3122 3147 [[package]] 3123 3148 name = "oxc_allocator" 3124 - version = "0.92.0" 3149 + version = "0.108.0" 3125 3150 source = "registry+https://github.com/rust-lang/crates.io-index" 3126 - checksum = "79d9ac4e239df6f418d86176aa4af85f850f60823a8708fd50a6f7d6f475a07d" 3151 + checksum = "78958640bcae9b5b42f9eaafe4995b5460195e961439c236095547bb78952f8d" 3127 3152 dependencies = [ 3128 3153 "allocator-api2", 3129 3154 "bumpalo", ··· 3136 3161 3137 3162 [[package]] 3138 3163 name = "oxc_ast" 3139 - version = "0.92.0" 3164 + version = "0.108.0" 3140 3165 source = "registry+https://github.com/rust-lang/crates.io-index" 3141 - checksum = "013500b777b89130b5f79b545d252d9a147db7ef91f07954da394400ae7f14c9" 3166 + checksum = "e0d1a3c841ad6204dcdba2e584efbff30ec7a5a2c88851108dd39a2ed4be3af3" 3142 3167 dependencies = [ 3143 3168 "bitflags 2.10.0", 3144 3169 "oxc_allocator", ··· 3153 3178 3154 3179 [[package]] 3155 3180 name = "oxc_ast_macros" 3156 - version = "0.92.0" 3181 + version = "0.108.0" 3157 3182 source = "registry+https://github.com/rust-lang/crates.io-index" 3158 - checksum = "9711ea5f01691277822413f0bb56085ac1b867f9cb2090387f634a94a2d4f64c" 3183 + checksum = "3fc4d7eb802fc2bfc49fdc004e875a4009c17657f53372af111eb9d98dc4a15f" 3159 3184 dependencies = [ 3160 3185 "phf", 3161 3186 "proc-macro2", ··· 3165 3190 3166 3191 [[package]] 3167 3192 name = "oxc_ast_visit" 3168 - version = "0.92.0" 3193 + version = "0.108.0" 3169 3194 source = "registry+https://github.com/rust-lang/crates.io-index" 3170 - checksum = "95f0e1f45a19d14d9e4660f426fb8abe31c86b43a43c426a6d182e786994b0bb" 3195 + checksum = "561ace6525ddc90b36103764a959eb261ff7f92a76172a34ac2d24d579f1260d" 3171 3196 dependencies = [ 3172 3197 "oxc_allocator", 3173 3198 "oxc_ast", ··· 3177 3202 3178 3203 [[package]] 3179 3204 name = "oxc_cfg" 3180 - version = "0.92.0" 3205 + version = "0.108.0" 3181 3206 source = "registry+https://github.com/rust-lang/crates.io-index" 3182 - checksum = "a32fdc832b6ed9b007f44022e3b273e5b2cc6d798a91ea5b46e150858b17be40" 3207 + checksum = "0d38997b36d3ad179b672110080c42ab9bf5c1761767754be148c5cbf8982947" 3183 3208 dependencies = [ 3184 3209 "bitflags 2.10.0", 3185 3210 "itertools", 3186 - "nonmax", 3187 3211 "oxc_index", 3188 3212 "oxc_syntax", 3189 3213 "petgraph", ··· 3192 3216 3193 3217 [[package]] 3194 3218 name = "oxc_codegen" 3195 - version = "0.92.0" 3219 + version = "0.108.0" 3196 3220 source = "registry+https://github.com/rust-lang/crates.io-index" 3197 - checksum = "b9e9e29e30d2252903c4c5e1104fb7542365d57ceba83e16d4f52b436f7ffa5d" 3221 + checksum = "0a075130a060ebc4bcf09a55fcf521243527a820937dccda4af92524d4c3def2" 3198 3222 dependencies = [ 3199 3223 "bitflags 2.10.0", 3200 3224 "cow-utils", 3201 3225 "dragonbox_ecma", 3202 3226 "itoa", 3203 - "nonmax", 3204 3227 "oxc_allocator", 3205 3228 "oxc_ast", 3206 3229 "oxc_data_structures", ··· 3214 3237 3215 3238 [[package]] 3216 3239 name = "oxc_compat" 3217 - version = "0.92.0" 3240 + version = "0.108.0" 3218 3241 source = "registry+https://github.com/rust-lang/crates.io-index" 3219 - checksum = "42631ddd366f3a6b829d346a5d8ceb4fb3a3796293916f437b244c4e60fa4dd9" 3242 + checksum = "c4df14ee33385dff8fc347c6ddb62b8c7168c4abf6957deec8415575e0f0f2e3" 3220 3243 dependencies = [ 3221 3244 "cow-utils", 3222 3245 "oxc-browserslist", ··· 3227 3250 3228 3251 [[package]] 3229 3252 name = "oxc_data_structures" 3230 - version = "0.92.0" 3253 + version = "0.108.0" 3231 3254 source = "registry+https://github.com/rust-lang/crates.io-index" 3232 - checksum = "5bccdfe08b75babe4944aefcc84f8d795d48a0155fcb20c4855c46eabf6e5d49" 3255 + checksum = "397842ac155f7c3f707232cc8758c0e67919ac7f75ec3bc34680ae176aca8b61" 3233 3256 dependencies = [ 3234 3257 "ropey", 3235 3258 ] 3236 3259 3237 3260 [[package]] 3238 3261 name = "oxc_diagnostics" 3239 - version = "0.92.0" 3262 + version = "0.108.0" 3240 3263 source = "registry+https://github.com/rust-lang/crates.io-index" 3241 - checksum = "e710dd26a2946f906ccd449a2d34f195b0461e5a8776db067ed207189f0213f3" 3264 + checksum = "2739661b22eb7abe3966ebbe1eb236337f940eed7e9598bdb089c3353aa2c15f" 3242 3265 dependencies = [ 3243 3266 "cow-utils", 3244 3267 "oxc-miette", ··· 3247 3270 3248 3271 [[package]] 3249 3272 name = "oxc_ecmascript" 3250 - version = "0.92.0" 3273 + version = "0.108.0" 3251 3274 source = "registry+https://github.com/rust-lang/crates.io-index" 3252 - checksum = "80c03f1a2246f422197c317585b056dbc283a4cfb10c8058cb3296b87cb835da" 3275 + checksum = "ef913bdaae2ed48335b500a25ecc6a9f186ca855968b5edfc6d1ebad4d0b2124" 3253 3276 dependencies = [ 3254 3277 "cow-utils", 3255 3278 "num-bigint", ··· 3262 3285 3263 3286 [[package]] 3264 3287 name = "oxc_estree" 3265 - version = "0.92.0" 3288 + version = "0.108.0" 3266 3289 source = "registry+https://github.com/rust-lang/crates.io-index" 3267 - checksum = "36ee39a2fc76ae96ccb5dcfea6c430e09e93e4fbcd9ec7f35fe787ea3fb6873a" 3290 + checksum = "a61584ac8cd52d6b6c05a7a5d4b883d5666ea4612ddfe3429f28f7bcd1e93a14" 3268 3291 dependencies = [ 3269 3292 "dragonbox_ecma", 3270 3293 "itoa", ··· 3273 3296 3274 3297 [[package]] 3275 3298 name = "oxc_index" 3276 - version = "3.1.0" 3299 + version = "4.1.0" 3277 3300 source = "registry+https://github.com/rust-lang/crates.io-index" 3278 - checksum = "967ae797e1f284bd1385f2d8e8ab94293ad27f623c76839ecf66827521365f5b" 3301 + checksum = "eb3e6120999627ec9703025eab7c9f410ebb7e95557632a8902ca48210416c2b" 3279 3302 dependencies = [ 3303 + "nonmax", 3280 3304 "rayon", 3281 3305 "serde", 3282 3306 ] 3283 3307 3284 3308 [[package]] 3285 3309 name = "oxc_isolated_declarations" 3286 - version = "0.92.0" 3310 + version = "0.108.0" 3287 3311 source = "registry+https://github.com/rust-lang/crates.io-index" 3288 - checksum = "132bb2006e95e63c0b07cc45c30e6d0de6bb643036d7b6316f7c1398a72c1c42" 3312 + checksum = "04ddf2f1f37acbea0f3a7bc5b40b3e5e5a83a9ea845e48fbddf0e6da591994cc" 3289 3313 dependencies = [ 3290 3314 "bitflags 2.10.0", 3291 3315 "oxc_allocator", ··· 3300 3324 3301 3325 [[package]] 3302 3326 name = "oxc_mangler" 3303 - version = "0.92.0" 3327 + version = "0.108.0" 3304 3328 source = "registry+https://github.com/rust-lang/crates.io-index" 3305 - checksum = "cb797e995b53f0e112b0a1359f967de7cb3a702b46fa2492d6025be4de175a65" 3329 + checksum = "dedab0866f3106cbc831c79e522c5f5ca33412562f79cfecdbb600bbbd896261" 3306 3330 dependencies = [ 3307 3331 "itertools", 3308 3332 "oxc_allocator", ··· 3311 3335 "oxc_index", 3312 3336 "oxc_semantic", 3313 3337 "oxc_span", 3338 + "oxc_syntax", 3314 3339 "rustc-hash", 3315 3340 ] 3316 3341 3317 3342 [[package]] 3318 3343 name = "oxc_minifier" 3319 - version = "0.92.0" 3344 + version = "0.108.0" 3320 3345 source = "registry+https://github.com/rust-lang/crates.io-index" 3321 - checksum = "61dfdcff432cacd8257093842d1494225f72cbea8286610b86abfbad59a16003" 3346 + checksum = "69b6f6e96160888f73125b7345d3934fb0027c3e27cdfa99a3dd042ae033a77d" 3322 3347 dependencies = [ 3323 3348 "cow-utils", 3324 3349 "oxc_allocator", ··· 3328 3353 "oxc_compat", 3329 3354 "oxc_data_structures", 3330 3355 "oxc_ecmascript", 3356 + "oxc_index", 3331 3357 "oxc_mangler", 3332 3358 "oxc_parser", 3333 3359 "oxc_regular_expression", ··· 3340 3366 3341 3367 [[package]] 3342 3368 name = "oxc_parser" 3343 - version = "0.92.0" 3369 + version = "0.108.0" 3344 3370 source = "registry+https://github.com/rust-lang/crates.io-index" 3345 - checksum = "86612cd26f817679d522b7ed33e525537ec5c0a7165d4d23138b8cbaf896d0d5" 3371 + checksum = "06898c992b263f8e4dfcc338528445492a8d61292ad78a0ad7863a265e7beda2" 3346 3372 dependencies = [ 3347 3373 "bitflags 2.10.0", 3348 3374 "cow-utils", ··· 3363 3389 3364 3390 [[package]] 3365 3391 name = "oxc_regular_expression" 3366 - version = "0.92.0" 3392 + version = "0.108.0" 3367 3393 source = "registry+https://github.com/rust-lang/crates.io-index" 3368 - checksum = "e7dc07d4e5d8337f5b6bbadadf1787d2a320f99969c9602ed03c823babd0084a" 3394 + checksum = "7c658b8d107d9534816312d1fd4b77311df648d07ac8af0417355a8cbb09749b" 3369 3395 dependencies = [ 3370 3396 "bitflags 2.10.0", 3371 3397 "oxc_allocator", ··· 3379 3405 3380 3406 [[package]] 3381 3407 name = "oxc_resolver" 3382 - version = "11.9.0" 3408 + version = "11.16.4" 3383 3409 source = "registry+https://github.com/rust-lang/crates.io-index" 3384 - checksum = "9bc696688fc6cbab56971f02badc233541f964f4705240c986abc02535a3728e" 3410 + checksum = "b903284699f550838a491118e58e9d9adb4941c2514f148aedff1ce4b4fbd578" 3385 3411 dependencies = [ 3386 3412 "cfg-if", 3413 + "fast-glob", 3387 3414 "indexmap", 3388 3415 "json-strip-comments", 3389 - "libc", 3416 + "nodejs-built-in-modules", 3390 3417 "once_cell", 3391 3418 "papaya", 3419 + "parking_lot", 3392 3420 "pnp", 3393 3421 "rustc-hash", 3422 + "rustix", 3423 + "self_cell", 3394 3424 "serde", 3395 3425 "serde_json", 3426 + "simd-json", 3396 3427 "simdutf8", 3397 3428 "thiserror 2.0.18", 3398 3429 "tracing", ··· 3402 3433 3403 3434 [[package]] 3404 3435 name = "oxc_semantic" 3405 - version = "0.92.0" 3436 + version = "0.108.0" 3406 3437 source = "registry+https://github.com/rust-lang/crates.io-index" 3407 - checksum = "f9ce8984f6054d3deafebff4e318fea5a38d281905be8bf555e625a7d7c63220" 3438 + checksum = "7ef9534d21d00ac38ca4eab91e7b7f4fa0f1c7f0279d07865074c05357366d5c" 3408 3439 dependencies = [ 3409 3440 "itertools", 3441 + "memchr", 3410 3442 "oxc_allocator", 3411 3443 "oxc_ast", 3412 3444 "oxc_ast_visit", ··· 3417 3449 "oxc_index", 3418 3450 "oxc_span", 3419 3451 "oxc_syntax", 3420 - "phf", 3421 3452 "rustc-hash", 3422 3453 "self_cell", 3454 + "smallvec", 3423 3455 ] 3424 3456 3425 3457 [[package]] 3426 3458 name = "oxc_sourcemap" 3427 - version = "4.2.0" 3459 + version = "6.0.1" 3428 3460 source = "registry+https://github.com/rust-lang/crates.io-index" 3429 - checksum = "d3e5d53a1bdb071d10a83cc0b4c69ca6ebb55d55fc6333897aef72c057830b95" 3461 + checksum = "36801dbbd025f2fa133367494e38eef75a53d334ae6746ba0c889fc4e76fa3a3" 3430 3462 dependencies = [ 3431 3463 "base64-simd", 3432 3464 "json-escape-simd", ··· 3437 3469 3438 3470 [[package]] 3439 3471 name = "oxc_span" 3440 - version = "0.92.0" 3472 + version = "0.108.0" 3441 3473 source = "registry+https://github.com/rust-lang/crates.io-index" 3442 - checksum = "be7ea89d6e858be16ef14f9a9be81ee210c17cb29bb95d5c86881251075071af" 3474 + checksum = "3416e347dd4837cdfbffc49bd2ef106ba592133268a962381cc82d24e8593e40" 3443 3475 dependencies = [ 3444 3476 "compact_str", 3445 3477 "oxc-miette", ··· 3451 3483 3452 3484 [[package]] 3453 3485 name = "oxc_syntax" 3454 - version = "0.92.0" 3486 + version = "0.108.0" 3455 3487 source = "registry+https://github.com/rust-lang/crates.io-index" 3456 - checksum = "a6477f14f0e380033455f0e3e6cdc33fd19932fe5f627a17b38e4666649336cb" 3488 + checksum = "c44aa646ecb431595b3255b6eee2a7f9f292422b76cf5c156a825bd042073453" 3457 3489 dependencies = [ 3458 3490 "bitflags 2.10.0", 3459 3491 "cow-utils", ··· 3466 3498 "oxc_index", 3467 3499 "oxc_span", 3468 3500 "phf", 3469 - "rustc-hash", 3470 3501 "serde", 3471 3502 "unicode-id-start", 3472 3503 ] 3473 3504 3474 3505 [[package]] 3475 3506 name = "oxc_transformer" 3476 - version = "0.92.0" 3507 + version = "0.108.0" 3477 3508 source = "registry+https://github.com/rust-lang/crates.io-index" 3478 - checksum = "7c10b7504559c08191c3881ef53fb671619c62c9cc26bd5e66274c68057e6ad3" 3509 + checksum = "118d7149205362a9ab9de91112f36c13e4192db5036d5cad7cc083a849146450" 3479 3510 dependencies = [ 3480 3511 "base64", 3481 3512 "compact_str", ··· 3489 3520 "oxc_data_structures", 3490 3521 "oxc_diagnostics", 3491 3522 "oxc_ecmascript", 3492 - "oxc_parser", 3493 3523 "oxc_regular_expression", 3494 3524 "oxc_semantic", 3495 3525 "oxc_span", ··· 3503 3533 3504 3534 [[package]] 3505 3535 name = "oxc_transformer_plugins" 3506 - version = "0.92.0" 3536 + version = "0.108.0" 3507 3537 source = "registry+https://github.com/rust-lang/crates.io-index" 3508 - checksum = "1592bc6214448a4986e72e1f7a71ca52e5b7135e831e806eb09bb9a29343dbaf" 3538 + checksum = "a4f8bc0f738f2fa6703560466f3f45e811d1738be86ed50f1e68ea9a9204e9b6" 3509 3539 dependencies = [ 3510 3540 "cow-utils", 3511 3541 "itoa", ··· 3525 3555 3526 3556 [[package]] 3527 3557 name = "oxc_traverse" 3528 - version = "0.92.0" 3558 + version = "0.108.0" 3529 3559 source = "registry+https://github.com/rust-lang/crates.io-index" 3530 - checksum = "8bc2faa1b10f9044f0ef34cb3959684836733d0168ce98504e47010e000ee62e" 3560 + checksum = "0b0c8dc012307ff62260d1f9f3073d4933c5f7e0a01e479f52f6ddd2a487154b" 3531 3561 dependencies = [ 3532 3562 "itoa", 3533 3563 "oxc_allocator", ··· 3543 3573 3544 3574 [[package]] 3545 3575 name = "oxipng" 3546 - version = "9.1.5" 3576 + version = "10.0.0" 3547 3577 source = "registry+https://github.com/rust-lang/crates.io-index" 3548 - checksum = "26c613f0f566526a647c7473f6a8556dbce22c91b13485ee4b4ec7ab648e4973" 3578 + checksum = "d8c9a19c0bec7ec84da567e0a87abd378c0f6e988793f858ea5d58f4b87a81a8" 3549 3579 dependencies = [ 3550 3580 "bitvec", 3551 3581 "clap", ··· 3556 3586 "indexmap", 3557 3587 "libdeflater", 3558 3588 "log", 3589 + "parse-size", 3559 3590 "rayon", 3560 3591 "rgb", 3561 3592 "rustc-hash", ··· 3596 3627 ] 3597 3628 3598 3629 [[package]] 3630 + name = "parse-size" 3631 + version = "1.1.0" 3632 + source = "registry+https://github.com/rust-lang/crates.io-index" 3633 + checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b" 3634 + 3635 + [[package]] 3599 3636 name = "paste" 3600 3637 version = "1.0.15" 3601 3638 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3826 3863 checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" 3827 3864 3828 3865 [[package]] 3829 - name = "prefetch-prerender" 3830 - version = "0.1.0" 3831 - dependencies = [ 3832 - "maud", 3833 - "maudit", 3834 - ] 3835 - 3836 - [[package]] 3837 3866 name = "proc-macro-crate" 3838 3867 version = "3.4.0" 3839 3868 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3906 3935 3907 3936 [[package]] 3908 3937 name = "pulldown-cmark" 3909 - version = "0.12.2" 3938 + version = "0.13.0" 3910 3939 source = "registry+https://github.com/rust-lang/crates.io-index" 3911 - checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" 3940 + checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" 3912 3941 dependencies = [ 3913 3942 "bitflags 2.10.0", 3914 3943 "getopts", ··· 4149 4178 ] 4150 4179 4151 4180 [[package]] 4181 + name = "ref-cast" 4182 + version = "1.0.25" 4183 + source = "registry+https://github.com/rust-lang/crates.io-index" 4184 + checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" 4185 + dependencies = [ 4186 + "ref-cast-impl", 4187 + ] 4188 + 4189 + [[package]] 4190 + name = "ref-cast-impl" 4191 + version = "1.0.25" 4192 + source = "registry+https://github.com/rust-lang/crates.io-index" 4193 + checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" 4194 + dependencies = [ 4195 + "proc-macro2", 4196 + "quote", 4197 + "syn", 4198 + ] 4199 + 4200 + [[package]] 4152 4201 name = "regex" 4153 4202 version = "1.12.2" 4154 4203 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4237 4286 source = "registry+https://github.com/rust-lang/crates.io-index" 4238 4287 checksum = "77dff57c9de498bb1eb5b1ce682c2e3a0ae956b266fa0933c3e151b87b078967" 4239 4288 dependencies = [ 4240 - "unicode-width 0.2.2", 4289 + "unicode-width", 4241 4290 "yansi", 4242 4291 ] 4292 + 4293 + [[package]] 4294 + name = "rolldown-notify" 4295 + version = "10.1.0" 4296 + source = "registry+https://github.com/rust-lang/crates.io-index" 4297 + checksum = "e8bf250d410b79487a6d054e6bd16ec08dddd2998f5f5e6291867a35066cfc37" 4298 + dependencies = [ 4299 + "bitflags 2.10.0", 4300 + "inotify", 4301 + "kqueue", 4302 + "libc", 4303 + "mio", 4304 + "objc2-core-foundation", 4305 + "objc2-core-services", 4306 + "rolldown-notify-types", 4307 + "tracing", 4308 + "walkdir", 4309 + "windows-sys 0.61.2", 4310 + ] 4311 + 4312 + [[package]] 4313 + name = "rolldown-notify-types" 4314 + version = "2.0.2" 4315 + source = "registry+https://github.com/rust-lang/crates.io-index" 4316 + checksum = "1931923a28e14c01a27ca56669669eb3e3de4068859c34e17b96c93ba3a61afe" 4243 4317 4244 4318 [[package]] 4245 4319 name = "ropey" ··· 4524 4598 checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" 4525 4599 dependencies = [ 4526 4600 "libc", 4527 - "mio 0.8.11", 4601 + "mio", 4528 4602 "signal-hook", 4529 4603 ] 4530 4604 ··· 4545 4619 checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" 4546 4620 4547 4621 [[package]] 4622 + name = "simd-json" 4623 + version = "0.17.0" 4624 + source = "registry+https://github.com/rust-lang/crates.io-index" 4625 + checksum = "4255126f310d2ba20048db6321c81ab376f6a6735608bf11f0785c41f01f64e3" 4626 + dependencies = [ 4627 + "halfbrown", 4628 + "ref-cast", 4629 + "simdutf8", 4630 + "value-trait", 4631 + ] 4632 + 4633 + [[package]] 4548 4634 name = "simd_helpers" 4549 4635 version = "0.1.0" 4550 4636 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4586 4672 version = "1.15.1" 4587 4673 source = "registry+https://github.com/rust-lang/crates.io-index" 4588 4674 checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 4675 + dependencies = [ 4676 + "serde", 4677 + ] 4589 4678 4590 4679 [[package]] 4591 4680 name = "smawk" ··· 4764 4853 dependencies = [ 4765 4854 "smawk", 4766 4855 "unicode-linebreak", 4767 - "unicode-width 0.2.2", 4856 + "unicode-width", 4768 4857 ] 4769 4858 4770 4859 [[package]] ··· 4885 4974 dependencies = [ 4886 4975 "bytes", 4887 4976 "libc", 4888 - "mio 1.1.1", 4977 + "mio", 4889 4978 "pin-project-lite", 4890 4979 "signal-hook-registry", 4891 4980 "socket2", ··· 4931 5020 4932 5021 [[package]] 4933 5022 name = "toml_datetime" 4934 - version = "0.6.11" 4935 - source = "registry+https://github.com/rust-lang/crates.io-index" 4936 - checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" 4937 - 4938 - [[package]] 4939 - name = "toml_datetime" 4940 5023 version = "0.7.5+spec-1.1.0" 4941 5024 source = "registry+https://github.com/rust-lang/crates.io-index" 4942 5025 checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" ··· 4946 5029 4947 5030 [[package]] 4948 5031 name = "toml_edit" 4949 - version = "0.22.27" 5032 + version = "0.23.10+spec-1.0.0" 4950 5033 source = "registry+https://github.com/rust-lang/crates.io-index" 4951 - checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" 5034 + checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" 4952 5035 dependencies = [ 4953 5036 "indexmap", 4954 - "toml_datetime 0.6.11", 4955 - "toml_write", 5037 + "toml_datetime", 5038 + "toml_parser", 4956 5039 "winnow", 4957 5040 ] 4958 5041 4959 5042 [[package]] 4960 5043 name = "toml_edit" 4961 - version = "0.23.10+spec-1.0.0" 5044 + version = "0.24.0+spec-1.1.0" 4962 5045 source = "registry+https://github.com/rust-lang/crates.io-index" 4963 - checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" 5046 + checksum = "8c740b185920170a6d9191122cafef7010bd6270a3824594bff6784c04d7f09e" 4964 5047 dependencies = [ 4965 5048 "indexmap", 4966 - "toml_datetime 0.7.5+spec-1.1.0", 5049 + "toml_datetime", 4967 5050 "toml_parser", 5051 + "toml_writer", 4968 5052 "winnow", 4969 5053 ] 4970 5054 ··· 4978 5062 ] 4979 5063 4980 5064 [[package]] 4981 - name = "toml_write" 4982 - version = "0.1.2" 5065 + name = "toml_writer" 5066 + version = "1.0.6+spec-1.1.0" 4983 5067 source = "registry+https://github.com/rust-lang/crates.io-index" 4984 - checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" 5068 + checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" 4985 5069 4986 5070 [[package]] 4987 5071 name = "tower" ··· 5210 5294 5211 5295 [[package]] 5212 5296 name = "unicode-width" 5213 - version = "0.1.14" 5214 - source = "registry+https://github.com/rust-lang/crates.io-index" 5215 - checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" 5216 - 5217 - [[package]] 5218 - name = "unicode-width" 5219 5297 version = "0.2.2" 5220 5298 source = "registry+https://github.com/rust-lang/crates.io-index" 5221 5299 checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" ··· 5332 5410 checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 5333 5411 5334 5412 [[package]] 5413 + name = "value-trait" 5414 + version = "0.12.1" 5415 + source = "registry+https://github.com/rust-lang/crates.io-index" 5416 + checksum = "8e80f0c733af0720a501b3905d22e2f97662d8eacfe082a75ed7ffb5ab08cb59" 5417 + dependencies = [ 5418 + "float-cmp", 5419 + "halfbrown", 5420 + "itoa", 5421 + "ryu", 5422 + ] 5423 + 5424 + [[package]] 5335 5425 name = "version_check" 5336 5426 version = "0.9.5" 5337 5427 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5591 5681 5592 5682 [[package]] 5593 5683 name = "windows-sys" 5594 - version = "0.48.0" 5595 - source = "registry+https://github.com/rust-lang/crates.io-index" 5596 - checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 5597 - dependencies = [ 5598 - "windows-targets 0.48.5", 5599 - ] 5600 - 5601 - [[package]] 5602 - name = "windows-sys" 5603 5684 version = "0.52.0" 5604 5685 source = "registry+https://github.com/rust-lang/crates.io-index" 5605 5686 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" ··· 5632 5713 checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 5633 5714 dependencies = [ 5634 5715 "windows-link", 5635 - ] 5636 - 5637 - [[package]] 5638 - name = "windows-targets" 5639 - version = "0.48.5" 5640 - source = "registry+https://github.com/rust-lang/crates.io-index" 5641 - checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 5642 - dependencies = [ 5643 - "windows_aarch64_gnullvm 0.48.5", 5644 - "windows_aarch64_msvc 0.48.5", 5645 - "windows_i686_gnu 0.48.5", 5646 - "windows_i686_msvc 0.48.5", 5647 - "windows_x86_64_gnu 0.48.5", 5648 - "windows_x86_64_gnullvm 0.48.5", 5649 - "windows_x86_64_msvc 0.48.5", 5650 5716 ] 5651 5717 5652 5718 [[package]] ··· 5693 5759 5694 5760 [[package]] 5695 5761 name = "windows_aarch64_gnullvm" 5696 - version = "0.48.5" 5697 - source = "registry+https://github.com/rust-lang/crates.io-index" 5698 - checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 5699 - 5700 - [[package]] 5701 - name = "windows_aarch64_gnullvm" 5702 5762 version = "0.52.6" 5703 5763 source = "registry+https://github.com/rust-lang/crates.io-index" 5704 5764 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" ··· 5711 5771 5712 5772 [[package]] 5713 5773 name = "windows_aarch64_msvc" 5714 - version = "0.48.5" 5715 - source = "registry+https://github.com/rust-lang/crates.io-index" 5716 - checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 5717 - 5718 - [[package]] 5719 - name = "windows_aarch64_msvc" 5720 5774 version = "0.52.6" 5721 5775 source = "registry+https://github.com/rust-lang/crates.io-index" 5722 5776 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" ··· 5726 5780 version = "0.53.1" 5727 5781 source = "registry+https://github.com/rust-lang/crates.io-index" 5728 5782 checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" 5729 - 5730 - [[package]] 5731 - name = "windows_i686_gnu" 5732 - version = "0.48.5" 5733 - source = "registry+https://github.com/rust-lang/crates.io-index" 5734 - checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 5735 5783 5736 5784 [[package]] 5737 5785 name = "windows_i686_gnu" ··· 5759 5807 5760 5808 [[package]] 5761 5809 name = "windows_i686_msvc" 5762 - version = "0.48.5" 5763 - source = "registry+https://github.com/rust-lang/crates.io-index" 5764 - checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 5765 - 5766 - [[package]] 5767 - name = "windows_i686_msvc" 5768 5810 version = "0.52.6" 5769 5811 source = "registry+https://github.com/rust-lang/crates.io-index" 5770 5812 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" ··· 5777 5819 5778 5820 [[package]] 5779 5821 name = "windows_x86_64_gnu" 5780 - version = "0.48.5" 5781 - source = "registry+https://github.com/rust-lang/crates.io-index" 5782 - checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 5783 - 5784 - [[package]] 5785 - name = "windows_x86_64_gnu" 5786 5822 version = "0.52.6" 5787 5823 source = "registry+https://github.com/rust-lang/crates.io-index" 5788 5824 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" ··· 5795 5831 5796 5832 [[package]] 5797 5833 name = "windows_x86_64_gnullvm" 5798 - version = "0.48.5" 5799 - source = "registry+https://github.com/rust-lang/crates.io-index" 5800 - checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 5801 - 5802 - [[package]] 5803 - name = "windows_x86_64_gnullvm" 5804 5834 version = "0.52.6" 5805 5835 source = "registry+https://github.com/rust-lang/crates.io-index" 5806 5836 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" ··· 5810 5840 version = "0.53.1" 5811 5841 source = "registry+https://github.com/rust-lang/crates.io-index" 5812 5842 checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" 5813 - 5814 - [[package]] 5815 - name = "windows_x86_64_msvc" 5816 - version = "0.48.5" 5817 - source = "registry+https://github.com/rust-lang/crates.io-index" 5818 - checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 5819 5843 5820 5844 [[package]] 5821 5845 name = "windows_x86_64_msvc"
+1 -1
Cargo.toml
··· 6 6 maudit = { path = "crates/maudit", version = "*" } 7 7 oubli = { path = "crates/oubli", version = "*" } 8 8 maud = { version = "0.27.0" } 9 - serde = { version = "1.0.216" } 9 + serde = { version = "1.0.228" } 10 10 11 11 [profile.profiling] 12 12 inherits = "release"
+2 -2
benchmarks/realistic-blog/Cargo.toml
··· 7 7 [dependencies] 8 8 maudit = { workspace = true } 9 9 maud = "0.27.0" 10 - serde = { version = "1.0.216" } 11 - chrono = { version = "0.4.42", features = ["serde"] } 10 + serde = { version = "1.0.228" } 11 + chrono = { version = "0.4.43", features = ["serde"] } 12 12 13 13 [dev-dependencies] 14 14 divan = { version = "3.0.5", package = "codspeed-divan-compat" }
+13 -12
crates/maudit/Cargo.toml
··· 22 22 maud = { workspace = true, optional = true } 23 23 24 24 # TODO: Allow making those optional 25 - rolldown = { package = "brk_rolldown", version = "0.2.3" } 25 + rolldown = { package = "brk_rolldown", version = "0.8.0" } 26 26 serde = { workspace = true } 27 27 serde_yaml = "0.9.34" 28 - pulldown-cmark = "0.12.2" 28 + pulldown-cmark = "0.13.0" 29 29 tokio = { version = "1", features = ["macros", "rt-multi-thread"] } 30 - glob = "0.3.1" 31 - syntect = "5.0" 30 + glob = "0.3.3" 31 + syntect = "5.3" 32 32 lol_html = "2.7.1" 33 33 slug = "0.1.6" 34 - image = "0.25.6" 34 + image = "0.25.9" 35 35 webp = "0.3.1" 36 - oxipng = "9.1.5" 36 + oxipng = "10.0.0" 37 37 thumbhash = "0.1.0" 38 38 base64 = "0.22.1" 39 39 40 40 maudit-macros = { path = "../maudit-macros", version = "0.7.0" } 41 41 log = { version = "0.4", features = ["kv"] } 42 - env_logger = "0.11.5" 43 - chrono = "0.4.39" 44 - colored = "2.2.0" 42 + env_logger = "0.11.8" 43 + chrono = "0.4.43" 44 + colored = "3.1.1" 45 45 rustc-hash = "2.1" 46 - thiserror = "2.0.9" 47 - oxc_sourcemap = "4.1.0" 46 + thiserror = "2.0.18" 47 + oxc_sourcemap = "6.0.1" 48 48 rayon = "1.11.0" 49 - rapidhash = "4.1.1" 49 + rapidhash = "4.2.1" 50 50 pathdiff = "0.2.3" 51 + rolldown_plugin_replace = { package = "brk_rolldown_plugin_replace", version = "0.8.0" } 51 52 52 53 [dev-dependencies] 53 54 tempfile = "3.24.0"
+58 -5
crates/maudit/src/assets/image.rs
··· 154 154 /// Get a placeholder for the image, which can be used for low-quality image placeholders (LQIP) or similar techniques. 155 155 /// 156 156 /// This uses the [ThumbHash](https://evanw.github.io/thumbhash/) algorithm to generate a very small placeholder image. 157 - pub fn placeholder(&self) -> ImagePlaceholder { 157 + /// 158 + /// Returns an error if the image cannot be loaded. 159 + pub fn placeholder(&self) -> Result<ImagePlaceholder, crate::errors::AssetError> { 158 160 get_placeholder(&self.path, self.cache.as_ref()) 159 161 } 160 162 ··· 258 260 } 259 261 } 260 262 261 - fn get_placeholder(path: &PathBuf, cache: Option<&ImageCache>) -> ImagePlaceholder { 263 + fn get_placeholder( 264 + path: &PathBuf, 265 + cache: Option<&ImageCache>, 266 + ) -> Result<ImagePlaceholder, crate::errors::AssetError> { 262 267 // Check cache first if provided 263 268 if let Some(cache) = cache 264 269 && let Some(cached) = cache.get_placeholder(path) 265 270 { 266 271 debug!("Using cached placeholder for {}", path.display()); 267 272 let thumbhash_base64 = base64::engine::general_purpose::STANDARD.encode(&cached.thumbhash); 268 - return ImagePlaceholder::new(cached.thumbhash, thumbhash_base64); 273 + return Ok(ImagePlaceholder::new(cached.thumbhash, thumbhash_base64)); 269 274 } 270 275 271 276 let total_start = Instant::now(); 272 277 273 278 let load_start = Instant::now(); 274 - let image = image::open(path).ok().unwrap(); 279 + let image = image::open(path).map_err(|e| crate::errors::AssetError::ImageLoadFailed { 280 + path: path.clone(), 281 + source: e, 282 + })?; 275 283 let (width, height) = image.dimensions(); 276 284 let (width, height) = (width as usize, height as usize); 277 285 debug!( ··· 329 337 cache.cache_placeholder(path, thumb_hash.clone()); 330 338 } 331 339 332 - ImagePlaceholder::new(thumb_hash, thumbhash_base64) 340 + Ok(ImagePlaceholder::new(thumb_hash, thumbhash_base64)) 333 341 } 334 342 335 343 /// Port of https://github.com/evanw/thumbhash/blob/a652ce6ed691242f459f468f0a8756cda3b90a82/js/thumbhash.js#L234 ··· 516 524 ).into() 517 525 } 518 526 } 527 + 528 + #[cfg(test)] 529 + mod tests { 530 + use crate::errors::AssetError; 531 + 532 + use super::*; 533 + use std::{error::Error, path::PathBuf}; 534 + 535 + #[test] 536 + fn test_placeholder_with_missing_file() { 537 + let nonexistent_path = PathBuf::from("/this/file/does/not/exist.png"); 538 + 539 + let result = get_placeholder(&nonexistent_path, None); 540 + 541 + assert!(result.is_err()); 542 + if let Err(AssetError::ImageLoadFailed { path, .. }) = result { 543 + assert_eq!(path, nonexistent_path); 544 + } else { 545 + panic!("Expected ImageLoadFailed error"); 546 + } 547 + } 548 + 549 + #[test] 550 + fn test_placeholder_with_valid_image() { 551 + let temp_dir = tempfile::tempdir().unwrap(); 552 + let image_path = temp_dir.path().join("test.png"); 553 + 554 + // Create a minimal valid 1x1 PNG file using the image crate to ensure correct CRCs 555 + let img = image::ImageBuffer::<image::Rgba<u8>, _>::from_fn(1, 1, |_x, _y| { 556 + image::Rgba([255, 0, 0, 255]) 557 + }); 558 + img.save(&image_path).unwrap(); 559 + 560 + let result = get_placeholder(&image_path, None); 561 + 562 + if let Err(e) = &result { 563 + eprintln!("get_placeholder failed: {:?}", e.source()); 564 + } 565 + 566 + assert!(result.is_ok()); 567 + let placeholder = result.unwrap(); 568 + assert!(!placeholder.thumbhash.is_empty()); 569 + assert!(!placeholder.thumbhash_base64.is_empty()); 570 + } 571 + }
+167 -46
crates/maudit/src/assets.rs
··· 432 432 } 433 433 434 434 fn make_filename(path: &Path, hash: &String, extension: Option<&str>) -> PathBuf { 435 - let file_stem = path.file_stem().unwrap(); 436 - let sanitized_stem = sanitize_filename::default_sanitize_file_name(file_stem.to_str().unwrap()); 435 + let file_stem = path.file_stem().and_then(|s| s.to_str()).unwrap_or("asset"); 436 + 437 + let sanitized_stem = sanitize_filename::default_sanitize_file_name(file_stem); 437 438 438 439 let mut filename = PathBuf::new(); 439 440 filename.push(format!("{}.{}", sanitized_stem, hash)); ··· 532 533 533 534 #[cfg(test)] 534 535 mod tests { 535 - use super::*; 536 - use std::env; 536 + use std::path::PathBuf; 537 + 538 + use crate::{ 539 + AssetHashingStrategy, 540 + assets::{ 541 + Asset, ImageFormat, ImageOptions, RouteAssets, RouteAssetsOptions, StyleOptions, 542 + make_filename, 543 + }, 544 + }; 537 545 538 - fn setup_temp_dir() -> PathBuf { 539 - // Create a temporary directory and test files 540 - let temp_dir = env::temp_dir().join("maudit_test"); 541 - std::fs::create_dir_all(&temp_dir).unwrap(); 546 + fn setup_temp_dir() -> tempfile::TempDir { 547 + let temp_dir = tempfile::tempdir().unwrap(); 542 548 543 - std::fs::write(temp_dir.join("style.css"), "body { background: red; }").unwrap(); 544 - std::fs::write(temp_dir.join("script.js"), "console.log('Hello, world!');").unwrap(); 545 - std::fs::write(temp_dir.join("image.png"), b"").unwrap(); 549 + std::fs::write( 550 + temp_dir.path().join("style.css"), 551 + "body { background: red; }", 552 + ) 553 + .unwrap(); 554 + std::fs::write( 555 + temp_dir.path().join("script.js"), 556 + "console.log('Hello, world!');", 557 + ) 558 + .unwrap(); 559 + std::fs::write(temp_dir.path().join("image.png"), b"").unwrap(); 546 560 temp_dir 547 561 } 548 562 ··· 550 564 fn test_add_style() { 551 565 let temp_dir = setup_temp_dir(); 552 566 let mut page_assets = RouteAssets::default(); 553 - page_assets.add_style(temp_dir.join("style.css")).unwrap(); 567 + page_assets 568 + .add_style(temp_dir.path().join("style.css")) 569 + .unwrap(); 554 570 555 571 assert!(page_assets.styles.len() == 1); 556 572 } ··· 561 577 let mut page_assets = RouteAssets::default(); 562 578 563 579 page_assets 564 - .include_style(temp_dir.join("style.css")) 580 + .include_style(temp_dir.path().join("style.css")) 565 581 .unwrap(); 566 582 567 583 assert!(page_assets.styles.len() == 1); ··· 573 589 let temp_dir = setup_temp_dir(); 574 590 let mut page_assets = RouteAssets::default(); 575 591 576 - page_assets.add_script(temp_dir.join("script.js")).unwrap(); 592 + page_assets 593 + .add_script(temp_dir.path().join("script.js")) 594 + .unwrap(); 577 595 assert!(page_assets.scripts.len() == 1); 578 596 } 579 597 ··· 583 601 let mut page_assets = RouteAssets::default(); 584 602 585 603 page_assets 586 - .include_script(temp_dir.join("script.js")) 604 + .include_script(temp_dir.path().join("script.js")) 587 605 .unwrap(); 588 606 589 607 assert!(page_assets.scripts.len() == 1); ··· 595 613 let temp_dir = setup_temp_dir(); 596 614 let mut page_assets = RouteAssets::default(); 597 615 598 - page_assets.add_image(temp_dir.join("image.png")).unwrap(); 616 + page_assets 617 + .add_image(temp_dir.path().join("image.png")) 618 + .unwrap(); 599 619 assert!(page_assets.images.len() == 1); 600 620 } 601 621 ··· 604 624 let temp_dir = setup_temp_dir(); 605 625 let mut page_assets = RouteAssets::default(); 606 626 607 - let image = page_assets.add_image(temp_dir.join("image.png")).unwrap(); 627 + let image = page_assets 628 + .add_image(temp_dir.path().join("image.png")) 629 + .unwrap(); 608 630 assert_eq!(image.url().chars().next(), Some('/')); 609 631 610 - let script = page_assets.add_script(temp_dir.join("script.js")).unwrap(); 632 + let script = page_assets 633 + .add_script(temp_dir.path().join("script.js")) 634 + .unwrap(); 611 635 assert_eq!(script.url().chars().next(), Some('/')); 612 636 613 - let style = page_assets.add_style(temp_dir.join("style.css")).unwrap(); 637 + let style = page_assets 638 + .add_style(temp_dir.path().join("style.css")) 639 + .unwrap(); 614 640 assert_eq!(style.url().chars().next(), Some('/')); 615 641 } 616 642 ··· 619 645 let temp_dir = setup_temp_dir(); 620 646 let mut page_assets = RouteAssets::default(); 621 647 622 - let image = page_assets.add_image(temp_dir.join("image.png")).unwrap(); 648 + let image = page_assets 649 + .add_image(temp_dir.path().join("image.png")) 650 + .unwrap(); 623 651 assert!(image.url().contains(&image.hash)); 624 652 625 - let script = page_assets.add_script(temp_dir.join("script.js")).unwrap(); 653 + let script = page_assets 654 + .add_script(temp_dir.path().join("script.js")) 655 + .unwrap(); 626 656 assert!(script.url().contains(&script.hash)); 627 657 628 - let style = page_assets.add_style(temp_dir.join("style.css")).unwrap(); 658 + let style = page_assets 659 + .add_style(temp_dir.path().join("style.css")) 660 + .unwrap(); 629 661 assert!(style.url().contains(&style.hash)); 630 662 } 631 663 ··· 634 666 let temp_dir = setup_temp_dir(); 635 667 let mut page_assets = RouteAssets::default(); 636 668 637 - let image = page_assets.add_image(temp_dir.join("image.png")).unwrap(); 669 + let image = page_assets 670 + .add_image(temp_dir.path().join("image.png")) 671 + .unwrap(); 638 672 assert!(image.build_path().to_string_lossy().contains(&image.hash)); 639 673 640 - let script = page_assets.add_script(temp_dir.join("script.js")).unwrap(); 674 + let script = page_assets 675 + .add_script(temp_dir.path().join("script.js")) 676 + .unwrap(); 641 677 assert!(script.build_path().to_string_lossy().contains(&script.hash)); 642 678 643 - let style = page_assets.add_style(temp_dir.join("style.css")).unwrap(); 679 + let style = page_assets 680 + .add_style(temp_dir.path().join("style.css")) 681 + .unwrap(); 644 682 assert!(style.build_path().to_string_lossy().contains(&style.hash)); 645 683 } 646 684 647 685 #[test] 648 686 fn test_image_hash_different_options() { 649 687 let temp_dir = setup_temp_dir(); 650 - let image_path = temp_dir.join("image.png"); 688 + let image_path = temp_dir.path().join("image.png"); 651 689 652 - // Create a simple test PNG (1x1 transparent pixel) 653 - let png_data = [ 654 - 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 655 - 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 656 - 0x00, 0x1F, 0x15, 0xC4, 0x89, 0x00, 0x00, 0x00, 0x0B, 0x49, 0x44, 0x41, 0x54, 0x78, 657 - 0x9C, 0x63, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x01, 0x0D, 0x0A, 0x2D, 0xB4, 0x00, 658 - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, 659 - ]; 660 - std::fs::write(&image_path, png_data).unwrap(); 690 + let img = image::ImageBuffer::<image::Rgba<u8>, _>::from_fn(1, 1, |_x, _y| { 691 + image::Rgba([255, 0, 0, 255]) 692 + }); 693 + img.save(&image_path).unwrap(); 661 694 662 - let mut page_assets = RouteAssets::default(); 695 + let mut page_assets = RouteAssets::new( 696 + &RouteAssetsOptions { 697 + hashing_strategy: AssetHashingStrategy::Precise, 698 + ..Default::default() 699 + }, 700 + None, 701 + ); 663 702 664 703 // Test that different options produce different hashes 665 704 let image_default = page_assets.add_image(&image_path).unwrap(); ··· 716 755 #[test] 717 756 fn test_image_hash_same_options() { 718 757 let temp_dir = setup_temp_dir(); 719 - let image_path = temp_dir.join("image.png"); 758 + let image_path = temp_dir.path().join("image.png"); 720 759 721 760 // Create a simple test PNG (1x1 transparent pixel) 722 761 let png_data = [ ··· 728 767 ]; 729 768 std::fs::write(&image_path, png_data).unwrap(); 730 769 731 - let mut page_assets = RouteAssets::default(); 770 + let mut page_assets = RouteAssets::new( 771 + &RouteAssetsOptions { 772 + hashing_strategy: AssetHashingStrategy::Precise, 773 + ..Default::default() 774 + }, 775 + None, 776 + ); 732 777 733 778 // Same options should produce same hash 734 779 let image1 = page_assets ··· 762 807 #[test] 763 808 fn test_style_hash_different_options() { 764 809 let temp_dir = setup_temp_dir(); 765 - let style_path = temp_dir.join("style.css"); 810 + let style_path = temp_dir.path().join("style.css"); 766 811 767 - let mut page_assets = RouteAssets::new(&RouteAssetsOptions::default(), None); 812 + let mut page_assets = RouteAssets::new( 813 + &RouteAssetsOptions { 814 + hashing_strategy: AssetHashingStrategy::Precise, 815 + ..Default::default() 816 + }, 817 + None, 818 + ); 768 819 769 820 // Test that different tailwind options produce different hashes 770 821 let style_default = page_assets.add_style(&style_path).unwrap(); ··· 784 835 785 836 // Create two identical files with different paths 786 837 let content = "body { background: blue; }"; 787 - let style1_path = temp_dir.join("style1.css"); 788 - let style2_path = temp_dir.join("style2.css"); 838 + let style1_path = temp_dir.path().join("style1.css"); 839 + let style2_path = temp_dir.path().join("style2.css"); 789 840 790 841 std::fs::write(&style1_path, content).unwrap(); 791 842 std::fs::write(&style2_path, content).unwrap(); 792 843 793 - let mut page_assets = RouteAssets::new(&RouteAssetsOptions::default(), None); 844 + let mut page_assets = RouteAssets::new( 845 + &RouteAssetsOptions { 846 + hashing_strategy: AssetHashingStrategy::Precise, 847 + ..Default::default() 848 + }, 849 + None, 850 + ); 794 851 795 852 let style1 = page_assets.add_style(&style1_path).unwrap(); 796 853 let style2 = page_assets.add_style(&style2_path).unwrap(); ··· 804 861 #[test] 805 862 fn test_hash_includes_content() { 806 863 let temp_dir = setup_temp_dir(); 807 - let style_path = temp_dir.join("dynamic_style.css"); 864 + let style_path = temp_dir.path().join("dynamic_style.css"); 808 865 809 - let assets_options = RouteAssetsOptions::default(); 810 - let mut page_assets = RouteAssets::new(&assets_options, None); 866 + let mut page_assets = RouteAssets::new( 867 + &RouteAssetsOptions { 868 + hashing_strategy: AssetHashingStrategy::Precise, 869 + ..Default::default() 870 + }, 871 + None, 872 + ); 811 873 812 874 // Write first content and get hash 813 875 std::fs::write(&style_path, "body { background: red; }").unwrap(); ··· 823 885 hash1, hash2, 824 886 "Different content should produce different hashes" 825 887 ); 888 + } 889 + 890 + #[test] 891 + fn test_make_filename_normal_path() { 892 + let path = PathBuf::from("/foo/bar/test.png"); 893 + let hash = "abc12".to_string(); 894 + 895 + let filename = make_filename(&path, &hash, Some("png")); 896 + 897 + // Format is: stem.hash with extension hash.ext 898 + assert_eq!(filename.to_string_lossy(), "test.abc12.png"); 899 + } 900 + 901 + #[test] 902 + fn test_make_filename_no_extension() { 903 + let path = PathBuf::from("/foo/bar/test"); 904 + let hash = "abc12".to_string(); 905 + 906 + let filename = make_filename(&path, &hash, None); 907 + 908 + assert_eq!(filename.to_string_lossy(), "test.abc12"); 909 + } 910 + 911 + #[test] 912 + fn test_make_filename_fallback_for_root_path() { 913 + // Root path has no file stem 914 + let path = PathBuf::from("/"); 915 + let hash = "abc12".to_string(); 916 + 917 + let filename = make_filename(&path, &hash, Some("css")); 918 + 919 + // Should fallback to "asset" 920 + assert_eq!(filename.to_string_lossy(), "asset.abc12.css"); 921 + } 922 + 923 + #[test] 924 + fn test_make_filename_fallback_for_dotdot_path() { 925 + // Path ending with ".." has no file stem 926 + let path = PathBuf::from("/foo/.."); 927 + let hash = "xyz99".to_string(); 928 + 929 + let filename = make_filename(&path, &hash, Some("js")); 930 + 931 + // Should fallback to "asset" 932 + assert_eq!(filename.to_string_lossy(), "asset.xyz99.js"); 933 + } 934 + 935 + #[test] 936 + fn test_make_filename_with_special_characters() { 937 + // Test that special characters get sanitized 938 + let path = PathBuf::from("/foo/test:file*.txt"); 939 + let hash = "def45".to_string(); 940 + 941 + let filename = make_filename(&path, &hash, Some("txt")); 942 + 943 + // Special characters should be replaced with underscores 944 + let result = filename.to_string_lossy(); 945 + assert!(result.contains("test_file_")); 946 + assert!(result.ends_with(".def45.txt")); 826 947 } 827 948 }
+2
crates/maudit/src/build.rs
··· 26 26 use log::{debug, info, trace, warn}; 27 27 use pathdiff::diff_paths; 28 28 use rolldown::{Bundler, BundlerOptions, InputItem, ModuleType}; 29 + use rolldown_plugin_replace::ReplacePlugin; 29 30 use rustc_hash::{FxHashMap, FxHashSet}; 30 31 31 32 use crate::assets::Asset; ··· 495 496 .collect::<Vec<PathBuf>>(), 496 497 }), 497 498 Arc::new(PrefetchPlugin {}), 499 + Arc::new(ReplacePlugin::new(FxHashMap::default())?), 498 500 ], 499 501 )?; 500 502
+3
crates/maudit/src/content/markdown/components.rs
··· 48 48 ShortcutUnknown, 49 49 Autolink, 50 50 Email, 51 + WikiLink(bool), 51 52 } 52 53 53 54 impl From<pulldown_cmark::LinkType> for LinkType { ··· 62 63 pulldown_cmark::LinkType::ShortcutUnknown => LinkType::ShortcutUnknown, 63 64 pulldown_cmark::LinkType::Autolink => LinkType::Autolink, 64 65 pulldown_cmark::LinkType::Email => LinkType::Email, 66 + pulldown_cmark::LinkType::WikiLink { has_pothole } => LinkType::WikiLink(has_pothole), 65 67 } 66 68 } 67 69 } ··· 84 86 LinkType::ShortcutUnknown => "shortcut_unknown", 85 87 LinkType::Autolink => "autolink", 86 88 LinkType::Email => "email", 89 + LinkType::WikiLink(_) => "wikilink", 87 90 } 88 91 } 89 92 }
+6
crates/maudit/src/errors.rs
··· 53 53 #[source] 54 54 source: std::io::Error, 55 55 }, 56 + #[error("Failed to load image for placeholder generation: {path}")] 57 + ImageLoadFailed { 58 + path: PathBuf, 59 + #[source] 60 + source: image::ImageError, 61 + }, 56 62 } 57 63 58 64 #[derive(Error, Debug)]
+17 -1
crates/maudit/src/routing.rs
··· 56 56 57 57 #[cfg(test)] 58 58 mod tests { 59 - use crate::routing::{ParameterDef, extract_params_from_raw_route}; 59 + use crate::routing::{ParameterDef, extract_params_from_raw_route, guess_if_route_is_endpoint}; 60 60 61 61 #[test] 62 62 fn test_extract_params() { ··· 123 123 }]; 124 124 125 125 assert_eq!(extract_params_from_raw_route(input), expected); 126 + } 127 + 128 + #[test] 129 + fn test_guess_if_route_is_endpoint() { 130 + // Routes with file extensions should be detected as endpoints 131 + assert!(guess_if_route_is_endpoint("/api/data.json")); 132 + assert!(guess_if_route_is_endpoint("/feed.xml")); 133 + assert!(guess_if_route_is_endpoint("/sitemap.xml")); 134 + assert!(guess_if_route_is_endpoint("/robots.txt")); 135 + assert!(guess_if_route_is_endpoint("/path/to/file.tar.gz")); 136 + assert!(guess_if_route_is_endpoint("/api/users/[id].json")); 137 + 138 + assert!(!guess_if_route_is_endpoint("/")); 139 + assert!(!guess_if_route_is_endpoint("/articles")); 140 + assert!(!guess_if_route_is_endpoint("/articles/[slug]")); 141 + assert!(!guess_if_route_is_endpoint("/blog/posts/[year]/[month]")); 126 142 } 127 143 }
+14 -14
crates/maudit-cli/Cargo.toml
··· 11 11 path = "src/main.rs" 12 12 13 13 [dependencies] 14 - chrono = "0.4.39" 15 - colored = "2.2.0" 16 - clap = { version = "4.5.23", features = ["derive"] } 14 + chrono = "0.4.43" 15 + colored = "3.1.1" 16 + clap = { version = "4.5.54", features = ["derive"] } 17 17 tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal", "process"] } 18 - axum = { version = "0.8.6", features = ["ws"] } 18 + axum = { version = "0.8.8", features = ["ws"] } 19 19 futures = "0.3" 20 - tower-http = { version = "0.6.6", features = ["fs", "trace"] } 20 + tower-http = { version = "0.6.8", features = ["fs", "trace"] } 21 21 tracing = "0.1" 22 22 tracing-subscriber = { version = "=0.3.19", features = ["env-filter", "chrono"] } 23 23 notify = "8.2.0" 24 - notify-debouncer-full = "0.6.0" 25 - inquire = "0.7.5" 26 - rand = "0.9.0" 24 + notify-debouncer-full = "0.7.0" 25 + inquire = "0.9.2" 26 + rand = "0.9.2" 27 27 spinach = "3" 28 - ureq = "3.0.5" 29 - tar = "0.4.43" 30 - toml_edit = "0.22.23" 31 - local-ip-address = "0.6.3" 32 - flate2 = "1.0.35" 28 + ureq = "3.1.4" 29 + tar = "0.4.44" 30 + toml_edit = "0.24.0" 31 + local-ip-address = "0.6.9" 32 + flate2 = "1.1.8" 33 33 quanta = "0.12.6" 34 34 serde_json = "1.0" 35 35 tokio-util = "0.7" 36 - cargo_metadata = "0.23.0" 36 + cargo_metadata = "0.23.1"
+5 -1
crates/maudit-cli/src/dev.rs
··· 20 20 21 21 use crate::dev::build::BuildManager; 22 22 23 - pub async fn start_dev_env(cwd: &str, host: bool, port: Option<u16>) -> Result<(), Box<dyn std::error::Error>> { 23 + pub async fn start_dev_env( 24 + cwd: &str, 25 + host: bool, 26 + port: Option<u16>, 27 + ) -> Result<(), Box<dyn std::error::Error>> { 24 28 let start_time = Instant::now(); 25 29 info!(name: "dev", "Preparing dev environmentโ€ฆ"); 26 30
+3
e2e/README.md
··· 13 13 ## Running Tests 14 14 15 15 The tests will automatically: 16 + 16 17 1. Build the prefetch.js bundle (via `cargo xtask build-maudit-js`) 17 18 2. Start the Maudit dev server on the test fixture site 18 19 3. Run the tests ··· 46 47 ## Features Tested 47 48 48 49 ### Basic Prefetch 50 + 49 51 - Creating link elements with `rel="prefetch"` 50 52 - Preventing duplicate prefetches 51 53 - Skipping current page prefetch 52 54 - Blocking cross-origin prefetches 53 55 54 56 ### Prerendering (Chromium only) 57 + 55 58 - Creating `<script type="speculationrules">` elements 56 59 - Different eagerness levels (immediate, eager, moderate, conservative) 57 60 - Fallback to link prefetch on non-Chromium browsers
+9
e2e/fixtures/hot-reload/Cargo.toml
··· 1 + [package] 2 + name = "fixtures-hot-reload" 3 + version = "0.1.0" 4 + edition = "2024" 5 + publish = false 6 + 7 + [dependencies] 8 + maudit.workspace = true 9 + maud.workspace = true
+14
e2e/fixtures/hot-reload/src/main.rs
··· 1 + use maudit::{BuildOptions, BuildOutput, content_sources, coronate, routes}; 2 + 3 + mod pages { 4 + mod index; 5 + pub use index::Index; 6 + } 7 + 8 + fn main() -> Result<BuildOutput, Box<dyn std::error::Error>> { 9 + coronate( 10 + routes![pages::Index], 11 + content_sources![], 12 + BuildOptions::default(), 13 + ) 14 + }
+30
e2e/fixtures/hot-reload/src/pages/index.rs
··· 1 + use maud::html; 2 + use maudit::route::prelude::*; 3 + 4 + #[route("/")] 5 + pub struct Index; 6 + 7 + impl Route for Index { 8 + fn render(&self, _ctx: &mut PageContext) -> impl Into<RenderResult> { 9 + Ok(html! { 10 + html { 11 + head { 12 + title { "Hot Reload Test" } 13 + } 14 + body { 15 + h1 id="title" { "Original Title" } 16 + div id="content" { 17 + p id="message" { "Original message" } 18 + ul id="list" { 19 + li { "Item 1" } 20 + li { "Item 2" } 21 + } 22 + } 23 + footer { 24 + p { "Footer content" } 25 + } 26 + } 27 + } 28 + }) 29 + } 30 + }
+2 -1
e2e/fixtures/prefetch-prerender/Cargo.toml
··· 1 1 [package] 2 - name = "prefetch-prerender" 2 + name = "fixtures-prefetch-prerender" 3 3 version = "0.1.0" 4 4 edition = "2024" 5 + publish = false 5 6 6 7 [dependencies] 7 8 maudit.workspace = true
+1 -1
e2e/fixtures/prefetch-prerender/src/main.rs
··· 1 - use maudit::{content_sources, coronate, routes, BuildOptions, BuildOutput}; 1 + use maudit::{BuildOptions, BuildOutput, content_sources, coronate, routes}; 2 2 3 3 mod pages { 4 4 mod about;
+58
e2e/tests/hot-reload.spec.ts
··· 1 + import { expect } from "@playwright/test"; 2 + import { createTestWithFixture } from "./test-utils"; 3 + import { readFileSync, writeFileSync } from "node:fs"; 4 + import { resolve, dirname } from "node:path"; 5 + import { fileURLToPath } from "node:url"; 6 + 7 + const __filename = fileURLToPath(import.meta.url); 8 + const __dirname = dirname(__filename); 9 + 10 + // Create test instance with hot-reload fixture 11 + const test = createTestWithFixture("hot-reload"); 12 + 13 + test.describe.configure({ mode: "serial" }); 14 + 15 + test.describe("Hot Reload", () => { 16 + const fixturePath = resolve(__dirname, "..", "fixtures", "hot-reload"); 17 + const indexPath = resolve(fixturePath, "src", "pages", "index.rs"); 18 + let originalContent: string; 19 + 20 + test.beforeAll(async () => { 21 + // Save original content 22 + originalContent = readFileSync(indexPath, "utf-8"); 23 + }); 24 + 25 + test.afterEach(async () => { 26 + // Restore original content after each test 27 + writeFileSync(indexPath, originalContent, "utf-8"); 28 + // Wait a bit for the rebuild 29 + await new Promise((resolve) => setTimeout(resolve, 2000)); 30 + }); 31 + 32 + test.afterAll(async () => { 33 + // Restore original content 34 + writeFileSync(indexPath, originalContent, "utf-8"); 35 + }); 36 + 37 + test("should show updated content after file changes", async ({ page, devServer }) => { 38 + await page.goto(devServer.url); 39 + 40 + // Verify initial content 41 + await expect(page.locator("#title")).toHaveText("Original Title"); 42 + 43 + // Prepare to wait for actual reload by waiting for the same URL to reload 44 + const currentUrl = page.url(); 45 + 46 + // Modify the file 47 + const modifiedContent = originalContent.replace( 48 + 'h1 id="title" { "Original Title" }', 49 + 'h1 id="title" { "Another Update" }', 50 + ); 51 + writeFileSync(indexPath, modifiedContent, "utf-8"); 52 + 53 + // Wait for the page to actually reload on the same URL 54 + await page.waitForURL(currentUrl, { timeout: 15000 }); 55 + // Verify the updated content 56 + await expect(page.locator("#title")).toHaveText("Another Update", { timeout: 15000 }); 57 + }); 58 + });
+3 -1
e2e/tests/prefetch.spec.ts
··· 1 - import { test, expect } from "./test-utils"; 1 + import { createTestWithFixture, expect } from "./test-utils"; 2 2 import { prefetchScript } from "./utils"; 3 + 4 + const test = createTestWithFixture("prefetch-prerender"); 3 5 4 6 test.describe("Prefetch", () => { 5 7 test("should create prefetch via speculation rules on Chromium or link element elsewhere", async ({
+3 -1
e2e/tests/prerender.spec.ts
··· 1 - import { test, expect } from "./test-utils"; 1 + import { createTestWithFixture, expect } from "./test-utils"; 2 2 import { prefetchScript } from "./utils"; 3 + 4 + const test = createTestWithFixture("prefetch-prerender"); 3 5 4 6 test.describe("Prefetch - Speculation Rules (Prerender)", () => { 5 7 test("should create speculation rules on Chromium or link prefetch elsewhere when prerender is enabled", async ({
+44 -23
e2e/tests/test-utils.ts
··· 1 - import { spawn, execFile, type ChildProcess } from "node:child_process"; 2 - import { join, resolve, dirname } from "node:path"; 1 + import { spawn } from "node:child_process"; 2 + import { resolve, dirname } from "node:path"; 3 3 import { existsSync } from "node:fs"; 4 4 import { fileURLToPath } from "node:url"; 5 5 import { test as base } from "@playwright/test"; ··· 136 136 } 137 137 138 138 // Worker-scoped server pool - one server per worker, shared across all tests in that worker 139 - const workerServers = new Map<number, DevServer>(); 139 + // Key format: "workerIndex-fixtureName" 140 + const workerServers = new Map<string, DevServer>(); 140 141 141 - // Extend Playwright's test with a devServer fixture 142 - export const test = base.extend<{ devServer: DevServer }>({ 143 - devServer: async ({}, use, testInfo) => { 144 - // Use worker index to get or create a server for this worker 145 - const workerIndex = testInfo.workerIndex; 142 + /** 143 + * Create a test instance with a devServer fixture for a specific fixture. 144 + * This allows each test file to use a different fixture while sharing the same pattern. 145 + * 146 + * @param fixtureName - Name of the fixture directory under e2e/fixtures/ 147 + * @param basePort - Starting port number (default: 1864). Each worker gets basePort + workerIndex 148 + * 149 + * @example 150 + * ```ts 151 + * import { createTestWithFixture } from "./test-utils"; 152 + * const test = createTestWithFixture("my-fixture"); 153 + * 154 + * test("my test", async ({ devServer }) => { 155 + * // devServer is automatically started for "my-fixture" 156 + * }); 157 + * ``` 158 + */ 159 + export function createTestWithFixture(fixtureName: string, basePort = 1864) { 160 + return base.extend<{ devServer: DevServer }>({ 161 + // oxlint-disable-next-line no-empty-pattern 162 + devServer: async ({}, use, testInfo) => { 163 + // Use worker index to get or create a server for this worker 164 + const workerIndex = testInfo.workerIndex; 165 + const serverKey = `${workerIndex}-${fixtureName}`; 146 166 147 - let server = workerServers.get(workerIndex); 167 + let server = workerServers.get(serverKey); 148 168 149 - if (!server) { 150 - // Assign unique port based on worker index 151 - const port = 1864 + workerIndex; 169 + if (!server) { 170 + // Assign unique port based on worker index 171 + const port = basePort + workerIndex; 152 172 153 - server = await startDevServer({ 154 - fixture: "prefetch-prerender", 155 - port, 156 - }); 173 + server = await startDevServer({ 174 + fixture: fixtureName, 175 + port, 176 + }); 157 177 158 - workerServers.set(workerIndex, server); 159 - } 178 + workerServers.set(serverKey, server); 179 + } 160 180 161 - await use(server); 181 + await use(server); 162 182 163 - // Don't stop the server here - it stays alive for all tests in this worker 164 - // Playwright will clean up when the worker exits 165 - }, 166 - }); 183 + // Don't stop the server here - it stays alive for all tests in this worker 184 + // Playwright will clean up when the worker exits 185 + }, 186 + }); 187 + } 167 188 168 189 export { expect } from "@playwright/test";
+1 -1
e2e/tests/utils.ts
··· 4 4 // Find the actual prefetch bundle file (hash changes on each build) 5 5 const distDir = join(process.cwd(), "../crates/maudit/js/dist"); 6 6 const prefetchFile = readdirSync(distDir).find( 7 - (f) => f.startsWith("prefetch-") && f.endsWith(".js"), 7 + (f) => f.startsWith("prefetch") && f.endsWith(".js"), 8 8 ); 9 9 if (!prefetchFile) throw new Error("Could not find prefetch bundle"); 10 10
+1 -1
examples/blog/Cargo.toml
··· 10 10 [dependencies] 11 11 maudit = { workspace = true } 12 12 maud = "0.27.0" 13 - serde = { version = "1.0.216" } 13 + serde = { version = "1.0.228" }
+1 -1
examples/library/Cargo.toml
··· 10 10 [dependencies] 11 11 maudit = { workspace = true } 12 12 maud = "0.27.0" 13 - serde = { version = "1.0.216" } 13 + serde = { version = "1.0.228" }
+2 -1
package.json
··· 12 12 "lint:fix": "oxlint --fix --type-aware && cargo clippy --fix --allow-dirty --allow-staged", 13 13 "format": "pnpm run format:ts && pnpm run format:rs", 14 14 "format:ts": "oxfmt", 15 - "format:rs": "cargo fmt" 15 + "format:rs": "cargo fmt", 16 + "test:e2e": "cd e2e && pnpm run test" 16 17 }, 17 18 "dependencies": { 18 19 "@tailwindcss/cli": "^4.1.18",
+1 -1
website/Cargo.toml
··· 8 8 maudit = { workspace = true } 9 9 maud = { workspace = true } 10 10 serde = { workspace = true } 11 - chrono = { version = "0.4.42", features = ["serde"] } 11 + chrono = { version = "0.4.43", features = ["serde"] }
+1 -1
website/content/docs/content.md
··· 214 214 215 215 ```markdown 216 216 --- 217 - title: {{ enhance title="Super Title" /}} 217 + title: { { enhance title="Super Title" / } } 218 218 --- 219 219 220 220 Here's an image with a caption:
+1 -1
website/content/docs/images.md
··· 96 96 impl Route for ImagePage { 97 97 fn render(&self, ctx: &mut PageContext) -> impl Into<RenderResult> { 98 98 let image = ctx.assets.add_image("path/to/image.jpg")?; 99 - let placeholder = image.placeholder(); 99 + let placeholder = image.placeholder()?; 100 100 101 101 Ok(format!("<img src=\"{}\" alt=\"Image with placeholder\" style=\"background-image: url('{}'); background-size: cover;\" />", image.url(), placeholder.data_uri())) 102 102 }
+1 -1
website/content/docs/prefetching.md
··· 49 49 50 50 Note that prerendering, unlike prefetching, may require rethinking how the JavaScript on your pages works, as it'll run JavaScript from pages that the user hasn't visited yet. For example, this might result in analytics reporting incorrect page views. 51 51 52 - ## Possible risks 52 + ## Possible risks 53 53 54 54 Prefetching pages in static websites is typically always safe. In more traditional apps, an issue can arise if your pages cause side effects to happen on the server. For instance, if you were to prefetch `/logout`, your user might get disconnected on hover, or worse as soon as the log out link appear in the viewport. In modern times, it is typically not recommended to have links cause such side effects anyway, reducing the risk of this happening. 55 55
+2 -2
website/content/news/2026-in-the-cursed-lands.md
··· 55 55 impl Route for ImagePage { 56 56 fn render(&self, ctx: &mut PageContext) -> impl Into<RenderResult> { 57 57 let image = ctx.assets.add_image("path/to/image.jpg")?; 58 - let placeholder = image.placeholder(); 58 + let placeholder = image.placeholder()?; 59 59 60 60 Ok(format!("<img src=\"{}\" alt=\"Image with placeholder\" style=\"background-image: url('{}'); background-size: cover;\" />", image.url(), placeholder.data_uri())) 61 61 } ··· 70 70 71 71 ### Shortcodes 72 72 73 - Embedding a YouTube video typically means copying a long, ugly iframe tag and configuring several attributes to ensure proper rendering. It'd be nice to have something friendlier, a code that would be short, you will. 73 + Embedding a YouTube video typically means copying a long, ugly iframe tag and configuring several attributes to ensure proper rendering. It'd be nice to have something friendlier, a code that would be short, if you will. 74 74 75 75 ```md 76 76 Here's my cool video:
+1 -1
xtask/Cargo.toml
··· 5 5 publish = false 6 6 7 7 [dependencies] 8 - rolldown = { package = "brk_rolldown", version = "0.2.3" } 8 + rolldown = { package = "brk_rolldown", version = "0.8.0" } 9 9 tokio = { version = "1", features = ["rt"] }
+18 -2
xtask/src/main.rs
··· 110 110 // Configure Rolldown bundler input 111 111 let input_items = vec![ 112 112 InputItem { 113 - name: Some("prefetch".to_string()), 113 + name: None, 114 114 import: js_src_dir.join("prefetch.ts").to_string_lossy().to_string(), 115 115 }, 116 116 InputItem { 117 - name: Some("hover".to_string()), 117 + name: None, 118 118 import: js_src_dir 119 119 .join("prefetch") 120 120 .join("hover.ts") 121 + .to_string_lossy() 122 + .to_string(), 123 + }, 124 + InputItem { 125 + name: None, 126 + import: js_src_dir 127 + .join("prefetch") 128 + .join("tap.ts") 129 + .to_string_lossy() 130 + .to_string(), 131 + }, 132 + InputItem { 133 + name: None, 134 + import: js_src_dir 135 + .join("prefetch") 136 + .join("viewport.ts") 121 137 .to_string_lossy() 122 138 .to_string(), 123 139 },