diff --git a/bun.lock b/bun.lock index e4702699..df0e5e53 100644 --- a/bun.lock +++ b/bun.lock @@ -253,7 +253,7 @@ }, "packages/captcha": { "name": "@wrnexus/captcha", - "version": "0.8.8", + "version": "0.8.9", "dependencies": { "@wrnexus/core": "workspace:*", "@wrnexus/plugin": "workspace:*", @@ -268,7 +268,7 @@ }, "packages/cli": { "name": "@wrnexus/cli", - "version": "0.8.8", + "version": "0.8.9", "bin": { "wrnexus": "src/index.ts", }, @@ -617,7 +617,7 @@ }, "packages/ui": { "name": "@wrnexus/ui", - "version": "0.8.8", + "version": "0.8.9", "dependencies": { "@wrnexus/core": "workspace:*", }, diff --git a/docs/ui-visual-contract-0.8.json b/docs/ui-visual-contract-0.8.json index 8e099d82..7e19d975 100644 --- a/docs/ui-visual-contract-0.8.json +++ b/docs/ui-visual-contract-0.8.json @@ -2,56 +2,56 @@ "schemaVersion": 1, "releaseLine": "0.8", "artifacts": { - "packages/ui/components/Accordion.wrn": "285df0aa50733618afb1b82aa125a67030d3af4bd8b9de52bc2e6366cea871de", - "packages/ui/components/AdvancedSelect.wrn": "e8666638204f9eb044ee6f163d6af432b119bf7f39d9df20243cfae471d20bcd", + "packages/ui/components/Accordion.wrn": "6532417153592cf60ab437a3b4e500176b14394dd66756d47df087d8c4f863ef", + "packages/ui/components/AdvancedSelect.wrn": "c3779c89ce309de8c1e2fbc02a39472fffd6fb10c2b83db0104c6d1135b87082", "packages/ui/components/AnnouncementBar.wrn": "903bfd9421a7350c923ace3315cedc5763fe3e6b7b54b660a0f26281d46a8754", - "packages/ui/components/AuthForm.wrn": "ec8796a67320afa2fb2070edba194382d1ab0a00cbd574f936a502da819d00fa", - "packages/ui/components/AuthSplitLayout.wrn": "675c6ac9b07e0e9c5d6572f30028dda2391f9c6599b45945eb626df056a5b987", - "packages/ui/components/AvatarGroup.wrn": "85dd6c64f8064d0980bf4157963bf366410c2ba391fd65df86a54b1a336f43a4", + "packages/ui/components/AuthForm.wrn": "bb5ac1ac8d981d490652eba5d4edf3612980470aa8b94bf4995cec1aa2db4bfc", + "packages/ui/components/AuthSplitLayout.wrn": "2a04cabb8bf2bda8739e2aba6dcfd29713efa7b51777f99b03dad1645b6ddae1", + "packages/ui/components/AvatarGroup.wrn": "737cd929e3bcd9f9b2fe1b602ae17c1fbf584bd8a1949ce36b65427931e27abc", "packages/ui/components/BackToTop.wrn": "b12c56ec8b7aabad68cbdc47f4b3237e2c21a61398f0aa51f9add6229b7357cd", - "packages/ui/components/Blockquote.wrn": "6f91cee9538c11858aaeb98ef1a098a814a6e319e3777e59cecd2de078b3beaf", + "packages/ui/components/Blockquote.wrn": "70bb7f0da2743a44d38d38daebe09637c2653ccb8454d78a226c034cfece31d6", "packages/ui/components/Breadcrumb.wrn": "5ab85d273ce72e4d5b87907975bb33f0249a34f2f87f01dc0812e827f775eed9", - "packages/ui/components/ButtonGroup.wrn": "0bb23d927e03926cc303498bc4ac1ab098343782082ac1fceeb2402702945842", + "packages/ui/components/ButtonGroup.wrn": "be6675ae06b9f3285187e04d8d3312cf14cf4d24fe9bc0f78b2f796b6819ff69", "packages/ui/components/CTASection.wrn": "2d2241d4f1018cfd2f8ea1ddd5fa8c8fcb8d1bbb2d4e4498cb9f39ff47a3801c", - "packages/ui/components/Card.wrn": "ba1b577ae4ffa9bd93c1e6a650ce90745df3f78cd6ff9ee85530e32dab56860a", - "packages/ui/components/Carousel.wrn": "0d39e17a623fb623022f48e79ea1ab9f268e2eb359c491609c137f711a1a3ffc", + "packages/ui/components/Card.wrn": "db5f313be0d057dac8c2d693574d15a146296c0aec6e41ec58b96966e45186d5", + "packages/ui/components/Carousel.wrn": "72e216882e3d1d744edd0d7697ce5810353a7cc0c386022452546bd959ff351d", "packages/ui/components/Chart.wrn": "d2cedd0e02818d0908708c2d07a495c629fad13fa021a2e035d5023dc5c367de", - "packages/ui/components/ChatBubble.wrn": "c46b9aef38f54e6243663046fe1b18ba6f9223cbe9b479d9335f96f217d401cc", + "packages/ui/components/ChatBubble.wrn": "c7c0ffcf732161330cc7fba79775ac829264b16731c980d3ec0820fc3ac8f9a7", "packages/ui/components/Clipboard.wrn": "03fcfb9786008fd7fb0a7719c3279711253afc5bbb9b0262b805dd553c44da8a", - "packages/ui/components/Collapse.wrn": "8869ff4a39541b7e0d538e2b63b9a3dcdcfcd4055fa362519c7e73f164f1be9d", - "packages/ui/components/ColorPicker.wrn": "02f5744c3eb984de4b24de26fbfd3f69021633d4b0b33aceeba84df32f6a7284", + "packages/ui/components/Collapse.wrn": "90220ce36529d2b44bc45b1b265373462b5871a4e492be127f52743fa0619b0b", + "packages/ui/components/ColorPicker.wrn": "602752f2ad7f6b092987ccae9c35a0a413a6261d63d6e88f279ee939d0ec4049", "packages/ui/components/Columns.wrn": "e01496aa53025444cc51671efcce40d6d24d86775b2cbb1ee0def1862bb6315d", - "packages/ui/components/Combobox.wrn": "140b038735a5902eb901386281a5a01e16fd1c345560a48ff2b143ebaebe1f3d", + "packages/ui/components/Combobox.wrn": "78c97205f42f015d22dd58018641bbd6b0d9cba55b1138af5c9d1da8d1095202", "packages/ui/components/Confetti.wrn": "b9aece64735c721c24356122e52ca84602d9f646c7d8be1e0b80d9de3163a501", "packages/ui/components/Container.wrn": "4a0acbb896f4c11714e3925d912b10ef9aeedfa904b4ad8561aa2cbd9a0fdca0", "packages/ui/components/ContextMenu.wrn": "33fb0f60268b12411d66e3031dc0557cb231149e7a8d83340b4b453a6e37cb09", "packages/ui/components/CustomScrollbar.wrn": "fedb2ab06cc2cf9499c130590945ca6971a3edfb60407b6658ef7756e4be9823", - "packages/ui/components/DataMap.wrn": "6058f92be7fb95e9eedcc714cad1ad43fa70e40c9dd50fd8bba5aae9935953a7", - "packages/ui/components/DataTable.wrn": "edb935b091750ee3d1aff354007eabd4998fc7e5584d50a6c726c6657765d800", - "packages/ui/components/DatePicker.wrn": "2c46f92612528cf60aa0b7e8aaae9826094acb5518d3982c2db65aca6d01e103", - "packages/ui/components/DeviceFrame.wrn": "d918d213e6e0b74d690911ab3b3f440e9b62fa019fd9e8140c5a56c5c0a0843d", + "packages/ui/components/DataMap.wrn": "553677298a28cced00c419fe35dff3d989a8b6d829cadad6e563d4a63a02581e", + "packages/ui/components/DataTable.wrn": "cfc3bb9110ccd1aa38b85fd74995180b6b82c177d0bbd6dcce99d56c99cc6e5b", + "packages/ui/components/DatePicker.wrn": "0c63bc72951961105529c4ebdc1064c22f44d0ce5fc8b813df7554280c7b1ad0", + "packages/ui/components/DeviceFrame.wrn": "b76a0c820278ac7df5c07702b5d95e764ce0ebfcf7d4f89a8b629df8ecafee11", "packages/ui/components/Divider.wrn": "f5cc449611022b3d3eedf982ae48f6b1a289db7855cc9b6ea0248dcda807ffb3", - "packages/ui/components/DragAndDrop.wrn": "31ffe9d41fc655a38257c841a520c947d3ce2338e174b5e89e32fe9ccf23b9b3", + "packages/ui/components/DragAndDrop.wrn": "4c01e56b5f7734b50dbff57157e0fbf163667b8e8a8fc50e1907e77a87f69c51", "packages/ui/components/Drawer.wrn": "e6e2778e515361a3475439ab91b6efec3895efab2a4dfdcfb535713f656cc7ed", "packages/ui/components/Dropdown.wrn": "627319de0f555f0f07f80e19a59f9fd52e7f74af7cf2cf9ff09e114678ad9eb8", "packages/ui/components/FeatureCard.wrn": "2a1bfb01cec8a9892d3ff066e48c276fa7c548cb59c15bcd9b4bbf85450a07a2", - "packages/ui/components/FeatureGrid.wrn": "9bd3e9becb5d7359841ed21d607131c58da20f2e8e87e25a9fb48f6b1a2b17e5", + "packages/ui/components/FeatureGrid.wrn": "3b4539ad3a5f93deb1ff29a98118dd8fa53cce1dd8433f7662d907019c04df37", "packages/ui/components/FeatureIconCard.wrn": "620f66a36ca5c8ad8f2ea09e94dc4471e4146189c42149e9d31db58501281639", - "packages/ui/components/FileInput.wrn": "cc4b8f95f11d91ead9a5796e202b2264eeea24aa1c3b1718327a6ea1dd28d785", - "packages/ui/components/FileUploadProgress.wrn": "c4b4174025a1de75c35a3497e0afd0b8acc645ad5f85c3ed7296ea295bb05749", + "packages/ui/components/FileInput.wrn": "2cc422b2dc9d28b1c7ec8d83aa76ba8ddc2a83eb1d57f940fe320f6c4581c4b8", + "packages/ui/components/FileUploadProgress.wrn": "185715b5c9cf6a285cdae2c17b54d4136faf7779c7841ad89e346397f61dad73", "packages/ui/components/Footer.wrn": "71790c99e4b15a62fdaf4b7a65d7016ca427408b62a2b1c7695ef1b39ba29440", "packages/ui/components/Grid.wrn": "d089d8657298b4d33993ba4bf7b581f816c65db513d8e48cf1fdd18da19e05a8", "packages/ui/components/Hero.wrn": "e4e39dcd59c273192c7e4136f6583279e20b0956bcba4cfbc3f6e01a1fade152", "packages/ui/components/HeroActions.wrn": "77f69085db73b946c00aa684d50fb5ae474684e440e81edbccfd8ef5dc357e33", "packages/ui/components/Image.wrn": "8113441bf90ab0d1d8618d477125ad339021f39e853db89d656c72c492e7a20b", - "packages/ui/components/InputGroup.wrn": "95333e7cb883c52958e3d6112899f337b00825e7678a2323baed1724983a7238", + "packages/ui/components/InputGroup.wrn": "dc8d9bf4ed4fa7eb1b81c2d7dc443fc4a2cef1f7cd4acceee06618c8d1faa61b", "packages/ui/components/InputNumber.wrn": "0ec020084f3e556d438f8264d61f836cfab4951c52d4df60e4944fb734fb38a9", "packages/ui/components/Kbd.wrn": "5afaabbb15902bd8fb82cb4155cf6cbfff55600927b54d564d27e2dd8b752386", "packages/ui/components/LayoutSplitter.wrn": "6bd6812e364420ed5d3439862116c58d0b011b298679005795bdccdbb7455066", - "packages/ui/components/LegendIndicator.wrn": "11f13413242e106daf347638ee2b2313fd20b05fc7001f03c0f4c00a558dfec0", + "packages/ui/components/LegendIndicator.wrn": "830a79bcda542b372c8e5164651d2e6f6192beeca73a64fb2e31adb25cb0ee16", "packages/ui/components/Link.wrn": "b986abcc66bc0b1c6296f3ff4e560812e35d89cc680d5251d7a3883e68c1d053", "packages/ui/components/List.wrn": "9bfa9613f388e5b126fc27d505e8165d7aa4a058e72132b755585464e116490e", - "packages/ui/components/ListGroup.wrn": "885020eea4dbdfc90b5a659e48a339cba7a205ddb539e30d7f1aa57244d728a5", + "packages/ui/components/ListGroup.wrn": "94d1887e74992e0ad8fc204c9b37c2888ed19ee796c62ab04aae34eef1e6c6d0", "packages/ui/components/Map.wrn": "9023a7a188480b24222a3910d26f6926918470369a1ab610f841c31a6120b9aa", "packages/ui/components/MarketingSectionHeader.wrn": "6f89a3b298ea299db686ddf903f92c4fe5d321719213943b16be82ba36c23302", "packages/ui/components/Marquee.wrn": "2a88c8bd8378469add26b0d937adccac4aa9f2c2005393010298e8e4fa89693e", @@ -60,16 +60,16 @@ "packages/ui/components/MetricGrid.wrn": "6018a98c10628ed240ed236ed916c0ff60994d192c3aadafd10bc876be0f9364", "packages/ui/components/Modal.wrn": "59d4ae9d6dd2700692d9edecfe53ee868e9f864363a4885961d1813cb2bee51f", "packages/ui/components/Nav.wrn": "7dc456b879e9248bde267b986cdcb138b8f3127d98b51e27bc9708129953f5e2", - "packages/ui/components/Navbar.wrn": "70640f9ff6e615c70ea9a5e996058bad45ebf0e97b02c9d827228a8f475f72e2", + "packages/ui/components/Navbar.wrn": "4f55470827c7a36062db82c495bf646f6bb428b75ba331e5a932e21f940476ea", "packages/ui/components/PageHeader.wrn": "59264dfb26a132fd3eb265c4374f9fcae781f30dd94a087c57e6e8256717cf14", "packages/ui/components/Pagination.wrn": "9ceb74745b159150b015bbbb1974c68e14a7d4b92bd03491cb23b8855aa07983", - "packages/ui/components/PinInput.wrn": "2b656cf832c02fa9c28e2fe78bf1147ff05b17a9d8e744c33e1a63bad7c7ebb3", + "packages/ui/components/PinInput.wrn": "dff3c69e2b5b2ee39f97a2c54ec6e36becd46bdc9b636a9ec249201b7d606d5a", "packages/ui/components/Popover.wrn": "f2996f00fad3e35fba2d48e70af17f592854eb73b9e8c6a83526aa78c4e41293", - "packages/ui/components/PortalDashboard.wrn": "79b54868f150a551cede0731cc5390a45ce22375f1929f2d537ce67a987bde50", - "packages/ui/components/PreferenceSwitcher.wrn": "241060fb24a16e795c53981506d273fe9110cbb250c73c85928c788c75d05ded", + "packages/ui/components/PortalDashboard.wrn": "ed1713879ab6911920d641111885254e747081c54eb64e9305eda23272318e44", + "packages/ui/components/PreferenceSwitcher.wrn": "5daf957dd91ab3acd5f2e16d8c717cc7938ef6fa41ea0b60e0561cf06aa146d2", "packages/ui/components/PublicPageShell.wrn": "369b74f65e27227311a2ed73e9ca56c8b60908100d6840a798e8ba5f2c8b1040", - "packages/ui/components/RangeSlider.wrn": "eff9db1616d424f9c803185b4efe011942866acad3328179438a200210d97710", - "packages/ui/components/Rating.wrn": "41bbce2eb7fb6ad08a3aacde97d03af6e346824962148e7655743028c59185d3", + "packages/ui/components/RangeSlider.wrn": "97e77a1ba628d43b8585bc27d14167d5743ae8f435398fb7bcead50fe07dfc9b", + "packages/ui/components/Rating.wrn": "959063a3a912d5f9247f851ceb882d7df986f8cd6e1893304224a59be6f88481", "packages/ui/components/Scrollspy.wrn": "76d1c17580c8d460f1222ce97585bdcac9779141f2f30d5460c84ff9f75413d8", "packages/ui/components/SearchBox.wrn": "717f7647fabd762f8ed60a7c3306eac3ddb83c0da292a53c76d91886c2b8f94f", "packages/ui/components/Section.wrn": "33eb8a82a2102229c2b1f64cec497e9e8e70b67adab8dbe396be860fccbb699c", @@ -78,34 +78,32 @@ "packages/ui/components/SplitHero.wrn": "70e843565ff869bcf413b11b6d9830b2e2bd229863a00904596f71e2dff0e76d", "packages/ui/components/StatsBar.wrn": "c7d1df3895f25b6d3a2e1012a18b97592c7f33e65418b880d486f20c2d490686", "packages/ui/components/Stepper.wrn": "df9093e4222ef3250963a8c6fbfec74477242735d23eabe896c29731c54fc14d", - "packages/ui/components/StrongPassword.wrn": "0df060bf01ace77ad0158df489588df75fd5d426dc04f000abacc2b3ddd93fc5", - "packages/ui/components/StyledIcon.wrn": "bf9b41e9c402c4886feddda504c3f12348bbbe49b9003de69d807db4bf52d1b1", + "packages/ui/components/StrongPassword.wrn": "a89d82649983e4b251babe69ff85f3f9623ad7c230c7ef74883749e646f43cf4", + "packages/ui/components/StyledIcon.wrn": "ef3406d097cc9967f0f7d8d5f66108de4c78b453b47cc0c6627630d455acc9fa", "packages/ui/components/Tabs.wrn": "e38336d28876caa4e97da32a569749e3803b030284a85ce9f35fa788e51cc5b0", "packages/ui/components/TextLink.wrn": "6e18906337cd3d30c2a0122593d249bde8f7cedc697b90ae388e2bd0e8eff3e1", - "packages/ui/components/TimePicker.wrn": "d2fb7cd156bb2abb997a9e85d27c36b80f4ba81515b523a125e793363568475c", + "packages/ui/components/TimePicker.wrn": "3b5bc1c380bb4d3569863ed783a8d8f94f7a5fa8948f4bda54f48b828a15ab52", "packages/ui/components/Timeline.wrn": "686a37ebc62732842846d004491336970db94945bca942f226097d863e159d1c", "packages/ui/components/Toaster.wrn": "288b2b370f65bf823e8d2a6f8c8cf66972332b8174303d33ebe8546d5e1d52c4", - "packages/ui/components/ToggleCount.wrn": "285abf0ed5c7156c5a6f404af0c2519f181b591975515e845cbc3c21349c5cfd", - "packages/ui/components/TogglePassword.wrn": "94cd3579bb48e53283c82400bff58ea0f2ca92646b87385502e3b474ba787a96", + "packages/ui/components/ToggleCount.wrn": "a17440af5d52be0ce59655bb61565a89832fe41f950f115da1da0abfaa86dea3", + "packages/ui/components/TogglePassword.wrn": "a4546b6825533efc6b010a095583da1664f8b63a28718bfab71609c4136aeeb5", "packages/ui/components/TreeView.wrn": "c354fce9c5e81fed6eec4089dfd2a7f6bb84eb189c94efc88e00251efdc12c0b", "packages/ui/components/Typography.wrn": "1b4d1b91dee0ff522d27c566becc3bc49bd9ec979ae6334e6a15fca5d88eccac", - "packages/ui/components/WysiwygEditor.wrn": "231da25f4064b065adb2783252d430aa336585e008547a010a41174a41284524", - "packages/ui/components/alert.wrn": "6dde2cee818a66e1d80df6b93e9f971d5389f95387961593350b0c297e3ed367", - "packages/ui/components/avatar.wrn": "ac2239cc746ec35b81a34ec6e27f4ee74ca04dc6058bad5853aa66640f2a9426", - "packages/ui/components/badge.wrn": "9e1e884e9e2e9d881348c5121f53f4c85b91355cbfa49eeb2bff43f5ab38fab5", + "packages/ui/components/WysiwygEditor.wrn": "5535de685d70514651da061698eafc954c5dfea6de944e0c852c456c2d489df1", + "packages/ui/components/alert.wrn": "490a6f5b311b22ca5d630639c831b325b6918b2dd5440a242749f90af59f8b13", + "packages/ui/components/avatar.wrn": "78f602b031eb1de2db588dbcb83bbbbb9c52bef2c1c6a4a905276c3ec3e78119", + "packages/ui/components/badge.wrn": "7049be83eab9c909f2efc39cbbb5dae4aba3a6be2051b9271b92892a6438ad93", "packages/ui/components/button.wrn": "da1660c671daf2feffe1024203ac1a8bc947beb07691bef595c1552c664b9cde", - "packages/ui/components/checkbox.wrn": "a5fb8410558696b3c8e63d5cd8dd49b44d51ed35b809cb2b189501e2e7b323e2", - "packages/ui/components/input.wrn": "184066a837982ef3fe44e518730d0cccb7dd6772d5af58116c0774b71cb894e2", + "packages/ui/components/checkbox.wrn": "6e055207275294fd2390671dfa6c16db2bae692422f38689adad282601d04539", + "packages/ui/components/input.wrn": "5c7c2a8e2334e8c2c966a70ec4c4140ddd99a9084b9f7e2de630152bb3f2d8a4", "packages/ui/components/progress.wrn": "61b01ba575d35691e3dfebfcb03ccd1c6b79f1df1c0d41857ec3b01944081a5d", - "packages/ui/components/radio.wrn": "cc65395aad6c0bac690c18cb7c36b1d2784e4c3284be3d3cb277b745f2f29bbc", - "packages/ui/components/select.wrn": "d58b454958edccce99f96c642eb67d5a0e64e2b97e58e742d445fe45164a7660", + "packages/ui/components/radio.wrn": "f5ec1cab84c0d1b5e75133c44ce2220cd3ae5ad16a72d04c6b92b2482b9bf8b8", + "packages/ui/components/select.wrn": "0a15a19f17e3f9565d8370eab1b97f1ec7299c4e248d80d64e63897fe6ff1c0e", "packages/ui/components/skeleton.wrn": "dda95a2c59c6060ab2b9f916eb046fbe74a68b398a051afc0bde41808e059c3a", "packages/ui/components/spinner.wrn": "ffbd28ec6fc017fc94c67778f8966eab2eefa3b47f3f27f064c77dbeb65d84c1", - "packages/ui/components/switch.wrn": "917219d77b2089584bc444fe94f2cb0670f800d73f69ae70f0368bfece16be0c", - "packages/ui/components/textarea.wrn": "602ef2c8a081476f790408119b96ec2b51fb18abe76a43ee2b955dcb60debd17", + "packages/ui/components/switch.wrn": "9d3892f7a800e0fd98f39c3205eeb96a416f8a1d6834d11678a4c8abf9ee5d71", + "packages/ui/components/textarea.wrn": "dc6f079201c06caaa0ca01b65c5efe80ec4a0b50fecac9726ac3e5a8256c4f16", "packages/ui/components/tooltip.wrn": "40028dfbb17f6725c76c2e091af9c30ea4db6aa4dea919d38f53874ea70315d1", - "packages/ui/styles/ComponentBaseStyles.wrn": "566724a7bcc8f7caa067d5415177bf982ebae7b579a34052ce6f2092cbade4d7", - "packages/ui/styles/FieldStyles.wrn": "460fc8cbb0228151927fd6a61caceae0a148fdbc3009c13ba511ab0a4010b42d", "packages/ui/styles/SelectStyles.wrn": "2c45e9c04678aaff76632e908b3c061410be0d6999a54a9203a39a3817d698f2", "packages/ui/ui.css": "b7e2ae796ffbb738451364f63fce13022a81d81207f7e49c7f6220d24c36acd9" } diff --git a/editors/vscode/syntaxes/wrn.tmLanguage.json b/editors/vscode/syntaxes/wrn.tmLanguage.json index 96994153..05cb88c3 100644 --- a/editors/vscode/syntaxes/wrn.tmLanguage.json +++ b/editors/vscode/syntaxes/wrn.tmLanguage.json @@ -328,7 +328,8 @@ { "include": "source.css" } - ] + ], + "applyEndPatternLast": true }, "css-braces": { "begin": "\\{", @@ -753,6 +754,24 @@ }, "interpolation": { "patterns": [ + { + "name": "meta.block.directive.wrn", + "match": "(\\{)(#if|#each|:else(?:\\s+if)?|/if|/each)(?:\\s+([^}]*))?(\\})", + "captures": { + "1": { + "name": "punctuation.definition.keyword.wrn" + }, + "2": { + "name": "keyword.control.wrn" + }, + "3": { + "name": "meta.embedded.expr.wrn" + }, + "4": { + "name": "punctuation.definition.keyword.wrn" + } + } + }, { "name": "meta.interpolation.i18n.wrn", "match": "(\\{)(t:)([^}]*)(\\})", diff --git a/editors/vscode/test/validate.mjs b/editors/vscode/test/validate.mjs index b62242ef..3ed87f44 100644 --- a/editors/vscode/test/validate.mjs +++ b/editors/vscode/test/validate.mjs @@ -58,6 +58,17 @@ missingIncludes.length === 0 grammar.repository?.["conditional-class-single"] ? ok("single-quoted class directives are registered") : bad("single-quoted class directives are registered"); +grammar.repository?.["style-block"]?.applyEndPatternLast === true + ? ok("style blocks keep nested CSS braces embedded") + : bad("style blocks keep nested CSS braces embedded"); +grammar.repository?.["view-block"]?.applyEndPatternLast === true + ? ok("view blocks keep template directive braces embedded") + : bad("view blocks keep template directive braces embedded"); +grammar.repository?.interpolation?.patterns?.some( + (pattern) => pattern.name === "meta.block.directive.wrn", +) + ? ok("template block directives have dedicated grammar scopes") + : bad("template block directives have dedicated grammar scopes"); // 3. Marketplace metadata and the gallery icon meet vsce requirements. try { diff --git a/package.json b/package.json index 06aa3def..ad11f459 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,13 @@ "test:all": "bun run test && bun run test:examples && bun run test:services && bun run test:editor", "test:coverage": "bun test --coverage packages", "security:audit": "bun audit", - "release:prepare": "bun run scripts/release.ts prepare", - "release:private": "bun run scripts/release.ts publish", + "release:prepare": "bun run scripts/release-changed.ts prepare", + "release:private": "bun run scripts/release-changed.ts publish", + "release:all:prepare": "bun run scripts/release.ts prepare", + "release:all:private": "bun run scripts/release.ts publish", + "release:changed:plan": "bun run scripts/release-changed.ts plan", + "release:changed:prepare": "bun run scripts/release-changed.ts prepare", + "release:changed:publish": "bun run scripts/release-changed.ts publish", "test:db:live": "bash scripts/test-live-db.sh", "typecheck": "tsc --noEmit", "lint": "eslint .", diff --git a/packages/captcha/components/Captcha.wrn b/packages/captcha/components/Captcha.wrn index 16023a72..22105479 100644 --- a/packages/captcha/components/Captcha.wrn +++ b/packages/captcha/components/Captcha.wrn @@ -318,4 +318,34 @@ component Captcha { } + + style { + /* + * Compact image challenges read as a single sequence: challenge, + * secondary actions, answer, then verification. Flattening the footer + * lets Listen/New challenge move directly beneath the image without + * changing the DOM or the client runtime selectors. + */ + [data-wrn-captcha]:is([data-captcha-compact="true"], [data-captcha-size="compact"])[data-captcha-layout="horizontal"] { + grid-template-columns: minmax(0, 1fr); + } + + [data-wrn-captcha]:is([data-captcha-compact="true"], [data-captcha-size="compact"]) + [data-captcha-response-panel] + [data-captcha-footer] { + display: contents; + } + + [data-wrn-captcha]:is([data-captcha-compact="true"], [data-captcha-size="compact"]) + [data-captcha-footer] + > div:first-child { + order: -1; + justify-content: flex-start; + } + + [data-wrn-captcha]:is([data-captcha-compact="true"], [data-captcha-size="compact"]) + [data-captcha-verify] { + align-self: flex-start; + } + } } diff --git a/packages/captcha/package.json b/packages/captcha/package.json index e1fe85f3..d36cf27c 100644 --- a/packages/captcha/package.json +++ b/packages/captcha/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/captcha", - "version": "0.8.8", + "version": "0.8.9", "description": "First-class CAPTCHA challenges, providers, verification guards, page gates, and WRNexusJS UI.", "type": "module", "sideEffects": false, diff --git a/packages/captcha/test/component.test.ts b/packages/captcha/test/component.test.ts index c5696898..27a9dd25 100644 --- a/packages/captcha/test/component.test.ts +++ b/packages/captcha/test/component.test.ts @@ -58,6 +58,9 @@ test("Captcha.wrn parses and exposes the full public contract", async () => { expect(source).toContain("group-data-[captcha-size=compact]/captcha:max-h-24"); expect(source).toContain("group-data-[captcha-size=compact]/captcha:h-8"); expect(source).toContain("group-data-[captcha-size=compact]/captcha:hidden"); + expect(source).toContain("[data-captcha-footer]"); + expect(source).toContain("display: contents"); + expect(source).toContain("order: -1"); expect(source).toContain("data-[captcha-size=big]"); expect(source).toContain("{...attrs}"); expect(source).toContain("--wire-"); diff --git a/packages/cli/package.json b/packages/cli/package.json index c669062a..a8dfb93a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/cli", - "version": "0.8.8", + "version": "0.8.9", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/cli/src/doctor.ts b/packages/cli/src/doctor.ts index a1a4fe56..34bfcc9c 100644 --- a/packages/cli/src/doctor.ts +++ b/packages/cli/src/doctor.ts @@ -79,24 +79,7 @@ export function repairProject(appRoot: string): DoctorRepair[] { try { const source = readFileSync(pkgPath, "utf8"); const pkg = JSON.parse(source) as Record; - const ranges = frameworkRanges(pkg); - const preferred = [...ranges.keys()].sort((left, right) => { - const a = parseVersion(left); - const b = parseVersion(right); - return b[0] - a[0] || b[1] - a[1] || b[2] - a[2]; - })[0]; let changed = false; - if (preferred && ranges.size > 1) { - for (const field of ["dependencies", "devDependencies", "peerDependencies"]) { - const dependencies = pkg[field] as Record | undefined; - for (const name of Object.keys(dependencies ?? {})) { - if (name.startsWith("@wrnexus/") && dependencies![name] !== preferred) { - dependencies![name] = preferred; - changed = true; - } - } - } - } const marker = (pkg.wrnexus as Record | undefined) ?? {}; if (!marker.version || !versionAtLeast(String(marker.version), "0.8.0")) { marker.version = "0.8.0"; @@ -108,9 +91,7 @@ export function repairProject(appRoot: string): DoctorRepair[] { repairs.push({ name: "package.json", changed: true, - detail: preferred - ? `aligned framework packages to ${preferred}` - : "recorded 0.8.0 marker", + detail: "recorded 0.8.0 migration marker", }); } } catch { @@ -154,15 +135,13 @@ export function inspectProject(appRoot: string): DoctorCheck[] { try { const pkg = JSON.parse(readFileSync(pkgPath, "utf8")) as Record; const ranges = frameworkRanges(pkg); + const invalid = [...ranges.keys()].filter((range) => !/[~^]?\d+\.\d+\.\d+/.test(range)); checks.push({ name: "framework package versions", - ok: ranges.size <= 1, - detail: - ranges.size <= 1 - ? ([...ranges.keys()][0] ?? "No @wrnexus packages declared") - : `version skew: ${[...ranges.entries()] - .map(([range, names]) => `${range} (${names.join(", ")})`) - .join("; ")}`, + ok: invalid.length === 0, + detail: invalid.length + ? `invalid ranges: ${invalid.join(", ")}` + : `${[...ranges.values()].reduce((count, names) => count + names.length, 0)} independently versioned package(s)`, }); const marker = (pkg.wrnexus as { version?: string } | undefined)?.version; checks.push({ diff --git a/packages/cli/src/update.ts b/packages/cli/src/update.ts index 10f2c484..065b9f83 100644 --- a/packages/cli/src/update.ts +++ b/packages/cli/src/update.ts @@ -2,13 +2,13 @@ * `wrnexus update [dir] [--version=x.y.z | --latest] [--dry-run]` * * Upgrade an app (or every app in a workspace) to a WrNexus release: - * 1. Bump every `@wrnexus/*` dependency to the target version. + * 1. Resolve and bump every installed `@wrnexus/*` dependency independently. * 2. `bun install`. * 3. Refresh framework-owned reference files (public/llms.txt) and apply any * versioned, idempotent migrations that newer releases introduce. * 4. Record the applied version in package.json (`"wrnexus": { version }`). * - * Target version resolution: `--version=x.y.z` > `--latest` (queries npm) > + * Migration version resolution: `--version=x.y.z` > `--latest` (queries npm) > * the running CLI's own version (the default — pair with `bunx @wrnexus/cli@latest * update` to jump to the newest release with no network guesswork). * @@ -27,7 +27,8 @@ import { statSync, writeFileSync, } from "node:fs"; -import { spawnSync } from "node:child_process"; +import { execFile, spawnSync } from "node:child_process"; +import { promisify } from "node:util"; import { basename, dirname, join, relative, resolve } from "node:path"; import { pathToFileURL } from "node:url"; import { formatWrn, parse } from "@wrnexus/syntax"; @@ -56,6 +57,31 @@ function latestPublished(): string | null { } } +const execFileAsync = promisify(execFile); + +/** Resolve every installed WRNexus dependency independently and in parallel. */ +export async function latestPackageVersions(names: string[]): Promise> { + const npm = process.platform === "win32" ? "npm.cmd" : "npm"; + const unique = [...new Set(names.filter((name) => name.startsWith("@wrnexus/")))]; + const entries = await Promise.all( + unique.map(async (name) => { + try { + const { stdout } = await execFileAsync(npm, ["view", name, "version", "--json"], { + encoding: "utf8", + }); + const parsed = JSON.parse(stdout.trim()) as string | string[]; + const version = Array.isArray(parsed) ? parsed.at(-1) : parsed; + return typeof version === "string" && /^\d+\.\d+\.\d+/.test(version) + ? ([name, version] as const) + : null; + } catch { + return null; + } + }), + ); + return new Map(entries.filter((entry): entry is readonly [string, string] => entry !== null)); +} + /** Numeric compare of `x.y.z` (pre-release/build tags ignored). */ function cmp(a: string, b: string): number { const pa = a.split("-")[0]!.split(".").map(Number); @@ -2131,6 +2157,16 @@ const MIGRATIONS: Migration[] = [ // interface contracts produced by earlier releases. }, }, + { + version: "0.8.9", + id: "0.8.9-independent-package-updates", + description: + "Resolves and updates each installed WRNexus package to its independently published npm version.", + apply() { + // Dependency resolution is handled by the update command before install; + // no application source rewrite is required. + }, + }, ]; /** Release tooling uses this to require an explicit migration entry per version. */ @@ -2138,15 +2174,22 @@ export function updateMigrationVersions(): string[] { return [...new Set(MIGRATIONS.map((migration) => migration.version))]; } -/** Bump every `@wrnexus/*` range to `^target`. Returns the human-readable changes. */ -function bumpDeps(pkg: Record, target: string): string[] { +/** Bump each `@wrnexus/*` range to its independently resolved target. */ +export function bumpDeps( + pkg: Record, + target: string, + packageVersions?: ReadonlyMap, +): string[] { const changed: string[] = []; - const next = `^${target}`; for (const field of ["dependencies", "devDependencies", "peerDependencies"]) { const deps = pkg[field] as Record | undefined; if (!deps) continue; for (const name of Object.keys(deps)) { - if (name.startsWith("@wrnexus/") && deps[name] !== next) { + if (!name.startsWith("@wrnexus/")) continue; + const resolved = packageVersions ? packageVersions.get(name) : target; + if (!resolved) continue; + const next = `^${resolved}`; + if (deps[name] !== next) { changed.push(`${name} ${deps[name]} → ${next}`); deps[name] = next; } @@ -2240,7 +2283,11 @@ export function updateApp( appRoot: string, target: string, dryRun: boolean, - options: { explicitImports?: boolean; report?: MigrationReport } = {}, + options: { + explicitImports?: boolean; + report?: MigrationReport; + packageVersions?: ReadonlyMap; + } = {}, ): UpdatedApp | null { const pkgPath = join(appRoot, "package.json"); if (!existsSync(pkgPath)) { @@ -2264,7 +2311,7 @@ export function updateApp( if (!dryRun) log(`backup: ${backupProjectFiles(appRoot, from, target)}`); - const changes = bumpDeps(pkg, target); + const changes = bumpDeps(pkg, target, options.packageVersions); changes.forEach((c) => log(c)); if (!changes.length) log("dependencies already current"); @@ -2288,7 +2335,7 @@ export function updateApp( // changes back before writing the dependency bump so neither side is lost. if (!dryRun) { Object.assign(pkg, JSON.parse(readFileSync(pkgPath, "utf8")) as Record); - bumpDeps(pkg, target); + bumpDeps(pkg, target, options.packageVersions); } if (!dryRun) writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8"); return { root: appRoot, packagePath: pkgPath, pkg }; @@ -2386,11 +2433,30 @@ export async function runUpdate(dir: string, args: string[]): Promise { return; } - console.log(`\n ⚡ wrnexus update → ${target}${dryRun ? " (dry run)" : ""}\n`); - // Workspace → update the root manifest + every app; else just this app. const apps = await workspaceApps(root); const targets = apps ? [root, ...apps] : [root]; + const dependencyNames = targets.flatMap((targetRoot) => { + const file = join(targetRoot, "package.json"); + if (!existsSync(file)) return []; + const manifest = JSON.parse(readFileSync(file, "utf8")) as Record; + return ["dependencies", "devDependencies", "peerDependencies"].flatMap((field) => + Object.keys(manifest[field] ?? {}).filter((name) => name.startsWith("@wrnexus/")), + ); + }); + const packageVersions = versionArg + ? new Map() + : await latestPackageVersions(dependencyNames); + + console.log(`\n ⚡ wrnexus update → migrations ${target}${dryRun ? " (dry run)" : ""}`); + if (!versionArg) { + console.log( + ` Resolved ${packageVersions.size} installed WRNexus package version(s) from npm.\n`, + ); + } else { + console.log(""); + } + const reports = new Map(); const updated = targets .map((targetRoot) => { @@ -2403,7 +2469,7 @@ export async function runUpdate(dir: string, args: string[]): Promise { parseFailures: [], }; reports.set(targetRoot, report); - return updateApp(targetRoot, target, dryRun, { explicitImports, report }); + return updateApp(targetRoot, target, dryRun, { explicitImports, report, packageVersions }); }) .filter(Boolean) as UpdatedApp[]; @@ -2453,6 +2519,7 @@ export async function runUpdate(dir: string, args: string[]): Promise { writeFileSync(app.packagePath, JSON.stringify(app.pkg, null, 2) + "\n", "utf8"); } - console.log(`\n ✓ Updated and verified ${updated.length} package(s) at ${target}.`); + console.log(`\n ✓ Updated and verified ${updated.length} project manifest(s).`); + console.log(` Migration checkpoint: ${target}; dependencies use their own npm versions.`); console.log(` Backups are under .wrnexus/update-backups/. Review and redeploy.\n`); } diff --git a/packages/cli/test/doctor.test.ts b/packages/cli/test/doctor.test.ts index 5033266b..be76cc00 100644 --- a/packages/cli/test/doctor.test.ts +++ b/packages/cli/test/doctor.test.ts @@ -41,7 +41,7 @@ test("doctor --fix applies safe repairs and is idempotent", () => { expect(repairs.map(({ name }) => name)).toContain("configuration"); expect(existsSync(join(root, "wrnexus.config.ts"))).toBe(true); const manifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8")); - expect(manifest.dependencies["@wrnexus/router"]).toBe("^0.8.0"); + expect(manifest.dependencies["@wrnexus/router"]).toBe("^0.7.0"); expect(manifest.wrnexus.version).toBe("0.8.0"); expect(repairProject(root)).toEqual([]); }); diff --git a/packages/cli/test/update.test.ts b/packages/cli/test/update.test.ts index ad68887f..73d0270a 100644 --- a/packages/cli/test/update.test.ts +++ b/packages/cli/test/update.test.ts @@ -2,7 +2,38 @@ import { expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { blockingVerificationChecks, updateApp, verificationCommands } from "../src/update.ts"; +import { + blockingVerificationChecks, + bumpDeps, + updateApp, + verificationCommands, +} from "../src/update.ts"; + +test("dependency updates use each package's independently published version", () => { + const pkg = { + dependencies: { + "@wrnexus/ui": "^0.8.8", + "@wrnexus/core": "^0.8.8", + "@wrnexus/unavailable": "^0.8.7", + }, + devDependencies: { "@wrnexus/cli": "^0.8.8" }, + }; + const changes = bumpDeps( + pkg, + "0.8.9", + new Map([ + ["@wrnexus/ui", "0.8.10"], + ["@wrnexus/core", "0.8.8"], + ["@wrnexus/cli", "0.8.9"], + ]), + ); + + expect(pkg.dependencies["@wrnexus/ui"]).toBe("^0.8.10"); + expect(pkg.dependencies["@wrnexus/core"]).toBe("^0.8.8"); + expect(pkg.dependencies["@wrnexus/unavailable"]).toBe("^0.8.7"); + expect(pkg.devDependencies["@wrnexus/cli"]).toBe("^0.8.9"); + expect(changes).toHaveLength(2); +}); test("updateApp migrates project files without marking an unverified update complete", () => { const root = mkdtempSync(join(tmpdir(), "wrnexus-update-")); diff --git a/packages/ui/components/Accordion.wrn b/packages/ui/components/Accordion.wrn index ceb9ed1f..61147700 100644 --- a/packages/ui/components/Accordion.wrn +++ b/packages/ui/components/Accordion.wrn @@ -1,5 +1,3 @@ -import ComponentBaseStyles from "../styles/ComponentBaseStyles.wrn" - component Accordion { outputs { change(payload: { value?: string | number | boolean | null; values?: Array; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null) @@ -206,7 +204,6 @@ component Accordion { {/each} -