From fd4272954632c2523785ed48063588cfba902c76 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 16 Sep 2023 15:27:50 -0500 Subject: [PATCH 1/4] Support `--respect-ignores` --- src/cli/main.rs | 56 ++++++++++++++++++++++++++++++++++++++----------- src/cli/opt.rs | 4 ++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/cli/main.rs b/src/cli/main.rs index 4554f04d..553dba7c 100644 --- a/src/cli/main.rs +++ b/src/cli/main.rs @@ -221,7 +221,13 @@ fn get_ignore( directory: &Path, search_parent_directories: bool, ) -> Result { - let file_path = find_ignore_file_path(directory.to_path_buf(), search_parent_directories); + let file_path = find_ignore_file_path(directory.to_path_buf(), search_parent_directories) + .or_else(|| { + std::env::current_dir() + .ok() + .and_then(|cwd| find_ignore_file_path(cwd, false)) + }); + if let Some(file_path) = file_path { let (ignore, err) = Gitignore::new(file_path); if let Some(err) = err { @@ -234,6 +240,31 @@ fn get_ignore( } } +/// Whether the provided path was explicitly provided to the tool +fn is_explicitly_provided(opt: &opt::Opt, path: &Path) -> bool { + opt.files.iter().any(|p| path == *p) +} + +/// By default, files explicitly passed to the command line will be formatted regardless of whether +/// they are present in .styluaignore / not glob matched. If `--respect-ignores` is provided, +/// then we enforce .styluaignore / glob matching on explicitly passed paths. +fn should_respect_ignores(opt: &opt::Opt, path: &Path) -> bool { + !is_explicitly_provided(opt, path) || opt.respect_ignores +} + +fn path_is_stylua_ignored(path: &Path, search_parent_directories: bool) -> Result { + let ignore = get_ignore( + path.parent().expect("cannot get parent directory"), + search_parent_directories, + ) + .context("failed to parse ignore file")?; + + Ok(matches!( + ignore.matched(path, false), + ignore::Match::Ignore(_) + )) +} + fn format(opt: opt::Opt) -> Result { if opt.files.is_empty() { bail!("no files provided"); @@ -400,15 +431,7 @@ fn format(opt: opt::Opt) -> Result { let opt = opt.clone(); let should_skip_format = match &opt.stdin_filepath { - Some(filepath) => { - let ignore = get_ignore( - filepath.parent().expect("cannot get parent directory"), - opt.search_parent_directories, - ) - .context("failed to parse ignore file")?; - - matches!(ignore.matched(filepath, false), ignore::Match::Ignore(_)) - } + Some(path) => path_is_stylua_ignored(path, opt.search_parent_directories)?, None => false, }; @@ -468,8 +491,8 @@ fn format(opt: opt::Opt) -> Result { if path.is_file() { // If the user didn't provide a glob pattern, we should match against our default one - // We should ignore the glob check if the path provided was explicitly given to the CLI - if use_default_glob && !opt.files.iter().any(|p| path == *p) { + if use_default_glob && should_respect_ignores(opt.as_ref(), path.as_path()) + { lazy_static::lazy_static! { static ref DEFAULT_GLOB: globset::GlobSet = { let mut builder = globset::GlobSetBuilder::new(); @@ -484,6 +507,15 @@ fn format(opt: opt::Opt) -> Result { } } + // If `--respect-ignores` was given and this is an explicit file path, + // we should check .styluaignore + if is_explicitly_provided(opt.as_ref(), &path) + && should_respect_ignores(opt.as_ref(), &path) + && path_is_stylua_ignored(&path, opt.search_parent_directories)? + { + continue; + } + let tx = tx.clone(); pool.execute(move || { #[cfg(not(feature = "editorconfig"))] diff --git a/src/cli/opt.rs b/src/cli/opt.rs index e37fe5ae..6a75f470 100644 --- a/src/cli/opt.rs +++ b/src/cli/opt.rs @@ -101,6 +101,10 @@ pub struct Opt { #[cfg(feature = "editorconfig")] #[structopt(long)] pub no_editorconfig: bool, + + /// Respect .styluaignore and glob matching for file paths provided directly to the tool + #[structopt(long)] + pub respect_ignores: bool, } #[derive(ArgEnum, Clone, Copy, Debug, PartialEq, Eq)] From 55d746c1617f6f2b92f1d58cc8206b1d9e0ab60f Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 16 Sep 2023 15:27:57 -0500 Subject: [PATCH 2/4] Update readme and changelog --- CHANGELOG.md | 4 ++++ README.md | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef0ebac3..25d15113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added flag `--respect-ignores`. By default, files explicitly passed to stylua (e.g. `stylua foo.lua`) will always be formatted, regardless of whether the file is ignored. Enabling this flag will consider `.styluaignore` or glob matches before formatting the file. + ## [0.18.2] - 2023-09-10 ### Fixed diff --git a/README.md b/README.md index e1575e51..8b233bde 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,9 @@ stylua -g '*.lua' -g '!*.spec.lua' -- . # format all Lua files except test files Note, if you are using the glob argument, it can take in multiple strings, so `--` is required to break between the glob pattern and the files to format. -Glob Filtering is only used for directory searching - passing a file directly (e.g. `stylua foo.txt`) will override the glob. +By default, glob filtering (and `.styluaignore` files) are only applied for directory traversal and searching. +Files passed directly (e.g. `stylua foo.txt`) will override the glob / ignore and always be formatted. +To disable this behaviour, pass the `--respect-ignores` flag (`stylua --respect-ignores foo.txt`). ### Filtering using `.styluaignore` From 1babf3ad2eb8f48a0568084cb6f6c9e9ddb1c317 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 16 Sep 2023 15:28:04 -0500 Subject: [PATCH 3/4] Add tests --- Cargo.lock | 224 ++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 1 + src/cli/main.rs | 88 ++++++++++++++++++- 3 files changed, 296 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc2133b2..ec09c668 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstyle" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" + [[package]] name = "anyhow" version = "1.0.75" @@ -31,12 +37,27 @@ checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" dependencies = [ "bstr 0.2.16", "doc-comment", - "predicates", + "predicates 2.1.1", "predicates-core", "predicates-tree", "wait-timeout", ] +[[package]] +name = "assert_fs" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f070617a68e5c2ed5d06ee8dd620ee18fb72b99f6c094bed34cf8ab07c875b48" +dependencies = [ + "anstyle", + "doc-comment", + "globwalk", + "predicates 3.0.3", + "predicates-core", + "predicates-tree", + "tempfile", +] + [[package]] name = "atty" version = "0.2.14" @@ -66,6 +87,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "bstr" version = "0.2.16" @@ -105,6 +132,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -145,7 +181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_derive", "indexmap 1.7.0", "lazy_static", @@ -178,7 +214,7 @@ dependencies = [ "lazy_static", "libc", "unicode-width", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -331,6 +367,33 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +[[package]] +name = "errno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "fnv" version = "1.0.7" @@ -378,6 +441,17 @@ dependencies = [ "regex", ] +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + [[package]] name = "half" version = "1.7.1" @@ -502,9 +576,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.119" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "linked-hash-map" @@ -512,6 +586,12 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +[[package]] +name = "linux-raw-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" + [[package]] name = "log" version = "0.4.19" @@ -650,11 +730,23 @@ dependencies = [ "predicates-core", ] +[[package]] +name = "predicates" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" +dependencies = [ + "anstyle", + "difflib", + "itertools", + "predicates-core", +] + [[package]] name = "predicates-core" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" [[package]] name = "predicates-tree" @@ -733,6 +825,15 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.9.5" @@ -783,6 +884,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "rustversion" version = "1.0.9" @@ -932,6 +1046,7 @@ version = "0.18.2" dependencies = [ "anyhow", "assert_cmd", + "assert_fs", "cfg-if", "clap", "console", @@ -979,6 +1094,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -1234,7 +1362,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -1243,13 +1380,28 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1258,42 +1410,84 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "winnow" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 78b40b1f..965eded0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ wasm-bindgen = { version = "0.2.81", optional = true } criterion = "0.4.0" insta = { version = "1.12.0", features = ["glob"] } assert_cmd = "2.0.4" +assert_fs = "1.0.13" [[bench]] name = "date" diff --git a/src/cli/main.rs b/src/cli/main.rs index 553dba7c..4c19a428 100644 --- a/src/cli/main.rs +++ b/src/cli/main.rs @@ -664,10 +664,27 @@ fn main() { #[cfg(test)] mod tests { use assert_cmd::Command; + use assert_fs::prelude::*; + + macro_rules! construct_tree { + ({ $($file_name:literal:$file_contents:literal,)+ }) => {{ + let cwd = assert_fs::TempDir::new().unwrap(); + + $( + cwd.child($file_name).write_str($file_contents).unwrap(); + )+ + + cwd + }}; + } + + fn create_stylua() -> Command { + Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap() + } #[test] fn test_no_files_provided() { - let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap(); + let mut cmd = create_stylua(); cmd.assert() .failure() .code(2) @@ -676,11 +693,78 @@ mod tests { #[test] fn test_format_stdin() { - let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap(); + let mut cmd = create_stylua(); cmd.arg("-") .write_stdin("local x = 1") .assert() .success() .stdout("local x = 1\n"); } + + #[test] + fn test_format_file() { + let cwd = construct_tree!({ + "foo.lua": "local x = 1", + }); + + let mut cmd = create_stylua(); + cmd.current_dir(cwd.path()).arg(".").assert().success(); + + cwd.child("foo.lua").assert("local x = 1\n"); + + cwd.close().unwrap(); + } + + #[test] + fn test_stylua_ignore() { + let cwd = construct_tree!({ + ".styluaignore": "ignored/", + "foo.lua": "local x = 1", + "ignored/bar.lua": "local x = 1", + }); + + let mut cmd = create_stylua(); + cmd.current_dir(cwd.path()).arg(".").assert().success(); + + cwd.child("foo.lua").assert("local x = 1\n"); + cwd.child("ignored/bar.lua").assert("local x = 1"); + + cwd.close().unwrap(); + } + + #[test] + fn explicitly_provided_files_dont_check_ignores() { + let cwd = construct_tree!({ + ".styluaignore": "foo.lua", + "foo.lua": "local x = 1", + }); + + let mut cmd = create_stylua(); + cmd.current_dir(cwd.path()) + .arg("foo.lua") + .assert() + .success(); + + cwd.child("foo.lua").assert("local x = 1\n"); + + cwd.close().unwrap(); + } + + #[test] + fn test_respect_ignores() { + let cwd = construct_tree!({ + ".styluaignore": "foo.lua", + "foo.lua": "local x = 1", + }); + + let mut cmd = create_stylua(); + cmd.current_dir(cwd.path()) + .args(["--respect-ignores", "foo.lua"]) + .assert() + .success(); + + cwd.child("foo.lua").assert("local x = 1"); + + cwd.close().unwrap(); + } } From bbc05c9ecc3e971483526d8ff1a24fef88954bac Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 11 Nov 2023 11:32:55 +0100 Subject: [PATCH 4/4] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25d15113..1c432d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added flag `--respect-ignores`. By default, files explicitly passed to stylua (e.g. `stylua foo.lua`) will always be formatted, regardless of whether the file is ignored. Enabling this flag will consider `.styluaignore` or glob matches before formatting the file. + - Note: for backwards compatibility reasons, formatting via stdin always respects ignores. This behaviour will change in the next major release ## [0.18.2] - 2023-09-10