diff --git a/Cargo.lock b/Cargo.lock index c7109fb6..535126a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" - [[package]] name = "ahash" version = "0.8.11" @@ -37,9 +31,15 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arrayvec" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ast_node" @@ -50,14 +50,14 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "better_scoped_tls" @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bumpalo" @@ -83,11 +83,34 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "capacity_builder" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2d24a6dcf0cd402a21b65d35340f3a49ff3475dc5fdac91d22d2733e6641c6" +dependencies = [ + "capacity_builder_macros", + "itoa", +] + +[[package]] +name = "capacity_builder_macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4a6cae9efc04cc6cbb8faf338d2c497c165c83e74509cf4dbedea948bbf6e5" +dependencies = [ + "quote", + "syn 2.0.100", +] + [[package]] name = "cc" -version = "1.1.6" +version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -97,31 +120,37 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "console" -version = "0.15.8" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width 0.1.13", + "once_cell", + "unicode-width 0.2.0", "windows-sys", ] [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "css_dataset" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "25670139e591f1c2869eb8d0d977028f8d05e859132b4c874ecd02a00d3c9174" [[package]] name = "data-url" @@ -131,9 +160,9 @@ checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" [[package]] name = "deno_ast" -version = "0.46.3" +version = "0.46.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a020d7b6480c15ab5706b595b78a48f31f6df70a6faabe2fee8d4f83b23c82a8" +checksum = "57fa4986eb7deb465906266ee29faa26566d33f8b6a755ac93d49730164ae5e8" dependencies = [ "deno_error", "deno_media_type", @@ -172,7 +201,7 @@ checksum = "5abb2556e91848b66f562451fcbcdee2a3b7c88281828908dcf7cca355f5d997" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -220,7 +249,21 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", +] + +[[package]] +name = "dprint-core" +version = "0.62.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6563addfa2b6c6fa96acdda0341090beba2c5c4ff6ef91f3a232a6d4dd34156" +dependencies = [ + "anyhow", + "bumpalo", + "indexmap 1.9.3", + "rustc-hash 1.1.0", + "serde", + "unicode-width 0.1.14", ] [[package]] @@ -232,8 +275,8 @@ dependencies = [ "anyhow", "bumpalo", "hashbrown 0.15.2", - "indexmap", - "rustc-hash", + "indexmap 2.9.0", + "rustc-hash 2.1.1", "serde", "serde_json", "unicode-width 0.2.0", @@ -262,18 +305,34 @@ dependencies = [ "similar", ] +[[package]] +name = "dprint-plugin-sql" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e1dc125c68e1dcd8b3d7f7a8cedfd2a2b449a495a01358688efa1b0bf3b89f9" +dependencies = [ + "anyhow", + "dprint-core 0.62.1", + "serde", + "sqlformat", +] + [[package]] name = "dprint-plugin-typescript" version = "0.94.0" dependencies = [ "anyhow", + "capacity_builder", "deno_ast", - "dprint-core", + "dprint-core 0.67.4", "dprint-core-macros", "dprint-development", + "dprint-plugin-sql", + "malva", + "markup_fmt", "percent-encoding", "pretty_assertions", - "rustc-hash", + "rustc-hash 2.1.1", "serde", "serde_json", ] @@ -287,7 +346,7 @@ dependencies = [ "allocator-api2", "bumpalo", "num-bigint", - "rustc-hash", + "rustc-hash 2.1.1", "swc_atoms", "swc_common", "swc_ecma_ast", @@ -297,21 +356,21 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "file_test_runner" @@ -324,14 +383,14 @@ dependencies = [ "deno_terminal 0.1.1", "parking_lot", "regex", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -350,9 +409,15 @@ checksum = "8d7ccf961415e7aa17ef93dcb6c2441faaa8e768abe09e659b908089546f74c5" dependencies = [ "proc-macro2", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.100", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -374,6 +439,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hstr" version = "1.0.0" @@ -384,7 +455,7 @@ dependencies = [ "new_debug_unreachable", "once_cell", "phf", - "rustc-hash", + "rustc-hash 2.1.1", "triomphe", ] @@ -429,9 +500,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -453,9 +524,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -474,9 +545,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -503,7 +574,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -529,9 +600,20 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -540,33 +622,45 @@ dependencies = [ [[package]] name = "is-macro" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a85abdc13717906baccb5a1e435556ce0df215f242892f721dff62bf25288f" +checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" dependencies = [ - "Inflector", + "heck", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] -name = "itoa" -version = "1.0.14" +name = "itertools" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] [[package]] -name = "lazy_static" -version = "1.5.0" +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "litemap" @@ -584,18 +678,60 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "malva" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a952f521471c6c8302a17fc0c64a512221a9d4ff268af4d43a02bc2be48c712" +dependencies = [ + "aho-corasick", + "itertools 0.14.0", + "memchr", + "raffia", + "tiny_pretty", +] + +[[package]] +name = "markup_fmt" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff37c5cadfdf4d91c0f140d516755c055a184a4e37757ff4a071272635b9f546" +dependencies = [ + "aho-corasick", + "css_dataset", + "itertools 0.13.0", + "memchr", + "tiny_pretty", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "new_debug_unreachable" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -662,9 +798,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", @@ -672,9 +808,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", @@ -682,37 +818,37 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.1", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -720,18 +856,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.21" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" dependencies = [ "cc", ] @@ -753,18 +889,39 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "raffia" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c36f58fa7ad2f26bca656054c902becddeac5582df2bb31d4b4d2a148c62cfd5" +dependencies = [ + "raffia_macro", + "smallvec", +] + +[[package]] +name = "raffia_macro" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fdb50eb5bf734fa5a770680a61876a6ec77b99c1e0e52d1f18ad6ebfa85759f" +dependencies = [ + "heck", + "quote", + "syn 2.0.100", +] + [[package]] name = "rand" version = "0.8.5" @@ -782,18 +939,18 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -803,9 +960,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -814,9 +971,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" @@ -826,9 +989,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "scoped-tls" @@ -859,26 +1022,33 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "indexmap", + "indexmap 2.9.0", "itoa", + "memchr", "ryu", "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "similar" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "siphasher" @@ -886,11 +1056,17 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "smartstring" @@ -903,6 +1079,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -911,15 +1097,15 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.15" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9" dependencies = [ "cc", "cfg-if", "libc", "psm", - "winapi", + "windows-sys", ] [[package]] @@ -946,7 +1132,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -958,7 +1144,7 @@ dependencies = [ "allocator-api2", "bumpalo", "ptr_meta", - "rustc-hash", + "rustc-hash 2.1.1", "triomphe", ] @@ -970,16 +1156,17 @@ checksum = "9d7077ba879f95406459bc0c81f3141c529b34580bc64d7ab7bd15e7118a0391" dependencies = [ "hstr", "once_cell", - "rustc-hash", + "rustc-hash 2.1.1", "serde", ] [[package]] name = "swc_common" -version = "8.0.1" +version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e4a932c152e7142de2d5dba1c393e5523c47cd8fe656e5b0d411954bbaf1810" +checksum = "7d96ac5d021c7c20acb3073940b4ee59b62989a705f855783c4a452e0737a2e6" dependencies = [ + "anyhow", "ast_node", "better_scoped_tls", "cfg-if", @@ -988,28 +1175,30 @@ dependencies = [ "new_debug_unreachable", "num-bigint", "once_cell", - "rustc-hash", + "rustc-hash 2.1.1", "serde", - "siphasher", + "siphasher 0.3.11", "swc_allocator", "swc_atoms", "swc_eq_ignore_macros", "swc_visit", "tracing", - "unicode-width 0.1.13", + "unicode-width 0.1.14", "url", ] [[package]] name = "swc_ecma_ast" -version = "8.1.0" +version = "8.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01f80679b1afc52ae0663eed0a2539cc3c108d48c287b5601712f9850d9fa9c2" +checksum = "4062a54522a9c02d2b68cc09282774b87121cd48693b0e67ae8c18b31b709866" dependencies = [ "bitflags", "is-macro", "num-bigint", + "once_cell", "phf", + "rustc-hash 2.1.1", "scoped-tls", "serde", "string_enum", @@ -1021,16 +1210,18 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "11.0.0" +version = "11.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41e06ecaef86a547831f7f01f342434e4b0d0f363762f8e7a2b84da7a0a5f92e" +checksum = "aa942372098c7c0e7fd8c584a577378d2f659c934429b8252c4e26fae31d7ea7" dependencies = [ + "arrayvec", + "bitflags", "either", "new_debug_unreachable", "num-bigint", "num-traits", "phf", - "rustc-hash", + "rustc-hash 2.1.1", "serde", "smallvec", "smartstring", @@ -1050,7 +1241,7 @@ checksum = "e96e15288bf385ab85eb83cff7f9e2d834348da58d0a31b33bdb572e66ee413e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -1061,7 +1252,7 @@ checksum = "a509f56fca05b39ba6c15f3e58636c3924c78347d63853632ed2ffcb6f5a0ac7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -1087,9 +1278,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -1104,7 +1295,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -1127,11 +1318,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.63", + "thiserror-impl 1.0.69", ] [[package]] @@ -1145,13 +1336,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -1162,7 +1353,16 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", +] + +[[package]] +name = "tiny_pretty" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b3f46f0549180b9c6f7f76270903f1a06867c43a03998b99dce81aa1760c3b2" +dependencies = [ + "unicode-width 0.1.14", ] [[package]] @@ -1177,9 +1377,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -1188,29 +1388,29 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] [[package]] name = "triomphe" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" dependencies = [ "serde", "stable_deref_trait", @@ -1224,21 +1424,21 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "unicode-id-start" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3882f69607a2ac8cc4de3ee7993d8f68bb06f2974271195065b3bd07f2edea" +checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" @@ -1246,6 +1446,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "url" version = "2.5.4" @@ -1276,42 +1482,20 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] @@ -1394,9 +1578,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" @@ -1418,7 +1602,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", "synstructure", ] @@ -1439,7 +1623,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] [[package]] @@ -1459,7 +1643,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", "synstructure", ] @@ -1482,5 +1666,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.100", ] diff --git a/Cargo.toml b/Cargo.toml index a9504bbe..5a26436b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ harness = false [dependencies] anyhow = "1.0.64" +capacity_builder = "0.5.0" deno_ast = { version = "0.46.3", features = ["view"] } dprint-core = { version = "0.67.4", features = ["formatting"] } dprint-core-macros = "0.1.0" @@ -41,5 +42,8 @@ serde_json = { version = "1.0", optional = true } [dev-dependencies] dprint-development = "0.10.1" +dprint-plugin-sql = "0.2.0" +malva = "0.11.1" +markup_fmt = "0.19.0" pretty_assertions = "1.3.0" serde_json = { version = "1.0" } diff --git a/src/format_text.rs b/src/format_text.rs index 13eea7c9..4e10d78b 100644 --- a/src/format_text.rs +++ b/src/format_text.rs @@ -10,8 +10,17 @@ use crate::swc::ensure_no_specific_syntax_errors; use super::configuration::Configuration; use super::generation::generate; +pub use super::generation::ExternalFormatter; use super::swc::parse_swc_ast; +pub struct FormatTextOptions<'a> { + pub path: &'a Path, + pub extension: Option<&'a str>, + pub text: String, + pub config: &'a Configuration, + pub external_formatter: Option<&'a ExternalFormatter>, +} + /// Formats a file. /// /// Returns the file text or an error when it failed to parse. @@ -35,11 +44,24 @@ use super::swc::parse_swc_ast; /// // now format many files (it is recommended to parallelize this) /// let files_to_format = vec![(PathBuf::from("path/to/file.ts"), "const t = 5 ;")]; /// for (file_path, file_text) in files_to_format { -/// let result = format_text(&file_path, None, file_text.into(), &config); +/// let result = format_text(FormatTextOptions { +/// path: &file_path, +/// extension: None, +/// text: file_text.into(), +/// config: &config, +/// external_formatter: None, +/// }); /// // save result here... /// } /// ``` -pub fn format_text(file_path: &Path, file_extension: Option<&str>, file_text: String, config: &Configuration) -> Result> { +pub fn format_text(options: FormatTextOptions) -> Result> { + let FormatTextOptions { + path: file_path, + extension: file_extension, + text: file_text, + config, + external_formatter, + } = options; if super::utils::file_text_has_ignore_comment(&file_text, &config.ignore_file_comment_text) { Ok(None) } else { @@ -47,7 +69,7 @@ pub fn format_text(file_path: &Path, file_extension: Option<&str>, file_text: St let file_text = if had_bom { file_text[3..].to_string() } else { file_text }; let file_text: Arc = file_text.into(); let parsed_source = parse_swc_ast(file_path, file_extension, file_text)?; - match inner_format(&parsed_source, config)? { + match inner_format(&parsed_source, config, external_formatter)? { Some(new_text) => Ok(Some(new_text)), None => { if had_bom { @@ -61,20 +83,20 @@ pub fn format_text(file_path: &Path, file_extension: Option<&str>, file_text: St } /// Formats an already parsed source. This is useful as a performance optimization. -pub fn format_parsed_source(source: &ParsedSource, config: &Configuration) -> Result> { +pub fn format_parsed_source(source: &ParsedSource, config: &Configuration, external_formatter: Option<&ExternalFormatter>) -> Result> { if super::utils::file_text_has_ignore_comment(source.text(), &config.ignore_file_comment_text) { Ok(None) } else { ensure_no_specific_syntax_errors(source)?; - inner_format(source, config) + inner_format(source, config, external_formatter) } } -fn inner_format(parsed_source: &ParsedSource, config: &Configuration) -> Result> { +fn inner_format(parsed_source: &ParsedSource, config: &Configuration, external_formatter: Option<&ExternalFormatter>) -> Result> { let result = dprint_core::formatting::format( || { #[allow(clippy::let_and_return)] - let print_items = generate(parsed_source, config); + let print_items = generate(parsed_source, config, external_formatter); // println!("{}", print_items.get_as_text()); print_items }, @@ -91,7 +113,7 @@ fn inner_format(parsed_source: &ParsedSource, config: &Configuration) -> Result< pub fn trace_file(file_path: &Path, file_text: &str, config: &Configuration) -> dprint_core::formatting::TracingResult { let parsed_source = parse_swc_ast(file_path, None, file_text.into()).unwrap(); ensure_no_specific_syntax_errors(&parsed_source).unwrap(); - dprint_core::formatting::trace_printing(|| generate(&parsed_source, config), config_to_print_options(file_text, config)) + dprint_core::formatting::trace_printing(|| generate(&parsed_source, config, None), config_to_print_options(file_text, config)) } fn config_to_print_options(file_text: &str, config: &Configuration) -> PrintOptions { @@ -111,9 +133,15 @@ mod test { fn strips_bom() { for input_text in ["\u{FEFF}const t = 5;\n", "\u{FEFF}const t = 5;"] { let config = crate::configuration::ConfigurationBuilder::new().build(); - let result = format_text(&std::path::PathBuf::from("test.ts"), None, input_text.into(), &config) - .unwrap() - .unwrap(); + let result = format_text(FormatTextOptions { + path: &std::path::PathBuf::from("test.ts"), + extension: None, + text: input_text.into(), + config: &config, + external_formatter: None, + }) + .unwrap() + .unwrap(); assert_eq!(result, "const t = 5;\n"); } } diff --git a/src/generation/context.rs b/src/generation/context.rs index 1368f1ce..728ea7e9 100644 --- a/src/generation/context.rs +++ b/src/generation/context.rs @@ -18,11 +18,41 @@ use super::*; use crate::configuration::*; use crate::utils::Stack; +/// A callback that will be called when encountering certain tagged templates. +/// +/// Currently supports `css`, `html` and `sql` tagged templated. +/// +/// Examples: +/// ```ignore +/// const styles = css`color: red;`; +/// +/// const markup = html` +/// +///

