diff --git a/.github/workflows/clippy-rustfmt-fix.yml b/.github/workflows/clippy-rustfmt-fix.yml index 620863af..fc2cfd76 100644 --- a/.github/workflows/clippy-rustfmt-fix.yml +++ b/.github/workflows/clippy-rustfmt-fix.yml @@ -12,7 +12,7 @@ env: target/ jobs: - publish: + run-and-commit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -23,15 +23,19 @@ jobs: - name: Run automated fixes run: | - cargo clippy --fix + # Run clippy on projects + cargo clippy --fix --manifest-path ./parser/Cargo.toml --allow-dirty + cargo clippy --fix --manifest-path ./checker/Cargo.toml --allow-dirty + cargo clippy --fix --allow-dirty + + # Format cargo fmt - - name: Commit + - name: Commit changes run: | - git add . - git commit -m "Run clippy --fix & formatting" - git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - + + git add . + git commit -m "Run clippy --fix & cargo fmt" git push diff --git a/.github/workflows/github-release.yml b/.github/workflows/github-release.yml index 86484f2c..f2fd325a 100644 --- a/.github/workflows/github-release.yml +++ b/.github/workflows/github-release.yml @@ -21,7 +21,8 @@ jobs: runs-on: ubuntu-latest outputs: - new-ezno-version: ${{ steps.get-version.outputs.new-ezno-version }} + LATEST_EZNO_VERSION: ${{ steps.get-version.outputs.LATEST_EZNO_VERSION }} + LATEST_EZNO_VERSION_DASH: ${{ steps.get-version.outputs.LATEST_EZNO_VERSION_DASH }} SPONSORS: ${{ steps.get-sponsors-and-contributors.outputs.SPONSORS }} CONTRIBUTORS: ${{ steps.get-sponsors-and-contributors.outputs.CONTRIBUTORS }} @@ -38,43 +39,32 @@ jobs: git for-each-ref --sort=creatordate --format '%(refname:short)' 'refs/tags/release/ezno-[0-9]*' echo "::endgroup::" - TAG=$(git for-each-ref --sort=creatordate --format '%(refname:short)' 'refs/tags/release/ezno-[0-9]*' | tail -n 1) - echo "Building GH release for ${TAG:13}" - echo "new-ezno-version=${TAG:13}" >> $GITHUB_OUTPUT + TAG=$(git for-each-ref --sort=creatordate --format '%(refname:short)' 'refs/tags/release/ezno-[0-9]*' | tail -n 1 | cut -c 14-) - # Replace '.' with '-' - NAME_VERSION=$(echo $VERSION | sed -e "s/\./-/g") + echo "::notice::Releasing with found version $TAG" + echo "LATEST_EZNO_VERSION=${TAG}" >> "$GITHUB_OUTPUT" + echo "LATEST_EZNO_VERSION_DASH=${TAG//./-}" >> "$GITHUB_OUTPUT" else - VERSION="${{ inputs.ezno-version }}" - echo "Building GH release for ${VERSION}" - echo "new-ezno-version=${VERSION}" >> $GITHUB_OUTPUT + TAG="${{ inputs.ezno-version }}" - # Replace '.' with '-' - NAME_VERSION=$(echo $VERSION | sed -e "s/\./-/g") + echo "::notice::Releasing with specific version $TAG" + echo "LATEST_EZNO_VERSION=${TAG}" >> "$GITHUB_OUTPUT" + echo "LATEST_EZNO_VERSION_DASH=${TAG//./-}" >> "$GITHUB_OUTPUT" fi - - id: get-sponsors-and-contributors + - name: Get sponsors and contributors + id: get-sponsors-and-contributors run: | - SPONSORS=$(gh api graphql -f query='{ - user(login: "kaleidawave") { - sponsorshipsAsMaintainer(first: 100, activeOnly: false) { - edges { - node { - sponsor { - name, login - } - } - } - } - } - }' -q '.data.user.sponsorshipsAsMaintainer.edges | map(.node.sponsor.name // .node.sponsor.login) | join(",")') - - CONTRIBUTORS=$( - gh pr list --state merged --json author | jq 'map(.author.name // .author.login) | unique | join(",")' --raw-output - ) + SQP='.data.user.sponsorshipsAsMaintainer.edges | map(.node.sponsor.name // .node.sponsor.login) | join(",")' + GQL_SQ='{ user(login: "kaleidawave") { sponsorshipsAsMaintainer(first: 100, activeOnly: false) { edges { node { sponsor { name, login } } } } } }' + SPONSORS=$(gh api graphql -f query="$GQL_SQ" -q "$SQP") + + CQP='map(.author.name // .author.login) | unique | join(",")' + CONTRIBUTORS=$(gh pr list --state merged --json author | jq "$CQP" --raw-output) - echo "SPONSORS=$SPONSORS" # >> $GITHUB_OUTPUT - echo "CONTRIBUTORS=$CONTRIBUTORS" + echo "SPONSORS=$SPONSORS" >> "$GITHUB_OUTPUT" + echo "CONTRIBUTORS=$CONTRIBUTORS" >> "$GITHUB_OUTPUT" + echo "::notice::CONTRIBUTORS=$CONTRIBUTORS and SPONSORS=$SPONSORS" shell: bash env: @@ -88,13 +78,16 @@ jobs: os: [ubuntu-latest, windows-latest] include: - os: windows-latest - executable-extension: .exe - platform_name: x86_64-pc-windows + platform-name: x86_64-pc-windows + executable-extension: ".exe" - os: ubuntu-latest - platform_name: x86_64-unknown-linux + platform-name: x86_64-unknown-linux runs-on: ${{ matrix.os }} + env: + LEVEL: release + # Important that everything here works in all the above OSes! steps: - uses: actions/checkout@v4 @@ -110,10 +103,10 @@ jobs: SPONSORS: ${{ needs.get-build-info.outputs.SPONSORS }} CONTRIBUTORS: ${{ needs.get-build-info.outputs.CONTRIBUTORS }} - - name: Rename and move release assets + - name: Rename and move ${{ env.LEVEL }} assets run: | mkdir artifacts - mv target/release/ezno${{ matrix.executable-extension }} "artifacts/ezno-${{ needs.get-build-info.outputs.new-ezno-version }}-${{ matrix.platform_name }}${{ matrix.executable-extension }}" + mv "target/${{ env.LEVEL }}/ezno${{ matrix.executable-extension }}" "artifacts/ezno-${{ needs.get-build-info.outputs.LATEST_EZNO_VERSION_DASH }}-${{ matrix.platform-name }}${{ matrix.executable-extension }}" - uses: actions/upload-artifact@v4 with: @@ -144,8 +137,8 @@ jobs: - name: GitHub release uses: softprops/action-gh-release@v1 with: - name: "Ezno ${{ needs.get-build-info.outputs.new-ezno-version }}" - tag_name: "release/ezno-${{ needs.get-build-info.outputs.new-ezno-version }}" + name: "Ezno ${{ needs.get-build-info.outputs.LATEST_EZNO_VERSION }}" + tag_name: "release/ezno-${{ needs.get-build-info.outputs.LATEST_EZNO_VERSION }}" body: "For @kaleidawave to update" files: | README.md diff --git a/.github/workflows/performance-and-size.yml b/.github/workflows/performance-and-size.yml index e58e86c5..6d5dcdb6 100644 --- a/.github/workflows/performance-and-size.yml +++ b/.github/workflows/performance-and-size.yml @@ -28,21 +28,47 @@ jobs: - uses: brndnmtthws/rust-action-cargo-binstall@v1 with: packages: hyperfine + + - name: Install valgrind + run: sudo apt-get install valgrind - name: Build Ezno run: cargo build --release env: CARGO_PROFILE_RELEASE_DEBUG: true + - name: Get base ezno + if: github.ref_name != 'main' + uses: actions/download-artifact@v4 + continue-on-error: true + with: + name: latest-checker + path: previous-ezno + + - name: Set compilers + id: compilers + shell: bash + run: | + if [ -d "previous-ezno" ]; then + echo "::notice::Comparing against previous" + echo "BINARIES=./target/release/ezno,./previous-ezno/ezno" >> "$GITHUB_OUTPUT" + else + echo "::notice::Running singularly" + echo "BINARIES=./target/release/ezno" >> "$GITHUB_OUTPUT" + fi + - name: Run checker performance shell: bash run: | # Generate a file which contains everything that Ezno currently implements - cargo run -p ezno-parser --example code_blocks_to_script ./checker/specification/specification.md --comment-headers --out ./demo.tsx + cargo run -p ezno-parser \ + --example code_blocks_to_script ./checker/specification/specification.md \ + --comment-headers \ + --out ./demo.tsx echo "### Checking \`\`\`shell - $(hyperfine -i './target/release/ezno check demo.tsx') + $(hyperfine -i -L compiler ${{ steps.compilers.outputs.BINARIES }} '{compiler} check demo.tsx') \`\`\`" >> $GITHUB_STEP_SUMMARY echo "
@@ -58,8 +84,8 @@ jobs: echo "::info::Wrote code to summary" command_output=$(./target/release/ezno check demo.tsx --timings --max-diagnostics all 2>&1 || true) + diagnostics=""; statistics=""; found_splitter=false; - while IFS= read -r line; do if [[ "$line" == "---"* ]]; then found_splitter=true; elif [[ "$found_splitter" == false ]]; then diagnostics+="$line"$'\n'; @@ -73,16 +99,35 @@ jobs: $diagnostics \`\`\`
- -
- Statistics - - \`\`\` - $statistics - \`\`\` -
" >> $GITHUB_STEP_SUMMARY + if [ -d "previous-ezno" ]; then + OUT=$(./previous-ezno/ezno check demo.tsx --timings --max-diagnostics all 2>&1 || true) + $base_statistics=$(echo $OUT | rg "Diagnostics:" -A 100) + echo " +
+ Statistics + + \`\`\` + $statistics + \`\`\` + against base + \`\`\` + $base_statistics + \`\`\` + against base +
+ " >> $GITHUB_STEP_SUMMARY + else + echo "
+ Statistics + + \`\`\` + $statistics + \`\`\` +
" >> $GITHUB_STEP_SUMMARY + fi + - name: Run checker performance w/staging shell: bash if: github.ref_name != 'main' @@ -93,7 +138,8 @@ jobs: cargo run -p ezno-parser --example code_blocks_to_script all.md --comment-headers --out ./all.tsx ./target/release/ezno check all.tsx --timings || true - hyperfine -i './target/release/ezno check all.tsx' + + hyperfine -i -L compiler ${{ steps.compilers.outputs.BINARIES }} '{compiler} check all.tsx' echo "::endgroup::" - name: Run checker performance on large file @@ -109,23 +155,58 @@ jobs: done ./target/release/ezno check large.tsx --timings --max-diagnostics 0 || true - hyperfine -i './target/release/ezno check large.tsx' + + hyperfine -i -L compiler ${{ steps.compilers.outputs.BINARIES }} '{compiler} check large.tsx' echo "::endgroup::" + - name: Valgrind and callgrind + shell: bash + continue-on-error: true + run: | + IFS=',' read -ra ITEMS <<< ${{ steps.compilers.outputs.BINARIES }} + + for compiler in ${ITEMS[@]}; do + echo "::group::Running $compiler" + + echo "::group::Callgrind" + valgrind --tool=callgrind --callgrind-out-file=cpu-out $compiler check demo.tsx | true + echo "CPU usage:" + head -n100 cpu-out + echo "::endgroup::" + + echo "::group::Valgrind" + valgrind --log-file=memory-out $compiler check demo.tsx | true + echo "Memory usage:" + cat memory-out + echo "::endgroup::" + + echo "::endgroup::" + done + - name: Run parsing & stringing (minfied) benchmarks shell: bash + continue-on-error: true run: | strings=( "https://esm.sh/v128/react-dom@18.2.0/es2022/react-dom.mjs" + "https://esm.sh/v135/typescript@5.3.3/es2022/typescript.mjs" ) - # Currently broken "https://esm.sh/v135/typescript@5.3.3/es2022/typescript.mjs" for url in "${strings[@]}"; do - curl -sS $url > input.js - echo "--- debug: $url ---" - cargo run -p ezno-parser --example parse input.js --timings --render-timings - echo "--- release: $url ---" - cargo run -p ezno-parser --release --example parse input.js --timings --render-timings - - hyperfine "./target/debug/examples/parse input.js" "./target/release/examples/parse input.js" + # TODO copy expression + curl -sS $url > input.js + + echo "::group::Comparison" + hyperfine \ + -L compiler ${{ steps.compilers.outputs.BINARIES }} \ + '{compiler} ast-explorer full input.js --timings' + echo "::endgroup::" done + + - name: Upload checker + if: github.ref == 'main' + uses: actions/upload-artifact@v4 + with: + name: latest-checker + path: target/release/ezno + retention-days: 90 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 193a1505..f7411899 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -58,30 +58,20 @@ jobs: echo "publish-json-args=$KEY_PAIR_ARGS_JSON" >> $GITHUB_OUTPUT shell: bash - - id: get-sponsors + # Needed for WASM + - name: Get sponsors and contributors + id: get-sponsors-and-contributors run: | - SPONSORS=$( - gh api graphql -f query='{ - user(login: "kaleidawave") { - sponsorshipsAsMaintainer(first: 100, activeOnly: false) { - edges { - node { - sponsor { - name, login - } - } - } - } - } - }' -q '.data.user.sponsorshipsAsMaintainer.edges | map(.node.sponsor.name // .node.sponsor.login) | join(",")' - ) - - CONTRIBUTORS=$( - gh pr list --state merged --json author | jq 'map(.author.name // .author.login) | unique | join(",")' --raw-output - ) - - echo "SPONSORS=$SPONSORS" >> $GITHUB_OUTPUT - echo "CONTRIBUTORS=$CONTRIBUTORS" >> $GITHUB_OUTPUT + SQP='.data.user.sponsorshipsAsMaintainer.edges | map(.node.sponsor.name // .node.sponsor.login) | join(",")' + GQL_SQ='{ user(login: "kaleidawave") { sponsorshipsAsMaintainer(first: 100, activeOnly: false) { edges { node { sponsor { name, login } } } } } }' + SPONSORS=$(gh api graphql -f query="$GQL_SQ" -q "$SQP") + + CQP='map(.author.name // .author.login) | unique | join(",")' + CONTRIBUTORS=$(gh pr list --state merged --json author | jq "$CQP" --raw-output) + + echo "SPONSORS=$SPONSORS" >> "$GITHUB_OUTPUT" + echo "CONTRIBUTORS=$CONTRIBUTORS" >> "$GITHUB_OUTPUT" + echo "::notice::CONTRIBUTORS=$CONTRIBUTORS and SPONSORS=$SPONSORS" shell: bash env: @@ -94,8 +84,8 @@ jobs: version: ${{ steps.set-arguments.outputs.publish-json-args }} crates-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} env: - SPONSORS: ${{ steps.get-sponsors.outputs.SPONSORS }} - CONTRIBUTORS: ${{ steps.get-sponsors.outputs.CONTRIBUTORS }} + SPONSORS: ${{ steps.get-sponsors-and-contributors.outputs.SPONSORS }} + CONTRIBUTORS: ${{ steps.get-sponsors-and-contributors.outputs.CONTRIBUTORS }} - name: Add WASM to rustup if: ${{ inputs.ezno-version != 'none' }} @@ -115,7 +105,8 @@ jobs: ls dist working-directory: src/js-cli-and-library env: - SPONSORS: ${{ steps.get-sponsors.outputs.sponsors }} + SPONSORS: ${{ steps.get-sponsors-and-contributors.outputs.SPONSORS }} + CONTRIBUTORS: ${{ steps.get-sponsors-and-contributors.outputs.CONTRIBUTORS }} - name: NPM publish (CLI and library) if: ${{ inputs.ezno-version != 'none' }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9a2efc66..e45c83c5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -88,6 +88,7 @@ jobs: run: | cargo test + # TODO more curl https://esm.sh/v128/react-dom@18.2.0/es2022/react-dom.mjs > react.js cargo run -p ezno-parser --example parse react.js working-directory: parser @@ -95,12 +96,19 @@ jobs: - name: Run checker specification if: (steps.changes.outputs.checker == 'true' && github.event_name != 'pull_request') || github.ref_name == 'main' run: cargo test - working-directory: checker/specification - name: Run checker specification (w/ staging) if: steps.changes.outputs.checker == 'true' && github.event_name == 'pull_request' - run: cargo test -F staging - working-directory: checker/specification + run: cargo test -F staging -p ezno-checker-specification + env: + EZNO_DEBUG: 1 + + - name: Run checker specification (just to implement) + continue-on-error: true + if: steps.changes.outputs.checker == 'true' && github.event_name == 'pull_request' + run: | + # Aim of this test is to catch anything that may have been fixed in this next commit or any bad regressions (stack overflows) + cargo test --no-default-features -F to_implement -p ezno-checker-specification env: EZNO_DEBUG: 1 @@ -108,10 +116,9 @@ jobs: if: steps.changes.outputs.checker == 'true' || github.ref_name == 'main' run: | # Test checker with the parser features - cargo test -F ezno-parser - working-directory: checker + cargo test -F ezno-parser -p ezno-checker - - name: Run base tests + - name: Run CLI and base tests run: cargo test extras: @@ -126,7 +133,7 @@ jobs: with: path: ${{ env.CACHE_PATHS }} key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - + - uses: dorny/paths-filter@v3 id: changes with: @@ -145,7 +152,7 @@ jobs: - uses: actions/setup-node@v4 if: steps.changes.outputs.src == 'true' || github.ref_name == 'main' with: - node-version: 18 + node-version: 23 - name: Check parser without extras if: steps.changes.outputs.parser == 'true' @@ -167,17 +174,19 @@ jobs: - name: Build and test WASM if: steps.changes.outputs.src == 'true' || github.ref_name == 'main' + timeout-minutes: 5 run: | # TODO `cargo check --target wasm32-unknown-unknown --lib` might be good enough rustup target add wasm32-unknown-unknown npm ci npm run build - npm run run-tests node ./dist/cli.cjs info deno run -A ./dist/cli.mjs info + npm run run-tests + npx -p typescript tsc --strict --pretty ./build/ezno_lib.d.ts echo "debug checked with TSC" cargo run -p ezno-parser --example parse ./build/ezno_lib.d.ts --type-definition-module @@ -190,6 +199,7 @@ jobs: working-directory: src/js-cli-and-library shell: bash + # WIP - uses: actions/upload-artifact@v4 if: steps.changes.outputs.src == 'true' || github.ref_name == 'main' with: @@ -198,6 +208,7 @@ jobs: retention-days: 3 fuzzing_parser: + if: ${{ github.ref == 'main' || !github.event.pull_request.draft || contains(github.event.pull_request.labels.*.name, 'fuzz-me') }} needs: validity runs-on: ubuntu-latest timeout-minutes: 15 @@ -255,6 +266,7 @@ jobs: working-directory: parser/fuzz fuzzing_checker: + if: ${{ github.ref == 'main' || !github.event.pull_request.draft || contains(github.event.pull_request.labels.*.name, 'fuzz-me') }} needs: validity runs-on: ubuntu-latest timeout-minutes: 15 @@ -347,3 +359,15 @@ jobs: fi done shell: bash + + performance-and-size: + # WIP + runs-on: ubuntu-latest + needs: validity + steps: + - uses: actions/checkout@v4 + - name: Kick off other workflow if the PR has a label + if: github.ref_name != 'main' && contains(github.event.pull_request.labels.*.name, 'compiler-performance') + run: gh workflow run performance-and-size.yml --ref "${{ github.head_ref }}" + env: + GH_TOKEN: ${{ github.token }} diff --git a/Cargo.lock b/Cargo.lock index fcfcbdfc..b6be9713 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,7 +39,7 @@ dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" @@ -90,15 +90,15 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.17.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ "shlex", ] @@ -190,7 +190,7 @@ checksum = "42e5ddace13a8459cb452b19e01f59f16d3e2049c8b808f338a13eeadc326e33" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] @@ -211,7 +211,7 @@ dependencies = [ "either_n", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] @@ -266,7 +266,7 @@ dependencies = [ "proc-macro2", "quote", "string-cases", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] @@ -384,15 +384,6 @@ dependencies = [ "syn-helpers", ] -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.1.1" @@ -511,15 +502,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "iterator-endiate" version = "0.2.1" @@ -575,9 +557,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libredox" @@ -727,15 +709,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -754,7 +736,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] @@ -765,9 +747,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -777,9 +759,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.2.2" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a91171844676f8c7990ce64959210cd2eaef32c2612c50f9fae9f8aaa6065a6" +checksum = "c65ee1f9701bf938026630b455d5315f490640234259037edb259798b3bcf85e" dependencies = [ "num-traits", ] @@ -833,15 +815,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -849,9 +831,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -867,18 +849,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "regress" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16fe0a24af5daaae947294213d2fd2646fbf5e1fbacc1d4ba3e84b2393854842" +checksum = "1541daf4e4ed43a0922b7969bdc2170178bcacc5dabf7e39bc508a9fa3953a7a" dependencies = [ "hashbrown", "memchr", @@ -886,18 +868,18 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f86ae463694029097b846d8f99fd5536740602ae00022c0c50c5600720b2f71" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags 2.6.0", "errno", @@ -923,11 +905,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -951,9 +933,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -961,13 +943,13 @@ dependencies = [ [[package]] name = "self-replace" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7828a58998685d8bf5a3c5e7a3379a5867289c20828c3ee436280b44b598515" +checksum = "03ec815b5eab420ab893f63393878d89c90fdd94c0bcc44c07abb8ad95552fb7" dependencies = [ - "fastrand 1.9.0", + "fastrand", "tempfile", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -992,9 +974,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] @@ -1012,13 +994,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] @@ -1029,14 +1011,14 @@ checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -1094,9 +1076,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.76" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -1112,17 +1094,17 @@ dependencies = [ "either_n", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", - "fastrand 2.1.1", + "fastrand", "once_cell", "rustix", "windows-sys 0.59.0", @@ -1174,20 +1156,20 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.76", + "syn 2.0.87", ] [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "vcpkg" @@ -1238,7 +1220,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -1282,7 +1264,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1495,9 +1477,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" @@ -1516,5 +1498,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.87", ] diff --git a/Cargo.toml b/Cargo.toml index 8e1d21e6..7f0a5fd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ members = [ [package] name = "ezno" -description = "A JavaScript type checker and compiler. For use as a library or through the CLI" +description = "A fast and correct TypeScript type checker and compiler with additional experiments. For use as a library or through the CLI" authors = ["Ben "] version = "0.0.22" edition = "2021" @@ -48,6 +48,7 @@ pretty_assertions = "1.3.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" simple-json-parser = "0.0.2" +js-sys = "0.3" [target.'cfg(not(target_family = "wasm"))'.dependencies] # For updating binary diff --git a/README.md b/README.md index 1a174c96..27dfc88b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -A JavaScript compiler and TypeScript checker written in Rust with a focus on static analysis and runtime performance. +A fast and correct TypeScript type checker and compiler with additional experiments > [!IMPORTANT] > Ezno is in active development and **does not currently support enough features to check existing projects** (see [blocking issues](https://github.com/kaleidawave/ezno/labels/blocking)). Check out the [getting started guide](./checker/documentation/getting-started.md) for experimenting with what it [currently supports](./checker/specification/specification.md). @@ -28,6 +28,7 @@ Read more about Ezno (in chronological order) - [Ezno in '23](https://kaleidawave.github.io/posts/ezno-23/) - [A preview of the checker](https://kaleidawave.github.io/posts/a-preview-of-the-checker/) - [The quest continues](https://kaleidawave.github.io/posts/the-quest-continues/) +- [Sets, types and type checking](https://kaleidawave.github.io/posts/sets-types-and-type-checking/) (*general post*) --- diff --git a/checker/Cargo.toml b/checker/Cargo.toml index 242c5608..2461cae6 100644 --- a/checker/Cargo.toml +++ b/checker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ezno-checker" -description = "A type checker for JavaScript" +description = "A fast and correct TypeScript type checker with additional experiments" version = "0.0.17" license = "MIT" repository = "https://github.com/kaleidawave/ezno" diff --git a/checker/examples/run_checker.rs b/checker/examples/run_checker.rs index aab40341..124c86e8 100644 --- a/checker/examples/run_checker.rs +++ b/checker/examples/run_checker.rs @@ -52,7 +52,7 @@ fn main() { let result = check_project::<_, synthesis::EznoParser>( entry_points, type_definition_files, - resolver, + &resolver, options, (), None, diff --git a/checker/fuzz/fuzz_targets/check_project_naive.rs b/checker/fuzz/fuzz_targets/check_project_naive.rs index 6a6039d9..014b25ea 100644 --- a/checker/fuzz/fuzz_targets/check_project_naive.rs +++ b/checker/fuzz/fuzz_targets/check_project_naive.rs @@ -19,7 +19,7 @@ fn do_fuzz(data: &str) -> Corpus { let _result = check_project::<_, synthesis::EznoParser>( vec![root.into()], type_definition_files, - |_path: &std::path::Path| Some(input.to_owned()), + &|_path: &std::path::Path| Some(input.to_owned()), options, (), None, diff --git a/checker/specification/build.rs b/checker/specification/build.rs index e31236a4..1b20193d 100644 --- a/checker/specification/build.rs +++ b/checker/specification/build.rs @@ -19,14 +19,18 @@ fn main() -> Result<(), Box> { if cfg!(feature = "staging") { let staging = read_to_string("./staging.md")?; - writeln!(&mut out, "mod staging {{ use super::check_errors; ").unwrap(); + writeln!(&mut out, "mod staging {{ ").unwrap(); + writeln!(&mut out, "use super::{{check_expected_diagnostics, TypeCheckOptions}}; ") + .unwrap(); markdown_lines_append_test_to_rust(staging.lines().enumerate(), &mut out)?; writeln!(&mut out, "}}").unwrap(); } if cfg!(feature = "all") { let to_implement = read_to_string("./to_implement.md")?; - writeln!(&mut out, "mod to_implement {{ use super::check_errors; ").unwrap(); + writeln!(&mut out, "mod to_implement {{ ").unwrap(); + writeln!(&mut out, "use super::{{check_expected_diagnostics, TypeCheckOptions}}; ") + .unwrap(); markdown_lines_append_test_to_rust(to_implement.lines().enumerate(), &mut out)?; writeln!(&mut out, "}}").unwrap(); } @@ -60,8 +64,20 @@ fn markdown_lines_append_test_to_rust( let heading = line.strip_prefix("####").unwrap().trim_start(); let test_title = heading_to_rust_identifier(heading); - let blocks = { - let mut blocks = Vec::new(); + pub struct File<'a> { + path: &'a str, + code: String, + } + + // pub struct Block { + // /// Vec for FS tests + // files: Vec, + // expected_diagnostics: Vec, + // options: Vec + // } + + let files = { + let mut files = Vec::::new(); let mut current_filename = None; for (_, line) in lines.by_ref() { // Also handles TSX @@ -74,10 +90,10 @@ fn markdown_lines_append_test_to_rust( for (_, line) in lines.by_ref() { if let Some(path) = line.strip_prefix("// in ") { if !code.trim().is_empty() { - blocks.push(( - current_filename.unwrap_or(DEFAULT_FILE_PATH), - mem::take(&mut code), - )); + files.push(File { + path: current_filename.unwrap_or(DEFAULT_FILE_PATH), + code: mem::take(&mut code), + }); } current_filename = Some(path); continue; @@ -88,40 +104,64 @@ fn markdown_lines_append_test_to_rust( code.push_str(line); code.push('\n') } - blocks.push((current_filename.unwrap_or(DEFAULT_FILE_PATH), code)); - blocks + files.push(File { path: current_filename.unwrap_or(DEFAULT_FILE_PATH), code }); + files }; - let errors = { - let mut errors = Vec::new(); + + let (expected_diagnostics, options) = { + let mut expected_diagnostics = Vec::new(); + let mut options = None::>; for (_, line) in lines.by_ref() { - if line.starts_with("#") { + if let (Some(args), false) = (line.strip_prefix("With "), options.is_some()) { + options = Some(args.split(',').collect()); + } else if line.starts_with("#") { panic!("block with no diagnostics or break between in {test_title}") - } else if line.starts_with('-') { - let error = - line.strip_prefix("- ").unwrap().replace('\\', "").replace('"', "\\\""); - errors.push(format!("\"{}\"", error)) - } else if !errors.is_empty() { + } else if let Some(diagnostic) = line.strip_prefix("-") { + let error = diagnostic.trim().replace('\\', "").replace('"', "\\\""); + expected_diagnostics.push(format!("\"{}\"", error)) + } else if !expected_diagnostics.is_empty() { break; } } - errors + (expected_diagnostics, options) }; - let errors = errors.join(", "); + let expected_diagnostics = expected_diagnostics.join(", "); let heading_idx = heading_idx + 1; - let code = blocks + // TODO don't allocate + let code_as_list = files .into_iter() - .map(|(path, content)| format!("(\"{path}\",r#\"{content}\"#),")) - .fold(String::new(), |mut acc, cur| { - acc.push_str(&cur); + .map(|File { path, code }| format!("(\"{path}\",r#\"{code}\"#),")) + .reduce(|mut acc, slice| { + acc.push_str(&slice); acc - }); + }) + .unwrap(); + + let options = if let Some(options) = options { + let arguments = options + .into_iter() + .map(|value| format!("{value}: true")) + .reduce(|mut acc, slice| { + acc.push_str(&slice); + acc.push_str(", "); + acc + }) + .unwrap(); + format!("Some(super::TypeCheckOptions {{ {arguments}, ..super::TypeCheckOptions::default() }})") + } else { + format!("None") + }; writeln!( out, "#[test] fn {test_title}() {{ - super::check_errors(\"{heading}\", {heading_idx}, &[{code}], &[{errors}]) + super::check_expected_diagnostics( + \"{heading}\", {heading_idx}, + &[{code_as_list}], &[{expected_diagnostics}], + {options} + ) }}", )?; } @@ -136,6 +176,6 @@ fn heading_to_rust_identifier(heading: &str) -> String { heading .replace("...", "") .replace([' ', '-', '/', '.', '+'], "_") - .replace(['*', '\'', '`', '"', '&', '!', '(', ')', ','], "") + .replace(['*', '\'', '`', '"', '&', '!', '(', ')', ',', ':'], "") .to_lowercase() } diff --git a/checker/specification/specification.md b/checker/specification/specification.md index 60dbc932..88a305b0 100644 --- a/checker/specification/specification.md +++ b/checker/specification/specification.md @@ -3684,18 +3684,6 @@ box(someNumber) satisfies boolean; - Expected string, found number - Expected boolean, found { item: number } -#### Template literal type restriction - -```ts -type Name = "Ben" -"test" satisfies `Hello ${Name}`; -"Hello Ben" satisfies `Hello ${Name}`; -``` - -> Should be `Expected "Hello Ben", found "test"`. See #188 - -- Expected `Hello ${Name}`, found \"test\" - #### Template literal type specialisation > Uses `+` logic behind the scenes diff --git a/checker/specification/test.rs b/checker/specification/test.rs index 85166a18..b98dd727 100644 --- a/checker/specification/test.rs +++ b/checker/specification/test.rs @@ -11,13 +11,14 @@ use checker::{ diagnostics, source_map::{Nullable, SourceId}, synthesis::EznoParser, + TypeCheckOptions, }; // This is here as it is used in the included `/specification.rs` use parser::ASTNode; mod specification { - use super::check_errors; + use super::{check_expected_diagnostics, TypeCheckOptions}; // from build.rs include!(concat!(env!("OUT_DIR"), "/specification.rs")); @@ -37,12 +38,13 @@ const SIMPLE_DTS: Option<&str> = None; const IN_CI: bool = option_env!("CI").is_some(); /// Called by each test -fn check_errors( +fn check_expected_diagnostics( heading: &'static str, - _line: usize, + line: usize, // (Path, Content) code: &[(&'static str, &'static str)], expected_diagnostics: &[&'static str], + type_check_options: Option, ) { // let global_buffer = Arc::new(Mutex::new(String::new())); // let old_panic_hook = panic::take_hook(); @@ -59,10 +61,7 @@ fn check_errors( // }) // }); - // TODO could test these - let type_check_options = Default::default(); - - // eprintln!("{:?}", code); + let type_check_options = type_check_options.unwrap_or_default(); // let result = panic::catch_unwind(|| { @@ -95,7 +94,7 @@ fn check_errors( let result = checker::check_project::<_, EznoParser>( vec![PathBuf::from("main.tsx")], type_definition_files, - resolver, + &resolver, type_check_options, (), None, @@ -125,7 +124,7 @@ fn check_errors( if diagnostics != expected_diagnostics { panic!( - "{}", + "In '{heading}' on line {line}, found\n{}", pretty_assertions::Comparison::new(expected_diagnostics, &diagnostics).to_string() ) } diff --git a/checker/src/context/invocation.rs b/checker/src/context/invocation.rs index b7218ade..c20fa8da 100644 --- a/checker/src/context/invocation.rs +++ b/checker/src/context/invocation.rs @@ -69,7 +69,7 @@ pub struct InvocationContext(Vec); /// TODO want to have type arguments on each of these pub(crate) enum InvocationKind { - Conditional(LocalInformation), + Conditional(Box), /// *Unconditional* /// /// TODO does this need [`LocalInformation`]?? @@ -89,15 +89,13 @@ impl CallCheckingBehavior for InvocationContext { self.0 .iter_mut() .rev() - .find_map( - |kind| { - if let InvocationKind::Conditional(info) = kind { - Some(info) - } else { - None - } - }, - ) + .find_map(|kind| -> Option<&mut LocalInformation> { + if let InvocationKind::Conditional(info) = kind { + Some(&mut *info) + } else { + None + } + }) .unwrap_or(&mut environment.info) } @@ -142,10 +140,10 @@ impl InvocationContext { &mut self, cb: impl for<'a> FnOnce(&'a mut InvocationContext) -> T, ) -> (LocalInformation, T) { - self.0.push(InvocationKind::Conditional(LocalInformation::default())); + self.0.push(InvocationKind::Conditional(Box::default())); let result = cb(self); if let Some(InvocationKind::Conditional(info)) = self.0.pop() { - (info, result) + (*info, result) } else { unreachable!() } diff --git a/checker/src/diagnostics.rs b/checker/src/diagnostics.rs index 94cecf0a..78943ade 100644 --- a/checker/src/diagnostics.rs +++ b/checker/src/diagnostics.rs @@ -114,18 +114,18 @@ pub struct DiagnosticsContainer { diagnostics: Vec, // Quick way to check whether a error was added #[cfg_attr(feature = "serde-serialize", serde(skip_serializing))] - has_error: bool, + contains_error: bool, } // TODO the add methods are the same... impl DiagnosticsContainer { #[must_use] pub fn new() -> Self { - Self { diagnostics: Default::default(), has_error: false } + Self { diagnostics: Default::default(), contains_error: false } } pub fn add_error>(&mut self, error: T) { - self.has_error = true; + self.contains_error = true; self.diagnostics.push(error.into()); } @@ -138,8 +138,8 @@ impl DiagnosticsContainer { } #[must_use] - pub fn has_error(&self) -> bool { - self.has_error + pub fn contains_error(&self) -> bool { + self.contains_error } pub fn sources(&self) -> impl Iterator + '_ { @@ -153,7 +153,7 @@ impl DiagnosticsContainer { } pub fn into_result(self) -> Result { - if self.has_error { + if self.contains_error { Err(self) } else { Ok(self) diff --git a/checker/src/features/regexp.rs b/checker/src/features/regexp.rs index 7797cef9..297d0334 100644 --- a/checker/src/features/regexp.rs +++ b/checker/src/features/regexp.rs @@ -15,7 +15,7 @@ pub struct RegExp { source: String, re: Regex, groups: u32, - named_group_indices: crate::Map, + group_names: Vec>, flags_unsupported: bool, used: bool, } @@ -65,13 +65,12 @@ impl RegExp { // let start_pred = compiled_regex.start_pred; // let loops = compiled_regex.loops; let groups = compiled_regex.groups + 1; - let named_group_indices = - compiled_regex.named_group_indices.iter().map(|(l, r)| (l.clone(), *r)).collect(); + let group_names = compiled_regex.group_names.to_vec(); // let flags = compiled_regex.flags; let re = Regex::from(compiled_regex); - Ok(Self { source, re, groups, named_group_indices, flags_unsupported, used: false }) + Ok(Self { source, re, groups, group_names, flags_unsupported, used: false }) } #[must_use] @@ -262,7 +261,7 @@ impl RegExp { &mut environment.info, ); - for name in self.named_group_indices.keys() { + for name in &self.group_names { let key = PropertyKey::String(name.to_string().into()); named_groups_object.append( diff --git a/checker/src/lib.rs b/checker/src/lib.rs index 39e60306..d7ee7802 100644 --- a/checker/src/lib.rs +++ b/checker/src/lib.rs @@ -459,13 +459,13 @@ impl CheckOutput { pub fn check_project( entry_points: Vec, type_definition_files: Vec, - resolver: T, + resolver: &T, options: TypeCheckOptions, parser_requirements: A::ParserRequirements, existing_files: Option>, ) -> CheckOutput { let mut checking_data = - CheckingData::::new(options, &resolver, existing_files, parser_requirements); + CheckingData::::new(options, resolver, existing_files, parser_requirements); let mut root = crate::context::RootContext::new_with_primitive_references(); @@ -478,7 +478,7 @@ pub fn check_project( add_definition_files_to_root(type_definition_files, &mut root, &mut checking_data); crate::utilities::unpause_debug_mode(); - if checking_data.diagnostics_container.has_error() { + if checking_data.diagnostics_container.contains_error() { return CheckOutput { types: checking_data.types, module_contents: checking_data.modules.files, @@ -753,7 +753,7 @@ pub fn generate_cache( add_definition_files_to_root(vec![on.to_path_buf()], &mut root, &mut checking_data); assert!( - !checking_data.diagnostics_container.has_error(), + !checking_data.diagnostics_container.contains_error(), "found error in definition file {:#?}", checking_data.diagnostics_container.get_diagnostics() ); diff --git a/checker/src/synthesis/interactive.rs b/checker/src/synthesis/interactive.rs new file mode 100644 index 00000000..54f8a620 --- /dev/null +++ b/checker/src/synthesis/interactive.rs @@ -0,0 +1,90 @@ +/// For the REPL in Ezno's CLI +use std::{mem, path::PathBuf}; + +use source_map::{FileSystem, MapFileStore, SourceId, WithPathMap}; + +use crate::{ + add_definition_files_to_root, types::printing::print_type, CheckingData, DiagnosticsContainer, + RootContext, TypeId, +}; + +use super::{block::synthesise_block, expressions::synthesise_multiple_expression}; + +pub struct State<'a, T: crate::ReadFromFS> { + checking_data: CheckingData<'a, T, super::EznoParser>, + root: RootContext, + source: SourceId, +} + +impl<'a, T: crate::ReadFromFS> State<'a, T> { + pub fn new( + resolver: &'a T, + type_definition_files: Vec, + ) -> Result)> { + let mut root = RootContext::new_with_primitive_references(); + let mut checking_data = + CheckingData::new(Default::default(), resolver, Default::default(), ()); + + add_definition_files_to_root(type_definition_files, &mut root, &mut checking_data); + + if checking_data.diagnostics_container.contains_error() { + Err((checking_data.diagnostics_container, checking_data.modules.files)) + } else { + let source = + checking_data.modules.files.new_source_id("CLI.tsx".into(), String::default()); + Ok(Self { checking_data, root, source }) + } + } + + pub fn check_item( + &mut self, + item: &parser::Module, + ) -> Result<(Option, DiagnosticsContainer), DiagnosticsContainer> { + let (ty, ..) = self.root.new_lexical_environment_fold_into_parent( + crate::Scope::PassThrough { source: self.source }, + &mut self.checking_data, + |environment, checking_data| { + if let Some(parser::StatementOrDeclaration::Statement( + parser::Statement::Expression(expression), + )) = item.items.last() + { + synthesise_block( + &item.items[..(item.items.len() - 1)], + environment, + checking_data, + ); + let result = synthesise_multiple_expression( + expression, + environment, + checking_data, + TypeId::ANY_TYPE, + ); + Some(print_type(result, &checking_data.types, environment, false)) + } else { + synthesise_block(&item.items, environment, checking_data); + None + } + }, + ); + let dc = mem::take(&mut self.checking_data.diagnostics_container); + if dc.contains_error() { + Err(dc) + } else { + Ok((ty, dc)) + } + } + + #[must_use] + pub fn get_source_id(&self) -> SourceId { + self.source + } + + #[must_use] + pub fn get_fs_ref(&self) -> &MapFileStore { + &self.checking_data.modules.files + } + + pub fn get_fs_mut(&mut self) -> &mut MapFileStore { + &mut self.checking_data.modules.files + } +} diff --git a/checker/src/synthesis/interfaces.rs b/checker/src/synthesis/interfaces.rs index 12863cd4..fed3dc65 100644 --- a/checker/src/synthesis/interfaces.rs +++ b/checker/src/synthesis/interfaces.rs @@ -58,7 +58,7 @@ pub(crate) enum InterfaceKey<'a> { } pub(crate) enum InterfaceValue { - Function(FunctionType, Option), + Function(Box, Option), Value(TypeId), } @@ -90,16 +90,16 @@ fn register( let value = match value { InterfaceValue::Function(function, getter_setter) => match getter_setter { Some(GetterSetter::Getter) => PropertyValue::Getter(Callable::new_from_function( - function, + *function, &mut checking_data.types, )), Some(GetterSetter::Setter) => PropertyValue::Setter(Callable::new_from_function( - function, + *function, &mut checking_data.types, )), None => { let function_id = function.id; - checking_data.types.functions.insert(function.id, function); + checking_data.types.functions.insert(function.id, *function); let ty = Type::FunctionReference(function_id); PropertyValue::Value(checking_data.types.register_type(ty)) } @@ -232,7 +232,7 @@ pub(super) fn synthesise_signatures { - checking_data: CheckingData<'a, T, super::EznoParser>, - root: RootContext, - source: SourceId, - } - - impl<'a, T: crate::ReadFromFS> State<'a, T> { - pub fn new( - resolver: &'a T, - type_definition_files: Vec, - ) -> Result)> { - let mut root = RootContext::new_with_primitive_references(); - let mut checking_data = - CheckingData::new(Default::default(), resolver, Default::default(), ()); - - add_definition_files_to_root(type_definition_files, &mut root, &mut checking_data); - - if checking_data.diagnostics_container.has_error() { - Err((checking_data.diagnostics_container, checking_data.modules.files)) - } else { - let source = - checking_data.modules.files.new_source_id("CLI.tsx".into(), String::default()); - Ok(Self { checking_data, root, source }) - } - } - - pub fn check_item( - &mut self, - item: &parser::Module, - ) -> Result<(Option, DiagnosticsContainer), DiagnosticsContainer> { - let (ty, ..) = self.root.new_lexical_environment_fold_into_parent( - crate::Scope::PassThrough { source: self.source }, - &mut self.checking_data, - |environment, checking_data| { - if let Some(parser::StatementOrDeclaration::Statement( - parser::Statement::Expression(expression), - )) = item.items.last() - { - synthesise_block( - &item.items[..(item.items.len() - 1)], - environment, - checking_data, - ); - let result = synthesise_multiple_expression( - expression, - environment, - checking_data, - TypeId::ANY_TYPE, - ); - Some(print_type(result, &checking_data.types, environment, false)) - } else { - synthesise_block(&item.items, environment, checking_data); - None - } - }, - ); - let dc = mem::take(&mut self.checking_data.diagnostics_container); - if dc.has_error() { - Err(dc) - } else { - Ok((ty, dc)) - } - } - - #[must_use] - pub fn get_source_id(&self) -> SourceId { - self.source - } - - #[must_use] - pub fn get_fs_ref(&self) -> &MapFileStore { - &self.checking_data.modules.files - } - - pub fn get_fs_mut(&mut self) -> &mut MapFileStore { - &mut self.checking_data.modules.files - } - } -} diff --git a/checker/tests/partial_source.rs b/checker/tests/partial_source.rs index 867b2f96..3b74f56b 100644 --- a/checker/tests/partial_source.rs +++ b/checker/tests/partial_source.rs @@ -21,7 +21,7 @@ fn partial_checking() { let result = check_project::<_, synthesis::EznoParser>( vec![root.into()], type_definition_files, - |_path: &std::path::Path| Some(text.to_owned()), + &|_path: &std::path::Path| Some(text.to_owned()), options, (), None, diff --git a/checker/tests/suggestions.rs b/checker/tests/suggestions.rs index 4a9f3e41..301b4a52 100644 --- a/checker/tests/suggestions.rs +++ b/checker/tests/suggestions.rs @@ -41,7 +41,7 @@ console.log(obj2.proberly); let result = check_project::<_, ezno_checker::synthesis::EznoParser>( vec![root.into()], type_definition_files, - resolver, + &resolver, options, (), None, diff --git a/checker/tests/type_mappings.rs b/checker/tests/type_mappings.rs index e6eef489..bccb65c3 100644 --- a/checker/tests/type_mappings.rs +++ b/checker/tests/type_mappings.rs @@ -17,7 +17,7 @@ y()"; let result = check_project::<_, synthesis::EznoParser>( vec![root.into()], type_definition_files, - |_path: &std::path::Path| Some(text.to_owned()), + &|_path: &std::path::Path| Some(text.to_owned()), options, (), None, diff --git a/parser/examples/duplicate_block.rs b/parser/examples/duplicate_block.rs new file mode 100644 index 00000000..21183a2f --- /dev/null +++ b/parser/examples/duplicate_block.rs @@ -0,0 +1,135 @@ +use ezno_parser::{ + declarations::VariableDeclaration, + visiting::{Chain, ImmutableVariableOrProperty, VisitOptions, Visitor, Visitors}, + ASTNode, Declaration, Expression, Module, StatementOrDeclaration, VariableField, +}; +use std::collections::{HashMap, HashSet}; + +struct Offsets { + pub offsets: Vec, + /// TODO use &str references + pub top_level_variables: HashSet, + pub top_level_types: HashSet, +} + +/// TODO this could use visting right? +/// TODO abstract to library +/// TODO do for funtions and types +fn get_top_level_identifiers(m: &Module) -> (HashSet, HashSet) { + let (mut variables, mut types): (HashSet<_>, HashSet<_>) = Default::default(); + for item in &m.items { + match item { + StatementOrDeclaration::Declaration(Declaration::Variable(variable)) => { + match variable { + VariableDeclaration::ConstDeclaration { declarations, position: _ } => { + for declaration in declarations { + if let VariableField::Name(identifier) = declaration.name.get_ast_ref() + { + variables.insert(identifier.as_option_str().unwrap().to_owned()); + } + } + } + VariableDeclaration::LetDeclaration { declarations, position: _ } => { + for declaration in declarations { + if let VariableField::Name(identifier) = declaration.name.get_ast_ref() + { + variables.insert(identifier.as_option_str().unwrap().to_owned()); + } + } + } + } + } + StatementOrDeclaration::Declaration(Declaration::Function(function)) => { + variables.insert(function.on.name.identifier.as_option_str().unwrap().to_owned()); + } + _ => {} + } + } + (variables, types) +} + +fn main() { + let code = " +let x = 2; +let y = x + 2; +let z = 6; +" + .trim(); + + // function func() {{ return [x, z] }} + let module = Module::from_string(code.into(), Default::default()).unwrap(); + + let (top_level_variables, top_level_types) = get_top_level_identifiers(&module); + + let mut visitors = Visitors { + expression_visitors: vec![Box::new(NameReferenceFinder)], + statement_visitors: Default::default(), + variable_visitors: vec![Box::new(NameIndexFinder)], + block_visitors: Default::default(), + }; + + // eprintln!("variables={:#?}", (&top_level_variables, &top_level_types)); + + let mut offsets: Offsets = + Offsets { offsets: Default::default(), top_level_variables, top_level_types }; + + module.visit::( + &mut visitors, + &mut offsets, + &VisitOptions { visit_nested_blocks: true, reverse_statements: false }, + source_map::Nullable::NULL, + ); + + // TODO why is this backwards + // eprintln!("offsets={:#?}", offsets); + + offsets.offsets.sort_unstable(); + let mut rest = code.to_owned(); + for (idx, offset) in offsets.offsets.iter_mut().enumerate().rev() { + let current_offset = *offset as usize; + rest.insert_str(current_offset, "000"); + // need to ammed offset now string has been changed + *offset += ("000".len() * idx) as u32; + } + rest.push('\n'); + + let mut total = rest.clone(); + const SIZE: usize = 10; + total.reserve(rest.len() * (SIZE - 1)); + + for i in 1..SIZE { + let name = format!("{:03}", i); + for offset in offsets.offsets.iter().copied() { + let range = offset as usize..(offset as usize + 3); + rest.replace_range(range, &name); + } + + total.push_str(&rest); + } + + eprintln!("{}", total); +} + +/// TODO this could be collected in the same process as above +struct NameIndexFinder; + +impl<'a> Visitor, Offsets> for NameIndexFinder { + fn visit(&mut self, item: &ImmutableVariableOrProperty<'a>, data: &mut Offsets, chain: &Chain) { + if chain.len() == 1 && item.get_variable_name().is_some() { + data.offsets.push(item.get_position().end); + // data.insert(name.to_owned()); + } + } +} + +struct NameReferenceFinder; + +impl Visitor for NameReferenceFinder { + fn visit(&mut self, item: &Expression, data: &mut Offsets, _chain: &Chain) { + if let Expression::VariableReference(name, position) = item { + if data.top_level_variables.contains(name) { + data.offsets.push(position.end); + } + } + } +} diff --git a/parser/examples/parse.rs b/parser/examples/parse.rs index cd189381..ccd5b852 100644 --- a/parser/examples/parse.rs +++ b/parser/examples/parse.rs @@ -1,8 +1,10 @@ -use std::{collections::VecDeque, time::Instant}; +use std::{collections::VecDeque, path::Path, time::Instant}; use ezno_parser::{ASTNode, Comments, Module, ParseOptions, ToStringOptions}; use source_map::FileSystem; +type Files = source_map::MapFileStore; + fn main() -> Result<(), Box> { let mut args: VecDeque<_> = std::env::args().skip(1).collect(); let path = args.pop_front().ok_or("expected argument")?; @@ -18,20 +20,18 @@ fn main() -> Result<(), Box> { let display_keywords = args.iter().any(|item| item == "--keywords"); let extras = args.iter().any(|item| item == "--extras"); let partial_syntax = args.iter().any(|item| item == "--partial"); - let source_maps = args.iter().any(|item| item == "--source-map"); + let print_source_maps = args.iter().any(|item| item == "--source-map"); let timings = args.iter().any(|item| item == "--timings"); - let render_timings = args.iter().any(|item| item == "--render-timings"); let type_definition_module = args.iter().any(|item| item == "--type-definition-module"); let type_annotations = !args.iter().any(|item| item == "--no-type-annotations"); let top_level_html = args.iter().any(|item| item == "--top-level-html"); + let parse_imports = args.iter().any(|item| item == "--parse-imports"); let print_ast = args.iter().any(|item| item == "--ast"); - let render_output = args.iter().any(|item| item == "--render"); + let to_string_output = args.iter().any(|item| item == "--to-string"); let pretty = args.iter().any(|item| item == "--pretty"); - let now = Instant::now(); - // TODO temp const STACK_SIZE_MB: usize = 32; let parse_options = ParseOptions { @@ -52,14 +52,48 @@ fn main() -> Result<(), Box> { ..ParseOptions::default() }; - let mut fs = source_map::MapFileStore::::default(); - - let source = std::fs::read_to_string(path.clone())?; + let mut fs = Files::default(); + + let to_string_options = to_string_output.then(|| ToStringOptions { + expect_markers: true, + include_type_annotations: type_annotations, + pretty, + comments: if pretty { Comments::All } else { Comments::None }, + // 60 is temp + max_line_length: if pretty { 60 } else { u8::MAX }, + ..Default::default() + }); + + parse_path( + path.as_ref(), + timings, + parse_imports, + &parse_options, + print_ast, + print_source_maps, + &to_string_options, + display_keywords, + &mut fs, + ) +} +fn parse_path( + path: &Path, + timings: bool, + parse_imports: bool, + parse_options: &ParseOptions, + print_ast: bool, + print_source_maps: bool, + to_string_options: &Option, + display_keywords: bool, + fs: &mut Files, +) -> Result<(), Box> { + let source = std::fs::read_to_string(path)?; let source_id = fs.new_source_id(path.into(), source.clone()); - eprintln!("parsing {:?} bytes", source.len()); - let result = Module::from_string_with_options(source.clone(), parse_options, None); + eprintln!("parsing {:?} ({:?} bytes)", path.display(), source.len()); + let now = Instant::now(); + let result = Module::from_string_with_options(source.clone(), parse_options.clone(), None); match result { Ok((module, state)) => { @@ -70,45 +104,55 @@ fn main() -> Result<(), Box> { if print_ast { println!("{module:#?}"); } - if source_maps || render_output || render_timings { - let now = Instant::now(); - let to_string_options = ToStringOptions { - expect_markers: true, - include_type_annotations: type_annotations, - pretty, - comments: if pretty { Comments::All } else { Comments::None }, - // 60 is temp - max_line_length: if pretty { 60 } else { u8::MAX }, - ..Default::default() - }; + if let Some(to_string_options) = to_string_options { + let now = Instant::now(); let (output, source_map) = - module.to_string_with_source_map(&to_string_options, source_id, &fs); + module.to_string_with_source_map(to_string_options, source_id, fs); - if timings || render_timings { + if timings { eprintln!("ToString'ed in: {:?}", now.elapsed()); } - if source_maps { - let sm = source_map.unwrap().to_json(&fs); - println!("{output}\n{sm}"); - } - if render_output { - println!("{output}"); + + println!("{output}"); + if print_source_maps { + let sm = source_map.unwrap().to_json(fs); + println!("{sm}"); } } if display_keywords { - println!("{:?}", state.keyword_positions.unwrap()); + println!("{:?}", state.keyword_positions.as_ref()); } + if parse_imports { + for import in state.constant_imports.iter() { + // Don't reparse files (+ catches cycles) + let resolved_path = path.parent().unwrap().join(import); + if fs.get_paths().contains_key(&resolved_path) { + continue; + } + let _ = parse_path( + &resolved_path, + timings, + parse_imports, + parse_options, + print_ast, + print_source_maps, + to_string_options, + display_keywords, + fs, + )?; + } + } Ok(()) } Err(parse_err) => { let mut line_column = parse_err .position .with_source(source_id) - .into_line_column_span::(&fs); + .into_line_column_span::(fs); { // Editor are one indexed line_column.line_start += 1; diff --git a/parser/examples/simple.rs b/parser/examples/simple.rs new file mode 100644 index 00000000..46475a22 --- /dev/null +++ b/parser/examples/simple.rs @@ -0,0 +1,9 @@ +#[allow(unused)] +use ezno_parser::{ASTNode, Expression, Module}; + +fn main() { + let source = "'Hello World!'".to_owned(); + let parse_options = Default::default(); + let result = Expression::from_string_with_options(source.clone(), parse_options, Some(40)); + eprintln!("{result:#?}"); +} diff --git a/parser/src/block.rs b/parser/src/block.rs index 3070dde8..e37b0f20 100644 --- a/parser/src/block.rs +++ b/parser/src/block.rs @@ -43,7 +43,8 @@ impl StatementOrDeclaration { on: ExportDeclaration::Default { .. } | ExportDeclaration::Item { exported: Exportable::ImportAll { .. } - | Exportable::ImportParts { .. } | Exportable::Parts { .. }, + | Exportable::ImportParts { .. } + | Exportable::Parts { .. }, .. }, .. @@ -392,10 +393,11 @@ pub(crate) fn parse_statements_and_declarations( expect_semi_colon(reader, &state.line_starts, end, options)? } else if options.retain_blank_lines { let Token(kind, next) = reader.peek().ok_or_else(crate::parse_lexing_error)?; - let lines = state.line_starts.byte_indexes_crosses_lines(end as usize, next.0 as usize); if let TSXToken::EOS = kind { - lines + 1 } else { + let lines = + state.line_starts.byte_indexes_crosses_lines(end as usize, next.0 as usize); lines.saturating_sub(1) } } else { diff --git a/parser/src/declarations/mod.rs b/parser/src/declarations/mod.rs index 53d3344a..080f7dc6 100644 --- a/parser/src/declarations/mod.rs +++ b/parser/src/declarations/mod.rs @@ -78,8 +78,10 @@ impl Declaration { token, TSXToken::Keyword( TSXKeyword::Let - | TSXKeyword::Const | TSXKeyword::Function - | TSXKeyword::Class | TSXKeyword::Export + | TSXKeyword::Const + | TSXKeyword::Function + | TSXKeyword::Class + | TSXKeyword::Export ) | TSXToken::At, ); @@ -123,7 +125,8 @@ impl Declaration { reader.peek_n(1), Some(Token( TSXToken::OpenBrace - | TSXToken::Keyword(..) | TSXToken::Identifier(..) + | TSXToken::Keyword(..) + | TSXToken::Identifier(..) | TSXToken::StringLiteral(..) | TSXToken::Multiply, _ diff --git a/parser/src/extensions/jsx.rs b/parser/src/extensions/jsx.rs index 88f58aac..ebec2d33 100644 --- a/parser/src/extensions/jsx.rs +++ b/parser/src/extensions/jsx.rs @@ -485,7 +485,7 @@ pub fn html_tag_is_self_closing(tag_name: &str) -> bool { | "hr" | "img" | "input" | "link" | "meta" | "param" - | "source" | "track" - | "wbr" + | "source" + | "track" | "wbr" ) } diff --git a/parser/src/functions/mod.rs b/parser/src/functions/mod.rs index 7d86a4bb..84bb66a1 100644 --- a/parser/src/functions/mod.rs +++ b/parser/src/functions/mod.rs @@ -644,22 +644,23 @@ pub(crate) fn get_method_name( state: &mut crate::ParsingState, options: &ParseOptions, ) -> Result<(MethodHeader, WithComment>), crate::ParseError> { - let is_named_get_set_or_async = - matches!( - reader.peek(), - Some(Token(TSXToken::Keyword(kw), _)) - if kw.is_in_method_header() - ) && matches!( - reader.peek_n(1), - Some(Token( - TSXToken::OpenParentheses - | TSXToken::Colon | TSXToken::OpenChevron - | TSXToken::CloseBrace - | TSXToken::Comma | TSXToken::QuestionMark - | TSXToken::OptionalMember, - _ - )) - ); + let is_named_get_set_or_async = matches!( + reader.peek(), + Some(Token(TSXToken::Keyword(kw), _)) + if kw.is_in_method_header() + ) && matches!( + reader.peek_n(1), + Some(Token( + TSXToken::OpenParentheses + | TSXToken::Colon + | TSXToken::OpenChevron + | TSXToken::CloseBrace + | TSXToken::Comma + | TSXToken::QuestionMark + | TSXToken::OptionalMember, + _ + )) + ); let (function_header, key) = if is_named_get_set_or_async { let token = reader.next().unwrap(); diff --git a/parser/src/lexer.rs b/parser/src/lexer.rs index 49c202ed..e6d68467 100644 --- a/parser/src/lexer.rs +++ b/parser/src/lexer.rs @@ -47,14 +47,18 @@ fn is_number_delimiter(chr: char) -> bool { chr, ' ' | ',' | '\n' | '\r' - | ';' | '+' | '-' - | '*' | '/' | '&' - | '|' | '!' | '^' - | '(' | '{' | '[' - | ')' | '}' | ']' - | '%' | '=' | ':' - | '<' | '>' | '?' - | '"' | '\'' | '`' + | ';' | '+' + | '-' | '*' + | '/' | '&' + | '|' | '!' + | '^' | '(' + | '{' | '[' + | ')' | '}' + | ']' | '%' + | '=' | ':' + | '<' | '>' + | '?' | '"' + | '\'' | '`' | '#' ) } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 7944ac01..93633225 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -266,10 +266,10 @@ pub(crate) fn throw_unexpected_token_with_token( #[derive(Debug)] pub struct ParsingState { - pub(crate) line_starts: source_map::LineStarts, - pub(crate) length_of_source: u32, + pub line_starts: source_map::LineStarts, + pub length_of_source: u32, /// TODO as multithreaded channel + record is dynamic exists - pub(crate) constant_imports: Vec, + pub constant_imports: Vec, pub keyword_positions: Option, pub partial_points: Vec, } diff --git a/parser/src/modules.rs b/parser/src/modules.rs index f284b658..777e575f 100644 --- a/parser/src/modules.rs +++ b/parser/src/modules.rs @@ -44,7 +44,8 @@ impl ASTNode for Module { state: &mut crate::ParsingState, options: &ParseOptions, ) -> ParseResult { - let span = Span { start: 0, source: (), end: state.length_of_source }; + let start = reader.peek().map(|t| t.1 .0).unwrap_or_default(); + let span = Span { start, source: (), end: start + state.length_of_source }; let hashbang_comment = if let Some(crate::Token(TSXToken::HashBangComment(_), _)) = reader.peek() { diff --git a/parser/src/tokens.rs b/parser/src/tokens.rs index 9c61e8b9..1cedf7ed 100644 --- a/parser/src/tokens.rs +++ b/parser/src/tokens.rs @@ -456,7 +456,8 @@ impl TSXToken { | TSXToken::LogicalAnd | TSXToken::LogicalOr | TSXToken::Multiply - | TSXToken::Add | TSXToken::Subtract + | TSXToken::Add + | TSXToken::Subtract | TSXToken::Divide ) || self.is_assignment() } @@ -479,10 +480,14 @@ impl TSXToken { self, TSXToken::Keyword( TSXKeyword::Function - | TSXKeyword::If | TSXKeyword::For - | TSXKeyword::While | TSXKeyword::Const - | TSXKeyword::Let | TSXKeyword::Break - | TSXKeyword::Import | TSXKeyword::Export + | TSXKeyword::If + | TSXKeyword::For + | TSXKeyword::While + | TSXKeyword::Const + | TSXKeyword::Let + | TSXKeyword::Break + | TSXKeyword::Import + | TSXKeyword::Export ) ) } diff --git a/parser/src/types/type_annotations.rs b/parser/src/types/type_annotations.rs index 271e2b52..68009ab0 100644 --- a/parser/src/types/type_annotations.rs +++ b/parser/src/types/type_annotations.rs @@ -479,7 +479,8 @@ impl TypeAnnotation { TSXToken::CloseParentheses | TSXToken::CloseBracket | TSXToken::CloseBrace - | TSXToken::Comma | TSXToken::OpenChevron + | TSXToken::Comma + | TSXToken::OpenChevron ) || peek.is_assignment() || (start.map_or(false, |start| { peek.is_statement_or_declaration_start() diff --git a/src/ast_explorer.rs b/src/ast_explorer.rs index 7879d421..d8fd7b8a 100644 --- a/src/ast_explorer.rs +++ b/src/ast_explorer.rs @@ -1,16 +1,12 @@ #![allow(dead_code)] -use std::{fs, path::PathBuf}; +use std::path::PathBuf; use argh::FromArgs; -use console::style; use enum_variants_strings::EnumVariantsStrings; use parser::{source_map::FileSystem, ASTNode, Expression, Module, ToStringOptions}; -use crate::{ - reporting::report_diagnostics_to_cli, - utilities::{print_to_cli, print_to_cli_without_newline}, -}; +use crate::{reporting::report_diagnostics_to_cli, utilities::print_to_cli}; /// REPL for printing out AST from user input #[derive(FromArgs, Debug)] @@ -24,23 +20,25 @@ pub(crate) struct ExplorerArguments { } impl ExplorerArguments { + #[cfg(target_family = "wasm")] + pub(crate) fn run(&mut self, _fs_resolver: &T) { + panic!("Cannot run ast-explorer in WASM because of input callback. Consider reimplementing using library"); + } + #[allow(clippy::needless_continue)] - pub(crate) fn run( - &mut self, - fs_resolver: &T, - cli_input_resolver: U, - ) { + #[cfg(not(target_family = "wasm"))] + pub(crate) fn run(&mut self, fs_resolver: &T) { if let Some(ref file) = self.file { - let content = fs_resolver.get_content_at_path(file); + let content = fs_resolver.read_file(file); if let Some(content) = content { - self.nested.run(content, Some(file.to_owned())); + self.nested.run(String::from_utf8(content).unwrap(), Some(file.to_owned())); } else { eprintln!("Could not find file at {}", file.display()); } } else { print_to_cli(format_args!("ezno ast-explorer\nUse #exit to leave. Also #switch-mode *mode name* and #load-file *path*")); loop { - let input = cli_input_resolver(self.nested.to_str()).unwrap_or_default(); + let input = crate::utilities::cli_input_resolver(self.nested.to_str()); if input.is_empty() { continue; @@ -55,7 +53,7 @@ impl ExplorerArguments { } }; } else if let Some(path) = input.strip_prefix("#load-file ") { - let input = match fs::read_to_string(path.trim()) { + let input = match std::fs::read_to_string(path.trim()) { Ok(string) => string, Err(err) => { print_to_cli(format_args!("{err:?}")); @@ -80,7 +78,6 @@ pub(crate) enum ExplorerSubCommand { FullAST(FullASTArgs), Prettifier(PrettyArgs), Uglifier(UglifierArgs), - Lexer(LexerArgs), } /// Prints AST for a given expression @@ -99,6 +96,9 @@ pub(crate) struct FullASTArgs { /// print results as json #[argh(switch)] json: bool, + /// just print whether parse was successful + #[argh(switch)] + check: bool, } /// Prettifies source code (full whitespace) @@ -111,11 +111,6 @@ pub(crate) struct PrettyArgs {} #[argh(subcommand, name = "uglifier")] pub(crate) struct UglifierArgs {} -/// Prints sources with tokens over -#[derive(FromArgs, Debug, Default)] -#[argh(subcommand, name = "lexer")] -pub(crate) struct LexerArgs {} - impl ExplorerSubCommand { pub fn run(&self, input: String, path: Option) { match self { @@ -148,11 +143,20 @@ impl ExplorerSubCommand { ExplorerSubCommand::FullAST(cfg) => { let mut fs = parser::source_map::MapFileStore::::default(); - let source_id = fs.new_source_id(path.unwrap_or_default(), input.clone()); + let source_id = fs.new_source_id(path.clone().unwrap_or_default(), input.clone()); let res = Module::from_string(input, parser::ParseOptions::all_features()); match res { Ok(res) => { - if cfg.json { + if cfg.check { + if let Some(ref path) = path { + print_to_cli(format_args!( + "{path} parsed successfully", + path = path.display() + )); + } else { + print_to_cli(format_args!("Parsed successfully",)); + } + } else if cfg.json { print_to_cli(format_args!( "{}", serde_json::to_string_pretty(&res).unwrap() @@ -194,28 +198,6 @@ impl ExplorerSubCommand { .unwrap(), } } - ExplorerSubCommand::Lexer(_) => { - let mut color = console::Color::Red; - for (section, with) in parser::script_to_tokens(input) { - if with { - let value = style(section).bg(color); - // Cycle through colors - color = match color { - console::Color::Red => console::Color::Green, - console::Color::Green => console::Color::Yellow, - console::Color::Yellow => console::Color::Blue, - console::Color::Blue => console::Color::Magenta, - console::Color::Magenta => console::Color::Cyan, - console::Color::Cyan => console::Color::Red, - _ => unreachable!(), - }; - print_to_cli_without_newline(format_args!("{value}")); - } else { - print_to_cli_without_newline(format_args!("{section}")); - } - } - print_to_cli(format_args!("")); - } } } } diff --git a/src/build.rs b/src/build.rs index 0bc7f94f..e2b4fcb0 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,11 +1,8 @@ -use std::{ - mem, - path::{Path, PathBuf}, -}; +use std::{collections::HashMap, mem, path::PathBuf}; -use checker::{DiagnosticsContainer, TypeCheckOptions}; +use checker::TypeCheckOptions; use parser::{ - source_map::{MapFileStore, SourceMap, WithPathMap}, + source_map::{SourceId, SourceMap, WithPathMap}, ToStringOptions, }; @@ -17,45 +14,53 @@ pub struct Output { pub mappings: SourceMap, } -#[cfg_attr(target_family = "wasm", derive(serde::Serialize, tsify::Tsify))] pub struct BuildOutput { - pub outputs: Vec, - pub diagnostics: DiagnosticsContainer, - /// For diagnostics - /// TODO serde - #[cfg_attr(target_family = "wasm", serde(skip))] - pub fs: MapFileStore, + pub artifacts: Vec, + pub check_output: checker::CheckOutput, } -#[cfg_attr(target_family = "wasm", derive(serde::Serialize, tsify::Tsify))] -pub struct FailedBuildOutput { - pub diagnostics: DiagnosticsContainer, - /// For diagnostics - /// TODO serde - #[cfg_attr(target_family = "wasm", serde(skip))] - pub fs: MapFileStore, -} +pub struct FailedBuildOutput(pub checker::CheckOutput); -#[cfg_attr(target_family = "wasm", derive(serde::Deserialize))] +#[cfg_attr(target_family = "wasm", derive(serde::Deserialize, tsify::Tsify), serde(default))] pub struct BuildConfig { - #[cfg_attr(target_family = "wasm", serde(default))] + pub tree_shake: bool, pub strip_whitespace: bool, - #[cfg_attr(target_family = "wasm", serde(default))] pub source_maps: bool, + /// Run checker with partial syntax support + pub lsp_mode: bool, + pub output_path: PathBuf, + pub type_definition_module: Option, + #[cfg_attr(target_family = "wasm", serde(skip))] + pub other_transformers: Option, +} + +impl Default for BuildConfig { + fn default() -> BuildConfig { + BuildConfig { + tree_shake: false, + strip_whitespace: true, + source_maps: false, + lsp_mode: false, + type_definition_module: None, + // TODO not sure + output_path: PathBuf::from("out.js"), + other_transformers: None, + } + } } pub type EznoParsePostCheckVisitors = parser::visiting::VisitorsMut; +pub type OwnedEznoModule = + ::OwnedModule; +pub type SynthesisedEznoModule = checker::features::modules::SynthesisedModule; + +/// Subset of check output which is nicer for transformers to inferface on pub struct CheckingOutputWithoutDiagnostics { pub types: checker::types::TypeStore, - pub module_contents: parser::source_map::MapFileStore, - pub modules: std::collections::HashMap< - parser::SourceId, - checker::features::modules::SynthesisedModule< - ::OwnedModule, - >, - >, + pub module_contents: parser::source_map::MapFileStore, + pub modules: HashMap, } impl CheckingOutputWithoutDiagnostics { @@ -68,24 +73,33 @@ impl CheckingOutputWithoutDiagnostics { pub fn build( entry_points: Vec, fs_resolver: &T, - type_definition_module: Option<&Path>, - output_path: &Path, - config: &BuildConfig, - transformers: Option, + config: BuildConfig, ) -> Result { // TODO parse options + non_standard_library & non_standard_syntax - let type_check_options = TypeCheckOptions { store_type_mappings: true, ..Default::default() }; - - let result = - crate::check(entry_points, fs_resolver, type_definition_module, type_check_options); - - let mut data = CheckingOutputWithoutDiagnostics { - module_contents: result.module_contents, - modules: result.modules, - types: result.types, + let type_check_options = TypeCheckOptions { + store_type_mappings: true, + lsp_mode: config.lsp_mode, + ..Default::default() }; - if !result.diagnostics.has_error() { + let result = crate::check( + entry_points, + fs_resolver, + config.type_definition_module.as_deref(), + type_check_options, + ); + + if !result.diagnostics.contains_error() { + let checker::CheckOutput { + diagnostics, + module_contents, + chronometer, + types, + modules, + top_level_information, + } = result; + let mut data = CheckingOutputWithoutDiagnostics { module_contents, modules, types }; + // TODO For all modules let keys = data.modules.keys().cloned().collect::>(); @@ -95,9 +109,18 @@ pub fn build( span: parser::source_map::Nullable::NULL, }; - let mut outputs = Vec::new(); + let mut artifacts = Vec::new(); + let mut transformers = config.other_transformers.unwrap_or_default(); + + if config.tree_shake { + transformers + .expression_visitors_mut + .push(Box::new(crate::transformers::optimisations::ExpressionOptimiser)); - let mut transformers = transformers.unwrap_or_default(); + transformers + .statement_visitors_mut + .push(Box::new(crate::transformers::optimisations::StatementOptimiser)); + } for source in keys { // Remove the module @@ -115,26 +138,88 @@ pub fn build( source, ); - let to_string_options = if config.strip_whitespace { + let mut to_string_options = if config.strip_whitespace { ToStringOptions::minified() } else { ToStringOptions::default() }; - // TODO under cfg + // TODO temp fix + if config.lsp_mode { + to_string_options.expect_markers = true; + } + + // TODO source map creation not neccessary let (content, mappings) = module.to_string_with_source_map(&to_string_options, source, &data.module_contents); - outputs.push(Output { - output_path: output_path.to_path_buf(), + artifacts.push(Output { + output_path: config.output_path.to_path_buf(), content, mappings: mappings.unwrap(), - }) + }); } - Ok(BuildOutput { outputs, diagnostics: result.diagnostics, fs: data.module_contents }) + // Reconstruct + let check_output = checker::CheckOutput { + module_contents: data.module_contents, + modules: data.modules, + types: data.types, + diagnostics, + chronometer, + top_level_information, + }; + + Ok(BuildOutput { artifacts, check_output }) } else { - Err(FailedBuildOutput { diagnostics: result.diagnostics, fs: data.module_contents }) + Err(FailedBuildOutput(result)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[ignore = "not fixed implemented"] + fn tree_shaking() { + let source = r#" + function make_observable(obj) { + return new Proxy(obj, { + get(on, prop: string, _rec) { + return on[prop] + }, + }) + } + function get_a() { + return 1 + } + function get_b() { + return 1 + } + const obj = { + a() { return get_a() }, + b() { return get_b() }, + c: 2 + } + const value = make_observable(obj); + const a_value = value.a(); + const c_value = value.c; + "#; + + let config = BuildConfig { tree_shake: true, ..Default::default() }; + + if let Ok(output) = build( + vec!["index.tsx".into()], + &|_path: &std::path::Path| Some(source.to_owned()), + config, + ) { + let first_source = &output.artifacts[0].content; + // TODO assert output equal + panic!("{first_source:?}"); + } else { + panic!("build failed") + } } } diff --git a/src/check.rs b/src/check.rs index 436e6c28..b242f8b2 100644 --- a/src/check.rs +++ b/src/check.rs @@ -13,8 +13,12 @@ pub fn check( vec![checker::INTERNAL_DEFINITION_FILE_PATH.into()] }; - let read_from_fs = - |path: &Path| read_from_filesystem.get_content_at_path(path).map(String::into_bytes); - - checker::check_project(entry_points, definitions, read_from_fs, type_check_options, (), None) + checker::check_project( + entry_points, + definitions, + read_from_filesystem, + type_check_options, + (), + None, + ) } diff --git a/src/cli.rs b/src/cli.rs index a86bc4db..a62dab08 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -9,10 +9,10 @@ use std::{ }; use crate::{ - build::{build, BuildConfig, BuildOutput, EznoParsePostCheckVisitors, FailedBuildOutput}, + build::{build, BuildConfig, BuildOutput, FailedBuildOutput}, check::check, reporting::report_diagnostics_to_cli, - utilities::{self, print_to_cli, MaxDiagnostics}, + utilities::{print_to_cli, MaxDiagnostics}, }; use argh::FromArgs; use checker::{CheckOutput, TypeCheckOptions}; @@ -88,7 +88,7 @@ pub(crate) struct BuildArguments { pub compact_diagnostics: bool, /// enable optimising transforms (warning can currently break code) #[argh(switch)] - pub optimise: bool, + pub tree_shake: bool, /// maximum diagnostics to print (defaults to 30, pass `all` for all and `0` to count) #[argh(option, default = "MaxDiagnostics::default()")] pub max_diagnostics: MaxDiagnostics, @@ -182,13 +182,14 @@ fn run_checker( type_check_options: TypeCheckOptions, compact_diagnostics: bool, ) -> ExitCode { - let CheckOutput { diagnostics, module_contents, chronometer, types, .. } = - check(entry_points, read_file, definition_file.as_deref(), type_check_options); + let result = check(entry_points, read_file, definition_file.as_deref(), type_check_options); + + let CheckOutput { diagnostics, module_contents, chronometer, types, .. } = result; let diagnostics_count = diagnostics.count(); let current = timings.then(std::time::Instant::now); - let result = if diagnostics.has_error() { + let result = if diagnostics.contains_error() { if let MaxDiagnostics::FixedTo(0) = max_diagnostics { let count = diagnostics.into_iter().count(); print_to_cli(format_args!( @@ -235,11 +236,10 @@ fn run_checker( result } -pub fn run_cli( +pub fn run_cli( cli_arguments: &[&str], - read_file: &T, + read_file: T, write_file: U, - cli_input_resolver: V, ) -> ExitCode { let command = match FromArgs::from_args(&["ezno-cli"], cli_arguments) { Ok(TopLevel { nested }) => nested, @@ -264,18 +264,21 @@ pub fn run_cli entry_points, - Err(_) => return ExitCode::FAILURE, + Err(_) => { + print_to_cli(format_args!("Entry point error")); + return ExitCode::FAILURE; + } }; + // run_checker is written three times because cloning if watch { #[cfg(target_family = "wasm")] panic!("'watch' mode not supported on WASM"); @@ -293,13 +296,12 @@ pub fn run_cli { - run_checker( + let _out = run_checker( entry_points.clone(), - read_file, + &read_file, timings, definition_file.clone(), - max_diagnostics.clone(), + max_diagnostics, type_check_options.clone(), compact_diagnostics, ); @@ -320,57 +322,49 @@ pub fn run_cli eprintln!("Error: {error:?}"), } } - // Infinite loop here so the compiler is satisfied that this never returns - loop {} + + unreachable!() } + } else { + run_checker( + entry_points, + &read_file, + timings, + definition_file, + max_diagnostics, + type_check_options, + compact_diagnostics, + ) } - - run_checker( - entry_points, - read_file, - timings, - definition_file, - max_diagnostics, - type_check_options, - compact_diagnostics, - ) } CompilerSubCommand::Experimental(ExperimentalArguments { nested: ExperimentalSubcommand::Build(build_config), }) => { - let output_path = build_config.output.unwrap_or("ezno_output.js".into()); - - let mut default_builders = EznoParsePostCheckVisitors::default(); - - if build_config.optimise { - default_builders - .expression_visitors_mut - .push(Box::new(crate::transformers::optimisations::ExpressionOptimiser)); - - default_builders - .statement_visitors_mut - .push(Box::new(crate::transformers::optimisations::StatementOptimiser)); - } + let output_path = build_config.output.unwrap_or("ezno.out.js".into()); let entry_points = match get_entry_points(build_config.input) { Ok(entry_points) => entry_points, - Err(_) => return ExitCode::FAILURE, + Err(_) => { + print_to_cli(format_args!("Entry point error")); + return ExitCode::FAILURE; + } }; #[cfg(not(target_family = "wasm"))] let start = build_config.timings.then(std::time::Instant::now); - let output = build( - entry_points, - read_file, - build_config.definition_file.as_deref(), - &output_path, - &BuildConfig { - strip_whitespace: build_config.minify, - source_maps: build_config.source_maps, - }, - Some(default_builders), - ); + let config = BuildConfig { + tree_shake: build_config.tree_shake, + strip_whitespace: build_config.minify, + source_maps: build_config.source_maps, + type_definition_module: build_config.definition_file, + // TODO not sure + output_path: PathBuf::from(output_path), + other_transformers: None, + lsp_mode: false, + }; + + let output = build(entry_points, &read_file, config); #[cfg(not(target_family = "wasm"))] if let Some(start) = start { @@ -380,13 +374,16 @@ pub fn run_cli { - for output in outputs { + Ok(BuildOutput { + artifacts, + check_output: CheckOutput { module_contents, diagnostics, .. }, + }) => { + for output in artifacts { write_file(output.output_path.as_path(), output.content); } report_diagnostics_to_cli( diagnostics, - &fs, + &module_contents, compact_diagnostics, build_config.max_diagnostics, ) @@ -397,10 +394,10 @@ pub fn run_cli { + Err(FailedBuildOutput(CheckOutput { module_contents, diagnostics, .. })) => { report_diagnostics_to_cli( diagnostics, - &fs, + &module_contents, compact_diagnostics, build_config.max_diagnostics, ) @@ -467,7 +464,7 @@ pub fn run_cli match utilities::upgrade_self() { + }) => match crate::utilities::upgrade_self() { Ok(name) => { print_to_cli(format_args!("Successfully updated to {name}")); std::process::ExitCode::SUCCESS @@ -478,12 +475,12 @@ pub fn run_cli { - repl.run(read_file, cli_input_resolver); + repl.run(&read_file); // TODO not always true ExitCode::SUCCESS } CompilerSubCommand::Repl(argument) => { - crate::repl::run_repl(cli_input_resolver, argument); + crate::repl::run_repl(argument); // TODO not always true ExitCode::SUCCESS } // CompilerSubCommand::Run(run_arguments) => { diff --git a/src/js-based-plugin/index.mjs b/src/js-based-plugin/index.mjs index 827e6643..414f34b7 100644 --- a/src/js-based-plugin/index.mjs +++ b/src/js-based-plugin/index.mjs @@ -74,13 +74,12 @@ function plugin(options = {}) { } const output = build(path, readFile, false); - if (output.Ok) { - emitDiagnostics(code, output.Ok.diagnostics, this) + emitDiagnostics(code, output.diagnostics, this) + if (output.artifacts.length) { return { - code: output.Ok.outputs[0].content + code: output.artifacts[0] } } else { - emitDiagnostics(code, output.Err.diagnostics, this) this.warn("ezno had errors and did not transform"); return code; } diff --git a/src/js-cli-and-library/package-lock.json b/src/js-cli-and-library/package-lock.json index 5c68a52a..87ad852d 100644 --- a/src/js-cli-and-library/package-lock.json +++ b/src/js-cli-and-library/package-lock.json @@ -8,10 +8,14 @@ "name": "ezno", "version": "0.0.22", "license": "MIT", + "dependencies": { + "snapshot-fixtures": "^1.2.0" + }, "bin": { "ezno": "dist/cli.mjs" }, "devDependencies": { + "strip-ansi": "^7.1.0", "unbuild": "^2.0.0", "wasm-pack": "^0.13.0" }, @@ -21,70 +25,57 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -99,30 +90,40 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -130,63 +131,37 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" + "bin": { + "semver": "bin/semver.js" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -195,104 +170,54 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@babel/types": "^7.26.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -301,42 +226,39 @@ } }, "node_modules/@babel/standalone": { - "version": "7.23.10", - "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.23.10.tgz", - "integrity": "sha512-xqWviI/pt1Zb/d+6ilWa5IDL2mkDzsBnlHbreqnfyP3/QB/ofQ1bNVcHj8YQX154Rf/xZKR6y0s1ydVF3nAS8g==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.26.2.tgz", + "integrity": "sha512-i2VbegsRfwa9yq3xmfDX3tG2yh9K0cCqwpSyVG2nPxifh0EOnucAZUeO/g4lW2Zfg03aPJNtPfxQbDHzXc7H+w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -345,14 +267,13 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -646,6 +567,22 @@ "node": ">=12" } }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/openbsd-x64": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", @@ -727,47 +664,47 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -810,13 +747,10 @@ } }, "node_modules/@rollup/plugin-alias": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.1.0.tgz", - "integrity": "sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.1.1.tgz", + "integrity": "sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==", "dev": true, - "dependencies": { - "slash": "^4.0.0" - }, "engines": { "node": ">=14.0.0" }, @@ -830,9 +764,9 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.7", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", - "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -875,15 +809,14 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", - "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", + "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.1", "is-module": "^1.0.0", "resolve": "^1.22.1" }, @@ -900,9 +833,9 @@ } }, "node_modules/@rollup/plugin-replace": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.5.tgz", - "integrity": "sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz", + "integrity": "sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -921,14 +854,14 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", + "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", "dev": true, "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "picomatch": "^4.0.2" }, "engines": { "node": ">=14.0.0" @@ -952,9 +885,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, "node_modules/@types/resolve": { @@ -963,10 +896,15 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" + }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -975,22 +913,25 @@ "node": ">=0.4.0" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "dependencies": { - "color-convert": "^1.9.0" + "engines": { + "node": ">=12" }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "dev": true, "funding": [ { @@ -1007,11 +948,11 @@ } ], "dependencies": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -1069,21 +1010,21 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -1100,10 +1041,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -1112,18 +1053,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -1137,9 +1066,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001585", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz", - "integrity": "sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==", + "version": "1.0.30001677", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz", + "integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==", "dev": true, "funding": [ { @@ -1160,7 +1089,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -1177,30 +1105,29 @@ "node": ">=10" } }, - "node_modules/citty": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.5.tgz", - "integrity": "sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==", - "dev": true, - "dependencies": { - "consola": "^3.2.3" + "node_modules/ci-info": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "consola": "^3.2.3" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -1228,6 +1155,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true + }, "node_modules/consola": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", @@ -1244,9 +1177,9 @@ "dev": true }, "node_modules/css-declaration-sorter": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.1.1.tgz", - "integrity": "sha512-dZ3bVTEEc1vxr3Bek9vGwfB5Z6ESPULhcRvO472mfjVnj8jRcTnKO8/JTczlvxM10Myb+wBM++1MtdO76eWcaQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", "dev": true, "engines": { "node": "^14 || ^16 || >=18" @@ -1309,16 +1242,16 @@ } }, "node_modules/cssnano": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.3.tgz", - "integrity": "sha512-MRq4CIj8pnyZpcI2qs6wswoYoDD1t0aL28n+41c1Ukcpm56m1h6mCexIHBGjfZfnTqtGSSCP4/fB1ovxgjBOiw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.0.6.tgz", + "integrity": "sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw==", "dev": true, "dependencies": { - "cssnano-preset-default": "^6.0.3", - "lilconfig": "^3.0.0" + "cssnano-preset-default": "^7.0.6", + "lilconfig": "^3.1.2" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "funding": { "type": "opencollective", @@ -1329,55 +1262,56 @@ } }, "node_modules/cssnano-preset-default": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.3.tgz", - "integrity": "sha512-4y3H370aZCkT9Ev8P4SO4bZbt+AExeKhh8wTbms/X7OLDo5E7AYUUy6YPxa/uF5Grf+AJwNcCnxKhZynJ6luBA==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^7.1.1", - "cssnano-utils": "^4.0.1", - "postcss-calc": "^9.0.1", - "postcss-colormin": "^6.0.2", - "postcss-convert-values": "^6.0.2", - "postcss-discard-comments": "^6.0.1", - "postcss-discard-duplicates": "^6.0.1", - "postcss-discard-empty": "^6.0.1", - "postcss-discard-overridden": "^6.0.1", - "postcss-merge-longhand": "^6.0.2", - "postcss-merge-rules": "^6.0.3", - "postcss-minify-font-values": "^6.0.1", - "postcss-minify-gradients": "^6.0.1", - "postcss-minify-params": "^6.0.2", - "postcss-minify-selectors": "^6.0.2", - "postcss-normalize-charset": "^6.0.1", - "postcss-normalize-display-values": "^6.0.1", - "postcss-normalize-positions": "^6.0.1", - "postcss-normalize-repeat-style": "^6.0.1", - "postcss-normalize-string": "^6.0.1", - "postcss-normalize-timing-functions": "^6.0.1", - "postcss-normalize-unicode": "^6.0.2", - "postcss-normalize-url": "^6.0.1", - "postcss-normalize-whitespace": "^6.0.1", - "postcss-ordered-values": "^6.0.1", - "postcss-reduce-initial": "^6.0.2", - "postcss-reduce-transforms": "^6.0.1", - "postcss-svgo": "^6.0.2", - "postcss-unique-selectors": "^6.0.2" - }, - "engines": { - "node": "^14 || ^16 || >=18.0" + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.6.tgz", + "integrity": "sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.3", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^5.0.0", + "postcss-calc": "^10.0.2", + "postcss-colormin": "^7.0.2", + "postcss-convert-values": "^7.0.4", + "postcss-discard-comments": "^7.0.3", + "postcss-discard-duplicates": "^7.0.1", + "postcss-discard-empty": "^7.0.0", + "postcss-discard-overridden": "^7.0.0", + "postcss-merge-longhand": "^7.0.4", + "postcss-merge-rules": "^7.0.4", + "postcss-minify-font-values": "^7.0.0", + "postcss-minify-gradients": "^7.0.0", + "postcss-minify-params": "^7.0.2", + "postcss-minify-selectors": "^7.0.4", + "postcss-normalize-charset": "^7.0.0", + "postcss-normalize-display-values": "^7.0.0", + "postcss-normalize-positions": "^7.0.0", + "postcss-normalize-repeat-style": "^7.0.0", + "postcss-normalize-string": "^7.0.0", + "postcss-normalize-timing-functions": "^7.0.0", + "postcss-normalize-unicode": "^7.0.2", + "postcss-normalize-url": "^7.0.0", + "postcss-normalize-whitespace": "^7.0.0", + "postcss-ordered-values": "^7.0.1", + "postcss-reduce-initial": "^7.0.2", + "postcss-reduce-transforms": "^7.0.0", + "postcss-svgo": "^7.0.1", + "postcss-unique-selectors": "^7.0.3" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/cssnano-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.1.tgz", - "integrity": "sha512-6qQuYDqsGoiXssZ3zct6dcMxiqfT6epy7x4R0TQJadd4LWO3sPR6JH6ZByOvVLoZ6EdwPGgd7+DR1EmX3tiXQQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-5.0.0.tgz", + "integrity": "sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" @@ -1417,12 +1351,12 @@ "dev": true }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1448,6 +1382,14 @@ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", "dev": true }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1516,9 +1458,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.665", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.665.tgz", - "integrity": "sha512-UpyCWObBoD+nSZgOC2ToaIdZB0r9GhqT2WahPKiSki6ckkSuKhQNso8V2PrFcHBMleI/eqbKgVQgVC4Wni4ilw==", + "version": "1.5.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.52.tgz", + "integrity": "sha512-xtoijJTZ+qeucLBDNztDOuQBE1ksqjvNjvqFoST3nGC7fSpqJ+X6BdTBaY5BHG+IhWWmpc6b/KfpeuEDupEPOQ==", "dev": true }, "node_modules/entities": { @@ -1572,23 +1514,14 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -1620,10 +1553,24 @@ "reusify": "^1.0.4" } }, + "node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "dev": true, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -1633,9 +1580,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -1665,20 +1612,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -1751,6 +1684,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -1806,25 +1740,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { "function-bind": "^1.1.2" @@ -1840,9 +1759,9 @@ "dev": true }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -1852,6 +1771,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "dependencies": { "once": "^1.3.0", @@ -1864,28 +1784,16 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "dependencies": { - "builtin-modules": "^3.3.0" + "hasown": "^2.0.2" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1937,9 +1845,9 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -1952,15 +1860,15 @@ "dev": true }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json5": { @@ -1975,31 +1883,16 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lodash.memoize": { @@ -2024,15 +1917,12 @@ } }, "node_modules/magic-string": { - "version": "0.30.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", - "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/mdn-data": { @@ -2051,18 +1941,30 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -2128,31 +2030,32 @@ } }, "node_modules/mkdist": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/mkdist/-/mkdist-1.4.0.tgz", - "integrity": "sha512-LzzdzWDx6cWWPd8saIoO+kT5jnbijfeDaE6jZfmCYEi3YL2aJSyF23/tCFee/mDuh/ek1UQeSYdLeSa6oesdiw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mkdist/-/mkdist-1.6.0.tgz", + "integrity": "sha512-nD7J/mx33Lwm4Q4qoPgRBVA9JQNKgyE7fLo5vdPWVDdjz96pXglGERp/fRnGPCTB37Kykfxs5bDdXa9BWOT9nw==", "dev": true, "dependencies": { - "autoprefixer": "^10.4.14", - "citty": "^0.1.5", - "cssnano": "^6.0.1", - "defu": "^6.1.3", - "esbuild": "^0.19.7", - "fs-extra": "^11.1.1", - "globby": "^13.2.2", - "jiti": "^1.21.0", - "mlly": "^1.4.2", - "mri": "^1.2.0", - "pathe": "^1.1.1", - "postcss": "^8.4.26", - "postcss-nested": "^6.0.1" + "autoprefixer": "^10.4.20", + "citty": "^0.1.6", + "cssnano": "^7.0.6", + "defu": "^6.1.4", + "esbuild": "^0.24.0", + "jiti": "^1.21.6", + "mlly": "^1.7.1", + "pathe": "^1.1.2", + "pkg-types": "^1.2.0", + "postcss": "^8.4.45", + "postcss-nested": "^6.2.0", + "semver": "^7.6.3", + "tinyglobby": "^0.2.9" }, "bin": { "mkdist": "dist/cli.cjs" }, "peerDependencies": { - "sass": "^1.69.5", - "typescript": ">=5.3.2" + "sass": "^1.78.0", + "typescript": ">=5.5.4", + "vue-tsc": "^1.8.27 || ^2.0.21" }, "peerDependenciesMeta": { "sass": { @@ -2160,39 +2063,449 @@ }, "typescript": { "optional": true + }, + "vue-tsc": { + "optional": true } } }, - "node_modules/mlly": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz", - "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==", + "node_modules/mkdist/node_modules/@esbuild/aix-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.0.3", - "ufo": "^1.3.2" + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" } }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "node_modules/mkdist/node_modules/@esbuild/android-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "node_modules/mkdist/node_modules/@esbuild/android-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/android-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/darwin-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/darwin-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/freebsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-loong64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-mips64el": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-riscv64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-s390x": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/linux-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/netbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/openbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/sunos-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/win32-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/win32-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/@esbuild/win32-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/mkdist/node_modules/esbuild": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" + } + }, + "node_modules/mlly": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.2.tgz", + "integrity": "sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.1", + "pathe": "^1.1.2", + "pkg-types": "^1.2.0", + "ufo": "^1.5.4" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ @@ -2209,9 +2522,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "node_modules/normalize-range": { @@ -2275,38 +2588,38 @@ "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==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pkg-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", - "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", "dev": true, "dependencies": { - "jsonc-parser": "^3.2.0", - "mlly": "^1.2.0", - "pathe": "^1.1.0" + "confbox": "^0.1.8", + "mlly": "^1.7.2", + "pathe": "^1.1.2" } }, "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -2324,412 +2637,422 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/postcss-calc": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", - "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-10.0.2.tgz", + "integrity": "sha512-DT/Wwm6fCKgpYVI7ZEWuPJ4az8hiEHtCUeYjZXqU7Ou4QqYh1Df2yCQ7Ca6N7xqKPFkxN3fhf+u9KSoOCJNAjg==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.11", + "postcss-selector-parser": "^6.1.2", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12 || ^20.9 || >=22.0" }, "peerDependencies": { - "postcss": "^8.2.2" + "postcss": "^8.4.38" } }, "node_modules/postcss-colormin": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.2.tgz", - "integrity": "sha512-TXKOxs9LWcdYo5cgmcSHPkyrLAh86hX1ijmyy6J8SbOhyv6ua053M3ZAM/0j44UsnQNIWdl8gb5L7xX2htKeLw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-7.0.2.tgz", + "integrity": "sha512-YntRXNngcvEvDbEjTdRWGU606eZvB5prmHG4BF0yLmVpamXbpsRJzevyy6MZVyuecgzI2AWAlvFi8DAeCqwpvA==", "dev": true, "dependencies": { - "browserslist": "^4.22.2", + "browserslist": "^4.23.3", "caniuse-api": "^3.0.0", - "colord": "^2.9.1", + "colord": "^2.9.3", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-convert-values": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.2.tgz", - "integrity": "sha512-aeBmaTnGQ+NUSVQT8aY0sKyAD/BaLJenEKZ03YK0JnDE1w1Rr8XShoxdal2V2H26xTJKr3v5haByOhJuyT4UYw==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.4.tgz", + "integrity": "sha512-e2LSXPqEHVW6aoGbjV9RsSSNDO3A0rZLCBxN24zvxF25WknMPpX8Dm9UxxThyEbaytzggRuZxaGXqaOhxQ514Q==", "dev": true, "dependencies": { - "browserslist": "^4.22.2", + "browserslist": "^4.23.3", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-discard-comments": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.1.tgz", - "integrity": "sha512-f1KYNPtqYLUeZGCHQPKzzFtsHaRuECe6jLakf/RjSRqvF5XHLZnM2+fXLhb8Qh/HBFHs3M4cSLb1k3B899RYIg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.3.tgz", + "integrity": "sha512-q6fjd4WU4afNhWOA2WltHgCbkRhZPgQe7cXF74fuVB/ge4QbM9HEaOIzGSiMvM+g/cOsNAUGdf2JDzqA2F8iLA==", "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.1.2" + }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-discard-duplicates": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.1.tgz", - "integrity": "sha512-1hvUs76HLYR8zkScbwyJ8oJEugfPV+WchpnA+26fpJ7Smzs51CzGBHC32RS03psuX/2l0l0UKh2StzNxOrKCYg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-7.0.1.tgz", + "integrity": "sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-discard-empty": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.1.tgz", - "integrity": "sha512-yitcmKwmVWtNsrrRqGJ7/C0YRy53i0mjexBDQ9zYxDwTWVBgbU4+C9jIZLmQlTDT9zhml+u0OMFJh8+31krmOg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-7.0.0.tgz", + "integrity": "sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-discard-overridden": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.1.tgz", - "integrity": "sha512-qs0ehZMMZpSESbRkw1+inkf51kak6OOzNRaoLd/U7Fatp0aN2HQ1rxGOrJvYcRAN9VpX8kUF13R2ofn8OlvFVA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-7.0.0.tgz", + "integrity": "sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-merge-longhand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.2.tgz", - "integrity": "sha512-+yfVB7gEM8SrCo9w2lCApKIEzrTKl5yS1F4yGhV3kSim6JzbfLGJyhR1B6X+6vOT0U33Mgx7iv4X9MVWuaSAfw==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.4.tgz", + "integrity": "sha512-zer1KoZA54Q8RVHKOY5vMke0cCdNxMP3KBfDerjH/BYHh4nCIh+1Yy0t1pAEQF18ac/4z3OFclO+ZVH8azjR4A==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", - "stylehacks": "^6.0.2" + "stylehacks": "^7.0.4" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-merge-rules": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.3.tgz", - "integrity": "sha512-yfkDqSHGohy8sGYIJwBmIGDv4K4/WrJPX355XrxQb/CSsT4Kc/RxDi6akqn5s9bap85AWgv21ArcUWwWdGNSHA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-7.0.4.tgz", + "integrity": "sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg==", "dev": true, "dependencies": { - "browserslist": "^4.22.2", + "browserslist": "^4.23.3", "caniuse-api": "^3.0.0", - "cssnano-utils": "^4.0.1", - "postcss-selector-parser": "^6.0.15" + "cssnano-utils": "^5.0.0", + "postcss-selector-parser": "^6.1.2" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-minify-font-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.1.tgz", - "integrity": "sha512-tIwmF1zUPoN6xOtA/2FgVk1ZKrLcCvE0dpZLtzyyte0j9zUeB8RTbCqrHZGjJlxOvNWKMYtunLrrl7HPOiR46w==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-7.0.0.tgz", + "integrity": "sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-minify-gradients": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.1.tgz", - "integrity": "sha512-M1RJWVjd6IOLPl1hYiOd5HQHgpp6cvJVLrieQYS9y07Yo8itAr6jaekzJphaJFR0tcg4kRewCk3kna9uHBxn/w==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-7.0.0.tgz", + "integrity": "sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==", "dev": true, "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^4.0.1", + "colord": "^2.9.3", + "cssnano-utils": "^5.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-minify-params": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.2.tgz", - "integrity": "sha512-zwQtbrPEBDj+ApELZ6QylLf2/c5zmASoOuA4DzolyVGdV38iR2I5QRMsZcHkcdkZzxpN8RS4cN7LPskOkTwTZw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-7.0.2.tgz", + "integrity": "sha512-nyqVLu4MFl9df32zTsdcLqCFfE/z2+f8GE1KHPxWOAmegSo6lpV2GNy5XQvrzwbLmiU7d+fYay4cwto1oNdAaQ==", "dev": true, "dependencies": { - "browserslist": "^4.22.2", - "cssnano-utils": "^4.0.1", + "browserslist": "^4.23.3", + "cssnano-utils": "^5.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-minify-selectors": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.2.tgz", - "integrity": "sha512-0b+m+w7OAvZejPQdN2GjsXLv5o0jqYHX3aoV0e7RBKPCsB7TYG5KKWBFhGnB/iP3213Ts8c5H4wLPLMm7z28Sg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-7.0.4.tgz", + "integrity": "sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.15" + "cssesc": "^3.0.0", + "postcss-selector-parser": "^6.1.2" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "postcss-selector-parser": "^6.0.11" + "postcss-selector-parser": "^6.1.1" }, "engines": { "node": ">=12.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.2.14" } }, "node_modules/postcss-normalize-charset": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.1.tgz", - "integrity": "sha512-aW5LbMNRZ+oDV57PF9K+WI1Z8MPnF+A8qbajg/T8PP126YrGX1f9IQx21GI2OlGz7XFJi/fNi0GTbY948XJtXg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-7.0.0.tgz", + "integrity": "sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-display-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.1.tgz", - "integrity": "sha512-mc3vxp2bEuCb4LgCcmG1y6lKJu1Co8T+rKHrcbShJwUmKJiEl761qb/QQCfFwlrvSeET3jksolCR/RZuMURudw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-7.0.0.tgz", + "integrity": "sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-positions": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.1.tgz", - "integrity": "sha512-HRsq8u/0unKNvm0cvwxcOUEcakFXqZ41fv3FOdPn916XFUrympjr+03oaLkuZENz3HE9RrQE9yU0Xv43ThWjQg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-7.0.0.tgz", + "integrity": "sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-repeat-style": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.1.tgz", - "integrity": "sha512-Gbb2nmCy6tTiA7Sh2MBs3fj9W8swonk6lw+dFFeQT68B0Pzwp1kvisJQkdV6rbbMSd9brMlS8I8ts52tAGWmGQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-7.0.0.tgz", + "integrity": "sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-string": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.1.tgz", - "integrity": "sha512-5Fhx/+xzALJD9EI26Aq23hXwmv97Zfy2VFrt5PLT8lAhnBIZvmaT5pQk+NuJ/GWj/QWaKSKbnoKDGLbV6qnhXg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-7.0.0.tgz", + "integrity": "sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-timing-functions": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.1.tgz", - "integrity": "sha512-4zcczzHqmCU7L5dqTB9rzeqPWRMc0K2HoR+Bfl+FSMbqGBUcP5LRfgcH4BdRtLuzVQK1/FHdFoGT3F7rkEnY+g==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-7.0.0.tgz", + "integrity": "sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-unicode": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.2.tgz", - "integrity": "sha512-Ff2VdAYCTGyMUwpevTZPZ4w0+mPjbZzLLyoLh/RMpqUqeQKZ+xMm31hkxBavDcGKcxm6ACzGk0nBfZ8LZkStKA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-7.0.2.tgz", + "integrity": "sha512-ztisabK5C/+ZWBdYC+Y9JCkp3M9qBv/XFvDtSw0d/XwfT3UaKeW/YTm/MD/QrPNxuecia46vkfEhewjwcYFjkg==", "dev": true, "dependencies": { - "browserslist": "^4.22.2", + "browserslist": "^4.23.3", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.1.tgz", - "integrity": "sha512-jEXL15tXSvbjm0yzUV7FBiEXwhIa9H88JOXDGQzmcWoB4mSjZIsmtto066s2iW9FYuIrIF4k04HA2BKAOpbsaQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-7.0.0.tgz", + "integrity": "sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-normalize-whitespace": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.1.tgz", - "integrity": "sha512-76i3NpWf6bB8UHlVuLRxG4zW2YykF9CTEcq/9LGAiz2qBuX5cBStadkk0jSkg9a9TCIXbMQz7yzrygKoCW9JuA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-7.0.0.tgz", + "integrity": "sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-ordered-values": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.1.tgz", - "integrity": "sha512-XXbb1O/MW9HdEhnBxitZpPFbIvDgbo9NK4c/5bOfiKpnIGZDoL2xd7/e6jW5DYLsWxBbs+1nZEnVgnjnlFViaA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-7.0.1.tgz", + "integrity": "sha512-irWScWRL6nRzYmBOXReIKch75RRhNS86UPUAxXdmW/l0FcAsg0lvAXQCby/1lymxn/o0gVa6Rv/0f03eJOwHxw==", "dev": true, "dependencies": { - "cssnano-utils": "^4.0.1", + "cssnano-utils": "^5.0.0", "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-reduce-initial": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.2.tgz", - "integrity": "sha512-YGKalhNlCLcjcLvjU5nF8FyeCTkCO5UtvJEt0hrPZVCTtRLSOH4z00T1UntQPj4dUmIYZgMj8qK77JbSX95hSw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-7.0.2.tgz", + "integrity": "sha512-pOnu9zqQww7dEKf62Nuju6JgsW2V0KRNBHxeKohU+JkHd/GAH5uvoObqFLqkeB2n20mr6yrlWDvo5UBU5GnkfA==", "dev": true, "dependencies": { - "browserslist": "^4.22.2", + "browserslist": "^4.23.3", "caniuse-api": "^3.0.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-reduce-transforms": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.1.tgz", - "integrity": "sha512-fUbV81OkUe75JM+VYO1gr/IoA2b/dRiH6HvMwhrIBSUrxq3jNZQZitSnugcTLDi1KkQh1eR/zi+iyxviUNBkcQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-7.0.0.tgz", + "integrity": "sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -2740,31 +3063,31 @@ } }, "node_modules/postcss-svgo": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.2.tgz", - "integrity": "sha512-IH5R9SjkTkh0kfFOQDImyy1+mTCb+E830+9SV1O+AaDcoHTvfsvt6WwJeo7KwcHbFnevZVCsXhDmjFiGVuwqFQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-7.0.1.tgz", + "integrity": "sha512-0WBUlSL4lhD9rA5k1e5D8EN5wCEyZD6HJk0jIvRxl+FDVOMlJ7DePHYWGGVc5QRqrJ3/06FTXM0bxjmJpmTPSA==", "dev": true, "dependencies": { "postcss-value-parser": "^4.2.0", - "svgo": "^3.2.0" + "svgo": "^3.3.2" }, "engines": { - "node": "^14 || ^16 || >= 18" + "node": "^18.12.0 || ^20.9.0 || >= 18" }, "peerDependencies": { "postcss": "^8.4.31" } }, "node_modules/postcss-unique-selectors": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.2.tgz", - "integrity": "sha512-8IZGQ94nechdG7Y9Sh9FlIY2b4uS8/k8kdKRX040XHsS3B6d1HrJAkXrBSsSu4SuARruSsUjW3nlSw8BHkaAYQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-7.0.3.tgz", + "integrity": "sha512-J+58u5Ic5T1QjP/LDV9g3Cx4CNOgB5vz+kM6+OxHHhFACdcDeKhBXjQmB7fnIZM12YSTvsL0Opwco83DmacW2g==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.15" + "postcss-selector-parser": "^6.1.2" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": "^18.12.0 || ^20.9.0 || >=22.0" }, "peerDependencies": { "postcss": "^8.4.31" @@ -2895,9 +3218,9 @@ } }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -2911,12 +3234,12 @@ } }, "node_modules/rollup-plugin-dts": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.1.0.tgz", - "integrity": "sha512-ijSCPICkRMDKDLBK9torss07+8dl9UpY9z1N/zTeA1cIqdzMlpkV3MOOC7zukyvQfDyxa1s3Dl2+DeiP/G6DOw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.1.1.tgz", + "integrity": "sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==", "dev": true, "dependencies": { - "magic-string": "^0.30.4" + "magic-string": "^0.30.10" }, "engines": { "node": ">=16" @@ -2925,7 +3248,7 @@ "url": "https://github.com/sponsors/Swatinem" }, "optionalDependencies": { - "@babel/code-frame": "^7.22.13" + "@babel/code-frame": "^7.24.2" }, "peerDependencies": { "rollup": "^3.29.4 || ^4", @@ -2962,12 +3285,15 @@ "dev": true }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/slash": { @@ -2982,41 +3308,82 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/snapshot-fixtures": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/snapshot-fixtures/-/snapshot-fixtures-1.2.0.tgz", + "integrity": "sha512-+JH/QfYxlFCD64/ifTAk39dHFzv+cHHeu+U1ocyBNcYhgTath5CFHH8m6yW7I27xODKQc8gIDQbsl8HwRnyWRg==", + "dependencies": { + "chalk": "^5.0.0", + "ci-info": "^4.0.0", + "diff": "^5.0.0", + "to-vfile": "^8.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + }, + "peerDependencies": { + "prettier": ">=3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, "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==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/stylehacks": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.2.tgz", "integrity": "sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg==", "dev": true, "dependencies": { - "browserslist": "^4.22.2", - "postcss-selector-parser": "^6.0.15" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=12" }, - "peerDependencies": { - "postcss": "^8.4.31" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/stylehacks": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.4.tgz", + "integrity": "sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "browserslist": "^4.23.3", + "postcss-selector-parser": "^6.1.2" }, "engines": { - "node": ">=4" + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -3032,9 +3399,9 @@ } }, "node_modules/svgo": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", - "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", "dev": true, "dependencies": { "@trysound/sax": "0.2.0", @@ -3079,13 +3446,17 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/tinyglobby": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", "dev": true, + "dependencies": { + "fdir": "^6.4.2", + "picomatch": "^4.0.2" + }, "engines": { - "node": ">=4" + "node": ">=12.0.0" } }, "node_modules/to-regex-range": { @@ -3100,10 +3471,22 @@ "node": ">=8.0" } }, + "node_modules/to-vfile": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-8.0.0.tgz", + "integrity": "sha512-IcmH1xB5576MJc9qcfEC/m/nQCFt3fzMHz45sSlgJyTWjRbKW1HAkJpuf3DgE57YzIlZcwcBZA5ENQbBo4aLkg==", + "dependencies": { + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "peer": true, "bin": { @@ -3115,9 +3498,9 @@ } }, "node_modules/ufo": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", - "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", "dev": true }, "node_modules/unbuild": { @@ -3163,37 +3546,49 @@ } } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/untyped": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/untyped/-/untyped-1.4.2.tgz", - "integrity": "sha512-nC5q0DnPEPVURPhfPQLahhSTnemVtPzdx7ofiRxXpOB2SYnb3MfdU3DVGyJdS8Lx+tBWeAePO8BfU/3EgksM7Q==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/untyped/-/untyped-1.5.1.tgz", + "integrity": "sha512-reBOnkJBFfBZ8pCKaeHgfZLcehXtM6UTxc+vqs1JvCps0c4amLNp3fhdGBZwYp+VLyoY9n3X5KOP7lCyWBUX9A==", "dev": true, "dependencies": { - "@babel/core": "^7.23.7", - "@babel/standalone": "^7.23.8", - "@babel/types": "^7.23.6", + "@babel/core": "^7.25.7", + "@babel/standalone": "^7.25.7", + "@babel/types": "^7.25.7", "defu": "^6.1.4", - "jiti": "^1.21.0", + "jiti": "^2.3.1", "mri": "^1.2.0", - "scule": "^1.2.0" + "scule": "^1.3.0" }, "bin": { "untyped": "dist/cli.mjs" } }, + "node_modules/untyped/node_modules/jiti": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.0.tgz", + "integrity": "sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==", + "dev": true, + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -3210,8 +3605,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -3226,10 +3621,36 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/wasm-pack": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.13.0.tgz", - "integrity": "sha512-AmboGZEnZoIcVCzSlkLEmNFEqJN+IwgshJ5S7pi30uNUTce4LvWkifQzsQRxnWj47G8gkqZxlyGlyQplsnIS7w==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.13.1.tgz", + "integrity": "sha512-P9exD4YkjpDbw68xUhF3MDm/CC/3eTmmthyG5bHJ56kalxOTewOunxTke4SyF8MTXV6jUtNjXggPgrGmMtczGg==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -3252,4 +3673,4 @@ "dev": true } } -} +} \ No newline at end of file diff --git a/src/js-cli-and-library/package.json b/src/js-cli-and-library/package.json index 7a6f1067..5653a853 100644 --- a/src/js-cli-and-library/package.json +++ b/src/js-cli-and-library/package.json @@ -20,13 +20,13 @@ }, "scripts": { "clean": "rmdir dist && rmdir build", - "build": "wasm-pack build --dev --out-dir src/js-cli-and-library/build --target web --no-pack && npm run build-js", - "build-release": "wasm-pack build --release --out-dir src/js-cli-and-library/build --target web --no-pack && npm run build-js", + "build": "wasm-pack build --dev --target web --no-pack --out-dir src/js-cli-and-library/build && npm run build-js", + "build-release": "wasm-pack build --release --target web --no-pack --out-dir src/js-cli-and-library/build && npm run build-js", "--": "Manually assembles the output", "build-manual-bind": "cargo build --lib --target wasm32-unknown-unknown --profile debug && wasm-bindgen --out-dir build --target web ../../target/wasm32-unknown-unknown/debug/ezno_lib.wasm && npm run build-js", "build-js": "unbuild && cp ./build/ezno_lib_bg.wasm dist/shared && cp src/cli_node.cjs dist/cli.cjs", "test": "npm run build && npm run run-tests", - "run-tests": "node test.mjs && deno run -A test.mjs" + "run-tests": "node --test" }, "keywords": [ "typescript", @@ -74,7 +74,9 @@ } }, "devDependencies": { - "unbuild": "^2.0.0", - "wasm-pack": "^0.13.0" + "strip-ansi": "^7.1.0", + "unbuild": "^2.0.0", + "wasm-pack": "^0.13.0", + "snapshot-fixtures": "^1.2.0" } -} +} \ No newline at end of file diff --git a/src/js-cli-and-library/src/cli.js b/src/js-cli-and-library/src/cli.js index 863f1e5e..d0f620b5 100644 --- a/src/js-cli-and-library/src/cli.js +++ b/src/js-cli-and-library/src/cli.js @@ -1,7 +1,9 @@ #!/usr/bin/env node -import { initSync, run_cli } from "../build/ezno_lib.js"; +import { initSync, run_cli, parse_module, ReplSystem } from "../build/ezno_lib.js"; import { readFileSync, writeFileSync } from "node:fs"; +import * as readline from 'node:readline/promises'; +import { stdin as input, stdout as output } from 'node:process'; const wasmPath = new URL("./shared/ezno_lib_bg.wasm", import.meta.url); if (wasmPath.protocol === "https:") { @@ -21,13 +23,33 @@ function writeFile(path, content) { writeFileSync(path, content) } -function readFromCLI(prompt_msg) { - if (typeof Deno !== "undefined") { - return prompt(`${prompt_msg}>`); - } else { - console.error("Prompt not supported in NodeJS (sync issue)"); - throw new Error("Prompt not supported in NodeJS"); +// Fix because REPL requires syncronous stdin input which isn't +// TODO also ast-explorer +if (cliArguments.length === 1 && (cliArguments[0] === "repl" || cliArguments[0] === "ast-explorer")) { + const kind = cliArguments[0]; + const rl = readline.createInterface({ input, output }); + + if (kind === "repl") { + console.log("Entering REPL"); + const system = ReplSystem.new_system({}, (path) => { console.trace(path); return "" }); + while (true) { + const answer = await rl.question('> '); + if (answer.length === 0 || answer === ".exit" || answer === "close()") { + break + } + system.execute_statement(answer); + } + } else if (kind === "ast-explorer") { + console.log("Entering ast-explorer"); + while (true) { + const answer = await rl.question('> '); + if (answer.length === 0 || answer === ".exit" || answer === "close()") { + break + } + console.dir(parse_module(answer), { depth: Number.POSITIVE_INFINITY }); + } } + rl.close(); +} else { + run_cli(cliArguments, readFile, writeFile); } - -run_cli(cliArguments, readFile, writeFile, readFromCLI); diff --git a/src/js-cli-and-library/test.mjs b/src/js-cli-and-library/test.mjs deleted file mode 100644 index 42c21cba..00000000 --- a/src/js-cli-and-library/test.mjs +++ /dev/null @@ -1,38 +0,0 @@ -import { check, parse_expression, get_version } from "./dist/initialised.mjs"; -import assert, { deepStrictEqual } from "node:assert"; - -function buildTest() { - // TODO -} - -buildTest() - -function checkTest() { - const example = "const x: 4 = 2;" - const output = check("input.ts", (_path) => example); - deepStrictEqual(output.diagnostics, [ - { - reason: "Type 2 is not assignable to type 4", - position: { start: 13, end: 14, source: 2 }, - labels: [ - [ - "Variable declared with type 4", - { - end: 10, - source: 2, - start: 9, - }, - ], - ], - kind: "error" - }, - ], - ); - console.log("WASM: check test passed") -} - -checkTest() - -console.log(parse_expression("x = 4 + 2")) - -console.log(get_version()) \ No newline at end of file diff --git a/src/js-cli-and-library/tests/cli.test.mjs b/src/js-cli-and-library/tests/cli.test.mjs new file mode 100644 index 00000000..e5fb66e6 --- /dev/null +++ b/src/js-cli-and-library/tests/cli.test.mjs @@ -0,0 +1,64 @@ +import { test } from "node:test"; +import { spawn } from "node:child_process"; +import { assertEqual } from "snapshot-fixtures"; +import stripAnsi from "strip-ansi"; + +const wait = (timeout = 500) => new Promise((res, rej) => setTimeout(res, timeout)); + +test("ast-explorer", { timeout: 10000 }, async (t) => { + await t.test("works", async () => { + const decoder = new TextDecoder(); + + function write(child, command) { + child.stdin.write(command + "\r\n"); + } + + const child = spawn("node", ["./dist/cli.mjs", "ast-explorer"], { stdio: "pipe" }); + + child.stdout.on("data", (d) => out.push(decoder.decode(d))); + child.stderr.on("data", (d) => out.push(decoder.decode(d))); + + const out = []; + + await wait(); + write(child, "'Hello World'"); + await wait(); + write(child, "close()") + await wait(); + + const expected = `Entering ast-explorer\n> {\n Ok: {\n hashbang_comment: undefined,\n items: [\n {\n Statement: {\n Expression: {\n Single: {\n StringLiteral: [ 'Hello World', 'Single', { start: 0, end: 13 } ]\n }\n }\n }\n }\n ],\n span: { start: 0, end: 13 }\n }\n}\n> `; + + // console.log(stripAnsi(out.join("")).replaceAll("\n", "\\n")); + + assertEqual(stripAnsi(out.join("")), expected); + }); +}); + +test("type checking repl", { timeout: 10000 }, async (t) => { + await t.test("works", async () => { + const decoder = new TextDecoder(); + + function write(child, command) { + child.stdin.write(command + "\r\n"); + } + + const child = spawn("node", ["./dist/cli.mjs", "repl"], { stdio: "pipe" }); + + child.stdout.on("data", (d) => out.push(decoder.decode(d))); + child.stderr.on("data", (d) => out.push(decoder.decode(d))); + + const out = []; + + await wait(); + write(child, "const var1: string = 5 + 6;"); + await wait(); + write(child, "close()") + await wait(); + + const expected = `Entering REPL\n> error: \n ┌─ CLI.tsx:1:22\n │\n1 │ const var1: string = 5 + 6;\n │ ------ ^^^^^ Type 11 is not assignable to type string\n │ │ \n │ Variable declared with type string\n\n\n> `; + + // console.log(stripAnsi(out.join("")).replaceAll("\n", "\\n")); + + assertEqual(stripAnsi(out.join("")), expected); + }); +}); diff --git a/src/js-cli-and-library/tests/library.test.mjs b/src/js-cli-and-library/tests/library.test.mjs new file mode 100644 index 00000000..0a8468fe --- /dev/null +++ b/src/js-cli-and-library/tests/library.test.mjs @@ -0,0 +1,66 @@ +import { check, parse_expression, get_version, experimental_build } from "../dist/initialised.mjs"; +import { deepStrictEqual } from "node:assert"; +import { test } from "node:test"; +import { inspect } from "node:util"; + +// console.log(`Running ezno@${get_version()}`) + +test("Type checking on code diagnostics", (t) => { + t.test("type check", () => { + const example = "const x: 4 = 2;" + const output = check("input.ts", (_path) => example); + deepStrictEqual(output.diagnostics, [ + { + reason: "Type 2 is not assignable to type 4", + position: { start: 13, end: 14, source: 2 }, + labels: [ + [ + "Variable declared with type 4", + { + end: 10, + source: 2, + start: 9, + }, + ], + ], + kind: "error" + }, + ]); + }); +}); + +test("Compiling", (t) => { + t.test("Compile", () => { + const example = "const x: 4 = 2 + 2;" + const output = experimental_build("input.ts", (_path) => example, { strip_whitespace: true }); + deepStrictEqual(output.diagnostics, []); + deepStrictEqual(output.artifacts, [{ content: 'const x=2+2', output_path: 'out.js' }]); + }) +}); + +test("Parsing", (t) => { + t.test("expressions", () => { + const expression = parse_expression("x = 4 + 2"); + + // console.log(inspect(expression, { depth: Infinity, colors: true })); + + deepStrictEqual(expression, { + Ok: { + Assignment: { + lhs: { + VariableOrPropertyAccess: { Variable: ['x', { start: 0, end: 1 }] } + }, + rhs: { + BinaryOperation: { + lhs: { NumberLiteral: [{ Number: 4 }, { start: 4, end: 5 }] }, + operator: 'Add', + rhs: { NumberLiteral: [{ Number: 2 }, { start: 8, end: 9 }] }, + position: { start: 4, end: 9 } + } + }, + position: { start: 0, end: 9 } + } + } + }); + }) +}) diff --git a/src/lib.rs b/src/lib.rs index e5b7a08e..6f0f12e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(target_family = "wasm", allow(unused))] + mod ast_explorer; mod build; mod check; @@ -11,6 +13,7 @@ pub mod transformers; pub use build::build; pub use check::check; +pub(crate) use checker::ReadFromFS; pub use checker::{Diagnostic, DiagnosticKind}; pub use parser::{source_map, ASTNode, ToStringOptions}; @@ -21,42 +24,6 @@ pub fn prettifier(input: String) -> Result { Ok(module.to_string(&ToStringOptions::default())) } -#[cfg(target_family = "wasm")] -pub trait ReadFromFS { - fn get_content_at_path(&self, path: &std::path::Path) -> Option; -} - -// Not WASM require `Sync + Send` for watch mode -#[cfg(not(target_family = "wasm"))] -pub trait ReadFromFS: Sync + Send { - fn get_content_at_path(&self, path: &std::path::Path) -> Option; -} - -#[cfg(target_family = "wasm")] -impl ReadFromFS for T -where - T: Fn(&std::path::Path) -> Option, -{ - fn get_content_at_path(&self, path: &std::path::Path) -> Option { - (self)(path) - } -} - -#[cfg(not(target_family = "wasm"))] -impl ReadFromFS for T -where - T: Fn(&std::path::Path) -> Option + Sync + Send, -{ - fn get_content_at_path(&self, path: &std::path::Path) -> Option { - (self)(path) - } -} - -/// prompt -> response -pub trait CLIInputResolver: Fn(&str) -> Option {} - -impl CLIInputResolver for T where T: Fn(&str) -> Option {} - pub trait WriteToFS: Fn(&std::path::Path, String) {} impl WriteToFS for T where T: Fn(&std::path::Path, String) {} diff --git a/src/main.rs b/src/main.rs index db171795..2c13db82 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,28 +13,6 @@ #![warn(clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss)] use ezno_lib::cli::run_cli; -use std::io; - -#[cfg(target_family = "windows")] -pub(crate) fn cli_input_resolver(prompt: &str) -> String { - print!("{prompt}> "); - io::Write::flush(&mut io::stdout()).unwrap(); - let mut input = String::new(); - let std_in = &mut io::stdin(); - let _n = multiline_term_input::read_string(std_in, &mut input); - input -} - -#[cfg(target_family = "unix")] -#[allow(clippy::unnecessary_wraps)] -pub(crate) fn cli_input_resolver(prompt: &str) -> String { - print!("{prompt}> "); - io::Write::flush(&mut io::stdout()).unwrap(); - let mut input = String::new(); - let std_in = &mut io::stdin(); - let _n = std_in.read_line(&mut input).unwrap(); - input -} fn main() -> std::process::ExitCode { fn read_from_file(path: &std::path::Path) -> Option { @@ -48,5 +26,5 @@ fn main() -> std::process::ExitCode { let arguments = std::env::args().skip(1).collect::>(); let arguments = arguments.iter().map(String::as_str).collect::>(); - run_cli(&arguments, &read_from_file, write_to_file, |p| Some(cli_input_resolver(p))) + run_cli(&arguments, read_from_file, write_to_file) } diff --git a/src/repl.rs b/src/repl.rs index 1978a1a1..316bb9f1 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,17 +1,18 @@ -use std::fs; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use argh::FromArgs; -use parser::{visiting::VisitorsMut, ASTNode}; -use parser::{Expression, Module, Statement}; +use parser::{visiting::VisitorsMut, ASTNode, Expression, Module, SourceId, Statement}; use crate::reporting::report_diagnostics_to_cli; -use crate::utilities::print_to_cli; -/// Run project repl using deno. (`deno` command must be in path) -#[derive(FromArgs, PartialEq, Debug)] +#[cfg(target_family = "wasm")] +use wasm_bindgen::prelude::wasm_bindgen; + +/// Run type checking REPL +#[derive(FromArgs, PartialEq, Debug, Default)] #[argh(subcommand, name = "repl")] -pub(crate) struct ReplArguments { +#[cfg_attr(target_family = "wasm", derive(serde::Deserialize), serde(default))] +pub struct ReplArguments { /// use mutable variables everywhere #[argh(switch)] const_as_let: bool, @@ -20,68 +21,72 @@ pub(crate) struct ReplArguments { type_definition_module: Option, } -#[allow(unused)] -fn file_system_resolver(path: &Path) -> Option> { - // Cheaty - if path.to_str() == Some("BLANK") { - Some(Vec::new()) - } else { - match fs::read_to_string(path) { - Ok(source) => Some(source.into()), - Err(_) => None, - } - } +/// Wraps `checker::synthesis::interactive::State` +#[cfg_attr(target_family = "wasm", wasm_bindgen)] +pub struct ReplSystem { + arguments: ReplArguments, + source: SourceId, + state: checker::synthesis::interactive::State<'static, crate::utilities::FSFunction>, } -pub(crate) fn run_repl( - cli_input_resolver: U, - ReplArguments { const_as_let, type_definition_module }: ReplArguments, -) { - print_to_cli(format_args!("Entering REPL. Exit with `close()`")); +pub type ReplSystemErr = ( + checker::DiagnosticsContainer, + crate::source_map::MapFileStore, +); + +impl ReplSystem { + pub fn new( + arguments: ReplArguments, + file_system_resolver: crate::utilities::FSFunction, + ) -> Result { + let definitions = if let Some(tdm) = arguments.type_definition_module.clone() { + std::iter::once(tdm).collect() + } else { + std::iter::once(checker::INTERNAL_DEFINITION_FILE_PATH.into()).collect() + }; - let definitions = if let Some(tdm) = type_definition_module { - std::iter::once(tdm).collect() - } else { - std::iter::once(checker::INTERNAL_DEFINITION_FILE_PATH.into()).collect() - }; + // TOOD + let static_file_system_resolver = Box::leak(Box::new(file_system_resolver)); - let state = checker::synthesis::interactive::State::new(&file_system_resolver, definitions); + let state = + checker::synthesis::interactive::State::new(static_file_system_resolver, definitions)?; + let source = state.get_source_id(); - let mut state = match state { - Ok(state) => state, - Err((diagnostics, fs)) => { - report_diagnostics_to_cli( - diagnostics, - &fs, - false, - crate::utilities::MaxDiagnostics::All, - ) - .unwrap(); - return; - } - }; + Ok(ReplSystem { arguments, source, state }) + } +} - let source = state.get_source_id(); +#[cfg_attr(target_family = "wasm", wasm_bindgen)] +impl ReplSystem { + /// Not a constructor because returns result (can fail if can't find `d.ts` file) + /// Also `repl_arguments` rather than `arguments` otherwise breaks JS emit + #[cfg(target_family = "wasm")] + #[wasm_bindgen(js_name = "new_system")] + pub fn new_js( + repl_arguments: wasm_bindgen::JsValue, + cb: &js_sys::Function, + ) -> Option { + let repl_arguments: ReplArguments = + serde_wasm_bindgen::from_value(repl_arguments).expect("invalid ReplArguments"); + let cb = crate::utilities::FSFunction(cb.clone()); + Self::new(repl_arguments, cb).ok() + } - loop { - let input = cli_input_resolver(""); - let input = if let Some(input) = input { - if input.is_empty() { - continue; - } else if input.trim() == "close()" { - break; - } + #[cfg_attr(target_family = "wasm", wasm_bindgen)] + pub fn execute_statement(&mut self, mut input: String) { + // New line fixes #210 + input.truncate(input.trim_end().len()); + input.push('\n'); + let (start, _) = self.state.get_fs_mut().append_to_file(self.source, &input); - input - } else { - continue; - }; + let options = Default::default(); + let offset = Some(start as u32); - let (from_index, _) = state.get_fs_mut().append_to_file(source, &input); + // self.offset += input.len() as u32 + 1; - let options = Default::default(); - let offset = Some(from_index as u32); - let result = if input.trim_start().starts_with('{') { + // Fix to remain consistent with other JS REPLs + let starts_with_brace = input.trim_start().starts_with('{'); + let result = if starts_with_brace { Expression::from_string_with_options(input, options, offset).map(|(expression, _)| { Module { hashbang_comment: None, @@ -90,59 +95,99 @@ pub(crate) fn run_repl( } }) } else { - Module::from_string(input, options) + Module::from_string_with_options(input, options, offset).map(|(module, _state)| module) }; - let mut item = match result { - Ok(item) => item, + match result { + Ok(mut item) => { + // crate::utilities::print_to_cli(format_args!("item={item:?}")); + + if self.arguments.const_as_let { + item.visit_mut( + &mut VisitorsMut { + statement_visitors_mut: vec![Box::new(crate::transformers::ConstToLet)], + ..Default::default() + }, + &mut (), + &Default::default(), + self.source, + ); + } + + let result = self.state.check_item(&item); + + match result { + Ok((last_ty, diagnostics)) => { + report_diagnostics_to_cli( + diagnostics, + self.state.get_fs_ref(), + false, + crate::utilities::MaxDiagnostics::All, + ) + .unwrap(); + + if let Some(last_ty) = last_ty { + crate::utilities::print_to_cli(format_args!("{last_ty}")); + } + } + Err(diagnostics) => { + report_diagnostics_to_cli( + diagnostics, + self.state.get_fs_ref(), + false, + crate::utilities::MaxDiagnostics::All, + ) + .unwrap(); + } + } + } Err(err) => { report_diagnostics_to_cli( - std::iter::once((err, source).into()), - state.get_fs_ref(), + std::iter::once((err, self.source).into()), + self.state.get_fs_ref(), false, crate::utilities::MaxDiagnostics::All, ) .unwrap(); - continue; } - }; - - if const_as_let { - item.visit_mut( - &mut VisitorsMut { - statement_visitors_mut: vec![Box::new(crate::transformers::ConstToLet)], - ..Default::default() - }, - &mut (), - &Default::default(), - source, - ); } + } +} - let result = state.check_item(&item); +#[cfg(target_family = "wasm")] +pub(crate) fn run_repl(_arguments: ReplArguments) { + panic!( + "Cannot run repl in WASM because of input callback. Consider reimplementing using library" + ); +} - match result { - Ok((last_ty, diagnostics)) => { - report_diagnostics_to_cli( - diagnostics, - state.get_fs_ref(), - false, - crate::utilities::MaxDiagnostics::All, - ) - .unwrap(); - if let Some(last_ty) = last_ty { - println!("{last_ty}"); - } - } - Err(diagnostics) => { - report_diagnostics_to_cli( - diagnostics, - state.get_fs_ref(), - false, - crate::utilities::MaxDiagnostics::All, - ) - .unwrap(); - } +#[cfg(not(target_family = "wasm"))] +pub(crate) fn run_repl(arguments: ReplArguments) { + use crate::utilities::print_to_cli; + + print_to_cli(format_args!("Entering Repl. Exit with `close()`")); + + let mut system = match ReplSystem::new(arguments, crate::utilities::FSFunction) { + Ok(system) => system, + Err((diagnostics, fs)) => { + report_diagnostics_to_cli( + diagnostics, + &fs, + false, + crate::utilities::MaxDiagnostics::All, + ) + .unwrap(); + return; + } + }; + + loop { + let input = crate::utilities::cli_input_resolver(""); + if input.is_empty() { + continue; + } else if input.trim() == "close()" { + break; } + system.execute_statement(input) } } diff --git a/src/reporting.rs b/src/reporting.rs index 7a9ef81d..f3abc273 100644 --- a/src/reporting.rs +++ b/src/reporting.rs @@ -1,12 +1,6 @@ -use std::io::Write; - use codespan_reporting::{ diagnostic::{Diagnostic, Label, Severity}, - term::{ - emit, - termcolor::{BufferedStandardStream, ColorChoice}, - Config, DisplayStyle, - }, + term::{emit, Config, DisplayStyle}, }; use checker::source_map::{MapFileStore, PathMap, SourceId}; @@ -97,7 +91,9 @@ where }; #[cfg(not(target_family = "wasm"))] - let mut writer = BufferedStandardStream::stderr(ColorChoice::Auto); + let mut writer = codespan_reporting::term::termcolor::BufferedStandardStream::stderr( + codespan_reporting::term::termcolor::ColorChoice::Auto, + ); let files = fs.into_code_span_store(); let diagnostics = diagnostics.into_iter(); @@ -121,11 +117,13 @@ where } #[cfg(not(target_family = "wasm"))] - emit(&mut writer, &config, &files, &diagnostic)?; + { + emit(&mut writer, &config, &files, &diagnostic)?; + } } #[cfg(not(target_family = "wasm"))] - writer.flush().unwrap(); + std::io::Write::flush(&mut writer).unwrap(); if count > maximum { crate::utilities::print_to_cli(format_args!( diff --git a/src/utilities.rs b/src/utilities.rs index 5a3165bc..69889bce 100644 --- a/src/utilities.rs +++ b/src/utilities.rs @@ -2,64 +2,77 @@ use std::fmt::Arguments; pub(crate) fn print_info() { if let Some(run_id) = option_env!("GITHUB_RUN_ID") { - print_to_cli_with_break_after(format_args!( - "{}@{} (#{run_id})", + print_to_cli(format_args!( + "{}@{} (#{run_id})\n", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION") )); } else { - print_to_cli_with_break_after(format_args!( - "{}@{}", - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_VERSION") - )); + print_to_cli(format_args!("{}@{}\n", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"))); } print_to_cli(format_args!("{}", env!("CARGO_PKG_DESCRIPTION"))); - print_to_cli_with_break_after(format_args!( - "Repository: {}, License: {}", + print_to_cli(format_args!( + "Repository: {}, License: {}\n", env!("CARGO_PKG_REPOSITORY"), env!("CARGO_PKG_LICENSE") )); - print_to_cli_with_break_after(format_args!("For help run --help")); + print_to_cli(format_args!("For help run --help\n")); if let (Some(sponsors), Some(contributors)) = (option_env!("SPONSORS"), option_env!("CONTRIBUTORS")) { const SPONSORS_URL: &str = "https://github.com/sponsors/kaleidawave"; - print_to_cli_with_break_after(format_args!( - "With thanks to all supporters of the project including:" - )); + print_to_cli(format_args!("With thanks to all supporters of the project including:")); print_to_cli(format_args!( " Contributors (join them @ https://github.com/kaleidawave/ezno/issues):" )); - wrap_with_ident(contributors); + wrap_with_indent(contributors); print_to_cli(format_args!(" Sponsors (join them @ {SPONSORS_URL}):")); - wrap_with_ident(sponsors); + wrap_with_indent(sponsors); } } -fn wrap_with_ident(input: &str) { - // Four spaces is stable across terminals (unlike tabs) +pub(crate) fn cli_input_resolver(prompt: &str) -> String { + use std::io; + print!("{prompt}> "); + std::io::Write::flush(&mut io::stdout()).unwrap(); + let mut input = String::new(); + let std_in = &mut io::stdin(); + + // multiline_term_input only works on windows for now + #[cfg(target_family = "windows")] + let _n = multiline_term_input::read_string(std_in, &mut input); + + #[cfg(target_family = "unix")] + let _n = std_in.read_line(&mut input).unwrap(); + + input +} + +fn wrap_with_indent(input: &str) { + // Four spaces is consitently rendered across terminals (unlike tabs) const INDENT: &str = " "; + const MAX_WIDTH: usize = 60; + let mut buf = String::new(); - for part in input.split(',') { - buf.push_str(part); - buf.push_str(", "); - if buf.len() > 40 { - print_to_cli(format_args!("{INDENT}{buf}")); - buf.clear(); + let mut iter = input.split(',').peekable(); + while let Some(part) = iter.next() { + buf.push_str(part.trim()); + if let Some(next) = iter.peek() { + if buf.len() + next.len() > MAX_WIDTH { + buf.push(','); + print_to_cli(format_args!("{INDENT}{buf}")); + buf.clear(); + } else { + buf.push_str(", "); + } } } - if !buf.is_empty() { - print_to_cli_with_break_after(format_args!("{INDENT}{buf}")); - } else { - print_to_cli(format_args!("\n")) - } -} - -/// Adds and extra new line afterwards -fn print_to_cli_with_break_after(arguments: Arguments) { - print_to_cli(format_args!("{arguments}\n")); + // TODO double check whether there needs to be another new line? + print_to_cli(format_args!( + "{INDENT}{buf}\n", + INDENT = if buf.is_empty() { "" } else { INDENT } + )); } #[cfg(target_family = "wasm")] @@ -67,12 +80,6 @@ pub(crate) fn print_to_cli(arguments: Arguments) { super::wasm_bindings::log(&arguments.to_string()); } -#[cfg(target_family = "wasm")] -pub(crate) fn print_to_cli_without_newline(arguments: Arguments) { - // TODO :( - super::wasm_bindings::log(&arguments.to_string()); -} - #[cfg(not(target_family = "wasm"))] pub(crate) fn print_to_cli(arguments: Arguments) { use std::io; @@ -81,14 +88,6 @@ pub(crate) fn print_to_cli(arguments: Arguments) { io::Write::flush(&mut io::stdout()).unwrap(); } -#[cfg(not(target_family = "wasm"))] -pub(crate) fn print_to_cli_without_newline(arguments: Arguments) { - use std::io; - - print!("{arguments}"); - io::Write::flush(&mut io::stdout()).unwrap(); -} - #[derive(Debug, Copy, Clone)] pub(crate) enum MaxDiagnostics { All, @@ -114,6 +113,33 @@ impl Default for MaxDiagnostics { } } +#[cfg(target_family = "wasm")] +pub struct FSFunction(pub js_sys::Function); + +#[cfg(target_family = "wasm")] +impl checker::ReadFromFS for FSFunction { + fn read_file(&self, path: &std::path::Path) -> Option> { + self.0 + .call1( + &wasm_bindgen::JsValue::null(), + &wasm_bindgen::JsValue::from(path.display().to_string()), + ) + .ok() + .and_then(|s| s.as_string()) + .map(|s| s.into_bytes()) + } +} + +#[cfg(not(target_family = "wasm"))] +pub struct FSFunction; + +#[cfg(not(target_family = "wasm"))] +impl checker::ReadFromFS for FSFunction { + fn read_file(&self, path: &std::path::Path) -> Option> { + std::fs::read(path).ok() + } +} + // yes i implemented it only using `native_tls`... // TODO or(..., debug_assertions) #[cfg(not(target_family = "wasm"))] diff --git a/src/wasm_bindings.rs b/src/wasm_bindings.rs index 42436575..c11d7c9e 100644 --- a/src/wasm_bindings.rs +++ b/src/wasm_bindings.rs @@ -7,43 +7,7 @@ extern "C" { pub(crate) fn log(s: &str); } -#[derive(Clone, Copy, Default, serde::Deserialize)] -#[wasm_bindgen] -pub struct CheckOptions { - pub lsp_mode: bool, -} - -#[wasm_bindgen(typescript_custom_section)] -const TYPES_EXPERIMENTAL_BUILD: &str = r###" -export function experimental_build( - entry_path: string, fs_resolve_js: (path: string) => string | undefined, minify: boolean -): {Ok: BuildOutput} | {Err: FailedBuildOutput} -"###; -#[wasm_bindgen(js_name = experimental_build, skip_typescript)] -pub fn experimental_build_wasm( - entry_path: String, - fs_resolver_js: &js_sys::Function, - minify: bool, -) -> JsValue { - std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - - let fs_resolver = |path: &std::path::Path| { - let res = - fs_resolver_js.call1(&JsValue::null(), &JsValue::from(path.display().to_string())); - res.ok().and_then(|res| res.as_string()) - }; - let result = crate::build::build( - vec![entry_path.into()], - &fs_resolver, - None, - Path::new("out.js"), - &crate::build::BuildConfig { strip_whitespace: minify, source_maps: false }, - None, - ); - - serde_wasm_bindgen::to_value(&result).unwrap() -} - +/// Wrapper the abstracts some of the properties #[wasm_bindgen(typescript_custom_section)] const TYPES_WASM_CHECK_OUTPUT: &str = r###" interface WASMCheckOutput { @@ -78,48 +42,112 @@ impl WASMCheckOutput { } #[wasm_bindgen(typescript_custom_section)] -const TYPES_CHECK: &str = r#" -export function check(entry_path: string, fs_resolver_js: (path: string) => string | undefined): WASMCheckOutput -"#; +const TYPES_CHECK_WITH_OPTIONS: &str = r#" +export function check( + entry_path: string, + fs_resolver_js: (path: string) => string | undefined, + options: TypeCheckOptions | undefined +): WASMCheckOutput"#; #[wasm_bindgen(js_name = check, skip_typescript)] -pub fn check_wasm(entry_path: String, fs_resolver_js: &js_sys::Function) -> WASMCheckOutput { +pub fn check_wasm( + entry_path: String, + fs_resolver_js: &js_sys::Function, + options: JsValue, +) -> WASMCheckOutput { std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + let options: checker::TypeCheckOptions = if options.is_undefined() || options.is_null() { + Default::default() + } else { + serde_wasm_bindgen::from_value(options).expect("invalid TypeCheckOptions") + }; + let fs_resolver = |path: &std::path::Path| { let res = fs_resolver_js.call1(&JsValue::null(), &JsValue::from(path.display().to_string())); res.ok().and_then(|res| res.as_string()) }; - WASMCheckOutput(crate::check::check( - vec![entry_path.into()], - &fs_resolver, - None, - checker::TypeCheckOptions::default(), - )) + + WASMCheckOutput(crate::check::check(vec![entry_path.into()], &fs_resolver, None, options)) } +/// Wrapper the abstracts some of the properties #[wasm_bindgen(typescript_custom_section)] -const TYPES_CHECK_WITH_OPTIONS: &str = r#" -export function check_with_options(entry_path: string, fs_resolver_js: (path: string) => string | undefined, options: TypeCheckOptions): WASMCheckOutput -"#; -#[wasm_bindgen(js_name = check_with_options, skip_typescript)] -pub fn check_wasm_with_options( +const TYPES_WASM_CHECK_OUTPUT: &str = r###" +interface WASMBuildOutput { + readonly artifacts: Array, + readonly diagnostics: DiagnosticsContainer, + get_type_at_position(path: string, pos: number): string; + get_type_at_position_debug(path: string, pos: number): string; +} +"###; +#[wasm_bindgen] +pub struct WASMBuildOutput { + artifacts: Vec, + check_output: WASMCheckOutput, +} + +#[wasm_bindgen] +impl WASMBuildOutput { + #[wasm_bindgen(js_name = artifacts, getter, skip_typescript)] + pub fn get_artifacts(&self) -> JsValue { + serde_wasm_bindgen::to_value(&self.artifacts).unwrap() + } + + #[wasm_bindgen(js_name = diagnostics, getter, skip_typescript)] + pub fn get_diagnostics(&self) -> JsValue { + self.check_output.get_diagnostics() + } + + pub fn get_type_at_position(&self, path: &str, pos: u32) -> Option { + self.check_output.get_type_at_position(path, pos) + } + + pub fn get_type_at_position_debug(&self, path: &str, pos: u32) -> Option { + self.check_output.get_type_at_position_debug(path, pos) + } +} + +#[wasm_bindgen(typescript_custom_section)] +const TYPES_EXPERIMENTAL_BUILD: &str = r###" +export function experimental_build( + entry_path: string, + fs_resolve_js: (path: string) => string | undefined, + config: BuildConfig | undefined +): WASMBuildOutput +"###; +#[wasm_bindgen(js_name = experimental_build, skip_typescript)] +pub fn experimental_build_wasm( entry_path: String, fs_resolver_js: &js_sys::Function, - options: JsValue, -) -> WASMCheckOutput { + config: JsValue, +) -> WASMBuildOutput { std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - let options: checker::TypeCheckOptions = - serde_wasm_bindgen::from_value(options).expect("invalid TypeCheckOptions"); let fs_resolver = |path: &std::path::Path| { let res = fs_resolver_js.call1(&JsValue::null(), &JsValue::from(path.display().to_string())); - res.ok().and_then(|res| res.as_string()) }; - WASMCheckOutput(crate::check::check(vec![entry_path.into()], &fs_resolver, None, options)) + + let config: crate::build::BuildConfig = if config.is_undefined() || config.is_null() { + Default::default() + } else { + serde_wasm_bindgen::from_value(config).expect("invalid BuildConfig") + }; + + let result = crate::build::build(vec![entry_path.into()], &fs_resolver, config); + + match result { + Ok(crate::build::BuildOutput { artifacts, check_output }) => { + WASMBuildOutput { artifacts, check_output: WASMCheckOutput(check_output) } + } + Err(crate::build::FailedBuildOutput(check_output)) => WASMBuildOutput { + artifacts: Default::default(), + check_output: WASMCheckOutput(check_output), + }, + } } #[wasm_bindgen(typescript_custom_section)] @@ -128,7 +156,6 @@ export function run_cli( cli_arguments: string[], read_from_file: (path: string) => string | undefined, write_to_file: (path: string, content: string) => void, - cli_input_resolver: (prompt: string) => string | undefined ): void "#; #[wasm_bindgen(js_name = run_cli, skip_typescript)] @@ -136,11 +163,10 @@ pub fn run_cli_wasm( cli_arguments: Box<[JsValue]>, read_from_file: &js_sys::Function, write_to_file: &js_sys::Function, - cli_input_resolver_js: &js_sys::Function, ) { std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - let arguments = cli_arguments.into_iter().flat_map(JsValue::as_string).collect::>(); + let arguments = cli_arguments.iter().flat_map(JsValue::as_string).collect::>(); let arguments = arguments.iter().map(String::as_str).collect::>(); let read_from_file = |path: &std::path::Path| { @@ -159,21 +185,12 @@ pub fn run_cli_wasm( .unwrap(); }; - let cli_input_resolver = |prompt: &str| { - cli_input_resolver_js - .call1(&JsValue::null(), &JsValue::from(prompt.to_owned())) - .ok() - .as_ref() - .and_then(JsValue::as_string) - }; - - crate::run_cli(&arguments, &read_from_file, write_to_file, cli_input_resolver); + crate::run_cli(&arguments, &read_from_file, write_to_file); } #[wasm_bindgen(typescript_custom_section)] -const TYPES_PARSE_EXPRESSION: &str = r#" -export function parse_expression(input: string): Expression | [string, Span] -"#; +const TYPES_PARSE_EXPRESSION: &str = + "export function parse_expression(input: string): Expression | [string, Span]"; #[wasm_bindgen(js_name = parse_expression, skip_typescript)] pub fn parse_expression_to_json(input: String) -> JsValue { use parser::{ASTNode, Expression}; @@ -189,9 +206,8 @@ pub fn parse_expression_to_json(input: String) -> JsValue { } #[wasm_bindgen(typescript_custom_section)] -const TYPES_PARSE_MODULE: &str = r#" -export function parse_module(input: string): Module | [string, Span] -"#; +const TYPES_PARSE_MODULE: &str = + "export function parse_module(input: string): Module | [string, Span]"; #[wasm_bindgen(js_name = parse_module, skip_typescript)] pub fn parse_module_to_json(input: String) -> JsValue { use parser::{ASTNode, Module}; @@ -237,9 +253,8 @@ pub fn parse_module_and_into_string( } } #[wasm_bindgen(typescript_custom_section)] -const TYPES_JUST_IMPORTS: &str = r#" -export function just_imports(input: string): string | [string, Span] -"#; +const TYPES_JUST_IMPORTS: &str = + "export function just_imports(input: string): string | [string, Span]"; #[wasm_bindgen(skip_typescript)] pub fn just_imports(input: String) -> JsValue { use parser::{ASTNode, Module};