diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 5273ac994b..30ab001e97 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -12,7 +12,7 @@ env:
RUSTUP_MAX_RETRIES: 10
jobs:
- cargo_build:
+ cargo-build:
name: "cargo build"
runs-on: ubuntu-latest
steps:
@@ -45,8 +45,11 @@ jobs:
- run: ./target/release/ruff_dev generate-json-schema
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. You may have to rerun 'cargo dev generate-json-schema'."
- run: git diff --exit-code -- ruff.schema.json
+ - run: ./target/release/ruff_dev generate-playground-options
+ - run: git diff --quiet playground/src/ruff_options.rs || echo "::error file=playground/src/ruff_options.ts::This file is outdated. You may have to rerun 'cargo dev generate-playground-options'."
+ - run: git diff --exit-code -- README.md src/checks_gen.rs playground/src/ruff_options.ts
- cargo_fmt:
+ cargo-fmt:
name: "cargo fmt"
runs-on: ubuntu-latest
steps:
@@ -82,6 +85,7 @@ jobs:
toolchain: nightly-2022-11-01
override: true
components: clippy
+ target: wasm32-unknown-unknown
- uses: actions/cache@v3
env:
cache-name: cache-cargo
@@ -95,8 +99,9 @@ jobs:
${{ runner.os }}-build-
${{ runner.os }}-
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
+ - run: cargo clippy --workspace --target wasm32-unknown-unknown --all-features -- -D warnings -W clippy::pedantic
- cargo_test:
+ cargo-test:
name: "cargo test"
runs-on: ubuntu-latest
steps:
@@ -122,7 +127,32 @@ jobs:
- run: cargo test --all
- run: cargo test --package ruff --test black_compatibility_test -- --ignored
- maturin_build:
+ wasm-pack-test:
+ name: "wasm-pack test"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: nightly-2022-11-01
+ override: true
+ - uses: actions/cache@v3
+ env:
+ cache-name: cache-cargo
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-build-${{ env.cache-name }}-
+ ${{ runner.os }}-build-
+ ${{ runner.os }}-
+ - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+ - run: wasm-pack test --node
+
+ maturin-build:
name: "maturin build"
runs-on: ubuntu-latest
steps:
diff --git a/.github/workflows/playground.yaml b/.github/workflows/playground.yaml
new file mode 100644
index 0000000000..ac400e9514
--- /dev/null
+++ b/.github/workflows/playground.yaml
@@ -0,0 +1,57 @@
+name: Playground
+
+on:
+ workflow_dispatch:
+ push:
+ branches: [main]
+
+env:
+ CARGO_INCREMENTAL: 0
+ CARGO_NET_RETRY: 10
+ RUSTUP_MAX_RETRIES: 10
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: nightly-2022-11-01
+ override: true
+ target: wasm32-unknown-unknown
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ cache: 'npm'
+ cache-dependency-path: playground/package-lock.json
+ - uses: actions/cache@v3
+ env:
+ cache-name: cache-cargo
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-build-${{ env.cache-name }}-
+ ${{ runner.os }}-build-
+ ${{ runner.os }}-
+ - name: "Install wasm-pack"
+ run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+ - name: "Run wasm-pack"
+ run: wasm-pack build --target web --out-dir playground/src/pkg
+ - name: "Install Node dependencies"
+ run: npm ci
+ working-directory: playground
+ - name: "Build JavaScript bundle"
+ run: npm run build
+ working-directory: playground
+ - name: "Deploy to Cloudflare Pages"
+ uses: cloudflare/wrangler-action@2.0.0
+ with:
+ apiToken: ${{ secrets.CF_API_TOKEN }}
+ accountId: ${{ secrets.CF_ACCOUNT_ID }}
+ workingDirectory: playground
+ command: pages publish dist --project-name=ruff
diff --git a/Cargo.lock b/Cargo.lock
index 536b081283..058b0515c5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,9 +61,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.66"
+version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
+checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
[[package]]
name = "ascii"
@@ -86,7 +86,7 @@ version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa3d466004a8b4cb1bc34044240a2fd29d17607e2e3bd613eb44fd48e8100da3"
dependencies = [
- "bstr 1.0.1",
+ "bstr 1.1.0",
"doc-comment",
"predicates",
"predicates-core",
@@ -160,9 +160,9 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd"
+checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
dependencies = [
"memchr",
"once_cell",
@@ -193,9 +193,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.0.77"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
+checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
@@ -280,9 +280,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.0.29"
+version = "4.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
+checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
dependencies = [
"bitflags",
"clap_derive",
@@ -295,11 +295,11 @@ dependencies = [
[[package]]
name = "clap_complete"
-version = "4.0.6"
+version = "4.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7b3c9eae0de7bf8e3f904a5e40612b21fb2e2e566456d177809a48b892d24da"
+checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
dependencies = [
- "clap 4.0.29",
+ "clap 4.0.32",
]
[[package]]
@@ -308,7 +308,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4160b4a4f72ef58bd766bad27c09e6ef1cc9d82a22f6a0f55d152985a4a48e31"
dependencies = [
- "clap 4.0.29",
+ "clap 4.0.32",
"clap_complete",
"clap_complete_fig",
]
@@ -319,7 +319,7 @@ version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
dependencies = [
- "clap 4.0.29",
+ "clap 4.0.32",
"clap_complete",
]
@@ -422,6 +422,26 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "console_error_panic_hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
+dependencies = [
+ "cfg-if 1.0.0",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "console_log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494"
+dependencies = [
+ "log",
+ "web-sys",
+]
+
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
@@ -524,9 +544,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "cxx"
-version = "1.0.83"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf"
+checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd"
dependencies = [
"cc",
"cxxbridge-flags",
@@ -536,9 +556,9 @@ dependencies = [
[[package]]
name = "cxx-build"
-version = "1.0.83"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39"
+checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0"
dependencies = [
"cc",
"codespan-reporting",
@@ -551,15 +571,15 @@ dependencies = [
[[package]]
name = "cxxbridge-flags"
-version = "1.0.83"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12"
+checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59"
[[package]]
name = "cxxbridge-macro"
-version = "1.0.83"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6"
+checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
dependencies = [
"proc-macro2",
"quote",
@@ -712,9 +732,9 @@ dependencies = [
[[package]]
name = "filetime"
-version = "0.2.18"
+version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
+checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
dependencies = [
"cfg-if 1.0.0",
"libc",
@@ -733,7 +753,7 @@ name = "flake8-to-ruff"
version = "0.0.194-dev.0"
dependencies = [
"anyhow",
- "clap 4.0.29",
+ "clap 4.0.32",
"configparser",
"once_cell",
"regex",
@@ -952,9 +972,9 @@ dependencies = [
[[package]]
name = "insta"
-version = "1.22.0"
+version = "1.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "197f4e300af8b23664d4077bf5c40e0afa9ba66a567bb5a51d3def3c7b287d1c"
+checksum = "e48b08a091dfe5b09a6a9688c468fdd5b4396e92ce09e2eb932f0884b02788a4"
dependencies = [
"console",
"lazy_static",
@@ -985,9 +1005,9 @@ dependencies = [
[[package]]
name = "is-terminal"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
+checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
@@ -1006,9 +1026,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "joinery"
@@ -1115,9 +1135,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.138"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "libcst"
@@ -1145,9 +1165,9 @@ dependencies = [
[[package]]
name = "link-cplusplus"
-version = "1.0.7"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
dependencies = [
"cc",
]
@@ -1160,9 +1180,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
-version = "0.1.3"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
+checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "lock_api"
@@ -1340,11 +1360,11 @@ dependencies = [
[[package]]
name = "num_cpus"
-version = "1.14.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "hermit-abi 0.1.19",
+ "hermit-abi 0.2.6",
"libc",
]
@@ -1391,9 +1411,9 @@ dependencies = [
[[package]]
name = "paste"
-version = "1.0.9"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
+checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
[[package]]
name = "path-absolutize"
@@ -1631,9 +1651,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
@@ -1663,9 +1683,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@@ -1759,11 +1779,10 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.6.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
+checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
- "crossbeam-deque",
"either",
"rayon-core",
]
@@ -1868,12 +1887,15 @@ dependencies = [
"bincode",
"bitflags",
"cachedir",
+ "cfg-if 1.0.0",
"chrono",
- "clap 4.0.29",
+ "clap 4.0.32",
"clap_complete_command",
"clearscreen",
"colored",
"common-path",
+ "console_error_panic_hook",
+ "console_log",
"criterion",
"dirs 4.0.0",
"fern",
@@ -1884,6 +1906,7 @@ dependencies = [
"ignore",
"insta",
"itertools",
+ "js-sys",
"libcst",
"log",
"natord",
@@ -1904,6 +1927,7 @@ dependencies = [
"schemars",
"semver",
"serde",
+ "serde-wasm-bindgen",
"serde_json",
"shellexpand",
"strum",
@@ -1915,6 +1939,8 @@ dependencies = [
"update-informer",
"ureq",
"walkdir",
+ "wasm-bindgen",
+ "wasm-bindgen-test",
]
[[package]]
@@ -1922,7 +1948,7 @@ name = "ruff_dev"
version = "0.0.194"
dependencies = [
"anyhow",
- "clap 4.0.29",
+ "clap 4.0.32",
"codegen",
"itertools",
"libcst",
@@ -1935,6 +1961,7 @@ dependencies = [
"serde_json",
"strum",
"strum_macros",
+ "textwrap",
]
[[package]]
@@ -1955,9 +1982,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
-version = "0.36.4"
+version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23"
+checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
dependencies = [
"bitflags",
"errno",
@@ -2056,15 +2083,15 @@ dependencies = [
[[package]]
name = "rustversion"
-version = "1.0.9"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
+checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "same-file"
@@ -2099,6 +2126,12 @@ dependencies = [
"syn",
]
+[[package]]
+name = "scoped-tls"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
+
[[package]]
name = "scopeguard"
version = "1.1.0"
@@ -2107,9 +2140,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "scratch"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
+checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
[[package]]
name = "sct"
@@ -2129,18 +2162,29 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
[[package]]
name = "serde"
-version = "1.0.148"
+version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
+checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
dependencies = [
"serde_derive",
]
[[package]]
-name = "serde_derive"
-version = "1.0.148"
+name = "serde-wasm-bindgen"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
+checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
+dependencies = [
+ "js-sys",
+ "serde",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
dependencies = [
"proc-macro2",
"quote",
@@ -2216,9 +2260,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "str_indices"
-version = "0.4.0"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d9199fa80c817e074620be84374a520062ebac833f358d74b37060ce4a0f2c0"
+checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd"
[[package]]
name = "string_cache"
@@ -2263,9 +2307,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.105"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -2370,18 +2414,18 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.37"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.37"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
@@ -2455,9 +2499,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.5.9"
+version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
dependencies = [
"serde",
]
@@ -2544,9 +2588,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-linebreak"
@@ -2715,6 +2759,18 @@ dependencies = [
"wasm-bindgen-shared",
]
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
+dependencies = [
+ "cfg-if 1.0.0",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
@@ -2744,6 +2800,30 @@ version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+[[package]]
+name = "wasm-bindgen-test"
+version = "0.3.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d"
+dependencies = [
+ "console_error_panic_hook",
+ "js-sys",
+ "scoped-tls",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-bindgen-test-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-test-macro"
+version = "0.3.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
[[package]]
name = "web-sys"
version = "0.3.60"
@@ -2766,9 +2846,9 @@ dependencies = [
[[package]]
name = "webpki-roots"
-version = "0.22.5"
+version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
+checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
dependencies = [
"webpki",
]
diff --git a/Cargo.toml b/Cargo.toml
index 955a583f48..6b2965b8cc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,7 @@ rust-version = "1.65.0"
[lib]
name = "ruff"
+crate-type = ["cdylib", "rlib"]
[dependencies]
annotate-snippets = { version = "0.9.1", features = ["color"] }
@@ -20,9 +21,10 @@ atty = { version = "0.2.14" }
bincode = { version = "1.3.3" }
bitflags = { version = "1.3.2" }
cachedir = { version = "0.3.0" }
+cfg-if = { version = "1.0.0" }
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
clap = { version = "4.0.1", features = ["derive"] }
-clap_complete_command = "0.4.0"
+clap_complete_command = { version = "0.4.0" }
colored = { version = "2.0.0" }
common-path = { version = "1.0.0" }
dirs = { version = "4.0.0" }
@@ -41,7 +43,6 @@ num-bigint = { version = "0.4.3" }
once_cell = { version = "1.16.0" }
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
quick-junit = { version = "0.3.2" }
-rayon = { version = "1.5.3" }
regex = { version = "1.6.0" }
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
ruff_macros = { version = "0.0.194", path = "ruff_macros" }
@@ -59,23 +60,32 @@ strum_macros = { version = "0.24.3" }
textwrap = { version = "0.16.0" }
titlecase = { version = "2.2.1" }
toml = { version = "0.5.9" }
-update-informer = { version = "0.5.0", default-features = false, features = ["pypi"], optional = true }
walkdir = { version = "2.3.2" }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
-clearscreen = { version = "1.0.10" } # uses which
+clearscreen = { version = "1.0.10" }
+rayon = { version = "1.5.3" }
+update-informer = { version = "0.5.0", default-features = false, features = ["pypi"], optional = true }
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
# For (future) wasm-pack support
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
getrandom = { version = "0.2.7", features = ["js"] }
+console_error_panic_hook = { version = "0.1.7" }
+console_log = { version = "0.2.0" }
+serde-wasm-bindgen = { version = "0.4" }
+js-sys = { version = "0.3.60" }
+wasm-bindgen = { version = "0.2.83" }
[dev-dependencies]
-assert_cmd = { version = "2.0.4" }
-criterion = { version = "0.4.0" }
insta = { version = "1.19.1", features = ["yaml"] }
test-case = { version = "2.2.2" }
ureq = { version = "2.5.0", features = [] }
+wasm-bindgen-test = { version = "0.3.33" }
+
+[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
+assert_cmd = { version = "2.0.4" }
+criterion = { version = "0.4.0" }
[features]
default = ["update-informer"]
@@ -93,6 +103,11 @@ opt-level = 3
[profile.dev.package.similar]
opt-level = 3
+# Reduce complexity of a parser function that would trigger a locals limit in a wasm tool.
+# https://github.com/bytecodealliance/wasm-tools/blob/b5c3d98e40590512a3b12470ef358d5c7b983b15/crates/wasmparser/src/limits.rs#L29
+[profile.dev.package.rustpython-parser]
+opt-level = 1
+
[[bench]]
name = "source_code_locator"
harness = false
diff --git a/playground/.gitignore b/playground/.gitignore
new file mode 100644
index 0000000000..a547bf36d8
--- /dev/null
+++ b/playground/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/playground/index.html b/playground/index.html
new file mode 100644
index 0000000000..64adf3868f
--- /dev/null
+++ b/playground/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Ruff Playground
+
+
+
+
+
+
diff --git a/playground/package-lock.json b/playground/package-lock.json
new file mode 100644
index 0000000000..9fb3a44df1
--- /dev/null
+++ b/playground/package-lock.json
@@ -0,0 +1,1517 @@
+{
+ "name": "playground",
+ "version": "0.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "playground",
+ "version": "0.0.0",
+ "dependencies": {
+ "@monaco-editor/react": "^4.4.6",
+ "lz-string": "^1.4.4",
+ "monaco-editor": "^0.34.1",
+ "prettier": "^2.8.1",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.26",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react-swc": "^3.0.0",
+ "typescript": "^4.9.3",
+ "vite": "^4.0.0"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.9.tgz",
+ "integrity": "sha512-kW5ccqWHVOOTGUkkJbtfoImtqu3kA1PFkivM+9QPFSHphPfPBlBalX9eDRqPK+wHCqKhU48/78T791qPgC9e9A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.9.tgz",
+ "integrity": "sha512-ndIAZJUeLx4O+4AJbFQCurQW4VRUXjDsUvt1L+nP8bVELOWdmdCEOtlIweCUE6P+hU0uxYbEK2AEP0n5IVQvhg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.9.tgz",
+ "integrity": "sha512-UbMcJB4EHrAVOnknQklREPgclNU2CPet2h+sCBCXmF2mfoYWopBn/CfTfeyOkb/JglOcdEADqAljFndMKnFtOw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.9.tgz",
+ "integrity": "sha512-d7D7/nrt4CxPul98lx4PXhyNZwTYtbdaHhOSdXlZuu5zZIznjqtMqLac8Bv+IuT6SVHiHUwrkL6ywD7mOgLW+A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.9.tgz",
+ "integrity": "sha512-LZc+Wlz06AkJYtwWsBM3x2rSqTG8lntDuftsUNQ3fCx9ZttYtvlDcVtgb+NQ6t9s6K5No5zutN3pcjZEC2a4iQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.9.tgz",
+ "integrity": "sha512-gIj0UQZlQo93CHYouHKkpzP7AuruSaMIm1etcWIxccFEVqCN1xDr6BWlN9bM+ol/f0W9w3hx3HDuEwcJVtGneQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.9.tgz",
+ "integrity": "sha512-GNors4vaMJ7lzGOuhzNc7jvgsQZqErGA8rsW+nck8N1nYu86CvsJW2seigVrQQWOV4QzEP8Zf3gm+QCjA2hnBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.9.tgz",
+ "integrity": "sha512-cNx1EF99c2t1Ztn0lk9N+MuwBijGF8mH6nx9GFsB3e0lpUpPkCE/yt5d+7NP9EwJf5uzqdjutgVYoH1SNqzudA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.9.tgz",
+ "integrity": "sha512-YPxQunReYp8RQ1FvexFrOEqqf+nLbS3bKVZF5FRT2uKM7Wio7BeATqAwO02AyrdSEntt3I5fhFsujUChIa8CZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.9.tgz",
+ "integrity": "sha512-zb12ixDIKNwFpIqR00J88FFitVwOEwO78EiUi8wi8FXlmSc3GtUuKV/BSO+730Kglt0B47+ZrJN1BhhOxZaVrw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.9.tgz",
+ "integrity": "sha512-X8te4NLxtHiNT6H+4Pfm5RklzItA1Qy4nfyttihGGX+Koc53Ar20ViC+myY70QJ8PDEOehinXZj/F7QK3A+MKQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.9.tgz",
+ "integrity": "sha512-ZqyMDLt02c5smoS3enlF54ndK5zK4IpClLTxF0hHfzHJlfm4y8IAkIF8LUW0W7zxcKy7oAwI7BRDqeVvC120SA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.9.tgz",
+ "integrity": "sha512-k+ca5W5LDBEF3lfDwMV6YNXwm4wEpw9krMnNvvlNz3MrKSD2Eb2c861O0MaKrZkG/buTQAP4vkavbLwgIe6xjg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.9.tgz",
+ "integrity": "sha512-GuInVdogjmg9DhgkEmNipHkC+3tzkanPJzgzTC2ihsvrruLyFoR1YrTGixblNSMPudQLpiqkcwGwwe0oqfrvfA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.9.tgz",
+ "integrity": "sha512-49wQ0aYkvwXonGsxc7LuuLNICMX8XtO92Iqmug5Qau0kpnV6SP34jk+jIeu4suHwAbSbRhVFtDv75yRmyfQcHw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.9.tgz",
+ "integrity": "sha512-Nx4oKEAJ6EcQlt4dK7qJyuZUoXZG7CAeY22R7rqZijFzwFfMOD+gLP56uV7RrV86jGf8PeRY8TBsRmOcZoG42w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.9.tgz",
+ "integrity": "sha512-d0WnpgJ+FTiMZXEQ1NOv9+0gvEhttbgKEvVqWWAtl1u9AvlspKXbodKHzQ5MLP6YV1y52Xp+p8FMYqj8ykTahg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.9.tgz",
+ "integrity": "sha512-jccK11278dvEscHFfMk5EIPjF4wv1qGD0vps7mBV1a6TspdR36O28fgPem/SA/0pcsCPHjww5ouCLwP+JNAFlw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.9.tgz",
+ "integrity": "sha512-OetwTSsv6mIDLqN7I7I2oX9MmHGwG+AP+wKIHvq+6sIHwcPPJqRx+DJB55jy9JG13CWcdcQno/7V5MTJ5a0xfQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.9.tgz",
+ "integrity": "sha512-tKSSSK6unhxbGbHg+Cc+JhRzemkcsX0tPBvG0m5qsWbkShDK9c+/LSb13L18LWVdOQZwuA55Vbakxmt6OjBDOQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.9.tgz",
+ "integrity": "sha512-ZTQ5vhNS5gli0KK8I6/s6+LwXmNEfq1ftjnSVyyNm33dBw8zDpstqhGXYUbZSWWLvkqiRRjgxgmoncmi6Yy7Ng==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.9.tgz",
+ "integrity": "sha512-C4ZX+YFIp6+lPrru3tpH6Gaapy8IBRHw/e7l63fzGDhn/EaiGpQgbIlT5paByyy+oMvRFQoxxyvC4LE0AjJMqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@monaco-editor/loader": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.3.2.tgz",
+ "integrity": "sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g==",
+ "dependencies": {
+ "state-local": "^1.0.6"
+ },
+ "peerDependencies": {
+ "monaco-editor": ">= 0.21.0 < 1"
+ }
+ },
+ "node_modules/@monaco-editor/react": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.4.6.tgz",
+ "integrity": "sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==",
+ "dependencies": {
+ "@monaco-editor/loader": "^1.3.2",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "monaco-editor": ">= 0.25.0 < 1",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@swc/core": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.23.tgz",
+ "integrity": "sha512-Aa7yw5+7ErOxr+G0J1eU2hkb9nEMSdt1Ye3isdAgg9mrsPuttk+cfLp6nP/Lux/VUnu5k4eOxeTy9UhjJhRAFw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "swcx": "run_swcx.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.3.23",
+ "@swc/core-darwin-x64": "1.3.23",
+ "@swc/core-linux-arm-gnueabihf": "1.3.23",
+ "@swc/core-linux-arm64-gnu": "1.3.23",
+ "@swc/core-linux-arm64-musl": "1.3.23",
+ "@swc/core-linux-x64-gnu": "1.3.23",
+ "@swc/core-linux-x64-musl": "1.3.23",
+ "@swc/core-win32-arm64-msvc": "1.3.23",
+ "@swc/core-win32-ia32-msvc": "1.3.23",
+ "@swc/core-win32-x64-msvc": "1.3.23"
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.23.tgz",
+ "integrity": "sha512-IGOEHmE4aBDX7gQWpanI3A0ni47UcvX7rmcy0H8kE6mm/y7mEMWskvNsYhYzJl4GVZgw38v1/lL/A7MRX6g71A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.23.tgz",
+ "integrity": "sha512-eQSN+JJqx/5Dk2C5uet2l7HifGsDBorQHD3PAVnge5jxl+rXU/zbzX9Un56+uuUB0QYeS4Dyr8cN7NHuIKGxBA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.23.tgz",
+ "integrity": "sha512-zxYvggbw6R/sTNey0qgsigFMY59DYepm1+JNojxOKjbnvxmgyeIa5sPdu/5gLj0TtJOiWvSGrpMPNUIVreUSGA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.23.tgz",
+ "integrity": "sha512-l8UWhcNvZ6RzNZBBToMYuKYijF0h7mbw2RuFV5rpCYF/k/Wh85PaDHPQIQ6qjMHJsIBHYXUt0HLAP+fiAfBiDw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.23.tgz",
+ "integrity": "sha512-TZDPp1wUE1ynVyY0vwIToyOULKEQ91H49R+p6Iu/2YY+UQQwUamhX0Gp8O85RT+j72/iHyhbQkz7yRg6v+GB5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.23.tgz",
+ "integrity": "sha512-rKqWnOmUyQfoKZuuXs/S0RNobN+kcUyMtwoCdRdCNqOlk1XZRCMpjGc9Aqn73K3xlZ6JXX6oLrXKn375b2dydw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.23.tgz",
+ "integrity": "sha512-1MK9eocIhuIr/+yUKnTNHpYovMQvfKTJQbU4UMfQLg2qyCGKAvO+jOy5JIGR9x04MWqz9U3EHHS/7Id35ekhFQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.23.tgz",
+ "integrity": "sha512-3nmdugj0SJIGWeCJBhvPWIfnE2Ax8H2KZsJfcaWmWg0SDh19aAt48Ncyd8WHHBandJmVm2fSjaANSjp+cS2S9A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.23.tgz",
+ "integrity": "sha512-2AlGRhys1BsfLjXyWOd+5J/Ko2kkVQVuy3ZR8OBGy7XI54p0PpepabloYI9irr+4bi9vtyxoc5rS21PmJxB83Q==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.23.tgz",
+ "integrity": "sha512-qYKP8sIM7VVLuDb5BkRBoHy28OHZWrUhPTO7WgpErhVVM9wnzmMi/Jgg8SyfMy6oheBjO0QiwWbXONxBwByjnQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
+ "dev": true
+ },
+ "node_modules/@types/react": {
+ "version": "18.0.26",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
+ "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
+ "dev": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.0.9",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.9.tgz",
+ "integrity": "sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
+ "dev": true
+ },
+ "node_modules/@vitejs/plugin-react-swc": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.0.1.tgz",
+ "integrity": "sha512-3GQ2oruZO9j8dSHcI0MUeOZQBhjYyDQsF/pKY4Px+CJxn0M16OhgFeEzUjeuwci4zhhjoNIDE9aFNaV5GMQ09g==",
+ "dev": true,
+ "dependencies": {
+ "@swc/core": "^1.3.22"
+ },
+ "peerDependencies": {
+ "vite": "^4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
+ "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
+ "dev": true
+ },
+ "node_modules/esbuild": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.9.tgz",
+ "integrity": "sha512-gkH83yHyijMSZcZFs1IWew342eMdFuWXmQo3zkDPTre25LIPBJsXryg02M3u8OpTwCJdBkdaQwqKkDLnAsAeLQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.16.9",
+ "@esbuild/android-arm64": "0.16.9",
+ "@esbuild/android-x64": "0.16.9",
+ "@esbuild/darwin-arm64": "0.16.9",
+ "@esbuild/darwin-x64": "0.16.9",
+ "@esbuild/freebsd-arm64": "0.16.9",
+ "@esbuild/freebsd-x64": "0.16.9",
+ "@esbuild/linux-arm": "0.16.9",
+ "@esbuild/linux-arm64": "0.16.9",
+ "@esbuild/linux-ia32": "0.16.9",
+ "@esbuild/linux-loong64": "0.16.9",
+ "@esbuild/linux-mips64el": "0.16.9",
+ "@esbuild/linux-ppc64": "0.16.9",
+ "@esbuild/linux-riscv64": "0.16.9",
+ "@esbuild/linux-s390x": "0.16.9",
+ "@esbuild/linux-x64": "0.16.9",
+ "@esbuild/netbsd-x64": "0.16.9",
+ "@esbuild/openbsd-x64": "0.16.9",
+ "@esbuild/sunos-x64": "0.16.9",
+ "@esbuild/win32-arm64": "0.16.9",
+ "@esbuild/win32-ia32": "0.16.9",
+ "@esbuild/win32-x64": "0.16.9"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lz-string": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
+ "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==",
+ "bin": {
+ "lz-string": "bin/bin.js"
+ }
+ },
+ "node_modules/monaco-editor": {
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz",
+ "integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/postcss": {
+ "version": "8.4.20",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
+ "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz",
+ "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "3.7.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.5.tgz",
+ "integrity": "sha512-z0ZbqHBtS/et2EEUKMrAl2CoSdwN7ZPzL17UMiKN9RjjqHShTlv7F9J6ZJZJNREYjBh3TvBrdfjkFDIXFNeuiQ==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/state-local": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+ "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.1.tgz",
+ "integrity": "sha512-kZQPzbDau35iWOhy3CpkrRC7It+HIHtulAzBhMqzGHKRf/4+vmh8rPDDdv98SWQrFWo6//3ozwsRmwQIPZsK9g==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.16.3",
+ "postcss": "^8.4.20",
+ "resolve": "^1.22.1",
+ "rollup": "^3.7.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@types/node": ">= 14",
+ "less": "*",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ }
+ },
+ "dependencies": {
+ "@esbuild/android-arm": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.9.tgz",
+ "integrity": "sha512-kW5ccqWHVOOTGUkkJbtfoImtqu3kA1PFkivM+9QPFSHphPfPBlBalX9eDRqPK+wHCqKhU48/78T791qPgC9e9A==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.9.tgz",
+ "integrity": "sha512-ndIAZJUeLx4O+4AJbFQCurQW4VRUXjDsUvt1L+nP8bVELOWdmdCEOtlIweCUE6P+hU0uxYbEK2AEP0n5IVQvhg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.9.tgz",
+ "integrity": "sha512-UbMcJB4EHrAVOnknQklREPgclNU2CPet2h+sCBCXmF2mfoYWopBn/CfTfeyOkb/JglOcdEADqAljFndMKnFtOw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.9.tgz",
+ "integrity": "sha512-d7D7/nrt4CxPul98lx4PXhyNZwTYtbdaHhOSdXlZuu5zZIznjqtMqLac8Bv+IuT6SVHiHUwrkL6ywD7mOgLW+A==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.9.tgz",
+ "integrity": "sha512-LZc+Wlz06AkJYtwWsBM3x2rSqTG8lntDuftsUNQ3fCx9ZttYtvlDcVtgb+NQ6t9s6K5No5zutN3pcjZEC2a4iQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.9.tgz",
+ "integrity": "sha512-gIj0UQZlQo93CHYouHKkpzP7AuruSaMIm1etcWIxccFEVqCN1xDr6BWlN9bM+ol/f0W9w3hx3HDuEwcJVtGneQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.9.tgz",
+ "integrity": "sha512-GNors4vaMJ7lzGOuhzNc7jvgsQZqErGA8rsW+nck8N1nYu86CvsJW2seigVrQQWOV4QzEP8Zf3gm+QCjA2hnBQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.9.tgz",
+ "integrity": "sha512-cNx1EF99c2t1Ztn0lk9N+MuwBijGF8mH6nx9GFsB3e0lpUpPkCE/yt5d+7NP9EwJf5uzqdjutgVYoH1SNqzudA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.9.tgz",
+ "integrity": "sha512-YPxQunReYp8RQ1FvexFrOEqqf+nLbS3bKVZF5FRT2uKM7Wio7BeATqAwO02AyrdSEntt3I5fhFsujUChIa8CZg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ia32": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.9.tgz",
+ "integrity": "sha512-zb12ixDIKNwFpIqR00J88FFitVwOEwO78EiUi8wi8FXlmSc3GtUuKV/BSO+730Kglt0B47+ZrJN1BhhOxZaVrw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.9.tgz",
+ "integrity": "sha512-X8te4NLxtHiNT6H+4Pfm5RklzItA1Qy4nfyttihGGX+Koc53Ar20ViC+myY70QJ8PDEOehinXZj/F7QK3A+MKQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-mips64el": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.9.tgz",
+ "integrity": "sha512-ZqyMDLt02c5smoS3enlF54ndK5zK4IpClLTxF0hHfzHJlfm4y8IAkIF8LUW0W7zxcKy7oAwI7BRDqeVvC120SA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ppc64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.9.tgz",
+ "integrity": "sha512-k+ca5W5LDBEF3lfDwMV6YNXwm4wEpw9krMnNvvlNz3MrKSD2Eb2c861O0MaKrZkG/buTQAP4vkavbLwgIe6xjg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-riscv64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.9.tgz",
+ "integrity": "sha512-GuInVdogjmg9DhgkEmNipHkC+3tzkanPJzgzTC2ihsvrruLyFoR1YrTGixblNSMPudQLpiqkcwGwwe0oqfrvfA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-s390x": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.9.tgz",
+ "integrity": "sha512-49wQ0aYkvwXonGsxc7LuuLNICMX8XtO92Iqmug5Qau0kpnV6SP34jk+jIeu4suHwAbSbRhVFtDv75yRmyfQcHw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.9.tgz",
+ "integrity": "sha512-Nx4oKEAJ6EcQlt4dK7qJyuZUoXZG7CAeY22R7rqZijFzwFfMOD+gLP56uV7RrV86jGf8PeRY8TBsRmOcZoG42w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/netbsd-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.9.tgz",
+ "integrity": "sha512-d0WnpgJ+FTiMZXEQ1NOv9+0gvEhttbgKEvVqWWAtl1u9AvlspKXbodKHzQ5MLP6YV1y52Xp+p8FMYqj8ykTahg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/openbsd-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.9.tgz",
+ "integrity": "sha512-jccK11278dvEscHFfMk5EIPjF4wv1qGD0vps7mBV1a6TspdR36O28fgPem/SA/0pcsCPHjww5ouCLwP+JNAFlw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/sunos-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.9.tgz",
+ "integrity": "sha512-OetwTSsv6mIDLqN7I7I2oX9MmHGwG+AP+wKIHvq+6sIHwcPPJqRx+DJB55jy9JG13CWcdcQno/7V5MTJ5a0xfQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-arm64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.9.tgz",
+ "integrity": "sha512-tKSSSK6unhxbGbHg+Cc+JhRzemkcsX0tPBvG0m5qsWbkShDK9c+/LSb13L18LWVdOQZwuA55Vbakxmt6OjBDOQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-ia32": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.9.tgz",
+ "integrity": "sha512-ZTQ5vhNS5gli0KK8I6/s6+LwXmNEfq1ftjnSVyyNm33dBw8zDpstqhGXYUbZSWWLvkqiRRjgxgmoncmi6Yy7Ng==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-x64": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.9.tgz",
+ "integrity": "sha512-C4ZX+YFIp6+lPrru3tpH6Gaapy8IBRHw/e7l63fzGDhn/EaiGpQgbIlT5paByyy+oMvRFQoxxyvC4LE0AjJMqQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@monaco-editor/loader": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.3.2.tgz",
+ "integrity": "sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g==",
+ "requires": {
+ "state-local": "^1.0.6"
+ }
+ },
+ "@monaco-editor/react": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.4.6.tgz",
+ "integrity": "sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==",
+ "requires": {
+ "@monaco-editor/loader": "^1.3.2",
+ "prop-types": "^15.7.2"
+ }
+ },
+ "@swc/core": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.23.tgz",
+ "integrity": "sha512-Aa7yw5+7ErOxr+G0J1eU2hkb9nEMSdt1Ye3isdAgg9mrsPuttk+cfLp6nP/Lux/VUnu5k4eOxeTy9UhjJhRAFw==",
+ "dev": true,
+ "requires": {
+ "@swc/core-darwin-arm64": "1.3.23",
+ "@swc/core-darwin-x64": "1.3.23",
+ "@swc/core-linux-arm-gnueabihf": "1.3.23",
+ "@swc/core-linux-arm64-gnu": "1.3.23",
+ "@swc/core-linux-arm64-musl": "1.3.23",
+ "@swc/core-linux-x64-gnu": "1.3.23",
+ "@swc/core-linux-x64-musl": "1.3.23",
+ "@swc/core-win32-arm64-msvc": "1.3.23",
+ "@swc/core-win32-ia32-msvc": "1.3.23",
+ "@swc/core-win32-x64-msvc": "1.3.23"
+ }
+ },
+ "@swc/core-darwin-arm64": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.23.tgz",
+ "integrity": "sha512-IGOEHmE4aBDX7gQWpanI3A0ni47UcvX7rmcy0H8kE6mm/y7mEMWskvNsYhYzJl4GVZgw38v1/lL/A7MRX6g71A==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-darwin-x64": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.23.tgz",
+ "integrity": "sha512-eQSN+JJqx/5Dk2C5uet2l7HifGsDBorQHD3PAVnge5jxl+rXU/zbzX9Un56+uuUB0QYeS4Dyr8cN7NHuIKGxBA==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-arm-gnueabihf": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.23.tgz",
+ "integrity": "sha512-zxYvggbw6R/sTNey0qgsigFMY59DYepm1+JNojxOKjbnvxmgyeIa5sPdu/5gLj0TtJOiWvSGrpMPNUIVreUSGA==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-arm64-gnu": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.23.tgz",
+ "integrity": "sha512-l8UWhcNvZ6RzNZBBToMYuKYijF0h7mbw2RuFV5rpCYF/k/Wh85PaDHPQIQ6qjMHJsIBHYXUt0HLAP+fiAfBiDw==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-arm64-musl": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.23.tgz",
+ "integrity": "sha512-TZDPp1wUE1ynVyY0vwIToyOULKEQ91H49R+p6Iu/2YY+UQQwUamhX0Gp8O85RT+j72/iHyhbQkz7yRg6v+GB5A==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-x64-gnu": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.23.tgz",
+ "integrity": "sha512-rKqWnOmUyQfoKZuuXs/S0RNobN+kcUyMtwoCdRdCNqOlk1XZRCMpjGc9Aqn73K3xlZ6JXX6oLrXKn375b2dydw==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-linux-x64-musl": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.23.tgz",
+ "integrity": "sha512-1MK9eocIhuIr/+yUKnTNHpYovMQvfKTJQbU4UMfQLg2qyCGKAvO+jOy5JIGR9x04MWqz9U3EHHS/7Id35ekhFQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-win32-arm64-msvc": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.23.tgz",
+ "integrity": "sha512-3nmdugj0SJIGWeCJBhvPWIfnE2Ax8H2KZsJfcaWmWg0SDh19aAt48Ncyd8WHHBandJmVm2fSjaANSjp+cS2S9A==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-win32-ia32-msvc": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.23.tgz",
+ "integrity": "sha512-2AlGRhys1BsfLjXyWOd+5J/Ko2kkVQVuy3ZR8OBGy7XI54p0PpepabloYI9irr+4bi9vtyxoc5rS21PmJxB83Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@swc/core-win32-x64-msvc": {
+ "version": "1.3.23",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.23.tgz",
+ "integrity": "sha512-qYKP8sIM7VVLuDb5BkRBoHy28OHZWrUhPTO7WgpErhVVM9wnzmMi/Jgg8SyfMy6oheBjO0QiwWbXONxBwByjnQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
+ "dev": true
+ },
+ "@types/react": {
+ "version": "18.0.26",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
+ "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
+ "dev": true,
+ "requires": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@types/react-dom": {
+ "version": "18.0.9",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.9.tgz",
+ "integrity": "sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/scheduler": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
+ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
+ "dev": true
+ },
+ "@vitejs/plugin-react-swc": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.0.1.tgz",
+ "integrity": "sha512-3GQ2oruZO9j8dSHcI0MUeOZQBhjYyDQsF/pKY4Px+CJxn0M16OhgFeEzUjeuwci4zhhjoNIDE9aFNaV5GMQ09g==",
+ "dev": true,
+ "requires": {
+ "@swc/core": "^1.3.22"
+ }
+ },
+ "csstype": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
+ "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
+ "dev": true
+ },
+ "esbuild": {
+ "version": "0.16.9",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.9.tgz",
+ "integrity": "sha512-gkH83yHyijMSZcZFs1IWew342eMdFuWXmQo3zkDPTre25LIPBJsXryg02M3u8OpTwCJdBkdaQwqKkDLnAsAeLQ==",
+ "dev": true,
+ "requires": {
+ "@esbuild/android-arm": "0.16.9",
+ "@esbuild/android-arm64": "0.16.9",
+ "@esbuild/android-x64": "0.16.9",
+ "@esbuild/darwin-arm64": "0.16.9",
+ "@esbuild/darwin-x64": "0.16.9",
+ "@esbuild/freebsd-arm64": "0.16.9",
+ "@esbuild/freebsd-x64": "0.16.9",
+ "@esbuild/linux-arm": "0.16.9",
+ "@esbuild/linux-arm64": "0.16.9",
+ "@esbuild/linux-ia32": "0.16.9",
+ "@esbuild/linux-loong64": "0.16.9",
+ "@esbuild/linux-mips64el": "0.16.9",
+ "@esbuild/linux-ppc64": "0.16.9",
+ "@esbuild/linux-riscv64": "0.16.9",
+ "@esbuild/linux-s390x": "0.16.9",
+ "@esbuild/linux-x64": "0.16.9",
+ "@esbuild/netbsd-x64": "0.16.9",
+ "@esbuild/openbsd-x64": "0.16.9",
+ "@esbuild/sunos-x64": "0.16.9",
+ "@esbuild/win32-arm64": "0.16.9",
+ "@esbuild/win32-ia32": "0.16.9",
+ "@esbuild/win32-x64": "0.16.9"
+ }
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lz-string": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
+ "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ=="
+ },
+ "monaco-editor": {
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz",
+ "integrity": "sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ=="
+ },
+ "nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "8.4.20",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
+ "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
+ "dev": true,
+ "requires": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ }
+ },
+ "prettier": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz",
+ "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg=="
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ }
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "rollup": {
+ "version": "3.7.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.5.tgz",
+ "integrity": "sha512-z0ZbqHBtS/et2EEUKMrAl2CoSdwN7ZPzL17UMiKN9RjjqHShTlv7F9J6ZJZJNREYjBh3TvBrdfjkFDIXFNeuiQ==",
+ "dev": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true
+ },
+ "state-local": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.9.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+ "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "dev": true
+ },
+ "vite": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.1.tgz",
+ "integrity": "sha512-kZQPzbDau35iWOhy3CpkrRC7It+HIHtulAzBhMqzGHKRf/4+vmh8rPDDdv98SWQrFWo6//3ozwsRmwQIPZsK9g==",
+ "dev": true,
+ "requires": {
+ "esbuild": "^0.16.3",
+ "fsevents": "~2.3.2",
+ "postcss": "^8.4.20",
+ "resolve": "^1.22.1",
+ "rollup": "^3.7.0"
+ }
+ }
+ }
+}
diff --git a/playground/package.json b/playground/package.json
new file mode 100644
index 0000000000..08adeaeb54
--- /dev/null
+++ b/playground/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "playground",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview",
+ "push": "wrangler pages publish dist --project-name=ruff"
+ },
+ "dependencies": {
+ "@monaco-editor/react": "^4.4.6",
+ "lz-string": "^1.4.4",
+ "monaco-editor": "^0.34.1",
+ "prettier": "^2.8.1",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.26",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react-swc": "^3.0.0",
+ "typescript": "^4.9.3",
+ "vite": "^4.0.0"
+ }
+}
diff --git a/playground/src/App.tsx b/playground/src/App.tsx
new file mode 100644
index 0000000000..8c4fc883b2
--- /dev/null
+++ b/playground/src/App.tsx
@@ -0,0 +1,141 @@
+import lzstring from "lz-string";
+import Editor, { useMonaco } from "@monaco-editor/react";
+import { MarkerSeverity } from "monaco-editor/esm/vs/editor/editor.api";
+import { useEffect, useState, useCallback } from "react";
+
+// @ts-ignore
+import init, { Check, check } from "./pkg/ruff.js";
+import { AVAILABLE_OPTIONS } from "./ruff_options";
+import { Config, getDefaultConfig, toRuffConfig } from "./config";
+import { Options } from "./Options";
+
+const DEFAULT_SOURCE = "print(1 + 2)";
+
+function restoreConfigAndSource(): [Config, string] {
+ let value = lzstring.decompressFromEncodedURIComponent(
+ window.location.hash.slice(1)
+ );
+ let config = {};
+ let source = DEFAULT_SOURCE;
+
+ if (value) {
+ let parts = value.split("$$$");
+ config = JSON.parse(parts[0]);
+ source = parts[1];
+ }
+
+ return [config, source];
+}
+
+function persistConfigAndSource(config: Config, source: string) {
+ window.location.hash = lzstring.compressToEncodedURIComponent(
+ JSON.stringify(config) + "$$$" + source
+ );
+}
+
+const defaultConfig = getDefaultConfig(AVAILABLE_OPTIONS);
+
+export default function App() {
+ const monaco = useMonaco();
+ const [ruffInitialized, setRuffInitialized] = useState(false);
+ const [config, setConfig] = useState(null);
+ const [source, setSource] = useState(null);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ init().then(() => setRuffInitialized(true));
+ }, []);
+
+ useEffect(() => {
+ if (source === null && config === null && monaco) {
+ let [config, source] = restoreConfigAndSource();
+ setConfig(config);
+ setSource(source);
+ }
+ }, [monaco, source, config]);
+
+ useEffect(() => {
+ if (config != null && source != null) {
+ persistConfigAndSource(config, source);
+ }
+ }, [config, source]);
+
+ useEffect(() => {
+ let editor = monaco?.editor;
+ let model = editor?.getModels()[0];
+ if (
+ !editor ||
+ !model ||
+ !ruffInitialized ||
+ source === null ||
+ config === null
+ ) {
+ return;
+ }
+
+ let checks: Check[];
+ try {
+ checks = check(source, toRuffConfig(config));
+ setError(null);
+ } catch (e) {
+ setError(String(e));
+ return;
+ }
+
+ editor.setModelMarkers(
+ model,
+ "owner",
+ checks.map((check) => ({
+ startLineNumber: check.location.row,
+ startColumn: check.location.column + 1,
+ endLineNumber: check.end_location.row,
+ endColumn: check.end_location.column + 1,
+ message: `${check.code}: ${check.message}`,
+ severity: MarkerSeverity.Error,
+ }))
+ );
+ }, [config, source, monaco, ruffInitialized]);
+
+ const handleEditorChange = useCallback(
+ (value: string | undefined) => {
+ value && setSource(value);
+ },
+ [setSource]
+ );
+
+ const handleOptionChange = useCallback(
+ (groupName: string, fieldName: string, value: string) => {
+ let group = Object.assign({}, (config || {})[groupName]);
+ if (value === defaultConfig[groupName][fieldName] || value === "") {
+ delete group[fieldName];
+ } else {
+ group[fieldName] = value;
+ }
+
+ setConfig({
+ ...config,
+ [groupName]: group,
+ });
+ },
+ [config]
+ );
+
+ return (
+
+
+
+ {error &&
{error}
}
+
+ );
+}
diff --git a/playground/src/Options.tsx b/playground/src/Options.tsx
new file mode 100644
index 0000000000..375d04429f
--- /dev/null
+++ b/playground/src/Options.tsx
@@ -0,0 +1,72 @@
+import { Config } from "./config";
+import { AVAILABLE_OPTIONS } from "./ruff_options";
+
+function OptionEntry({
+ config,
+ defaultConfig,
+ groupName,
+ fieldName,
+ onChange,
+}: {
+ config: Config | null;
+ defaultConfig: Config;
+ groupName: string;
+ fieldName: string;
+ onChange: (groupName: string, fieldName: string, value: string) => void;
+}) {
+ const value =
+ config && config[groupName] && config[groupName][fieldName]
+ ? config[groupName][fieldName]
+ : "";
+
+ return (
+
+
+
+ );
+}
+
+export function Options({
+ config,
+ defaultConfig,
+ onChange,
+}: {
+ config: Config | null;
+ defaultConfig: Config;
+ onChange: (groupName: string, fieldName: string, value: string) => void;
+}) {
+ return (
+
+ {AVAILABLE_OPTIONS.map((group) => (
+
+ {group.name}
+
+
+ {group.fields.map((field) => (
+ -
+
+
+ ))}
+
+
+
+ ))}
+
+ );
+}
diff --git a/playground/src/config.ts b/playground/src/config.ts
new file mode 100644
index 0000000000..82573bc87d
--- /dev/null
+++ b/playground/src/config.ts
@@ -0,0 +1,52 @@
+import { OptionGroup } from "./ruff_options";
+
+export type Config = { [key: string]: { [key: string]: string } };
+
+export function getDefaultConfig(availableOptions: OptionGroup[]): Config {
+ const config: Config = {};
+ availableOptions.forEach((group) => {
+ config[group.name] = {};
+ group.fields.forEach((f) => {
+ config[group.name][f.name] = f.default;
+ });
+ });
+ return config;
+}
+
+/**
+ * Convert the config in the application to something Ruff accepts.
+ *
+ * Application config is always nested one level. Ruff allows for some
+ * top-level options.
+ *
+ * Any option value is parsed as JSON to convert it to a native JS object.
+ * If that fails, e.g. while a user is typing, we let the application handle that
+ * and show an error.
+ */
+export function toRuffConfig(config: Config): any {
+ const convertValue = (value: string): any => {
+ return value === "None" ? null : JSON.parse(value);
+ };
+
+ let result: any = {};
+ Object.keys(config).forEach((group_name) => {
+ let fields = config[group_name];
+ if (!fields || Object.keys(fields).length === 0) {
+ return;
+ }
+
+ if (group_name === "globals") {
+ Object.keys(fields).forEach((field_name) => {
+ result[field_name] = convertValue(fields[field_name]);
+ });
+ } else {
+ result[group_name] = {};
+
+ Object.keys(fields).forEach((field_name) => {
+ result[group_name][field_name] = convertValue(fields[field_name]);
+ });
+ }
+ });
+
+ return result;
+}
diff --git a/playground/src/custom.d.ts b/playground/src/custom.d.ts
new file mode 100644
index 0000000000..29a97b8ece
--- /dev/null
+++ b/playground/src/custom.d.ts
@@ -0,0 +1,6 @@
+declare module "lz-string" {
+ function decompressFromEncodedURIComponent(
+ input: string | null
+ ): string | null;
+ function compressToEncodedURIComponent(input: string | null): string;
+}
diff --git a/playground/src/main.tsx b/playground/src/main.tsx
new file mode 100644
index 0000000000..7d6d78e120
--- /dev/null
+++ b/playground/src/main.tsx
@@ -0,0 +1,10 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App";
+import "./style.css";
+
+ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
+
+
+
+);
diff --git a/playground/src/ruff_options.ts b/playground/src/ruff_options.ts
new file mode 100644
index 0000000000..4f66dab44c
--- /dev/null
+++ b/playground/src/ruff_options.ts
@@ -0,0 +1,222 @@
+
+// This file is auto-generated by `cargo dev generate-playground-options`.
+export interface OptionGroup {
+ name: string;
+ fields: {
+ name: string;
+ default: string;
+ type: string;
+ }[];
+};
+
+export const AVAILABLE_OPTIONS: OptionGroup[] = [
+ {"name": "globals", "fields": [
+ {
+ "name": "allowed-confusables",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "dummy-variable-rgx",
+ "default": '"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"',
+ "type": 'Regex',
+ },
+ {
+ "name": "extend-ignore",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "extend-select",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "external",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "fix-only",
+ "default": 'false',
+ "type": 'bool',
+ },
+ {
+ "name": "ignore",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "line-length",
+ "default": '88',
+ "type": 'usize',
+ },
+ {
+ "name": "required-version",
+ "default": 'None',
+ "type": 'String',
+ },
+ {
+ "name": "select",
+ "default": '["E", "F"]',
+ "type": 'Vec',
+ },
+ {
+ "name": "target-version",
+ "default": '"py310"',
+ "type": 'PythonVersion',
+ },
+ {
+ "name": "unfixable",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ ]},
+ {"name": "flake8-annotations", "fields": [
+ {
+ "name": "allow-star-arg-any",
+ "default": 'false',
+ "type": 'bool',
+ },
+ {
+ "name": "mypy-init-return",
+ "default": 'false',
+ "type": 'bool',
+ },
+ {
+ "name": "suppress-dummy-args",
+ "default": 'false',
+ "type": 'bool',
+ },
+ {
+ "name": "suppress-none-returning",
+ "default": 'false',
+ "type": 'bool',
+ },
+ ]},
+ {"name": "flake8-bugbear", "fields": [
+ {
+ "name": "extend-immutable-calls",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ ]},
+ {"name": "flake8-errmsg", "fields": [
+ {
+ "name": "max-string-length",
+ "default": '0',
+ "type": 'usize',
+ },
+ ]},
+ {"name": "flake8-import-conventions", "fields": [
+ {
+ "name": "aliases",
+ "default": '{"altair": "alt", "matplotlib.pyplot": "plt", "numpy": "np", "pandas": "pd", "seaborn": "sns"}',
+ "type": 'FxHashMap',
+ },
+ {
+ "name": "extend-aliases",
+ "default": '{}',
+ "type": 'FxHashMap',
+ },
+ ]},
+ {"name": "flake8-quotes", "fields": [
+ {
+ "name": "avoid-escape",
+ "default": 'true',
+ "type": 'bool',
+ },
+ {
+ "name": "docstring-quotes",
+ "default": '"double"',
+ "type": 'Quote',
+ },
+ {
+ "name": "inline-quotes",
+ "default": '"double"',
+ "type": 'Quote',
+ },
+ {
+ "name": "multiline-quotes",
+ "default": '"double"',
+ "type": 'Quote',
+ },
+ ]},
+ {"name": "flake8-tidy-imports", "fields": [
+ {
+ "name": "ban-relative-imports",
+ "default": '"parents"',
+ "type": 'Strictness',
+ },
+ ]},
+ {"name": "flake8-unused-arguments", "fields": [
+ {
+ "name": "ignore-variadic-names",
+ "default": 'false',
+ "type": 'bool',
+ },
+ ]},
+ {"name": "isort", "fields": [
+ {
+ "name": "combine-as-imports",
+ "default": 'false',
+ "type": 'bool',
+ },
+ {
+ "name": "extra-standard-library",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "force-wrap-aliases",
+ "default": 'false',
+ "type": 'bool',
+ },
+ {
+ "name": "known-first-party",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "known-third-party",
+ "default": '[]',
+ "type": 'Vec',
+ },
+ {
+ "name": "split-on-trailing-comma",
+ "default": 'true',
+ "type": 'bool',
+ },
+ ]},
+ {"name": "mccabe", "fields": [
+ {
+ "name": "max-complexity",
+ "default": '10',
+ "type": 'usize',
+ },
+ ]},
+ {"name": "pep8-naming", "fields": [
+ {
+ "name": "classmethod-decorators",
+ "default": '["classmethod"]',
+ "type": 'Vec',
+ },
+ {
+ "name": "ignore-names",
+ "default": '["setUp", "tearDown", "setUpClass", "tearDownClass", "setUpModule", "tearDownModule", "asyncSetUp", "asyncTearDown", "setUpTestData", "failureException", "longMessage", "maxDiff"]',
+ "type": 'Vec',
+ },
+ {
+ "name": "staticmethod-decorators",
+ "default": '["staticmethod"]',
+ "type": 'Vec',
+ },
+ ]},
+ {"name": "pyupgrade", "fields": [
+ {
+ "name": "keep-runtime-typing",
+ "default": 'false',
+ "type": 'bool',
+ },
+ ]},
+];
\ No newline at end of file
diff --git a/playground/src/style.css b/playground/src/style.css
new file mode 100644
index 0000000000..da649ebfc2
--- /dev/null
+++ b/playground/src/style.css
@@ -0,0 +1,60 @@
+* {
+ box-sizing: border-box;
+}
+
+body,
+html,
+#root,
+#app {
+ margin: 0;
+ height: 100%;
+ width: 100%;
+}
+
+#app {
+ display: flex;
+}
+
+.options {
+ height: 100vh;
+ overflow-y: scroll;
+ padding: 1em;
+ min-width: 300px;
+ border-right: 1px solid lightgray;
+}
+
+.options ul {
+ padding-left: 1em;
+ list-style-type: none;
+}
+
+.options li {
+ margin-bottom: 0.3em;
+}
+
+.options details {
+ margin-bottom: 1em;
+}
+
+.options summary {
+ font-size: 1.3rem;
+}
+
+.options input {
+ display: block;
+ width: 100%;
+}
+
+.editor {
+ padding: 1em;
+}
+
+#error {
+ position: fixed;
+ bottom: 0;
+ width: 100%;
+ min-height: 1em;
+ padding: 1em;
+ background: darkred;
+ color: white;
+}
diff --git a/playground/src/vite-env.d.ts b/playground/src/vite-env.d.ts
new file mode 100644
index 0000000000..11f02fe2a0
--- /dev/null
+++ b/playground/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/playground/tsconfig.json b/playground/tsconfig.json
new file mode 100644
index 0000000000..3d0a51a86e
--- /dev/null
+++ b/playground/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "esModuleInterop": false,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/playground/tsconfig.node.json b/playground/tsconfig.node.json
new file mode 100644
index 0000000000..9d31e2aed9
--- /dev/null
+++ b/playground/tsconfig.node.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/playground/vite.config.ts b/playground/vite.config.ts
new file mode 100644
index 0000000000..d366e8c8d7
--- /dev/null
+++ b/playground/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react-swc";
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/ruff_dev/Cargo.toml b/ruff_dev/Cargo.toml
index 7f413b0c5d..1b5259d93a 100644
--- a/ruff_dev/Cargo.toml
+++ b/ruff_dev/Cargo.toml
@@ -18,3 +18,4 @@ schemars = { version = "0.8.11" }
serde_json = {version="1.0.91"}
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
+textwrap = { version = "0.16.0" }
diff --git a/ruff_dev/src/generate_playground_options.rs b/ruff_dev/src/generate_playground_options.rs
new file mode 100644
index 0000000000..759c2fc5e6
--- /dev/null
+++ b/ruff_dev/src/generate_playground_options.rs
@@ -0,0 +1,142 @@
+//! Generate typescript file defining options to be used by the web playground.
+
+use std::fs::OpenOptions;
+use std::io::Write;
+use std::path::PathBuf;
+
+use anyhow::Result;
+use clap::Args;
+use itertools::Itertools;
+use ruff::settings::options::Options;
+use ruff::settings::options_base::{ConfigurationOptions, OptionEntry, OptionField};
+
+#[derive(Args)]
+pub struct Cli {
+ /// Write the generated table to stdout (rather than to `TODO`).
+ #[arg(long)]
+ dry_run: bool,
+}
+
+fn emit_field(output: &mut String, field: &OptionField) {
+ output.push_str(&textwrap::indent(
+ &textwrap::dedent(&format!(
+ "
+ {{
+ \"name\": \"{}\",
+ \"default\": '{}',
+ \"type\": '{}',
+ }},",
+ field.name, field.default, field.value_type
+ )),
+ " ",
+ ));
+}
+
+pub fn main(cli: &Cli) -> Result<()> {
+ let mut output = String::new();
+
+ // Generate all the top-level fields.
+ output.push_str(&format!("{{\"name\": \"{}\", \"fields\": [", "globals"));
+ for field in Options::get_available_options()
+ .into_iter()
+ .filter_map(|entry| {
+ if let OptionEntry::Field(field) = entry {
+ Some(field)
+ } else {
+ None
+ }
+ })
+ // Filter out options that don't make sense in the playground.
+ .filter(|field| {
+ !matches!(
+ field.name,
+ "src"
+ | "fix"
+ | "format"
+ | "exclude"
+ | "extend"
+ | "extend-exclude"
+ | "fixable"
+ | "force-exclude"
+ | "ignore-init-module-imports"
+ | "respect-gitignore"
+ | "show-source"
+ | "cache-dir"
+ | "per-file-ignores"
+ )
+ })
+ .sorted_by_key(|field| field.name)
+ {
+ emit_field(&mut output, &field);
+ }
+ output.push_str("\n]},\n");
+
+ // Generate all the sub-groups.
+ for group in Options::get_available_options()
+ .into_iter()
+ .filter_map(|entry| {
+ if let OptionEntry::Group(group) = entry {
+ Some(group)
+ } else {
+ None
+ }
+ })
+ .sorted_by_key(|group| group.name)
+ {
+ output.push_str(&format!("{{\"name\": \"{}\", \"fields\": [", group.name));
+ for field in group
+ .fields
+ .iter()
+ .filter_map(|entry| {
+ if let OptionEntry::Field(field) = entry {
+ Some(field)
+ } else {
+ None
+ }
+ })
+ .sorted_by_key(|field| field.name)
+ {
+ emit_field(&mut output, field);
+ }
+ output.push_str("\n]},\n");
+ }
+
+ let prefix = textwrap::dedent(
+ r"
+ // This file is auto-generated by `cargo dev generate-playground-options`.
+ export interface OptionGroup {
+ name: string;
+ fields: {
+ name: string;
+ default: string;
+ type: string;
+ }[];
+ };
+
+ export const AVAILABLE_OPTIONS: OptionGroup[] = [
+ ",
+ );
+ let postfix = "];";
+
+ if cli.dry_run {
+ print!("{output}");
+ } else {
+ let file = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+ .parent()
+ .expect("Failed to find root directory")
+ .join("playground")
+ .join("src")
+ .join("ruff_options.ts");
+
+ let mut f = OpenOptions::new()
+ .create(true)
+ .write(true)
+ .truncate(true)
+ .open(file)?;
+ write!(f, "{prefix}")?;
+ write!(f, "{}", textwrap::indent(&output, " "))?;
+ write!(f, "{postfix}")?;
+ }
+
+ Ok(())
+}
diff --git a/ruff_dev/src/lib.rs b/ruff_dev/src/lib.rs
index 577ea5d301..8b53230bf6 100644
--- a/ruff_dev/src/lib.rs
+++ b/ruff_dev/src/lib.rs
@@ -14,6 +14,7 @@
pub mod generate_check_code_prefix;
pub mod generate_json_schema;
pub mod generate_options;
+pub mod generate_playground_options;
pub mod generate_rules_table;
pub mod generate_source_code;
pub mod print_ast;
diff --git a/ruff_dev/src/main.rs b/ruff_dev/src/main.rs
index fbcbda5d19..3f99f48609 100644
--- a/ruff_dev/src/main.rs
+++ b/ruff_dev/src/main.rs
@@ -14,8 +14,9 @@
use anyhow::Result;
use clap::{Parser, Subcommand};
use ruff_dev::{
- generate_check_code_prefix, generate_json_schema, generate_options, generate_rules_table,
- generate_source_code, print_ast, print_cst, print_tokens,
+ generate_check_code_prefix, generate_json_schema, generate_options,
+ generate_playground_options, generate_rules_table, generate_source_code, print_ast, print_cst,
+ print_tokens,
};
#[derive(Parser)]
@@ -36,6 +37,9 @@ enum Commands {
GenerateRulesTable(generate_rules_table::Cli),
/// Generate a Markdown-compatible listing of configuration options.
GenerateOptions(generate_options::Cli),
+ /// Generate typescript file defining options to be used by the web
+ /// playground.
+ GeneratePlaygroundOptions(generate_playground_options::Cli),
/// Run round-trip source code generation on a given Python file.
GenerateSourceCode(generate_source_code::Cli),
/// Print the AST for a given Python file.
@@ -54,6 +58,7 @@ fn main() -> Result<()> {
Commands::GenerateRulesTable(args) => generate_rules_table::main(args)?,
Commands::GenerateSourceCode(args) => generate_source_code::main(args)?,
Commands::GenerateOptions(args) => generate_options::main(args)?,
+ Commands::GeneratePlaygroundOptions(args) => generate_playground_options::main(args)?,
Commands::PrintAST(args) => print_ast::main(args)?,
Commands::PrintCST(args) => print_cst::main(args)?,
Commands::PrintTokens(args) => print_tokens::main(args)?,
diff --git a/src/lib.rs b/src/lib.rs
index 9e4f15d0db..d918027168 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,19 +11,10 @@
clippy::too_many_lines
)]
-use std::path::Path;
-
-use anyhow::Result;
-use path_absolutize::path_dedot;
-use rustpython_helpers::tokenize;
-use rustpython_parser::lexer::LexResult;
-use settings::{pyproject, Settings};
+use cfg_if::cfg_if;
use crate::checks::Check;
-use crate::linter::check_path;
-use crate::resolver::Relativity;
-use crate::settings::configuration::Configuration;
-use crate::settings::flags;
+use crate::settings::Settings;
use crate::source_code_locator::SourceCodeLocator;
mod ast;
@@ -34,7 +25,6 @@ pub mod checks;
pub mod checks_gen;
pub mod cli;
pub mod code_gen;
-pub mod commands;
mod cst;
mod directives;
mod docstrings;
@@ -66,7 +56,6 @@ pub mod logging;
pub mod mccabe;
pub mod message;
mod noqa;
-mod packages;
mod pandas_vet;
pub mod pep8_naming;
pub mod printer;
@@ -82,58 +71,20 @@ mod ruff;
mod rustpython_helpers;
pub mod settings;
pub mod source_code_locator;
-#[cfg(feature = "update-informer")]
-pub mod updates;
mod vendored;
pub mod visibility;
-/// Load the relevant `Settings` for a given `Path`.
-fn resolve(path: &Path) -> Result {
- if let Some(pyproject) = pyproject::find_settings_toml(path)? {
- // First priority: `pyproject.toml` in the current `Path`.
- resolver::resolve_settings(&pyproject, &Relativity::Parent, None)
- } else if let Some(pyproject) = pyproject::find_user_settings_toml() {
- // Second priority: user-specific `pyproject.toml`.
- resolver::resolve_settings(&pyproject, &Relativity::Cwd, None)
+cfg_if! {
+ if #[cfg(not(target_family = "wasm"))] {
+ pub mod commands;
+ mod packages;
+ #[cfg(all(feature = "update-informer"))]
+ pub mod updates;
+
+ mod lib_native;
+ pub use lib_native::check;
} else {
- // Fallback: default settings.
- Settings::from_configuration(Configuration::default(), &path_dedot::CWD)
+ mod lib_wasm;
+ pub use lib_wasm::check;
}
}
-
-/// Run Ruff over Python source code directly.
-pub fn check(path: &Path, contents: &str, autofix: bool) -> Result> {
- // Load the relevant `Settings` for the given `Path`.
- let settings = resolve(path)?;
-
- // Validate the `Settings` and return any errors.
- settings.validate()?;
-
- // Tokenize once.
- let tokens: Vec = tokenize(contents);
-
- // Initialize the SourceCodeLocator (which computes offsets lazily).
- let locator = SourceCodeLocator::new(contents);
-
- // Extract the `# noqa` and `# isort: skip` directives from the source.
- let directives = directives::extract_directives(
- &tokens,
- &locator,
- directives::Flags::from_settings(&settings),
- );
-
- // Generate checks.
- let checks = check_path(
- path,
- packages::detect_package_root(path),
- contents,
- tokens,
- &locator,
- &directives,
- &settings,
- autofix.into(),
- flags::Noqa::Enabled,
- )?;
-
- Ok(checks)
-}
diff --git a/src/lib_native.rs b/src/lib_native.rs
new file mode 100644
index 0000000000..789a9ea998
--- /dev/null
+++ b/src/lib_native.rs
@@ -0,0 +1,65 @@
+use std::path::Path;
+
+use anyhow::Result;
+use path_absolutize::path_dedot;
+use rustpython_parser::lexer::LexResult;
+
+use crate::checks::Check;
+use crate::linter::check_path;
+use crate::resolver::Relativity;
+use crate::rustpython_helpers::tokenize;
+use crate::settings::configuration::Configuration;
+use crate::settings::{flags, pyproject, Settings};
+use crate::source_code_locator::SourceCodeLocator;
+use crate::{directives, packages, resolver};
+
+/// Load the relevant `Settings` for a given `Path`.
+fn resolve(path: &Path) -> Result {
+ if let Some(pyproject) = pyproject::find_settings_toml(path)? {
+ // First priority: `pyproject.toml` in the current `Path`.
+ resolver::resolve_settings(&pyproject, &Relativity::Parent, None)
+ } else if let Some(pyproject) = pyproject::find_user_settings_toml() {
+ // Second priority: user-specific `pyproject.toml`.
+ resolver::resolve_settings(&pyproject, &Relativity::Cwd, None)
+ } else {
+ // Fallback: default settings.
+ Settings::from_configuration(Configuration::default(), &path_dedot::CWD)
+ }
+}
+
+/// Run Ruff over Python source code directly.
+pub fn check(path: &Path, contents: &str, autofix: bool) -> Result> {
+ // Load the relevant `Settings` for the given `Path`.
+ let settings = resolve(path)?;
+
+ // Validate the `Settings` and return any errors.
+ settings.validate()?;
+
+ // Tokenize once.
+ let tokens: Vec = tokenize(contents);
+
+ // Initialize the SourceCodeLocator (which computes offsets lazily).
+ let locator = SourceCodeLocator::new(contents);
+
+ // Extract the `# noqa` and `# isort: skip` directives from the source.
+ let directives = directives::extract_directives(
+ &tokens,
+ &locator,
+ directives::Flags::from_settings(&settings),
+ );
+
+ // Generate checks.
+ let checks = check_path(
+ path,
+ packages::detect_package_root(path),
+ contents,
+ tokens,
+ &locator,
+ &directives,
+ &settings,
+ autofix.into(),
+ flags::Noqa::Enabled,
+ )?;
+
+ Ok(checks)
+}
diff --git a/src/lib_wasm.rs b/src/lib_wasm.rs
new file mode 100644
index 0000000000..c9bede8c48
--- /dev/null
+++ b/src/lib_wasm.rs
@@ -0,0 +1,141 @@
+use std::path::Path;
+
+use rustpython_ast::Location;
+use rustpython_parser::lexer::LexResult;
+use serde::{Deserialize, Serialize};
+use wasm_bindgen::prelude::*;
+
+use crate::checks::CheckCode;
+use crate::directives;
+use crate::linter::check_path;
+use crate::rustpython_helpers::tokenize;
+use crate::settings::configuration::Configuration;
+use crate::settings::options::Options;
+use crate::settings::{flags, Settings};
+use crate::source_code_locator::SourceCodeLocator;
+
+#[wasm_bindgen(typescript_custom_section)]
+const TYPES: &'static str = r#"
+export interface Check {
+ code: string;
+ message: string;
+ location: {
+ row: number;
+ column: number;
+ };
+ end_location: {
+ row: number;
+ column: number;
+ };
+};
+"#;
+
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
+struct Message {
+ code: CheckCode,
+ message: String,
+ location: Location,
+ end_location: Location,
+}
+
+#[wasm_bindgen(start)]
+pub fn run() {
+ use log::Level;
+ console_error_panic_hook::set_once();
+ console_log::init_with_level(Level::Debug).expect("Initializing logger went wrong.");
+}
+
+#[wasm_bindgen]
+pub fn check(contents: &str, options: JsValue) -> Result {
+ let options: Options = serde_wasm_bindgen::from_value(options).map_err(|e| e.to_string())?;
+ let configuration =
+ Configuration::from_options(options, Path::new(".")).map_err(|e| e.to_string())?;
+ let settings =
+ Settings::from_configuration(configuration, Path::new(".")).map_err(|e| e.to_string())?;
+
+ // Tokenize once.
+ let tokens: Vec = tokenize(contents);
+
+ // Initialize the SourceCodeLocator (which computes offsets lazily).
+ let locator = SourceCodeLocator::new(contents);
+
+ // Extract the `# noqa` and `# isort: skip` directives from the source.
+ let directives = directives::extract_directives(&tokens, &locator, directives::Flags::empty());
+
+ // Generate checks.
+ let checks = check_path(
+ Path::new(""),
+ None,
+ contents,
+ tokens,
+ &locator,
+ &directives,
+ &settings,
+ false.into(),
+ flags::Noqa::Enabled,
+ )
+ .map_err(|e| e.to_string())?;
+
+ let messages: Vec = checks
+ .into_iter()
+ .map(|check| Message {
+ code: check.kind.code().clone(),
+ message: check.kind.body(),
+ location: check.location,
+ end_location: check.end_location,
+ })
+ .collect();
+
+ Ok(serde_wasm_bindgen::to_value(&messages)?)
+}
+
+#[cfg(test)]
+mod test {
+ use js_sys;
+ use wasm_bindgen_test::*;
+
+ use super::*;
+
+ macro_rules! check {
+ ($source:expr, $config:expr, $expected:expr) => {{
+ let foo = js_sys::JSON::parse($config).unwrap();
+ match check($source, foo) {
+ Ok(output) => {
+ let result: Vec = serde_wasm_bindgen::from_value(output).unwrap();
+ assert_eq!(result, $expected);
+ }
+ Err(e) => assert!(false, "{:#?}", e),
+ }
+ }};
+ }
+
+ #[wasm_bindgen_test]
+ fn empty_config() {
+ check!(
+ "if (1, 2): pass",
+ r#"{}"#,
+ [Message {
+ code: CheckCode::F634,
+ message: "If test is a tuple, which is always `True`".to_string(),
+ location: Location::new(1, 0),
+ end_location: Location::new(1, 15)
+ }]
+ );
+ }
+
+ #[wasm_bindgen_test]
+ fn partial_config() {
+ check!("if (1, 2): pass", r#"{"ignore": ["F"]}"#, []);
+ }
+
+ #[wasm_bindgen_test]
+ fn partial_nested_config() {
+ let config = r#"{
+ "select": ["Q"],
+ "flake8-quotes": {
+ "inline-quotes": "single"
+ }
+ }"#;
+ check!(r#"print('hello world')"#, config, []);
+ }
+}
diff --git a/src/linter.rs b/src/linter.rs
index 0c142f7e63..499446ace2 100644
--- a/src/linter.rs
+++ b/src/linter.rs
@@ -5,7 +5,6 @@ use std::ops::AddAssign;
use std::path::Path;
use anyhow::Result;
-#[cfg(not(target_family = "wasm"))]
use log::debug;
use rustpython_parser::lexer::LexResult;
diff --git a/src/main.rs b/src/main.rs
index a8f6fe9aa6..592e86dc87 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,263 +11,23 @@
clippy::too_many_lines
)]
-use std::io::{self};
-use std::path::{Path, PathBuf};
use std::process::ExitCode;
-use std::sync::mpsc::channel;
-use ::ruff::autofix::fixer;
-use ::ruff::cli::{extract_log_level, Cli, Overrides};
-use ::ruff::commands;
-use ::ruff::logging::{set_up_logging, LogLevel};
-use ::ruff::printer::{Printer, Violations};
-use ::ruff::resolver::{resolve_settings, FileDiscovery, PyprojectDiscovery, Relativity};
-use ::ruff::settings::configuration::Configuration;
-use ::ruff::settings::types::SerializationFormat;
-use ::ruff::settings::{pyproject, Settings};
-#[cfg(feature = "update-informer")]
-use ::ruff::updates;
-use anyhow::Result;
-use clap::{CommandFactory, Parser};
+use cfg_if::cfg_if;
use colored::Colorize;
-use notify::{recommended_watcher, RecursiveMode, Watcher};
-use path_absolutize::path_dedot;
-/// Resolve the relevant settings strategy and defaults for the current
-/// invocation.
-fn resolve(
- config: Option<&Path>,
- overrides: &Overrides,
- stdin_filename: Option<&Path>,
-) -> Result {
- if let Some(pyproject) = config {
- // First priority: the user specified a `pyproject.toml` file. Use that
- // `pyproject.toml` for _all_ configuration, and resolve paths relative to the
- // current working directory. (This matches ESLint's behavior.)
- let settings = resolve_settings(pyproject, &Relativity::Cwd, Some(overrides))?;
- Ok(PyprojectDiscovery::Fixed(settings))
- } else if let Some(pyproject) = pyproject::find_settings_toml(
- stdin_filename
- .as_ref()
- .unwrap_or(&path_dedot::CWD.as_path()),
- )? {
- // Second priority: find a `pyproject.toml` file in either an ancestor of
- // `stdin_filename` (if set) or the current working path all paths relative to
- // that directory. (With `Strategy::Hierarchical`, we'll end up finding
- // the "closest" `pyproject.toml` file for every Python file later on,
- // so these act as the "default" settings.)
- let settings = resolve_settings(&pyproject, &Relativity::Parent, Some(overrides))?;
- Ok(PyprojectDiscovery::Hierarchical(settings))
- } else if let Some(pyproject) = pyproject::find_user_settings_toml() {
- // Third priority: find a user-specific `pyproject.toml`, but resolve all paths
- // relative the current working directory. (With `Strategy::Hierarchical`, we'll
- // end up the "closest" `pyproject.toml` file for every Python file later on, so
- // these act as the "default" settings.)
- let settings = resolve_settings(&pyproject, &Relativity::Cwd, Some(overrides))?;
- Ok(PyprojectDiscovery::Hierarchical(settings))
+cfg_if! {
+ if #[cfg(not(target_family = "wasm"))] {
+ mod main_native;
+ use main_native::inner_main;
} else {
- // Fallback: load Ruff's default settings, and resolve all paths relative to the
- // current working directory. (With `Strategy::Hierarchical`, we'll end up the
- // "closest" `pyproject.toml` file for every Python file later on, so these act
- // as the "default" settings.)
- let mut config = Configuration::default();
- // Apply command-line options that override defaults.
- config.apply(overrides.clone());
- let settings = Settings::from_configuration(config, &path_dedot::CWD)?;
- Ok(PyprojectDiscovery::Hierarchical(settings))
- }
-}
+ use anyhow::Result;
-fn inner_main() -> Result {
- // Extract command-line arguments.
- let (cli, overrides) = Cli::parse().partition();
- let log_level = extract_log_level(&cli);
- set_up_logging(&log_level)?;
-
- if cli.show_settings && cli.show_files {
- anyhow::bail!("specify --show-settings or show-files (not both)")
- }
- if let Some(shell) = cli.generate_shell_completion {
- shell.generate(&mut Cli::command(), &mut io::stdout());
- return Ok(ExitCode::SUCCESS);
- }
-
- // Construct the "default" settings. These are used when no `pyproject.toml`
- // files are present, or files are injected from outside of the hierarchy.
- let pyproject_strategy = resolve(
- cli.config.as_deref(),
- &overrides,
- cli.stdin_filename.as_deref(),
- )?;
-
- // Validate the `Settings` and return any errors.
- match &pyproject_strategy {
- PyprojectDiscovery::Fixed(settings) => settings.validate()?,
- PyprojectDiscovery::Hierarchical(settings) => settings.validate()?,
- };
-
- // Extract options that are included in `Settings`, but only apply at the top
- // level.
- let file_strategy = FileDiscovery {
- force_exclude: match &pyproject_strategy {
- PyprojectDiscovery::Fixed(settings) => settings.force_exclude,
- PyprojectDiscovery::Hierarchical(settings) => settings.force_exclude,
- },
- respect_gitignore: match &pyproject_strategy {
- PyprojectDiscovery::Fixed(settings) => settings.respect_gitignore,
- PyprojectDiscovery::Hierarchical(settings) => settings.respect_gitignore,
- },
- };
- let (fix, fix_only, format) = match &pyproject_strategy {
- PyprojectDiscovery::Fixed(settings) => (settings.fix, settings.fix_only, settings.format),
- PyprojectDiscovery::Hierarchical(settings) => {
- (settings.fix, settings.fix_only, settings.format)
- }
- };
- let autofix = if fix || fix_only {
- fixer::Mode::Apply
- } else if matches!(format, SerializationFormat::Json) {
- fixer::Mode::Generate
- } else {
- fixer::Mode::None
- };
- let violations = if fix_only {
- Violations::Hide
- } else {
- Violations::Show
- };
- let cache = !cli.no_cache;
-
- if let Some(code) = cli.explain {
- commands::explain(&code, &format)?;
- return Ok(ExitCode::SUCCESS);
- }
- if cli.show_settings {
- commands::show_settings(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
- return Ok(ExitCode::SUCCESS);
- }
- if cli.show_files {
- commands::show_files(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
- return Ok(ExitCode::SUCCESS);
- }
-
- let printer = Printer::new(&format, &log_level, &autofix, &violations);
- if cli.watch {
- if matches!(autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
- eprintln!("Warning: --fix is not enabled in watch mode.");
- }
- if cli.add_noqa {
- eprintln!("Warning: --add-noqa is not enabled in watch mode.");
- }
- if cli.autoformat {
- eprintln!("Warning: --autoformat is not enabled in watch mode.");
- }
- if format != SerializationFormat::Text {
- eprintln!("Warning: --format 'text' is used in watch mode.");
- }
-
- // Perform an initial run instantly.
- printer.clear_screen()?;
- printer.write_to_user("Starting linter in watch mode...\n");
-
- let messages = commands::run(
- &cli.files,
- &pyproject_strategy,
- &file_strategy,
- &overrides,
- cache.into(),
- fixer::Mode::None,
- )?;
- printer.write_continuously(&messages)?;
-
- // Configure the file watcher.
- let (tx, rx) = channel();
- let mut watcher = recommended_watcher(tx)?;
- for file in &cli.files {
- watcher.watch(file, RecursiveMode::Recursive)?;
- }
-
- loop {
- match rx.recv() {
- Ok(event) => {
- let paths = event?.paths;
- let py_changed = paths.iter().any(|path| {
- path.extension()
- .map(|ext| ext == "py" || ext == "pyi")
- .unwrap_or_default()
- });
- if py_changed {
- printer.clear_screen()?;
- printer.write_to_user("File change detected...\n");
-
- let messages = commands::run(
- &cli.files,
- &pyproject_strategy,
- &file_strategy,
- &overrides,
- cache.into(),
- fixer::Mode::None,
- )?;
- printer.write_continuously(&messages)?;
- }
- }
- Err(err) => return Err(err.into()),
- }
- }
- } else if cli.add_noqa {
- let modifications =
- commands::add_noqa(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
- if modifications > 0 && log_level >= LogLevel::Default {
- println!("Added {modifications} noqa directives.");
- }
- } else if cli.autoformat {
- let modifications =
- commands::autoformat(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
- if modifications > 0 && log_level >= LogLevel::Default {
- println!("Formatted {modifications} files.");
- }
- } else {
- let is_stdin = cli.files == vec![PathBuf::from("-")];
-
- // Generate lint violations.
- let diagnostics = if is_stdin {
- commands::run_stdin(
- cli.stdin_filename.as_deref(),
- &pyproject_strategy,
- &file_strategy,
- &overrides,
- autofix,
- )?
- } else {
- commands::run(
- &cli.files,
- &pyproject_strategy,
- &file_strategy,
- &overrides,
- cache.into(),
- autofix,
- )?
- };
-
- // Always try to print violations (the printer itself may suppress output),
- // unless we're writing fixes via stdin (in which case, the transformed
- // source code goes to stdout).
- if !(is_stdin && matches!(autofix, fixer::Mode::Apply)) {
- printer.write_once(&diagnostics)?;
- }
-
- // Check for updates if we're in a non-silent log level.
- #[cfg(feature = "update-informer")]
- if !is_stdin && log_level >= LogLevel::Default && atty::is(atty::Stream::Stdout) {
- drop(updates::check_for_updates());
- }
-
- if !diagnostics.messages.is_empty() && !cli.exit_zero && !fix_only {
- return Ok(ExitCode::FAILURE);
+ #[allow(clippy::unnecessary_wraps)]
+ fn inner_main() -> Result {
+ Ok(ExitCode::FAILURE)
}
}
-
- Ok(ExitCode::SUCCESS)
}
fn main() -> ExitCode {
diff --git a/src/main_native.rs b/src/main_native.rs
new file mode 100644
index 0000000000..19ee5bb6a3
--- /dev/null
+++ b/src/main_native.rs
@@ -0,0 +1,270 @@
+#![allow(
+ clippy::collapsible_else_if,
+ clippy::collapsible_if,
+ clippy::implicit_hasher,
+ clippy::match_same_arms,
+ clippy::missing_errors_doc,
+ clippy::missing_panics_doc,
+ clippy::module_name_repetitions,
+ clippy::must_use_candidate,
+ clippy::similar_names,
+ clippy::too_many_lines
+)]
+
+use std::io::{self};
+use std::path::{Path, PathBuf};
+use std::process::ExitCode;
+use std::sync::mpsc::channel;
+
+use ::ruff::autofix::fixer;
+use ::ruff::cli::{extract_log_level, Cli, Overrides};
+use ::ruff::commands;
+use ::ruff::logging::{set_up_logging, LogLevel};
+use ::ruff::printer::{Printer, Violations};
+use ::ruff::resolver::{resolve_settings, FileDiscovery, PyprojectDiscovery, Relativity};
+use ::ruff::settings::configuration::Configuration;
+use ::ruff::settings::types::SerializationFormat;
+use ::ruff::settings::{pyproject, Settings};
+#[cfg(feature = "update-informer")]
+use ::ruff::updates;
+use anyhow::Result;
+use clap::{CommandFactory, Parser};
+use notify::{recommended_watcher, RecursiveMode, Watcher};
+use path_absolutize::path_dedot;
+
+/// Resolve the relevant settings strategy and defaults for the current
+/// invocation.
+fn resolve(
+ config: Option<&Path>,
+ overrides: &Overrides,
+ stdin_filename: Option<&Path>,
+) -> Result {
+ if let Some(pyproject) = config {
+ // First priority: the user specified a `pyproject.toml` file. Use that
+ // `pyproject.toml` for _all_ configuration, and resolve paths relative to the
+ // current working directory. (This matches ESLint's behavior.)
+ let settings = resolve_settings(pyproject, &Relativity::Cwd, Some(overrides))?;
+ Ok(PyprojectDiscovery::Fixed(settings))
+ } else if let Some(pyproject) = pyproject::find_settings_toml(
+ stdin_filename
+ .as_ref()
+ .unwrap_or(&path_dedot::CWD.as_path()),
+ )? {
+ // Second priority: find a `pyproject.toml` file in either an ancestor of
+ // `stdin_filename` (if set) or the current working path all paths relative to
+ // that directory. (With `Strategy::Hierarchical`, we'll end up finding
+ // the "closest" `pyproject.toml` file for every Python file later on,
+ // so these act as the "default" settings.)
+ let settings = resolve_settings(&pyproject, &Relativity::Parent, Some(overrides))?;
+ Ok(PyprojectDiscovery::Hierarchical(settings))
+ } else if let Some(pyproject) = pyproject::find_user_settings_toml() {
+ // Third priority: find a user-specific `pyproject.toml`, but resolve all paths
+ // relative the current working directory. (With `Strategy::Hierarchical`, we'll
+ // end up the "closest" `pyproject.toml` file for every Python file later on, so
+ // these act as the "default" settings.)
+ let settings = resolve_settings(&pyproject, &Relativity::Cwd, Some(overrides))?;
+ Ok(PyprojectDiscovery::Hierarchical(settings))
+ } else {
+ // Fallback: load Ruff's default settings, and resolve all paths relative to the
+ // current working directory. (With `Strategy::Hierarchical`, we'll end up the
+ // "closest" `pyproject.toml` file for every Python file later on, so these act
+ // as the "default" settings.)
+ let mut config = Configuration::default();
+ // Apply command-line options that override defaults.
+ config.apply(overrides.clone());
+ let settings = Settings::from_configuration(config, &path_dedot::CWD)?;
+ Ok(PyprojectDiscovery::Hierarchical(settings))
+ }
+}
+
+pub(crate) fn inner_main() -> Result {
+ // Extract command-line arguments.
+ let (cli, overrides) = Cli::parse().partition();
+ let log_level = extract_log_level(&cli);
+ set_up_logging(&log_level)?;
+
+ if cli.show_settings && cli.show_files {
+ anyhow::bail!("specify --show-settings or show-files (not both)")
+ }
+ if let Some(shell) = cli.generate_shell_completion {
+ shell.generate(&mut Cli::command(), &mut io::stdout());
+ return Ok(ExitCode::SUCCESS);
+ }
+
+ // Construct the "default" settings. These are used when no `pyproject.toml`
+ // files are present, or files are injected from outside of the hierarchy.
+ let pyproject_strategy = resolve(
+ cli.config.as_deref(),
+ &overrides,
+ cli.stdin_filename.as_deref(),
+ )?;
+
+ // Validate the `Settings` and return any errors.
+ match &pyproject_strategy {
+ PyprojectDiscovery::Fixed(settings) => settings.validate()?,
+ PyprojectDiscovery::Hierarchical(settings) => settings.validate()?,
+ };
+
+ // Extract options that are included in `Settings`, but only apply at the top
+ // level.
+ let file_strategy = FileDiscovery {
+ force_exclude: match &pyproject_strategy {
+ PyprojectDiscovery::Fixed(settings) => settings.force_exclude,
+ PyprojectDiscovery::Hierarchical(settings) => settings.force_exclude,
+ },
+ respect_gitignore: match &pyproject_strategy {
+ PyprojectDiscovery::Fixed(settings) => settings.respect_gitignore,
+ PyprojectDiscovery::Hierarchical(settings) => settings.respect_gitignore,
+ },
+ };
+ let (fix, fix_only, format) = match &pyproject_strategy {
+ PyprojectDiscovery::Fixed(settings) => (settings.fix, settings.fix_only, settings.format),
+ PyprojectDiscovery::Hierarchical(settings) => {
+ (settings.fix, settings.fix_only, settings.format)
+ }
+ };
+ let autofix = if fix || fix_only {
+ fixer::Mode::Apply
+ } else if matches!(format, SerializationFormat::Json) {
+ fixer::Mode::Generate
+ } else {
+ fixer::Mode::None
+ };
+ let violations = if fix_only {
+ Violations::Hide
+ } else {
+ Violations::Show
+ };
+ let cache = !cli.no_cache;
+
+ if let Some(code) = cli.explain {
+ commands::explain(&code, &format)?;
+ return Ok(ExitCode::SUCCESS);
+ }
+ if cli.show_settings {
+ commands::show_settings(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
+ return Ok(ExitCode::SUCCESS);
+ }
+ if cli.show_files {
+ commands::show_files(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
+ return Ok(ExitCode::SUCCESS);
+ }
+
+ let printer = Printer::new(&format, &log_level, &autofix, &violations);
+ if cli.watch {
+ if matches!(autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
+ eprintln!("Warning: --fix is not enabled in watch mode.");
+ }
+ if cli.add_noqa {
+ eprintln!("Warning: --add-noqa is not enabled in watch mode.");
+ }
+ if cli.autoformat {
+ eprintln!("Warning: --autoformat is not enabled in watch mode.");
+ }
+ if format != SerializationFormat::Text {
+ eprintln!("Warning: --format 'text' is used in watch mode.");
+ }
+
+ // Perform an initial run instantly.
+ printer.clear_screen()?;
+ printer.write_to_user("Starting linter in watch mode...\n");
+
+ let messages = commands::run(
+ &cli.files,
+ &pyproject_strategy,
+ &file_strategy,
+ &overrides,
+ cache.into(),
+ fixer::Mode::None,
+ )?;
+ printer.write_continuously(&messages)?;
+
+ // Configure the file watcher.
+ let (tx, rx) = channel();
+ let mut watcher = recommended_watcher(tx)?;
+ for file in &cli.files {
+ watcher.watch(file, RecursiveMode::Recursive)?;
+ }
+
+ loop {
+ match rx.recv() {
+ Ok(event) => {
+ let paths = event?.paths;
+ let py_changed = paths.iter().any(|path| {
+ path.extension()
+ .map(|ext| ext == "py" || ext == "pyi")
+ .unwrap_or_default()
+ });
+ if py_changed {
+ printer.clear_screen()?;
+ printer.write_to_user("File change detected...\n");
+
+ let messages = commands::run(
+ &cli.files,
+ &pyproject_strategy,
+ &file_strategy,
+ &overrides,
+ cache.into(),
+ fixer::Mode::None,
+ )?;
+ printer.write_continuously(&messages)?;
+ }
+ }
+ Err(err) => return Err(err.into()),
+ }
+ }
+ } else if cli.add_noqa {
+ let modifications =
+ commands::add_noqa(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
+ if modifications > 0 && log_level >= LogLevel::Default {
+ println!("Added {modifications} noqa directives.");
+ }
+ } else if cli.autoformat {
+ let modifications =
+ commands::autoformat(&cli.files, &pyproject_strategy, &file_strategy, &overrides)?;
+ if modifications > 0 && log_level >= LogLevel::Default {
+ println!("Formatted {modifications} files.");
+ }
+ } else {
+ let is_stdin = cli.files == vec![PathBuf::from("-")];
+
+ // Generate lint violations.
+ let diagnostics = if is_stdin {
+ commands::run_stdin(
+ cli.stdin_filename.as_deref(),
+ &pyproject_strategy,
+ &file_strategy,
+ &overrides,
+ autofix,
+ )?
+ } else {
+ commands::run(
+ &cli.files,
+ &pyproject_strategy,
+ &file_strategy,
+ &overrides,
+ cache.into(),
+ autofix,
+ )?
+ };
+
+ // Always try to print violations (the printer itself may suppress output),
+ // unless we're writing fixes via stdin (in which case, the transformed
+ // source code goes to stdout).
+ if !(is_stdin && matches!(autofix, fixer::Mode::Apply)) {
+ printer.write_once(&diagnostics)?;
+ }
+
+ // Check for updates if we're in a non-silent log level.
+ #[cfg(feature = "update-informer")]
+ if !is_stdin && log_level >= LogLevel::Default && atty::is(atty::Stream::Stdout) {
+ drop(updates::check_for_updates());
+ }
+
+ if !diagnostics.messages.is_empty() && !cli.exit_zero && !fix_only {
+ return Ok(ExitCode::FAILURE);
+ }
+ }
+
+ Ok(ExitCode::SUCCESS)
+}
diff --git a/tests/black_compatibility_test.rs b/tests/black_compatibility_test.rs
index 18565c099e..84e9db1fca 100644
--- a/tests/black_compatibility_test.rs
+++ b/tests/black_compatibility_test.rs
@@ -1,3 +1,5 @@
+#![cfg(not(target_family = "wasm"))]
+
use std::io::{ErrorKind, Read};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener, TcpStream};
use std::path::{Path, PathBuf};
diff --git a/tests/integration_test.rs b/tests/integration_test.rs
index 0e6376f200..d7b219be20 100644
--- a/tests/integration_test.rs
+++ b/tests/integration_test.rs
@@ -1,3 +1,5 @@
+#![cfg(not(target_family = "wasm"))]
+
use std::str;
use anyhow::Result;