Hello!

+/// +/// `; +/// +/// const query = sql` +/// SELECT +/// * +/// FROM +/// users +/// WHERE +/// active IS TRUE; +/// ``` +/// +/// External formatter should return `None` if it doesn't understand given `MediaType`, in such +/// cases the templates will be left as they are. +/// +/// Only templates with no interpolation are supported. +pub type ExternalFormatter = dyn Fn(MediaType, String, &Configuration) -> Option; + pub struct Context<'a> { pub media_type: MediaType, pub program: Program<'a>, pub config: &'a Configuration, pub comments: CommentTracker<'a>, + pub external_formatter: Option<&'a ExternalFormatter>, pub token_finder: TokenFinder<'a>, pub current_node: Node<'a>, pub parent_stack: Stack>, @@ -43,12 +73,20 @@ pub struct Context<'a> { } impl<'a> Context<'a> { - pub fn new(media_type: MediaType, tokens: &'a [TokenAndSpan], current_node: Node<'a>, program: Program<'a>, config: &'a Configuration) -> Context<'a> { + pub fn new( + media_type: MediaType, + tokens: &'a [TokenAndSpan], + current_node: Node<'a>, + program: Program<'a>, + config: &'a Configuration, + external_formatter: Option<&'a ExternalFormatter>, + ) -> Context<'a> { Context { media_type, program, config, comments: CommentTracker::new(program, tokens), + external_formatter, token_finder: TokenFinder::new(program), current_node, parent_stack: Default::default(), diff --git a/src/generation/generate.rs b/src/generation/generate.rs index 62342c59..df0e3953 100644 --- a/src/generation/generate.rs +++ b/src/generation/generate.rs @@ -25,13 +25,20 @@ use super::*; use crate::configuration::*; use crate::utils; -pub fn generate(parsed_source: &ParsedSource, config: &Configuration) -> PrintItems { +pub fn generate(parsed_source: &ParsedSource, config: &Configuration, external_formatter: Option<&ExternalFormatter>) -> PrintItems { // eprintln!("Leading: {:?}", parsed_source.comments().leading_map()); // eprintln!("Trailing: {:?}", parsed_source.comments().trailing_map()); parsed_source.with_view(|program| { let program_node = program.into(); - let mut context = Context::new(parsed_source.media_type(), parsed_source.tokens(), program_node, program, config); + let mut context = Context::new( + parsed_source.media_type(), + parsed_source.tokens(), + program_node, + program, + config, + external_formatter, + ); let mut items = gen_node(program_node, &mut context); items.push_condition(if_true( "endOfFileNewLine", @@ -3001,6 +3008,97 @@ fn gen_spread_element<'a>(node: &SpreadElement<'a>, context: &mut Context<'a>) - items } +/// Formats the tagged template literal using an external formatter. +/// Detects the type of embedded language automatically. +fn maybe_gen_tagged_tpl_with_external_formatter<'a>(node: &TaggedTpl<'a>, context: &mut Context<'a>) -> Option { + let external_formatter = context.external_formatter.as_ref()?; + let media_type = detect_embedded_language_type(node)?; + + // First creates text with placeholders for the expressions. + let placeholder_text = "dpr1nt_"; + let text = capacity_builder::StringBuilder::::build(|builder| { + let expr_len = node.tpl.exprs.len(); + for (i, quasi) in node.tpl.quasis.iter().enumerate() { + builder.append(quasi.raw().as_str()); + if i < expr_len { + builder.append(placeholder_text); + if i < 10 { + // increase chance all placeholders have the same length + builder.append("0"); + } + builder.append(i); // give each placeholder a unique name so the formatter doesn't remove duplicates + builder.append("_d"); + } + } + }) + .unwrap(); + + // Then formats the text with the external formatter. + let formatted_tpl = external_formatter(media_type, text, context.config)?; + + let mut items = PrintItems::new(); + items.push_sc(sc!("`")); + items.push_signal(Signal::NewLine); + items.push_signal(Signal::StartIndent); + let mut index = 0; + for line in formatted_tpl.lines() { + let mut pos = 0; + let mut parts = line.split(placeholder_text).enumerate().peekable(); + while let Some((i, part)) = parts.next() { + let end = pos + part.len(); + if i > 0 { + pos += part.find("_d").unwrap() + 2; + } + let text = &line[pos..end]; + if !text.is_empty() { + items.push_string(text.to_string()); + } + if parts.peek().is_some() { + items.push_sc(sc!("${")); + items.extend(gen_node(node.tpl.exprs[index].into(), context)); + items.push_sc(sc!("}")); + pos = end + placeholder_text.len(); + index += 1; + } + } + items.push_signal(Signal::NewLine); + } + items.push_signal(Signal::FinishIndent); + items.push_sc(sc!("`")); + Some(items) +} + +/// Detects the type of embedded language in a tagged template literal. +fn detect_embedded_language_type<'a>(node: &TaggedTpl<'a>) -> Option { + match node.tag { + Expr::Ident(ident) => { + match ident.sym().as_str() { + "css" => Some(MediaType::Css), // css`...` + "html" => Some(MediaType::Html), // html`...` + "sql" => Some(MediaType::Sql), // sql`...` + _ => None, + } + } + Expr::Member(member_expr) => { + if let Expr::Ident(ident) = member_expr.obj { + if ident.sym().as_str() == "styled" { + return Some(MediaType::Css); // styled.foo`...` + } + } + None + } + Expr::Call(call_expr) => { + if let Callee::Expr(Expr::Ident(ident)) = call_expr.callee { + if ident.sym().as_str() == "styled" { + return Some(MediaType::Css); // styled(Button)`...` + } + } + None + } + _ => None, + } +} + fn gen_tagged_tpl<'a>(node: &TaggedTpl<'a>, context: &mut Context<'a>) -> PrintItems { let use_space = context.config.tagged_template_space_before_literal; let mut items = gen_node(node.tag.into(), context); @@ -3017,6 +3115,11 @@ fn gen_tagged_tpl<'a>(node: &TaggedTpl<'a>, context: &mut Context<'a>) -> PrintI items.extend(generated_between_comments); } + if let Some(formatted_tpl) = maybe_gen_tagged_tpl_with_external_formatter(node, context) { + items.push_condition(conditions::indent_if_start_of_line(formatted_tpl)); + return items; + } + items.push_condition(conditions::indent_if_start_of_line(gen_node(node.tpl.into(), context))); items } diff --git a/src/generation/mod.rs b/src/generation/mod.rs index 09e0434a..7696bcb8 100644 --- a/src/generation/mod.rs +++ b/src/generation/mod.rs @@ -12,4 +12,5 @@ use context::*; use generate_types::*; use tokens::*; +pub use context::ExternalFormatter; pub use generate::generate; diff --git a/src/lib.rs b/src/lib.rs index 38c5a479..cb04f545 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,8 @@ mod utils; pub use format_text::format_parsed_source; pub use format_text::format_text; +pub use format_text::ExternalFormatter; +pub use format_text::FormatTextOptions; #[cfg(feature = "tracing")] pub use format_text::trace_file; diff --git a/src/swc.rs b/src/swc.rs index 0401f169..21d75507 100644 --- a/src/swc.rs +++ b/src/swc.rs @@ -359,6 +359,6 @@ Merge conflict marker encountered. at file:///test.ts:6:1 // a source file that had a non-fatal diagnostic let parsed_source = parse_inner_no_diagnostic_check(&file_path, None, text.into()).unwrap(); let config = ConfigurationBuilder::new().build(); - assert_eq!(crate::format_parsed_source(&parsed_source, &config).err().unwrap().to_string(), expected); + assert_eq!(crate::format_parsed_source(&parsed_source, &config, None).err().unwrap().to_string(), expected); } } diff --git a/src/wasm_plugin.rs b/src/wasm_plugin.rs index ffd3163b..162a9252 100644 --- a/src/wasm_plugin.rs +++ b/src/wasm_plugin.rs @@ -60,7 +60,15 @@ impl SyncPluginHandler for TypeScriptPluginHandler { fn format(&mut self, request: SyncFormatRequest, _format_with_host: impl FnMut(SyncHostFormatRequest) -> FormatResult) -> FormatResult { let file_text = String::from_utf8(request.file_bytes)?; - super::format_text(request.file_path, None, file_text, request.config).map(|maybe_text| maybe_text.map(|t| t.into_bytes())) + super::format_text(super::FormatTextOptions { + path: request.file_path, + extension: None, + text: file_text, + config: request.config, + // todo: support this in Wasm + external_formatter: None, + }) + .map(|maybe_text| maybe_text.map(|t| t.into_bytes())) } } diff --git a/tests/spec_test.rs b/tests/spec_test.rs index c0c429ce..8157bdca 100644 --- a/tests/spec_test.rs +++ b/tests/spec_test.rs @@ -1,11 +1,79 @@ -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::Arc; +use deno_ast::MediaType; use dprint_core::configuration::*; use dprint_development::*; use dprint_plugin_typescript::configuration::*; use dprint_plugin_typescript::*; +fn external_formatter(media_type: MediaType, text: String, config: &Configuration) -> Option { + match media_type { + MediaType::Css => format_embedded_css(&text, config), + MediaType::Html => format_html(&text, config), + MediaType::Sql => format_sql(&text, config), + _ => unreachable!(), + } +} + +fn format_embedded_css(text: &str, config: &Configuration) -> Option { + use malva::config; + let options = config::FormatOptions { + layout: config::LayoutOptions { + indent_width: config.indent_width as usize, + ..Default::default() + }, + ..Default::default() + }; + // Wraps the text in a css block of `a { ... }` + // to make it valid css (scss) + let Ok(text) = malva::format_text(&format!("a{{\n{}\n}}", text), malva::Syntax::Scss, &options) else { + return None; + }; + let mut buf = vec![]; + for (i, l) in text.lines().enumerate() { + // skip the first line (a {) + if i == 0 { + continue; + } + // skip the last line (}) + if l.starts_with("}") { + continue; + } + let mut chars = l.chars(); + // drop the indentation + for _ in 0..config.indent_width { + chars.next(); + } + buf.push(chars.as_str()); + } + Some(buf.join("\n").to_string()) +} + +fn format_html(text: &str, config: &Configuration) -> Option { + use markup_fmt::config; + let options = config::FormatOptions { + layout: config::LayoutOptions { + indent_width: config.indent_width as usize, + ..Default::default() + }, + ..Default::default() + }; + let Ok(text) = markup_fmt::format_text(text, markup_fmt::Language::Html, &options, |code, _| { + Ok::<_, std::convert::Infallible>(code.into()) + }) else { + return None; + }; + Some(text.to_string()) +} + +fn format_sql(text: &str, config: &Configuration) -> Option { + let options = dprint_plugin_sql::configuration::ConfigurationBuilder::new() + .indent_width(config.indent_width) + .build(); + dprint_plugin_sql::format_text(Path::new("_path.sql"), text, &options).ok().flatten() +} + fn main() { //debug_here!(); let global_config = GlobalConfiguration { @@ -28,7 +96,13 @@ fn main() { let config_result = resolve_config(spec_config, &global_config); ensure_no_diagnostics(&config_result.diagnostics); - format_text(file_name, None, file_text.into(), &config_result.config) + format_text(FormatTextOptions { + path: file_name, + extension: None, + text: file_text.into(), + config: &config_result.config, + external_formatter: Some(&external_formatter), + }) }) }, Arc::new(move |_file_name, _file_text, _spec_config| { diff --git a/tests/specs/external_formatter/css.txt b/tests/specs/external_formatter/css.txt new file mode 100644 index 00000000..2b05f334 --- /dev/null +++ b/tests/specs/external_formatter/css.txt @@ -0,0 +1,124 @@ +== should format css in css`...` == +const Header = css` +height: 40px; padding: 0 15px ; +display: flex; align-items: center ; +border-top-left-radius: +5px; +border-top-right-radius:5px;;; +`; +[expect] +const Header = css` + height: 40px; + padding: 0 15px; + display: flex; + align-items: center; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +`; + +== should format css in css`...` with correct indent == +function foo() { + const Tag = css`height: 40px; padding: 0 15px;` +} +[expect] +function foo() { + const Tag = css` + height: 40px; + padding: 0 15px; + `; +} + +== should format css in styled.tag`...` == +styled.div`padding: 1px;`; +[expect] +styled.div` + padding: 1px; +`; + +== should format full css (not only properties) in css`...` == +css`.foo-bar { height: ${height}px; }`; +[expect] +css` + .foo-bar { + height: ${height}px; + } +`; + +== should format css with long expressions reasonably == +styled.div` +padding-left:${foo0+foo1+foo2+foo3+foo4+foo5+foo6+foo7+foo8+foo9+foo10+foo11+foo12}px; +padding-right: ${foo0+foo1+foo2+foo3+foo4+foo5+foo6+foo7+foo8+foo9+foo10+foo11+foo12+foo13}px; +padding-top: ${(props) => { return props.top+props.top+props.top+props.top+props.top+props.top+props.top }}px; +margin: ${margin}px; +` +[expect] +styled.div` + padding-left: ${foo0 + foo1 + foo2 + foo3 + foo4 + foo5 + foo6 + foo7 + foo8 + foo9 + foo10 + foo11 + foo12}px; + padding-right: ${foo0 + foo1 + foo2 + foo3 + foo4 + foo5 + foo6 + foo7 + foo8 + foo9 + foo10 + foo11 + foo12 + + foo13}px; + padding-top: ${(props) => { + return props.top + props.top + props.top + props.top + props.top + props.top + props.top; + }}px; + margin: ${margin}px; +`; + +== should format css with arrow function expressions reasonably == +// this case was borrowed from https://github.com/prettier/prettier/blob/40a04dd216a61d41945b2302468864ffa38af77f/tests/format/js/template-literals/styled-components-with-expressions.js#L6 +styled.div` + display: ${props=>props.display}; + border: ${props=>props.border}px; + margin: 10px ${props=>props.border}px ; +`; +[expect] +// this case was borrowed from https://github.com/prettier/prettier/blob/40a04dd216a61d41945b2302468864ffa38af77f/tests/format/js/template-literals/styled-components-with-expressions.js#L6 +styled.div` + display: ${props => props.display}; + border: ${props => props.border}px; + margin: 10px ${props => props.border}px; +`; + +== should format nested css reasonably == +// this case was borrowed from https://github.com/prettier/prettier/blob/40a04dd216a61d41945b2302468864ffa38af77f/tests/format/js/template-literals/styled-components-with-expressions.js#L12 +const EqualDivider = styled.div` +margin: 0.5rem; + padding: 1rem; + background: papayawhip ; + + > * { + flex: 1; + + &:not(:first-child) { + ${props => props.vertical ? 'margin-top' : 'margin-left'}: 1rem; + } + } +`; +[expect] +// this case was borrowed from https://github.com/prettier/prettier/blob/40a04dd216a61d41945b2302468864ffa38af77f/tests/format/js/template-literals/styled-components-with-expressions.js#L12 +const EqualDivider = styled.div` + margin: 0.5rem; + padding: 1rem; + background: papayawhip; + + > * { + flex: 1; + + &:not(:first-child) { + ${props => props.vertical ? "margin-top" : "margin-left"}: 1rem; + } + } +`; + +== should format css in styled(Component)`...` == +styled(Button)` color : #222 ; background-color: #ccc ; `; +[expect] +styled(Button)` + color: #222; + background-color: #ccc; +`; + +== should not format css if ignore directive is present == +// dprint-ignore +styled.div`color:red;`; +[expect] +// dprint-ignore +styled.div`color:red;`; diff --git a/tests/specs/external_formatter/html.txt b/tests/specs/external_formatter/html.txt new file mode 100644 index 00000000..86d8278b --- /dev/null +++ b/tests/specs/external_formatter/html.txt @@ -0,0 +1,21 @@ +== should format html in html`...` == +let htmlString = html`
HEADER
Hello there!
FOOTER
`; +[expect] +let htmlString = html` + +
HEADER
+
Hello there!
+
FOOTER
+ +`; + +== should format html in html`...` with multiple quasis == +htmlString = html`
${header}
${main}
${footer}
`; +[expect] +htmlString = html` + +
${header}
+
${main}
+ + +`; diff --git a/tests/specs/external_formatter/sql.txt b/tests/specs/external_formatter/sql.txt new file mode 100644 index 00000000..937cd0b9 --- /dev/null +++ b/tests/specs/external_formatter/sql.txt @@ -0,0 +1,19 @@ +== should format sql in sql`...` == +let query = sql`SELECT * FROM users;`; +[expect] +let query = sql` + SELECT + * + FROM + users; +`; + +== should format sql in sql`...` with multiple quasis == +query = sql`SELECT ${table}.${field} FROM ${table};`; +[expect] +query = sql` + SELECT + ${table}.${field} + FROM + ${table}; +`;