Compare commits
31 Commits
fillet-err
...
franknoiro
Author | SHA1 | Date | |
---|---|---|---|
7ca51be5bc | |||
0bb5797377 | |||
c3097aa334 | |||
2cd0fcc9a7 | |||
5b653fb558 | |||
6a5b23f848 | |||
a480783ee8 | |||
bc0f5b5787 | |||
962eb0e376 | |||
ababe24b97 | |||
1bf7a2abd4 | |||
0ea4f94e8f | |||
6cc6130b6a | |||
8294903cd0 | |||
7b7379c3dd | |||
9acdf1e42f | |||
5dd95d27de | |||
1016b4c879 | |||
df6f571294 | |||
be05dd7ba1 | |||
bc22d888ee | |||
e6ae89ebf9 | |||
e7b23e1638 | |||
ce7a967f5f | |||
38446b5b2a | |||
48e1a8ed02 | |||
a059166b9c | |||
086a2b851d | |||
8e4c5fb24d | |||
6993893600 | |||
bfdf8babed |
@ -1,3 +1,3 @@
|
|||||||
[codespell]
|
[codespell]
|
||||||
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser
|
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser,fromM,FromM
|
||||||
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,./public/kcl-samples,./rust/kcl-lib/tests/kcl_samples,tsconfig.tsbuildinfo
|
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,./public/kcl-samples,./rust/kcl-lib/tests/kcl_samples,tsconfig.tsbuildinfo
|
||||||
|
24
.github/ci-cd-scripts/start-vector-macos.sh
vendored
Executable file
24
.github/ci-cd-scripts/start-vector-macos.sh
vendored
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Install vector
|
||||||
|
brew tap vectordotdev/brew && brew install vector
|
||||||
|
|
||||||
|
# Configure vector
|
||||||
|
mkdir -p /tmp/vector
|
||||||
|
cp .github/workflows/vector.toml /tmp/vector.toml
|
||||||
|
sed -i '' "s#OS_NAME#${OS_NAME}#g" /tmp/vector.toml
|
||||||
|
sed -i '' "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
|
||||||
|
sed -i '' "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
|
||||||
|
sed -i '' "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
|
||||||
|
sed -i '' "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
|
||||||
|
sed -i '' "s#GH_ACTIONS_AXIOM_TOKEN#${GH_ACTIONS_AXIOM_TOKEN}#g" /tmp/vector.toml
|
||||||
|
|
||||||
|
# Display settings
|
||||||
|
echo
|
||||||
|
echo 'Vector config:'
|
||||||
|
cat /tmp/vector.toml
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Start in the background
|
||||||
|
$(brew --prefix)/opt/vector/bin/vector --config /tmp/vector.toml &
|
24
.github/ci-cd-scripts/start-vector-ubuntu.sh
vendored
Executable file
24
.github/ci-cd-scripts/start-vector-ubuntu.sh
vendored
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Install vector
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev | bash -s -- -y
|
||||||
|
|
||||||
|
# Configure vector
|
||||||
|
mkdir -p /tmp/vector
|
||||||
|
cp .github/workflows/vector.toml /tmp/vector.toml
|
||||||
|
sed -i "s#OS_NAME#${OS_NAME}#g" /tmp/vector.toml
|
||||||
|
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
|
||||||
|
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
|
||||||
|
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
|
||||||
|
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
|
||||||
|
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${GH_ACTIONS_AXIOM_TOKEN}#g" /tmp/vector.toml
|
||||||
|
|
||||||
|
# Display settings
|
||||||
|
echo
|
||||||
|
echo 'Vector config:'
|
||||||
|
cat /tmp/vector.toml
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Start in background
|
||||||
|
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
|
2
.github/workflows/build-and-store-wasm.yml
vendored
2
.github/workflows/build-and-store-wasm.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
|||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
|
2
.github/workflows/build-apps.yml
vendored
2
.github/workflows/build-apps.yml
vendored
@ -77,7 +77,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
|
|
||||||
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
|
19
.github/workflows/cargo-test.yml
vendored
19
.github/workflows/cargo-test.yml
vendored
@ -34,20 +34,11 @@ jobs:
|
|||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
- name: Install vector
|
- name: Start Vector
|
||||||
run: |
|
run: .github/ci-cd-scripts/start-vector-ubuntu.sh
|
||||||
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
|
env:
|
||||||
chmod +x /tmp/vector.sh
|
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||||
/tmp/vector.sh -y -no-modify-path
|
OS_NAME: ${{ env.OS_NAME }}
|
||||||
mkdir -p /tmp/vector
|
|
||||||
cp .github/workflows/vector.toml /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
|
|
||||||
cat /tmp/vector.toml
|
|
||||||
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
|
|
||||||
- uses: taiki-e/install-action@cargo-llvm-cov
|
- uses: taiki-e/install-action@cargo-llvm-cov
|
||||||
- uses: taiki-e/install-action@nextest
|
- uses: taiki-e/install-action@nextest
|
||||||
- name: Install just
|
- name: Install just
|
||||||
|
28
.github/workflows/e2e-tests.yml
vendored
28
.github/workflows/e2e-tests.yml
vendored
@ -140,7 +140,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
|
|
||||||
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
@ -281,7 +281,7 @@ jobs:
|
|||||||
os:
|
os:
|
||||||
- "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
|
- "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
|
||||||
- namespace-profile-macos-8-cores
|
- namespace-profile-macos-8-cores
|
||||||
- windows-latest
|
- windows-latest-8-cores
|
||||||
shardIndex: [1, 2, 3, 4]
|
shardIndex: [1, 2, 3, 4]
|
||||||
shardTotal: [4]
|
shardTotal: [4]
|
||||||
# Disable macos and windows tests on hourly e2e tests since we only care
|
# Disable macos and windows tests on hourly e2e tests since we only care
|
||||||
@ -292,7 +292,7 @@ jobs:
|
|||||||
exclude:
|
exclude:
|
||||||
- os: namespace-profile-macos-8-cores
|
- os: namespace-profile-macos-8-cores
|
||||||
isScheduled: true
|
isScheduled: true
|
||||||
- os: windows-latest
|
- os: windows-latest-8-cores
|
||||||
isScheduled: true
|
isScheduled: true
|
||||||
# TODO: add ref here for main and latest release tag
|
# TODO: add ref here for main and latest release tag
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
@ -339,22 +339,12 @@ jobs:
|
|||||||
if: needs.conditions.outputs.should-run == 'true'
|
if: needs.conditions.outputs.should-run == 'true'
|
||||||
run: yarn tronb:vite:dev
|
run: yarn tronb:vite:dev
|
||||||
|
|
||||||
- name: Install vector
|
- name: Start Vector
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && contains(matrix.os, 'ubuntu') }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && !contains(matrix.os, 'windows') }}
|
||||||
shell: bash
|
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
|
||||||
run: |
|
env:
|
||||||
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
|
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||||
chmod +x /tmp/vector.sh
|
OS_NAME: ${{ env.OS_NAME }}
|
||||||
/tmp/vector.sh -y -no-modify-path
|
|
||||||
mkdir -p /tmp/vector
|
|
||||||
cp .github/workflows/vector.toml /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
|
|
||||||
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
|
|
||||||
cat /tmp/vector.toml
|
|
||||||
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||||
|
6
.github/workflows/static-analysis.yml
vendored
6
.github/workflows/static-analysis.yml
vendored
@ -51,7 +51,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
|
|
||||||
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ jobs:
|
|||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
|
|
||||||
- run: yarn install
|
- run: yarn install
|
||||||
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ jobs:
|
|||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
|
|
||||||
- run: yarn install
|
- run: yarn install
|
||||||
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
|
|
||||||
|
1
.github/workflows/vector.toml
vendored
1
.github/workflows/vector.toml
vendored
@ -8,6 +8,7 @@ include = ["/tmp/github-actions.log"]
|
|||||||
type = "remap"
|
type = "remap"
|
||||||
inputs = [ "github-actions-file" ]
|
inputs = [ "github-actions-file" ]
|
||||||
source = '''
|
source = '''
|
||||||
|
.platform = "OS_NAME"
|
||||||
.action = "GITHUB_WORKFLOW"
|
.action = "GITHUB_WORKFLOW"
|
||||||
.repo = "GITHUB_REPOSITORY"
|
.repo = "GITHUB_REPOSITORY"
|
||||||
.sha = "GITHUB_SHA"
|
.sha = "GITHUB_SHA"
|
||||||
|
@ -18,7 +18,7 @@ std::math::PI: number = 3.14159265358979323846264338327950288_
|
|||||||
circumference = 70
|
circumference = 70
|
||||||
|
|
||||||
exampleSketch = startSketchOn(XZ)
|
exampleSketch = startSketchOn(XZ)
|
||||||
|> circle(center = [0, 0], radius = circumference/ (2 * PI))
|
|> circle(center = [0, 0], radius = circumference / (2 * PI))
|
||||||
|
|
||||||
example = extrude(exampleSketch, length = 5)
|
example = extrude(exampleSketch, length = 5)
|
||||||
```
|
```
|
||||||
|
45
docs/kcl/fromCm.md
Normal file
45
docs/kcl/fromCm.md
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -65,11 +65,15 @@ layout: manual
|
|||||||
* [`chamfer`](kcl/chamfer)
|
* [`chamfer`](kcl/chamfer)
|
||||||
* [`circleThreePoint`](kcl/circleThreePoint)
|
* [`circleThreePoint`](kcl/circleThreePoint)
|
||||||
* [`close`](kcl/close)
|
* [`close`](kcl/close)
|
||||||
* [`cm`](kcl/cm)
|
|
||||||
* [`extrude`](kcl/extrude)
|
* [`extrude`](kcl/extrude)
|
||||||
* [`fillet`](kcl/fillet)
|
* [`fillet`](kcl/fillet)
|
||||||
* [`floor`](kcl/floor)
|
* [`floor`](kcl/floor)
|
||||||
* [`ft`](kcl/ft)
|
* [`fromCm`](kcl/fromCm)
|
||||||
|
* [`fromFt`](kcl/fromFt)
|
||||||
|
* [`fromInches`](kcl/fromInches)
|
||||||
|
* [`fromM`](kcl/fromM)
|
||||||
|
* [`fromMm`](kcl/fromMm)
|
||||||
|
* [`fromYd`](kcl/fromYd)
|
||||||
* [`getCommonEdge`](kcl/getCommonEdge)
|
* [`getCommonEdge`](kcl/getCommonEdge)
|
||||||
* [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge)
|
* [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge)
|
||||||
* [`getOppositeEdge`](kcl/getOppositeEdge)
|
* [`getOppositeEdge`](kcl/getOppositeEdge)
|
||||||
@ -77,7 +81,6 @@ layout: manual
|
|||||||
* [`helix`](kcl/std-helix)
|
* [`helix`](kcl/std-helix)
|
||||||
* [`hole`](kcl/hole)
|
* [`hole`](kcl/hole)
|
||||||
* [`hollow`](kcl/hollow)
|
* [`hollow`](kcl/hollow)
|
||||||
* [`inch`](kcl/inch)
|
|
||||||
* [`lastSegX`](kcl/lastSegX)
|
* [`lastSegX`](kcl/lastSegX)
|
||||||
* [`lastSegY`](kcl/lastSegY)
|
* [`lastSegY`](kcl/lastSegY)
|
||||||
* [`legAngX`](kcl/legAngX)
|
* [`legAngX`](kcl/legAngX)
|
||||||
@ -89,11 +92,9 @@ layout: manual
|
|||||||
* [`log`](kcl/log)
|
* [`log`](kcl/log)
|
||||||
* [`log10`](kcl/log10)
|
* [`log10`](kcl/log10)
|
||||||
* [`log2`](kcl/log2)
|
* [`log2`](kcl/log2)
|
||||||
* [`m`](kcl/m)
|
|
||||||
* [`map`](kcl/map)
|
* [`map`](kcl/map)
|
||||||
* [`max`](kcl/max)
|
* [`max`](kcl/max)
|
||||||
* [`min`](kcl/min)
|
* [`min`](kcl/min)
|
||||||
* [`mm`](kcl/mm)
|
|
||||||
* [`offsetPlane`](kcl/offsetPlane)
|
* [`offsetPlane`](kcl/offsetPlane)
|
||||||
* [`patternCircular2d`](kcl/patternCircular2d)
|
* [`patternCircular2d`](kcl/patternCircular2d)
|
||||||
* [`patternCircular3d`](kcl/patternCircular3d)
|
* [`patternCircular3d`](kcl/patternCircular3d)
|
||||||
@ -101,7 +102,6 @@ layout: manual
|
|||||||
* [`patternLinear3d`](kcl/patternLinear3d)
|
* [`patternLinear3d`](kcl/patternLinear3d)
|
||||||
* [`patternTransform`](kcl/patternTransform)
|
* [`patternTransform`](kcl/patternTransform)
|
||||||
* [`patternTransform2d`](kcl/patternTransform2d)
|
* [`patternTransform2d`](kcl/patternTransform2d)
|
||||||
* [`polar`](kcl/polar)
|
|
||||||
* [`polygon`](kcl/polygon)
|
* [`polygon`](kcl/polygon)
|
||||||
* [`pop`](kcl/pop)
|
* [`pop`](kcl/pop)
|
||||||
* [`pow`](kcl/pow)
|
* [`pow`](kcl/pow)
|
||||||
@ -137,12 +137,12 @@ layout: manual
|
|||||||
* [`translate`](kcl/translate)
|
* [`translate`](kcl/translate)
|
||||||
* [`xLine`](kcl/xLine)
|
* [`xLine`](kcl/xLine)
|
||||||
* [`yLine`](kcl/yLine)
|
* [`yLine`](kcl/yLine)
|
||||||
* [`yd`](kcl/yd)
|
|
||||||
* **std::math**
|
* **std::math**
|
||||||
* [`E`](kcl/consts/std-math-E)
|
* [`E`](kcl/consts/std-math-E)
|
||||||
* [`PI`](kcl/consts/std-math-PI)
|
* [`PI`](kcl/consts/std-math-PI)
|
||||||
* [`TAU`](kcl/consts/std-math-TAU)
|
* [`TAU`](kcl/consts/std-math-TAU)
|
||||||
* [`cos`](kcl/std-math-cos)
|
* [`cos`](kcl/std-math-cos)
|
||||||
|
* [`polar`](kcl/std-math-polar)
|
||||||
* [`sin`](kcl/std-math-sin)
|
* [`sin`](kcl/std-math-sin)
|
||||||
* [`tan`](kcl/std-math-tan)
|
* [`tan`](kcl/std-math-tan)
|
||||||
* **std::sketch**
|
* **std::sketch**
|
||||||
|
File diff suppressed because one or more lines are too long
@ -6,7 +6,7 @@ layout: manual
|
|||||||
|
|
||||||
# KCL Settings
|
# KCL Settings
|
||||||
|
|
||||||
There are three levels of settings available in the KittyCAD Design Studiolication:
|
There are three levels of settings available in Zoo Design Studio:
|
||||||
|
|
||||||
1. [User Settings](/docs/kcl/settings/user): Global settings that apply to all projects, stored in `user.toml`
|
1. [User Settings](/docs/kcl/settings/user): Global settings that apply to all projects, stored in `user.toml`
|
||||||
2. [Project Settings](/docs/kcl/settings/project): Settings specific to a project, stored in `project.toml`
|
2. [Project Settings](/docs/kcl/settings/project): Settings specific to a project, stored in `project.toml`
|
||||||
@ -14,7 +14,7 @@ There are three levels of settings available in the KittyCAD Design Studiolicati
|
|||||||
|
|
||||||
## Configuration Files
|
## Configuration Files
|
||||||
|
|
||||||
The KittyCAD Design Studio uses TOML files for configuration:
|
Zoo Design Studio uses TOML files for configuration:
|
||||||
|
|
||||||
* **User Settings**: `user.toml` - See [complete documentation](/docs/kcl/settings/user)
|
* **User Settings**: `user.toml` - See [complete documentation](/docs/kcl/settings/user)
|
||||||
* **Project Settings**: `project.toml` - See [complete documentation](/docs/kcl/settings/project)
|
* **Project Settings**: `project.toml` - See [complete documentation](/docs/kcl/settings/project)
|
||||||
|
@ -96,7 +96,7 @@ Permanently dismiss the banner warning to download the desktop app. This setting
|
|||||||
|
|
||||||
##### stream_idle_mode
|
##### stream_idle_mode
|
||||||
|
|
||||||
When the user is idle, and this is true, the stream will be torn down.
|
When the user is idle, teardown the stream after some time.
|
||||||
|
|
||||||
|
|
||||||
**Default:** None
|
**Default:** None
|
||||||
|
44
docs/kcl/std-math-polar.md
Normal file
44
docs/kcl/std-math-polar.md
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -79599,34 +79599,6 @@
|
|||||||
"exampleSketch = startSketchOn(-XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [10, 0])\n |> line(end = [0, 10])\n |> close()\n\nexample = extrude(exampleSketch, length = 10)"
|
"exampleSketch = startSketchOn(-XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [10, 0])\n |> line(end = [0, 10])\n |> close()\n\nexample = extrude(exampleSketch, length = 10)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "cm",
|
|
||||||
"summary": "Centimeters conversion factor for current projects units.",
|
|
||||||
"description": "No matter what units the current project uses, this function will always return the conversion factor to centimeters.\n\nFor example, if the current project uses inches, this function will return `0.393701`. If the current project uses millimeters, this function will return `10`. If the current project uses centimeters, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * cm()` is more readable that your intent is \"I want 10 centimeters\" than `10 * 10`, if the project settings are in millimeters.",
|
|
||||||
"tags": [
|
|
||||||
"units"
|
|
||||||
],
|
|
||||||
"keywordArguments": false,
|
|
||||||
"args": [],
|
|
||||||
"returnValue": {
|
|
||||||
"name": "",
|
|
||||||
"type": "number",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
|
||||||
"title": "double",
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"includeInSnippet": true,
|
|
||||||
"labelRequired": true
|
|
||||||
},
|
|
||||||
"unpublished": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"examples": [
|
|
||||||
"totalWidth = 10 * cm()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "e",
|
"name": "e",
|
||||||
"summary": "Return the value of Euler’s number `e`.",
|
"summary": "Return the value of Euler’s number `e`.",
|
||||||
@ -97490,14 +97462,28 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ft",
|
"name": "fromCm",
|
||||||
"summary": "Feet conversion factor for current projects units.",
|
"summary": "Converts a number from centimeters to the current default unit.",
|
||||||
"description": "No matter what units the current project uses, this function will always return the conversion factor to feet.\n\nFor example, if the current project uses inches, this function will return `12`. If the current project uses millimeters, this function will return `304.8`. If the current project uses feet, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * ft()` is more readable that your intent is \"I want 10 feet\" than `10 * 304.8`, if the project settings are in millimeters.",
|
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in centimeters.\n\nFor example, if the current file uses inches, `fromCm(1)` will return `0.393701`. If the current file uses millimeters, `fromCm(1)` will return `10`. If the current file uses centimeters, `fromCm(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromCm(10)` is more readable that your intent is \"I want 10 centimeters\" than `10 * 10`, if the file settings are in millimeters.",
|
||||||
"tags": [
|
"tags": [
|
||||||
"units"
|
"units"
|
||||||
],
|
],
|
||||||
"keywordArguments": false,
|
"keywordArguments": false,
|
||||||
"args": [],
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"returnValue": {
|
"returnValue": {
|
||||||
"name": "",
|
"name": "",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@ -97514,7 +97500,217 @@
|
|||||||
"unpublished": false,
|
"unpublished": false,
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"examples": [
|
"examples": [
|
||||||
"totalWidth = 10 * ft()"
|
"totalWidth = fromCm(10)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fromFt",
|
||||||
|
"summary": "Converts a number from feet to the current default unit.",
|
||||||
|
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in feet.\n\nFor example, if the current file uses inches, `fromFt(1)` will return `12`. If the current file uses millimeters, `fromFt(1)` will return `304.8`. If the current file uses feet, `fromFt(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromFt(10)` is more readable that your intent is \"I want 10 feet\" than `10 * 304.8`, if the file settings are in millimeters.",
|
||||||
|
"tags": [
|
||||||
|
"units"
|
||||||
|
],
|
||||||
|
"keywordArguments": false,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returnValue": {
|
||||||
|
"name": "",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
},
|
||||||
|
"unpublished": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"examples": [
|
||||||
|
"totalWidth = fromFt(10)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fromInches",
|
||||||
|
"summary": "Converts a number from inches to the current default unit.",
|
||||||
|
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in inches.\n\nFor example, if the current file uses inches, `fromInches(1)` will return `1`. If the current file uses millimeters, `fromInches(1)` will return `25.4`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromInches(10)` is more readable that your intent is \"I want 10 inches\" than `10 * 25.4`, if the file settings are in millimeters.",
|
||||||
|
"tags": [
|
||||||
|
"units"
|
||||||
|
],
|
||||||
|
"keywordArguments": false,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returnValue": {
|
||||||
|
"name": "",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
},
|
||||||
|
"unpublished": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"examples": [
|
||||||
|
"totalWidth = fromInches(10)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fromM",
|
||||||
|
"summary": "Converts a number from meters to the current default unit.",
|
||||||
|
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in meters.\n\nFor example, if the current file uses inches, `fromM(1)` will return `39.3701`. If the current file uses millimeters, `fromM(1)` will return `1000`. If the current file uses meters, `fromM(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromM(10)` is more readable that your intent is \"I want 10 meters\" than `10 * 1000`, if the file settings are in millimeters.",
|
||||||
|
"tags": [
|
||||||
|
"units"
|
||||||
|
],
|
||||||
|
"keywordArguments": false,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returnValue": {
|
||||||
|
"name": "",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
},
|
||||||
|
"unpublished": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"examples": [
|
||||||
|
"totalWidth = 10 * fromM(10)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fromMm",
|
||||||
|
"summary": "Converts a number from mm to the current default unit.",
|
||||||
|
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in millimeters.\n\nFor example, if the current file uses inches, `fromMm(1)` will return `1/25.4`. If the current file uses millimeters, `fromMm(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromMm(10)` is more readable that your intent is \"I want 10 millimeters\" than `10 * (1/25.4)`, if the file settings are in inches.",
|
||||||
|
"tags": [
|
||||||
|
"units"
|
||||||
|
],
|
||||||
|
"keywordArguments": false,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returnValue": {
|
||||||
|
"name": "",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
},
|
||||||
|
"unpublished": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"examples": [
|
||||||
|
"totalWidth = fromMm(10)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fromYd",
|
||||||
|
"summary": "Converts a number from yards to the current default unit.",
|
||||||
|
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in yards.\n\nFor example, if the current file uses inches, `fromYd(1)` will return `36`. If the current file uses millimeters, `fromYd(1)` will return `914.4`. If the current file uses yards, `fromYd(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromYd(10)` is more readable that your intent is \"I want 10 yards\" than `10 * 914.4`, if the file settings are in millimeters.",
|
||||||
|
"tags": [
|
||||||
|
"units"
|
||||||
|
],
|
||||||
|
"keywordArguments": false,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "input",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returnValue": {
|
||||||
|
"name": "",
|
||||||
|
"type": "number",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
|
"title": "double",
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"includeInSnippet": true,
|
||||||
|
"labelRequired": true
|
||||||
|
},
|
||||||
|
"unpublished": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"examples": [
|
||||||
|
"totalWidth = fromYd(10)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -106369,34 +106565,6 @@
|
|||||||
"import height, buildSketch from \"common.kcl\"\n\nplane = XZ\nmargin = 2\ns1 = buildSketch(plane, [0, 0])\ns2 = buildSketch(plane, [0, height() + margin])"
|
"import height, buildSketch from \"common.kcl\"\n\nplane = XZ\nmargin = 2\ns1 = buildSketch(plane, [0, 0])\ns2 = buildSketch(plane, [0, height() + margin])"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "inch",
|
|
||||||
"summary": "Inches conversion factor for current projects units.",
|
|
||||||
"description": "No matter what units the current project uses, this function will always return the conversion factor to inches.\n\nFor example, if the current project uses inches, this function will return `1`. If the current project uses millimeters, this function will return `25.4`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * inch()` is more readable that your intent is \"I want 10 inches\" than `10 * 25.4`, if the project settings are in millimeters.",
|
|
||||||
"tags": [
|
|
||||||
"units"
|
|
||||||
],
|
|
||||||
"keywordArguments": false,
|
|
||||||
"args": [],
|
|
||||||
"returnValue": {
|
|
||||||
"name": "",
|
|
||||||
"type": "number",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
|
||||||
"title": "double",
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"includeInSnippet": true,
|
|
||||||
"labelRequired": true
|
|
||||||
},
|
|
||||||
"unpublished": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"examples": [
|
|
||||||
"totalWidth = 10 * inch()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "int",
|
"name": "int",
|
||||||
"summary": "Convert a number to an integer.",
|
"summary": "Convert a number to an integer.",
|
||||||
@ -111321,7 +111489,7 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "TyF64",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double"
|
"format": "double"
|
||||||
},
|
},
|
||||||
@ -113005,7 +113173,7 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "TyF64",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double"
|
"format": "double"
|
||||||
},
|
},
|
||||||
@ -134361,34 +134529,6 @@
|
|||||||
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [log2(100), 0])\n |> line(end = [5, 8])\n |> line(end = [-10, 0])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
|
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [log2(100), 0])\n |> line(end = [5, 8])\n |> line(end = [-10, 0])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "m",
|
|
||||||
"summary": "Meters conversion factor for current projects units.",
|
|
||||||
"description": "No matter what units the current project uses, this function will always return the conversion factor to meters.\n\nFor example, if the current project uses inches, this function will return `39.3701`. If the current project uses millimeters, this function will return `1000`. If the current project uses meters, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * m()` is more readable that your intent is \"I want 10 meters\" than `10 * 1000`, if the project settings are in millimeters.",
|
|
||||||
"tags": [
|
|
||||||
"units"
|
|
||||||
],
|
|
||||||
"keywordArguments": false,
|
|
||||||
"args": [],
|
|
||||||
"returnValue": {
|
|
||||||
"name": "",
|
|
||||||
"type": "number",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
|
||||||
"title": "double",
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"includeInSnippet": true,
|
|
||||||
"labelRequired": true
|
|
||||||
},
|
|
||||||
"unpublished": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"examples": [
|
|
||||||
"totalWidth = 10 * m()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "map",
|
"name": "map",
|
||||||
"summary": "Apply a function to every element of a list.",
|
"summary": "Apply a function to every element of a list.",
|
||||||
@ -141853,34 +141993,6 @@
|
|||||||
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle = 70,\n length = min(15, 31, 4, 13, 22)\n }, %)\n |> line(end = [20, 0])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
|
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle = 70,\n length = min(15, 31, 4, 13, 22)\n }, %)\n |> line(end = [20, 0])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "mm",
|
|
||||||
"summary": "Millimeters conversion factor for current projects units.",
|
|
||||||
"description": "No matter what units the current project uses, this function will always return the conversion factor to millimeters.\n\nFor example, if the current project uses inches, this function will return `(1/25.4)`. If the current project uses millimeters, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * mm()` is more readable that your intent is \"I want 10 millimeters\" than `10 * (1/25.4)`, if the project settings are in inches.",
|
|
||||||
"tags": [
|
|
||||||
"units"
|
|
||||||
],
|
|
||||||
"keywordArguments": false,
|
|
||||||
"args": [],
|
|
||||||
"returnValue": {
|
|
||||||
"name": "",
|
|
||||||
"type": "number",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
|
||||||
"title": "double",
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"includeInSnippet": true,
|
|
||||||
"labelRequired": true
|
|
||||||
},
|
|
||||||
"unpublished": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"examples": [
|
|
||||||
"totalWidth = 10 * mm()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "offsetPlane",
|
"name": "offsetPlane",
|
||||||
"summary": "Offset a plane by a distance along its normal.",
|
"summary": "Offset a plane by a distance along its normal.",
|
||||||
@ -201537,76 +201649,6 @@
|
|||||||
"circumference = 70\n\nexampleSketch = startSketchOn(XZ)\n |> circle(center = [0, 0], radius = circumference / (2 * pi()))\n\nexample = extrude(exampleSketch, length = 5)"
|
"circumference = 70\n\nexampleSketch = startSketchOn(XZ)\n |> circle(center = [0, 0], radius = circumference / (2 * pi()))\n\nexample = extrude(exampleSketch, length = 5)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "polar",
|
|
||||||
"summary": "Convert polar/sphere (azimuth, elevation, distance) coordinates to cartesian (x/y/z grid) coordinates.",
|
|
||||||
"description": "",
|
|
||||||
"tags": [],
|
|
||||||
"keywordArguments": false,
|
|
||||||
"args": [
|
|
||||||
{
|
|
||||||
"name": "data",
|
|
||||||
"type": "PolarCoordsData",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
|
||||||
"title": "PolarCoordsData",
|
|
||||||
"description": "Data for polar coordinates.",
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"angle",
|
|
||||||
"length"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"angle": {
|
|
||||||
"description": "The angle of the line (in degrees).",
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"length": {
|
|
||||||
"description": "The length of the line.",
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/TyF64"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"definitions": {
|
|
||||||
"TyF64": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"includeInSnippet": true,
|
|
||||||
"labelRequired": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"returnValue": {
|
|
||||||
"name": "",
|
|
||||||
"type": "[number]",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
|
||||||
"title": "Array_size_2_of_double",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"maxItems": 2,
|
|
||||||
"minItems": 2
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"includeInSnippet": true,
|
|
||||||
"labelRequired": true
|
|
||||||
},
|
|
||||||
"unpublished": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"examples": [
|
|
||||||
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = polar({ angle = 30, length = 5 }), tag = $thing)\n |> line(end = [0, 5])\n |> line(end = [segEndX(thing), 0])\n |> line(end = [-20, 10])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "polygon",
|
"name": "polygon",
|
||||||
"summary": "Create a regular polygon with the specified number of sides that is either inscribed or circumscribed around a circle of the specified radius.",
|
"summary": "Create a regular polygon with the specified number of sides that is either inscribed or circumscribed around a circle of the specified radius.",
|
||||||
@ -258524,14 +258566,19 @@
|
|||||||
"type": "[number]",
|
"type": "[number]",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "Array_size_2_of_double",
|
"title": "Array_size_2_of_TyF64",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "number",
|
"$ref": "#/components/schemas/TyF64"
|
||||||
"format": "double"
|
|
||||||
},
|
},
|
||||||
"maxItems": 2,
|
"maxItems": 2,
|
||||||
"minItems": 2
|
"minItems": 2,
|
||||||
|
"definitions": {
|
||||||
|
"TyF64": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": true,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
@ -258577,7 +258624,7 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "TyF64",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double"
|
"format": "double"
|
||||||
},
|
},
|
||||||
@ -258625,7 +258672,7 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "TyF64",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double"
|
"format": "double"
|
||||||
},
|
},
|
||||||
@ -258673,7 +258720,7 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "TyF64",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double"
|
"format": "double"
|
||||||
},
|
},
|
||||||
@ -258721,14 +258768,19 @@
|
|||||||
"type": "[number]",
|
"type": "[number]",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "Array_size_2_of_double",
|
"title": "Array_size_2_of_TyF64",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "number",
|
"$ref": "#/components/schemas/TyF64"
|
||||||
"format": "double"
|
|
||||||
},
|
},
|
||||||
"maxItems": 2,
|
"maxItems": 2,
|
||||||
"minItems": 2
|
"minItems": 2,
|
||||||
|
"definitions": {
|
||||||
|
"TyF64": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": true,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
@ -258774,7 +258826,7 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "TyF64",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double"
|
"format": "double"
|
||||||
},
|
},
|
||||||
@ -258822,7 +258874,7 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "TyF64",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double"
|
"format": "double"
|
||||||
},
|
},
|
||||||
@ -336171,33 +336223,5 @@
|
|||||||
"examples": [
|
"examples": [
|
||||||
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> yLine(length = 15)\n |> angledLine({ angle = 30, length = 15 }, %)\n |> line(end = [8, -10])\n |> yLine(length = -5)\n |> close()\n\nexample = extrude(exampleSketch, length = 10)"
|
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> yLine(length = 15)\n |> angledLine({ angle = 30, length = 15 }, %)\n |> line(end = [8, -10])\n |> yLine(length = -5)\n |> close()\n\nexample = extrude(exampleSketch, length = 10)"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "yd",
|
|
||||||
"summary": "Yards conversion factor for current projects units.",
|
|
||||||
"description": "No matter what units the current project uses, this function will always return the conversion factor to yards.\n\nFor example, if the current project uses inches, this function will return `36`. If the current project uses millimeters, this function will return `914.4`. If the current project uses yards, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * yd()` is more readable that your intent is \"I want 10 yards\" than `10 * 914.4`, if the project settings are in millimeters.",
|
|
||||||
"tags": [
|
|
||||||
"units"
|
|
||||||
],
|
|
||||||
"keywordArguments": false,
|
|
||||||
"args": [],
|
|
||||||
"returnValue": {
|
|
||||||
"name": "",
|
|
||||||
"type": "number",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
|
||||||
"title": "double",
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"includeInSnippet": true,
|
|
||||||
"labelRequired": true
|
|
||||||
},
|
|
||||||
"unpublished": false,
|
|
||||||
"deprecated": false,
|
|
||||||
"examples": [
|
|
||||||
"totalWidth = 10 * yd()"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
title: "PolarCoordsData"
|
|
||||||
excerpt: "Data for polar coordinates."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
Data for polar coordinates.
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No |
|
|
||||||
| `length` |[`number`](/docs/kcl/types/number)| The length of the line. | No |
|
|
||||||
|
|
||||||
|
|
@ -38,7 +38,7 @@ test.describe('Point and click for boolean workflows', () => {
|
|||||||
path.resolve(
|
path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../../',
|
'../../',
|
||||||
'./rust/kcl-lib/e2e/executor/inputs/boolean-setup-with'
|
'./rust/kcl-lib/e2e/executor/inputs/boolean-setup-with-sketch-on-faces.kcl'
|
||||||
),
|
),
|
||||||
'utf-8'
|
'utf-8'
|
||||||
)
|
)
|
||||||
@ -46,8 +46,6 @@ test.describe('Point and click for boolean workflows', () => {
|
|||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
|
||||||
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Test coordinates for selection - these might need adjustment based on actual scene layout
|
// Test coordinates for selection - these might need adjustment based on actual scene layout
|
||||||
@ -77,6 +75,7 @@ test.describe('Point and click for boolean workflows', () => {
|
|||||||
|
|
||||||
// Select first object in the scene, expect there to be a pixel diff from the selection color change
|
// Select first object in the scene, expect there to be a pixel diff from the selection color change
|
||||||
await clickFirstObject({ pixelDiff: 50 })
|
await clickFirstObject({ pixelDiff: 50 })
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
// For subtract, we need to proceed to the next step before selecting the second object
|
// For subtract, we need to proceed to the next step before selecting the second object
|
||||||
if (operationName !== 'subtract') {
|
if (operationName !== 'subtract') {
|
||||||
@ -87,6 +86,8 @@ test.describe('Point and click for boolean workflows', () => {
|
|||||||
// Select second object
|
// Select second object
|
||||||
await clickSecondObject({ pixelDiff: 50 })
|
await clickSecondObject({ pixelDiff: 50 })
|
||||||
|
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
// Confirm the operation in the command bar
|
// Confirm the operation in the command bar
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { uuidv4 } from '@src/lib/utils'
|
|||||||
|
|
||||||
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
||||||
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
|
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||||
import { getUtils } from '@e2e/playwright/test-utils'
|
import { getUtils } from '@e2e/playwright/test-utils'
|
||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ test.describe(
|
|||||||
page: Page,
|
page: Page,
|
||||||
homePage: HomePageFixture,
|
homePage: HomePageFixture,
|
||||||
scene: SceneFixture,
|
scene: SceneFixture,
|
||||||
|
toolbar: ToolbarFixture,
|
||||||
plane: string,
|
plane: string,
|
||||||
clickCoords: { x: number; y: number }
|
clickCoords: { x: number; y: number }
|
||||||
) => {
|
) => {
|
||||||
@ -59,9 +61,12 @@ test.describe(
|
|||||||
await u.sendCustomCmd(updateCamCommand)
|
await u.sendCustomCmd(updateCamCommand)
|
||||||
|
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
await page.mouse.click(clickCoords.x, clickCoords.y)
|
await page.mouse.click(clickCoords.x, clickCoords.y)
|
||||||
await page.waitForTimeout(600) // wait for animation
|
await page.waitForTimeout(600) // wait for animation
|
||||||
|
|
||||||
|
await toolbar.waitUntilSketchingReady()
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'line Line', exact: true })
|
page.getByRole('button', { name: 'line Line', exact: true })
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
@ -117,11 +122,12 @@ test.describe(
|
|||||||
]
|
]
|
||||||
|
|
||||||
for (const config of planeConfigs) {
|
for (const config of planeConfigs) {
|
||||||
test(config.plane, async ({ page, homePage, scene }) => {
|
test(config.plane, async ({ page, homePage, scene, toolbar }) => {
|
||||||
await sketchOnPlaneAndBackSideTest(
|
await sketchOnPlaneAndBackSideTest(
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
toolbar,
|
||||||
config.plane,
|
config.plane,
|
||||||
config.coords
|
config.coords
|
||||||
)
|
)
|
||||||
|
@ -15,6 +15,7 @@ test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
|
|||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
|
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Ensure no badge is present
|
// Ensure no badge is present
|
||||||
const codePaneButtonHolder = page.locator('#code-button-holder')
|
const codePaneButtonHolder = page.locator('#code-button-holder')
|
||||||
@ -171,6 +172,8 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
// Load the app with the working starter code
|
// Load the app with the working starter code
|
||||||
await context.addInitScript((code) => {
|
await context.addInitScript((code) => {
|
||||||
@ -180,9 +183,7 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
// FIXME: await scene.waitForExecutionDone() does not work. It still fails.
|
await scene.settled(cmdBar)
|
||||||
// I needed to increase this timeout to get this to pass.
|
|
||||||
await page.waitForTimeout(10000)
|
|
||||||
|
|
||||||
// Ensure badge is present
|
// Ensure badge is present
|
||||||
const codePaneButtonHolder = page.locator('#code-button-holder')
|
const codePaneButtonHolder = page.locator('#code-button-holder')
|
||||||
|
@ -317,9 +317,13 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
|
|||||||
test('Can switch between sketch tools via command bar', async ({
|
test('Can switch between sketch tools via command bar', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
toolbar,
|
||||||
}) => {
|
}) => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const sketchButton = page.getByRole('button', { name: 'Start Sketch' })
|
const sketchButton = page.getByRole('button', { name: 'Start Sketch' })
|
||||||
const cmdBarButton = page.getByRole('button', { name: 'Commands' })
|
const cmdBarButton = page.getByRole('button', { name: 'Commands' })
|
||||||
@ -343,7 +347,9 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
// Start a sketch
|
// Start a sketch
|
||||||
await sketchButton.click()
|
await sketchButton.click()
|
||||||
|
|
||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
|
await toolbar.waitUntilSketchingReady()
|
||||||
|
|
||||||
// Switch between sketch tools via the command bar
|
// Switch between sketch tools via the command bar
|
||||||
await expect(lineToolButton).toHaveAttribute('aria-pressed', 'true')
|
await expect(lineToolButton).toHaveAttribute('aria-pressed', 'true')
|
||||||
|
@ -11,7 +11,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
test(
|
test(
|
||||||
'export works on the first try',
|
'export works on the first try',
|
||||||
{ tag: ['@electron', '@skipLocalEngine'] },
|
{ tag: ['@electron', '@skipLocalEngine'] },
|
||||||
async ({ page, context, scene, tronApp }, testInfo) => {
|
async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
}
|
}
|
||||||
@ -32,53 +32,41 @@ test(
|
|||||||
})
|
})
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
await test.step('on open of project', async () => {
|
await test.step('on open of project', async () => {
|
||||||
await expect(page.getByText(`bracket`)).toBeVisible()
|
// Open the project
|
||||||
|
const projectName = page.getByText(`bracket`)
|
||||||
|
await expect(projectName).toBeVisible()
|
||||||
|
await projectName.click()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// open the project
|
// Expect zero errors in gutter
|
||||||
await page.getByText(`bracket`).click()
|
|
||||||
|
|
||||||
// expect zero errors in guter
|
|
||||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||||
|
|
||||||
// export the model
|
// Click the export button
|
||||||
const exportButton = page.getByTestId('export-pane-button')
|
const exportButton = page.getByTestId('export-pane-button')
|
||||||
await expect(exportButton).toBeVisible()
|
await expect(exportButton).toBeVisible()
|
||||||
|
|
||||||
await scene.waitForExecutionDone()
|
|
||||||
|
|
||||||
const gltfOption = page.getByText('glTF')
|
|
||||||
const submitButton = page.getByText('Confirm Export')
|
|
||||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
|
||||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
|
||||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
|
||||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
|
||||||
// The open file's name is `main.kcl`, so the export file name should be `main.gltf`
|
|
||||||
const exportFileName = `main.gltf`
|
|
||||||
|
|
||||||
// Click the export button
|
|
||||||
await exportButton.click()
|
await exportButton.click()
|
||||||
|
|
||||||
|
// Select the first format option
|
||||||
|
const gltfOption = cmdBar.selectOption({ name: 'glTF' })
|
||||||
|
const exportFileName = `main.gltf` // source file is named `main.kcl`
|
||||||
await expect(gltfOption).toBeVisible()
|
await expect(gltfOption).toBeVisible()
|
||||||
await expect(page.getByText('STL')).toBeVisible()
|
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
|
const submitButton = page.getByText('Confirm Export')
|
||||||
await expect(submitButton).toBeVisible()
|
await expect(submitButton).toBeVisible()
|
||||||
|
|
||||||
await page.waitForTimeout(500)
|
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Find the toast.
|
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
|
const exportingToastMessage = page.getByText(`Exporting...`)
|
||||||
|
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
await expect(exportingToastMessage).toBeVisible()
|
||||||
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
// Expect it to succeed.
|
// Expect it to succeed
|
||||||
|
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||||
|
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||||
await expect(errorToastMessage).not.toBeVisible()
|
await expect(errorToastMessage).not.toBeVisible()
|
||||||
await expect(engineErrorToastMessage).not.toBeVisible()
|
await expect(engineErrorToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
@ -86,6 +74,7 @@ test(
|
|||||||
await expect(successToastMessage).toBeVisible()
|
await expect(successToastMessage).toBeVisible()
|
||||||
await expect(exportingToastMessage).not.toBeVisible()
|
await expect(exportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
|
// Check for the exported file
|
||||||
const firstFileFullPath = path.resolve(
|
const firstFileFullPath = path.resolve(
|
||||||
getPlaywrightDownloadDir(tronApp.projectDirName),
|
getPlaywrightDownloadDir(tronApp.projectDirName),
|
||||||
exportFileName
|
exportFileName
|
||||||
@ -112,60 +101,50 @@ test(
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await u.openFilePanel()
|
await u.openFilePanel()
|
||||||
|
|
||||||
|
// Click on the other file
|
||||||
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
|
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
|
||||||
|
|
||||||
// Click the file
|
|
||||||
await otherKclButton.click()
|
await otherKclButton.click()
|
||||||
|
|
||||||
// Close the file pane
|
// Close the file pane
|
||||||
await u.closeFilePanel()
|
await u.closeFilePanel()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// FIXME: await scene.waitForExecutionDone() does not work. The modeling indicator stays in -receive-reliable and not execution done
|
// Expect zero errors in gutter
|
||||||
await page.waitForTimeout(10000)
|
|
||||||
|
|
||||||
// expect zero errors in guter
|
|
||||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||||
|
|
||||||
// export the model
|
// Click the export button
|
||||||
const exportButton = page.getByTestId('export-pane-button')
|
const exportButton = page.getByTestId('export-pane-button')
|
||||||
await expect(exportButton).toBeVisible()
|
await expect(exportButton).toBeVisible()
|
||||||
|
|
||||||
const gltfOption = page.getByText('glTF')
|
|
||||||
const submitButton = page.getByText('Confirm Export')
|
|
||||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
|
||||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
|
||||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
|
||||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
|
||||||
// The open file's name is `other.kcl`, so the export file name should be `other.gltf`
|
|
||||||
const exportFileName = `other.gltf`
|
|
||||||
|
|
||||||
// Click the export button
|
|
||||||
await exportButton.click()
|
await exportButton.click()
|
||||||
|
|
||||||
|
// Select the first format option
|
||||||
|
const gltfOption = cmdBar.selectOption({ name: 'glTF' })
|
||||||
|
const exportFileName = `other.gltf` // source file is named `other.kcl`
|
||||||
await expect(gltfOption).toBeVisible()
|
await expect(gltfOption).toBeVisible()
|
||||||
await expect(page.getByText('STL')).toBeVisible()
|
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
|
const submitButton = page.getByText('Confirm Export')
|
||||||
await expect(submitButton).toBeVisible()
|
await expect(submitButton).toBeVisible()
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Find the toast.
|
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
|
const exportingToastMessage = page.getByText(`Exporting...`)
|
||||||
|
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
await expect(exportingToastMessage).toBeVisible()
|
||||||
|
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
|
// Expect it to succeed
|
||||||
|
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||||
|
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||||
|
await expect(errorToastMessage).not.toBeVisible()
|
||||||
|
await expect(engineErrorToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
await test.step('Check the success toast message shows and nothing else', async () =>
|
await expect(successToastMessage).toBeVisible()
|
||||||
Promise.all([
|
await expect(exportingToastMessage).not.toBeVisible()
|
||||||
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
|
||||||
expect(errorToastMessage).not.toBeVisible(),
|
|
||||||
expect(engineErrorToastMessage).not.toBeVisible(),
|
|
||||||
expect(successToastMessage).toBeVisible(),
|
|
||||||
expect(exportingToastMessage).not.toBeVisible(),
|
|
||||||
]))
|
|
||||||
|
|
||||||
|
// Check for the exported file=
|
||||||
const secondFileFullPath = path.resolve(
|
const secondFileFullPath = path.resolve(
|
||||||
getPlaywrightDownloadDir(tronApp.projectDirName),
|
getPlaywrightDownloadDir(tronApp.projectDirName),
|
||||||
exportFileName
|
exportFileName
|
||||||
|
@ -78,12 +78,14 @@ sketch001 = startSketchOn(XY)
|
|||||||
|
|
||||||
// Ensure we execute the first time.
|
// Ensure we execute the first time.
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
await expect(
|
await expect
|
||||||
page.locator('[data-receive-command-type="scene_clear_all"]')
|
.poll(() =>
|
||||||
).toHaveCount(1)
|
page.locator('[data-receive-command-type="scene_clear_all"]').count()
|
||||||
await expect(
|
)
|
||||||
page.locator('[data-message-type="execution-done"]')
|
.toBe(1)
|
||||||
).toHaveCount(2)
|
await expect
|
||||||
|
.poll(() => page.locator('[data-message-type="execution-done"]').count())
|
||||||
|
.toBe(2)
|
||||||
|
|
||||||
// Add whitespace to the end of the code.
|
// Add whitespace to the end of the code.
|
||||||
await u.codeLocator.click()
|
await u.codeLocator.click()
|
||||||
@ -110,12 +112,14 @@ sketch001 = startSketchOn(XY)
|
|||||||
test('ensure we use the cache, and do not clear on append', async ({
|
test('ensure we use the cache, and do not clear on append', async ({
|
||||||
homePage,
|
homePage,
|
||||||
page,
|
page,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await u.codeLocator.click()
|
await u.codeLocator.click()
|
||||||
await page.keyboard.type(`sketch001 = startSketchOn(XY)
|
await page.keyboard.type(`sketch001 = startSketchOn(XY)
|
||||||
@ -499,7 +503,7 @@ sketch_001 = startSketchOn(XY)
|
|||||||
await page.keyboard.press('ArrowLeft')
|
await page.keyboard.press('ArrowLeft')
|
||||||
await page.keyboard.press('ArrowRight')
|
await page.keyboard.press('ArrowRight')
|
||||||
|
|
||||||
await scene.waitForExecutionDone()
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
// error in guter
|
// error in guter
|
||||||
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
|
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
|
||||||
@ -1315,4 +1319,38 @@ sketch001 = startSketchOn(XZ)
|
|||||||
const element = page.locator('[data-overlay-index="1"]')
|
const element = page.locator('[data-overlay-index="1"]')
|
||||||
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
|
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test(`Only show axis planes when there are no errors`, async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
|
||||||
|
|
||||||
|
sketch002 = startSketchOn(XZ)
|
||||||
|
profile002 = circle(sketch002, center = [-100.0, 100.0], radius = 50.0)
|
||||||
|
extrude001 = extrude(profile002, length = 0)` // length = 0 is causing the error
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const viewportSize = { width: 1200, height: 800 }
|
||||||
|
await page.setBodyDimensions(viewportSize)
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
TEST_COLORS.DARK_MODE_BKGD,
|
||||||
|
// This is a position where the blue part of the axis plane is visible if its rendered
|
||||||
|
{ x: viewportSize.width * 0.75, y: viewportSize.height * 0.2 },
|
||||||
|
15
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -64,7 +64,7 @@ test.describe('Feature Tree pane', () => {
|
|||||||
test(
|
test(
|
||||||
'User can go to definition and go to function definition',
|
'User can go to definition and go to function definition',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, homePage, scene, editor, toolbar }) => {
|
async ({ context, homePage, scene, editor, toolbar, cmdBar, page }) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'test-sample')
|
const bracketDir = join(dir, 'test-sample')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -86,9 +86,13 @@ test.describe('Feature Tree pane', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await homePage.openProject('test-sample')
|
await homePage.openProject('test-sample')
|
||||||
await scene.waitForExecutionDone()
|
await scene.connectionEstablished()
|
||||||
await editor.closePane()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await toolbar.openFeatureTreePane()
|
await toolbar.openFeatureTreePane()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Feature tree').count())
|
||||||
|
.toBeGreaterThan(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function testViewSource({
|
async function testViewSource({
|
||||||
@ -254,7 +258,7 @@ test.describe('Feature Tree pane', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await homePage.openProject('test-sample')
|
await homePage.openProject('test-sample')
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
await toolbar.openFeatureTreePane()
|
await toolbar.openFeatureTreePane()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -339,7 +343,7 @@ test.describe('Feature Tree pane', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await homePage.openProject('test-sample')
|
await homePage.openProject('test-sample')
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
await toolbar.openFeatureTreePane()
|
await toolbar.openFeatureTreePane()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -414,8 +418,7 @@ profile003 = startProfileAt([0, -4.93], sketch001)
|
|||||||
const planeColor: [number, number, number] = [74, 74, 74]
|
const planeColor: [number, number, number] = [74, 74, 74]
|
||||||
|
|
||||||
await homePage.openProject('test-sample')
|
await homePage.openProject('test-sample')
|
||||||
// FIXME: @lf94 has a better way to verify execution completion, in a PR rn
|
await scene.settled(cmdBar)
|
||||||
await scene.waitForExecutionDone()
|
|
||||||
|
|
||||||
await test.step(`Verify we see the sketch`, async () => {
|
await test.step(`Verify we see the sketch`, async () => {
|
||||||
await scene.expectPixelColor(sketchColor, testPoint, 10)
|
await scene.expectPixelColor(sketchColor, testPoint, 10)
|
||||||
|
@ -47,6 +47,7 @@ test.describe('integrations tests', () => {
|
|||||||
await scene.connectionEstablished()
|
await scene.connectionEstablished()
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
await clickObj()
|
await clickObj()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await scene.moveNoWhere()
|
await scene.moveNoWhere()
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
activeLines: [
|
activeLines: [
|
||||||
@ -72,11 +73,11 @@ test.describe('integrations tests', () => {
|
|||||||
})
|
})
|
||||||
await test.step('setup for next assertion', async () => {
|
await test.step('setup for next assertion', async () => {
|
||||||
await toolbar.openFile('main.kcl')
|
await toolbar.openFile('main.kcl')
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
await clickObj()
|
await clickObj()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await scene.moveNoWhere()
|
await scene.moveNoWhere()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
activeLines: [
|
activeLines: [
|
||||||
'|>startProfileAt([75.8,317.2],%)//[$startCapTag,$EndCapTag]',
|
'|>startProfileAt([75.8,317.2],%)//[$startCapTag,$EndCapTag]',
|
||||||
@ -89,7 +90,7 @@ test.describe('integrations tests', () => {
|
|||||||
await toolbar.expectFileTreeState(['main.kcl', fileName])
|
await toolbar.expectFileTreeState(['main.kcl', fileName])
|
||||||
})
|
})
|
||||||
await test.step('check sketch mode is exited when opening a different file', async () => {
|
await test.step('check sketch mode is exited when opening a different file', async () => {
|
||||||
await toolbar.openFile(fileName, { wait: false })
|
await toolbar.openFile(fileName)
|
||||||
|
|
||||||
// check we're out of sketch mode
|
// check we're out of sketch mode
|
||||||
await expect(toolbar.exitSketchBtn).not.toBeVisible()
|
await expect(toolbar.exitSketchBtn).not.toBeVisible()
|
||||||
|
@ -112,22 +112,16 @@ export class CmdBarFixture {
|
|||||||
* and assumes we are past the `pickCommand` step.
|
* and assumes we are past the `pickCommand` step.
|
||||||
*/
|
*/
|
||||||
progressCmdBar = async (shouldFuzzProgressMethod = true) => {
|
progressCmdBar = async (shouldFuzzProgressMethod = true) => {
|
||||||
// FIXME: Progressing the command bar is a race condition. We have an async useEffect that reports the final state via useCalculateKclExpression. If this does not run quickly enough, it will not "fail" the continue because you can press continue if the state is not ready. E2E tests do not know this.
|
await this.page.waitForTimeout(2000)
|
||||||
// Wait 1250ms to assume the await executeAst of the KCL input field is finished
|
const arrowButton = this.page.getByRole('button', {
|
||||||
await this.page.waitForTimeout(1250)
|
name: 'arrow right Continue',
|
||||||
if (shouldFuzzProgressMethod || Math.random() > 0.5) {
|
})
|
||||||
const arrowButton = this.page.getByRole('button', {
|
if (await arrowButton.isVisible()) {
|
||||||
name: 'arrow right Continue',
|
await arrowButton.click()
|
||||||
})
|
|
||||||
if (await arrowButton.isVisible()) {
|
|
||||||
await arrowButton.click()
|
|
||||||
} else {
|
|
||||||
await this.page
|
|
||||||
.getByRole('button', { name: 'checkmark Submit command' })
|
|
||||||
.click()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
await this.page.keyboard.press('Enter')
|
await this.page
|
||||||
|
.getByRole('button', { name: 'checkmark Submit command' })
|
||||||
|
.click()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ export class AuthenticatedApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async initialise(code = '') {
|
async initialise(code = '') {
|
||||||
await setup(this.context, this.page, this.testInfo)
|
const testDir = this.testInfo.outputPath('electron-test-projects-dir')
|
||||||
|
await setup(this.context, this.page, testDir, this.testInfo)
|
||||||
const u = await getUtils(this.page)
|
const u = await getUtils(this.page)
|
||||||
|
|
||||||
await this.page.addInitScript(async (code) => {
|
await this.page.addInitScript(async (code) => {
|
||||||
@ -102,11 +103,11 @@ export class ElectronZoo {
|
|||||||
return resolve(undefined)
|
return resolve(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Date.now() - timeA > 10000) {
|
if (Date.now() - timeA > 3000) {
|
||||||
return resolve(undefined)
|
return resolve(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(checkDisconnected, 0)
|
setTimeout(checkDisconnected, 1)
|
||||||
}
|
}
|
||||||
checkDisconnected()
|
checkDisconnected()
|
||||||
})
|
})
|
||||||
@ -128,11 +129,9 @@ export class ElectronZoo {
|
|||||||
const that = this
|
const that = this
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
timeout: 120000,
|
|
||||||
args: ['.', '--no-sandbox'],
|
args: ['.', '--no-sandbox'],
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
TEST_SETTINGS_FILE_KEY: this.projectDirName,
|
|
||||||
IS_PLAYWRIGHT: 'true',
|
IS_PLAYWRIGHT: 'true',
|
||||||
},
|
},
|
||||||
...(process.env.ELECTRON_OVERRIDE_DIST_PATH
|
...(process.env.ELECTRON_OVERRIDE_DIST_PATH
|
||||||
@ -200,7 +199,14 @@ export class ElectronZoo {
|
|||||||
|
|
||||||
await this.context.tracing.startChunk()
|
await this.context.tracing.startChunk()
|
||||||
|
|
||||||
await setup(this.context, this.page, testInfo)
|
// THIS IS ABSOLUTELY NECESSARY TO CHANGE THE PROJECT DIRECTORY BETWEEN
|
||||||
|
// TESTS BECAUSE OF THE ELECTRON INSTANCE REUSE.
|
||||||
|
await this.electron?.evaluate(({ app }, projectDirName) => {
|
||||||
|
// @ts-ignore can't declaration merge see main.ts
|
||||||
|
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
|
||||||
|
}, this.projectDirName)
|
||||||
|
|
||||||
|
await setup(this.context, this.page, this.projectDirName, testInfo)
|
||||||
|
|
||||||
await this.cleanProjectDir()
|
await this.cleanProjectDir()
|
||||||
|
|
||||||
@ -250,11 +256,6 @@ export class ElectronZoo {
|
|||||||
// return app.reuseWindowForTest();
|
// return app.reuseWindowForTest();
|
||||||
// });
|
// });
|
||||||
|
|
||||||
await this.electron?.evaluate(({ app }, projectDirName) => {
|
|
||||||
// @ts-ignore can't declaration merge see main.ts
|
|
||||||
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
|
|
||||||
}, this.projectDirName)
|
|
||||||
|
|
||||||
// Always start at the root view
|
// Always start at the root view
|
||||||
await this.page.goto(this.firstUrl)
|
await this.page.goto(this.firstUrl)
|
||||||
|
|
||||||
@ -278,8 +279,9 @@ export class ElectronZoo {
|
|||||||
// Not a problem if it already exists.
|
// Not a problem if it already exists.
|
||||||
}
|
}
|
||||||
|
|
||||||
const tempSettingsFilePath = path.join(
|
const tempSettingsFilePath = path.resolve(
|
||||||
this.projectDirName,
|
this.projectDirName,
|
||||||
|
'..',
|
||||||
SETTINGS_FILE_NAME
|
SETTINGS_FILE_NAME
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,21 +43,13 @@ type DragFromHandler = (
|
|||||||
export class SceneFixture {
|
export class SceneFixture {
|
||||||
public page: Page
|
public page: Page
|
||||||
public streamWrapper!: Locator
|
public streamWrapper!: Locator
|
||||||
public loadingIndicator!: Locator
|
|
||||||
public networkToggleConnected!: Locator
|
public networkToggleConnected!: Locator
|
||||||
public startEditSketchBtn!: Locator
|
public startEditSketchBtn!: Locator
|
||||||
|
|
||||||
get exeIndicator() {
|
|
||||||
return this.page
|
|
||||||
.getByTestId('model-state-indicator-execution-done')
|
|
||||||
.or(this.page.getByTestId('model-state-indicator-receive-reliable'))
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page
|
this.page = page
|
||||||
this.streamWrapper = page.getByTestId('stream')
|
this.streamWrapper = page.getByTestId('stream')
|
||||||
this.networkToggleConnected = page.getByTestId('network-toggle-ok')
|
this.networkToggleConnected = page.getByTestId('network-toggle-ok')
|
||||||
this.loadingIndicator = this.streamWrapper.getByTestId('loading')
|
|
||||||
this.startEditSketchBtn = page
|
this.startEditSketchBtn = page
|
||||||
.getByRole('button', { name: 'Start Sketch' })
|
.getByRole('button', { name: 'Start Sketch' })
|
||||||
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
||||||
@ -231,10 +223,6 @@ export class SceneFixture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForExecutionDone = async () => {
|
|
||||||
await expect(this.exeIndicator).toBeVisible({ timeout: 30000 })
|
|
||||||
}
|
|
||||||
|
|
||||||
connectionEstablished = async () => {
|
connectionEstablished = async () => {
|
||||||
const timeout = 30000
|
const timeout = 30000
|
||||||
await expect(this.networkToggleConnected).toBeVisible({ timeout })
|
await expect(this.networkToggleConnected).toBeVisible({ timeout })
|
||||||
@ -243,6 +231,9 @@ export class SceneFixture {
|
|||||||
settled = async (cmdBar: CmdBarFixture) => {
|
settled = async (cmdBar: CmdBarFixture) => {
|
||||||
const u = await getUtils(this.page)
|
const u = await getUtils(this.page)
|
||||||
|
|
||||||
|
await expect(this.startEditSketchBtn).not.toBeDisabled()
|
||||||
|
await expect(this.startEditSketchBtn).toBeVisible()
|
||||||
|
|
||||||
await cmdBar.openCmdBar()
|
await cmdBar.openCmdBar()
|
||||||
await cmdBar.chooseCommand('Settings · app · show debug panel')
|
await cmdBar.chooseCommand('Settings · app · show debug panel')
|
||||||
await cmdBar.selectOption({ name: 'on' }).click()
|
await cmdBar.selectOption({ name: 'on' }).click()
|
||||||
@ -250,10 +241,6 @@ export class SceneFixture {
|
|||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
await this.waitForExecutionDone()
|
|
||||||
await expect(this.startEditSketchBtn).not.toBeDisabled()
|
|
||||||
await expect(this.startEditSketchBtn).toBeVisible()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expectPixelColor = async (
|
expectPixelColor = async (
|
||||||
|
@ -44,6 +44,7 @@ export class ToolbarFixture {
|
|||||||
featureTreePane!: Locator
|
featureTreePane!: Locator
|
||||||
gizmo!: Locator
|
gizmo!: Locator
|
||||||
gizmoDisabled!: Locator
|
gizmoDisabled!: Locator
|
||||||
|
insertButton!: Locator
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page
|
this.page = page
|
||||||
@ -78,18 +79,14 @@ export class ToolbarFixture {
|
|||||||
// element or two different elements can represent these states.
|
// element or two different elements can represent these states.
|
||||||
this.gizmo = page.getByTestId('gizmo')
|
this.gizmo = page.getByTestId('gizmo')
|
||||||
this.gizmoDisabled = page.getByTestId('gizmo-disabled')
|
this.gizmoDisabled = page.getByTestId('gizmo-disabled')
|
||||||
|
|
||||||
|
this.insertButton = page.getByTestId('insert-pane-button')
|
||||||
}
|
}
|
||||||
|
|
||||||
get logoLink() {
|
get logoLink() {
|
||||||
return this.page.getByTestId('app-logo')
|
return this.page.getByTestId('app-logo')
|
||||||
}
|
}
|
||||||
|
|
||||||
get exeIndicator() {
|
|
||||||
return this.page
|
|
||||||
.getByTestId('model-state-indicator-receive-reliable')
|
|
||||||
.or(this.page.getByTestId('model-state-indicator-execution-done'))
|
|
||||||
}
|
|
||||||
|
|
||||||
startSketchPlaneSelection = async () =>
|
startSketchPlaneSelection = async () =>
|
||||||
doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500)
|
doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500)
|
||||||
|
|
||||||
@ -165,16 +162,10 @@ export class ToolbarFixture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Opens file by it's name and waits for execution to finish
|
* Opens file by it's name
|
||||||
*/
|
*/
|
||||||
openFile = async (
|
openFile = async (fileName: string) => {
|
||||||
fileName: string,
|
|
||||||
{ wait }: { wait?: boolean } = { wait: true }
|
|
||||||
) => {
|
|
||||||
await this.filePane.getByText(fileName).click()
|
await this.filePane.getByText(fileName).click()
|
||||||
if (wait) {
|
|
||||||
await expect(this.exeIndicator).toBeVisible({ timeout: 15_000 })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
selectCenterRectangle = async () => {
|
selectCenterRectangle = async () => {
|
||||||
await this.page
|
await this.page
|
||||||
|
@ -10,6 +10,7 @@ test.describe('Import UI tests', () => {
|
|||||||
toolbar,
|
toolbar,
|
||||||
scene,
|
scene,
|
||||||
editor,
|
editor,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const projectDir = path.join(dir, 'import-test')
|
const projectDir = path.join(dir, 'import-test')
|
||||||
@ -61,7 +62,7 @@ sketch002 = startSketchOn(extrude001, seg01)`
|
|||||||
})
|
})
|
||||||
|
|
||||||
await homePage.openProject('import-test')
|
await homePage.openProject('import-test')
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await scene.moveCameraTo(
|
await scene.moveCameraTo(
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
test(
|
test(
|
||||||
'When machine-api server not found butt is disabled and shows the reason',
|
'When machine-api server not found butt is disabled and shows the reason',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'bracket')
|
const bracketDir = join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -23,10 +23,7 @@ test(
|
|||||||
|
|
||||||
await page.getByText('bracket').click()
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
const notFoundText = 'Machine API server was not discovered'
|
const notFoundText = 'Machine API server was not discovered'
|
||||||
await expect(page.getByText(notFoundText).first()).not.toBeVisible()
|
await expect(page.getByText(notFoundText).first()).not.toBeVisible()
|
||||||
@ -47,7 +44,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'When machine-api server not found home screen & project status shows the reason',
|
'When machine-api server not found home screen & project status shows the reason',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'bracket')
|
const bracketDir = join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -71,10 +68,7 @@ test(
|
|||||||
|
|
||||||
await page.getByText('bracket').click()
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(page.getByText(notFoundText).nth(1)).not.toBeVisible()
|
await expect(page.getByText(notFoundText).nth(1)).not.toBeVisible()
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ test.describe('Named view tests', () => {
|
|||||||
|
|
||||||
// Create and load project
|
// Create and load project
|
||||||
await createProject({ name: projectName, page })
|
await createProject({ name: projectName, page })
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Create named view
|
// Create named view
|
||||||
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
|
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
|
||||||
@ -110,14 +110,17 @@ test.describe('Named view tests', () => {
|
|||||||
expect(exists).toBe(true)
|
expect(exists).toBe(true)
|
||||||
}).toPass()
|
}).toPass()
|
||||||
|
|
||||||
// Read project.toml into memory
|
await expect(async () => {
|
||||||
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
// Read project.toml into memory
|
||||||
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
||||||
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
|
||||||
|
|
||||||
// Write the entire tomlString to a snapshot.
|
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
||||||
// There are many key/value pairs to check this is a safer match.
|
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
||||||
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
|
|
||||||
|
// Write the entire tomlString to a snapshot.
|
||||||
|
// There are many key/value pairs to check this is a safer match.
|
||||||
|
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
|
||||||
|
}).toPass()
|
||||||
})
|
})
|
||||||
test('Verify named view gets deleted', async ({
|
test('Verify named view gets deleted', async ({
|
||||||
cmdBar,
|
cmdBar,
|
||||||
@ -130,7 +133,7 @@ test.describe('Named view tests', () => {
|
|||||||
|
|
||||||
// Create project and go into the project
|
// Create project and go into the project
|
||||||
await createProject({ name: projectName, page })
|
await createProject({ name: projectName, page })
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Create a new named view
|
// Create a new named view
|
||||||
await cmdBar.openCmdBar()
|
await cmdBar.openCmdBar()
|
||||||
@ -152,14 +155,16 @@ test.describe('Named view tests', () => {
|
|||||||
expect(exists).toBe(true)
|
expect(exists).toBe(true)
|
||||||
}).toPass()
|
}).toPass()
|
||||||
|
|
||||||
// Read project.toml into memory
|
await expect(async () => {
|
||||||
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
// Read project.toml into memory
|
||||||
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
||||||
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
||||||
|
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
||||||
|
|
||||||
// Write the entire tomlString to a snapshot.
|
// Write the entire tomlString to a snapshot.
|
||||||
// There are many key/value pairs to check this is a safer match.
|
// There are many key/value pairs to check this is a safer match.
|
||||||
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
|
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
|
||||||
|
}).toPass()
|
||||||
|
|
||||||
// Delete a named view
|
// Delete a named view
|
||||||
await cmdBar.openCmdBar()
|
await cmdBar.openCmdBar()
|
||||||
@ -167,14 +172,16 @@ test.describe('Named view tests', () => {
|
|||||||
cmdBar.selectOption({ name: myNamedView2 })
|
cmdBar.selectOption({ name: myNamedView2 })
|
||||||
await cmdBar.progressCmdBar(false)
|
await cmdBar.progressCmdBar(false)
|
||||||
|
|
||||||
// Read project.toml into memory again since we deleted a named view
|
await expect(async () => {
|
||||||
tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
// Read project.toml into memory again since we deleted a named view
|
||||||
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
||||||
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
||||||
|
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
||||||
|
|
||||||
// // Write the entire tomlString to a snapshot.
|
// // Write the entire tomlString to a snapshot.
|
||||||
// // There are many key/value pairs to check this is a safer match.
|
// // There are many key/value pairs to check this is a safer match.
|
||||||
expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted')
|
expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted')
|
||||||
|
}).toPass()
|
||||||
})
|
})
|
||||||
test('Verify named view gets loaded', async ({
|
test('Verify named view gets loaded', async ({
|
||||||
cmdBar,
|
cmdBar,
|
||||||
@ -186,7 +193,7 @@ test.describe('Named view tests', () => {
|
|||||||
|
|
||||||
// Create project and go into the project
|
// Create project and go into the project
|
||||||
await createProject({ name: projectName, page })
|
await createProject({ name: projectName, page })
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Create a new named view
|
// Create a new named view
|
||||||
await cmdBar.openCmdBar()
|
await cmdBar.openCmdBar()
|
||||||
@ -208,14 +215,16 @@ test.describe('Named view tests', () => {
|
|||||||
expect(exists).toBe(true)
|
expect(exists).toBe(true)
|
||||||
}).toPass()
|
}).toPass()
|
||||||
|
|
||||||
// Read project.toml into memory
|
await expect(async () => {
|
||||||
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
// Read project.toml into memory
|
||||||
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
||||||
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
||||||
|
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
||||||
|
|
||||||
// Write the entire tomlString to a snapshot.
|
// Write the entire tomlString to a snapshot.
|
||||||
// There are many key/value pairs to check this is a safer match.
|
// There are many key/value pairs to check this is a safer match.
|
||||||
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
|
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
|
||||||
|
}).toPass()
|
||||||
|
|
||||||
// Create a load a named view
|
// Create a load a named view
|
||||||
await cmdBar.openCmdBar()
|
await cmdBar.openCmdBar()
|
||||||
@ -239,7 +248,7 @@ test.describe('Named view tests', () => {
|
|||||||
|
|
||||||
// Create and load project
|
// Create and load project
|
||||||
await createProject({ name: projectName, page })
|
await createProject({ name: projectName, page })
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Create named view
|
// Create named view
|
||||||
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
|
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
|
||||||
@ -282,13 +291,15 @@ test.describe('Named view tests', () => {
|
|||||||
expect(exists).toBe(true)
|
expect(exists).toBe(true)
|
||||||
}).toPass()
|
}).toPass()
|
||||||
|
|
||||||
// Read project.toml into memory
|
await expect(async () => {
|
||||||
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
// Read project.toml into memory
|
||||||
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
|
||||||
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
|
||||||
|
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
|
||||||
|
|
||||||
// Write the entire tomlString to a snapshot.
|
// Write the entire tomlString to a snapshot.
|
||||||
// There are many key/value pairs to check this is a safer match.
|
// There are many key/value pairs to check this is a safer match.
|
||||||
expect(tomlString).toMatchSnapshot('verify-two-named-view-gets-created')
|
expect(tomlString).toMatchSnapshot('verify-two-named-view-gets-created')
|
||||||
|
}).toPass()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
File diff suppressed because it is too large
Load Diff
115
e2e/playwright/point-click-assemblies.spec.ts
Normal file
115
e2e/playwright/point-click-assemblies.spec.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import * as fsp from 'fs/promises'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import { executorInputPath } from '@e2e/playwright/test-utils'
|
||||||
|
import { test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
|
// test file is for testing point an click code gen functionality that's assemblies related
|
||||||
|
test.describe('Point-and-click assemblies tests', () => {
|
||||||
|
test(
|
||||||
|
`Insert kcl part into assembly as whole module import`,
|
||||||
|
{ tag: ['@electron'] },
|
||||||
|
async ({
|
||||||
|
context,
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
editor,
|
||||||
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
|
tronApp,
|
||||||
|
}) => {
|
||||||
|
if (!tronApp) {
|
||||||
|
fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
// One dumb hardcoded screen pixel value
|
||||||
|
const testPoint = { x: 575, y: 200 }
|
||||||
|
const initialColor: [number, number, number] = [50, 50, 50]
|
||||||
|
const partColor: [number, number, number] = [150, 150, 150]
|
||||||
|
const tolerance = 50
|
||||||
|
|
||||||
|
await test.step('Setup parts and expect empty assembly scene', async () => {
|
||||||
|
const projectName = 'assembly'
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const bracketDir = path.join(dir, projectName)
|
||||||
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
|
await Promise.all([
|
||||||
|
fsp.copyFile(
|
||||||
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
|
path.join(bracketDir, 'cylinder.kcl')
|
||||||
|
),
|
||||||
|
fsp.copyFile(
|
||||||
|
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||||
|
path.join(bracketDir, 'bracket.kcl')
|
||||||
|
),
|
||||||
|
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
await homePage.openProject(projectName)
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await scene.expectPixelColor(initialColor, testPoint, tolerance)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Insert first part into the assembly', async () => {
|
||||||
|
await toolbar.insertButton.click()
|
||||||
|
await cmdBar.selectOption({ name: 'cylinder.kcl' }).click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'localName',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: { Path: 'cylinder.kcl', LocalName: '' },
|
||||||
|
highlightedHeaderArg: 'localName',
|
||||||
|
commandName: 'Insert',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('cylinder')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: { Path: 'cylinder.kcl', LocalName: 'cylinder' },
|
||||||
|
commandName: 'Insert',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`
|
||||||
|
import "cylinder.kcl" as cylinder
|
||||||
|
cylinder
|
||||||
|
`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
await scene.expectPixelColor(partColor, testPoint, tolerance)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Insert second part into the assembly', async () => {
|
||||||
|
await toolbar.insertButton.click()
|
||||||
|
await cmdBar.selectOption({ name: 'bracket.kcl' }).click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'localName',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: { Path: 'bracket.kcl', LocalName: '' },
|
||||||
|
highlightedHeaderArg: 'localName',
|
||||||
|
commandName: 'Insert',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('bracket')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: { Path: 'bracket.kcl', LocalName: 'bracket' },
|
||||||
|
commandName: 'Insert',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`
|
||||||
|
import "cylinder.kcl" as cylinder
|
||||||
|
import "bracket.kcl" as bracket
|
||||||
|
cylinder
|
||||||
|
bracket
|
||||||
|
`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
@ -5,13 +5,14 @@ import path from 'node:path'
|
|||||||
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
||||||
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||||
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
|
import { orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
|
||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
// test file is for testing point an click code gen functionality that's not sketch mode related
|
// test file is for testing point an click code gen functionality that's not sketch mode related
|
||||||
|
|
||||||
test.describe('Point-and-click tests', () => {
|
test.describe('Point-and-click tests', () => {
|
||||||
test('verify extruding circle works', async ({
|
test('verify extruding circle works', async ({
|
||||||
|
page,
|
||||||
context,
|
context,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
@ -30,8 +31,9 @@ test.describe('Point-and-click tests', () => {
|
|||||||
await context.addInitScript((file) => {
|
await context.addInitScript((file) => {
|
||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
|
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
|
||||||
|
|
||||||
@ -72,7 +74,6 @@ test.describe('Point-and-click tests', () => {
|
|||||||
|
|
||||||
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
|
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'distance',
|
currentArgKey: 'distance',
|
||||||
@ -186,6 +187,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
editor,
|
editor,
|
||||||
toolbar,
|
toolbar,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const file = await fs.readFile(
|
const file = await fs.readFile(
|
||||||
path.resolve(
|
path.resolve(
|
||||||
@ -200,9 +202,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
}, file)
|
}, file)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await expect(
|
await scene.settled(cmdBar)
|
||||||
page.getByTestId('model-state-indicator-receive-reliable')
|
|
||||||
).toBeVisible()
|
|
||||||
|
|
||||||
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
|
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
|
||||||
|
|
||||||
@ -377,6 +377,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
|||||||
editor,
|
editor,
|
||||||
toolbar,
|
toolbar,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const file = await fs.readFile(
|
const file = await fs.readFile(
|
||||||
path.resolve(
|
path.resolve(
|
||||||
@ -392,7 +393,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
|
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
|
||||||
|
|
||||||
@ -479,6 +480,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
|||||||
await page.setBodyDimensions(viewPortSize)
|
await page.setBodyDimensions(viewPortSize)
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
// Constants and locators
|
// Constants and locators
|
||||||
// These are mappings from screenspace to KCL coordinates,
|
// These are mappings from screenspace to KCL coordinates,
|
||||||
@ -537,8 +539,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
|||||||
await toolbar.startSketchPlaneSelection()
|
await toolbar.startSketchPlaneSelection()
|
||||||
await moveToXzPlane()
|
await moveToXzPlane()
|
||||||
await clickOnXzPlane()
|
await clickOnXzPlane()
|
||||||
// timeout wait for engine animation is unavoidable
|
await toolbar.waitUntilSketchingReady()
|
||||||
await page.waitForTimeout(600)
|
|
||||||
await editor.expectEditor.toContain(expectedCodeSnippets.sketchOnXzPlane)
|
await editor.expectEditor.toContain(expectedCodeSnippets.sketchOnXzPlane)
|
||||||
})
|
})
|
||||||
await test.step(`Place a point a few pixels off the middle, verify it still snaps to 0,0`, async () => {
|
await test.step(`Place a point a few pixels off the middle, verify it still snaps to 0,0`, async () => {
|
||||||
@ -580,9 +581,8 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
|||||||
editor,
|
editor,
|
||||||
toolbar,
|
toolbar,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
|
||||||
|
|
||||||
const initialCode = `closedSketch = startSketchOn(XZ)
|
const initialCode = `closedSketch = startSketchOn(XZ)
|
||||||
|> circle(center = [8, 5], radius = 2)
|
|> circle(center = [8, 5], radius = 2)
|
||||||
openSketch = startSketchOn(XY)
|
openSketch = startSketchOn(XY)
|
||||||
@ -599,8 +599,6 @@ openSketch = startSketchOn(XY)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
|
|
||||||
const pointInsideCircle = {
|
const pointInsideCircle = {
|
||||||
x: viewPortSize.width * 0.63,
|
x: viewPortSize.width * 0.63,
|
||||||
@ -625,15 +623,16 @@ openSketch = startSketchOn(XY)
|
|||||||
const exitSketch = async () => {
|
const exitSketch = async () => {
|
||||||
await test.step(`Exit sketch mode`, async () => {
|
await test.step(`Exit sketch mode`, async () => {
|
||||||
await toolbar.exitSketchBtn.click()
|
await toolbar.exitSketchBtn.click()
|
||||||
await expect(toolbar.exitSketchBtn).not.toBeVisible()
|
|
||||||
await expect(toolbar.startSketchBtn).toBeEnabled()
|
await expect(toolbar.startSketchBtn).toBeEnabled()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
await test.step(`Double-click on the closed sketch`, async () => {
|
await test.step(`Double-click on the closed sketch`, async () => {
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await moveToCircle()
|
await moveToCircle()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await dblClickCircle()
|
await dblClickCircle()
|
||||||
await expect(toolbar.startSketchBtn).not.toBeVisible()
|
await page.waitForTimeout(1000)
|
||||||
await expect(toolbar.exitSketchBtn).toBeVisible()
|
await expect(toolbar.exitSketchBtn).toBeVisible()
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
activeLines: [`|>circle(center=[8,5],radius=2)`],
|
activeLines: [`|>circle(center=[8,5],radius=2)`],
|
||||||
@ -670,7 +669,6 @@ openSketch = startSketchOn(XY)
|
|||||||
// There is a full execution after exiting sketch that clears the scene.
|
// There is a full execution after exiting sketch that clears the scene.
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
await dblClickOpenPath()
|
await dblClickOpenPath()
|
||||||
await expect(toolbar.startSketchBtn).not.toBeVisible()
|
|
||||||
await expect(toolbar.exitSketchBtn).toBeVisible()
|
await expect(toolbar.exitSketchBtn).toBeVisible()
|
||||||
// Wait for enter sketch mode to complete
|
// Wait for enter sketch mode to complete
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
@ -1031,6 +1029,9 @@ openSketch = startSketchOn(XY)
|
|||||||
})
|
})
|
||||||
await test.step(`Go through the command bar flow`, async () => {
|
await test.step(`Go through the command bar flow`, async () => {
|
||||||
await toolbar.offsetPlaneButton.click()
|
await toolbar.offsetPlaneButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'plane',
|
currentArgKey: 'plane',
|
||||||
@ -1088,6 +1089,7 @@ openSketch = startSketchOn(XY)
|
|||||||
const expectedLine = `axis=X,`
|
const expectedLine = `axis=X,`
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
await test.step(`Go through the command bar flow`, async () => {
|
await test.step(`Go through the command bar flow`, async () => {
|
||||||
await toolbar.helixButton.click()
|
await toolbar.helixButton.click()
|
||||||
@ -1106,6 +1108,7 @@ openSketch = startSketchOn(XY)
|
|||||||
commandName: 'Helix',
|
commandName: 'Helix',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await expect.poll(() => page.getByText('Axis').count()).toBe(6)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -1233,6 +1236,7 @@ openSketch = startSketchOn(XY)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await test.step(`Go through the command bar flow`, async () => {
|
await test.step(`Go through the command bar flow`, async () => {
|
||||||
await toolbar.closePane('code')
|
await toolbar.closePane('code')
|
||||||
@ -1252,15 +1256,22 @@ openSketch = startSketchOn(XY)
|
|||||||
commandName: 'Helix',
|
commandName: 'Helix',
|
||||||
})
|
})
|
||||||
await cmdBar.selectOption({ name: 'Edge' }).click()
|
await cmdBar.selectOption({ name: 'Edge' }).click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await clickOnEdge()
|
await clickOnEdge()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await cmdBar.argumentInput.focus()
|
await cmdBar.argumentInput.focus()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await page.keyboard.insertText('20')
|
await page.keyboard.insertText('20')
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await page.keyboard.insertText('0')
|
await page.keyboard.insertText('0')
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await page.keyboard.insertText('1')
|
await page.keyboard.insertText('1')
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.keyboard.insertText('100')
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
@ -1274,6 +1285,7 @@ openSketch = startSketchOn(XY)
|
|||||||
commandName: 'Helix',
|
commandName: 'Helix',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||||
@ -1369,7 +1381,7 @@ extrude001 = extrude(profile001, length = 100)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 620, y: 257 }
|
const testPoint = { x: 620, y: 257 }
|
||||||
@ -1530,6 +1542,9 @@ extrude001 = extrude(profile001, length = 100)
|
|||||||
if (!shouldPreselect) {
|
if (!shouldPreselect) {
|
||||||
await test.step(`Go through the command bar flow without preselected sketches`, async () => {
|
await test.step(`Go through the command bar flow without preselected sketches`, async () => {
|
||||||
await toolbar.loftButton.click()
|
await toolbar.loftButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'selection',
|
currentArgKey: 'selection',
|
||||||
@ -1579,6 +1594,7 @@ extrude001 = extrude(profile001, length = 100)
|
|||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||||
|> circle(center = [0, 0], radius = 30)
|
|> circle(center = [0, 0], radius = 30)
|
||||||
@ -1592,7 +1608,7 @@ loft001 = loft([sketch001, sketch002])
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 575, y: 200 }
|
const testPoint = { x: 575, y: 200 }
|
||||||
@ -1687,7 +1703,7 @@ sketch002 = startSketchOn(XZ)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||||
@ -1707,6 +1723,9 @@ sketch002 = startSketchOn(XZ)
|
|||||||
|
|
||||||
await test.step(`Go through the command bar flow`, async () => {
|
await test.step(`Go through the command bar flow`, async () => {
|
||||||
await toolbar.sweepButton.click()
|
await toolbar.sweepButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
currentArgKey: 'target',
|
currentArgKey: 'target',
|
||||||
@ -1826,7 +1845,7 @@ sketch002 = startSketchOn(XZ)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 700, y: 250 }
|
const testPoint = { x: 700, y: 250 }
|
||||||
@ -1843,6 +1862,9 @@ sketch002 = startSketchOn(XZ)
|
|||||||
|
|
||||||
await test.step(`Go through the command bar flow and fail validation with a toast`, async () => {
|
await test.step(`Go through the command bar flow and fail validation with a toast`, async () => {
|
||||||
await toolbar.sweepButton.click()
|
await toolbar.sweepButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
currentArgKey: 'target',
|
currentArgKey: 'target',
|
||||||
@ -2059,6 +2081,9 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
await test.step(`Open fillet UI without selecting edges`, async () => {
|
await test.step(`Open fillet UI without selecting edges`, async () => {
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await toolbar.filletButton.click()
|
await toolbar.filletButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'selection',
|
currentArgKey: 'selection',
|
||||||
@ -2184,6 +2209,7 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
toolbar,
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn(XY)
|
const initialCode = `sketch001 = startSketchOn(XY)
|
||||||
profile001 = circle(
|
profile001 = circle(
|
||||||
@ -2200,7 +2226,7 @@ fillet001 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await test.step('Double-click in feature tree and expect error toast', async () => {
|
await test.step('Double-click in feature tree and expect error toast', async () => {
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
@ -2521,7 +2547,7 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Test 1: Command bar flow with preselected edges
|
// Test 1: Command bar flow with preselected edges
|
||||||
@ -2554,6 +2580,7 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Chamfer',
|
commandName: 'Chamfer',
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
@ -2565,7 +2592,10 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
},
|
},
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
|
await cmdBar.argumentInput.focus()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Chamfer',
|
commandName: 'Chamfer',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
@ -2649,6 +2679,9 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
await test.step(`Open chamfer UI without selecting edges`, async () => {
|
await test.step(`Open chamfer UI without selecting edges`, async () => {
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await toolbar.chamferButton.click()
|
await toolbar.chamferButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'selection',
|
currentArgKey: 'selection',
|
||||||
@ -2771,6 +2804,7 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
scene,
|
scene,
|
||||||
editor,
|
editor,
|
||||||
toolbar,
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
// Code samples
|
// Code samples
|
||||||
const initialCode = `@settings(defaultLengthUnit = in)
|
const initialCode = `@settings(defaultLengthUnit = in)
|
||||||
@ -2814,7 +2848,7 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// verify modeling scene is loaded
|
// verify modeling scene is loaded
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
@ -2936,9 +2970,11 @@ extrude001 = extrude(sketch001, length = 30)
|
|||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
localStorage.setItem('persistCode', initialCode)
|
localStorage.setItem('persistCode', initialCode)
|
||||||
}, initialCode)
|
}, initialCode)
|
||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 575, y: 200 }
|
const testPoint = { x: 575, y: 200 }
|
||||||
@ -2955,6 +2991,9 @@ extrude001 = extrude(sketch001, length = 30)
|
|||||||
if (!shouldPreselect) {
|
if (!shouldPreselect) {
|
||||||
await test.step(`Go through the command bar flow without preselected faces`, async () => {
|
await test.step(`Go through the command bar flow without preselected faces`, async () => {
|
||||||
await toolbar.shellButton.click()
|
await toolbar.shellButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'selection',
|
currentArgKey: 'selection',
|
||||||
@ -3015,7 +3054,6 @@ extrude001 = extrude(sketch001, length = 30)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Edit shell via feature tree selection works', async () => {
|
await test.step('Edit shell via feature tree selection works', async () => {
|
||||||
await toolbar.closePane('code')
|
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
'Shell',
|
'Shell',
|
||||||
@ -3044,7 +3082,6 @@ extrude001 = extrude(sketch001, length = 30)
|
|||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await toolbar.closePane('feature-tree')
|
await toolbar.closePane('feature-tree')
|
||||||
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
||||||
await toolbar.openPane('code')
|
|
||||||
await editor.expectEditor.toContain(editedShellDeclaration)
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
@ -3079,7 +3116,7 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 580, y: 180 }
|
const testPoint = { x: 580, y: 180 }
|
||||||
@ -3097,6 +3134,9 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
|
|
||||||
await test.step(`Go through the command bar flow, selecting a wall and keeping default thickness`, async () => {
|
await test.step(`Go through the command bar flow, selecting a wall and keeping default thickness`, async () => {
|
||||||
await toolbar.shellButton.click()
|
await toolbar.shellButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'selection',
|
currentArgKey: 'selection',
|
||||||
@ -3108,6 +3148,9 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
highlightedHeaderArg: 'selection',
|
highlightedHeaderArg: 'selection',
|
||||||
commandName: 'Shell',
|
commandName: 'Shell',
|
||||||
})
|
})
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await clickOnCap()
|
await clickOnCap()
|
||||||
await page.keyboard.down('Shift')
|
await page.keyboard.down('Shift')
|
||||||
await clickOnWall()
|
await clickOnWall()
|
||||||
@ -3116,6 +3159,7 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
@ -3124,7 +3168,9 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
},
|
},
|
||||||
commandName: 'Shell',
|
commandName: 'Shell',
|
||||||
})
|
})
|
||||||
|
await page.waitForTimeout(500)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||||
@ -3139,7 +3185,6 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Edit shell via feature tree selection works', async () => {
|
await test.step('Edit shell via feature tree selection works', async () => {
|
||||||
await editor.closePane()
|
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
||||||
await operationButton.dblclick({ button: 'left' })
|
await operationButton.dblclick({ button: 'left' })
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
@ -3154,6 +3199,7 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
})
|
})
|
||||||
await page.keyboard.insertText('1')
|
await page.keyboard.insertText('1')
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
@ -3164,7 +3210,6 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await toolbar.closePane('feature-tree')
|
await toolbar.closePane('feature-tree')
|
||||||
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
||||||
await toolbar.openPane('code')
|
|
||||||
await editor.expectEditor.toContain(editedShellDeclaration)
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
@ -3218,7 +3263,7 @@ extrude002 = extrude(sketch002, length = 50)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 580, y: 320 }
|
const testPoint = { x: 580, y: 320 }
|
||||||
@ -3243,12 +3288,13 @@ extrude002 = extrude(sketch002, length = 50)
|
|||||||
highlightedHeaderArg: 'selection',
|
highlightedHeaderArg: 'selection',
|
||||||
commandName: 'Shell',
|
commandName: 'Shell',
|
||||||
})
|
})
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await clickOnCap()
|
await clickOnCap()
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(1000)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await page.waitForTimeout(500)
|
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await page.waitForTimeout(500)
|
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
@ -3306,7 +3352,7 @@ profile001 = startProfileAt([-20, 20], sketch001)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
@ -3386,7 +3432,7 @@ sweep001 = sweep(sketch001, path = sketch002)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 500, y: 250 }
|
const testPoint = { x: 500, y: 250 }
|
||||||
@ -3399,6 +3445,9 @@ sweep001 = sweep(sketch001, path = sketch002)
|
|||||||
|
|
||||||
await test.step(`Go through the Shell flow and fail validation with a toast`, async () => {
|
await test.step(`Go through the Shell flow and fail validation with a toast`, async () => {
|
||||||
await toolbar.shellButton.click()
|
await toolbar.shellButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(() => page.getByText('Please select one').count())
|
||||||
|
.toBe(1)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'selection',
|
currentArgKey: 'selection',
|
||||||
@ -3462,12 +3511,13 @@ segAng(rectangleSegmentA002),
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// select line of code
|
// select line of code
|
||||||
const codeToSelecton = `segAng(rectangleSegmentA002) - 90,`
|
const codeToSelection = `segAng(rectangleSegmentA002) - 90,`
|
||||||
// revolve
|
// revolve
|
||||||
await page.getByText(codeToSelecton).click()
|
await editor.scrollToText(codeToSelection)
|
||||||
|
await page.getByText(codeToSelection).click()
|
||||||
await toolbar.revolveButton.click()
|
await toolbar.revolveButton.click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -3541,15 +3591,17 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// select line of code
|
// select line of code
|
||||||
const codeToSelecton = `center = [-11.34, 10.0]`
|
const codeToSelection = `center = [-11.34, 10.0]`
|
||||||
// revolve
|
// revolve
|
||||||
await page.getByText(codeToSelecton).click()
|
await editor.scrollToText(codeToSelection)
|
||||||
|
await page.getByText(codeToSelection).click()
|
||||||
await toolbar.revolveButton.click()
|
await toolbar.revolveButton.click()
|
||||||
await page.getByText('Edge', { exact: true }).click()
|
await page.getByText('Edge', { exact: true }).click()
|
||||||
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
|
const lineCodeToSelection = `angledLine([0, 202.6], %, $rectangleSegmentA001)`
|
||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -3595,6 +3647,7 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|
|||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
newCodeToFind.replace('angle = 360', 'angle = angle001')
|
newCodeToFind.replace('angle = 360', 'angle = angle001')
|
||||||
)
|
)
|
||||||
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
})
|
})
|
||||||
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
|
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
|
||||||
context,
|
context,
|
||||||
@ -3628,15 +3681,20 @@ sketch003 = startSketchOn(extrude001, 'START')
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// select line of code
|
// select line of code
|
||||||
const codeToSelecton = `center = [-0.69, 0.56]`
|
const codeToSelection = `center = [-0.69, 0.56]`
|
||||||
// revolve
|
// revolve
|
||||||
await page.getByText(codeToSelecton).click()
|
|
||||||
await toolbar.revolveButton.click()
|
await toolbar.revolveButton.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
await editor.scrollToText(codeToSelection)
|
||||||
|
await page.getByText(codeToSelection).click()
|
||||||
|
await expect.poll(() => page.getByText('AxisOrEdge').count()).toBe(2)
|
||||||
await page.getByText('Edge', { exact: true }).click()
|
await page.getByText('Edge', { exact: true }).click()
|
||||||
const lineCodeToSelection = `|> xLine(length = 2.6)`
|
const lineCodeToSelection = `length = 2.6`
|
||||||
|
await editor.scrollToText(lineCodeToSelection)
|
||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -3703,21 +3761,22 @@ extrude001 = extrude(profile001, length = 100)
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
// One dumb hardcoded screen pixel value
|
||||||
const testPoint = { x: 500, y: 250 }
|
const testPoint = { x: 500, y: 250 }
|
||||||
const initialColor: [number, number, number] = [123, 123, 123]
|
const initialColor: [number, number, number] = [123, 123, 123]
|
||||||
|
const tolerance = 50
|
||||||
|
|
||||||
await test.step(`Confirm extrude exists with default appearance`, async () => {
|
await test.step(`Confirm extrude exists with default appearance`, async () => {
|
||||||
await toolbar.closePane('code')
|
await toolbar.closePane('code')
|
||||||
await scene.expectPixelColor(initialColor, testPoint, 15)
|
await scene.expectPixelColor(initialColor, testPoint, tolerance)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function setApperanceAndCheck(
|
async function setApperanceAndCheck(
|
||||||
option: string,
|
option: string,
|
||||||
hex: string,
|
hex: string,
|
||||||
shapeColor: [number, number, number]
|
shapeColor?: [number, number, number]
|
||||||
) {
|
) {
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
const enterAppearanceFlow = async (stepName: string) =>
|
const enterAppearanceFlow = async (stepName: string) =>
|
||||||
@ -3766,7 +3825,9 @@ extrude001 = extrude(profile001, length = 100)
|
|||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await toolbar.closePane('feature-tree')
|
await toolbar.closePane('feature-tree')
|
||||||
await scene.expectPixelColor(shapeColor, testPoint, 10)
|
if (shapeColor) {
|
||||||
|
await scene.expectPixelColor(shapeColor, testPoint, tolerance)
|
||||||
|
}
|
||||||
await toolbar.openPane('code')
|
await toolbar.openPane('code')
|
||||||
if (hex === 'default') {
|
if (hex === 'default') {
|
||||||
const anyAppearanceDeclaration = `|> appearance(`
|
const anyAppearanceDeclaration = `|> appearance(`
|
||||||
@ -3785,16 +3846,17 @@ extrude001 = extrude(profile001, length = 100)
|
|||||||
}
|
}
|
||||||
|
|
||||||
await test.step(`Go through the Set Appearance flow for all options`, async () => {
|
await test.step(`Go through the Set Appearance flow for all options`, async () => {
|
||||||
await setApperanceAndCheck('Red', '#FF0000', [180, 0, 0])
|
await setApperanceAndCheck('Red', '#FF0000', [180, 30, 30])
|
||||||
await setApperanceAndCheck('Green', '#00FF00', [0, 180, 0])
|
// Not checking the scene color every time cause that's not really deterministic. Red seems reliable though
|
||||||
await setApperanceAndCheck('Blue', '#0000FF', [0, 0, 180])
|
await setApperanceAndCheck('Green', '#00FF00')
|
||||||
await setApperanceAndCheck('Turquoise', '#00FFFF', [0, 180, 180])
|
await setApperanceAndCheck('Blue', '#0000FF')
|
||||||
await setApperanceAndCheck('Purple', '#FF00FF', [180, 0, 180])
|
await setApperanceAndCheck('Turquoise', '#00FFFF')
|
||||||
await setApperanceAndCheck('Yellow', '#FFFF00', [180, 180, 0])
|
await setApperanceAndCheck('Purple', '#FF00FF')
|
||||||
await setApperanceAndCheck('Black', '#000000', [0, 0, 0])
|
await setApperanceAndCheck('Yellow', '#FFFF00')
|
||||||
await setApperanceAndCheck('Dark Grey', '#080808', [0x33, 0x33, 0x33])
|
await setApperanceAndCheck('Black', '#000000')
|
||||||
await setApperanceAndCheck('Light Grey', '#D3D3D3', [176, 176, 176])
|
await setApperanceAndCheck('Dark Grey', '#080808')
|
||||||
await setApperanceAndCheck('White', '#FFFFFF', [184, 184, 184])
|
await setApperanceAndCheck('Light Grey', '#D3D3D3')
|
||||||
|
await setApperanceAndCheck('White', '#FFFFFF')
|
||||||
await setApperanceAndCheck(
|
await setApperanceAndCheck(
|
||||||
'Default (clear appearance)',
|
'Default (clear appearance)',
|
||||||
'default',
|
'default',
|
||||||
|
@ -83,7 +83,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'click help/keybindings from project page',
|
'click help/keybindings from project page',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -95,17 +95,11 @@ test(
|
|||||||
|
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
// expect to see the text bracket
|
// expect to see the text bracket
|
||||||
await expect(page.getByText('bracket')).toBeVisible()
|
await expect(page.getByText('bracket')).toBeVisible()
|
||||||
|
|
||||||
await page.getByText('bracket').click()
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
// click ? button
|
// click ? button
|
||||||
await page.getByTestId('help-button').click()
|
await page.getByTestId('help-button').click()
|
||||||
@ -120,7 +114,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
|
'open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page, editor }, testInfo) => {
|
async ({ scene, cmdBar, context, page, editor }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -149,24 +143,7 @@ test(
|
|||||||
|
|
||||||
await page.getByText('bracket').click()
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
|
||||||
).toBeEnabled({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
// gray at this pixel means the stream has loaded in the most
|
|
||||||
// user way we can verify it (pixel color)
|
|
||||||
await expect
|
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [110, 110, 110]), {
|
|
||||||
timeout: 10_000,
|
|
||||||
})
|
|
||||||
.toBeLessThan(20)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
|
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
|
||||||
@ -209,7 +186,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
|
'open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -235,24 +212,7 @@ test(
|
|||||||
|
|
||||||
await page.getByText('bracket').click()
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
|
||||||
).toBeEnabled({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
// gray at this pixel means the stream has loaded in the most
|
|
||||||
// user way we can verify it (pixel color)
|
|
||||||
await expect
|
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
|
||||||
timeout: 10_000,
|
|
||||||
})
|
|
||||||
.toBeLessThan(15)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
|
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
|
||||||
@ -352,7 +312,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'open a file in a project works and renders, open another file in the same project with errors, it should clear the scene',
|
'open a file in a project works and renders, open another file in the same project with errors, it should clear the scene',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
if (runningOnWindows()) {
|
if (runningOnWindows()) {
|
||||||
test.fixme(orRunWhenFullSuiteEnabled())
|
test.fixme(orRunWhenFullSuiteEnabled())
|
||||||
}
|
}
|
||||||
@ -380,10 +340,7 @@ test(
|
|||||||
|
|
||||||
await page.getByText('bracket').click()
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
@ -443,10 +400,10 @@ test(
|
|||||||
await expect(page.getByText('broken-code')).toBeVisible()
|
await expect(page.getByText('broken-code')).toBeVisible()
|
||||||
await page.getByText('broken-code').click()
|
await page.getByText('broken-code').click()
|
||||||
|
|
||||||
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail
|
// Gotcha: You can not use scene.settled() since the KCL code is going to fail
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
await expect(
|
||||||
timeout: 20_000,
|
page.getByTestId('model-state-indicator-playing')
|
||||||
})
|
).toBeAttached()
|
||||||
|
|
||||||
// Gotcha: Scroll to the text content in code mirror because CodeMirror lazy loads DOM content
|
// Gotcha: Scroll to the text content in code mirror because CodeMirror lazy loads DOM content
|
||||||
await editor.scrollToText(
|
await editor.scrollToText(
|
||||||
@ -469,7 +426,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
test(
|
test(
|
||||||
`Can export using ${method}`,
|
`Can export using ${method}`,
|
||||||
{ tag: ['@electron', '@skipLocalEngine'] },
|
{ tag: ['@electron', '@skipLocalEngine'] },
|
||||||
async ({ context, page, tronApp }, testInfo) => {
|
async ({ scene, cmdBar, context, page, tronApp }, testInfo) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
}
|
}
|
||||||
@ -499,10 +456,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
|
|
||||||
await page.getByText('bracket').click()
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
@ -812,7 +766,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
test(
|
test(
|
||||||
`Rename from project page`,
|
`Rename from project page`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
const projectName = `my_project_to_rename`
|
const projectName = `my_project_to_rename`
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
||||||
@ -821,7 +775,6 @@ test.describe(`Project management commands`, () => {
|
|||||||
`${dir}/${projectName}/main.kcl`
|
`${dir}/${projectName}/main.kcl`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
const u = await getUtils(page)
|
|
||||||
|
|
||||||
// Constants and locators
|
// Constants and locators
|
||||||
const projectHomeLink = page.getByTestId('project-link')
|
const projectHomeLink = page.getByTestId('project-link')
|
||||||
@ -843,7 +796,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
page.on('console', console.log)
|
page.on('console', console.log)
|
||||||
|
|
||||||
await projectHomeLink.click()
|
await projectHomeLink.click()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Run rename command via command palette`, async () => {
|
await test.step(`Run rename command via command palette`, async () => {
|
||||||
@ -882,7 +835,6 @@ test.describe(`Project management commands`, () => {
|
|||||||
`${dir}/${projectName}/main.kcl`
|
`${dir}/${projectName}/main.kcl`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
const u = await getUtils(page)
|
|
||||||
|
|
||||||
// Constants and locators
|
// Constants and locators
|
||||||
const projectHomeLink = page.getByTestId('project-link')
|
const projectHomeLink = page.getByTestId('project-link')
|
||||||
@ -900,9 +852,9 @@ test.describe(`Project management commands`, () => {
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
page.on('console', console.log)
|
page.on('console', console.log)
|
||||||
|
|
||||||
|
await page.waitForTimeout(3000)
|
||||||
|
|
||||||
await projectHomeLink.click()
|
await projectHomeLink.click()
|
||||||
await u.waitForPageLoad()
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -926,7 +878,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
test(
|
test(
|
||||||
`Rename from home page`,
|
`Rename from home page`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page, homePage }, testInfo) => {
|
async ({ context, page, homePage, scene, cmdBar }, testInfo) => {
|
||||||
const projectName = `my_project_to_rename`
|
const projectName = `my_project_to_rename`
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
||||||
@ -982,7 +934,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
test(
|
test(
|
||||||
`Delete from home page`,
|
`Delete from home page`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
const projectName = `my_project_to_delete`
|
const projectName = `my_project_to_delete`
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
||||||
@ -1033,6 +985,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
homePage,
|
homePage,
|
||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
|
scene,
|
||||||
}) => {
|
}) => {
|
||||||
const projectName = 'test-project'
|
const projectName = 'test-project'
|
||||||
await test.step(`Setup`, async () => {
|
await test.step(`Setup`, async () => {
|
||||||
@ -1072,10 +1025,11 @@ test.describe(`Project management commands`, () => {
|
|||||||
})
|
})
|
||||||
await cmdBar.argumentInput.fill(projectName)
|
await cmdBar.argumentInput.fill(projectName)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await toolbar.logoLink.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Check the project was created with a non-colliding name`, async () => {
|
await test.step(`Check the project was created with a non-colliding name`, async () => {
|
||||||
await toolbar.logoLink.click()
|
|
||||||
await homePage.expectState({
|
await homePage.expectState({
|
||||||
projectCards: [
|
projectCards: [
|
||||||
{
|
{
|
||||||
@ -1106,10 +1060,11 @@ test.describe(`Project management commands`, () => {
|
|||||||
})
|
})
|
||||||
await cmdBar.argumentInput.fill(projectName)
|
await cmdBar.argumentInput.fill(projectName)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await toolbar.logoLink.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Check the second project was created with a non-colliding name`, async () => {
|
await test.step(`Check the second project was created with a non-colliding name`, async () => {
|
||||||
await toolbar.logoLink.click()
|
|
||||||
await homePage.expectState({
|
await homePage.expectState({
|
||||||
projectCards: [
|
projectCards: [
|
||||||
{
|
{
|
||||||
@ -1195,7 +1150,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'Nested directories in project without main.kcl do not create main.kcl',
|
'Nested directories in project without main.kcl do not create main.kcl',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
let testDir: string | undefined
|
let testDir: string | undefined
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(path.join(dir, 'router-template-slate', 'nested'), {
|
await fsp.mkdir(path.join(dir, 'router-template-slate', 'nested'), {
|
||||||
@ -1218,10 +1173,7 @@ test(
|
|||||||
|
|
||||||
await test.step('Open the project', async () => {
|
await test.step('Open the project', async () => {
|
||||||
await page.getByText('router-template-slate').click()
|
await page.getByText('router-template-slate').click()
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
// It actually loads.
|
// It actually loads.
|
||||||
await expect(u.codeLocator).toContainText('mounting bracket')
|
await expect(u.codeLocator).toContainText('mounting bracket')
|
||||||
@ -1334,7 +1286,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'Can load a file with CRLF line endings',
|
'Can load a file with CRLF line endings',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
if (runningOnWindows()) {
|
if (runningOnWindows()) {
|
||||||
test.fixme(orRunWhenFullSuiteEnabled())
|
test.fixme(orRunWhenFullSuiteEnabled())
|
||||||
}
|
}
|
||||||
@ -1357,13 +1309,8 @@ test(
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
await page.getByText('router-template-slate').click()
|
await page.getByText('router-template-slate').click()
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(u.codeLocator).toContainText('routerDiameter')
|
await expect(u.codeLocator).toContainText('routerDiameter')
|
||||||
await expect(u.codeLocator).toContainText('templateGap')
|
await expect(u.codeLocator).toContainText('templateGap')
|
||||||
@ -1578,7 +1525,7 @@ extrude001 = extrude(sketch001, length = 200)`)
|
|||||||
test(
|
test(
|
||||||
'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)',
|
'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page, cmdBar, homePage }, testInfo) => {
|
async ({ context, page, cmdBar, homePage, scene }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
|
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
@ -1607,13 +1554,10 @@ test(
|
|||||||
path.join(dir, 'bracket', 'main.kcl')
|
path.join(dir, 'bracket', 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
const u = await getUtils(page)
|
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
page.on('console', console.log)
|
||||||
|
|
||||||
const pointOnModel = { x: 630, y: 280 }
|
|
||||||
|
|
||||||
await test.step('Opening the bracket project via command palette should load the stream', async () => {
|
await test.step('Opening the bracket project via command palette should load the stream', async () => {
|
||||||
await homePage.expectState({
|
await homePage.expectState({
|
||||||
projectCards: [
|
projectCards: [
|
||||||
@ -1647,15 +1591,7 @@ test(
|
|||||||
stage: 'commandBarClosed',
|
stage: 'commandBarClosed',
|
||||||
})
|
})
|
||||||
|
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// gray at this pixel means the stream has loaded in the most
|
|
||||||
// user way we can verify it (pixel color)
|
|
||||||
await expect
|
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
|
|
||||||
timeout: 10_000,
|
|
||||||
})
|
|
||||||
.toBeLessThan(15)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
|
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
|
||||||
@ -1672,15 +1608,7 @@ test(
|
|||||||
|
|
||||||
await page.getByText('router-template-slate').click()
|
await page.getByText('router-template-slate').click()
|
||||||
|
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// gray at this pixel means the stream has loaded in the most
|
|
||||||
// user way we can verify it (pixel color)
|
|
||||||
await expect
|
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [143, 143, 143]), {
|
|
||||||
timeout: 10_000,
|
|
||||||
})
|
|
||||||
.toBeLessThan(15)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('The projects on the home page should still be normal', async () => {
|
await test.step('The projects on the home page should still be normal', async () => {
|
||||||
@ -1733,8 +1661,6 @@ test(
|
|||||||
})
|
})
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
// we'll grab this from the settings on screen before we switch
|
// we'll grab this from the settings on screen before we switch
|
||||||
let originalProjectDirName: string
|
let originalProjectDirName: string
|
||||||
const newProjectDirName = testInfo.outputPath(
|
const newProjectDirName = testInfo.outputPath(
|
||||||
@ -1875,7 +1801,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'file pane is scrollable when there are many files',
|
'file pane is scrollable when there are many files',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const testDir = path.join(dir, 'testProject')
|
const testDir = path.join(dir, 'testProject')
|
||||||
await fsp.mkdir(testDir, { recursive: true })
|
await fsp.mkdir(testDir, { recursive: true })
|
||||||
@ -1954,10 +1880,8 @@ test(
|
|||||||
|
|
||||||
await test.step('setup, open file pane', async () => {
|
await test.step('setup, open file pane', async () => {
|
||||||
await page.getByText('testProject').click()
|
await page.getByText('testProject').click()
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
await scene.settled(cmdBar)
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await page.getByTestId('files-pane-button').click()
|
await page.getByTestId('files-pane-button').click()
|
||||||
})
|
})
|
||||||
|
@ -63,7 +63,7 @@ test.describe('edit with AI example snapshots', () => {
|
|||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const body1CapCoords = { x: 571, y: 351 }
|
const body1CapCoords = { x: 571, y: 351 }
|
||||||
const [clickBody1Cap] = scene.makeMouseHelpers(
|
const [clickBody1Cap] = scene.makeMouseHelpers(
|
||||||
|
@ -61,7 +61,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
|||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const body1CapCoords = { x: 571, y: 311 }
|
const body1CapCoords = { x: 571, y: 311 }
|
||||||
const greenCheckCoords = { x: 565, y: 305 }
|
const greenCheckCoords = { x: 565, y: 305 }
|
||||||
@ -156,7 +156,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
|||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const body1CapCoords = { x: 571, y: 311 }
|
const body1CapCoords = { x: 571, y: 311 }
|
||||||
const [clickBody1Cap] = scene.makeMouseHelpers(
|
const [clickBody1Cap] = scene.makeMouseHelpers(
|
||||||
@ -212,7 +212,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
|||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
||||||
const successToast = page.getByText('Prompt to edit successful')
|
const successToast = page.getByText('Prompt to edit successful')
|
||||||
@ -281,7 +281,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
|||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
||||||
const successToast = page.getByText('Prompt to edit successful')
|
const successToast = page.getByText('Prompt to edit successful')
|
||||||
|
@ -689,6 +689,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
toolbar,
|
toolbar,
|
||||||
|
viewport,
|
||||||
}) => {
|
}) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const legoDir = path.join(dir, 'lego')
|
const legoDir = path.join(dir, 'lego')
|
||||||
@ -703,8 +704,8 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
await homePage.openProject('lego')
|
await homePage.openProject('lego')
|
||||||
await toolbar.closePane('code')
|
await toolbar.closePane('code')
|
||||||
})
|
})
|
||||||
await test.step(`Waiting for the loading spinner to disappear`, async () => {
|
await test.step(`Waiting for scene to settle`, async () => {
|
||||||
await scene.loadingIndicator.waitFor({ state: 'detached' })
|
await scene.connectionEstablished()
|
||||||
})
|
})
|
||||||
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
|
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
|
||||||
// TODO: use the viewport size to pick the center point, but the `viewport` fixture's values were wrong.
|
// TODO: use the viewport size to pick the center point, but the `viewport` fixture's values were wrong.
|
||||||
@ -762,7 +763,7 @@ plane002 = offsetPlane(XZ, offset = -2 * x)`
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
await homePage.openProject('test-sample')
|
await homePage.openProject('test-sample')
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
|
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
'Offset Plane',
|
'Offset Plane',
|
||||||
|
@ -22,6 +22,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
|||||||
context,
|
context,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
const selectionsSnippets = {
|
const selectionsSnippets = {
|
||||||
@ -82,7 +83,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// wait for execution done
|
// wait for execution done
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
@ -108,6 +109,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
|||||||
page,
|
page,
|
||||||
scene,
|
scene,
|
||||||
homePage,
|
homePage,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -122,7 +124,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 587, y: 270 }, 15)
|
await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 587, y: 270 }, 15)
|
||||||
|
|
||||||
@ -673,6 +675,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
editor,
|
editor,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -689,7 +692,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
@ -1614,7 +1617,7 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
test(
|
test(
|
||||||
`snapToProfile start only works for current profile`,
|
`snapToProfile start only works for current profile`,
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ context, page, scene, toolbar, editor, homePage }) => {
|
async ({ context, page, scene, toolbar, editor, homePage, cmdBar }) => {
|
||||||
// We seed the scene with a single offset plane
|
// We seed the scene with a single offset plane
|
||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -1630,6 +1633,8 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -1651,9 +1656,13 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
const codeFromTangentialArc = ` |> tangentialArcTo([39.49, 88.22], %)`
|
const codeFromTangentialArc = ` |> tangentialArcTo([39.49, 88.22], %)`
|
||||||
await test.step('check that tangential tool does not snap to other profile starts', async () => {
|
await test.step('check that tangential tool does not snap to other profile starts', async () => {
|
||||||
await toolbar.tangentialArcBtn.click()
|
await toolbar.tangentialArcBtn.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await endOfLowerSegMove()
|
await endOfLowerSegMove()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await endOfLowerSegClick()
|
await endOfLowerSegClick()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await profileStartOfHigherSegClick()
|
await profileStartOfHigherSegClick()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await editor.expectEditor.toContain(codeFromTangentialArc)
|
await editor.expectEditor.toContain(codeFromTangentialArc)
|
||||||
await editor.expectEditor.not.toContain(
|
await editor.expectEditor.not.toContain(
|
||||||
`[profileStartX(%), profileStartY(%)]`
|
`[profileStartX(%), profileStartY(%)]`
|
||||||
@ -2242,8 +2251,9 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
|
|||||||
|
|
||||||
await test.step('enter sketch and setup', async () => {
|
await test.step('enter sketch and setup', async () => {
|
||||||
await moveToClearToolBarPopover()
|
await moveToClearToolBarPopover()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await pointOnSegment({ shouldDbClick: true })
|
await pointOnSegment({ shouldDbClick: true })
|
||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(2000)
|
||||||
|
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
@ -2359,7 +2369,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
|
|||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -2965,6 +2975,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
|
|||||||
toolbar,
|
toolbar,
|
||||||
editor,
|
editor,
|
||||||
homePage,
|
homePage,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
// We seed the scene with a single offset plane
|
// We seed the scene with a single offset plane
|
||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
@ -2982,7 +2993,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
|
|||||||
})
|
})
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await test.step(`format the code`, async () => {
|
await test.step(`format the code`, async () => {
|
||||||
// doesn't contain condensed version
|
// doesn't contain condensed version
|
||||||
@ -3047,6 +3058,7 @@ test.describe('Redirecting to home page and back to the original file should cle
|
|||||||
toolbar,
|
toolbar,
|
||||||
editor,
|
editor,
|
||||||
homePage,
|
homePage,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
// We seed the scene with a single offset plane
|
// We seed the scene with a single offset plane
|
||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
@ -3059,7 +3071,7 @@ test.describe('Redirecting to home page and back to the original file should cle
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const [objClick] = scene.makeMouseHelpers(634, 274)
|
const [objClick] = scene.makeMouseHelpers(634, 274)
|
||||||
await objClick()
|
await objClick()
|
||||||
|
@ -103,7 +103,6 @@ part001 = startSketchOn(-XZ)
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
const axisDirectionPair: Models['AxisDirectionPair_type'] = {
|
const axisDirectionPair: Models['AxisDirectionPair_type'] = {
|
||||||
@ -369,7 +368,6 @@ const extrudeDefaultPlane = async (
|
|||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(page).toHaveScreenshot({
|
await expect(page).toHaveScreenshot({
|
||||||
@ -421,8 +419,6 @@ test(
|
|||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
|
|
||||||
const startXPx = 600
|
const startXPx = 600
|
||||||
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
|
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
|
||||||
startXPx + PUR * 30,
|
startXPx + PUR * 30,
|
||||||
@ -551,8 +547,6 @@ test(
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
|
|
||||||
// click on "Start Sketch" button
|
// click on "Start Sketch" button
|
||||||
await u.doAndWaitForImageDiff(
|
await u.doAndWaitForImageDiff(
|
||||||
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
@ -598,8 +592,6 @@ test(
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
|
|
||||||
await u.doAndWaitForImageDiff(
|
await u.doAndWaitForImageDiff(
|
||||||
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
200
|
200
|
||||||
@ -650,8 +642,6 @@ test.describe(
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
|
|
||||||
await u.doAndWaitForImageDiff(
|
await u.doAndWaitForImageDiff(
|
||||||
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
200
|
200
|
||||||
@ -744,7 +734,6 @@ test.describe(
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await u.doAndWaitForImageDiff(
|
await u.doAndWaitForImageDiff(
|
||||||
@ -846,7 +835,6 @@ part002 = startSketchOn(part001, seg01)
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Wait for the second extrusion to appear
|
// Wait for the second extrusion to appear
|
||||||
@ -902,7 +890,6 @@ test(
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Wait for the second extrusion to appear
|
// Wait for the second extrusion to appear
|
||||||
@ -943,7 +930,6 @@ test(
|
|||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Wait for the second extrusion to appear
|
// Wait for the second extrusion to appear
|
||||||
@ -976,7 +962,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
|
|||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await u.closeKclCodePanel()
|
await u.closeKclCodePanel()
|
||||||
@ -1041,7 +1026,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
|
|||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await u.closeKclCodePanel()
|
await u.closeKclCodePanel()
|
||||||
@ -1086,7 +1070,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
|
|||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await u.closeKclCodePanel()
|
await u.closeKclCodePanel()
|
||||||
@ -1205,7 +1188,6 @@ sweepSketch = startSketchOn(XY)
|
|||||||
await page.setViewportSize({ width: 1200, height: 1000 })
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(page, 'expect small color widget').toHaveScreenshot({
|
await expect(page, 'expect small color widget').toHaveScreenshot({
|
||||||
@ -1255,7 +1237,6 @@ sweepSketch = startSketchOn(XY)
|
|||||||
await page.setViewportSize({ width: 1200, height: 1000 })
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(page.locator('.cm-css-color-picker-wrapper')).toBeVisible()
|
await expect(page.locator('.cm-css-color-picker-wrapper')).toBeVisible()
|
||||||
|
@ -89,7 +89,7 @@ test.describe('Test network and connection issues', () => {
|
|||||||
test(
|
test(
|
||||||
'Engine disconnect & reconnect in sketch mode',
|
'Engine disconnect & reconnect in sketch mode',
|
||||||
{ tag: '@skipLocalEngine' },
|
{ tag: '@skipLocalEngine' },
|
||||||
async ({ page, homePage, toolbar }) => {
|
async ({ page, homePage, toolbar, scene, cmdBar }) => {
|
||||||
test.fixme(orRunWhenFullSuiteEnabled())
|
test.fixme(orRunWhenFullSuiteEnabled())
|
||||||
const networkToggle = page.getByTestId('network-toggle')
|
const networkToggle = page.getByTestId('network-toggle')
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ test.describe('Test network and connection issues', () => {
|
|||||||
|
|
||||||
// Expect the network to be up
|
// Expect the network to be up
|
||||||
await expect(networkToggle).toContainText('Connected')
|
await expect(networkToggle).toContainText('Connected')
|
||||||
await expect(page.getByTestId('loading-stream')).not.toBeAttached()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Click off the code pane.
|
// Click off the code pane.
|
||||||
await page.mouse.click(100, 100)
|
await page.mouse.click(100, 100)
|
||||||
|
@ -74,7 +74,10 @@ async function waitForPageLoadWithRetry(page: Page) {
|
|||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
const errorMessage = 'App failed to load - 🔃 Retrying ...'
|
const errorMessage = 'App failed to load - 🔃 Retrying ...'
|
||||||
await expect(page.getByTestId('loading'), errorMessage).not.toBeAttached({
|
await expect(
|
||||||
|
page.getByTestId('model-state-indicator-playing'),
|
||||||
|
errorMessage
|
||||||
|
).toBeAttached({
|
||||||
timeout: 20_000,
|
timeout: 20_000,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -87,9 +90,10 @@ async function waitForPageLoadWithRetry(page: Page) {
|
|||||||
}).toPass({ timeout: 70_000, intervals: [1_000] })
|
}).toPass({ timeout: 70_000, intervals: [1_000] })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lee: This needs to be replaced by scene.settled() eventually.
|
||||||
async function waitForPageLoad(page: Page) {
|
async function waitForPageLoad(page: Page) {
|
||||||
// wait for all spinners to be gone
|
// wait for all spinners to be gone
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
await expect(page.getByTestId('model-state-indicator-playing')).toBeVisible({
|
||||||
timeout: 20_000,
|
timeout: 20_000,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -871,9 +875,10 @@ export async function tearDown(page: Page, testInfo: TestInfo) {
|
|||||||
export async function setup(
|
export async function setup(
|
||||||
context: BrowserContext,
|
context: BrowserContext,
|
||||||
page: Page,
|
page: Page,
|
||||||
|
testDir: string,
|
||||||
testInfo?: TestInfo
|
testInfo?: TestInfo
|
||||||
) {
|
) {
|
||||||
await context.addInitScript(
|
await page.addInitScript(
|
||||||
async ({
|
async ({
|
||||||
token,
|
token,
|
||||||
settingsKey,
|
settingsKey,
|
||||||
@ -914,7 +919,7 @@ export async function setup(
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
IS_PLAYWRIGHT_KEY,
|
IS_PLAYWRIGHT_KEY,
|
||||||
PLAYWRIGHT_TEST_DIR: TEST_SETTINGS.project?.directory || '',
|
PLAYWRIGHT_TEST_DIR: testDir,
|
||||||
PERSIST_MODELING_CONTEXT,
|
PERSIST_MODELING_CONTEXT,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -934,7 +939,7 @@ export async function setup(
|
|||||||
await page.emulateMedia({ reducedMotion: 'reduce' })
|
await page.emulateMedia({ reducedMotion: 'reduce' })
|
||||||
|
|
||||||
// Trigger a navigation, since loading file:// doesn't.
|
// Trigger a navigation, since loading file:// doesn't.
|
||||||
// await page.reload()
|
await page.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {
|
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {
|
||||||
|
@ -5,12 +5,18 @@ import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
|
|||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
|
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
|
||||||
test('Can move camera reliably', async ({ page, context, homePage }) => {
|
test('Can move camera reliably', async ({
|
||||||
|
page,
|
||||||
|
context,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
await u.openAndClearDebugPanel()
|
||||||
await u.closeKclCodePanel()
|
await u.closeKclCodePanel()
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
.toBe(false)
|
.toBe(false)
|
||||||
})
|
})
|
||||||
test(`Remove constraints`, async ({ page, homePage }) => {
|
test(`Remove constraints`, async ({ page, homePage, scene, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -101,7 +101,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
|
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -142,7 +142,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { testName, offset } of cases) {
|
for (const { testName, offset } of cases) {
|
||||||
test(`${testName}`, async ({ page, homePage }) => {
|
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -166,7 +166,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
|
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -250,7 +250,12 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { testName, value, constraint } of cases) {
|
for (const { testName, value, constraint } of cases) {
|
||||||
test(`${constraint} - ${testName}`, async ({ page, homePage }) => {
|
test(`${constraint} - ${testName}`, async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -274,7 +279,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -361,7 +366,12 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { testName, addVariable, value, constraint } of cases) {
|
for (const { testName, addVariable, value, constraint } of cases) {
|
||||||
test(`${constraint} - ${testName}`, async ({ page, homePage }) => {
|
test(`${constraint} - ${testName}`, async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -385,7 +395,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -475,7 +485,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { testName, addVariable, value, axisSelect } of cases) {
|
for (const { testName, addVariable, value, axisSelect } of cases) {
|
||||||
test(`${testName}`, async ({ page, homePage }) => {
|
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -499,7 +509,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -578,7 +588,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { testName, addVariable, value, constraint } of cases) {
|
for (const { testName, addVariable, value, constraint } of cases) {
|
||||||
test(`${testName}`, async ({ page, homePage }) => {
|
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -602,7 +612,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -655,7 +665,14 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { testName, addVariable, value, constraint } of cases) {
|
for (const { testName, addVariable, value, constraint } of cases) {
|
||||||
test(`${testName}`, async ({ context, homePage, page, editor }) => {
|
test(`${testName}`, async ({
|
||||||
|
context,
|
||||||
|
homePage,
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
// constants and locators
|
// constants and locators
|
||||||
const cmdBarKclInput = page
|
const cmdBarKclInput = page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
@ -689,7 +706,7 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await editor.scrollToText('line(end = [74.36, 130.4])', true)
|
await editor.scrollToText('line(end = [74.36, 130.4])', true)
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
@ -746,7 +763,7 @@ part002 = startSketchOn(XZ)
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { codeAfter, constraintName } of cases) {
|
for (const { codeAfter, constraintName } of cases) {
|
||||||
test(`${constraintName}`, async ({ page, homePage }) => {
|
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
|
||||||
await page.addInitScript(async (customCode) => {
|
await page.addInitScript(async (customCode) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -770,7 +787,7 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -848,7 +865,7 @@ part002 = startSketchOn(XZ)
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { codeAfter, constraintName } of cases) {
|
for (const { codeAfter, constraintName } of cases) {
|
||||||
test(`${constraintName}`, async ({ page, homePage }) => {
|
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -871,7 +888,7 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -930,7 +947,7 @@ part002 = startSketchOn(XZ)
|
|||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { codeAfter, constraintName, axisClick } of cases) {
|
for (const { codeAfter, constraintName, axisClick } of cases) {
|
||||||
test(`${constraintName}`, async ({ page, homePage }) => {
|
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -953,7 +970,7 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [74.36, 130.4])').click()
|
await page.getByText('line(end = [74.36, 130.4])').click()
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
@ -994,6 +1011,8 @@ part002 = startSketchOn(XZ)
|
|||||||
test('Horizontally constrained line remains selected after applying constraint', async ({
|
test('Horizontally constrained line remains selected after applying constraint', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
test.fixme(orRunWhenFullSuiteEnabled())
|
test.fixme(orRunWhenFullSuiteEnabled())
|
||||||
test.setTimeout(70_000)
|
test.setTimeout(70_000)
|
||||||
@ -1010,7 +1029,7 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await page.getByText('line(end = [3.79, 2.68], tag = $seg01)').click()
|
await page.getByText('line(end = [3.79, 2.68], tag = $seg01)').click()
|
||||||
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
|
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
|
||||||
@ -1129,7 +1148,7 @@ test.describe('Electron constraint tests', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await homePage.openProject('test-sample')
|
await homePage.openProject('test-sample')
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function clickOnFirstSegmentLabel() {
|
async function clickOnFirstSegmentLabel() {
|
||||||
|
@ -8,10 +8,11 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
|
|
||||||
test.describe('Testing in-app sample loading', () => {
|
test.describe('Testing in-app sample loading', () => {
|
||||||
/**
|
/**
|
||||||
* Note this test implicitly depends on the KCL sample "a-parametric-bearing-pillow-block",
|
* Note this test implicitly depends on the KCL sample "parametric-bearing-pillow-block",
|
||||||
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
|
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl
|
||||||
*/
|
*/
|
||||||
test('Web: should overwrite current code, cannot create new file', async ({
|
// We have no more web tests
|
||||||
|
test.skip('Web: should overwrite current code, cannot create new file', async ({
|
||||||
editor,
|
editor,
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
@ -29,8 +30,8 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
|
|
||||||
// Locators and constants
|
// Locators and constants
|
||||||
const newSample = {
|
const newSample = {
|
||||||
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
|
file: 'parametric-bearing-pillow-block' + FILE_EXT,
|
||||||
title: 'A Parametric Bearing Pillow Block',
|
title: 'Parametric Bearing Pillow Block',
|
||||||
}
|
}
|
||||||
const commandBarButton = page.getByRole('button', { name: 'Commands' })
|
const commandBarButton = page.getByRole('button', { name: 'Commands' })
|
||||||
const samplesCommandOption = page.getByRole('option', {
|
const samplesCommandOption = page.getByRole('option', {
|
||||||
@ -72,13 +73,13 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Note this test implicitly depends on the KCL samples:
|
* Note this test implicitly depends on the KCL samples:
|
||||||
* "a-parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
|
* "parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl
|
||||||
* "gear-rack": https://github.com/KittyCAD/kcl-samples/blob/main/gear-rack/main.kcl
|
* "gear-rack": https://github.com/KittyCAD/kcl-samples/blob/main/gear-rack/main.kcl
|
||||||
*/
|
*/
|
||||||
test(
|
test(
|
||||||
'Desktop: should create new file by default, optionally overwrite',
|
'Desktop: should create new file by default, optionally overwrite',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ editor, context, page }, testInfo) => {
|
async ({ editor, context, page, scene, cmdBar }, testInfo) => {
|
||||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'bracket')
|
const bracketDir = join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -90,8 +91,8 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
|
|
||||||
// Locators and constants
|
// Locators and constants
|
||||||
const sampleOne = {
|
const sampleOne = {
|
||||||
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
|
file: 'parametric-bearing-pillow-block' + FILE_EXT,
|
||||||
title: 'A Parametric Bearing Pillow Block',
|
title: 'Parametric Bearing Pillow Block',
|
||||||
}
|
}
|
||||||
const sampleTwo = {
|
const sampleTwo = {
|
||||||
file: 'gear-rack' + FILE_EXT,
|
file: 'gear-rack' + FILE_EXT,
|
||||||
@ -125,7 +126,7 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
await test.step(`Test setup`, async () => {
|
await test.step(`Test setup`, async () => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await projectCard.click()
|
await projectCard.click()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Precondition: check the initial code`, async () => {
|
await test.step(`Precondition: check the initial code`, async () => {
|
||||||
@ -140,11 +141,14 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
|
|
||||||
await test.step(`Load a KCL sample with the command palette`, async () => {
|
await test.step(`Load a KCL sample with the command palette`, async () => {
|
||||||
await commandBarButton.click()
|
await commandBarButton.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await commandOption.click()
|
await commandOption.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await commandSampleOption(sampleOne.title).click()
|
await commandSampleOption(sampleOne.title).click()
|
||||||
await expect(overwriteWarning).not.toBeVisible()
|
await expect(overwriteWarning).not.toBeVisible()
|
||||||
await expect(newFileWarning).toBeVisible()
|
await expect(newFileWarning).toBeVisible()
|
||||||
await confirmButton.click()
|
await confirmButton.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Ensure we made and opened a new file`, async () => {
|
await test.step(`Ensure we made and opened a new file`, async () => {
|
||||||
@ -155,14 +159,20 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
|
|
||||||
await test.step(`Now overwrite the current file`, async () => {
|
await test.step(`Now overwrite the current file`, async () => {
|
||||||
await commandBarButton.click()
|
await commandBarButton.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await commandOption.click()
|
await commandOption.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await commandSampleOption(sampleTwo.title).click()
|
await commandSampleOption(sampleTwo.title).click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await commandMethodArgButton.click()
|
await commandMethodArgButton.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await commandMethodOption.click()
|
await commandMethodOption.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await expect(commandMethodArgButton).toContainText('overwrite')
|
await expect(commandMethodArgButton).toContainText('overwrite')
|
||||||
await expect(newFileWarning).not.toBeVisible()
|
await expect(newFileWarning).not.toBeVisible()
|
||||||
await expect(overwriteWarning).toBeVisible()
|
await expect(overwriteWarning).toBeVisible()
|
||||||
await confirmButton.click()
|
await confirmButton.click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Ensure we overwrote the current file without navigating`, async () => {
|
await test.step(`Ensure we overwrote the current file without navigating`, async () => {
|
||||||
|
@ -1520,6 +1520,8 @@ part001 = startSketchOn(XZ)
|
|||||||
page,
|
page,
|
||||||
editor,
|
editor,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
await page.addInitScript(
|
await page.addInitScript(
|
||||||
async ({ lineToBeDeleted }) => {
|
async ({ lineToBeDeleted }) => {
|
||||||
@ -1541,7 +1543,8 @@ part001 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await page.waitForTimeout(300)
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
await page.getByText(before).click()
|
await page.getByText(before).click()
|
||||||
|
@ -528,6 +528,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|
|||||||
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
|
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
||||||
@ -660,8 +662,8 @@ part001 = startSketchOn(XZ)
|
|||||||
for (const rgb of RGBs) {
|
for (const rgb of RGBs) {
|
||||||
const [r, g, b] = rgb
|
const [r, g, b] = rgb
|
||||||
const RGAverage = (r + g) / 2
|
const RGAverage = (r + g) / 2
|
||||||
const isRedGreenSameIsh = Math.abs(r - g) < 3
|
const isRedGreenSameIsh = Math.abs(r - g) < 10
|
||||||
const isBlueLessThanRG = RGAverage - b > 45
|
const isBlueLessThanRG = RGAverage - b > 40
|
||||||
const isYellowy = isRedGreenSameIsh && isBlueLessThanRG
|
const isYellowy = isRedGreenSameIsh && isBlueLessThanRG
|
||||||
if (isYellowy) return true
|
if (isYellowy) return true
|
||||||
}
|
}
|
||||||
@ -779,11 +781,7 @@ part001 = startSketchOn(XZ)
|
|||||||
)
|
)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
await expect(
|
await scene.settled(cmdBar)
|
||||||
page
|
|
||||||
.getByTestId('model-state-indicator-receive-reliable')
|
|
||||||
.or(page.getByTestId('model-state-indicator-execution-done'))
|
|
||||||
).toBeVisible()
|
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
await u.openAndClearDebugPanel()
|
||||||
await u.sendCustomCmd({
|
await u.sendCustomCmd({
|
||||||
@ -953,6 +951,7 @@ part001 = startSketchOn(XZ)
|
|||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const cases = [
|
const cases = [
|
||||||
{
|
{
|
||||||
@ -989,7 +988,7 @@ part001 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
await u.openAndClearDebugPanel()
|
await u.openAndClearDebugPanel()
|
||||||
|
|
||||||
await u.sendCustomCmd({
|
await u.sendCustomCmd({
|
||||||
@ -1024,6 +1023,7 @@ part001 = startSketchOn(XZ)
|
|||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -1043,7 +1043,7 @@ part001 = startSketchOn(XZ)
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
await u.openAndClearDebugPanel()
|
await u.openAndClearDebugPanel()
|
||||||
|
|
||||||
await u.sendCustomCmd({
|
await u.sendCustomCmd({
|
||||||
|
@ -55,7 +55,8 @@ test.describe('Testing settings', () => {
|
|||||||
// Check that the invalid settings were changed to good defaults
|
// Check that the invalid settings were changed to good defaults
|
||||||
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
|
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
|
||||||
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
|
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
|
||||||
expect(storedSettings.settings?.project?.directory).toBe('')
|
// Commenting this out because tests need this to be set to work properly.
|
||||||
|
// expect(storedSettings.settings?.app?.project_directory).toBe('')
|
||||||
expect(storedSettings.settings?.project?.default_project_name).toBe(
|
expect(storedSettings.settings?.project?.default_project_name).toBe(
|
||||||
'untitled'
|
'untitled'
|
||||||
)
|
)
|
||||||
@ -865,6 +866,8 @@ test.describe('Testing settings', () => {
|
|||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
tronApp,
|
tronApp,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
@ -886,6 +889,7 @@ test.describe('Testing settings', () => {
|
|||||||
})
|
})
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
// Constants and locators
|
// Constants and locators
|
||||||
const resizeHandle = page.locator('.sidebar-resize-handles > div.block')
|
const resizeHandle = page.locator('.sidebar-resize-handles > div.block')
|
||||||
@ -897,6 +901,7 @@ test.describe('Testing settings', () => {
|
|||||||
|
|
||||||
async function setShowDebugPanelTo(value: 'On' | 'Off') {
|
async function setShowDebugPanelTo(value: 'On' | 'Off') {
|
||||||
await commandsButton.click()
|
await commandsButton.click()
|
||||||
|
await debugPaneOption.scrollIntoViewIfNeeded()
|
||||||
await debugPaneOption.click()
|
await debugPaneOption.click()
|
||||||
await page.getByRole('option', { name: value }).click()
|
await page.getByRole('option', { name: value }).click()
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -612,3 +612,12 @@ profile001 = startProfileAt([-12.34, 12.34], sketch002)
|
|||||||
const sketch002 = extrude(sketch002, length = ${[5, 5]} + 7)`
|
const sketch002 = extrude(sketch002, length = ${[5, 5]} + 7)`
|
||||||
await expect(page.locator('.cm-content')).toHaveText(result2.regExp)
|
await expect(page.locator('.cm-content')).toHaveText(result2.regExp)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test.fixme(
|
||||||
|
`Opening a share link in the web isn't blocked by the web warning banner`,
|
||||||
|
async () => {
|
||||||
|
// This test is not able to be run right now since we don't have a web-only setup for Playwright.
|
||||||
|
// @franknoirot can implement it when that testing infra is set up. It should be a test to cover the fix from
|
||||||
|
// modeling-app issue #6172.
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ -17,7 +17,6 @@ declare module '@playwright/test' {
|
|||||||
}
|
}
|
||||||
interface Page {
|
interface Page {
|
||||||
dir: string
|
dir: string
|
||||||
TEST_SETTINGS_FILE_KEY?: string
|
|
||||||
setBodyDimensions: (dims: {
|
setBodyDimensions: (dims: {
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
|
@ -4,6 +4,7 @@ directories:
|
|||||||
buildResources: assets
|
buildResources: assets
|
||||||
files:
|
files:
|
||||||
- .vite/**
|
- .vite/**
|
||||||
|
- "!node_modules/win-ca/pem/**"
|
||||||
mac:
|
mac:
|
||||||
category: public.app-category.developer-tools
|
category: public.app-category.developer-tools
|
||||||
artifactName: "${productName}-${version}-${arch}-${os}.${ext}"
|
artifactName: "${productName}-${version}-${arch}-${os}.${ext}"
|
||||||
|
1
interface.d.ts
vendored
1
interface.d.ts
vendored
@ -72,7 +72,6 @@ export interface IElectronAPI {
|
|||||||
process: {
|
process: {
|
||||||
env: {
|
env: {
|
||||||
BASE_URL: string
|
BASE_URL: string
|
||||||
TEST_SETTINGS_FILE_KEY: string
|
|
||||||
IS_PLAYWRIGHT: string
|
IS_PLAYWRIGHT: string
|
||||||
VITE_KC_DEV_TOKEN: string
|
VITE_KC_DEV_TOKEN: string
|
||||||
VITE_KC_API_WS_MODELING_URL: string
|
VITE_KC_API_WS_MODELING_URL: string
|
||||||
|
@ -4,10 +4,10 @@ $ dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx
|
|||||||
02) src/lang/std/sketch.ts -> src/lang/modifyAst.ts
|
02) src/lang/std/sketch.ts -> src/lang/modifyAst.ts
|
||||||
03) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts
|
03) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts
|
||||||
04) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts
|
04) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts
|
||||||
05) src/lib/singletons.ts -> src/lang/KclSingleton.ts
|
05) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/engineStreamMachine.ts
|
||||||
06) src/lib/singletons.ts -> src/lang/codeManager.ts
|
06) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
|
||||||
07) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
|
07) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts
|
||||||
08) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
|
08) src/lib/singletons.ts -> src/lang/codeManager.ts
|
||||||
09) src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
|
09) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
|
||||||
10) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts
|
10) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts
|
||||||
11) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx
|
11) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx
|
||||||
|
27
package.json
27
package.json
@ -26,7 +26,7 @@
|
|||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@headlessui/react": "^1.7.19",
|
"@headlessui/react": "^1.7.19",
|
||||||
"@headlessui/tailwindcss": "^0.2.2",
|
"@headlessui/tailwindcss": "^0.2.2",
|
||||||
"@kittycad/lib": "2.0.26",
|
"@kittycad/lib": "2.0.28",
|
||||||
"@lezer/highlight": "^1.2.1",
|
"@lezer/highlight": "^1.2.1",
|
||||||
"@lezer/lr": "^1.4.1",
|
"@lezer/lr": "^1.4.1",
|
||||||
"@react-hook/resize-observer": "^2.0.1",
|
"@react-hook/resize-observer": "^2.0.1",
|
||||||
@ -59,13 +59,14 @@
|
|||||||
"react-modal-promise": "^1.0.2",
|
"react-modal-promise": "^1.0.2",
|
||||||
"react-router-dom": "^6.28.0",
|
"react-router-dom": "^6.28.0",
|
||||||
"sketch-helpers": "^0.0.4",
|
"sketch-helpers": "^0.0.4",
|
||||||
"three": "^0.174.0",
|
"three": "^0.175.0",
|
||||||
"ua-parser-js": "^1.0.37",
|
"ua-parser-js": "^1.0.37",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"vscode-jsonrpc": "^8.2.1",
|
"vscode-jsonrpc": "^8.2.1",
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.1.0",
|
"vscode-uri": "^3.1.0",
|
||||||
"web-vitals": "^3.5.2",
|
"web-vitals": "^3.5.2",
|
||||||
|
"win-ca": "^3.5.1",
|
||||||
"xstate": "^5.19.2",
|
"xstate": "^5.19.2",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
},
|
},
|
||||||
@ -172,13 +173,13 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-env": "^7.26.9",
|
"@babel/preset-env": "^7.26.9",
|
||||||
"@electron-forge/cli": "^7.7.0",
|
"@electron-forge/cli": "^7.8.0",
|
||||||
"@electron-forge/plugin-fuses": "^7.7.0",
|
"@electron-forge/plugin-fuses": "^7.8.0",
|
||||||
"@electron-forge/plugin-vite": "^7.7.0",
|
"@electron-forge/plugin-vite": "^7.8.0",
|
||||||
"@electron/fuses": "^1.8.0",
|
"@electron/fuses": "^1.8.0",
|
||||||
"@electron/notarize": "^2.5.0",
|
"@electron/notarize": "^2.5.0",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@lezer/generator": "^1.7.2",
|
"@lezer/generator": "^1.7.3",
|
||||||
"@nabla/vite-plugin-eslint": "^2.0.5",
|
"@nabla/vite-plugin-eslint": "^2.0.5",
|
||||||
"@playwright/test": "^1.51.1",
|
"@playwright/test": "^1.51.1",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
@ -189,17 +190,17 @@
|
|||||||
"@types/isomorphic-fetch": "^0.0.39",
|
"@types/isomorphic-fetch": "^0.0.39",
|
||||||
"@types/minimist": "^1.2.5",
|
"@types/minimist": "^1.2.5",
|
||||||
"@types/mocha": "^10.0.10",
|
"@types/mocha": "^10.0.10",
|
||||||
"@types/node": "^22.13.14",
|
"@types/node": "^22.14.0",
|
||||||
"@types/pixelmatch": "^5.2.6",
|
"@types/pixelmatch": "^5.2.6",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
"@types/react": "^18.3.4",
|
"@types/react": "^18.3.4",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@types/react-modal": "^3.16.3",
|
"@types/react-modal": "^3.16.3",
|
||||||
"@types/three": "^0.174.0",
|
"@types/three": "^0.175.0",
|
||||||
"@types/ua-parser-js": "^0.7.39",
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"@types/wicg-file-system-access": "^2023.10.5",
|
"@types/wicg-file-system-access": "^2023.10.6",
|
||||||
"@types/ws": "^8.18.0",
|
"@types/ws": "^8.18.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"@vitest/web-worker": "^1.5.0",
|
"@vitest/web-worker": "^1.5.0",
|
||||||
"@xstate/cli": "^0.5.17",
|
"@xstate/cli": "^0.5.17",
|
||||||
@ -212,7 +213,7 @@
|
|||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-jest": "^28.11.0",
|
"eslint-plugin-jest": "^28.11.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||||
"eslint-plugin-react": "^7.37.4",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-perf": "^3.3.3",
|
"eslint-plugin-react-perf": "^3.3.3",
|
||||||
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
||||||
@ -231,8 +232,8 @@
|
|||||||
"setimmediate": "^1.0.5",
|
"setimmediate": "^1.0.5",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"ts-node": "^10.0.0",
|
"ts-node": "^10.0.0",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.3",
|
||||||
"typescript-eslint": "^8.26.1",
|
"typescript-eslint": "^8.29.0",
|
||||||
"vite": "^5.4.17",
|
"vite": "^5.4.17",
|
||||||
"vite-plugin-package-version": "^1.1.0",
|
"vite-plugin-package-version": "^1.1.0",
|
||||||
"vite-plugin-top-level-await": "^1.5.0",
|
"vite-plugin-top-level-await": "^1.5.0",
|
||||||
|
@ -19,17 +19,17 @@
|
|||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.10.3",
|
"@codemirror/language": "^6.10.3",
|
||||||
"@codemirror/state": "^6.4.1",
|
"@codemirror/state": "^6.5.2",
|
||||||
"@lezer/highlight": "^1.2.1",
|
"@lezer/highlight": "^1.2.1",
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.7.2",
|
"@lezer/generator": "^1.7.3",
|
||||||
"@rollup/plugin-typescript": "^12.1.2",
|
"@rollup/plugin-typescript": "^12.1.2",
|
||||||
"rollup": "^4.29.1",
|
"rollup": "^4.29.1",
|
||||||
"rollup-plugin-dts": "^6.1.1",
|
"rollup-plugin-dts": "^6.1.1",
|
||||||
"vite-tsconfig-paths": "^4.3.2",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"vitest": "^2.1.9"
|
"vitest": "^3.1.1"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist/"
|
"dist/"
|
||||||
|
@ -28,10 +28,10 @@
|
|||||||
"@lezer/lr" "^1.0.0"
|
"@lezer/lr" "^1.0.0"
|
||||||
style-mod "^4.0.0"
|
style-mod "^4.0.0"
|
||||||
|
|
||||||
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.1", "@codemirror/state@^6.5.0":
|
"@codemirror/state@^6.0.0", "@codemirror/state@^6.5.0", "@codemirror/state@^6.5.2":
|
||||||
version "6.5.0"
|
version "6.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.0.tgz#e98dde85620618651543152fe1c2483300a0ccc9"
|
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6"
|
||||||
integrity sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==
|
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@marijn/find-cluster-break" "^1.0.0"
|
"@marijn/find-cluster-break" "^1.0.0"
|
||||||
|
|
||||||
@ -44,120 +44,130 @@
|
|||||||
style-mod "^4.1.0"
|
style-mod "^4.1.0"
|
||||||
w3c-keyname "^2.2.4"
|
w3c-keyname "^2.2.4"
|
||||||
|
|
||||||
"@esbuild/aix-ppc64@0.21.5":
|
"@esbuild/aix-ppc64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f"
|
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz#b87036f644f572efb2b3c75746c97d1d2d87ace8"
|
||||||
integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==
|
integrity sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==
|
||||||
|
|
||||||
"@esbuild/android-arm64@0.21.5":
|
"@esbuild/android-arm64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052"
|
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz#5ca7dc20a18f18960ad8d5e6ef5cf7b0a256e196"
|
||||||
integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==
|
integrity sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==
|
||||||
|
|
||||||
"@esbuild/android-arm@0.21.5":
|
"@esbuild/android-arm@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28"
|
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.2.tgz#3c49f607b7082cde70c6ce0c011c362c57a194ee"
|
||||||
integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==
|
integrity sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==
|
||||||
|
|
||||||
"@esbuild/android-x64@0.21.5":
|
"@esbuild/android-x64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e"
|
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.2.tgz#8a00147780016aff59e04f1036e7cb1b683859e2"
|
||||||
integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==
|
integrity sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==
|
||||||
|
|
||||||
"@esbuild/darwin-arm64@0.21.5":
|
"@esbuild/darwin-arm64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a"
|
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz#486efe7599a8d90a27780f2bb0318d9a85c6c423"
|
||||||
integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
|
integrity sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==
|
||||||
|
|
||||||
"@esbuild/darwin-x64@0.21.5":
|
"@esbuild/darwin-x64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22"
|
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz#95ee222aacf668c7a4f3d7ee87b3240a51baf374"
|
||||||
integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==
|
integrity sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==
|
||||||
|
|
||||||
"@esbuild/freebsd-arm64@0.21.5":
|
"@esbuild/freebsd-arm64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e"
|
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz#67efceda8554b6fc6a43476feba068fb37fa2ef6"
|
||||||
integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==
|
integrity sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==
|
||||||
|
|
||||||
"@esbuild/freebsd-x64@0.21.5":
|
"@esbuild/freebsd-x64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261"
|
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz#88a9d7ecdd3adadbfe5227c2122d24816959b809"
|
||||||
integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==
|
integrity sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==
|
||||||
|
|
||||||
"@esbuild/linux-arm64@0.21.5":
|
"@esbuild/linux-arm64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz#87be1099b2bbe61282333b084737d46bc8308058"
|
||||||
integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==
|
integrity sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==
|
||||||
|
|
||||||
"@esbuild/linux-arm@0.21.5":
|
"@esbuild/linux-arm@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz#72a285b0fe64496e191fcad222185d7bf9f816f6"
|
||||||
integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==
|
integrity sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==
|
||||||
|
|
||||||
"@esbuild/linux-ia32@0.21.5":
|
"@esbuild/linux-ia32@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz#337a87a4c4dd48a832baed5cbb022be20809d737"
|
||||||
integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==
|
integrity sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==
|
||||||
|
|
||||||
"@esbuild/linux-loong64@0.21.5":
|
"@esbuild/linux-loong64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz#1b81aa77103d6b8a8cfa7c094ed3d25c7579ba2a"
|
||||||
integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==
|
integrity sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==
|
||||||
|
|
||||||
"@esbuild/linux-mips64el@0.21.5":
|
"@esbuild/linux-mips64el@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz#afbe380b6992e7459bf7c2c3b9556633b2e47f30"
|
||||||
integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==
|
integrity sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==
|
||||||
|
|
||||||
"@esbuild/linux-ppc64@0.21.5":
|
"@esbuild/linux-ppc64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz#6bf8695cab8a2b135cca1aa555226dc932d52067"
|
||||||
integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==
|
integrity sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==
|
||||||
|
|
||||||
"@esbuild/linux-riscv64@0.21.5":
|
"@esbuild/linux-riscv64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz#43c2d67a1a39199fb06ba978aebb44992d7becc3"
|
||||||
integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==
|
integrity sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==
|
||||||
|
|
||||||
"@esbuild/linux-s390x@0.21.5":
|
"@esbuild/linux-s390x@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz#419e25737ec815c6dce2cd20d026e347cbb7a602"
|
||||||
integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==
|
integrity sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==
|
||||||
|
|
||||||
"@esbuild/linux-x64@0.21.5":
|
"@esbuild/linux-x64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz#22451f6edbba84abe754a8cbd8528ff6e28d9bcb"
|
||||||
integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==
|
integrity sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==
|
||||||
|
|
||||||
"@esbuild/netbsd-x64@0.21.5":
|
"@esbuild/netbsd-arm64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047"
|
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz#744affd3b8d8236b08c5210d828b0698a62c58ac"
|
||||||
integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==
|
integrity sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==
|
||||||
|
|
||||||
"@esbuild/openbsd-x64@0.21.5":
|
"@esbuild/netbsd-x64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70"
|
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz#dbbe7521fd6d7352f34328d676af923fc0f8a78f"
|
||||||
integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==
|
integrity sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==
|
||||||
|
|
||||||
"@esbuild/sunos-x64@0.21.5":
|
"@esbuild/openbsd-arm64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b"
|
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz#f9caf987e3e0570500832b487ce3039ca648ce9f"
|
||||||
integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==
|
integrity sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==
|
||||||
|
|
||||||
"@esbuild/win32-arm64@0.21.5":
|
"@esbuild/openbsd-x64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d"
|
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz#d2bb6a0f8ffea7b394bb43dfccbb07cabd89f768"
|
||||||
integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==
|
integrity sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==
|
||||||
|
|
||||||
"@esbuild/win32-ia32@0.21.5":
|
"@esbuild/sunos-x64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b"
|
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz#49b437ed63fe333b92137b7a0c65a65852031afb"
|
||||||
integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==
|
integrity sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==
|
||||||
|
|
||||||
"@esbuild/win32-x64@0.21.5":
|
"@esbuild/win32-arm64@0.25.2":
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c"
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz#081424168463c7d6c7fb78f631aede0c104373cf"
|
||||||
integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
|
integrity sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==
|
||||||
|
|
||||||
|
"@esbuild/win32-ia32@0.25.2":
|
||||||
|
version "0.25.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz#3f9e87143ddd003133d21384944a6c6cadf9693f"
|
||||||
|
integrity sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==
|
||||||
|
|
||||||
|
"@esbuild/win32-x64@0.25.2":
|
||||||
|
version "0.25.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz#839f72c2decd378f86b8f525e1979a97b920c67d"
|
||||||
|
integrity sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec@^1.5.0":
|
"@jridgewell/sourcemap-codec@^1.5.0":
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
@ -169,10 +179,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd"
|
resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd"
|
||||||
integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==
|
integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==
|
||||||
|
|
||||||
"@lezer/generator@^1.7.2":
|
"@lezer/generator@^1.7.3":
|
||||||
version "1.7.2"
|
version "1.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/@lezer/generator/-/generator-1.7.2.tgz#a491c91eb9f117ea803e748fa97574514156a2a3"
|
resolved "https://registry.yarnpkg.com/@lezer/generator/-/generator-1.7.3.tgz#8bf9e99c7690dd31327425ca46706a380413f54d"
|
||||||
integrity sha512-CwgULPOPPmH54tv4gki18bElLCdJ1+FBC+nGVSVD08vFWDsMjS7KEjNTph9JOypDnet90ujN3LzQiW3CyVODNQ==
|
integrity sha512-vAI2O1tPF8QMMgp+bdUeeJCneJNkOZvqsrtyb4ohnFVFdboSqPwBEacnt0HH4E+5h+qsIwTHUSAhffU4hzKl1A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@lezer/common" "^1.1.0"
|
"@lezer/common" "^1.1.0"
|
||||||
"@lezer/lr" "^1.3.0"
|
"@lezer/lr" "^1.3.0"
|
||||||
@ -218,159 +228,264 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz#9bd38df6a29afb7f0336d988bc8112af0c8816c0"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz#9bd38df6a29afb7f0336d988bc8112af0c8816c0"
|
||||||
integrity sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==
|
integrity sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==
|
||||||
|
|
||||||
|
"@rollup/rollup-android-arm-eabi@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz#1d8cc5dd3d8ffe569d8f7f67a45c7909828a0f66"
|
||||||
|
integrity sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==
|
||||||
|
|
||||||
"@rollup/rollup-android-arm64@4.29.1":
|
"@rollup/rollup-android-arm64@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz#bd1a98390e15b76eeef907175a37c5f0f9e4d214"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz#bd1a98390e15b76eeef907175a37c5f0f9e4d214"
|
||||||
integrity sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==
|
integrity sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==
|
||||||
|
|
||||||
|
"@rollup/rollup-android-arm64@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz#9c136034d3d9ed29d0b138c74dd63c5744507fca"
|
||||||
|
integrity sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==
|
||||||
|
|
||||||
"@rollup/rollup-darwin-arm64@4.29.1":
|
"@rollup/rollup-darwin-arm64@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz#bc6fa8a2cc77b5f367424e5e994e3537524e6879"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz#bc6fa8a2cc77b5f367424e5e994e3537524e6879"
|
||||||
integrity sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==
|
integrity sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==
|
||||||
|
|
||||||
|
"@rollup/rollup-darwin-arm64@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz#830d07794d6a407c12b484b8cf71affd4d3800a6"
|
||||||
|
integrity sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==
|
||||||
|
|
||||||
"@rollup/rollup-darwin-x64@4.29.1":
|
"@rollup/rollup-darwin-x64@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz#76059c91f06b17406347b127df10f065283b2e61"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz#76059c91f06b17406347b127df10f065283b2e61"
|
||||||
integrity sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==
|
integrity sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==
|
||||||
|
|
||||||
|
"@rollup/rollup-darwin-x64@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz#b26f0f47005c1fa5419a880f323ed509dc8d885c"
|
||||||
|
integrity sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-arm64@4.29.1":
|
"@rollup/rollup-freebsd-arm64@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz#83178315c0be4b4c8c1fd835e1952d2dc1eb4e6e"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz#83178315c0be4b4c8c1fd835e1952d2dc1eb4e6e"
|
||||||
integrity sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==
|
integrity sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==
|
||||||
|
|
||||||
|
"@rollup/rollup-freebsd-arm64@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz#2b60c81ac01ff7d1bc8df66aee7808b6690c6d19"
|
||||||
|
integrity sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-x64@4.29.1":
|
"@rollup/rollup-freebsd-x64@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz#1ef24fa0576bf7899a0a0a649156606dbd7a0d46"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz#1ef24fa0576bf7899a0a0a649156606dbd7a0d46"
|
||||||
integrity sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==
|
integrity sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==
|
||||||
|
|
||||||
|
"@rollup/rollup-freebsd-x64@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz#4826af30f4d933d82221289068846c9629cc628c"
|
||||||
|
integrity sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-gnueabihf@4.29.1":
|
"@rollup/rollup-linux-arm-gnueabihf@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz#443a6f5681bf4611caae42988994a6d8ee676216"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz#443a6f5681bf4611caae42988994a6d8ee676216"
|
||||||
integrity sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==
|
integrity sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm-gnueabihf@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz#a1f4f963d5dcc9e5575c7acf9911824806436bf7"
|
||||||
|
integrity sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-musleabihf@4.29.1":
|
"@rollup/rollup-linux-arm-musleabihf@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz#9738b27184102228637a683e5f35b22ea352394f"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz#9738b27184102228637a683e5f35b22ea352394f"
|
||||||
integrity sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==
|
integrity sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm-musleabihf@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz#e924b0a8b7c400089146f6278446e6b398b75a06"
|
||||||
|
integrity sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-gnu@4.29.1":
|
"@rollup/rollup-linux-arm64-gnu@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz#b5e9d5e30ff36a19bedd29c715ba18a1889ff269"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz#b5e9d5e30ff36a19bedd29c715ba18a1889ff269"
|
||||||
integrity sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==
|
integrity sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm64-gnu@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz#cb43303274ec9a716f4440b01ab4e20c23aebe20"
|
||||||
|
integrity sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-musl@4.29.1":
|
"@rollup/rollup-linux-arm64-musl@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz#1d8f68f0829b57f746ec03432ad046f1af014a98"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz#1d8f68f0829b57f746ec03432ad046f1af014a98"
|
||||||
integrity sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==
|
integrity sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm64-musl@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz#531c92533ce3d167f2111bfcd2aa1a2041266987"
|
||||||
|
integrity sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==
|
||||||
|
|
||||||
"@rollup/rollup-linux-loongarch64-gnu@4.29.1":
|
"@rollup/rollup-linux-loongarch64-gnu@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz#07027feb883408e74a3002c8e50caaedd288ae38"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz#07027feb883408e74a3002c8e50caaedd288ae38"
|
||||||
integrity sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==
|
integrity sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-loongarch64-gnu@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz#53403889755d0c37c92650aad016d5b06c1b061a"
|
||||||
|
integrity sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==
|
||||||
|
|
||||||
"@rollup/rollup-linux-powerpc64le-gnu@4.29.1":
|
"@rollup/rollup-linux-powerpc64le-gnu@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz#544ce1b0847a9c1240425e86f33daceac7ec4e12"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz#544ce1b0847a9c1240425e86f33daceac7ec4e12"
|
||||||
integrity sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==
|
integrity sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-powerpc64le-gnu@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz#f669f162e29094c819c509e99dbeced58fc708f9"
|
||||||
|
integrity sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-gnu@4.29.1":
|
"@rollup/rollup-linux-riscv64-gnu@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz#64be13d51852ec1e2dfbd25d997ed5f42f35ea6d"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz#64be13d51852ec1e2dfbd25d997ed5f42f35ea6d"
|
||||||
integrity sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==
|
integrity sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-riscv64-gnu@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz#4bab37353b11bcda5a74ca11b99dea929657fd5f"
|
||||||
|
integrity sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-riscv64-musl@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz#4d66be1ce3cfd40a7910eb34dddc7cbd4c2dd2a5"
|
||||||
|
integrity sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==
|
||||||
|
|
||||||
"@rollup/rollup-linux-s390x-gnu@4.29.1":
|
"@rollup/rollup-linux-s390x-gnu@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz#31f51e1e05c6264552d03875d9e2e673f0fd86e3"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz#31f51e1e05c6264552d03875d9e2e673f0fd86e3"
|
||||||
integrity sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==
|
integrity sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-s390x-gnu@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz#7181c329395ed53340a0c59678ad304a99627f6d"
|
||||||
|
integrity sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-gnu@4.29.1":
|
"@rollup/rollup-linux-x64-gnu@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz#f4c95b26f4ad69ebdb64b42f0ae4da2a0f617958"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz#f4c95b26f4ad69ebdb64b42f0ae4da2a0f617958"
|
||||||
integrity sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==
|
integrity sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-x64-gnu@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz#00825b3458094d5c27cb4ed66e88bfe9f1e65f90"
|
||||||
|
integrity sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-musl@4.29.1":
|
"@rollup/rollup-linux-x64-musl@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz#ab7be89192f72beb9ea6e2386186fefde4f69d82"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz#ab7be89192f72beb9ea6e2386186fefde4f69d82"
|
||||||
integrity sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==
|
integrity sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-x64-musl@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz#81caac2a31b8754186f3acc142953a178fcd6fba"
|
||||||
|
integrity sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==
|
||||||
|
|
||||||
"@rollup/rollup-win32-arm64-msvc@4.29.1":
|
"@rollup/rollup-win32-arm64-msvc@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz#7f12efb8240b238346951559998802722944421e"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz#7f12efb8240b238346951559998802722944421e"
|
||||||
integrity sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==
|
integrity sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-arm64-msvc@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz#3a3f421f5ce9bd99ed20ce1660cce7cee3e9f199"
|
||||||
|
integrity sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==
|
||||||
|
|
||||||
"@rollup/rollup-win32-ia32-msvc@4.29.1":
|
"@rollup/rollup-win32-ia32-msvc@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz#353d14d6eee943004d129796e4feddd3aa260921"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz#353d14d6eee943004d129796e4feddd3aa260921"
|
||||||
integrity sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==
|
integrity sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-ia32-msvc@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz#a44972d5cdd484dfd9cf3705a884bf0c2b7785a7"
|
||||||
|
integrity sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-msvc@4.29.1":
|
"@rollup/rollup-win32-x64-msvc@4.29.1":
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz#c82f04a09ba481e13857d6f2516e072aaa51b7f4"
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz#c82f04a09ba481e13857d6f2516e072aaa51b7f4"
|
||||||
integrity sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==
|
integrity sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-x64-msvc@4.39.0":
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz#bfe0214e163f70c4fec1c8f7bb8ce266f4c05b7e"
|
||||||
|
integrity sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==
|
||||||
|
|
||||||
"@types/estree@1.0.6", "@types/estree@^1.0.0":
|
"@types/estree@1.0.6", "@types/estree@^1.0.0":
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
||||||
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
||||||
|
|
||||||
"@vitest/expect@2.1.9":
|
"@types/estree@1.0.7":
|
||||||
version "2.1.9"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.9.tgz#b566ea20d58ea6578d8dc37040d6c1a47ebe5ff8"
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8"
|
||||||
integrity sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==
|
integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==
|
||||||
dependencies:
|
|
||||||
"@vitest/spy" "2.1.9"
|
|
||||||
"@vitest/utils" "2.1.9"
|
|
||||||
chai "^5.1.2"
|
|
||||||
tinyrainbow "^1.2.0"
|
|
||||||
|
|
||||||
"@vitest/mocker@2.1.9":
|
"@vitest/expect@3.1.1":
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.9.tgz#36243b27351ca8f4d0bbc4ef91594ffd2dc25ef5"
|
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.1.1.tgz#d64ddfdcf9e877d805e1eee67bd845bf0708c6c2"
|
||||||
integrity sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==
|
integrity sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vitest/spy" "2.1.9"
|
"@vitest/spy" "3.1.1"
|
||||||
|
"@vitest/utils" "3.1.1"
|
||||||
|
chai "^5.2.0"
|
||||||
|
tinyrainbow "^2.0.0"
|
||||||
|
|
||||||
|
"@vitest/mocker@3.1.1":
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.1.1.tgz#7689d99f87498684c71e9fe9defdbd13ffb7f1ac"
|
||||||
|
integrity sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==
|
||||||
|
dependencies:
|
||||||
|
"@vitest/spy" "3.1.1"
|
||||||
estree-walker "^3.0.3"
|
estree-walker "^3.0.3"
|
||||||
magic-string "^0.30.12"
|
magic-string "^0.30.17"
|
||||||
|
|
||||||
"@vitest/pretty-format@2.1.9", "@vitest/pretty-format@^2.1.9":
|
"@vitest/pretty-format@3.1.1", "@vitest/pretty-format@^3.1.1":
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.9.tgz#434ff2f7611689f9ce70cd7d567eceb883653fdf"
|
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.1.1.tgz#5b4d577771daccfced47baf3bf026ad59b52c283"
|
||||||
integrity sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==
|
integrity sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==
|
||||||
dependencies:
|
dependencies:
|
||||||
tinyrainbow "^1.2.0"
|
tinyrainbow "^2.0.0"
|
||||||
|
|
||||||
"@vitest/runner@2.1.9":
|
"@vitest/runner@3.1.1":
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.9.tgz#cc18148d2d797fd1fd5908d1f1851d01459be2f6"
|
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.1.1.tgz#76b598700737089d66c74272b2e1c94ca2891a49"
|
||||||
integrity sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==
|
integrity sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vitest/utils" "2.1.9"
|
"@vitest/utils" "3.1.1"
|
||||||
pathe "^1.1.2"
|
pathe "^2.0.3"
|
||||||
|
|
||||||
"@vitest/snapshot@2.1.9":
|
"@vitest/snapshot@3.1.1":
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.9.tgz#24260b93f798afb102e2dcbd7e61c6dfa118df91"
|
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-3.1.1.tgz#42b6aa0d0e2b3b48b95a5c76efdcc66a44cb11f3"
|
||||||
integrity sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==
|
integrity sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vitest/pretty-format" "2.1.9"
|
"@vitest/pretty-format" "3.1.1"
|
||||||
magic-string "^0.30.12"
|
magic-string "^0.30.17"
|
||||||
pathe "^1.1.2"
|
pathe "^2.0.3"
|
||||||
|
|
||||||
"@vitest/spy@2.1.9":
|
"@vitest/spy@3.1.1":
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.9.tgz#cb28538c5039d09818b8bfa8edb4043c94727c60"
|
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.1.1.tgz#deca0b025e151302ab514f38390fd7777e294837"
|
||||||
integrity sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==
|
integrity sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
tinyspy "^3.0.2"
|
tinyspy "^3.0.2"
|
||||||
|
|
||||||
"@vitest/utils@2.1.9":
|
"@vitest/utils@3.1.1":
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.9.tgz#4f2486de8a54acf7ecbf2c5c24ad7994a680a6c1"
|
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.1.1.tgz#2893c30219ab6bdf109f07ce5cd287fe8058438d"
|
||||||
integrity sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==
|
integrity sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vitest/pretty-format" "2.1.9"
|
"@vitest/pretty-format" "3.1.1"
|
||||||
loupe "^3.1.2"
|
loupe "^3.1.3"
|
||||||
tinyrainbow "^1.2.0"
|
tinyrainbow "^2.0.0"
|
||||||
|
|
||||||
assertion-error@^2.0.1:
|
assertion-error@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
@ -382,10 +497,10 @@ cac@^6.7.14:
|
|||||||
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
|
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
|
||||||
integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
|
integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
|
||||||
|
|
||||||
chai@^5.1.2:
|
chai@^5.2.0:
|
||||||
version "5.1.2"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d"
|
resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05"
|
||||||
integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==
|
integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==
|
||||||
dependencies:
|
dependencies:
|
||||||
assertion-error "^2.0.1"
|
assertion-error "^2.0.1"
|
||||||
check-error "^2.1.1"
|
check-error "^2.1.1"
|
||||||
@ -398,7 +513,7 @@ check-error@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
|
resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
|
||||||
integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
|
integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
|
||||||
|
|
||||||
debug@^4.1.1, debug@^4.3.7:
|
debug@^4.1.1, debug@^4.4.0:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
|
||||||
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
|
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
|
||||||
@ -410,39 +525,41 @@ deep-eql@^5.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
|
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
|
||||||
integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
|
integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
|
||||||
|
|
||||||
es-module-lexer@^1.5.4:
|
es-module-lexer@^1.6.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21"
|
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21"
|
||||||
integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==
|
integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==
|
||||||
|
|
||||||
esbuild@^0.21.3:
|
esbuild@^0.25.0:
|
||||||
version "0.21.5"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.2.tgz#55a1d9ebcb3aa2f95e8bba9e900c1a5061bc168b"
|
||||||
integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==
|
integrity sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@esbuild/aix-ppc64" "0.21.5"
|
"@esbuild/aix-ppc64" "0.25.2"
|
||||||
"@esbuild/android-arm" "0.21.5"
|
"@esbuild/android-arm" "0.25.2"
|
||||||
"@esbuild/android-arm64" "0.21.5"
|
"@esbuild/android-arm64" "0.25.2"
|
||||||
"@esbuild/android-x64" "0.21.5"
|
"@esbuild/android-x64" "0.25.2"
|
||||||
"@esbuild/darwin-arm64" "0.21.5"
|
"@esbuild/darwin-arm64" "0.25.2"
|
||||||
"@esbuild/darwin-x64" "0.21.5"
|
"@esbuild/darwin-x64" "0.25.2"
|
||||||
"@esbuild/freebsd-arm64" "0.21.5"
|
"@esbuild/freebsd-arm64" "0.25.2"
|
||||||
"@esbuild/freebsd-x64" "0.21.5"
|
"@esbuild/freebsd-x64" "0.25.2"
|
||||||
"@esbuild/linux-arm" "0.21.5"
|
"@esbuild/linux-arm" "0.25.2"
|
||||||
"@esbuild/linux-arm64" "0.21.5"
|
"@esbuild/linux-arm64" "0.25.2"
|
||||||
"@esbuild/linux-ia32" "0.21.5"
|
"@esbuild/linux-ia32" "0.25.2"
|
||||||
"@esbuild/linux-loong64" "0.21.5"
|
"@esbuild/linux-loong64" "0.25.2"
|
||||||
"@esbuild/linux-mips64el" "0.21.5"
|
"@esbuild/linux-mips64el" "0.25.2"
|
||||||
"@esbuild/linux-ppc64" "0.21.5"
|
"@esbuild/linux-ppc64" "0.25.2"
|
||||||
"@esbuild/linux-riscv64" "0.21.5"
|
"@esbuild/linux-riscv64" "0.25.2"
|
||||||
"@esbuild/linux-s390x" "0.21.5"
|
"@esbuild/linux-s390x" "0.25.2"
|
||||||
"@esbuild/linux-x64" "0.21.5"
|
"@esbuild/linux-x64" "0.25.2"
|
||||||
"@esbuild/netbsd-x64" "0.21.5"
|
"@esbuild/netbsd-arm64" "0.25.2"
|
||||||
"@esbuild/openbsd-x64" "0.21.5"
|
"@esbuild/netbsd-x64" "0.25.2"
|
||||||
"@esbuild/sunos-x64" "0.21.5"
|
"@esbuild/openbsd-arm64" "0.25.2"
|
||||||
"@esbuild/win32-arm64" "0.21.5"
|
"@esbuild/openbsd-x64" "0.25.2"
|
||||||
"@esbuild/win32-ia32" "0.21.5"
|
"@esbuild/sunos-x64" "0.25.2"
|
||||||
"@esbuild/win32-x64" "0.21.5"
|
"@esbuild/win32-arm64" "0.25.2"
|
||||||
|
"@esbuild/win32-ia32" "0.25.2"
|
||||||
|
"@esbuild/win32-x64" "0.25.2"
|
||||||
|
|
||||||
estree-walker@^2.0.2:
|
estree-walker@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
@ -456,10 +573,10 @@ estree-walker@^3.0.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/estree" "^1.0.0"
|
"@types/estree" "^1.0.0"
|
||||||
|
|
||||||
expect-type@^1.1.0:
|
expect-type@^1.2.0:
|
||||||
version "1.1.0"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75"
|
resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.1.tgz#af76d8b357cf5fa76c41c09dafb79c549e75f71f"
|
||||||
integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==
|
integrity sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==
|
||||||
|
|
||||||
fsevents@~2.3.2, fsevents@~2.3.3:
|
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||||
version "2.3.3"
|
version "2.3.3"
|
||||||
@ -495,12 +612,17 @@ js-tokens@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||||
|
|
||||||
loupe@^3.1.0, loupe@^3.1.2:
|
loupe@^3.1.0:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240"
|
resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240"
|
||||||
integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==
|
integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==
|
||||||
|
|
||||||
magic-string@^0.30.10, magic-string@^0.30.12:
|
loupe@^3.1.3:
|
||||||
|
version "3.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.3.tgz#042a8f7986d77f3d0f98ef7990a2b2fef18b0fd2"
|
||||||
|
integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==
|
||||||
|
|
||||||
|
magic-string@^0.30.10, magic-string@^0.30.17:
|
||||||
version "0.30.17"
|
version "0.30.17"
|
||||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
|
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
|
||||||
integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==
|
integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==
|
||||||
@ -512,20 +634,20 @@ ms@^2.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
nanoid@^3.3.7:
|
nanoid@^3.3.8:
|
||||||
version "3.3.8"
|
version "3.3.11"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
|
||||||
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
|
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
|
||||||
|
|
||||||
path-parse@^1.0.7:
|
path-parse@^1.0.7:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||||
|
|
||||||
pathe@^1.1.2:
|
pathe@^2.0.3:
|
||||||
version "1.1.2"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
|
resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716"
|
||||||
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
|
integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==
|
||||||
|
|
||||||
pathval@^2.0.0:
|
pathval@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -542,12 +664,12 @@ picomatch@^4.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab"
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab"
|
||||||
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
|
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
|
||||||
|
|
||||||
postcss@^8.4.43:
|
postcss@^8.5.3:
|
||||||
version "8.4.49"
|
version "8.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb"
|
||||||
integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
|
integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid "^3.3.7"
|
nanoid "^3.3.8"
|
||||||
picocolors "^1.1.1"
|
picocolors "^1.1.1"
|
||||||
source-map-js "^1.2.1"
|
source-map-js "^1.2.1"
|
||||||
|
|
||||||
@ -569,7 +691,7 @@ rollup-plugin-dts@^6.1.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@babel/code-frame" "^7.24.2"
|
"@babel/code-frame" "^7.24.2"
|
||||||
|
|
||||||
rollup@^4.20.0, rollup@^4.29.1:
|
rollup@^4.29.1:
|
||||||
version "4.29.1"
|
version "4.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.29.1.tgz#a9aaaece817e5f778489e5bf82e379cc8a5c05bc"
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.29.1.tgz#a9aaaece817e5f778489e5bf82e379cc8a5c05bc"
|
||||||
integrity sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==
|
integrity sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==
|
||||||
@ -597,6 +719,35 @@ rollup@^4.20.0, rollup@^4.29.1:
|
|||||||
"@rollup/rollup-win32-x64-msvc" "4.29.1"
|
"@rollup/rollup-win32-x64-msvc" "4.29.1"
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
rollup@^4.30.1:
|
||||||
|
version "4.39.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.39.0.tgz#9dc1013b70c0e2cb70ef28350142e9b81b3f640c"
|
||||||
|
integrity sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "1.0.7"
|
||||||
|
optionalDependencies:
|
||||||
|
"@rollup/rollup-android-arm-eabi" "4.39.0"
|
||||||
|
"@rollup/rollup-android-arm64" "4.39.0"
|
||||||
|
"@rollup/rollup-darwin-arm64" "4.39.0"
|
||||||
|
"@rollup/rollup-darwin-x64" "4.39.0"
|
||||||
|
"@rollup/rollup-freebsd-arm64" "4.39.0"
|
||||||
|
"@rollup/rollup-freebsd-x64" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-arm-gnueabihf" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-arm-musleabihf" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-arm64-gnu" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-arm64-musl" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-loongarch64-gnu" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-powerpc64le-gnu" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-riscv64-gnu" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-riscv64-musl" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-s390x-gnu" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-x64-gnu" "4.39.0"
|
||||||
|
"@rollup/rollup-linux-x64-musl" "4.39.0"
|
||||||
|
"@rollup/rollup-win32-arm64-msvc" "4.39.0"
|
||||||
|
"@rollup/rollup-win32-ia32-msvc" "4.39.0"
|
||||||
|
"@rollup/rollup-win32-x64-msvc" "4.39.0"
|
||||||
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
siginfo@^2.0.0:
|
siginfo@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30"
|
resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30"
|
||||||
@ -612,10 +763,10 @@ stackback@0.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
|
resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
|
||||||
integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==
|
integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==
|
||||||
|
|
||||||
std-env@^3.8.0:
|
std-env@^3.8.1:
|
||||||
version "3.8.0"
|
version "3.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5"
|
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.9.0.tgz#1a6f7243b339dca4c9fd55e1c7504c77ef23e8f1"
|
||||||
integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==
|
integrity sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==
|
||||||
|
|
||||||
style-mod@^4.0.0, style-mod@^4.1.0:
|
style-mod@^4.0.0, style-mod@^4.1.0:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
@ -632,20 +783,20 @@ tinybench@^2.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
|
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
|
||||||
integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
|
integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
|
||||||
|
|
||||||
tinyexec@^0.3.1:
|
tinyexec@^0.3.2:
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2"
|
resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2"
|
||||||
integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==
|
integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==
|
||||||
|
|
||||||
tinypool@^1.0.1:
|
tinypool@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2"
|
resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2"
|
||||||
integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==
|
integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==
|
||||||
|
|
||||||
tinyrainbow@^1.2.0:
|
tinyrainbow@^2.0.0:
|
||||||
version "1.2.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5"
|
resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294"
|
||||||
integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==
|
integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==
|
||||||
|
|
||||||
tinyspy@^3.0.2:
|
tinyspy@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
@ -662,61 +813,61 @@ typescript@^5.7.2:
|
|||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
|
||||||
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
|
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
|
||||||
|
|
||||||
vite-node@2.1.9:
|
vite-node@3.1.1:
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.9.tgz#549710f76a643f1c39ef34bdb5493a944e4f895f"
|
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.1.1.tgz#ad186c07859a6e5fca7c7f563e55fb11b16557bc"
|
||||||
integrity sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==
|
integrity sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==
|
||||||
dependencies:
|
dependencies:
|
||||||
cac "^6.7.14"
|
cac "^6.7.14"
|
||||||
debug "^4.3.7"
|
debug "^4.4.0"
|
||||||
es-module-lexer "^1.5.4"
|
es-module-lexer "^1.6.0"
|
||||||
pathe "^1.1.2"
|
pathe "^2.0.3"
|
||||||
vite "^5.0.0"
|
vite "^5.0.0 || ^6.0.0"
|
||||||
|
|
||||||
vite-tsconfig-paths@^4.3.2:
|
vite-tsconfig-paths@^5.1.4:
|
||||||
version "4.3.2"
|
version "5.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz#321f02e4b736a90ff62f9086467faf4e2da857a9"
|
resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz#d9a71106a7ff2c1c840c6f1708042f76a9212ed4"
|
||||||
integrity sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==
|
integrity sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.1.1"
|
debug "^4.1.1"
|
||||||
globrex "^0.1.2"
|
globrex "^0.1.2"
|
||||||
tsconfck "^3.0.3"
|
tsconfck "^3.0.3"
|
||||||
|
|
||||||
vite@^5.0.0:
|
"vite@^5.0.0 || ^6.0.0":
|
||||||
version "5.4.17"
|
version "6.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.17.tgz#4bf61dd4cdbf64b0d6661f5dba76954cc81d5082"
|
resolved "https://registry.yarnpkg.com/vite/-/vite-6.2.5.tgz#d093b5fe8eb96e594761584a966ab13f24457820"
|
||||||
integrity sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==
|
integrity sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild "^0.21.3"
|
esbuild "^0.25.0"
|
||||||
postcss "^8.4.43"
|
postcss "^8.5.3"
|
||||||
rollup "^4.20.0"
|
rollup "^4.30.1"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.3"
|
fsevents "~2.3.3"
|
||||||
|
|
||||||
vitest@^2.1.9:
|
vitest@^3.1.1:
|
||||||
version "2.1.9"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.9.tgz#7d01ffd07a553a51c87170b5e80fea3da7fb41e7"
|
resolved "https://registry.yarnpkg.com/vitest/-/vitest-3.1.1.tgz#39fa2356e510513fccdc5d16465a9fc066ef1fc6"
|
||||||
integrity sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==
|
integrity sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vitest/expect" "2.1.9"
|
"@vitest/expect" "3.1.1"
|
||||||
"@vitest/mocker" "2.1.9"
|
"@vitest/mocker" "3.1.1"
|
||||||
"@vitest/pretty-format" "^2.1.9"
|
"@vitest/pretty-format" "^3.1.1"
|
||||||
"@vitest/runner" "2.1.9"
|
"@vitest/runner" "3.1.1"
|
||||||
"@vitest/snapshot" "2.1.9"
|
"@vitest/snapshot" "3.1.1"
|
||||||
"@vitest/spy" "2.1.9"
|
"@vitest/spy" "3.1.1"
|
||||||
"@vitest/utils" "2.1.9"
|
"@vitest/utils" "3.1.1"
|
||||||
chai "^5.1.2"
|
chai "^5.2.0"
|
||||||
debug "^4.3.7"
|
debug "^4.4.0"
|
||||||
expect-type "^1.1.0"
|
expect-type "^1.2.0"
|
||||||
magic-string "^0.30.12"
|
magic-string "^0.30.17"
|
||||||
pathe "^1.1.2"
|
pathe "^2.0.3"
|
||||||
std-env "^3.8.0"
|
std-env "^3.8.1"
|
||||||
tinybench "^2.9.0"
|
tinybench "^2.9.0"
|
||||||
tinyexec "^0.3.1"
|
tinyexec "^0.3.2"
|
||||||
tinypool "^1.0.1"
|
tinypool "^1.0.2"
|
||||||
tinyrainbow "^1.2.0"
|
tinyrainbow "^2.0.0"
|
||||||
vite "^5.0.0"
|
vite "^5.0.0 || ^6.0.0"
|
||||||
vite-node "2.1.9"
|
vite-node "3.1.1"
|
||||||
why-is-node-running "^2.3.0"
|
why-is-node-running "^2.3.0"
|
||||||
|
|
||||||
w3c-keyname@^2.2.4:
|
w3c-keyname@^2.2.4:
|
||||||
|
@ -24,12 +24,12 @@
|
|||||||
"@lezer/highlight": "^1.2.1",
|
"@lezer/highlight": "^1.2.1",
|
||||||
"@ts-stack/markdown": "^1.5.0",
|
"@ts-stack/markdown": "^1.5.0",
|
||||||
"json-rpc-2.0": "^1.7.0",
|
"json-rpc-2.0": "^1.7.0",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.3",
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.1.0"
|
"vscode-uri": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.13.13",
|
"@types/node": "^22.14.0",
|
||||||
"ts-node": "^10.9.2"
|
"ts-node": "^10.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,12 +116,12 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
|
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
|
||||||
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
|
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
|
||||||
|
|
||||||
"@types/node@^22.13.13":
|
"@types/node@^22.14.0":
|
||||||
version "22.13.13"
|
version "22.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.13.tgz#5e7d110fb509b0d4a43fbf48fa9d6e0f83e1b1e7"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.0.tgz#d3bfa3936fef0dbacd79ea3eb17d521c628bb47e"
|
||||||
integrity sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==
|
integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~6.20.0"
|
undici-types "~6.21.0"
|
||||||
|
|
||||||
acorn-walk@^8.1.1:
|
acorn-walk@^8.1.1:
|
||||||
version "8.3.3"
|
version "8.3.3"
|
||||||
@ -189,15 +189,15 @@ tslib@^2.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
||||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||||
|
|
||||||
typescript@^5.8.2:
|
typescript@^5.8.3:
|
||||||
version "5.8.2"
|
version "5.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
|
||||||
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
|
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||||
|
|
||||||
undici-types@~6.20.0:
|
undici-types@~6.21.0:
|
||||||
version "6.20.0"
|
version "6.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
|
||||||
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
|
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
|
||||||
|
|
||||||
v8-compile-cache-lib@^3.0.1:
|
v8-compile-cache-lib@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
|
@ -94,4 +94,4 @@ outsideWallSketch = startSketchOn(offsetPlane(XY, offset = -overallThickness / 2
|
|||||||
|> circle(center = [0, 0], radius = outsideDiameter / 2)
|
|> circle(center = [0, 0], radius = outsideDiameter / 2)
|
||||||
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
|
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
|
||||||
|
|
||||||
outsideWall = extrude(outsideWallSketch, length = overallThickness)
|
outsideWall = extrude(outsideWallSketch, length = overallThickness)
|
||||||
|
@ -32,7 +32,7 @@ lugClearance = startSketchOn(lugExtrusion, 'END')
|
|||||||
|
|
||||||
// Create the circular pattern for the lug holes
|
// Create the circular pattern for the lug holes
|
||||||
lugHoles = startSketchOn(lugBase, 'END')
|
lugHoles = startSketchOn(lugBase, 'END')
|
||||||
|> circle(center = [lugSpacing / 2, 0], radius = 16 * mm() / 2)
|
|> circle(center = [lugSpacing / 2, 0], radius = fromMm(16) / 2)
|
||||||
|> patternCircular2d(
|
|> patternCircular2d(
|
||||||
arcDegrees = 360,
|
arcDegrees = 360,
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
|
@ -11,7 +11,7 @@ customPlane = {
|
|||||||
plane = {
|
plane = {
|
||||||
origin = {
|
origin = {
|
||||||
x = lugSpacing / 2,
|
x = lugSpacing / 2,
|
||||||
y = -30 * mm(),
|
y = fromMm(-30),
|
||||||
z = 0
|
z = 0
|
||||||
},
|
},
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
xAxis = { x = 1, y = 0, z = 0 },
|
||||||
@ -26,7 +26,7 @@ fn lug(plane, length, diameter) {
|
|||||||
|> angledLineOfYLength({ angle = 70, length = lugHeadLength }, %)
|
|> angledLineOfYLength({ angle = 70, length = lugHeadLength }, %)
|
||||||
|> xLine(endAbsolute = lugDiameter / 2)
|
|> xLine(endAbsolute = lugDiameter / 2)
|
||||||
|> yLine(endAbsolute = lugLength)
|
|> yLine(endAbsolute = lugLength)
|
||||||
|> tangentialArc({ offset = 90, radius = 3 * mm() }, %)
|
|> tangentialArc({ offset = 90, radius = fromMm(3) }, %)
|
||||||
|> xLine(endAbsolute = 0 + .001, tag = $c1)
|
|> xLine(endAbsolute = 0 + .001, tag = $c1)
|
||||||
|> yLine(endAbsolute = lugThreadDepth)
|
|> yLine(endAbsolute = lugThreadDepth)
|
||||||
|> xLine(endAbsolute = lugThreadDiameter)
|
|> xLine(endAbsolute = lugThreadDiameter)
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
// Car wheel
|
// Car wheel
|
||||||
export lugCount = 5
|
export lugCount = 5
|
||||||
export lugSpacing = 114.3 * mm()
|
export lugSpacing = fromMm(114.3)
|
||||||
export offset = -35 * mm()
|
export offset = fromMm(-35)
|
||||||
export backSpacing = 6.38
|
export backSpacing = 6.38
|
||||||
export wheelWidth = 9.5
|
export wheelWidth = 9.5
|
||||||
export wheelDiameter = 19
|
export wheelDiameter = 19
|
||||||
@ -16,11 +16,11 @@ export spokeAngle = 0.02
|
|||||||
export spokeThickness = 0.95
|
export spokeThickness = 0.95
|
||||||
|
|
||||||
// Lug Nut
|
// Lug Nut
|
||||||
export lugDiameter = 24 * mm()
|
export lugDiameter = fromMm(24)
|
||||||
export lugHeadLength = lugDiameter * .5
|
export lugHeadLength = lugDiameter * .5
|
||||||
export lugThreadDiameter = lugDiameter / 2 * .85
|
export lugThreadDiameter = lugDiameter / 2 * .85
|
||||||
export lugLength = 30 * mm()
|
export lugLength = fromMm(30)
|
||||||
export lugThreadDepth = lugLength - (12.7 * mm())
|
export lugThreadDepth = lugLength - fromMm(12.7)
|
||||||
|
|
||||||
// Car rotor
|
// Car rotor
|
||||||
export rotorDiameter = 12
|
export rotorDiameter = 12
|
||||||
|
@ -97,11 +97,11 @@ keyWay = startSketchOn(body, 'END')
|
|||||||
|> xLine(length = -keywayDepth)
|
|> xLine(length = -keywayDepth)
|
||||||
|> arc({
|
|> arc({
|
||||||
angleEnd = 180,
|
angleEnd = 180,
|
||||||
angleStart = -1 * 180 / PI * startAngle + 360,
|
angleStart = -1 * toDegrees(startAngle) + 360,
|
||||||
radius = holeRadius
|
radius = holeRadius
|
||||||
}, %)
|
}, %)
|
||||||
|> arc({
|
|> arc({
|
||||||
angleEnd = 180 / PI * startAngle,
|
angleEnd = toDegrees(startAngle),
|
||||||
angleStart = 180,
|
angleStart = 180,
|
||||||
radius = holeRadius
|
radius = holeRadius
|
||||||
}, %)
|
}, %)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
@settings(defaultLengthUnit = in)
|
@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
// Define parameters
|
// Define parameters
|
||||||
beamLength = 6 * ft()
|
beamLength = fromFt(6)
|
||||||
beamHeight = 4
|
beamHeight = 4
|
||||||
flangeWidth = 2.663
|
flangeWidth = 2.663
|
||||||
flangeThickness = 0.293
|
flangeThickness = 0.293
|
||||||
|
@ -21,7 +21,7 @@ archThickness = 1
|
|||||||
archRadius = mirrorRadius + archToMirrorGap
|
archRadius = mirrorRadius + archToMirrorGap
|
||||||
|
|
||||||
// Geometry
|
// Geometry
|
||||||
// Add a function to create the hinge
|
// Add a function to create the hinge
|
||||||
fn hingeFn(x, y, z) {
|
fn hingeFn(x, y, z) {
|
||||||
hingeBody = startSketchOn(offsetPlane(XY, offset = z))
|
hingeBody = startSketchOn(offsetPlane(XY, offset = z))
|
||||||
|> circle(center = [x, y], radius = hingeRadius)
|
|> circle(center = [x, y], radius = hingeRadius)
|
||||||
|
@ -9,7 +9,6 @@ import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "parameters.kcl"
|
|||||||
|
|
||||||
// Create a function to make the pipe. Export
|
// Create a function to make the pipe. Export
|
||||||
export fn pipe() {
|
export fn pipe() {
|
||||||
|
|
||||||
// Create the pipe base
|
// Create the pipe base
|
||||||
pipeBase = startSketchOn(XZ)
|
pipeBase = startSketchOn(XZ)
|
||||||
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|
||||||
|
@ -9,7 +9,6 @@ import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flange
|
|||||||
|
|
||||||
// Create a function to create the flange. We must create a function since we are using multiple flanges.
|
// Create a function to create the flange. We must create a function since we are using multiple flanges.
|
||||||
export fn flange() {
|
export fn flange() {
|
||||||
|
|
||||||
// Sketch the mounting hole pattern
|
// Sketch the mounting hole pattern
|
||||||
mountingHoles = startSketchOn(XY)
|
mountingHoles = startSketchOn(XY)
|
||||||
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|
||||||
@ -42,4 +41,4 @@ export fn flange() {
|
|||||||
|> appearance(%, color = "#bab0b0")
|
|> appearance(%, color = "#bab0b0")
|
||||||
|
|
||||||
return pipeCut
|
return pipeCut
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import hexNutDiameter, hexNutFlatToFlat, hexNutThickness, hexNutFlatLength from
|
|||||||
|
|
||||||
// Create a function to make the hex nut. Must be a function since multiple hex nuts are used
|
// Create a function to make the hex nut. Must be a function since multiple hex nuts are used
|
||||||
export fn hexNut() {
|
export fn hexNut() {
|
||||||
|
|
||||||
// Create the base of the hex nut
|
// Create the base of the hex nut
|
||||||
hexNutBase = startSketchOn(XY)
|
hexNutBase = startSketchOn(XY)
|
||||||
|> startProfileAt([
|
|> startProfileAt([
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// Import parameters
|
// Import parameters
|
||||||
import washerInnerDia, washerOuterDia, washerThickness from "parameters.kcl"
|
import washerInnerDia, washerOuterDia, washerThickness from "parameters.kcl"
|
||||||
|
|
||||||
// Create a function to make the washer. Must be a function since multiple washers are used.
|
// Create a function to make the washer. Must be a function since multiple washers are used.
|
||||||
export fn washer() {
|
export fn washer() {
|
||||||
// Create the base of the washer
|
// Create the base of the washer
|
||||||
washerBase = startSketchOn(XY)
|
washerBase = startSketchOn(XY)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
import * from "parameters.kcl"
|
import * from "parameters.kcl"
|
||||||
|
|
||||||
// Import parts
|
// Import parts
|
||||||
import '9472k188-gasket.kcl' as gasket
|
import "9472k188-gasket.kcl" as gasket
|
||||||
import flange from "68095k348-flange.kcl"
|
import flange from "68095k348-flange.kcl"
|
||||||
import washer from "98017a257-washer.kcl"
|
import washer from "98017a257-washer.kcl"
|
||||||
import bolt from "91251a404-bolt.kcl"
|
import bolt from "91251a404-bolt.kcl"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
// Define parameters
|
// Define parameters
|
||||||
routerDiameter = 12.7
|
routerDiameter = 12.7
|
||||||
templateDiameter = 11 / 16 * inch()
|
templateDiameter = fromInches(11 / 16)
|
||||||
slateWidthHalf = 41.5 / 2
|
slateWidthHalf = 41.5 / 2
|
||||||
minClampingDistance = 50 + 30
|
minClampingDistance = 50 + 30
|
||||||
templateThickness = 10
|
templateThickness = 10
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
// Define parameters
|
// Define parameters
|
||||||
routerDiameter = 12.7
|
routerDiameter = 12.7
|
||||||
templateDiameter = 11 / 16 * inch()
|
templateDiameter = fromInches(11 / 16)
|
||||||
slateWidthHalf = 41.5 / 2
|
slateWidthHalf = 41.5 / 2
|
||||||
minClampingDistance = 50 + 30
|
minClampingDistance = 50 + 30
|
||||||
templateThickness = 10
|
templateThickness = 10
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 69 KiB |
@ -764,14 +764,14 @@ fn rust_type_to_openapi_type(t: &str) -> String {
|
|||||||
t = format!("[{inner_type}]")
|
t = format!("[{inner_type}]")
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == "f64" {
|
if t == "f64" || t == "TyF64" {
|
||||||
return "number".to_string();
|
return "number".to_string();
|
||||||
} else if t == "u32" {
|
} else if t == "u32" {
|
||||||
return "integer".to_string();
|
return "integer".to_string();
|
||||||
} else if t == "str" {
|
} else if t == "str" {
|
||||||
return "string".to_string();
|
return "string".to_string();
|
||||||
} else {
|
} else {
|
||||||
return t.replace("f64", "number").to_string();
|
return t.replace("f64", "number").replace("TyF64", "number").to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,12 +138,12 @@
|
|||||||
"@typescript-eslint/eslint-plugin": "^8.27.0",
|
"@typescript-eslint/eslint-plugin": "^8.27.0",
|
||||||
"@typescript-eslint/parser": "^8.27.0",
|
"@typescript-eslint/parser": "^8.27.0",
|
||||||
"@vscode/test-electron": "^2.4.1",
|
"@vscode/test-electron": "^2.4.1",
|
||||||
"@vscode/vsce": "^3.3.0",
|
"@vscode/vsce": "^3.3.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"esbuild": "^0.25.1",
|
"esbuild": "^0.25.2",
|
||||||
"glob": "^11.0.1",
|
"glob": "^11.0.1",
|
||||||
"mocha": "^11.1.0",
|
"mocha": "^11.1.0",
|
||||||
"typescript": "^5.8.2"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vscode-languageclient": "^9.0.1"
|
"vscode-languageclient": "^9.0.1"
|
||||||
|
@ -120,130 +120,130 @@
|
|||||||
jsonwebtoken "^9.0.0"
|
jsonwebtoken "^9.0.0"
|
||||||
uuid "^8.3.0"
|
uuid "^8.3.0"
|
||||||
|
|
||||||
"@esbuild/aix-ppc64@0.25.1":
|
"@esbuild/aix-ppc64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz#c33cf6bbee34975626b01b80451cbb72b4c6c91d"
|
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz#b87036f644f572efb2b3c75746c97d1d2d87ace8"
|
||||||
integrity sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==
|
integrity sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==
|
||||||
|
|
||||||
"@esbuild/android-arm64@0.25.1":
|
"@esbuild/android-arm64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz#ea766015c7d2655164f22100d33d7f0308a28d6d"
|
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz#5ca7dc20a18f18960ad8d5e6ef5cf7b0a256e196"
|
||||||
integrity sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==
|
integrity sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==
|
||||||
|
|
||||||
"@esbuild/android-arm@0.25.1":
|
"@esbuild/android-arm@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.1.tgz#e84d2bf2fe2e6177a0facda3a575b2139fd3cb9c"
|
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.2.tgz#3c49f607b7082cde70c6ce0c011c362c57a194ee"
|
||||||
integrity sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==
|
integrity sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==
|
||||||
|
|
||||||
"@esbuild/android-x64@0.25.1":
|
"@esbuild/android-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.1.tgz#58337bee3bc6d78d10425e5500bd11370cfdfbed"
|
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.2.tgz#8a00147780016aff59e04f1036e7cb1b683859e2"
|
||||||
integrity sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==
|
integrity sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==
|
||||||
|
|
||||||
"@esbuild/darwin-arm64@0.25.1":
|
"@esbuild/darwin-arm64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz#a46805c1c585d451aa83be72500bd6e8495dd591"
|
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz#486efe7599a8d90a27780f2bb0318d9a85c6c423"
|
||||||
integrity sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==
|
integrity sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==
|
||||||
|
|
||||||
"@esbuild/darwin-x64@0.25.1":
|
"@esbuild/darwin-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz#0643e003bb238c63fc93ddbee7d26a003be3cd98"
|
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz#95ee222aacf668c7a4f3d7ee87b3240a51baf374"
|
||||||
integrity sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==
|
integrity sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==
|
||||||
|
|
||||||
"@esbuild/freebsd-arm64@0.25.1":
|
"@esbuild/freebsd-arm64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz#cff18da5469c09986b93e87979de5d6872fe8f8e"
|
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz#67efceda8554b6fc6a43476feba068fb37fa2ef6"
|
||||||
integrity sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==
|
integrity sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==
|
||||||
|
|
||||||
"@esbuild/freebsd-x64@0.25.1":
|
"@esbuild/freebsd-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz#362fc09c2de14987621c1878af19203c46365dde"
|
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz#88a9d7ecdd3adadbfe5227c2122d24816959b809"
|
||||||
integrity sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==
|
integrity sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==
|
||||||
|
|
||||||
"@esbuild/linux-arm64@0.25.1":
|
"@esbuild/linux-arm64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz#aa90d5b02efc97a271e124e6d1cea490634f7498"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz#87be1099b2bbe61282333b084737d46bc8308058"
|
||||||
integrity sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==
|
integrity sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==
|
||||||
|
|
||||||
"@esbuild/linux-arm@0.25.1":
|
"@esbuild/linux-arm@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz#dfcefcbac60a20918b19569b4b657844d39db35a"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz#72a285b0fe64496e191fcad222185d7bf9f816f6"
|
||||||
integrity sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==
|
integrity sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==
|
||||||
|
|
||||||
"@esbuild/linux-ia32@0.25.1":
|
"@esbuild/linux-ia32@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz#6f9527077ccb7953ed2af02e013d4bac69f13754"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz#337a87a4c4dd48a832baed5cbb022be20809d737"
|
||||||
integrity sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==
|
integrity sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==
|
||||||
|
|
||||||
"@esbuild/linux-loong64@0.25.1":
|
"@esbuild/linux-loong64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz#287d2412a5456e5860c2839d42a4b51284d1697c"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz#1b81aa77103d6b8a8cfa7c094ed3d25c7579ba2a"
|
||||||
integrity sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==
|
integrity sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==
|
||||||
|
|
||||||
"@esbuild/linux-mips64el@0.25.1":
|
"@esbuild/linux-mips64el@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz#530574b9e1bc5d20f7a4f44c5f045e26f3783d57"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz#afbe380b6992e7459bf7c2c3b9556633b2e47f30"
|
||||||
integrity sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==
|
integrity sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==
|
||||||
|
|
||||||
"@esbuild/linux-ppc64@0.25.1":
|
"@esbuild/linux-ppc64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz#5d7e6b283a0b321ea42c6bc0abeb9eb99c1f5589"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz#6bf8695cab8a2b135cca1aa555226dc932d52067"
|
||||||
integrity sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==
|
integrity sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==
|
||||||
|
|
||||||
"@esbuild/linux-riscv64@0.25.1":
|
"@esbuild/linux-riscv64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz#14fa0cd073c26b4ee2465d18cd1e18eea7859fa8"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz#43c2d67a1a39199fb06ba978aebb44992d7becc3"
|
||||||
integrity sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==
|
integrity sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==
|
||||||
|
|
||||||
"@esbuild/linux-s390x@0.25.1":
|
"@esbuild/linux-s390x@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz#e677b4b9d1b384098752266ccaa0d52a420dc1aa"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz#419e25737ec815c6dce2cd20d026e347cbb7a602"
|
||||||
integrity sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==
|
integrity sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==
|
||||||
|
|
||||||
"@esbuild/linux-x64@0.25.1":
|
"@esbuild/linux-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz#f1c796b78fff5ce393658313e8c58613198d9954"
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz#22451f6edbba84abe754a8cbd8528ff6e28d9bcb"
|
||||||
integrity sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==
|
integrity sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==
|
||||||
|
|
||||||
"@esbuild/netbsd-arm64@0.25.1":
|
"@esbuild/netbsd-arm64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz#0d280b7dfe3973f111b02d5fe9f3063b92796d29"
|
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz#744affd3b8d8236b08c5210d828b0698a62c58ac"
|
||||||
integrity sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==
|
integrity sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==
|
||||||
|
|
||||||
"@esbuild/netbsd-x64@0.25.1":
|
"@esbuild/netbsd-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz#be663893931a4bb3f3a009c5cc24fa9681cc71c0"
|
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz#dbbe7521fd6d7352f34328d676af923fc0f8a78f"
|
||||||
integrity sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==
|
integrity sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==
|
||||||
|
|
||||||
"@esbuild/openbsd-arm64@0.25.1":
|
"@esbuild/openbsd-arm64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz#d9021b884233673a05dc1cc26de0bf325d824217"
|
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz#f9caf987e3e0570500832b487ce3039ca648ce9f"
|
||||||
integrity sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==
|
integrity sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==
|
||||||
|
|
||||||
"@esbuild/openbsd-x64@0.25.1":
|
"@esbuild/openbsd-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz#9f1dc1786ed2e2938c404b06bcc48be9a13250de"
|
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz#d2bb6a0f8ffea7b394bb43dfccbb07cabd89f768"
|
||||||
integrity sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==
|
integrity sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==
|
||||||
|
|
||||||
"@esbuild/sunos-x64@0.25.1":
|
"@esbuild/sunos-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz#89aac24a4b4115959b3f790192cf130396696c27"
|
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz#49b437ed63fe333b92137b7a0c65a65852031afb"
|
||||||
integrity sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==
|
integrity sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==
|
||||||
|
|
||||||
"@esbuild/win32-arm64@0.25.1":
|
"@esbuild/win32-arm64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz#354358647a6ea98ea6d243bf48bdd7a434999582"
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz#081424168463c7d6c7fb78f631aede0c104373cf"
|
||||||
integrity sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==
|
integrity sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==
|
||||||
|
|
||||||
"@esbuild/win32-ia32@0.25.1":
|
"@esbuild/win32-ia32@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz#8cea7340f2647eba951a041dc95651e3908cd4cb"
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz#3f9e87143ddd003133d21384944a6c6cadf9693f"
|
||||||
integrity sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==
|
integrity sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==
|
||||||
|
|
||||||
"@esbuild/win32-x64@0.25.1":
|
"@esbuild/win32-x64@0.25.2":
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz#7d79922cb2d88f9048f06393dbf62d2e4accb584"
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz#839f72c2decd378f86b8f525e1979a97b920c67d"
|
||||||
integrity sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==
|
integrity sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==
|
||||||
|
|
||||||
"@eslint-community/eslint-utils@^4.4.0":
|
"@eslint-community/eslint-utils@^4.4.0":
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
@ -482,10 +482,10 @@
|
|||||||
"@vscode/vsce-sign-win32-arm64" "2.0.2"
|
"@vscode/vsce-sign-win32-arm64" "2.0.2"
|
||||||
"@vscode/vsce-sign-win32-x64" "2.0.2"
|
"@vscode/vsce-sign-win32-x64" "2.0.2"
|
||||||
|
|
||||||
"@vscode/vsce@^3.3.0":
|
"@vscode/vsce@^3.3.2":
|
||||||
version "3.3.0"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-3.3.0.tgz#803e41368a95d35693ce049076503f34f89fde09"
|
resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-3.3.2.tgz#1bb86222987814dbb3217c3f8befd63f249c8101"
|
||||||
integrity sha512-HA/pUyvh/TQWkc4wG7AudPIWUvsR8i4jiWZZgM/a69ncPi9Nm5FDogf/wVEk4EWJs4/UdxU7J6X18dfAwfPbxA==
|
integrity sha512-XQ4IhctYalSTMwLnMS8+nUaGbU7v99Qm2sOoGfIEf2QC7jpiLXZZMh7NwArEFsKX4gHTJLx0/GqAUlCdC3gKCw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@azure/identity" "^4.1.0"
|
"@azure/identity" "^4.1.0"
|
||||||
"@vscode/vsce-sign" "^2.0.0"
|
"@vscode/vsce-sign" "^2.0.0"
|
||||||
@ -993,36 +993,36 @@ es-errors@^1.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||||
|
|
||||||
esbuild@^0.25.1:
|
esbuild@^0.25.2:
|
||||||
version "0.25.1"
|
version "0.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.1.tgz#a16b8d070b6ad4871935277bda6ccfe852e3fa2f"
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.2.tgz#55a1d9ebcb3aa2f95e8bba9e900c1a5061bc168b"
|
||||||
integrity sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==
|
integrity sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@esbuild/aix-ppc64" "0.25.1"
|
"@esbuild/aix-ppc64" "0.25.2"
|
||||||
"@esbuild/android-arm" "0.25.1"
|
"@esbuild/android-arm" "0.25.2"
|
||||||
"@esbuild/android-arm64" "0.25.1"
|
"@esbuild/android-arm64" "0.25.2"
|
||||||
"@esbuild/android-x64" "0.25.1"
|
"@esbuild/android-x64" "0.25.2"
|
||||||
"@esbuild/darwin-arm64" "0.25.1"
|
"@esbuild/darwin-arm64" "0.25.2"
|
||||||
"@esbuild/darwin-x64" "0.25.1"
|
"@esbuild/darwin-x64" "0.25.2"
|
||||||
"@esbuild/freebsd-arm64" "0.25.1"
|
"@esbuild/freebsd-arm64" "0.25.2"
|
||||||
"@esbuild/freebsd-x64" "0.25.1"
|
"@esbuild/freebsd-x64" "0.25.2"
|
||||||
"@esbuild/linux-arm" "0.25.1"
|
"@esbuild/linux-arm" "0.25.2"
|
||||||
"@esbuild/linux-arm64" "0.25.1"
|
"@esbuild/linux-arm64" "0.25.2"
|
||||||
"@esbuild/linux-ia32" "0.25.1"
|
"@esbuild/linux-ia32" "0.25.2"
|
||||||
"@esbuild/linux-loong64" "0.25.1"
|
"@esbuild/linux-loong64" "0.25.2"
|
||||||
"@esbuild/linux-mips64el" "0.25.1"
|
"@esbuild/linux-mips64el" "0.25.2"
|
||||||
"@esbuild/linux-ppc64" "0.25.1"
|
"@esbuild/linux-ppc64" "0.25.2"
|
||||||
"@esbuild/linux-riscv64" "0.25.1"
|
"@esbuild/linux-riscv64" "0.25.2"
|
||||||
"@esbuild/linux-s390x" "0.25.1"
|
"@esbuild/linux-s390x" "0.25.2"
|
||||||
"@esbuild/linux-x64" "0.25.1"
|
"@esbuild/linux-x64" "0.25.2"
|
||||||
"@esbuild/netbsd-arm64" "0.25.1"
|
"@esbuild/netbsd-arm64" "0.25.2"
|
||||||
"@esbuild/netbsd-x64" "0.25.1"
|
"@esbuild/netbsd-x64" "0.25.2"
|
||||||
"@esbuild/openbsd-arm64" "0.25.1"
|
"@esbuild/openbsd-arm64" "0.25.2"
|
||||||
"@esbuild/openbsd-x64" "0.25.1"
|
"@esbuild/openbsd-x64" "0.25.2"
|
||||||
"@esbuild/sunos-x64" "0.25.1"
|
"@esbuild/sunos-x64" "0.25.2"
|
||||||
"@esbuild/win32-arm64" "0.25.1"
|
"@esbuild/win32-arm64" "0.25.2"
|
||||||
"@esbuild/win32-ia32" "0.25.1"
|
"@esbuild/win32-ia32" "0.25.2"
|
||||||
"@esbuild/win32-x64" "0.25.1"
|
"@esbuild/win32-x64" "0.25.2"
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
@ -2257,10 +2257,10 @@ typed-rest-client@^1.8.4:
|
|||||||
tunnel "0.0.6"
|
tunnel "0.0.6"
|
||||||
underscore "^1.12.1"
|
underscore "^1.12.1"
|
||||||
|
|
||||||
typescript@^5.8.2:
|
typescript@^5.8.3:
|
||||||
version "5.8.2"
|
version "5.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
|
||||||
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
|
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||||
|
|
||||||
uc.micro@^2.0.0, uc.micro@^2.1.0:
|
uc.micro@^2.0.0, uc.micro@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
|
@ -865,7 +865,7 @@ part = rectShape([0, 0], 20, 20)
|
|||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err.error.message(),
|
err.error.message(),
|
||||||
"The input argument of std::sketch::circle requires a value with type `Sketch | Plane | Face`, but found string (text)"
|
"The input argument of `std::sketch::circle` requires a value with type `Sketch | Plane | Face`, but found string (text)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,7 +709,7 @@ fn add_to_types(
|
|||||||
return Err(anyhow::anyhow!("Empty type name"));
|
return Err(anyhow::anyhow!("Empty type name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if DECLARED_TYPES.contains(&name) {
|
if DECLARED_TYPES.contains(&name) || name == "TyF64" {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,7 +769,7 @@ fn generate_type(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip over TagDeclarator and TagIdentifier since they have custom docs.
|
// Skip over TagDeclarator and TagIdentifier since they have custom docs.
|
||||||
if name == "TagDeclarator" || name == "TagIdentifier" || name == "TagNode" {
|
if name == "TagDeclarator" || name == "TagIdentifier" || name == "TagNode" || name == "TyF64" {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,7 +930,7 @@ fn recurse_and_create_references(
|
|||||||
schema: &schemars::schema::Schema,
|
schema: &schemars::schema::Schema,
|
||||||
types: &BTreeMap<String, schemars::schema::Schema>,
|
types: &BTreeMap<String, schemars::schema::Schema>,
|
||||||
) -> Result<schemars::schema::Schema> {
|
) -> Result<schemars::schema::Schema> {
|
||||||
if DECLARED_TYPES.contains(&name) {
|
if DECLARED_TYPES.contains(&name) || name == "TyF64" {
|
||||||
return Ok(schema.clone());
|
return Ok(schema.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -944,7 +944,7 @@ fn recurse_and_create_references(
|
|||||||
if let Some(reference) = &o.reference {
|
if let Some(reference) = &o.reference {
|
||||||
let mut obj = o.clone();
|
let mut obj = o.clone();
|
||||||
let reference = reference.trim_start_matches("#/components/schemas/");
|
let reference = reference.trim_start_matches("#/components/schemas/");
|
||||||
if DECLARED_TYPES.contains(&reference) {
|
if DECLARED_TYPES.contains(&reference) || reference == "TyF64" {
|
||||||
return Ok(schema.clone());
|
return Ok(schema.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +93,16 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
/// Get the artifact commands that have accumulated so far.
|
/// Get the artifact commands that have accumulated so far.
|
||||||
fn artifact_commands(&self) -> Arc<RwLock<Vec<ArtifactCommand>>>;
|
fn artifact_commands(&self) -> Arc<RwLock<Vec<ArtifactCommand>>>;
|
||||||
|
|
||||||
|
/// Take the batch of commands that have accumulated so far and clear them.
|
||||||
|
async fn take_batch(&self) -> Vec<(WebSocketRequest, SourceRange)> {
|
||||||
|
std::mem::take(&mut *self.batch().write().await)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Take the batch of end commands that have accumulated so far and clear them.
|
||||||
|
async fn take_batch_end(&self) -> IndexMap<Uuid, (WebSocketRequest, SourceRange)> {
|
||||||
|
std::mem::take(&mut *self.batch_end().write().await)
|
||||||
|
}
|
||||||
|
|
||||||
/// Clear all artifact commands that have accumulated so far.
|
/// Clear all artifact commands that have accumulated so far.
|
||||||
async fn clear_artifact_commands(&self) {
|
async fn clear_artifact_commands(&self) {
|
||||||
self.artifact_commands().write().await.clear();
|
self.artifact_commands().write().await.clear();
|
||||||
@ -370,11 +380,11 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
|
) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
|
||||||
let all_requests = if batch_end {
|
let all_requests = if batch_end {
|
||||||
let mut requests = self.batch().read().await.clone();
|
let mut requests = self.take_batch().await.clone();
|
||||||
requests.extend(self.batch_end().read().await.values().cloned());
|
requests.extend(self.take_batch_end().await.values().cloned());
|
||||||
requests
|
requests
|
||||||
} else {
|
} else {
|
||||||
self.batch().read().await.clone()
|
self.take_batch().await.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return early if we have no commands to send.
|
// Return early if we have no commands to send.
|
||||||
@ -442,11 +452,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw away the old batch queue.
|
|
||||||
self.batch().write().await.clear();
|
|
||||||
if batch_end {
|
|
||||||
self.batch_end().write().await.clear();
|
|
||||||
}
|
|
||||||
self.stats().batches_sent.fetch_add(1, Ordering::Relaxed);
|
self.stats().batches_sent.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
// We pop off the responses to cleanup our mappings.
|
// We pop off the responses to cleanup our mappings.
|
||||||
|
@ -120,7 +120,7 @@ impl From<KclErrorWithOutputs> for KclError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug, Serialize, Deserialize, ts_rs::TS, Clone, PartialEq)]
|
#[derive(Error, Debug, Serialize, ts_rs::TS, Clone, PartialEq)]
|
||||||
#[error("{error}")]
|
#[error("{error}")]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -3,11 +3,11 @@ use schemars::JsonSchema;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{types::NumericType, ArtifactId, KclValue};
|
use super::{types::NumericType, ArtifactId, KclValue};
|
||||||
use crate::{docs::StdLibFn, std::get_stdlib_fn, ModuleId, SourceRange};
|
use crate::{docs::StdLibFn, ModuleId, SourceRange};
|
||||||
|
|
||||||
/// A CAD modeling operation for display in the feature tree, AKA operations
|
/// A CAD modeling operation for display in the feature tree, AKA operations
|
||||||
/// timeline.
|
/// timeline.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export_to = "Operation.ts")]
|
#[ts(export_to = "Operation.ts")]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
@ -60,7 +60,7 @@ impl Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export_to = "Operation.ts")]
|
#[ts(export_to = "Operation.ts")]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
#[expect(clippy::large_enum_variant)]
|
#[expect(clippy::large_enum_variant)]
|
||||||
@ -90,7 +90,7 @@ pub enum Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An argument to a CAD modeling operation.
|
/// An argument to a CAD modeling operation.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export_to = "Operation.ts")]
|
#[ts(export_to = "Operation.ts")]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct OpArg {
|
pub struct OpArg {
|
||||||
@ -110,7 +110,7 @@ impl OpArg {
|
|||||||
|
|
||||||
/// A reference to a standard library function. This exists to implement
|
/// A reference to a standard library function. This exists to implement
|
||||||
/// `PartialEq` and `Eq` for `Operation`.
|
/// `PartialEq` and `Eq` for `Operation`.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export_to = "Operation.ts")]
|
#[ts(export_to = "Operation.ts")]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct StdLibFnRef {
|
pub struct StdLibFnRef {
|
||||||
@ -156,25 +156,13 @@ where
|
|||||||
serializer.serialize_str(&name)
|
serializer.serialize_str(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn std_lib_fn_from_name<'de, D>(deserializer: D) -> Result<Box<dyn StdLibFn>, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let s = String::deserialize(deserializer)?;
|
|
||||||
if let Some(std_lib_fn) = get_stdlib_fn(&s) {
|
|
||||||
Ok(std_lib_fn)
|
|
||||||
} else {
|
|
||||||
Err(serde::de::Error::custom(format!("not a KCL stdlib function: {}", s)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_false(b: &bool) -> bool {
|
fn is_false(b: &bool) -> bool {
|
||||||
!*b
|
!*b
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A KCL value used in Operations. `ArtifactId`s are used to refer to the
|
/// A KCL value used in Operations. `ArtifactId`s are used to refer to the
|
||||||
/// actual scene objects. Any data not needed in the UI may be omitted.
|
/// actual scene objects. Any data not needed in the UI may be omitted.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export_to = "Operation.ts")]
|
#[ts(export_to = "Operation.ts")]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum OpKclValue {
|
pub enum OpKclValue {
|
||||||
|
@ -3,7 +3,11 @@ use std::collections::HashMap;
|
|||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use super::{cad_op::Group, kcl_value::TypeDef, types::PrimitiveType};
|
use super::{
|
||||||
|
cad_op::Group,
|
||||||
|
kcl_value::TypeDef,
|
||||||
|
types::{PrimitiveType, CHECK_NUMERIC_TYPES},
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::ExecutionKind,
|
engine::ExecutionKind,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
@ -26,7 +30,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
std::{
|
std::{
|
||||||
args::{Arg, KwArgs},
|
args::{Arg, KwArgs, TyF64},
|
||||||
FunctionKind,
|
FunctionKind,
|
||||||
},
|
},
|
||||||
CompilationError,
|
CompilationError,
|
||||||
@ -705,14 +709,14 @@ impl ExecutorContext {
|
|||||||
let result = self
|
let result = self
|
||||||
.execute_expr(&expr.expr, exec_state, metadata, &[], statement_kind)
|
.execute_expr(&expr.expr, exec_state, metadata, &[], statement_kind)
|
||||||
.await?;
|
.await?;
|
||||||
coerce(&result, &expr.ty, exec_state, expr.into())?
|
apply_ascription(&result, &expr.ty, exec_state, expr.into())?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(item)
|
Ok(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coerce(
|
fn apply_ascription(
|
||||||
value: &KclValue,
|
value: &KclValue,
|
||||||
ty: &Node<Type>,
|
ty: &Node<Type>,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
@ -721,7 +725,24 @@ fn coerce(
|
|||||||
let ty = RuntimeType::from_parsed(ty.inner.clone(), exec_state, value.into())
|
let ty = RuntimeType::from_parsed(ty.inner.clone(), exec_state, value.into())
|
||||||
.map_err(|e| KclError::Semantic(e.into()))?;
|
.map_err(|e| KclError::Semantic(e.into()))?;
|
||||||
|
|
||||||
value.coerce(&ty, exec_state).ok_or_else(|| {
|
if let KclValue::Number {
|
||||||
|
ty: NumericType::Unknown,
|
||||||
|
value,
|
||||||
|
meta,
|
||||||
|
} = value
|
||||||
|
{
|
||||||
|
// If the number has unknown units but the user is explicitly specifying them, treat the value as having had it's units erased,
|
||||||
|
// rather than forcing the user to explicitly erase them.
|
||||||
|
KclValue::Number {
|
||||||
|
ty: NumericType::Any,
|
||||||
|
value: *value,
|
||||||
|
meta: meta.clone(),
|
||||||
|
}
|
||||||
|
.coerce(&ty, exec_state)
|
||||||
|
} else {
|
||||||
|
value.coerce(&ty, exec_state)
|
||||||
|
}
|
||||||
|
.map_err(|_| {
|
||||||
KclError::Semantic(KclErrorDetails {
|
KclError::Semantic(KclErrorDetails {
|
||||||
message: format!("could not coerce {} value to type {}", value.human_friendly_type(), ty),
|
message: format!("could not coerce {} value to type {}", value.human_friendly_type(), ty),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
@ -977,69 +998,85 @@ impl Node<BinaryExpression> {
|
|||||||
return Ok(KclValue::Bool { value: raw_value, meta });
|
return Ok(KclValue::Bool { value: raw_value, meta });
|
||||||
}
|
}
|
||||||
|
|
||||||
let (left, lty) = parse_number_as_f64(&left_value, self.left.clone().into())?;
|
let left = number_as_f64(&left_value, self.left.clone().into())?;
|
||||||
let (right, rty) = parse_number_as_f64(&right_value, self.right.clone().into())?;
|
let right = number_as_f64(&right_value, self.right.clone().into())?;
|
||||||
|
|
||||||
let value = match self.operator {
|
let value = match self.operator {
|
||||||
BinaryOperator::Add => KclValue::Number {
|
BinaryOperator::Add => {
|
||||||
value: left + right,
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
meta,
|
self.warn_on_unknown(&ty, "Adding", exec_state);
|
||||||
ty: NumericType::combine_add(lty, rty),
|
KclValue::Number { value: l + r, meta, ty }
|
||||||
},
|
}
|
||||||
BinaryOperator::Sub => KclValue::Number {
|
BinaryOperator::Sub => {
|
||||||
value: left - right,
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
meta,
|
self.warn_on_unknown(&ty, "Subtracting", exec_state);
|
||||||
ty: NumericType::combine_add(lty, rty),
|
KclValue::Number { value: l - r, meta, ty }
|
||||||
},
|
}
|
||||||
BinaryOperator::Mul => KclValue::Number {
|
BinaryOperator::Mul => {
|
||||||
value: left * right,
|
let (l, r, ty) = NumericType::combine_mul(left, right);
|
||||||
meta,
|
self.warn_on_unknown(&ty, "Multiplying", exec_state);
|
||||||
ty: NumericType::combine_mul(lty, rty),
|
KclValue::Number { value: l * r, meta, ty }
|
||||||
},
|
}
|
||||||
BinaryOperator::Div => KclValue::Number {
|
BinaryOperator::Div => {
|
||||||
value: left / right,
|
let (l, r, ty) = NumericType::combine_div(left, right);
|
||||||
meta,
|
self.warn_on_unknown(&ty, "Dividing", exec_state);
|
||||||
ty: NumericType::combine_div(lty, rty),
|
KclValue::Number { value: l / r, meta, ty }
|
||||||
},
|
}
|
||||||
BinaryOperator::Mod => KclValue::Number {
|
BinaryOperator::Mod => {
|
||||||
value: left % right,
|
let (l, r, ty) = NumericType::combine_div(left, right);
|
||||||
meta,
|
self.warn_on_unknown(&ty, "Modulo of", exec_state);
|
||||||
ty: NumericType::combine_div(lty, rty),
|
KclValue::Number { value: l % r, meta, ty }
|
||||||
},
|
}
|
||||||
BinaryOperator::Pow => KclValue::Number {
|
BinaryOperator::Pow => KclValue::Number {
|
||||||
value: left.powf(right),
|
value: left.n.powf(right.n),
|
||||||
meta,
|
meta,
|
||||||
ty: NumericType::Unknown,
|
ty: NumericType::Unknown,
|
||||||
},
|
},
|
||||||
BinaryOperator::Neq => KclValue::Bool {
|
BinaryOperator::Neq => {
|
||||||
value: left != right,
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
meta,
|
self.warn_on_unknown(&ty, "Comparing", exec_state);
|
||||||
},
|
KclValue::Bool { value: l != r, meta }
|
||||||
BinaryOperator::Gt => KclValue::Bool {
|
}
|
||||||
value: left > right,
|
BinaryOperator::Gt => {
|
||||||
meta,
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
},
|
self.warn_on_unknown(&ty, "Comparing", exec_state);
|
||||||
BinaryOperator::Gte => KclValue::Bool {
|
KclValue::Bool { value: l > r, meta }
|
||||||
value: left >= right,
|
}
|
||||||
meta,
|
BinaryOperator::Gte => {
|
||||||
},
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
BinaryOperator::Lt => KclValue::Bool {
|
self.warn_on_unknown(&ty, "Comparing", exec_state);
|
||||||
value: left < right,
|
KclValue::Bool { value: l >= r, meta }
|
||||||
meta,
|
}
|
||||||
},
|
BinaryOperator::Lt => {
|
||||||
BinaryOperator::Lte => KclValue::Bool {
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
value: left <= right,
|
self.warn_on_unknown(&ty, "Comparing", exec_state);
|
||||||
meta,
|
KclValue::Bool { value: l < r, meta }
|
||||||
},
|
}
|
||||||
BinaryOperator::Eq => KclValue::Bool {
|
BinaryOperator::Lte => {
|
||||||
value: left == right,
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
meta,
|
self.warn_on_unknown(&ty, "Comparing", exec_state);
|
||||||
},
|
KclValue::Bool { value: l <= r, meta }
|
||||||
|
}
|
||||||
|
BinaryOperator::Eq => {
|
||||||
|
let (l, r, ty) = NumericType::combine_eq(left, right);
|
||||||
|
self.warn_on_unknown(&ty, "Comparing", exec_state);
|
||||||
|
KclValue::Bool { value: l == r, meta }
|
||||||
|
}
|
||||||
BinaryOperator::And | BinaryOperator::Or => unreachable!(),
|
BinaryOperator::And | BinaryOperator::Or => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn warn_on_unknown(&self, ty: &NumericType, verb: &str, exec_state: &mut ExecState) {
|
||||||
|
if *CHECK_NUMERIC_TYPES && ty == &NumericType::Unknown {
|
||||||
|
// TODO suggest how to fix this
|
||||||
|
exec_state.warn(CompilationError::err(
|
||||||
|
self.as_source_range(),
|
||||||
|
format!("{} numbers which have unknown or incompatible units.", verb),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node<UnaryExpression> {
|
impl Node<UnaryExpression> {
|
||||||
@ -1759,21 +1796,15 @@ fn article_for(s: &str) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_number_as_f64(v: &KclValue, source_range: SourceRange) -> Result<(f64, NumericType), KclError> {
|
fn number_as_f64(v: &KclValue, source_range: SourceRange) -> Result<TyF64, KclError> {
|
||||||
if let KclValue::Number { value: n, ty, .. } = &v {
|
v.as_ty_f64().ok_or_else(|| {
|
||||||
Ok((*n, ty.clone()))
|
|
||||||
} else {
|
|
||||||
let actual_type = v.human_friendly_type();
|
let actual_type = v.human_friendly_type();
|
||||||
let article = if actual_type.starts_with(['a', 'e', 'i', 'o', 'u']) {
|
let article = article_for(actual_type);
|
||||||
"an"
|
KclError::Semantic(KclErrorDetails {
|
||||||
} else {
|
|
||||||
"a"
|
|
||||||
};
|
|
||||||
Err(KclError::Semantic(KclErrorDetails {
|
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
message: format!("Expected a number, but found {article} {actual_type}",),
|
message: format!("Expected a number, but found {article} {actual_type}",),
|
||||||
}))
|
})
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node<IfExpression> {
|
impl Node<IfExpression> {
|
||||||
@ -1975,32 +2006,102 @@ fn assign_args_to_params(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_args_to_params_kw(
|
fn type_check_params_kw(
|
||||||
|
fn_name: Option<&str>,
|
||||||
function_expression: NodeRef<'_, FunctionExpression>,
|
function_expression: NodeRef<'_, FunctionExpression>,
|
||||||
mut args: crate::std::args::KwArgs,
|
args: &mut crate::std::args::KwArgs,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
) -> Result<(), KclError> {
|
) -> Result<(), KclError> {
|
||||||
for (label, arg) in &args.labeled {
|
for (label, arg) in &mut args.labeled {
|
||||||
match function_expression.params.iter().find(|p| &p.identifier.name == label) {
|
match function_expression.params.iter().find(|p| &p.identifier.name == label) {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
if !p.labeled {
|
if !p.labeled {
|
||||||
exec_state.err(CompilationError::err(
|
exec_state.err(CompilationError::err(
|
||||||
arg.source_range,
|
arg.source_range,
|
||||||
format!(
|
format!(
|
||||||
"This function expects an unlabeled first parameter (`{label}`), but it is labelled in the call"
|
"{} expects an unlabeled first parameter (`{label}`), but it is labelled in the call",
|
||||||
|
fn_name
|
||||||
|
.map(|n| format!("The function `{}`", n))
|
||||||
|
.unwrap_or_else(|| "This function".to_owned()),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ty) = &p.type_ {
|
||||||
|
arg.value = arg
|
||||||
|
.value
|
||||||
|
.coerce(
|
||||||
|
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range).unwrap(),
|
||||||
|
exec_state,
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
let mut message = format!(
|
||||||
|
"{label} requires a value with type `{}`, but found {}",
|
||||||
|
ty.inner,
|
||||||
|
arg.value.human_friendly_type(),
|
||||||
|
);
|
||||||
|
if let Some(ty) = e.explicit_coercion {
|
||||||
|
// TODO if we have access to the AST for the argument we could choose which example to suggest.
|
||||||
|
message = format!("{message}\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`");
|
||||||
|
}
|
||||||
|
KclError::Semantic(KclErrorDetails {
|
||||||
|
message,
|
||||||
|
source_ranges: vec![arg.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
exec_state.err(CompilationError::err(
|
exec_state.err(CompilationError::err(
|
||||||
arg.source_range,
|
arg.source_range,
|
||||||
format!("`{label}` is not an argument of this function"),
|
format!(
|
||||||
|
"`{label}` is not an argument of {}",
|
||||||
|
fn_name
|
||||||
|
.map(|n| format!("`{}`", n))
|
||||||
|
.unwrap_or_else(|| "this function".to_owned()),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(arg) = &mut args.unlabeled {
|
||||||
|
if let Some(p) = function_expression.params.iter().find(|p| !p.labeled) {
|
||||||
|
if let Some(ty) = &p.type_ {
|
||||||
|
arg.value = arg
|
||||||
|
.value
|
||||||
|
.coerce(
|
||||||
|
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range).unwrap(),
|
||||||
|
exec_state,
|
||||||
|
)
|
||||||
|
.map_err(|_| {
|
||||||
|
KclError::Semantic(KclErrorDetails {
|
||||||
|
message: format!(
|
||||||
|
"The input argument of {} requires a value with type `{}`, but found {}",
|
||||||
|
fn_name
|
||||||
|
.map(|n| format!("`{}`", n))
|
||||||
|
.unwrap_or_else(|| "this function".to_owned()),
|
||||||
|
ty.inner,
|
||||||
|
arg.value.human_friendly_type()
|
||||||
|
),
|
||||||
|
source_ranges: vec![arg.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_args_to_params_kw(
|
||||||
|
fn_name: Option<&str>,
|
||||||
|
function_expression: NodeRef<'_, FunctionExpression>,
|
||||||
|
mut args: crate::std::args::KwArgs,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
) -> Result<(), KclError> {
|
||||||
|
type_check_params_kw(fn_name, function_expression, &mut args, exec_state)?;
|
||||||
|
|
||||||
// Add the arguments to the memory. A new call frame should have already
|
// Add the arguments to the memory. A new call frame should have already
|
||||||
// been created.
|
// been created.
|
||||||
let source_ranges = vec![function_expression.into()];
|
let source_ranges = vec![function_expression.into()];
|
||||||
@ -2087,6 +2188,7 @@ async fn call_user_defined_function(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn call_user_defined_function_kw(
|
async fn call_user_defined_function_kw(
|
||||||
|
fn_name: Option<&str>,
|
||||||
args: crate::std::args::KwArgs,
|
args: crate::std::args::KwArgs,
|
||||||
memory: EnvironmentRef,
|
memory: EnvironmentRef,
|
||||||
function_expression: NodeRef<'_, FunctionExpression>,
|
function_expression: NodeRef<'_, FunctionExpression>,
|
||||||
@ -2097,7 +2199,7 @@ async fn call_user_defined_function_kw(
|
|||||||
// variables shadow variables in the parent scope. The new environment's
|
// variables shadow variables in the parent scope. The new environment's
|
||||||
// parent should be the environment of the closure.
|
// parent should be the environment of the closure.
|
||||||
exec_state.mut_stack().push_new_env_for_call(memory);
|
exec_state.mut_stack().push_new_env_for_call(memory);
|
||||||
if let Err(e) = assign_args_to_params_kw(function_expression, args, exec_state) {
|
if let Err(e) = assign_args_to_params_kw(fn_name, function_expression, args, exec_state) {
|
||||||
exec_state.mut_stack().pop_env();
|
exec_state.mut_stack().pop_env();
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
@ -2175,47 +2277,7 @@ impl FunctionSource {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (label, arg) in &mut args.kw_args.labeled {
|
type_check_params_kw(Some(&props.name), ast, &mut args.kw_args, exec_state)?;
|
||||||
match ast.params.iter().find(|p| &p.identifier.name == label) {
|
|
||||||
Some(p) => {
|
|
||||||
if !p.labeled {
|
|
||||||
exec_state.err(CompilationError::err(
|
|
||||||
arg.source_range,
|
|
||||||
format!(
|
|
||||||
"The function `{}` expects an unlabeled first parameter (`{label}`), but it is labelled in the call",
|
|
||||||
props.name
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ty) = &p.type_ {
|
|
||||||
arg.value = arg
|
|
||||||
.value
|
|
||||||
.coerce(
|
|
||||||
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range)
|
|
||||||
.unwrap(),
|
|
||||||
exec_state,
|
|
||||||
)
|
|
||||||
.ok_or_else(|| {
|
|
||||||
KclError::Semantic(KclErrorDetails {
|
|
||||||
message: format!(
|
|
||||||
"{label} requires a value with type `{}`, but found {}",
|
|
||||||
ty.inner,
|
|
||||||
arg.value.human_friendly_type()
|
|
||||||
),
|
|
||||||
source_ranges: vec![callsite],
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
exec_state.err(CompilationError::err(
|
|
||||||
arg.source_range,
|
|
||||||
format!("`{label}` is not an argument of `{}`", props.name),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(arg) = &mut args.kw_args.unlabeled {
|
if let Some(arg) = &mut args.kw_args.unlabeled {
|
||||||
if let Some(p) = ast.params.iter().find(|p| !p.labeled) {
|
if let Some(p) = ast.params.iter().find(|p| !p.labeled) {
|
||||||
@ -2226,13 +2288,13 @@ impl FunctionSource {
|
|||||||
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range).unwrap(),
|
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range).unwrap(),
|
||||||
exec_state,
|
exec_state,
|
||||||
)
|
)
|
||||||
.ok_or_else(|| {
|
.map_err(|_| {
|
||||||
KclError::Semantic(KclErrorDetails {
|
KclError::Semantic(KclErrorDetails {
|
||||||
message: format!(
|
message: format!(
|
||||||
"The input argument of {} requires a value with type `{}`, but found {}",
|
"The input argument of {} requires a value with type `{}`, but found {}",
|
||||||
props.name,
|
props.name,
|
||||||
ty.inner,
|
ty.inner,
|
||||||
arg.value.human_friendly_type()
|
arg.value.human_friendly_type(),
|
||||||
),
|
),
|
||||||
source_ranges: vec![callsite],
|
source_ranges: vec![callsite],
|
||||||
})
|
})
|
||||||
@ -2295,7 +2357,7 @@ impl FunctionSource {
|
|||||||
.collect();
|
.collect();
|
||||||
exec_state.global.operations.push(Operation::GroupBegin {
|
exec_state.global.operations.push(Operation::GroupBegin {
|
||||||
group: Group::FunctionCall {
|
group: Group::FunctionCall {
|
||||||
name: fn_name,
|
name: fn_name.clone(),
|
||||||
function_source_range: ast.as_source_range(),
|
function_source_range: ast.as_source_range(),
|
||||||
unlabeled_arg: args
|
unlabeled_arg: args
|
||||||
.kw_args
|
.kw_args
|
||||||
@ -2308,7 +2370,7 @@ impl FunctionSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, ctx).await
|
call_user_defined_function_kw(fn_name.as_deref(), args.kw_args, *memory, ast, exec_state, ctx).await
|
||||||
}
|
}
|
||||||
FunctionSource::None => unreachable!(),
|
FunctionSource::None => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -2534,4 +2596,25 @@ a = foo()
|
|||||||
let result = parse_execute(program).await;
|
let result = parse_execute(program).await;
|
||||||
assert!(result.unwrap_err().to_string().contains("return"));
|
assert!(result.unwrap_err().to_string().contains("return"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn user_coercion() {
|
||||||
|
let program = r#"fn foo(x: Axis2d) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
foo(x = { direction = [0, 0], origin = [0, 0]})
|
||||||
|
"#;
|
||||||
|
|
||||||
|
parse_execute(program).await.unwrap();
|
||||||
|
|
||||||
|
let program = r#"fn foo(x: Axis3d) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
foo(x = { direction = [0, 0], origin = [0, 0]})
|
||||||
|
"#;
|
||||||
|
|
||||||
|
parse_execute(program).await.unwrap_err();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,16 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
execution::{ArtifactId, ExecState, Metadata, TagEngineInfo, TagIdentifier, UnitLen},
|
execution::{types::NumericType, ArtifactId, ExecState, Metadata, TagEngineInfo, TagIdentifier, UnitLen},
|
||||||
parsing::ast::types::{Node, NodeRef, TagDeclarator, TagNode},
|
parsing::ast::types::{Node, NodeRef, TagDeclarator, TagNode},
|
||||||
std::sketch::PlaneData,
|
std::{args::TyF64, sketch::PlaneData},
|
||||||
};
|
};
|
||||||
|
|
||||||
type Point2D = kcmc::shared::Point2d<f64>;
|
type Point2D = kcmc::shared::Point2d<f64>;
|
||||||
type Point3D = kcmc::shared::Point3d<f64>;
|
type Point3D = kcmc::shared::Point3d<f64>;
|
||||||
|
|
||||||
/// A geometry.
|
/// A geometry.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum Geometry {
|
pub enum Geometry {
|
||||||
@ -47,7 +47,7 @@ impl Geometry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A set of geometry.
|
/// A set of geometry.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
#[allow(clippy::vec_box)]
|
#[allow(clippy::vec_box)]
|
||||||
@ -66,7 +66,7 @@ impl From<Geometry> for Geometries {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Data for an imported geometry.
|
/// Data for an imported geometry.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ImportedGeometry {
|
pub struct ImportedGeometry {
|
||||||
@ -79,7 +79,7 @@ pub struct ImportedGeometry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Data for a solid or an imported geometry.
|
/// Data for a solid or an imported geometry.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
#[allow(clippy::vec_box)]
|
#[allow(clippy::vec_box)]
|
||||||
@ -159,7 +159,7 @@ pub struct Helix {
|
|||||||
pub meta: Vec<Metadata>,
|
pub meta: Vec<Metadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Plane {
|
pub struct Plane {
|
||||||
@ -353,7 +353,7 @@ impl Plane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A face.
|
/// A face.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Face {
|
pub struct Face {
|
||||||
@ -377,7 +377,7 @@ pub struct Face {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Type for a plane.
|
/// Type for a plane.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[display(style = "camelCase")]
|
#[display(style = "camelCase")]
|
||||||
pub enum PlaneType {
|
pub enum PlaneType {
|
||||||
@ -398,7 +398,7 @@ pub enum PlaneType {
|
|||||||
Uninit,
|
Uninit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub struct Sketch {
|
pub struct Sketch {
|
||||||
@ -418,6 +418,9 @@ pub struct Sketch {
|
|||||||
pub artifact_id: ArtifactId,
|
pub artifact_id: ArtifactId,
|
||||||
#[ts(skip)]
|
#[ts(skip)]
|
||||||
pub original_id: uuid::Uuid,
|
pub original_id: uuid::Uuid,
|
||||||
|
/// If the sketch includes a mirror.
|
||||||
|
#[serde(skip)]
|
||||||
|
pub mirror: Option<uuid::Uuid>,
|
||||||
pub units: UnitLen,
|
pub units: UnitLen,
|
||||||
/// Metadata.
|
/// Metadata.
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
@ -460,7 +463,7 @@ impl Sketch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A sketch type.
|
/// A sketch type.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub enum SketchSurface {
|
pub enum SketchSurface {
|
||||||
@ -579,7 +582,7 @@ impl Sketch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub struct Solid {
|
pub struct Solid {
|
||||||
@ -613,7 +616,7 @@ impl Solid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A fillet or a chamfer.
|
/// A fillet or a chamfer.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub enum EdgeCut {
|
pub enum EdgeCut {
|
||||||
@ -675,6 +678,12 @@ impl From<[f64; 2]> for Point2d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<[TyF64; 2]> for Point2d {
|
||||||
|
fn from(p: [TyF64; 2]) -> Self {
|
||||||
|
Self { x: p[0].n, y: p[1].n }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&[f64; 2]> for Point2d {
|
impl From<&[f64; 2]> for Point2d {
|
||||||
fn from(p: &[f64; 2]) -> Self {
|
fn from(p: &[f64; 2]) -> Self {
|
||||||
Self { x: p[0], y: p[1] }
|
Self { x: p[0], y: p[1] }
|
||||||
@ -764,7 +773,7 @@ impl Mul<f64> for Point3d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A base path.
|
/// A base path.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct BasePath {
|
pub struct BasePath {
|
||||||
@ -783,7 +792,7 @@ pub struct BasePath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Geometry metadata.
|
/// Geometry metadata.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct GeoMeta {
|
pub struct GeoMeta {
|
||||||
@ -795,7 +804,7 @@ pub struct GeoMeta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A path.
|
/// A path.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum Path {
|
pub enum Path {
|
||||||
@ -976,19 +985,23 @@ impl Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Where does this path segment start?
|
/// Where does this path segment start?
|
||||||
pub fn get_from(&self) -> &[f64; 2] {
|
pub fn get_from(&self) -> [TyF64; 2] {
|
||||||
&self.get_base().from
|
let p = &self.get_base().from;
|
||||||
|
let ty: NumericType = self.get_base().units.into();
|
||||||
|
[TyF64::new(p[0], ty.clone()), TyF64::new(p[1], ty)]
|
||||||
}
|
}
|
||||||
/// Where does this path segment end?
|
/// Where does this path segment end?
|
||||||
pub fn get_to(&self) -> &[f64; 2] {
|
pub fn get_to(&self) -> [TyF64; 2] {
|
||||||
&self.get_base().to
|
let p = &self.get_base().to;
|
||||||
|
let ty: NumericType = self.get_base().units.into();
|
||||||
|
[TyF64::new(p[0], ty.clone()), TyF64::new(p[1], ty)]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Length of this path segment, in cartesian plane.
|
/// Length of this path segment, in cartesian plane.
|
||||||
pub fn length(&self) -> f64 {
|
pub fn length(&self) -> TyF64 {
|
||||||
match self {
|
let n = match self {
|
||||||
Self::ToPoint { .. } | Self::Base { .. } | Self::Horizontal { .. } | Self::AngledLineTo { .. } => {
|
Self::ToPoint { .. } | Self::Base { .. } | Self::Horizontal { .. } | Self::AngledLineTo { .. } => {
|
||||||
linear_distance(self.get_from(), self.get_to())
|
linear_distance(&self.get_base().from, &self.get_base().to)
|
||||||
}
|
}
|
||||||
Self::TangentialArc {
|
Self::TangentialArc {
|
||||||
base: _,
|
base: _,
|
||||||
@ -1002,10 +1015,10 @@ impl Path {
|
|||||||
} => {
|
} => {
|
||||||
// The radius can be calculated as the linear distance between `to` and `center`,
|
// The radius can be calculated as the linear distance between `to` and `center`,
|
||||||
// or between `from` and `center`. They should be the same.
|
// or between `from` and `center`. They should be the same.
|
||||||
let radius = linear_distance(self.get_from(), center);
|
let radius = linear_distance(&self.get_base().from, center);
|
||||||
debug_assert_eq!(radius, linear_distance(self.get_to(), center));
|
debug_assert_eq!(radius, linear_distance(&self.get_base().to, center));
|
||||||
// TODO: Call engine utils to figure this out.
|
// TODO: Call engine utils to figure this out.
|
||||||
linear_distance(self.get_from(), self.get_to())
|
linear_distance(&self.get_base().from, &self.get_base().to)
|
||||||
}
|
}
|
||||||
Self::Circle { radius, .. } => 2.0 * std::f64::consts::PI * radius,
|
Self::Circle { radius, .. } => 2.0 * std::f64::consts::PI * radius,
|
||||||
Self::CircleThreePoint { .. } => {
|
Self::CircleThreePoint { .. } => {
|
||||||
@ -1019,13 +1032,14 @@ impl Path {
|
|||||||
}
|
}
|
||||||
Self::Arc { .. } => {
|
Self::Arc { .. } => {
|
||||||
// TODO: Call engine utils to figure this out.
|
// TODO: Call engine utils to figure this out.
|
||||||
linear_distance(self.get_from(), self.get_to())
|
linear_distance(&self.get_base().from, &self.get_base().to)
|
||||||
}
|
}
|
||||||
Self::ArcThreePoint { .. } => {
|
Self::ArcThreePoint { .. } => {
|
||||||
// TODO: Call engine utils to figure this out.
|
// TODO: Call engine utils to figure this out.
|
||||||
linear_distance(self.get_from(), self.get_to())
|
linear_distance(&self.get_base().from, &self.get_base().to)
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
TyF64::new(n, self.get_base().units.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_base_mut(&mut self) -> Option<&mut BasePath> {
|
pub fn get_base_mut(&mut self) -> Option<&mut BasePath> {
|
||||||
@ -1100,7 +1114,7 @@ fn linear_distance(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An extrude surface.
|
/// An extrude surface.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub enum ExtrudeSurface {
|
pub enum ExtrudeSurface {
|
||||||
@ -1112,7 +1126,7 @@ pub enum ExtrudeSurface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Chamfer surface.
|
// Chamfer surface.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ChamferSurface {
|
pub struct ChamferSurface {
|
||||||
@ -1126,7 +1140,7 @@ pub struct ChamferSurface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fillet surface.
|
// Fillet surface.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct FilletSurface {
|
pub struct FilletSurface {
|
||||||
@ -1140,7 +1154,7 @@ pub struct FilletSurface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An extruded plane.
|
/// An extruded plane.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ExtrudePlane {
|
pub struct ExtrudePlane {
|
||||||
@ -1154,7 +1168,7 @@ pub struct ExtrudePlane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An extruded arc.
|
/// An extruded arc.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ExtrudeArc {
|
pub struct ExtrudeArc {
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
parsing::ast::types::{
|
parsing::ast::types::{
|
||||||
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
|
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
|
||||||
},
|
},
|
||||||
std::StdFnProps,
|
std::{args::TyF64, StdFnProps},
|
||||||
CompilationError, KclError, ModuleId, SourceRange,
|
CompilationError, KclError, ModuleId, SourceRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -495,6 +495,7 @@ impl KclValue {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_f64(&self) -> Option<f64> {
|
pub fn as_f64(&self) -> Option<f64> {
|
||||||
if let KclValue::Number { value, .. } = &self {
|
if let KclValue::Number { value, .. } = &self {
|
||||||
Some(*value)
|
Some(*value)
|
||||||
@ -503,6 +504,14 @@ impl KclValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_ty_f64(&self) -> Option<TyF64> {
|
||||||
|
if let KclValue::Number { value, ty, .. } = &self {
|
||||||
|
Some(TyF64::new(*value, ty.clone()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_bool(&self) -> Option<bool> {
|
pub fn as_bool(&self) -> Option<bool> {
|
||||||
if let KclValue::Bool { value, meta: _ } = &self {
|
if let KclValue::Bool { value, meta: _ } = &self {
|
||||||
Some(*value)
|
Some(*value)
|
||||||
|
@ -175,7 +175,7 @@ impl std::hash::Hash for TagIdentifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Engine information for a tag.
|
/// Engine information for a tag.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub struct TagEngineInfo {
|
pub struct TagEngineInfo {
|
||||||
@ -1534,8 +1534,8 @@ let shape = layer() |> patternTransform(instances = 10, transform = transform)
|
|||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_unit_default() {
|
async fn test_unit_default() {
|
||||||
let ast = r#"const inMm = 25.4 * mm()
|
let ast = r#"const inMm = fromMm(25.4)
|
||||||
const inInches = 1.0 * inch()"#;
|
const inInches = fromInches(1)"#;
|
||||||
let result = parse_execute(ast).await.unwrap();
|
let result = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
25.4,
|
25.4,
|
||||||
@ -1554,8 +1554,8 @@ const inInches = 1.0 * inch()"#;
|
|||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_unit_overriden() {
|
async fn test_unit_overriden() {
|
||||||
let ast = r#"@settings(defaultLengthUnit = inch)
|
let ast = r#"@settings(defaultLengthUnit = inch)
|
||||||
const inMm = 25.4 * mm()
|
const inMm = fromMm(25.4)
|
||||||
const inInches = 1.0 * inch()"#;
|
const inInches = fromInches(1)"#;
|
||||||
let result = parse_execute(ast).await.unwrap();
|
let result = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1.0,
|
1.0,
|
||||||
@ -1575,8 +1575,8 @@ const inInches = 1.0 * inch()"#;
|
|||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_unit_overriden_in() {
|
async fn test_unit_overriden_in() {
|
||||||
let ast = r#"@settings(defaultLengthUnit = in)
|
let ast = r#"@settings(defaultLengthUnit = in)
|
||||||
const inMm = 25.4 * mm()
|
const inMm = fromMm(25.4)
|
||||||
const inInches = 2.0 * inch()"#;
|
const inInches = fromInches(2)"#;
|
||||||
let result = parse_execute(ast).await.unwrap();
|
let result = parse_execute(ast).await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1.0,
|
1.0,
|
||||||
|
@ -22,6 +22,8 @@ use crate::{
|
|||||||
CompilationError,
|
CompilationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::types::NumericType;
|
||||||
|
|
||||||
/// State for executing a program.
|
/// State for executing a program.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ExecState {
|
pub struct ExecState {
|
||||||
@ -228,6 +230,13 @@ impl ExecState {
|
|||||||
self.global.module_infos.insert(id, module_info);
|
self.global.module_infos.insert(id, module_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn current_default_units(&self) -> NumericType {
|
||||||
|
NumericType::Default {
|
||||||
|
len: self.length_unit(),
|
||||||
|
angle: self.angle_unit(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn length_unit(&self) -> UnitLen {
|
pub fn length_unit(&self) -> UnitLen {
|
||||||
self.mod_local.settings.default_length_units
|
self.mod_local.settings.default_length_units
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,20 @@ use crate::{
|
|||||||
ast::types::{PrimitiveType as AstPrimitiveType, Type},
|
ast::types::{PrimitiveType as AstPrimitiveType, Type},
|
||||||
token::NumericSuffix,
|
token::NumericSuffix,
|
||||||
},
|
},
|
||||||
std::args::FromKclValue,
|
std::args::{FromKclValue, TyF64},
|
||||||
CompilationError, SourceRange,
|
CompilationError, SourceRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
pub(super) static ref CHECK_NUMERIC_TYPES: bool = {
|
||||||
|
let env_var = std::env::var("ZOO_NUM_TYS");
|
||||||
|
let Ok(env_var) = env_var else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
!env_var.is_empty()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum RuntimeType {
|
pub enum RuntimeType {
|
||||||
Primitive(PrimitiveType),
|
Primitive(PrimitiveType),
|
||||||
@ -337,7 +347,7 @@ impl fmt::Display for PrimitiveType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum NumericType {
|
pub enum NumericType {
|
||||||
@ -351,62 +361,94 @@ pub enum NumericType {
|
|||||||
Any,
|
Any,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for NumericType {
|
||||||
|
fn default() -> Self {
|
||||||
|
NumericType::Default {
|
||||||
|
len: UnitLen::default(),
|
||||||
|
angle: UnitAngle::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NumericType {
|
impl NumericType {
|
||||||
pub fn count() -> Self {
|
pub const fn count() -> Self {
|
||||||
NumericType::Known(UnitType::Count)
|
NumericType::Known(UnitType::Count)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mm() -> Self {
|
pub const fn mm() -> Self {
|
||||||
NumericType::Known(UnitType::Length(UnitLen::Mm))
|
NumericType::Known(UnitType::Length(UnitLen::Mm))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn radians() -> Self {
|
||||||
|
NumericType::Known(UnitType::Angle(UnitAngle::Radians))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn degrees() -> Self {
|
||||||
|
NumericType::Known(UnitType::Angle(UnitAngle::Degrees))
|
||||||
|
}
|
||||||
|
|
||||||
/// Combine two types when we expect them to be equal.
|
/// Combine two types when we expect them to be equal.
|
||||||
pub fn combine_eq(self, other: &NumericType) -> NumericType {
|
pub fn combine_eq(a: TyF64, b: TyF64) -> (f64, f64, NumericType) {
|
||||||
if &self == other {
|
use NumericType::*;
|
||||||
self
|
match (a.ty, b.ty) {
|
||||||
} else {
|
(at, bt) if at == bt => (a.n, b.n, at),
|
||||||
NumericType::Unknown
|
(at, Any) => (a.n, b.n, at),
|
||||||
}
|
(Any, bt) => (a.n, b.n, bt),
|
||||||
}
|
(Default { .. }, Default { .. }) | (_, Unknown) | (Unknown, _) => (a.n, b.n, Unknown),
|
||||||
|
|
||||||
/// Combine n types when we expect them to be equal.
|
// Known types and compatible, but needs adjustment.
|
||||||
///
|
(t @ Known(UnitType::Length(l1)), Known(UnitType::Length(l2))) => (a.n, l2.adjust_to(b.n, l1), t),
|
||||||
/// Precondition: tys.len() > 0
|
(t @ Known(UnitType::Angle(a1)), Known(UnitType::Angle(a2))) => (a.n, a2.adjust_to(b.n, a1), t),
|
||||||
pub fn combine_n_eq(tys: &[NumericType]) -> NumericType {
|
|
||||||
let ty0 = tys[0].clone();
|
// Known but incompatible.
|
||||||
for t in &tys[1..] {
|
(Known(_), Known(_)) => (a.n, b.n, Unknown),
|
||||||
if t != &ty0 {
|
|
||||||
return NumericType::Unknown;
|
// Known and unknown => we assume the known one, possibly with adjustment
|
||||||
|
(Known(UnitType::Count), Default { .. }) | (Default { .. }, Known(UnitType::Count)) => {
|
||||||
|
(a.n, b.n, Known(UnitType::Count))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(t @ Known(UnitType::Length(l1)), Default { len: l2, .. }) => (a.n, l2.adjust_to(b.n, l1), t),
|
||||||
|
(Default { len: l1, .. }, t @ Known(UnitType::Length(l2))) => (l1.adjust_to(a.n, l2), b.n, t),
|
||||||
|
|
||||||
|
(t @ Known(UnitType::Angle(a1)), Default { angle: a2, .. }) => (a.n, a2.adjust_to(b.n, a1), t),
|
||||||
|
(Default { angle: a1, .. }, t @ Known(UnitType::Angle(a2))) => (a1.adjust_to(a.n, a2), b.n, t),
|
||||||
}
|
}
|
||||||
ty0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combine two types in addition-like operations.
|
/// Combine two types for multiplication-like operations.
|
||||||
pub fn combine_add(a: NumericType, b: NumericType) -> NumericType {
|
pub fn combine_mul(a: TyF64, b: TyF64) -> (f64, f64, NumericType) {
|
||||||
if a == b {
|
use NumericType::*;
|
||||||
return a;
|
match (a.ty, b.ty) {
|
||||||
|
(at @ Default { .. }, bt @ Default { .. }) if at != bt => (a.n, b.n, Unknown),
|
||||||
|
(Known(UnitType::Count) | Default { .. }, bt) => (a.n, b.n, bt),
|
||||||
|
(at, Known(UnitType::Count) | Default { .. }) => (a.n, b.n, at),
|
||||||
|
(Any, Any) => (a.n, b.n, Any),
|
||||||
|
_ => (a.n, b.n, Unknown),
|
||||||
}
|
}
|
||||||
NumericType::Unknown
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combine two types in multiplication-like operations.
|
/// Combine two types for division-like operations.
|
||||||
pub fn combine_mul(a: NumericType, b: NumericType) -> NumericType {
|
pub fn combine_div(a: TyF64, b: TyF64) -> (f64, f64, NumericType) {
|
||||||
if a == NumericType::count() {
|
use NumericType::*;
|
||||||
return b;
|
match (a.ty, b.ty) {
|
||||||
|
(at, bt) if at == bt => (a.n, b.n, Known(UnitType::Count)),
|
||||||
|
(Default { .. }, Default { .. }) => (a.n, b.n, Unknown),
|
||||||
|
(at, Known(UnitType::Count) | Default { .. } | Any) => (a.n, b.n, at),
|
||||||
|
(Known(UnitType::Length(l1)), Known(UnitType::Length(l2))) => {
|
||||||
|
(a.n, l2.adjust_to(b.n, l1), Known(UnitType::Count))
|
||||||
|
}
|
||||||
|
(Known(UnitType::Angle(a1)), Known(UnitType::Angle(a2))) => {
|
||||||
|
(a.n, a2.adjust_to(b.n, a1), Known(UnitType::Count))
|
||||||
|
}
|
||||||
|
(Default { len: l1, .. }, Known(UnitType::Length(l2))) => {
|
||||||
|
(l1.adjust_to(a.n, l2), b.n, Known(UnitType::Count))
|
||||||
|
}
|
||||||
|
(Default { angle: a1, .. }, Known(UnitType::Angle(a2))) => {
|
||||||
|
(a1.adjust_to(a.n, a2), b.n, Known(UnitType::Count))
|
||||||
|
}
|
||||||
|
_ => (a.n, b.n, Unknown),
|
||||||
}
|
}
|
||||||
if b == NumericType::count() {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
NumericType::Unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Combine two types in division-like operations.
|
|
||||||
pub fn combine_div(a: NumericType, b: NumericType) -> NumericType {
|
|
||||||
if b == NumericType::count() {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
NumericType::Unknown
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_parsed(suffix: NumericSuffix, settings: &super::MetaSettings) -> Self {
|
pub fn from_parsed(suffix: NumericSuffix, settings: &super::MetaSettings) -> Self {
|
||||||
@ -431,12 +473,104 @@ impl NumericType {
|
|||||||
use NumericType::*;
|
use NumericType::*;
|
||||||
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Unknown, _) | (_, Unknown) => false,
|
|
||||||
(a, b) if a == b => true,
|
|
||||||
(_, Any) => true,
|
(_, Any) => true,
|
||||||
|
(a, b) if a == b => true,
|
||||||
|
(Unknown, _) | (_, Unknown) => false,
|
||||||
(_, _) => false,
|
(_, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn example_ty(&self) -> Option<String> {
|
||||||
|
match self {
|
||||||
|
Self::Known(t) => Some(t.to_string()),
|
||||||
|
Self::Default { len, .. } => Some(len.to_string()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn coerce(&self, val: &KclValue) -> Result<KclValue, CoercionError> {
|
||||||
|
let KclValue::Number { value, ty, meta } = val else {
|
||||||
|
return Err(val.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
if !*CHECK_NUMERIC_TYPES {
|
||||||
|
return Ok(val.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ty.subtype(self) {
|
||||||
|
return Ok(KclValue::Number {
|
||||||
|
value: *value,
|
||||||
|
ty: ty.clone(),
|
||||||
|
meta: meta.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not subtypes, but might be able to coerce
|
||||||
|
use NumericType::*;
|
||||||
|
match (ty, self) {
|
||||||
|
// We don't have enough information to coerce.
|
||||||
|
(Unknown, _) => Err(CoercionError::from(val).with_explicit(self.example_ty().unwrap_or("mm".to_owned()))),
|
||||||
|
(_, Unknown) => Err(val.into()),
|
||||||
|
(Any, _) => Ok(KclValue::Number {
|
||||||
|
value: *value,
|
||||||
|
ty: self.clone(),
|
||||||
|
meta: meta.clone(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// We don't actually need to coerce, since we just keep the partially-known type with the value.
|
||||||
|
(Default { .. }, Default { .. }) => Ok(KclValue::Number {
|
||||||
|
value: *value,
|
||||||
|
ty: ty.clone(),
|
||||||
|
meta: meta.clone(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Known types and compatible, but needs adjustment.
|
||||||
|
(Known(UnitType::Length(l1)), Known(UnitType::Length(l2))) => Ok(KclValue::Number {
|
||||||
|
value: l1.adjust_to(*value, *l2),
|
||||||
|
ty: self.clone(),
|
||||||
|
meta: meta.clone(),
|
||||||
|
}),
|
||||||
|
(Known(UnitType::Angle(a1)), Known(UnitType::Angle(a2))) => Ok(KclValue::Number {
|
||||||
|
value: a1.adjust_to(*value, *a2),
|
||||||
|
ty: self.clone(),
|
||||||
|
meta: meta.clone(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Known but incompatible.
|
||||||
|
(Known(_), Known(_)) => Err(val.into()),
|
||||||
|
|
||||||
|
// Known and unknown => we assume the rhs, possibly with adjustment
|
||||||
|
(Known(UnitType::Count), Default { .. }) | (Default { .. }, Known(UnitType::Count)) => {
|
||||||
|
Ok(KclValue::Number {
|
||||||
|
value: *value,
|
||||||
|
ty: Known(UnitType::Count),
|
||||||
|
meta: meta.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
(Known(UnitType::Length(l1)), Default { len: l2, .. })
|
||||||
|
| (Default { len: l1, .. }, Known(UnitType::Length(l2))) => Ok(KclValue::Number {
|
||||||
|
value: l1.adjust_to(*value, *l2),
|
||||||
|
ty: Known(UnitType::Length(*l2)),
|
||||||
|
meta: meta.clone(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
(Known(UnitType::Angle(a1)), Default { angle: a2, .. })
|
||||||
|
| (Default { angle: a1, .. }, Known(UnitType::Angle(a2))) => Ok(KclValue::Number {
|
||||||
|
value: a1.adjust_to(*value, *a2),
|
||||||
|
ty: Known(UnitType::Angle(*a2)),
|
||||||
|
meta: meta.clone(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
(_, _) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NumericType> for RuntimeType {
|
||||||
|
fn from(t: NumericType) -> RuntimeType {
|
||||||
|
RuntimeType::Primitive(PrimitiveType::Number(t))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<UnitLen> for NumericType {
|
impl From<UnitLen> for NumericType {
|
||||||
@ -485,6 +619,39 @@ pub enum UnitLen {
|
|||||||
Yards,
|
Yards,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UnitLen {
|
||||||
|
fn adjust_to(self, value: f64, to: UnitLen) -> f64 {
|
||||||
|
if self == to {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
use UnitLen::*;
|
||||||
|
let (base, base_unit) = match self {
|
||||||
|
Mm => (value, Mm),
|
||||||
|
Cm => (value * 10.0, Mm),
|
||||||
|
M => (value * 1000.0, Mm),
|
||||||
|
Inches => (value, Inches),
|
||||||
|
Feet => (value * 12.0, Inches),
|
||||||
|
Yards => (value * 36.0, Inches),
|
||||||
|
};
|
||||||
|
let (base, base_unit) = match (base_unit, to) {
|
||||||
|
(Mm, Inches) | (Mm, Feet) | (Mm, Yards) => (base / 25.4, Inches),
|
||||||
|
(Inches, Mm) | (Inches, Cm) | (Inches, M) => (base * 25.4, Mm),
|
||||||
|
_ => (base, base_unit),
|
||||||
|
};
|
||||||
|
|
||||||
|
match (base_unit, to) {
|
||||||
|
(Mm, Mm) => base,
|
||||||
|
(Mm, Cm) => base / 10.0,
|
||||||
|
(Mm, M) => base / 1000.0,
|
||||||
|
(Inches, Inches) => base,
|
||||||
|
(Inches, Feet) => base / 12.0,
|
||||||
|
(Inches, Yards) => base / 36.0,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for UnitLen {
|
impl std::fmt::Display for UnitLen {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -563,6 +730,19 @@ pub enum UnitAngle {
|
|||||||
Radians,
|
Radians,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UnitAngle {
|
||||||
|
fn adjust_to(self, value: f64, to: UnitAngle) -> f64 {
|
||||||
|
use std::f64::consts::PI;
|
||||||
|
use UnitAngle::*;
|
||||||
|
match (self, to) {
|
||||||
|
(Degrees, Degrees) => value,
|
||||||
|
(Degrees, Radians) => (value / 180.0) * PI,
|
||||||
|
(Radians, Degrees) => 180.0 * value / PI,
|
||||||
|
(Radians, Radians) => value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for UnitAngle {
|
impl std::fmt::Display for UnitAngle {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -584,6 +764,28 @@ impl TryFrom<NumericSuffix> for UnitAngle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CoercionError {
|
||||||
|
pub found: Option<RuntimeType>,
|
||||||
|
pub explicit_coercion: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CoercionError {
|
||||||
|
fn with_explicit(mut self, c: String) -> Self {
|
||||||
|
self.explicit_coercion = Some(c);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&'_ KclValue> for CoercionError {
|
||||||
|
fn from(value: &'_ KclValue) -> Self {
|
||||||
|
CoercionError {
|
||||||
|
found: value.principal_type(),
|
||||||
|
explicit_coercion: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl KclValue {
|
impl KclValue {
|
||||||
/// True if `self` has a type which is a subtype of `ty` without coercion.
|
/// True if `self` has a type which is a subtype of `ty` without coercion.
|
||||||
pub fn has_type(&self, ty: &RuntimeType) -> bool {
|
pub fn has_type(&self, ty: &RuntimeType) -> bool {
|
||||||
@ -600,7 +802,7 @@ impl KclValue {
|
|||||||
/// - result.principal_type().unwrap().subtype(ty)
|
/// - result.principal_type().unwrap().subtype(ty)
|
||||||
///
|
///
|
||||||
/// If self.principal_type() == ty then result == self
|
/// If self.principal_type() == ty then result == self
|
||||||
pub fn coerce(&self, ty: &RuntimeType, exec_state: &mut ExecState) -> Option<KclValue> {
|
pub fn coerce(&self, ty: &RuntimeType, exec_state: &mut ExecState) -> Result<KclValue, CoercionError> {
|
||||||
match ty {
|
match ty {
|
||||||
RuntimeType::Primitive(ty) => self.coerce_to_primitive_type(ty, exec_state),
|
RuntimeType::Primitive(ty) => self.coerce_to_primitive_type(ty, exec_state),
|
||||||
RuntimeType::Array(ty, len) => self.coerce_to_array_type(ty, *len, exec_state, false),
|
RuntimeType::Array(ty, len) => self.coerce_to_array_type(ty, *len, exec_state, false),
|
||||||
@ -610,40 +812,52 @@ impl KclValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coerce_to_primitive_type(&self, ty: &PrimitiveType, exec_state: &mut ExecState) -> Option<KclValue> {
|
fn coerce_to_primitive_type(
|
||||||
|
&self,
|
||||||
|
ty: &PrimitiveType,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
) -> Result<KclValue, CoercionError> {
|
||||||
let value = match self {
|
let value = match self {
|
||||||
KclValue::MixedArray { value, .. } | KclValue::HomArray { value, .. } if value.len() == 1 => &value[0],
|
KclValue::MixedArray { value, .. } | KclValue::HomArray { value, .. } if value.len() == 1 => &value[0],
|
||||||
_ => self,
|
_ => self,
|
||||||
};
|
};
|
||||||
match ty {
|
match ty {
|
||||||
// TODO numeric type coercions
|
PrimitiveType::Number(ty) => ty.coerce(value),
|
||||||
PrimitiveType::Number(_ty) => match value {
|
|
||||||
KclValue::Number { .. } => Some(value.clone()),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
PrimitiveType::String => match value {
|
PrimitiveType::String => match value {
|
||||||
KclValue::String { .. } => Some(value.clone()),
|
KclValue::String { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Boolean => match value {
|
PrimitiveType::Boolean => match value {
|
||||||
KclValue::Bool { .. } => Some(value.clone()),
|
KclValue::Bool { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Sketch => match value {
|
PrimitiveType::Sketch => match value {
|
||||||
KclValue::Sketch { .. } => Some(value.clone()),
|
KclValue::Sketch { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Solid => match value {
|
PrimitiveType::Solid => match value {
|
||||||
KclValue::Solid { .. } => Some(value.clone()),
|
KclValue::Solid { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Plane => match value {
|
PrimitiveType::Plane => match value {
|
||||||
KclValue::Plane { .. } => Some(value.clone()),
|
KclValue::Plane { .. } => Ok(value.clone()),
|
||||||
KclValue::Object { value, meta } => {
|
KclValue::Object { value, meta } => {
|
||||||
let origin = value.get("origin").and_then(Point3d::from_kcl_val)?;
|
let origin = value
|
||||||
let x_axis = value.get("xAxis").and_then(Point3d::from_kcl_val)?;
|
.get("origin")
|
||||||
let y_axis = value.get("yAxis").and_then(Point3d::from_kcl_val)?;
|
.and_then(Point3d::from_kcl_val)
|
||||||
let z_axis = value.get("zAxis").and_then(Point3d::from_kcl_val)?;
|
.ok_or(CoercionError::from(self))?;
|
||||||
|
let x_axis = value
|
||||||
|
.get("xAxis")
|
||||||
|
.and_then(Point3d::from_kcl_val)
|
||||||
|
.ok_or(CoercionError::from(self))?;
|
||||||
|
let y_axis = value
|
||||||
|
.get("yAxis")
|
||||||
|
.and_then(Point3d::from_kcl_val)
|
||||||
|
.ok_or(CoercionError::from(self))?;
|
||||||
|
let z_axis = value
|
||||||
|
.get("zAxis")
|
||||||
|
.and_then(Point3d::from_kcl_val)
|
||||||
|
.ok_or(CoercionError::from(self))?;
|
||||||
|
|
||||||
let id = exec_state.mod_local.id_generator.next_uuid();
|
let id = exec_state.mod_local.id_generator.next_uuid();
|
||||||
let plane = Plane {
|
let plane = Plane {
|
||||||
@ -659,75 +873,87 @@ impl KclValue {
|
|||||||
meta: meta.clone(),
|
meta: meta.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(KclValue::Plane { value: Box::new(plane) })
|
Ok(KclValue::Plane { value: Box::new(plane) })
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Face => match value {
|
PrimitiveType::Face => match value {
|
||||||
KclValue::Face { .. } => Some(value.clone()),
|
KclValue::Face { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Helix => match value {
|
PrimitiveType::Helix => match value {
|
||||||
KclValue::Helix { .. } => Some(value.clone()),
|
KclValue::Helix { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Edge => match value {
|
PrimitiveType::Edge => match value {
|
||||||
KclValue::Uuid { .. } => Some(value.clone()),
|
KclValue::Uuid { .. } => Ok(value.clone()),
|
||||||
KclValue::TagIdentifier { .. } => Some(value.clone()),
|
KclValue::TagIdentifier { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Axis2d => match value {
|
PrimitiveType::Axis2d => match value {
|
||||||
KclValue::Object { value: values, meta } => {
|
KclValue::Object { value: values, meta } => {
|
||||||
if values.get("origin")?.has_type(&RuntimeType::point2d())
|
if values
|
||||||
&& values.get("direction")?.has_type(&RuntimeType::point2d())
|
.get("origin")
|
||||||
|
.ok_or(CoercionError::from(self))?
|
||||||
|
.has_type(&RuntimeType::point2d())
|
||||||
|
&& values
|
||||||
|
.get("direction")
|
||||||
|
.ok_or(CoercionError::from(self))?
|
||||||
|
.has_type(&RuntimeType::point2d())
|
||||||
{
|
{
|
||||||
return Some(value.clone());
|
return Ok(value.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let origin = values.get("origin").and_then(|p| {
|
let origin = values.get("origin").ok_or(self.into()).and_then(|p| {
|
||||||
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(2), exec_state, true)
|
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(2), exec_state, true)
|
||||||
})?;
|
})?;
|
||||||
let direction = values.get("direction").and_then(|p| {
|
let direction = values.get("direction").ok_or(self.into()).and_then(|p| {
|
||||||
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(2), exec_state, true)
|
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(2), exec_state, true)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Some(KclValue::Object {
|
Ok(KclValue::Object {
|
||||||
value: [("origin".to_owned(), origin), ("direction".to_owned(), direction)].into(),
|
value: [("origin".to_owned(), origin), ("direction".to_owned(), direction)].into(),
|
||||||
meta: meta.clone(),
|
meta: meta.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Axis3d => match value {
|
PrimitiveType::Axis3d => match value {
|
||||||
KclValue::Object { value: values, meta } => {
|
KclValue::Object { value: values, meta } => {
|
||||||
if values.get("origin")?.has_type(&RuntimeType::point3d())
|
if values
|
||||||
&& values.get("direction")?.has_type(&RuntimeType::point3d())
|
.get("origin")
|
||||||
|
.ok_or(CoercionError::from(self))?
|
||||||
|
.has_type(&RuntimeType::point3d())
|
||||||
|
&& values
|
||||||
|
.get("direction")
|
||||||
|
.ok_or(CoercionError::from(self))?
|
||||||
|
.has_type(&RuntimeType::point3d())
|
||||||
{
|
{
|
||||||
return Some(value.clone());
|
return Ok(value.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let origin = values.get("origin").and_then(|p| {
|
let origin = values.get("origin").ok_or(self.into()).and_then(|p| {
|
||||||
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(3), exec_state, true)
|
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(3), exec_state, true)
|
||||||
})?;
|
})?;
|
||||||
let direction = values.get("direction").and_then(|p| {
|
let direction = values.get("direction").ok_or(self.into()).and_then(|p| {
|
||||||
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(3), exec_state, true)
|
p.coerce_to_array_type(&RuntimeType::number_any(), ArrayLen::Known(3), exec_state, true)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Some(KclValue::Object {
|
Ok(KclValue::Object {
|
||||||
value: [("origin".to_owned(), origin), ("direction".to_owned(), direction)].into(),
|
value: [("origin".to_owned(), origin), ("direction".to_owned(), direction)].into(),
|
||||||
meta: meta.clone(),
|
meta: meta.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::ImportedGeometry => match value {
|
PrimitiveType::ImportedGeometry => match value {
|
||||||
KclValue::ImportedGeometry { .. } => Some(value.clone()),
|
KclValue::ImportedGeometry { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
PrimitiveType::Tag => match value {
|
PrimitiveType::Tag => match value {
|
||||||
KclValue::TagDeclarator { .. } => Some(value.clone()),
|
KclValue::TagDeclarator { .. } => Ok(value.clone()),
|
||||||
KclValue::TagIdentifier { .. } => Some(value.clone()),
|
KclValue::TagIdentifier { .. } => Ok(value.clone()),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -738,37 +964,40 @@ impl KclValue {
|
|||||||
len: ArrayLen,
|
len: ArrayLen,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
allow_shrink: bool,
|
allow_shrink: bool,
|
||||||
) -> Option<KclValue> {
|
) -> Result<KclValue, CoercionError> {
|
||||||
match self {
|
match self {
|
||||||
KclValue::HomArray { value, ty: aty } if aty.subtype(ty) => {
|
KclValue::HomArray { value, ty: aty } if aty.subtype(ty) => len
|
||||||
len.satisfied(value.len(), allow_shrink).map(|len| KclValue::HomArray {
|
.satisfied(value.len(), allow_shrink)
|
||||||
|
.map(|len| KclValue::HomArray {
|
||||||
value: value[..len].to_vec(),
|
value: value[..len].to_vec(),
|
||||||
ty: aty.clone(),
|
ty: aty.clone(),
|
||||||
})
|
})
|
||||||
}
|
.ok_or(self.into()),
|
||||||
value if len.satisfied(1, false).is_some() && value.has_type(ty) => Some(KclValue::HomArray {
|
value if len.satisfied(1, false).is_some() && value.has_type(ty) => Ok(KclValue::HomArray {
|
||||||
value: vec![value.clone()],
|
value: vec![value.clone()],
|
||||||
ty: ty.clone(),
|
ty: ty.clone(),
|
||||||
}),
|
}),
|
||||||
KclValue::MixedArray { value, .. } => {
|
KclValue::MixedArray { value, .. } => {
|
||||||
let len = len.satisfied(value.len(), allow_shrink)?;
|
let len = len
|
||||||
|
.satisfied(value.len(), allow_shrink)
|
||||||
|
.ok_or(CoercionError::from(self))?;
|
||||||
|
|
||||||
let value = value[..len]
|
let value = value[..len]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| v.coerce(ty, exec_state))
|
.map(|v| v.coerce(ty, exec_state))
|
||||||
.collect::<Option<Vec<_>>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Some(KclValue::HomArray { value, ty: ty.clone() })
|
Ok(KclValue::HomArray { value, ty: ty.clone() })
|
||||||
}
|
}
|
||||||
KclValue::KclNone { .. } if len.satisfied(0, false).is_some() => Some(KclValue::HomArray {
|
KclValue::KclNone { .. } if len.satisfied(0, false).is_some() => Ok(KclValue::HomArray {
|
||||||
value: Vec::new(),
|
value: Vec::new(),
|
||||||
ty: ty.clone(),
|
ty: ty.clone(),
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coerce_to_tuple_type(&self, tys: &[RuntimeType], exec_state: &mut ExecState) -> Option<KclValue> {
|
fn coerce_to_tuple_type(&self, tys: &[RuntimeType], exec_state: &mut ExecState) -> Result<KclValue, CoercionError> {
|
||||||
match self {
|
match self {
|
||||||
KclValue::MixedArray { value, .. } | KclValue::HomArray { value, .. } if value.len() == tys.len() => {
|
KclValue::MixedArray { value, .. } | KclValue::HomArray { value, .. } if value.len() == tys.len() => {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
@ -776,50 +1005,54 @@ impl KclValue {
|
|||||||
result.push(value[i].coerce(t, exec_state)?);
|
result.push(value[i].coerce(t, exec_state)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(KclValue::MixedArray {
|
Ok(KclValue::MixedArray {
|
||||||
value: result,
|
value: result,
|
||||||
meta: Vec::new(),
|
meta: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
KclValue::KclNone { meta, .. } if tys.is_empty() => Some(KclValue::MixedArray {
|
KclValue::KclNone { meta, .. } if tys.is_empty() => Ok(KclValue::MixedArray {
|
||||||
value: Vec::new(),
|
value: Vec::new(),
|
||||||
meta: meta.clone(),
|
meta: meta.clone(),
|
||||||
}),
|
}),
|
||||||
value if tys.len() == 1 && value.has_type(&tys[0]) => Some(KclValue::MixedArray {
|
value if tys.len() == 1 && value.has_type(&tys[0]) => Ok(KclValue::MixedArray {
|
||||||
value: vec![value.clone()],
|
value: vec![value.clone()],
|
||||||
meta: Vec::new(),
|
meta: Vec::new(),
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coerce_to_union_type(&self, tys: &[RuntimeType], exec_state: &mut ExecState) -> Option<KclValue> {
|
fn coerce_to_union_type(&self, tys: &[RuntimeType], exec_state: &mut ExecState) -> Result<KclValue, CoercionError> {
|
||||||
for t in tys {
|
for t in tys {
|
||||||
if let Some(v) = self.coerce(t, exec_state) {
|
if let Ok(v) = self.coerce(t, exec_state) {
|
||||||
return Some(v);
|
return Ok(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
Err(self.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coerce_to_object_type(&self, tys: &[(String, RuntimeType)], _exec_state: &mut ExecState) -> Option<KclValue> {
|
fn coerce_to_object_type(
|
||||||
|
&self,
|
||||||
|
tys: &[(String, RuntimeType)],
|
||||||
|
_exec_state: &mut ExecState,
|
||||||
|
) -> Result<KclValue, CoercionError> {
|
||||||
match self {
|
match self {
|
||||||
KclValue::Object { value, .. } => {
|
KclValue::Object { value, .. } => {
|
||||||
for (s, t) in tys {
|
for (s, t) in tys {
|
||||||
// TODO coerce fields
|
// TODO coerce fields
|
||||||
if !value.get(s)?.has_type(t) {
|
if !value.get(s).ok_or(CoercionError::from(self))?.has_type(t) {
|
||||||
return None;
|
return Err(self.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO remove non-required fields
|
// TODO remove non-required fields
|
||||||
Some(self.clone())
|
Ok(self.clone())
|
||||||
}
|
}
|
||||||
KclValue::KclNone { meta, .. } if tys.is_empty() => Some(KclValue::Object {
|
KclValue::KclNone { meta, .. } if tys.is_empty() => Ok(KclValue::Object {
|
||||||
value: HashMap::new(),
|
value: HashMap::new(),
|
||||||
meta: meta.clone(),
|
meta: meta.clone(),
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => Err(self.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,6 +1092,8 @@ impl KclValue {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use crate::execution::{parse_execute, ExecTestResults};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn values(exec_state: &mut ExecState) -> Vec<KclValue> {
|
fn values(exec_state: &mut ExecState) -> Vec<KclValue> {
|
||||||
@ -988,9 +1223,8 @@ mod test {
|
|||||||
|
|
||||||
for v in &values[1..] {
|
for v in &values[1..] {
|
||||||
// Not a subtype
|
// Not a subtype
|
||||||
assert!(v
|
v.coerce(&RuntimeType::Primitive(PrimitiveType::Boolean), &mut exec_state)
|
||||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Boolean), &mut exec_state)
|
.unwrap_err();
|
||||||
.is_none());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1024,8 +1258,8 @@ mod test {
|
|||||||
},
|
},
|
||||||
&mut exec_state,
|
&mut exec_state,
|
||||||
);
|
);
|
||||||
assert!(none.coerce(&aty1, &mut exec_state).is_none());
|
none.coerce(&aty1, &mut exec_state).unwrap_err();
|
||||||
assert!(none.coerce(&aty1p, &mut exec_state).is_none());
|
none.coerce(&aty1p, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
let tty = RuntimeType::Tuple(vec![]);
|
let tty = RuntimeType::Tuple(vec![]);
|
||||||
let tty1 = RuntimeType::Tuple(vec![RuntimeType::solid()]);
|
let tty1 = RuntimeType::Tuple(vec![RuntimeType::solid()]);
|
||||||
@ -1038,7 +1272,7 @@ mod test {
|
|||||||
},
|
},
|
||||||
&mut exec_state,
|
&mut exec_state,
|
||||||
);
|
);
|
||||||
assert!(none.coerce(&tty1, &mut exec_state).is_none());
|
none.coerce(&tty1, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
let oty = RuntimeType::Object(vec![]);
|
let oty = RuntimeType::Object(vec![]);
|
||||||
assert_coerce_results(
|
assert_coerce_results(
|
||||||
@ -1107,7 +1341,7 @@ mod test {
|
|||||||
assert_coerce_results(&obj2, &ty0, &obj2, &mut exec_state);
|
assert_coerce_results(&obj2, &ty0, &obj2, &mut exec_state);
|
||||||
|
|
||||||
let ty1 = RuntimeType::Object(vec![("foo".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean))]);
|
let ty1 = RuntimeType::Object(vec![("foo".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean))]);
|
||||||
assert!(&obj0.coerce(&ty1, &mut exec_state).is_none());
|
obj0.coerce(&ty1, &mut exec_state).unwrap_err();
|
||||||
assert_coerce_results(&obj1, &ty1, &obj1, &mut exec_state);
|
assert_coerce_results(&obj1, &ty1, &obj1, &mut exec_state);
|
||||||
assert_coerce_results(&obj2, &ty1, &obj2, &mut exec_state);
|
assert_coerce_results(&obj2, &ty1, &obj2, &mut exec_state);
|
||||||
|
|
||||||
@ -1119,19 +1353,19 @@ mod test {
|
|||||||
),
|
),
|
||||||
("foo".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean)),
|
("foo".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean)),
|
||||||
]);
|
]);
|
||||||
assert!(&obj0.coerce(&ty2, &mut exec_state).is_none());
|
obj0.coerce(&ty2, &mut exec_state).unwrap_err();
|
||||||
assert!(&obj1.coerce(&ty2, &mut exec_state).is_none());
|
obj1.coerce(&ty2, &mut exec_state).unwrap_err();
|
||||||
assert_coerce_results(&obj2, &ty2, &obj2, &mut exec_state);
|
assert_coerce_results(&obj2, &ty2, &obj2, &mut exec_state);
|
||||||
|
|
||||||
// field not present
|
// field not present
|
||||||
let tyq = RuntimeType::Object(vec![("qux".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean))]);
|
let tyq = RuntimeType::Object(vec![("qux".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean))]);
|
||||||
assert!(&obj0.coerce(&tyq, &mut exec_state).is_none());
|
obj0.coerce(&tyq, &mut exec_state).unwrap_err();
|
||||||
assert!(&obj1.coerce(&tyq, &mut exec_state).is_none());
|
obj1.coerce(&tyq, &mut exec_state).unwrap_err();
|
||||||
assert!(&obj2.coerce(&tyq, &mut exec_state).is_none());
|
obj2.coerce(&tyq, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
// field with different type
|
// field with different type
|
||||||
let ty1 = RuntimeType::Object(vec![("bar".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean))]);
|
let ty1 = RuntimeType::Object(vec![("bar".to_owned(), RuntimeType::Primitive(PrimitiveType::Boolean))]);
|
||||||
assert!(&obj2.coerce(&ty1, &mut exec_state).is_none());
|
obj2.coerce(&ty1, &mut exec_state).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -1209,8 +1443,8 @@ mod test {
|
|||||||
assert_coerce_results(&hom_arr, &tyh, &hom_arr, &mut exec_state);
|
assert_coerce_results(&hom_arr, &tyh, &hom_arr, &mut exec_state);
|
||||||
assert_coerce_results(&mixed1, &tym1, &mixed1, &mut exec_state);
|
assert_coerce_results(&mixed1, &tym1, &mixed1, &mut exec_state);
|
||||||
assert_coerce_results(&mixed2, &tym2, &mixed2, &mut exec_state);
|
assert_coerce_results(&mixed2, &tym2, &mixed2, &mut exec_state);
|
||||||
assert!(&mixed1.coerce(&tym2, &mut exec_state).is_none());
|
mixed1.coerce(&tym2, &mut exec_state).unwrap_err();
|
||||||
assert!(&mixed2.coerce(&tym1, &mut exec_state).is_none());
|
mixed2.coerce(&tym1, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
// Length subtyping
|
// Length subtyping
|
||||||
let tyhn = RuntimeType::Array(
|
let tyhn = RuntimeType::Array(
|
||||||
@ -1227,15 +1461,15 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert_coerce_results(&hom_arr, &tyhn, &hom_arr, &mut exec_state);
|
assert_coerce_results(&hom_arr, &tyhn, &hom_arr, &mut exec_state);
|
||||||
assert_coerce_results(&hom_arr, &tyh1, &hom_arr, &mut exec_state);
|
assert_coerce_results(&hom_arr, &tyh1, &hom_arr, &mut exec_state);
|
||||||
assert!(&hom_arr.coerce(&tyh3, &mut exec_state).is_none());
|
hom_arr.coerce(&tyh3, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
let hom_arr0 = KclValue::HomArray {
|
let hom_arr0 = KclValue::HomArray {
|
||||||
value: vec![],
|
value: vec![],
|
||||||
ty: RuntimeType::Primitive(PrimitiveType::Number(NumericType::count())),
|
ty: RuntimeType::Primitive(PrimitiveType::Number(NumericType::count())),
|
||||||
};
|
};
|
||||||
assert_coerce_results(&hom_arr0, &tyhn, &hom_arr0, &mut exec_state);
|
assert_coerce_results(&hom_arr0, &tyhn, &hom_arr0, &mut exec_state);
|
||||||
assert!(&hom_arr0.coerce(&tyh1, &mut exec_state).is_none());
|
hom_arr0.coerce(&tyh1, &mut exec_state).unwrap_err();
|
||||||
assert!(&hom_arr0.coerce(&tyh3, &mut exec_state).is_none());
|
hom_arr0.coerce(&tyh3, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
// Covariance
|
// Covariance
|
||||||
// let tyh = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Number(NumericType::Any))), ArrayLen::Known(4));
|
// let tyh = RuntimeType::Array(Box::new(RuntimeType::Primitive(PrimitiveType::Number(NumericType::Any))), ArrayLen::Known(4));
|
||||||
@ -1275,16 +1509,16 @@ mod test {
|
|||||||
assert_coerce_results(&mixed1, &tyhn, &hom_arr_2, &mut exec_state);
|
assert_coerce_results(&mixed1, &tyhn, &hom_arr_2, &mut exec_state);
|
||||||
assert_coerce_results(&mixed1, &tyh1, &hom_arr_2, &mut exec_state);
|
assert_coerce_results(&mixed1, &tyh1, &hom_arr_2, &mut exec_state);
|
||||||
assert_coerce_results(&mixed0, &tyhn, &hom_arr0, &mut exec_state);
|
assert_coerce_results(&mixed0, &tyhn, &hom_arr0, &mut exec_state);
|
||||||
assert!(&mixed0.coerce(&tyh, &mut exec_state).is_none());
|
mixed0.coerce(&tyh, &mut exec_state).unwrap_err();
|
||||||
assert!(&mixed0.coerce(&tyh1, &mut exec_state).is_none());
|
mixed0.coerce(&tyh1, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
// Homogehous to mixed
|
// Homogehous to mixed
|
||||||
assert_coerce_results(&hom_arr_2, &tym1, &mixed1, &mut exec_state);
|
assert_coerce_results(&hom_arr_2, &tym1, &mixed1, &mut exec_state);
|
||||||
assert!(&hom_arr.coerce(&tym1, &mut exec_state).is_none());
|
hom_arr.coerce(&tym1, &mut exec_state).unwrap_err();
|
||||||
assert!(&hom_arr_2.coerce(&tym2, &mut exec_state).is_none());
|
hom_arr_2.coerce(&tym2, &mut exec_state).unwrap_err();
|
||||||
|
|
||||||
assert!(&mixed0.coerce(&tym1, &mut exec_state).is_none());
|
mixed0.coerce(&tym1, &mut exec_state).unwrap_err();
|
||||||
assert!(&mixed0.coerce(&tym2, &mut exec_state).is_none());
|
mixed0.coerce(&tym2, &mut exec_state).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -1334,8 +1568,8 @@ mod test {
|
|||||||
RuntimeType::Primitive(PrimitiveType::Boolean),
|
RuntimeType::Primitive(PrimitiveType::Boolean),
|
||||||
RuntimeType::Primitive(PrimitiveType::String),
|
RuntimeType::Primitive(PrimitiveType::String),
|
||||||
]);
|
]);
|
||||||
assert!(count.coerce(&tyb, &mut exec_state).is_none());
|
count.coerce(&tyb, &mut exec_state).unwrap_err();
|
||||||
assert!(count.coerce(&tyb2, &mut exec_state).is_none());
|
count.coerce(&tyb2, &mut exec_state).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
@ -1450,6 +1684,196 @@ mod test {
|
|||||||
assert_coerce_results(&a2d, &ty2d, &a2d, &mut exec_state);
|
assert_coerce_results(&a2d, &ty2d, &a2d, &mut exec_state);
|
||||||
assert_coerce_results(&a3d, &ty3d, &a3d, &mut exec_state);
|
assert_coerce_results(&a3d, &ty3d, &a3d, &mut exec_state);
|
||||||
assert_coerce_results(&a3d, &ty2d, &a2d, &mut exec_state);
|
assert_coerce_results(&a3d, &ty2d, &a2d, &mut exec_state);
|
||||||
assert!(a2d.coerce(&ty3d, &mut exec_state).is_none());
|
a2d.coerce(&ty3d, &mut exec_state).unwrap_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn coerce_numeric() {
|
||||||
|
let mut exec_state = ExecState::new(&crate::ExecutorContext::new_mock().await);
|
||||||
|
|
||||||
|
let count = KclValue::Number {
|
||||||
|
value: 1.0,
|
||||||
|
ty: NumericType::count(),
|
||||||
|
meta: Vec::new(),
|
||||||
|
};
|
||||||
|
let mm = KclValue::Number {
|
||||||
|
value: 1.0,
|
||||||
|
ty: NumericType::mm(),
|
||||||
|
meta: Vec::new(),
|
||||||
|
};
|
||||||
|
let inches = KclValue::Number {
|
||||||
|
value: 1.0,
|
||||||
|
ty: NumericType::Known(UnitType::Length(UnitLen::Inches)),
|
||||||
|
meta: Vec::new(),
|
||||||
|
};
|
||||||
|
let rads = KclValue::Number {
|
||||||
|
value: 1.0,
|
||||||
|
ty: NumericType::Known(UnitType::Angle(UnitAngle::Radians)),
|
||||||
|
meta: Vec::new(),
|
||||||
|
};
|
||||||
|
let default = KclValue::Number {
|
||||||
|
value: 1.0,
|
||||||
|
ty: NumericType::default(),
|
||||||
|
meta: Vec::new(),
|
||||||
|
};
|
||||||
|
let any = KclValue::Number {
|
||||||
|
value: 1.0,
|
||||||
|
ty: NumericType::Any,
|
||||||
|
meta: Vec::new(),
|
||||||
|
};
|
||||||
|
let unknown = KclValue::Number {
|
||||||
|
value: 1.0,
|
||||||
|
ty: NumericType::Unknown,
|
||||||
|
meta: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Trivial coercions
|
||||||
|
assert_coerce_results(&count, &NumericType::count().into(), &count, &mut exec_state);
|
||||||
|
assert_coerce_results(&mm, &NumericType::mm().into(), &mm, &mut exec_state);
|
||||||
|
assert_coerce_results(&any, &NumericType::Any.into(), &any, &mut exec_state);
|
||||||
|
assert_coerce_results(&unknown, &NumericType::Unknown.into(), &unknown, &mut exec_state);
|
||||||
|
assert_coerce_results(&default, &NumericType::default().into(), &default, &mut exec_state);
|
||||||
|
|
||||||
|
assert_coerce_results(&count, &NumericType::Any.into(), &count, &mut exec_state);
|
||||||
|
assert_coerce_results(&mm, &NumericType::Any.into(), &mm, &mut exec_state);
|
||||||
|
assert_coerce_results(&unknown, &NumericType::Any.into(), &unknown, &mut exec_state);
|
||||||
|
assert_coerce_results(&default, &NumericType::Any.into(), &default, &mut exec_state);
|
||||||
|
|
||||||
|
if !*CHECK_NUMERIC_TYPES {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
default
|
||||||
|
.coerce(
|
||||||
|
&NumericType::Default {
|
||||||
|
len: UnitLen::Yards,
|
||||||
|
angle: UnitAngle::default()
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
&mut exec_state
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
default
|
||||||
|
);
|
||||||
|
|
||||||
|
// No coercion
|
||||||
|
count.coerce(&NumericType::mm().into(), &mut exec_state).unwrap_err();
|
||||||
|
mm.coerce(&NumericType::count().into(), &mut exec_state).unwrap_err();
|
||||||
|
unknown.coerce(&NumericType::mm().into(), &mut exec_state).unwrap_err();
|
||||||
|
unknown
|
||||||
|
.coerce(&NumericType::default().into(), &mut exec_state)
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
count.coerce(&NumericType::Unknown.into(), &mut exec_state).unwrap_err();
|
||||||
|
mm.coerce(&NumericType::Unknown.into(), &mut exec_state).unwrap_err();
|
||||||
|
default
|
||||||
|
.coerce(&NumericType::Unknown.into(), &mut exec_state)
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
inches
|
||||||
|
.coerce(&NumericType::mm().into(), &mut exec_state)
|
||||||
|
.unwrap()
|
||||||
|
.as_f64()
|
||||||
|
.unwrap()
|
||||||
|
.round(),
|
||||||
|
25.0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
rads.coerce(
|
||||||
|
&NumericType::Known(UnitType::Angle(UnitAngle::Degrees)).into(),
|
||||||
|
&mut exec_state
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.as_f64()
|
||||||
|
.unwrap()
|
||||||
|
.round(),
|
||||||
|
57.0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
inches
|
||||||
|
.coerce(&NumericType::default().into(), &mut exec_state)
|
||||||
|
.unwrap()
|
||||||
|
.as_f64()
|
||||||
|
.unwrap()
|
||||||
|
.round(),
|
||||||
|
25.0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
rads.coerce(&NumericType::default().into(), &mut exec_state)
|
||||||
|
.unwrap()
|
||||||
|
.as_f64()
|
||||||
|
.unwrap()
|
||||||
|
.round(),
|
||||||
|
57.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn assert_value_and_type(name: &str, result: &ExecTestResults, expected: f64, expected_ty: NumericType) {
|
||||||
|
let mem = result.exec_state.stack();
|
||||||
|
match mem
|
||||||
|
.memory
|
||||||
|
.get_from(name, result.mem_env, SourceRange::default(), 0)
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
KclValue::Number { value, ty, .. } => {
|
||||||
|
assert_eq!(value.round(), expected);
|
||||||
|
assert_eq!(*ty, expected_ty);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn combine_numeric() {
|
||||||
|
let program = r#"a = 5 + 4
|
||||||
|
b = 5 - 2
|
||||||
|
c = 5mm - 2mm + 10mm
|
||||||
|
d = 5mm - 2 + 10
|
||||||
|
e = 5 - 2mm + 10
|
||||||
|
f = 30mm - 1inch
|
||||||
|
|
||||||
|
g = 2 * 10
|
||||||
|
h = 2 * 10mm
|
||||||
|
i = 2mm * 10mm
|
||||||
|
j = 2_ * 10
|
||||||
|
k = 2_ * 3mm * 3mm
|
||||||
|
|
||||||
|
l = 1 / 10
|
||||||
|
m = 2mm / 1mm
|
||||||
|
n = 10inch / 2mm
|
||||||
|
o = 3mm / 3
|
||||||
|
p = 3_ / 4
|
||||||
|
q = 4inch / 2_
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let result = parse_execute(program).await.unwrap();
|
||||||
|
if *CHECK_NUMERIC_TYPES {
|
||||||
|
assert_eq!(result.exec_state.errors().len(), 2);
|
||||||
|
} else {
|
||||||
|
assert!(result.exec_state.errors().is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_value_and_type("a", &result, 9.0, NumericType::default());
|
||||||
|
assert_value_and_type("b", &result, 3.0, NumericType::default());
|
||||||
|
assert_value_and_type("c", &result, 13.0, NumericType::mm());
|
||||||
|
assert_value_and_type("d", &result, 13.0, NumericType::mm());
|
||||||
|
assert_value_and_type("e", &result, 13.0, NumericType::mm());
|
||||||
|
assert_value_and_type("f", &result, 5.0, NumericType::mm());
|
||||||
|
|
||||||
|
assert_value_and_type("g", &result, 20.0, NumericType::default());
|
||||||
|
assert_value_and_type("h", &result, 20.0, NumericType::mm());
|
||||||
|
assert_value_and_type("i", &result, 20.0, NumericType::Unknown);
|
||||||
|
assert_value_and_type("j", &result, 20.0, NumericType::default());
|
||||||
|
assert_value_and_type("k", &result, 18.0, NumericType::Unknown);
|
||||||
|
|
||||||
|
assert_value_and_type("l", &result, 0.0, NumericType::count());
|
||||||
|
assert_value_and_type("m", &result, 2.0, NumericType::count());
|
||||||
|
assert_value_and_type("n", &result, 127.0, NumericType::count());
|
||||||
|
assert_value_and_type("o", &result, 1.0, NumericType::mm());
|
||||||
|
assert_value_and_type("p", &result, 1.0, NumericType::count());
|
||||||
|
assert_value_and_type("q", &result, 2.0, NumericType::Known(UnitType::Length(UnitLen::Inches)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ pub mod project;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use validator::{Validate, ValidateRange};
|
use validator::{Validate, ValidateRange};
|
||||||
|
|
||||||
const DEFAULT_THEME_COLOR: f64 = 264.5;
|
const DEFAULT_THEME_COLOR: f64 = 264.5;
|
||||||
@ -131,9 +131,14 @@ pub struct AppSettings {
|
|||||||
/// This setting only applies to the web app. And is temporary until we have Linux support.
|
/// This setting only applies to the web app. And is temporary until we have Linux support.
|
||||||
#[serde(default, alias = "dismissWebBanner", skip_serializing_if = "is_default")]
|
#[serde(default, alias = "dismissWebBanner", skip_serializing_if = "is_default")]
|
||||||
pub dismiss_web_banner: bool,
|
pub dismiss_web_banner: bool,
|
||||||
/// When the user is idle, and this is true, the stream will be torn down.
|
/// When the user is idle, teardown the stream after some time.
|
||||||
#[serde(default, alias = "streamIdleMode", skip_serializing_if = "is_default")]
|
#[serde(
|
||||||
pub stream_idle_mode: bool,
|
default,
|
||||||
|
deserialize_with = "deserialize_stream_idle_mode",
|
||||||
|
alias = "streamIdleMode",
|
||||||
|
skip_serializing_if = "is_default"
|
||||||
|
)]
|
||||||
|
stream_idle_mode: Option<u32>,
|
||||||
/// When the user is idle, and this is true, the stream will be torn down.
|
/// When the user is idle, and this is true, the stream will be torn down.
|
||||||
#[serde(default, alias = "allowOrbitInSketchMode", skip_serializing_if = "is_default")]
|
#[serde(default, alias = "allowOrbitInSketchMode", skip_serializing_if = "is_default")]
|
||||||
pub allow_orbit_in_sketch_mode: bool,
|
pub allow_orbit_in_sketch_mode: bool,
|
||||||
@ -143,7 +148,31 @@ pub struct AppSettings {
|
|||||||
pub show_debug_panel: bool,
|
pub show_debug_panel: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: When we remove backwards compatibility with the old settings file, we can remove this.
|
fn deserialize_stream_idle_mode<'de, D>(deserializer: D) -> Result<Option<u32>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum StreamIdleModeValue {
|
||||||
|
Number(u32),
|
||||||
|
String(String),
|
||||||
|
Boolean(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_TIMEOUT: u32 = 1000 * 60 * 5;
|
||||||
|
|
||||||
|
Ok(match StreamIdleModeValue::deserialize(deserializer) {
|
||||||
|
Ok(StreamIdleModeValue::Number(value)) => Some(value),
|
||||||
|
Ok(StreamIdleModeValue::String(value)) => Some(value.parse::<u32>().unwrap_or(DEFAULT_TIMEOUT)),
|
||||||
|
// The old type of this value. I'm willing to say no one used it but
|
||||||
|
// we can never guarantee it.
|
||||||
|
Ok(StreamIdleModeValue::Boolean(true)) => Some(DEFAULT_TIMEOUT),
|
||||||
|
Ok(StreamIdleModeValue::Boolean(false)) => None,
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, ts_rs::TS, PartialEq)]
|
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, ts_rs::TS, PartialEq)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
@ -626,7 +655,7 @@ textWrapping = true
|
|||||||
theme_color: None,
|
theme_color: None,
|
||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
allow_orbit_in_sketch_mode: false,
|
allow_orbit_in_sketch_mode: false,
|
||||||
show_debug_panel: true,
|
show_debug_panel: true,
|
||||||
},
|
},
|
||||||
@ -691,7 +720,7 @@ includeSettings = false
|
|||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
show_debug_panel: true,
|
show_debug_panel: true,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
allow_orbit_in_sketch_mode: false,
|
allow_orbit_in_sketch_mode: false,
|
||||||
},
|
},
|
||||||
modeling: ModelingSettings {
|
modeling: ModelingSettings {
|
||||||
@ -759,7 +788,7 @@ defaultProjectName = "projects-$nnn"
|
|||||||
theme_color: None,
|
theme_color: None,
|
||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
allow_orbit_in_sketch_mode: false,
|
allow_orbit_in_sketch_mode: false,
|
||||||
show_debug_panel: true,
|
show_debug_panel: true,
|
||||||
},
|
},
|
||||||
@ -841,7 +870,7 @@ projectDirectory = "/Users/macinatormax/Documents/kittycad-modeling-projects""#;
|
|||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
show_debug_panel: false,
|
show_debug_panel: false,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
allow_orbit_in_sketch_mode: false,
|
allow_orbit_in_sketch_mode: false,
|
||||||
},
|
},
|
||||||
modeling: ModelingSettings {
|
modeling: ModelingSettings {
|
||||||
|
@ -84,7 +84,7 @@ fn parse_test(test: &Test) {
|
|||||||
insta::assert_json_snapshot!("ast", parse_res, {
|
insta::assert_json_snapshot!("ast", parse_res, {
|
||||||
".**.start" => 0,
|
".**.start" => 0,
|
||||||
".**.end" => 0,
|
".**.end" => 0,
|
||||||
".**.comment_start" => 0,
|
".**.commentStart" => 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use kcmc::{
|
|||||||
};
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
@ -72,7 +72,7 @@ impl KwArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TyF64 {
|
pub struct TyF64 {
|
||||||
@ -92,7 +92,7 @@ impl TyF64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map(mut self, n: f64) -> Self {
|
pub fn map_value(mut self, n: f64) -> Self {
|
||||||
self.n = n;
|
self.n = n;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ impl Args {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
let arg = arg.value.coerce(ty, exec_state).ok_or_else(|| {
|
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
||||||
let actual_type_name = arg.value.human_friendly_type();
|
let actual_type_name = arg.value.human_friendly_type();
|
||||||
let msg_base = format!(
|
let msg_base = format!(
|
||||||
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
||||||
@ -332,7 +332,7 @@ impl Args {
|
|||||||
message: format!("This function requires a value for the special unlabeled first parameter, '{label}'"),
|
message: format!("This function requires a value for the special unlabeled first parameter, '{label}'"),
|
||||||
}))?;
|
}))?;
|
||||||
|
|
||||||
let arg = arg.value.coerce(ty, exec_state).ok_or_else(|| {
|
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
||||||
let actual_type_name = arg.value.human_friendly_type();
|
let actual_type_name = arg.value.human_friendly_type();
|
||||||
let msg_base = format!(
|
let msg_base = format!(
|
||||||
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
||||||
@ -503,19 +503,19 @@ impl Args {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn make_user_val_from_point(&self, p: [f64; 2]) -> Result<KclValue, KclError> {
|
pub(crate) fn make_user_val_from_point(&self, p: [TyF64; 2]) -> Result<KclValue, KclError> {
|
||||||
let meta = Metadata {
|
let meta = Metadata {
|
||||||
source_range: self.source_range,
|
source_range: self.source_range,
|
||||||
};
|
};
|
||||||
let x = KclValue::Number {
|
let x = KclValue::Number {
|
||||||
value: p[0],
|
value: p[0].n,
|
||||||
meta: vec![meta],
|
meta: vec![meta],
|
||||||
ty: NumericType::Unknown,
|
ty: p[0].ty.clone(),
|
||||||
};
|
};
|
||||||
let y = KclValue::Number {
|
let y = KclValue::Number {
|
||||||
value: p[1],
|
value: p[1].n,
|
||||||
meta: vec![meta],
|
meta: vec![meta],
|
||||||
ty: NumericType::Unknown,
|
ty: p[1].ty.clone(),
|
||||||
};
|
};
|
||||||
Ok(KclValue::MixedArray {
|
Ok(KclValue::MixedArray {
|
||||||
value: vec![x, y],
|
value: vec![x, y],
|
||||||
@ -523,7 +523,7 @@ impl Args {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn make_user_val_from_f64(&self, f: f64) -> KclValue {
|
pub(super) fn make_user_val_from_f64(&self, f: f64) -> KclValue {
|
||||||
KclValue::from_number(
|
KclValue::from_number(
|
||||||
f,
|
f,
|
||||||
vec![Metadata {
|
vec![Metadata {
|
||||||
@ -532,7 +532,7 @@ impl Args {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn make_user_val_from_f64_with_type(&self, f: TyF64) -> KclValue {
|
pub(super) fn make_user_val_from_f64_with_type(&self, f: TyF64) -> KclValue {
|
||||||
KclValue::from_number_with_type(
|
KclValue::from_number_with_type(
|
||||||
f.n,
|
f.n,
|
||||||
f.ty,
|
f.ty,
|
||||||
@ -542,25 +542,6 @@ impl Args {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn make_user_val_from_f64_array(&self, f: Vec<f64>, ty: &NumericType) -> Result<KclValue, KclError> {
|
|
||||||
let array = f
|
|
||||||
.into_iter()
|
|
||||||
.map(|n| KclValue::Number {
|
|
||||||
value: n,
|
|
||||||
meta: vec![Metadata {
|
|
||||||
source_range: self.source_range,
|
|
||||||
}],
|
|
||||||
ty: ty.clone(),
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
Ok(KclValue::MixedArray {
|
|
||||||
value: array,
|
|
||||||
meta: vec![Metadata {
|
|
||||||
source_range: self.source_range,
|
|
||||||
}],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_number(&self) -> Result<f64, KclError> {
|
pub(crate) fn get_number(&self) -> Result<f64, KclError> {
|
||||||
FromArgs::from_args(self, 0)
|
FromArgs::from_args(self, 0)
|
||||||
}
|
}
|
||||||
@ -616,8 +597,7 @@ impl Args {
|
|||||||
let mut numbers = numbers.into_iter();
|
let mut numbers = numbers.into_iter();
|
||||||
let a = numbers.next().unwrap();
|
let a = numbers.next().unwrap();
|
||||||
let b = numbers.next().unwrap();
|
let b = numbers.next().unwrap();
|
||||||
let ty = a.ty.combine_eq(&b.ty);
|
Ok(NumericType::combine_eq(a, b))
|
||||||
Ok((a.n, b.n, ty))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_sketches(&self, exec_state: &mut ExecState) -> Result<(Vec<Sketch>, Sketch), KclError> {
|
pub(crate) fn get_sketches(&self, exec_state: &mut ExecState) -> Result<(Vec<Sketch>, Sketch), KclError> {
|
||||||
@ -627,16 +607,15 @@ impl Args {
|
|||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
let sarg = arg0
|
let sarg = arg0.value.coerce(&RuntimeType::sketches(), exec_state).map_err(|_| {
|
||||||
.value
|
KclError::Type(KclErrorDetails {
|
||||||
.coerce(&RuntimeType::sketches(), exec_state)
|
|
||||||
.ok_or(KclError::Type(KclErrorDetails {
|
|
||||||
message: format!(
|
message: format!(
|
||||||
"Expected an array of sketches, found {}",
|
"Expected an array of sketches, found {}",
|
||||||
arg0.value.human_friendly_type()
|
arg0.value.human_friendly_type()
|
||||||
),
|
),
|
||||||
source_ranges: vec![self.source_range],
|
source_ranges: vec![self.source_range],
|
||||||
}))?;
|
})
|
||||||
|
})?;
|
||||||
let sketches = match sarg {
|
let sketches = match sarg {
|
||||||
KclValue::HomArray { value, .. } => value.iter().map(|v| v.as_sketch().unwrap().clone()).collect(),
|
KclValue::HomArray { value, .. } => value.iter().map(|v| v.as_sketch().unwrap().clone()).collect(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -651,10 +630,12 @@ impl Args {
|
|||||||
let sarg = arg1
|
let sarg = arg1
|
||||||
.value
|
.value
|
||||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
||||||
.ok_or(KclError::Type(KclErrorDetails {
|
.map_err(|_| {
|
||||||
message: format!("Expected a sketch, found {}", arg1.value.human_friendly_type()),
|
KclError::Type(KclErrorDetails {
|
||||||
source_ranges: vec![self.source_range],
|
message: format!("Expected a sketch, found {}", arg1.value.human_friendly_type()),
|
||||||
}))?;
|
source_ranges: vec![self.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
let sketch = match sarg {
|
let sketch = match sarg {
|
||||||
KclValue::Sketch { value } => *value,
|
KclValue::Sketch { value } => *value,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -673,10 +654,12 @@ impl Args {
|
|||||||
let sarg = arg0
|
let sarg = arg0
|
||||||
.value
|
.value
|
||||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
||||||
.ok_or(KclError::Type(KclErrorDetails {
|
.map_err(|_| {
|
||||||
message: format!("Expected a sketch, found {}", arg0.value.human_friendly_type()),
|
KclError::Type(KclErrorDetails {
|
||||||
source_ranges: vec![self.source_range],
|
message: format!("Expected a sketch, found {}", arg0.value.human_friendly_type()),
|
||||||
}))?;
|
source_ranges: vec![self.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
match sarg {
|
match sarg {
|
||||||
KclValue::Sketch { value } => Ok(*value),
|
KclValue::Sketch { value } => Ok(*value),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -694,10 +677,9 @@ impl Args {
|
|||||||
FromArgs::from_args(self, 0)
|
FromArgs::from_args(self, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_data_and_optional_tag<'a, T>(&'a self) -> Result<(T, Option<FaceTag>), KclError>
|
pub(crate) fn get_sketch_data_and_optional_tag(
|
||||||
where
|
&self,
|
||||||
T: serde::de::DeserializeOwned + FromKclValue<'a> + Sized,
|
) -> Result<(super::sketch::SketchData, Option<FaceTag>), KclError> {
|
||||||
{
|
|
||||||
FromArgs::from_args(self, 0)
|
FromArgs::from_args(self, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,13 +700,15 @@ impl Args {
|
|||||||
let sarg = arg1
|
let sarg = arg1
|
||||||
.value
|
.value
|
||||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
||||||
.ok_or(KclError::Type(KclErrorDetails {
|
.map_err(|_| {
|
||||||
message: format!(
|
KclError::Type(KclErrorDetails {
|
||||||
"Expected a sketch for second argument, found {}",
|
message: format!(
|
||||||
arg1.value.human_friendly_type()
|
"Expected a sketch for second argument, found {}",
|
||||||
),
|
arg1.value.human_friendly_type()
|
||||||
source_ranges: vec![self.source_range],
|
),
|
||||||
}))?;
|
source_ranges: vec![self.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
let sketch = match sarg {
|
let sketch = match sarg {
|
||||||
KclValue::Sketch { value } => *value,
|
KclValue::Sketch { value } => *value,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -754,13 +738,15 @@ impl Args {
|
|||||||
let sarg = arg1
|
let sarg = arg1
|
||||||
.value
|
.value
|
||||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Solid), exec_state)
|
.coerce(&RuntimeType::Primitive(PrimitiveType::Solid), exec_state)
|
||||||
.ok_or(KclError::Type(KclErrorDetails {
|
.map_err(|_| {
|
||||||
message: format!(
|
KclError::Type(KclErrorDetails {
|
||||||
"Expected a solid for second argument, found {}",
|
message: format!(
|
||||||
arg1.value.human_friendly_type()
|
"Expected a solid for second argument, found {}",
|
||||||
),
|
arg1.value.human_friendly_type()
|
||||||
source_ranges: vec![self.source_range],
|
),
|
||||||
}))?;
|
source_ranges: vec![self.source_range],
|
||||||
|
})
|
||||||
|
})?;
|
||||||
let solid = match sarg {
|
let solid = match sarg {
|
||||||
KclValue::Solid { value } => value,
|
KclValue::Solid { value } => value,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -1165,15 +1151,6 @@ impl<'a> FromKclValue<'a> for super::shapes::PolygonData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromKclValue<'a> for crate::std::polar::PolarCoordsData {
|
|
||||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
|
||||||
let obj = arg.as_object()?;
|
|
||||||
let_field_of!(obj, angle);
|
|
||||||
let_field_of!(obj, length);
|
|
||||||
Some(Self { angle, length })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromKclValue<'a> for crate::execution::Plane {
|
impl<'a> FromKclValue<'a> for crate::execution::Plane {
|
||||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||||
arg.as_plane().cloned()
|
arg.as_plane().cloned()
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user