Compare commits
5 Commits
callbacks-
...
refactor-l
Author | SHA1 | Date | |
---|---|---|---|
2363010cbc | |||
bd17bc98d5 | |||
e7a2824cb2 | |||
f77ed3d790 | |||
bc5fdbad43 |
4
.github/workflows/cargo-bench.yml
vendored
@ -38,7 +38,5 @@ jobs:
|
|||||||
- name: Benchmark kcl library
|
- name: Benchmark kcl library
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |-
|
run: |-
|
||||||
cd src/wasm-lib/kcl; cargo bench --all-features -- iai
|
cd src/wasm-lib/kcl; cargo bench -- iai
|
||||||
env:
|
|
||||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
|
|
||||||
|
|
||||||
|
17
.github/workflows/ci.yml
vendored
@ -138,7 +138,6 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
if: github.event_name == 'schedule'
|
|
||||||
|
|
||||||
- name: Copy updated .json files
|
- name: Copy updated .json files
|
||||||
if: github.event_name == 'schedule'
|
if: github.event_name == 'schedule'
|
||||||
@ -239,8 +238,12 @@ jobs:
|
|||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
- name: Build the app (debug)
|
- name: Build the app (debug)
|
||||||
|
uses: tauri-apps/tauri-action@v0
|
||||||
if: ${{ env.BUILD_RELEASE == 'false' }}
|
if: ${{ env.BUILD_RELEASE == 'false' }}
|
||||||
run: "yarn tauri build --debug ${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
|
with:
|
||||||
|
includeRelease: false
|
||||||
|
includeDebug: true
|
||||||
|
args: "${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
|
||||||
|
|
||||||
- name: Build for Mac TestFlight (nightly)
|
- name: Build for Mac TestFlight (nightly)
|
||||||
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
|
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
|
||||||
@ -333,6 +336,7 @@ jobs:
|
|||||||
# specific and we want to overwrite it with the this new build after and
|
# specific and we want to overwrite it with the this new build after and
|
||||||
# not upload the apple store build to the public bucket
|
# not upload the apple store build to the public bucket
|
||||||
- name: Build the app (release) and sign
|
- name: Build the app (release) and sign
|
||||||
|
uses: tauri-apps/tauri-action@v0
|
||||||
if: ${{ env.BUILD_RELEASE == 'true' }}
|
if: ${{ env.BUILD_RELEASE == 'true' }}
|
||||||
env:
|
env:
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||||
@ -344,7 +348,8 @@ jobs:
|
|||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
|
TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
|
||||||
run: "yarn tauri build ${{ env.TAURI_CONF_ARGS }} ${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
|
with:
|
||||||
|
args: "${{ env.TAURI_CONF_ARGS }} ${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
if: matrix.os != 'ubuntu-latest'
|
if: matrix.os != 'ubuntu-latest'
|
||||||
@ -362,7 +367,7 @@ jobs:
|
|||||||
export VITE_KC_API_BASE_URL
|
export VITE_KC_API_BASE_URL
|
||||||
xvfb-run yarn test:e2e:tauri
|
xvfb-run yarn test:e2e:tauri
|
||||||
env:
|
env:
|
||||||
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/zoo-modeling-app"
|
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/app"
|
||||||
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
|
||||||
- name: Run e2e tests (windows only)
|
- name: Run e2e tests (windows only)
|
||||||
@ -371,15 +376,13 @@ jobs:
|
|||||||
cargo install tauri-driver --force
|
cargo install tauri-driver --force
|
||||||
yarn wdio run wdio.conf.ts
|
yarn wdio run wdio.conf.ts
|
||||||
env:
|
env:
|
||||||
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\Zoo Modeling App.exe"
|
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\app.exe"
|
||||||
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
VITE_KC_API_BASE_URL: ${{ env.BUILD_RELEASE == 'true' && 'https://api.zoo.dev' || 'https://api.dev.zoo.dev' }}
|
VITE_KC_API_BASE_URL: ${{ env.BUILD_RELEASE == 'true' && 'https://api.zoo.dev' || 'https://api.dev.zoo.dev' }}
|
||||||
E2E_TAURI_ENABLED: true
|
E2E_TAURI_ENABLED: true
|
||||||
TS_NODE_COMPILER_OPTIONS: '{"module": "commonjs"}'
|
TS_NODE_COMPILER_OPTIONS: '{"module": "commonjs"}'
|
||||||
|
|
||||||
publish-apps-release:
|
publish-apps-release:
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
|
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
|
||||||
needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps]
|
needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps]
|
||||||
|
27
.github/workflows/playwright.yml
vendored
@ -38,8 +38,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest-8-cores
|
runs-on: ubuntu-latest-8-cores
|
||||||
needs: check-rust-changes
|
needs: check-rust-changes
|
||||||
steps:
|
steps:
|
||||||
- name: Tune GitHub-hosted runner network
|
|
||||||
uses: smorimoto/tune-github-hosted-runner-network@v1
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@ -92,17 +90,14 @@ jobs:
|
|||||||
- name: build web
|
- name: build web
|
||||||
run: yarn build:local
|
run: yarn build:local
|
||||||
- name: Run ubuntu/chrome snapshots
|
- name: Run ubuntu/chrome snapshots
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
run: |
|
||||||
yarn playwright test --project="Google Chrome" --update-snapshots e2e/playwright/snapshot-tests.spec.ts
|
yarn playwright test --project="Google Chrome" --update-snapshots e2e/playwright/snapshot-tests.spec.ts
|
||||||
|
# remove test-results, messes with retry logic
|
||||||
|
rm -r test-results
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
||||||
- name: Clean up test-results
|
|
||||||
if: always()
|
|
||||||
continue-on-error: true
|
|
||||||
run: rm -r test-results
|
|
||||||
- name: check for changes
|
- name: check for changes
|
||||||
id: git-check
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
@ -129,7 +124,7 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: steps.git-check.outputs.modified == 'true'
|
if: steps.git-check.outputs.modified == 'true'
|
||||||
with:
|
with:
|
||||||
name: playwright-report-ubuntu-${{ github.sha }}
|
name: playwright-report-ubuntu
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
# if have previous run results, use them
|
# if have previous run results, use them
|
||||||
@ -137,7 +132,7 @@ jobs:
|
|||||||
if: always()
|
if: always()
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
name: test-results-ubuntu-${{ github.sha }}
|
name: test-results-ubuntu
|
||||||
path: test-results/
|
path: test-results/
|
||||||
- name: Run ubuntu/chrome flow retry failures
|
- name: Run ubuntu/chrome flow retry failures
|
||||||
id: retry
|
id: retry
|
||||||
@ -163,25 +158,23 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: test-results-ubuntu-${{ github.sha }}
|
name: test-results-ubuntu
|
||||||
path: test-results/
|
path: test-results/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report-ubuntu-${{ github.sha }}
|
name: playwright-report-ubuntu
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
playwright-macos:
|
playwright-macos:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
runs-on: macos-14-large
|
runs-on: macos-14
|
||||||
needs: check-rust-changes
|
needs: check-rust-changes
|
||||||
steps:
|
steps:
|
||||||
- name: Tune GitHub-hosted runner network
|
|
||||||
uses: smorimoto/tune-github-hosted-runner-network@v1
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@ -239,7 +232,7 @@ jobs:
|
|||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
name: test-results-macos-${{ github.sha }}
|
name: test-results-macos
|
||||||
path: test-results/
|
path: test-results/
|
||||||
- name: Run macos/safari flow retry failures
|
- name: Run macos/safari flow retry failures
|
||||||
id: retry
|
id: retry
|
||||||
@ -267,14 +260,14 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
with:
|
with:
|
||||||
name: test-results-macos-${{ github.sha }}
|
name: test-results-macos
|
||||||
path: test-results/
|
path: test-results/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
with:
|
with:
|
||||||
name: playwright-report-macos-${{ github.sha }}
|
name: playwright-report-macos
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
2
.gitignore
vendored
@ -56,5 +56,3 @@ src-tauri/gen
|
|||||||
|
|
||||||
src/wasm-lib/grackle/stdlib_cube_partial.json
|
src/wasm-lib/grackle/stdlib_cube_partial.json
|
||||||
Mac_App_Distribution.provisionprofile
|
Mac_App_Distribution.provisionprofile
|
||||||
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# Ignore artifacts:
|
# Ignore artifacts:
|
||||||
build
|
build
|
||||||
dist
|
|
||||||
coverage
|
coverage
|
||||||
|
|
||||||
# Ignore Rust projects:
|
# Ignore Rust projects:
|
||||||
@ -10,6 +9,5 @@ src/wasm-lib/pkg
|
|||||||
src/wasm-lib/kcl/bindings
|
src/wasm-lib/kcl/bindings
|
||||||
e2e/playwright/export-snapshots
|
e2e/playwright/export-snapshots
|
||||||
|
|
||||||
|
|
||||||
# XState generated files
|
# XState generated files
|
||||||
src/machines/**.typegen.ts
|
src/machines/**.typegen.ts
|
||||||
|
7
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"geos"
|
||||||
|
],
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.insertSpaces": true,
|
||||||
|
}
|
26
README.md
@ -124,20 +124,36 @@ Before you submit a contribution PR to this repo, please ensure that:
|
|||||||
|
|
||||||
## Release a new version
|
## Release a new version
|
||||||
|
|
||||||
1. Bump the versions by running `./make-realease.sh` while on a fresh pull of main
|
1. Bump the versions in the .json files by creating a `Cut release v{x}.{y}.{z}` PR, committing the changes from
|
||||||
|
|
||||||
That will create the branch with the updated json files for you.
|
```bash
|
||||||
|
VERSION=x.y.z yarn run bump-jsons
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively you can try the experimental `make-release.sh` bash script that will create the branch with the updated json files for you.
|
||||||
run `./make-release.sh` for a patch update
|
run `./make-release.sh` for a patch update
|
||||||
run `./make-release.sh "minor"` for minor
|
run `./make-release.sh "minor"` for minor
|
||||||
run `./make-release.sh "major"` for major
|
run `./make-release.sh "major"` for major
|
||||||
|
|
||||||
After it runs you should just need to push the push the branch and open a PR (it will suggest a changelog for you too, delete any that are not user facing)
|
The PR may serve as a place to discuss the human-readable changelog and extra QA. A quick way of getting PR's merged since the last bump is to [use this PR filter](https://github.com/KittyCAD/modeling-app/pulls?q=is%3Apr+sort%3Aupdated-desc+is%3Amerged+), open up the browser console and paste in the following
|
||||||
|
|
||||||
The PR may serve as a place to discuss the human-readable changelog and extra QA.
|
```typescript
|
||||||
|
console.log(
|
||||||
|
'- ' +
|
||||||
|
Array.from(
|
||||||
|
document.querySelectorAll('[data-hovercard-type="pull_request"]')
|
||||||
|
).map((a) => `[${a.innerText}](${a.href})`).join(`
|
||||||
|
- `)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
grab the md list and delete any that are older than the last bump
|
||||||
|
|
||||||
2. Merge the PR
|
2. Merge the PR
|
||||||
|
|
||||||
3. Profit (A new Action kicks in at https://github.com/KittyCAD/modeling-app/actions if the PR was correctly named)
|
3. Create a new release and tag pointing to the bump version commit using semantic versioning `v{x}.{y}.{z}`
|
||||||
|
|
||||||
|
4. A new Action kicks in at https://github.com/KittyCAD/modeling-app/actions, uploading artifacts to the release
|
||||||
|
|
||||||
## Fuzzing the parser
|
## Fuzzing the parser
|
||||||
|
|
||||||
|
@ -121,9 +121,6 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -285,9 +282,6 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -125,9 +125,6 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -289,9 +286,6 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -126,9 +126,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -290,9 +287,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -482,9 +476,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -646,9 +637,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -125,9 +125,6 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -289,9 +286,6 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -481,9 +475,6 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -645,9 +636,6 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -133,9 +133,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -297,9 +294,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -489,9 +483,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -653,9 +644,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -124,9 +124,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -288,9 +285,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -480,9 +474,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -644,9 +635,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -124,9 +124,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -288,9 +285,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -480,9 +474,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -644,9 +635,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -135,9 +135,6 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -299,9 +296,6 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -491,9 +485,6 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -655,9 +646,6 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -130,9 +130,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -294,9 +291,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -486,9 +480,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -650,9 +641,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -225,9 +225,6 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -535,9 +532,6 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -123,9 +123,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -413,9 +410,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -605,9 +599,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -769,9 +760,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -125,9 +125,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -289,9 +286,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -481,9 +475,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -645,9 +636,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -150,9 +150,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -314,9 +311,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
@ -586,9 +580,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -225,9 +225,6 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -527,9 +524,6 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -215,9 +215,6 @@ const revolution = startSketchOn(box, "revolveAxis")
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -211,9 +211,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -211,9 +211,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -213,9 +213,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -213,9 +213,6 @@ const part001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -515,9 +512,6 @@ const part001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -136,9 +136,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -300,9 +297,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
@ -485,9 +479,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -649,9 +640,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -833,9 +821,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -997,9 +982,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -55,7 +55,6 @@ layout: manual
|
|||||||
* [`patternCircular3d`](kcl/patternCircular3d)
|
* [`patternCircular3d`](kcl/patternCircular3d)
|
||||||
* [`patternLinear2d`](kcl/patternLinear2d)
|
* [`patternLinear2d`](kcl/patternLinear2d)
|
||||||
* [`patternLinear3d`](kcl/patternLinear3d)
|
* [`patternLinear3d`](kcl/patternLinear3d)
|
||||||
* [`patternTransform`](kcl/patternTransform)
|
|
||||||
* [`pi`](kcl/pi)
|
* [`pi`](kcl/pi)
|
||||||
* [`pow`](kcl/pow)
|
* [`pow`](kcl/pow)
|
||||||
* [`profileStart`](kcl/profileStart)
|
* [`profileStart`](kcl/profileStart)
|
||||||
|
@ -116,9 +116,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -280,9 +277,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -116,9 +116,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -280,9 +277,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -129,9 +129,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -293,9 +290,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -485,9 +479,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -649,9 +640,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -116,9 +116,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -280,9 +277,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -472,9 +466,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -636,9 +627,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -134,9 +134,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -298,9 +295,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
|
@ -217,9 +217,6 @@ const example = extrude(-5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -127,9 +127,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -291,9 +288,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
|
@ -215,9 +215,6 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -117,9 +117,6 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -281,9 +278,6 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -112,9 +112,6 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -276,9 +273,6 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -111,9 +111,6 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -275,9 +272,6 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -247,9 +247,6 @@ uuid |
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -411,9 +408,6 @@ uuid |
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -679,9 +673,6 @@ uuid |
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -124,9 +124,6 @@ const example = extrude(4, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -288,9 +285,6 @@ const example = extrude(4, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -122,9 +122,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -286,9 +283,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -123,9 +123,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -287,9 +284,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -121,9 +121,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -285,9 +282,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -213,9 +213,6 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -515,9 +512,6 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -195,9 +195,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -445,9 +442,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -609,9 +603,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -142,9 +142,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -306,9 +303,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -264,9 +264,6 @@ const a1 = startSketchOn({
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -542,9 +539,6 @@ const a1 = startSketchOn({
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
9885
docs/kcl/std.json
@ -125,9 +125,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -289,9 +286,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -481,9 +475,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -645,9 +636,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -116,9 +116,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -280,9 +277,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -472,9 +466,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -636,9 +627,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -74,107 +74,6 @@ You can nest expressions in parenthesis as well:
|
|||||||
let myMathExpression = 3 + (1 * 2 / (3 - 7))
|
let myMathExpression = 3 + (1 * 2 / (3 - 7))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tags
|
Please if you find any issues using any of the above expressions or syntax
|
||||||
|
|
||||||
Tags are used to give a name (tag) to a specific path.
|
|
||||||
|
|
||||||
### Tag Declaration
|
|
||||||
|
|
||||||
The syntax for declaring a tag is `$myTag` you would use it in the following
|
|
||||||
way:
|
|
||||||
|
|
||||||
```
|
|
||||||
startSketchOn('XZ')
|
|
||||||
|> startProfileAt(origin, %)
|
|
||||||
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001, %) - 90,
|
|
||||||
196.99
|
|
||||||
], %, $rectangleSegmentB001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001, %),
|
|
||||||
-segLen(rectangleSegmentA001, %)
|
|
||||||
], %, $rectangleSegmentC001)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tag Identifier
|
|
||||||
|
|
||||||
As per the example above you can use the tag identifier to get a reference to the
|
|
||||||
tagged object. The syntax for this is `myTag`.
|
|
||||||
|
|
||||||
In the example above we use the tag identifier to get the angle of the segment
|
|
||||||
`segAng(rectangleSegmentA001, %)`.
|
|
||||||
|
|
||||||
|
|
||||||
### Tag Scope
|
|
||||||
|
|
||||||
Tags are scoped globally if in the root context meaning in this example you can
|
|
||||||
use the tag `rectangleSegmentA001` in any function or expression in the file.
|
|
||||||
|
|
||||||
However if the code was written like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
fn rect = (origin) => {
|
|
||||||
return startSketchOn('XZ')
|
|
||||||
|> startProfileAt(origin, %)
|
|
||||||
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001, %) - 90,
|
|
||||||
196.99
|
|
||||||
], %, $rectangleSegmentB001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001, %),
|
|
||||||
-segLen(rectangleSegmentA001, %)
|
|
||||||
], %, $rectangleSegmentC001)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
}
|
|
||||||
|
|
||||||
rect([0, 0])
|
|
||||||
rect([20, 0])
|
|
||||||
```
|
|
||||||
|
|
||||||
Those tags would only be available in the `rect` function and not globally.
|
|
||||||
|
|
||||||
However you likely want to use those tags somewhere outside the `rect` function.
|
|
||||||
|
|
||||||
Tags are accessible through the sketch group they are declared in.
|
|
||||||
For example the following code works.
|
|
||||||
|
|
||||||
```
|
|
||||||
fn rect = (origin) => {
|
|
||||||
return startSketchOn('XZ')
|
|
||||||
|> startProfileAt(origin, %)
|
|
||||||
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001, %) - 90,
|
|
||||||
196.99
|
|
||||||
], %, $rectangleSegmentB001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001, %),
|
|
||||||
-segLen(rectangleSegmentA001, %)
|
|
||||||
], %, $rectangleSegmentC001)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
}
|
|
||||||
|
|
||||||
rect([0, 0])
|
|
||||||
const myRect = rect([20, 0])
|
|
||||||
|
|
||||||
myRect
|
|
||||||
|> extrude(10, %)
|
|
||||||
|> fillet({radius: 0.5, tags: [myRect.tags.rectangleSegmentA001]}, %)
|
|
||||||
```
|
|
||||||
|
|
||||||
See how we use the tag `rectangleSegmentA001` in the `fillet` function outside
|
|
||||||
the `rect` function. This is because the `rect` function is returning the
|
|
||||||
sketch group that contains the tags.
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
If you find any issues using any of the above expressions or syntax,
|
|
||||||
please file an issue with the `ast` label on the [modeling-app
|
please file an issue with the `ast` label on the [modeling-app
|
||||||
repo](https://github.com/KittyCAD/modeling-app/issues/new).
|
repo](https://github.com/KittyCAD/modeling-app/issues/new).
|
||||||
|
@ -119,9 +119,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -283,9 +280,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -475,9 +469,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -639,9 +630,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -119,9 +119,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -283,9 +280,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -475,9 +469,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -639,9 +630,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -117,9 +117,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -281,9 +278,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -473,9 +467,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -637,9 +628,6 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -115,9 +115,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -279,9 +276,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -471,9 +465,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -635,9 +626,6 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
},
|
|
||||||
// Tag identifiers that have been declared in this sketch group.
|
|
||||||
tags: {
|
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -91,9 +91,8 @@ const part001 = startSketchOn('-XZ')
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||||
await u.waitForCmdReceive('extrude')
|
await u.waitForCmdReceive('extrude')
|
||||||
@ -331,7 +330,7 @@ const extrudeDefaultPlane = async (context: any, page: any, plane: string) => {
|
|||||||
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
// wait for execution done
|
// wait for execution done
|
||||||
@ -387,8 +386,8 @@ test('Draft segments should look right', async ({ page, context }) => {
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
@ -444,7 +443,7 @@ test('Draft rectangles should look right', async ({ page, context }) => {
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
|
|
||||||
@ -491,7 +490,7 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
|
|
||||||
@ -590,7 +589,7 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
|
|
||||||
@ -690,7 +689,7 @@ const part002 = startSketchOn(part001, 'seg01')
|
|||||||
}, KCL_DEFAULT_LENGTH)
|
}, KCL_DEFAULT_LENGTH)
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
@ -740,7 +739,7 @@ test('Zoom to fit on load - solid 2d', async ({ page, context }) => {
|
|||||||
}, KCL_DEFAULT_LENGTH)
|
}, KCL_DEFAULT_LENGTH)
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
@ -777,7 +776,7 @@ test('Zoom to fit on load - solid 3d', async ({ page, context }) => {
|
|||||||
}, KCL_DEFAULT_LENGTH)
|
}, KCL_DEFAULT_LENGTH)
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
@ -796,83 +795,3 @@ test('Zoom to fit on load - solid 3d', async ({ page, context }) => {
|
|||||||
maxDiffPixels: 100,
|
maxDiffPixels: 100,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test.describe('Grid visibility', () => {
|
|
||||||
test('Grid turned off', async ({ page }) => {
|
|
||||||
const u = await getUtils(page)
|
|
||||||
const stream = page.getByTestId('stream')
|
|
||||||
const mask = [
|
|
||||||
page.locator('#app-header'),
|
|
||||||
page.locator('#sidebar-top-ribbon'),
|
|
||||||
page.locator('#sidebar-bottom-ribbon'),
|
|
||||||
]
|
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
|
||||||
await page.goto('/')
|
|
||||||
await u.waitForAuthSkipAppStart()
|
|
||||||
|
|
||||||
await u.openDebugPanel()
|
|
||||||
// wait for execution done
|
|
||||||
await expect(
|
|
||||||
page.locator('[data-message-type="execution-done"]')
|
|
||||||
).toHaveCount(2)
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
await u.closeKclCodePanel()
|
|
||||||
// TODO: Find a way to truly know that the objects have finished
|
|
||||||
// rendering, because an execution-done message is not sufficient.
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
|
|
||||||
await expect(stream).toHaveScreenshot({
|
|
||||||
maxDiffPixels: 100,
|
|
||||||
mask,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Grid turned on', async ({ page }) => {
|
|
||||||
await page.addInitScript(
|
|
||||||
async ({ settingsKey, settings }) => {
|
|
||||||
localStorage.setItem(settingsKey, settings)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
settingsKey: TEST_SETTINGS_KEY,
|
|
||||||
settings: TOML.stringify({
|
|
||||||
settings: {
|
|
||||||
...TEST_SETTINGS,
|
|
||||||
modeling: {
|
|
||||||
...TEST_SETTINGS.modeling,
|
|
||||||
showScaleGrid: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const u = await getUtils(page)
|
|
||||||
const stream = page.getByTestId('stream')
|
|
||||||
const mask = [
|
|
||||||
page.locator('#app-header'),
|
|
||||||
page.locator('#sidebar-top-ribbon'),
|
|
||||||
page.locator('#sidebar-bottom-ribbon'),
|
|
||||||
]
|
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
|
||||||
await page.goto('/')
|
|
||||||
await u.waitForAuthSkipAppStart()
|
|
||||||
|
|
||||||
await u.openDebugPanel()
|
|
||||||
// wait for execution done
|
|
||||||
await expect(
|
|
||||||
page.locator('[data-message-type="execution-done"]')
|
|
||||||
).toHaveCount(2)
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
await u.closeKclCodePanel()
|
|
||||||
// TODO: Find a way to truly know that the objects have finished
|
|
||||||
// rendering, because an execution-done message is not sufficient.
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
|
|
||||||
await expect(stream).toHaveScreenshot({
|
|
||||||
maxDiffPixels: 100,
|
|
||||||
mask,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 27 KiB |
@ -45,8 +45,8 @@ async function clearCommandLogs(page: Page) {
|
|||||||
await page.getByTestId('clear-commands').click()
|
await page.getByTestId('clear-commands').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function expectCmdLog(page: Page, locatorStr: string, timeout = 5000) {
|
async function expectCmdLog(page: Page, locatorStr: string) {
|
||||||
await expect(page.locator(locatorStr).last()).toBeVisible({ timeout })
|
await expect(page.locator(locatorStr).last()).toBeVisible()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForDefaultPlanesToBeVisible(page: Page) {
|
async function waitForDefaultPlanesToBeVisible(page: Page) {
|
||||||
@ -207,23 +207,6 @@ export const getMovementUtils = (opts: any) => {
|
|||||||
return { toSU, click00r }
|
return { toSU, click00r }
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForAuthAndLsp(page: Page) {
|
|
||||||
const waitForLspPromise = page.waitForEvent('console', async (message) => {
|
|
||||||
// it would be better to wait for a message that the kcl lsp has started by looking for the message message.text().includes('[lsp] [window/logMessage]')
|
|
||||||
// but that doesn't seem to make it to the console for macos/safari :(
|
|
||||||
if (message.text().includes('start kcl lsp')) {
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
await page.goto('/')
|
|
||||||
await waitForPageLoad(page)
|
|
||||||
|
|
||||||
return waitForLspPromise
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getUtils(page: Page) {
|
export async function getUtils(page: Page) {
|
||||||
// Chrome devtools protocol session only works in Chromium
|
// Chrome devtools protocol session only works in Chromium
|
||||||
const browserType = page.context().browser()?.browserType().name()
|
const browserType = page.context().browser()?.browserType().name()
|
||||||
@ -231,8 +214,7 @@ export async function getUtils(page: Page) {
|
|||||||
browserType !== 'chromium' ? null : await page.context().newCDPSession(page)
|
browserType !== 'chromium' ? null : await page.context().newCDPSession(page)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
waitForAuthSkipAppStart: () => waitForAuthAndLsp(page),
|
waitForAuthSkipAppStart: () => waitForPageLoad(page),
|
||||||
waitForPageLoad: () => waitForPageLoad(page),
|
|
||||||
removeCurrentCode: () => removeCurrentCode(page),
|
removeCurrentCode: () => removeCurrentCode(page),
|
||||||
sendCustomCmd: (cmd: EngineCommand) => sendCustomCmd(page, cmd),
|
sendCustomCmd: (cmd: EngineCommand) => sendCustomCmd(page, cmd),
|
||||||
updateCamPosition: async (xyz: [number, number, number]) => {
|
updateCamPosition: async (xyz: [number, number, number]) => {
|
||||||
@ -246,8 +228,7 @@ export async function getUtils(page: Page) {
|
|||||||
await fillInput('z', xyz[2])
|
await fillInput('z', xyz[2])
|
||||||
},
|
},
|
||||||
clearCommandLogs: () => clearCommandLogs(page),
|
clearCommandLogs: () => clearCommandLogs(page),
|
||||||
expectCmdLog: (locatorStr: string, timeout = 5000) =>
|
expectCmdLog: (locatorStr: string) => expectCmdLog(page, locatorStr),
|
||||||
expectCmdLog(page, locatorStr, timeout),
|
|
||||||
openKclCodePanel: () => openKclCodePanel(page),
|
openKclCodePanel: () => openKclCodePanel(page),
|
||||||
closeKclCodePanel: () => closeKclCodePanel(page),
|
closeKclCodePanel: () => closeKclCodePanel(page),
|
||||||
openDebugPanel: () => openDebugPanel(page),
|
openDebugPanel: () => openDebugPanel(page),
|
||||||
@ -319,19 +300,11 @@ export async function getUtils(page: Page) {
|
|||||||
(screenshot.width * coords.y * pixMultiplier +
|
(screenshot.width * coords.y * pixMultiplier +
|
||||||
coords.x * pixMultiplier) *
|
coords.x * pixMultiplier) *
|
||||||
4 // rbga is 4 channels
|
4 // rbga is 4 channels
|
||||||
const maxDiff = Math.max(
|
return Math.max(
|
||||||
Math.abs(screenshot.data[index] - expected[0]),
|
Math.abs(screenshot.data[index] - expected[0]),
|
||||||
Math.abs(screenshot.data[index + 1] - expected[1]),
|
Math.abs(screenshot.data[index + 1] - expected[1]),
|
||||||
Math.abs(screenshot.data[index + 2] - expected[2])
|
Math.abs(screenshot.data[index + 2] - expected[2])
|
||||||
)
|
)
|
||||||
if (maxDiff > 4) {
|
|
||||||
console.log(
|
|
||||||
`Expected: ${expected} Actual: [${screenshot.data[index]}, ${
|
|
||||||
screenshot.data[index + 1]
|
|
||||||
}, ${screenshot.data[index + 2]}]`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return maxDiff
|
|
||||||
},
|
},
|
||||||
doAndWaitForImageDiff: (fn: () => Promise<any>, diffCount = 200) =>
|
doAndWaitForImageDiff: (fn: () => Promise<any>, diffCount = 200) =>
|
||||||
new Promise(async (resolve) => {
|
new Promise(async (resolve) => {
|
||||||
|
3
examples/addition.cado
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// comment
|
||||||
|
|
||||||
|
const hi = 5 + 4
|
87
package.json
@ -1,43 +1,49 @@
|
|||||||
{
|
{
|
||||||
"name": "untitled-app",
|
"name": "untitled-app",
|
||||||
"version": "0.23.1",
|
"version": "0.22.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.17.0",
|
"@codemirror/autocomplete": "^6.16.0",
|
||||||
"@codemirror/commands": "^6.6.0",
|
|
||||||
"@codemirror/language": "^6.10.2",
|
|
||||||
"@codemirror/lint": "^6.8.1",
|
|
||||||
"@codemirror/search": "^6.5.6",
|
|
||||||
"@codemirror/state": "^6.4.1",
|
|
||||||
"@codemirror/theme-one-dark": "^6.1.2",
|
|
||||||
"@csstools/postcss-oklab-function": "^3.0.16",
|
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
||||||
"@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.0",
|
"@headlessui/tailwindcss": "^0.2.0",
|
||||||
"@kittycad/lib": "^0.0.69",
|
"@kittycad/lib": "^0.0.67",
|
||||||
|
"@lezer/javascript": "^1.4.9",
|
||||||
"@react-hook/resize-observer": "^2.0.1",
|
"@react-hook/resize-observer": "^2.0.1",
|
||||||
"@replit/codemirror-interact": "^6.3.1",
|
"@replit/codemirror-interact": "^6.3.1",
|
||||||
"@tauri-apps/api": "^2.0.0-beta.14",
|
"@tauri-apps/api": "2.0.0-beta.12",
|
||||||
"@tauri-apps/plugin-dialog": "^2.0.0-beta.6",
|
"@tauri-apps/plugin-dialog": "^2.0.0-beta.2",
|
||||||
"@tauri-apps/plugin-fs": "^2.0.0-beta.6",
|
"@tauri-apps/plugin-fs": "^2.0.0-beta.3",
|
||||||
"@tauri-apps/plugin-http": "^2.0.0-beta.7",
|
"@tauri-apps/plugin-http": "^2.0.0-beta.2",
|
||||||
"@tauri-apps/plugin-os": "^2.0.0-beta.6",
|
"@tauri-apps/plugin-os": "^2.0.0-beta.3",
|
||||||
"@tauri-apps/plugin-process": "^2.0.0-beta.6",
|
"@tauri-apps/plugin-process": "^2.0.0-beta.2",
|
||||||
"@tauri-apps/plugin-shell": "^2.0.0-beta.7",
|
"@tauri-apps/plugin-shell": "^2.0.0-beta.2",
|
||||||
"@tauri-apps/plugin-updater": "^2.0.0-beta.6",
|
"@tauri-apps/plugin-updater": "^2.0.0-beta.3",
|
||||||
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
|
"@testing-library/react": "^15.0.2",
|
||||||
|
"@testing-library/user-event": "^14.5.2",
|
||||||
"@ts-stack/markdown": "^1.5.0",
|
"@ts-stack/markdown": "^1.5.0",
|
||||||
"@tweenjs/tween.js": "^23.1.1",
|
"@tweenjs/tween.js": "^23.1.1",
|
||||||
|
"@types/node": "^18.19.31",
|
||||||
|
"@types/react": "^18.3.2",
|
||||||
|
"@types/react-dom": "^18.2.25",
|
||||||
|
"@uiw/react-codemirror": "^4.21.25",
|
||||||
"@xstate/inspect": "^0.8.0",
|
"@xstate/inspect": "^0.8.0",
|
||||||
"@xstate/react": "^3.2.2",
|
"@xstate/react": "^3.2.2",
|
||||||
"codemirror": "^6.0.1",
|
"crypto-js": "^4.2.0",
|
||||||
|
"debounce-promise": "^3.1.2",
|
||||||
"decamelize": "^6.0.0",
|
"decamelize": "^6.0.0",
|
||||||
|
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
||||||
|
"formik": "^2.4.6",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"html2canvas-pro": "^1.5.2",
|
"html2canvas-pro": "^1.4.3",
|
||||||
"json-rpc-2.0": "^1.6.0",
|
"http-server": "^14.1.1",
|
||||||
|
"json-rpc-2.0": "^1.7.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
"re-resizable": "^6.9.11",
|
"re-resizable": "^6.9.11",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
@ -48,15 +54,21 @@
|
|||||||
"react-modal-promise": "^1.0.2",
|
"react-modal-promise": "^1.0.2",
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"sketch-helpers": "^0.0.4",
|
"sketch-helpers": "^0.0.4",
|
||||||
"three": "^0.166.1",
|
"swr": "^2.2.5",
|
||||||
|
"three": "^0.164.1",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"ua-parser-js": "^1.0.37",
|
"ua-parser-js": "^1.0.37",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"vscode-jsonrpc": "^8.2.1",
|
"vitest": "^1.6.0",
|
||||||
|
"vscode-languageclient": "^9.0.1",
|
||||||
|
"vscode-languageserver": "^9.0.1",
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.0.8",
|
"wasm-pack": "^0.12.1",
|
||||||
"web-vitals": "^3.5.2",
|
"web-vitals": "^3.5.2",
|
||||||
"xstate": "^4.38.2"
|
"ws": "^8.17.0",
|
||||||
|
"xstate": "^4.38.2",
|
||||||
|
"zustand": "^4.5.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
@ -73,11 +85,11 @@
|
|||||||
"test:e2e:tauri": "E2E_TAURI_ENABLED=true TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\"}' wdio run wdio.conf.ts",
|
"test:e2e:tauri": "E2E_TAURI_ENABLED=true TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\"}' wdio run wdio.conf.ts",
|
||||||
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
|
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
|
||||||
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",
|
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",
|
||||||
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages",
|
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e",
|
||||||
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages",
|
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e",
|
||||||
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
||||||
"build:wasm-dev": "(cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
|
"build:wasm-dev": "(cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
|
||||||
"build:wasm": "(cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
|
"build:wasm": "(cd src/wasm-lib && wasm-pack build --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt",
|
||||||
"build:wasm-clean": "yarn wasm-prep && yarn build:wasm",
|
"build:wasm-clean": "yarn wasm-prep && yarn build:wasm",
|
||||||
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
||||||
"wasm-prep": "rm -rf src/wasm-lib/pkg && mkdir src/wasm-lib/pkg && rm -rf src/wasm-lib/kcl/bindings",
|
"wasm-prep": "rm -rf src/wasm-lib/pkg && mkdir src/wasm-lib/pkg && rm -rf src/wasm-lib/kcl/bindings",
|
||||||
@ -109,16 +121,13 @@
|
|||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-env": "^7.24.3",
|
"@babel/preset-env": "^7.24.3",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@playwright/test": "^1.45.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@tauri-apps/cli": "==2.0.0-beta.13",
|
"@tauri-apps/cli": "^2.0.0-beta.13",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@testing-library/react": "^15.0.2",
|
"@types/debounce-promise": "^3.1.9",
|
||||||
"@types/mocha": "^10.0.6",
|
"@types/mocha": "^10.0.6",
|
||||||
"@types/node": "^18.19.31",
|
|
||||||
"@types/pixelmatch": "^5.2.6",
|
"@types/pixelmatch": "^5.2.6",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
"@types/react": "^18.3.2",
|
|
||||||
"@types/react-dom": "^18.2.25",
|
|
||||||
"@types/react-modal": "^3.16.3",
|
"@types/react-modal": "^3.16.3",
|
||||||
"@types/three": "^0.163.0",
|
"@types/three": "^0.163.0",
|
||||||
"@types/ua-parser-js": "^0.7.39",
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
@ -138,27 +147,21 @@
|
|||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"eslint-plugin-css-modules": "^2.12.0",
|
"eslint-plugin-css-modules": "^2.12.0",
|
||||||
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
|
||||||
"happy-dom": "^14.3.10",
|
"happy-dom": "^14.3.10",
|
||||||
"http-server": "^14.1.1",
|
|
||||||
"husky": "^9.0.11",
|
"husky": "^9.0.11",
|
||||||
"node-fetch": "^3.3.2",
|
|
||||||
"pixelmatch": "^5.3.0",
|
"pixelmatch": "^5.3.0",
|
||||||
"pngjs": "^7.0.0",
|
"pngjs": "^7.0.0",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
"postinstall-postinstall": "^2.1.0",
|
"postinstall-postinstall": "^2.1.0",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.0",
|
||||||
"setimmediate": "^1.0.5",
|
"setimmediate": "^1.0.5",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"vite": "^5.2.9",
|
"vite": "^5.2.9",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vite-plugin-package-version": "^1.1.0",
|
"vite-plugin-package-version": "^1.1.0",
|
||||||
"vite-tsconfig-paths": "^4.3.2",
|
"vite-tsconfig-paths": "^4.3.2",
|
||||||
"vitest": "^1.6.0",
|
|
||||||
"vitest-webgl-canvas-mock": "^1.1.0",
|
"vitest-webgl-canvas-mock": "^1.1.0",
|
||||||
"wait-on": "^7.2.0",
|
"wait-on": "^7.2.0",
|
||||||
"wasm-pack": "^0.13.0",
|
|
||||||
"ws": "^8.17.0",
|
|
||||||
"yarn": "^1.22.22"
|
"yarn": "^1.22.22"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
packages/codemirror-lsp-client/.gitignore
vendored
@ -1,6 +0,0 @@
|
|||||||
node_modules
|
|
||||||
build
|
|
||||||
dist
|
|
||||||
tsconfig.tsbuildinfo
|
|
||||||
*.d.ts
|
|
||||||
*.js
|
|
@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@kittycad/codemirror-lsp-client",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "An LSP client for the codemirror editor.",
|
|
||||||
"main": "src/index.ts",
|
|
||||||
"exports": {
|
|
||||||
"import": "./dist/index.js",
|
|
||||||
"require": "./dist/index.js"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc"
|
|
||||||
},
|
|
||||||
"types": "dist/index.d.ts",
|
|
||||||
"module": "dist/index.js",
|
|
||||||
"type": "module",
|
|
||||||
"repository": "https://github.com/KittyCAD/modeling-app",
|
|
||||||
"author": "Zoo Engineering Team",
|
|
||||||
"license": "MIT",
|
|
||||||
"private": false,
|
|
||||||
"dependencies": {
|
|
||||||
"@codemirror/autocomplete": "^6.16.3",
|
|
||||||
"@codemirror/language": "^6.10.2",
|
|
||||||
"@codemirror/state": "^6.4.1",
|
|
||||||
"@lezer/highlight": "^1.2.0",
|
|
||||||
"@ts-stack/markdown": "^1.5.0",
|
|
||||||
"json-rpc-2.0": "^1.7.0",
|
|
||||||
"typescript": "^5.5.2",
|
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
|
||||||
"vscode-uri": "^3.0.8"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^20.14.9",
|
|
||||||
"ts-node": "^10.9.2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
import { encoder, decoder } from '../codec'
|
|
||||||
|
|
||||||
export default class Bytes {
|
|
||||||
static encode(input: string): Uint8Array {
|
|
||||||
return encoder.encode(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
static decode(input: Uint8Array): string {
|
|
||||||
return decoder.decode(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
static append<
|
|
||||||
T extends { length: number; set(arr: T, offset: number): void }
|
|
||||||
>(constructor: { new (length: number): T }, ...arrays: T[]) {
|
|
||||||
let totalLength = 0
|
|
||||||
for (const arr of arrays) {
|
|
||||||
totalLength += arr.length
|
|
||||||
}
|
|
||||||
const result = new constructor(totalLength)
|
|
||||||
let offset = 0
|
|
||||||
for (const arr of arrays) {
|
|
||||||
result.set(arr, offset)
|
|
||||||
offset += arr.length
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
import * as vsrpc from 'vscode-jsonrpc'
|
|
||||||
|
|
||||||
import { Codec } from '.'
|
|
||||||
import Bytes from './bytes'
|
|
||||||
import Queue from './queue'
|
|
||||||
import Tracer from './tracer'
|
|
||||||
import PromiseMap from './map'
|
|
||||||
|
|
||||||
export default class StreamDemuxer extends Queue<Uint8Array> {
|
|
||||||
readonly responses: PromiseMap<number | string, vsrpc.ResponseMessage> =
|
|
||||||
new PromiseMap()
|
|
||||||
readonly notifications: Queue<vsrpc.NotificationMessage> =
|
|
||||||
new Queue<vsrpc.NotificationMessage>()
|
|
||||||
readonly requests: Queue<vsrpc.RequestMessage> =
|
|
||||||
new Queue<vsrpc.RequestMessage>()
|
|
||||||
|
|
||||||
readonly #start: Promise<void>
|
|
||||||
private trace: boolean = false
|
|
||||||
|
|
||||||
constructor(trace?: boolean) {
|
|
||||||
super()
|
|
||||||
this.trace = trace || false
|
|
||||||
|
|
||||||
this.#start = this.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
private async start(): Promise<void> {
|
|
||||||
let contentLength: null | number = null
|
|
||||||
let buffer = new Uint8Array()
|
|
||||||
|
|
||||||
for await (const bytes of this) {
|
|
||||||
buffer = Bytes.append(Uint8Array, buffer, bytes)
|
|
||||||
while (buffer.length > 0) {
|
|
||||||
// check if the content length is known
|
|
||||||
if (null == contentLength) {
|
|
||||||
// if not, try to match the prefixed headers
|
|
||||||
const match = Bytes.decode(buffer).match(
|
|
||||||
/^Content-Length:\s*(\d+)\s*/
|
|
||||||
)
|
|
||||||
if (null == match) continue
|
|
||||||
|
|
||||||
// try to parse the content-length from the headers
|
|
||||||
const length = parseInt(match[1])
|
|
||||||
|
|
||||||
if (isNaN(length))
|
|
||||||
return Promise.reject(new Error('invalid content length'))
|
|
||||||
|
|
||||||
// slice the headers since we now have the content length
|
|
||||||
buffer = buffer.slice(match[0].length)
|
|
||||||
|
|
||||||
// set the content length
|
|
||||||
contentLength = length
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the buffer doesn't contain a full message; await another iteration
|
|
||||||
if (buffer.length < contentLength) continue
|
|
||||||
|
|
||||||
// Get just the slice of the buffer that is our content length.
|
|
||||||
const slice = buffer.slice(0, contentLength)
|
|
||||||
|
|
||||||
// decode buffer to a string
|
|
||||||
const delimited = Bytes.decode(slice)
|
|
||||||
|
|
||||||
// reset the buffer
|
|
||||||
buffer = buffer.slice(contentLength)
|
|
||||||
// reset the contentLength
|
|
||||||
contentLength = null
|
|
||||||
|
|
||||||
const message = JSON.parse(delimited) as vsrpc.Message
|
|
||||||
|
|
||||||
if (this.trace) {
|
|
||||||
Tracer.server(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// demux the message stream
|
|
||||||
if (vsrpc.Message.isResponse(message) && null != message.id) {
|
|
||||||
this.responses.set(message.id, message)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (vsrpc.Message.isNotification(message)) {
|
|
||||||
this.notifications.enqueue(message)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (vsrpc.Message.isRequest(message)) {
|
|
||||||
this.requests.enqueue(message)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add(bytes: Uint8Array): void {
|
|
||||||
const message = Codec.decode(bytes) as vsrpc.Message
|
|
||||||
if (this.trace) {
|
|
||||||
Tracer.server(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// demux the message stream
|
|
||||||
if (vsrpc.Message.isResponse(message) && null != message.id) {
|
|
||||||
this.responses.set(message.id, message)
|
|
||||||
}
|
|
||||||
if (vsrpc.Message.isNotification(message)) {
|
|
||||||
this.notifications.enqueue(message)
|
|
||||||
}
|
|
||||||
if (vsrpc.Message.isRequest(message)) {
|
|
||||||
this.requests.enqueue(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
export default class Headers {
|
|
||||||
static add(message: string): string {
|
|
||||||
return `Content-Length: ${message.length}\r\n\r\n${message}`
|
|
||||||
}
|
|
||||||
|
|
||||||
static remove(delimited: string): string {
|
|
||||||
return delimited.replace(/^Content-Length:\s*\d+\s*/, '')
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
import * as jsrpc from 'json-rpc-2.0'
|
|
||||||
import * as vsrpc from 'vscode-jsonrpc'
|
|
||||||
|
|
||||||
import Bytes from './bytes'
|
|
||||||
import StreamDemuxer from './demuxer'
|
|
||||||
import Headers from './headers'
|
|
||||||
import Queue from './queue'
|
|
||||||
import Tracer from './tracer'
|
|
||||||
|
|
||||||
export enum LspWorkerEventType {
|
|
||||||
Init = 'init',
|
|
||||||
Call = 'call',
|
|
||||||
}
|
|
||||||
|
|
||||||
export const encoder = new TextEncoder()
|
|
||||||
export const decoder = new TextDecoder()
|
|
||||||
|
|
||||||
export class Codec {
|
|
||||||
static encode(
|
|
||||||
json: jsrpc.JSONRPCRequest | jsrpc.JSONRPCResponse
|
|
||||||
): Uint8Array {
|
|
||||||
const message = JSON.stringify(json)
|
|
||||||
const delimited = Headers.add(message)
|
|
||||||
return Bytes.encode(delimited)
|
|
||||||
}
|
|
||||||
|
|
||||||
static decode<T>(data: Uint8Array): T {
|
|
||||||
const delimited = Bytes.decode(data)
|
|
||||||
const message = Headers.remove(delimited)
|
|
||||||
return JSON.parse(message) as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: tracing efficiency
|
|
||||||
export class IntoServer
|
|
||||||
extends Queue<Uint8Array>
|
|
||||||
implements AsyncGenerator<Uint8Array, never, void>
|
|
||||||
{
|
|
||||||
private worker: Worker | null = null
|
|
||||||
private type_: String | null = null
|
|
||||||
|
|
||||||
private trace: boolean = false
|
|
||||||
|
|
||||||
constructor(type_?: String, worker?: Worker, trace?: boolean) {
|
|
||||||
super()
|
|
||||||
if (worker && type_) {
|
|
||||||
this.worker = worker
|
|
||||||
this.type_ = type_
|
|
||||||
}
|
|
||||||
|
|
||||||
this.trace = trace || false
|
|
||||||
}
|
|
||||||
enqueue(item: Uint8Array): void {
|
|
||||||
if (this.trace) {
|
|
||||||
Tracer.client(Headers.remove(decoder.decode(item)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.worker) {
|
|
||||||
this.worker.postMessage({
|
|
||||||
worker: this.type_,
|
|
||||||
eventType: LspWorkerEventType.Call,
|
|
||||||
eventData: item,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
super.enqueue(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FromServer extends WritableStream<Uint8Array> {
|
|
||||||
readonly responses: {
|
|
||||||
get(key: number | string): null | Promise<vsrpc.ResponseMessage>
|
|
||||||
}
|
|
||||||
readonly notifications: AsyncGenerator<vsrpc.NotificationMessage, never, void>
|
|
||||||
readonly requests: AsyncGenerator<vsrpc.RequestMessage, never, void>
|
|
||||||
|
|
||||||
add(item: Uint8Array): void
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
||||||
export namespace FromServer {
|
|
||||||
export function create(): FromServer | Error {
|
|
||||||
// Calls private method .start() which can throw.
|
|
||||||
// This is an odd one of the bunch but try/catch seems most suitable here.
|
|
||||||
try {
|
|
||||||
return new StreamDemuxer(false)
|
|
||||||
} catch (e: any) {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
export default class PromiseMap<K, V extends { toString(): string }> {
|
|
||||||
#map: Map<K, PromiseMap.Entry<V>> = new Map()
|
|
||||||
|
|
||||||
get(key: K & { toString(): string }): null | Promise<V> {
|
|
||||||
let initialized: PromiseMap.Entry<V>
|
|
||||||
// if the entry doesn't exist, set it
|
|
||||||
if (!this.#map.has(key)) {
|
|
||||||
initialized = this.#set(key)
|
|
||||||
} else {
|
|
||||||
// otherwise return the entry
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
initialized = this.#map.get(key)!
|
|
||||||
}
|
|
||||||
// if the entry is a pending promise, return it
|
|
||||||
if (initialized.status === 'pending') {
|
|
||||||
return initialized.promise
|
|
||||||
} else {
|
|
||||||
// otherwise return null
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#set(key: K, value?: V): PromiseMap.Entry<V> {
|
|
||||||
if (this.#map.has(key)) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
return this.#map.get(key)!
|
|
||||||
}
|
|
||||||
// placeholder resolver for entry
|
|
||||||
let resolve = (item: V) => {
|
|
||||||
void item
|
|
||||||
}
|
|
||||||
// promise for entry (which assigns the resolver
|
|
||||||
const promise = new Promise<V>((resolver) => {
|
|
||||||
resolve = resolver
|
|
||||||
})
|
|
||||||
// the initialized entry
|
|
||||||
const initialized: PromiseMap.Entry<V> = {
|
|
||||||
status: 'pending',
|
|
||||||
resolve,
|
|
||||||
promise,
|
|
||||||
}
|
|
||||||
if (null != value) {
|
|
||||||
initialized.resolve(value)
|
|
||||||
}
|
|
||||||
// set the entry
|
|
||||||
this.#map.set(key, initialized)
|
|
||||||
return initialized
|
|
||||||
}
|
|
||||||
|
|
||||||
set(key: K & { toString(): string }, value: V): this {
|
|
||||||
const initialized = this.#set(key, value)
|
|
||||||
// if the promise is pending ...
|
|
||||||
if (initialized.status === 'pending') {
|
|
||||||
// ... set the entry status to resolved to free the promise
|
|
||||||
this.#map.set(key, { status: 'resolved' })
|
|
||||||
// ... and resolve the promise with the given value
|
|
||||||
initialized.resolve(value)
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
get size(): number {
|
|
||||||
return this.#map.size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
||||||
export namespace PromiseMap {
|
|
||||||
export type Entry<V> =
|
|
||||||
| { status: 'pending'; resolve: (item: V) => void; promise: Promise<V> }
|
|
||||||
| { status: 'resolved' }
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { Message } from 'vscode-languageserver-protocol'
|
|
||||||
|
|
||||||
export default class Tracer {
|
|
||||||
static client(message: string): void {
|
|
||||||
console.log('lsp client message', message)
|
|
||||||
}
|
|
||||||
|
|
||||||
static server(input: string | Message): void {
|
|
||||||
const message: string =
|
|
||||||
typeof input === 'string' ? input : JSON.stringify(input)
|
|
||||||
console.log('lsp server message', message)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,200 +0,0 @@
|
|||||||
import type * as LSP from 'vscode-languageserver-protocol'
|
|
||||||
|
|
||||||
import { FromServer, IntoServer } from './codec'
|
|
||||||
import Client from './jsonrpc'
|
|
||||||
import { LanguageServerPlugin } from '../plugin/lsp'
|
|
||||||
|
|
||||||
// https://microsoft.github.io/language-server-protocol/specifications/specification-current/
|
|
||||||
|
|
||||||
// Client to server then server to client
|
|
||||||
interface LSPRequestMap {
|
|
||||||
initialize: [LSP.InitializeParams, LSP.InitializeResult]
|
|
||||||
'textDocument/hover': [LSP.HoverParams, LSP.Hover]
|
|
||||||
'textDocument/completion': [
|
|
||||||
LSP.CompletionParams,
|
|
||||||
LSP.CompletionItem[] | LSP.CompletionList | null
|
|
||||||
]
|
|
||||||
'textDocument/semanticTokens/full': [
|
|
||||||
LSP.SemanticTokensParams,
|
|
||||||
LSP.SemanticTokens
|
|
||||||
]
|
|
||||||
'textDocument/formatting': [
|
|
||||||
LSP.DocumentFormattingParams,
|
|
||||||
LSP.TextEdit[] | null
|
|
||||||
]
|
|
||||||
'textDocument/foldingRange': [LSP.FoldingRangeParams, LSP.FoldingRange[]]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client to server
|
|
||||||
interface LSPNotifyMap {
|
|
||||||
initialized: LSP.InitializedParams
|
|
||||||
'textDocument/didChange': LSP.DidChangeTextDocumentParams
|
|
||||||
'textDocument/didOpen': LSP.DidOpenTextDocumentParams
|
|
||||||
'textDocument/didClose': LSP.DidCloseTextDocumentParams
|
|
||||||
'workspace/didChangeWorkspaceFolders': LSP.DidChangeWorkspaceFoldersParams
|
|
||||||
'workspace/didCreateFiles': LSP.CreateFilesParams
|
|
||||||
'workspace/didRenameFiles': LSP.RenameFilesParams
|
|
||||||
'workspace/didDeleteFiles': LSP.DeleteFilesParams
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LanguageServerClientOptions {
|
|
||||||
name: string
|
|
||||||
fromServer: FromServer
|
|
||||||
intoServer: IntoServer
|
|
||||||
initializedCallback: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LanguageServerClient {
|
|
||||||
private client: Client
|
|
||||||
readonly name: string
|
|
||||||
|
|
||||||
public ready: boolean
|
|
||||||
|
|
||||||
readonly plugins: LanguageServerPlugin[]
|
|
||||||
|
|
||||||
public initializePromise: Promise<void>
|
|
||||||
|
|
||||||
constructor(options: LanguageServerClientOptions) {
|
|
||||||
this.name = options.name
|
|
||||||
this.plugins = []
|
|
||||||
|
|
||||||
this.client = new Client(
|
|
||||||
options.fromServer,
|
|
||||||
options.intoServer,
|
|
||||||
options.initializedCallback
|
|
||||||
)
|
|
||||||
|
|
||||||
this.ready = false
|
|
||||||
|
|
||||||
this.initializePromise = this.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
async initialize() {
|
|
||||||
// Start the client in the background.
|
|
||||||
this.client.setNotifyFn(this.processNotifications.bind(this))
|
|
||||||
this.client.start()
|
|
||||||
|
|
||||||
this.ready = true
|
|
||||||
}
|
|
||||||
|
|
||||||
getName(): string {
|
|
||||||
return this.name
|
|
||||||
}
|
|
||||||
|
|
||||||
getServerCapabilities(): LSP.ServerCapabilities<any> {
|
|
||||||
return this.client.getServerCapabilities()
|
|
||||||
}
|
|
||||||
|
|
||||||
close() {}
|
|
||||||
|
|
||||||
textDocumentDidOpen(params: LSP.DidOpenTextDocumentParams) {
|
|
||||||
this.notify('textDocument/didOpen', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
textDocumentDidChange(params: LSP.DidChangeTextDocumentParams) {
|
|
||||||
this.notify('textDocument/didChange', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
textDocumentDidClose(params: LSP.DidCloseTextDocumentParams) {
|
|
||||||
this.notify('textDocument/didClose', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceDidChangeWorkspaceFolders(
|
|
||||||
added: LSP.WorkspaceFolder[],
|
|
||||||
removed: LSP.WorkspaceFolder[]
|
|
||||||
) {
|
|
||||||
this.notify('workspace/didChangeWorkspaceFolders', {
|
|
||||||
event: { added, removed },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceDidCreateFiles(params: LSP.CreateFilesParams) {
|
|
||||||
this.notify('workspace/didCreateFiles', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceDidRenameFiles(params: LSP.RenameFilesParams) {
|
|
||||||
this.notify('workspace/didRenameFiles', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceDidDeleteFiles(params: LSP.DeleteFilesParams) {
|
|
||||||
this.notify('workspace/didDeleteFiles', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
async textDocumentSemanticTokensFull(params: LSP.SemanticTokensParams) {
|
|
||||||
const serverCapabilities = this.getServerCapabilities()
|
|
||||||
if (!serverCapabilities.semanticTokensProvider) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request('textDocument/semanticTokens/full', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
async textDocumentHover(params: LSP.HoverParams) {
|
|
||||||
const serverCapabilities = this.getServerCapabilities()
|
|
||||||
if (!serverCapabilities.hoverProvider) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return await this.request('textDocument/hover', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
async textDocumentFormatting(params: LSP.DocumentFormattingParams) {
|
|
||||||
const serverCapabilities = this.getServerCapabilities()
|
|
||||||
if (!serverCapabilities.documentFormattingProvider) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return await this.request('textDocument/formatting', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
async textDocumentFoldingRange(params: LSP.FoldingRangeParams) {
|
|
||||||
const serverCapabilities = this.getServerCapabilities()
|
|
||||||
if (!serverCapabilities.foldingRangeProvider) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return await this.request('textDocument/foldingRange', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
async textDocumentCompletion(params: LSP.CompletionParams) {
|
|
||||||
const serverCapabilities = this.getServerCapabilities()
|
|
||||||
if (!serverCapabilities.completionProvider) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const response = await this.request('textDocument/completion', params)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
attachPlugin(plugin: LanguageServerPlugin) {
|
|
||||||
this.plugins.push(plugin)
|
|
||||||
}
|
|
||||||
|
|
||||||
detachPlugin(plugin: LanguageServerPlugin) {
|
|
||||||
const i = this.plugins.indexOf(plugin)
|
|
||||||
if (i === -1) return
|
|
||||||
this.plugins.splice(i, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
private request<K extends keyof LSPRequestMap>(
|
|
||||||
method: K,
|
|
||||||
params: LSPRequestMap[K][0]
|
|
||||||
): Promise<LSPRequestMap[K][1]> {
|
|
||||||
return this.client.request(method, params) as Promise<LSPRequestMap[K][1]>
|
|
||||||
}
|
|
||||||
|
|
||||||
requestCustom<P, R>(method: string, params: P): Promise<R> {
|
|
||||||
return this.client.request(method, params) as Promise<R>
|
|
||||||
}
|
|
||||||
|
|
||||||
private notify<K extends keyof LSPNotifyMap>(
|
|
||||||
method: K,
|
|
||||||
params: LSPNotifyMap[K]
|
|
||||||
): void {
|
|
||||||
return this.client.notify(method, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyCustom<P>(method: string, params: P): void {
|
|
||||||
return this.client.notify(method, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
private processNotifications(notification: LSP.NotificationMessage) {
|
|
||||||
for (const plugin of this.plugins) plugin.processNotification(notification)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,208 +0,0 @@
|
|||||||
import * as jsrpc from 'json-rpc-2.0'
|
|
||||||
import * as LSP from 'vscode-languageserver-protocol'
|
|
||||||
|
|
||||||
import {
|
|
||||||
registerServerCapability,
|
|
||||||
unregisterServerCapability,
|
|
||||||
} from './server-capability-registration'
|
|
||||||
import { Codec, FromServer, IntoServer } from './codec'
|
|
||||||
|
|
||||||
const client_capabilities: LSP.ClientCapabilities = {
|
|
||||||
textDocument: {
|
|
||||||
hover: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
contentFormat: ['plaintext', 'markdown'],
|
|
||||||
},
|
|
||||||
moniker: {},
|
|
||||||
synchronization: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
willSave: false,
|
|
||||||
didSave: false,
|
|
||||||
willSaveWaitUntil: false,
|
|
||||||
},
|
|
||||||
completion: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
completionItem: {
|
|
||||||
snippetSupport: false,
|
|
||||||
commitCharactersSupport: true,
|
|
||||||
documentationFormat: ['plaintext', 'markdown'],
|
|
||||||
deprecatedSupport: false,
|
|
||||||
preselectSupport: false,
|
|
||||||
},
|
|
||||||
contextSupport: false,
|
|
||||||
},
|
|
||||||
signatureHelp: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
signatureInformation: {
|
|
||||||
documentationFormat: ['plaintext', 'markdown'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
declaration: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
linkSupport: true,
|
|
||||||
},
|
|
||||||
definition: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
linkSupport: true,
|
|
||||||
},
|
|
||||||
typeDefinition: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
linkSupport: true,
|
|
||||||
},
|
|
||||||
implementation: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
linkSupport: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
workspace: {
|
|
||||||
didChangeConfiguration: {
|
|
||||||
dynamicRegistration: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Client extends jsrpc.JSONRPCServerAndClient {
|
|
||||||
afterInitializedHooks: (() => Promise<void>)[] = []
|
|
||||||
#fromServer: FromServer
|
|
||||||
private serverCapabilities: LSP.ServerCapabilities<any> = {}
|
|
||||||
private notifyFn: ((message: LSP.NotificationMessage) => void) | null = null
|
|
||||||
private initializedCallback: () => void
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
fromServer: FromServer,
|
|
||||||
intoServer: IntoServer,
|
|
||||||
initializedCallback: () => void
|
|
||||||
) {
|
|
||||||
super(
|
|
||||||
new jsrpc.JSONRPCServer(),
|
|
||||||
new jsrpc.JSONRPCClient(async (json: jsrpc.JSONRPCRequest) => {
|
|
||||||
const encoded = Codec.encode(json)
|
|
||||||
intoServer.enqueue(encoded)
|
|
||||||
if (null != json.id) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
const response = await fromServer.responses.get(json.id)
|
|
||||||
this.client.receive(response as jsrpc.JSONRPCResponse)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
this.#fromServer = fromServer
|
|
||||||
this.initializedCallback = initializedCallback
|
|
||||||
}
|
|
||||||
|
|
||||||
async start(): Promise<void> {
|
|
||||||
// process "window/logMessage": client <- server
|
|
||||||
this.addMethod(LSP.LogMessageNotification.type.method, (params) => {
|
|
||||||
const { type, message } = params as {
|
|
||||||
type: LSP.MessageType
|
|
||||||
message: string
|
|
||||||
}
|
|
||||||
let messageString = ''
|
|
||||||
switch (type) {
|
|
||||||
case LSP.MessageType.Error: {
|
|
||||||
messageString += '[error] '
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case LSP.MessageType.Warning: {
|
|
||||||
messageString += ' [warn] '
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case LSP.MessageType.Info: {
|
|
||||||
messageString += ' [info] '
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case LSP.MessageType.Log: {
|
|
||||||
messageString += ' [log] '
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
messageString += message
|
|
||||||
return
|
|
||||||
})
|
|
||||||
|
|
||||||
// process "client/registerCapability": client <- server
|
|
||||||
this.addMethod(LSP.RegistrationRequest.type.method, (params) => {
|
|
||||||
// Register a server capability.
|
|
||||||
params.registrations.forEach(
|
|
||||||
(capabilityRegistration: LSP.Registration) => {
|
|
||||||
const caps = registerServerCapability(
|
|
||||||
this.serverCapabilities,
|
|
||||||
capabilityRegistration
|
|
||||||
)
|
|
||||||
if (caps instanceof Error) {
|
|
||||||
return (this.serverCapabilities = {})
|
|
||||||
}
|
|
||||||
this.serverCapabilities = caps
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// process "client/unregisterCapability": client <- server
|
|
||||||
this.addMethod(LSP.UnregistrationRequest.type.method, (params) => {
|
|
||||||
// Unregister a server capability.
|
|
||||||
params.unregisterations.forEach(
|
|
||||||
(capabilityUnregistration: LSP.Unregistration) => {
|
|
||||||
const caps = unregisterServerCapability(
|
|
||||||
this.serverCapabilities,
|
|
||||||
capabilityUnregistration
|
|
||||||
)
|
|
||||||
if (caps instanceof Error) {
|
|
||||||
return (this.serverCapabilities = {})
|
|
||||||
}
|
|
||||||
this.serverCapabilities = caps
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// request "initialize": client <-> server
|
|
||||||
const { capabilities } = await this.request(
|
|
||||||
LSP.InitializeRequest.type.method,
|
|
||||||
{
|
|
||||||
processId: null,
|
|
||||||
clientInfo: {
|
|
||||||
name: 'codemirror-lsp-client',
|
|
||||||
},
|
|
||||||
capabilities: client_capabilities,
|
|
||||||
rootUri: null,
|
|
||||||
} as LSP.InitializeParams
|
|
||||||
)
|
|
||||||
|
|
||||||
this.serverCapabilities = capabilities
|
|
||||||
|
|
||||||
// notify "initialized": client --> server
|
|
||||||
this.notify(LSP.InitializedNotification.type.method, {})
|
|
||||||
|
|
||||||
this.initializedCallback()
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
this.afterInitializedHooks.map((f: () => Promise<void>) => f())
|
|
||||||
)
|
|
||||||
await Promise.all([this.processNotifications(), this.processRequests()])
|
|
||||||
}
|
|
||||||
|
|
||||||
getServerCapabilities(): LSP.ServerCapabilities<any> {
|
|
||||||
return this.serverCapabilities
|
|
||||||
}
|
|
||||||
|
|
||||||
setNotifyFn(fn: (message: LSP.NotificationMessage) => void): void {
|
|
||||||
this.notifyFn = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
async processNotifications(): Promise<void> {
|
|
||||||
for await (const notification of this.#fromServer.notifications) {
|
|
||||||
if (this.notifyFn) {
|
|
||||||
this.notifyFn(notification)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async processRequests(): Promise<void> {
|
|
||||||
for await (const request of this.#fromServer.requests) {
|
|
||||||
await this.receiveAndSend(request)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pushAfterInitializeHook(...hooks: (() => Promise<void>)[]): void {
|
|
||||||
this.afterInitializedHooks.push(...hooks)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
import {
|
|
||||||
Registration,
|
|
||||||
ServerCapabilities,
|
|
||||||
Unregistration,
|
|
||||||
} from 'vscode-languageserver-protocol'
|
|
||||||
|
|
||||||
interface IFlexibleServerCapabilities extends ServerCapabilities {
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMethodServerCapabilityProviderDictionary {
|
|
||||||
[key: string]: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const ServerCapabilitiesProviders: IMethodServerCapabilityProviderDictionary = {
|
|
||||||
'textDocument/hover': 'hoverProvider',
|
|
||||||
'textDocument/completion': 'completionProvider',
|
|
||||||
'textDocument/signatureHelp': 'signatureHelpProvider',
|
|
||||||
'textDocument/definition': 'definitionProvider',
|
|
||||||
'textDocument/typeDefinition': 'typeDefinitionProvider',
|
|
||||||
'textDocument/implementation': 'implementationProvider',
|
|
||||||
'textDocument/references': 'referencesProvider',
|
|
||||||
'textDocument/documentHighlight': 'documentHighlightProvider',
|
|
||||||
'textDocument/documentSymbol': 'documentSymbolProvider',
|
|
||||||
'textDocument/workspaceSymbol': 'workspaceSymbolProvider',
|
|
||||||
'textDocument/codeAction': 'codeActionProvider',
|
|
||||||
'textDocument/codeLens': 'codeLensProvider',
|
|
||||||
'textDocument/documentFormatting': 'documentFormattingProvider',
|
|
||||||
'textDocument/documentRangeFormatting': 'documentRangeFormattingProvider',
|
|
||||||
'textDocument/documentOnTypeFormatting': 'documentOnTypeFormattingProvider',
|
|
||||||
'textDocument/rename': 'renameProvider',
|
|
||||||
'textDocument/documentLink': 'documentLinkProvider',
|
|
||||||
'textDocument/color': 'colorProvider',
|
|
||||||
'textDocument/foldingRange': 'foldingRangeProvider',
|
|
||||||
'textDocument/declaration': 'declarationProvider',
|
|
||||||
'textDocument/executeCommand': 'executeCommandProvider',
|
|
||||||
'textDocument/semanticTokens/full': 'semanticTokensProvider',
|
|
||||||
'textDocument/publishDiagnostics': 'diagnosticsProvider',
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerServerCapability(
|
|
||||||
serverCapabilities: ServerCapabilities,
|
|
||||||
registration: Registration
|
|
||||||
): ServerCapabilities | Error {
|
|
||||||
const serverCapabilitiesCopy = JSON.parse(
|
|
||||||
JSON.stringify(serverCapabilities)
|
|
||||||
) as IFlexibleServerCapabilities
|
|
||||||
const { method, registerOptions } = registration
|
|
||||||
const providerName = ServerCapabilitiesProviders[method]
|
|
||||||
|
|
||||||
if (providerName) {
|
|
||||||
if (!registerOptions) {
|
|
||||||
serverCapabilitiesCopy[providerName] = true
|
|
||||||
} else {
|
|
||||||
serverCapabilitiesCopy[providerName] = Object.assign(
|
|
||||||
{},
|
|
||||||
JSON.parse(JSON.stringify(registerOptions))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new Error('Could not register server capability.')
|
|
||||||
}
|
|
||||||
|
|
||||||
return serverCapabilitiesCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
function unregisterServerCapability(
|
|
||||||
serverCapabilities: ServerCapabilities,
|
|
||||||
unregistration: Unregistration
|
|
||||||
): ServerCapabilities {
|
|
||||||
const serverCapabilitiesCopy = JSON.parse(
|
|
||||||
JSON.stringify(serverCapabilities)
|
|
||||||
) as IFlexibleServerCapabilities
|
|
||||||
const { method } = unregistration
|
|
||||||
const providerName = ServerCapabilitiesProviders[method]
|
|
||||||
|
|
||||||
delete serverCapabilitiesCopy[providerName]
|
|
||||||
|
|
||||||
return serverCapabilitiesCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
export { registerServerCapability, unregisterServerCapability }
|
|
@ -1,57 +0,0 @@
|
|||||||
import { foldService } from '@codemirror/language'
|
|
||||||
import { Extension, EditorState } from '@codemirror/state'
|
|
||||||
import { ViewPlugin } from '@codemirror/view'
|
|
||||||
|
|
||||||
import {
|
|
||||||
docPathFacet,
|
|
||||||
LanguageServerPlugin,
|
|
||||||
LanguageServerPluginSpec,
|
|
||||||
languageId,
|
|
||||||
workspaceFolders,
|
|
||||||
LanguageServerOptions,
|
|
||||||
} from './plugin/lsp'
|
|
||||||
|
|
||||||
export type { LanguageServerClientOptions } from './client'
|
|
||||||
export { LanguageServerClient } from './client'
|
|
||||||
export {
|
|
||||||
Codec,
|
|
||||||
FromServer,
|
|
||||||
IntoServer,
|
|
||||||
LspWorkerEventType,
|
|
||||||
} from './client/codec'
|
|
||||||
export type { LanguageServerOptions } from './plugin/lsp'
|
|
||||||
export {
|
|
||||||
LanguageServerPlugin,
|
|
||||||
LanguageServerPluginSpec,
|
|
||||||
docPathFacet,
|
|
||||||
languageId,
|
|
||||||
workspaceFolders,
|
|
||||||
lspSemanticTokensEvent,
|
|
||||||
lspDiagnosticsEvent,
|
|
||||||
lspFormatCodeEvent,
|
|
||||||
} from './plugin/lsp'
|
|
||||||
export { posToOffset, offsetToPos } from './plugin/util'
|
|
||||||
|
|
||||||
export function lspPlugin(options: LanguageServerOptions): Extension {
|
|
||||||
let plugin: LanguageServerPlugin | null = null
|
|
||||||
const viewPlugin = ViewPlugin.define(
|
|
||||||
(view) => (plugin = new LanguageServerPlugin(options, view)),
|
|
||||||
new LanguageServerPluginSpec()
|
|
||||||
)
|
|
||||||
|
|
||||||
let ext = [
|
|
||||||
docPathFacet.of(options.documentUri),
|
|
||||||
languageId.of('kcl'),
|
|
||||||
workspaceFolders.of(options.workspaceFolders),
|
|
||||||
viewPlugin,
|
|
||||||
foldService.of((state: EditorState, lineStart: number, lineEnd: number) => {
|
|
||||||
if (plugin == null) return null
|
|
||||||
// Get the folding ranges from the language server.
|
|
||||||
// Since this is async we directly need to update the folding ranges after.
|
|
||||||
const range = plugin?.foldingRange(lineStart, lineEnd)
|
|
||||||
return range
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
|
|
||||||
return ext
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
import {
|
|
||||||
acceptCompletion,
|
|
||||||
autocompletion,
|
|
||||||
clearSnippet,
|
|
||||||
closeCompletion,
|
|
||||||
hasNextSnippetField,
|
|
||||||
moveCompletionSelection,
|
|
||||||
nextSnippetField,
|
|
||||||
prevSnippetField,
|
|
||||||
startCompletion,
|
|
||||||
} from '@codemirror/autocomplete'
|
|
||||||
import { Prec, Extension } from '@codemirror/state'
|
|
||||||
import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view'
|
|
||||||
|
|
||||||
import {
|
|
||||||
CompletionItemKind,
|
|
||||||
CompletionTriggerKind,
|
|
||||||
} from 'vscode-languageserver-protocol'
|
|
||||||
|
|
||||||
import { LanguageServerPlugin } from './lsp'
|
|
||||||
import { offsetToPos } from './util'
|
|
||||||
import { syntaxTree } from '@codemirror/language'
|
|
||||||
|
|
||||||
export const CompletionItemKindMap = Object.fromEntries(
|
|
||||||
Object.entries(CompletionItemKind).map(([key, value]) => [value, key])
|
|
||||||
) as Record<CompletionItemKind, string>
|
|
||||||
|
|
||||||
const lspAutocompleteKeymap: readonly KeyBinding[] = [
|
|
||||||
{ key: 'Ctrl-Space', run: startCompletion },
|
|
||||||
{
|
|
||||||
key: 'Escape',
|
|
||||||
run: (view: EditorView): boolean => {
|
|
||||||
if (clearSnippet(view)) return true
|
|
||||||
|
|
||||||
return closeCompletion(view)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ key: 'ArrowDown', run: moveCompletionSelection(true) },
|
|
||||||
{ key: 'ArrowUp', run: moveCompletionSelection(false) },
|
|
||||||
{ key: 'PageDown', run: moveCompletionSelection(true, 'page') },
|
|
||||||
{ key: 'PageUp', run: moveCompletionSelection(false, 'page') },
|
|
||||||
{ key: 'Enter', run: acceptCompletion },
|
|
||||||
{
|
|
||||||
key: 'Tab',
|
|
||||||
run: (view: EditorView): boolean => {
|
|
||||||
if (hasNextSnippetField(view.state)) {
|
|
||||||
const result = nextSnippetField(view)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
return acceptCompletion(view)
|
|
||||||
},
|
|
||||||
shift: prevSnippetField,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const lspAutocompleteKeymapExt = Prec.highest(keymap.of(lspAutocompleteKeymap))
|
|
||||||
|
|
||||||
export default function lspAutocompleteExt(
|
|
||||||
plugin: ViewPlugin<LanguageServerPlugin>
|
|
||||||
): Extension {
|
|
||||||
return [
|
|
||||||
lspAutocompleteKeymapExt,
|
|
||||||
autocompletion({
|
|
||||||
defaultKeymap: false,
|
|
||||||
override: [
|
|
||||||
async (context) => {
|
|
||||||
const { state, pos, explicit, view } = context
|
|
||||||
let value = view?.plugin(plugin)
|
|
||||||
if (!value) return null
|
|
||||||
|
|
||||||
let nodeBefore = syntaxTree(state).resolveInner(pos, -1)
|
|
||||||
if (
|
|
||||||
nodeBefore.name === 'BlockComment' ||
|
|
||||||
nodeBefore.name === 'LineComment'
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
|
|
||||||
const line = state.doc.lineAt(pos)
|
|
||||||
let trigKind: CompletionTriggerKind = CompletionTriggerKind.Invoked
|
|
||||||
let trigChar: string | undefined
|
|
||||||
if (
|
|
||||||
!explicit &&
|
|
||||||
value.client
|
|
||||||
.getServerCapabilities()
|
|
||||||
.completionProvider?.triggerCharacters?.includes(
|
|
||||||
line.text[pos - line.from - 1]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
trigKind = CompletionTriggerKind.TriggerCharacter
|
|
||||||
trigChar = line.text[pos - line.from - 1]
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
trigKind === CompletionTriggerKind.Invoked &&
|
|
||||||
!context.matchBefore(/\w+$/)
|
|
||||||
) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return await value.requestCompletion(
|
|
||||||
context,
|
|
||||||
offsetToPos(state.doc, pos),
|
|
||||||
{
|
|
||||||
triggerKind: trigKind,
|
|
||||||
triggerCharacter: trigChar,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
import { Extension, Prec } from '@codemirror/state'
|
|
||||||
import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view'
|
|
||||||
|
|
||||||
import { LanguageServerPlugin } from './lsp'
|
|
||||||
|
|
||||||
export default function lspFormatExt(
|
|
||||||
plugin: ViewPlugin<LanguageServerPlugin>
|
|
||||||
): Extension {
|
|
||||||
const formatKeymap: readonly KeyBinding[] = [
|
|
||||||
{
|
|
||||||
key: 'Alt-Shift-f',
|
|
||||||
run: (view: EditorView) => {
|
|
||||||
let value = view.plugin(plugin)
|
|
||||||
if (!value) return false
|
|
||||||
value.requestFormatting()
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
// Create an extension for the key mappings.
|
|
||||||
const formatKeymapExt = Prec.highest(
|
|
||||||
keymap.computeN([], () => [formatKeymap])
|
|
||||||
)
|
|
||||||
|
|
||||||
return formatKeymapExt
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
import { Extension } from '@codemirror/state'
|
|
||||||
import { hoverTooltip, tooltips, ViewPlugin } from '@codemirror/view'
|
|
||||||
|
|
||||||
import { LanguageServerPlugin } from './lsp'
|
|
||||||
import { offsetToPos } from './util'
|
|
||||||
|
|
||||||
export default function lspHoverExt(
|
|
||||||
plugin: ViewPlugin<LanguageServerPlugin>
|
|
||||||
): Extension {
|
|
||||||
return [
|
|
||||||
hoverTooltip((view, pos) => {
|
|
||||||
const value = view.plugin(plugin)
|
|
||||||
return (
|
|
||||||
value?.requestHoverTooltip(view, offsetToPos(view.state.doc, pos)) ??
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
tooltips({
|
|
||||||
position: 'absolute',
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { indentService } from '@codemirror/language'
|
|
||||||
import { Extension } from '@codemirror/state'
|
|
||||||
|
|
||||||
export default function lspIndentExt(): Extension {
|
|
||||||
// Match the indentation of the previous line (if present).
|
|
||||||
return indentService.of((context, pos) => {
|
|
||||||
try {
|
|
||||||
const previousLine = context.lineAt(pos, -1)
|
|
||||||
const previousLineText = previousLine.text.replaceAll(
|
|
||||||
'\t',
|
|
||||||
' '.repeat(context.state.tabSize)
|
|
||||||
)
|
|
||||||
const match = previousLineText.match(/^(\s)*/)
|
|
||||||
if (match === null || match.length <= 0) return null
|
|
||||||
return match[0].length
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error in codemirror indentService', err)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { Extension } from '@codemirror/state'
|
|
||||||
import { linter, forEachDiagnostic, Diagnostic } from '@codemirror/lint'
|
|
||||||
|
|
||||||
export default function lspLintExt(): Extension {
|
|
||||||
return linter((view) => {
|
|
||||||
let diagnostics: Diagnostic[] = []
|
|
||||||
forEachDiagnostic(view.state, (d: Diagnostic, from: number, to: number) => {
|
|
||||||
diagnostics.push(d)
|
|
||||||
})
|
|
||||||
return diagnostics
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,175 +0,0 @@
|
|||||||
import { highlightingFor } from '@codemirror/language'
|
|
||||||
import { StateEffect, StateField, Extension } from '@codemirror/state'
|
|
||||||
import { EditorView, Decoration, DecorationSet } from '@codemirror/view'
|
|
||||||
|
|
||||||
import { Tag, tags } from '@lezer/highlight'
|
|
||||||
|
|
||||||
import { lspSemanticTokensEvent } from './lsp'
|
|
||||||
|
|
||||||
export interface SemanticToken {
|
|
||||||
from: number
|
|
||||||
to: number
|
|
||||||
type: string
|
|
||||||
modifiers: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const addToken = StateEffect.define<SemanticToken>({
|
|
||||||
map: (token: SemanticToken, change) => ({
|
|
||||||
...token,
|
|
||||||
from: change.mapPos(token.from),
|
|
||||||
to: change.mapPos(token.to),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
|
|
||||||
export default function lspSemanticTokenExt(): Extension {
|
|
||||||
return StateField.define<DecorationSet>({
|
|
||||||
create() {
|
|
||||||
return Decoration.none
|
|
||||||
},
|
|
||||||
update(highlights, tr) {
|
|
||||||
// Nothing can come before this line, this is very important!
|
|
||||||
// It makes sure the highlights are updated correctly for the changes.
|
|
||||||
highlights = highlights.map(tr.changes)
|
|
||||||
|
|
||||||
const isSemanticTokensEvent = tr.annotation(lspSemanticTokensEvent.type)
|
|
||||||
if (!isSemanticTokensEvent) {
|
|
||||||
return highlights
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any of the changes are addToken
|
|
||||||
const hasAddToken = tr.effects.some((e) => e.is(addToken))
|
|
||||||
if (hasAddToken) {
|
|
||||||
highlights = highlights.update({
|
|
||||||
filter: (from, to) => false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const e of tr.effects)
|
|
||||||
if (e.is(addToken)) {
|
|
||||||
const tag = getTag(e.value)
|
|
||||||
const className = tag
|
|
||||||
? highlightingFor(tr.startState, [tag])
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
if (e.value.from < e.value.to && tag) {
|
|
||||||
if (className) {
|
|
||||||
highlights = highlights.update({
|
|
||||||
add: [
|
|
||||||
Decoration.mark({ class: className }).range(
|
|
||||||
e.value.from,
|
|
||||||
e.value.to
|
|
||||||
),
|
|
||||||
],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return highlights
|
|
||||||
},
|
|
||||||
provide: (f) => EditorView.decorations.from(f),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getTag(semanticToken: SemanticToken): Tag | null {
|
|
||||||
let tokenType = convertSemanticTokenTypeToCodeMirrorTag(semanticToken.type)
|
|
||||||
|
|
||||||
if (
|
|
||||||
semanticToken.modifiers === undefined ||
|
|
||||||
semanticToken.modifiers === null ||
|
|
||||||
semanticToken.modifiers.length === 0
|
|
||||||
) {
|
|
||||||
return tokenType
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let modifier of semanticToken.modifiers) {
|
|
||||||
tokenType = convertSemanticTokenToCodeMirrorTag(
|
|
||||||
'',
|
|
||||||
modifier,
|
|
||||||
tokenType || undefined
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tokenType
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getTagName(semanticToken: SemanticToken): string {
|
|
||||||
let tokenType = semanticToken.type
|
|
||||||
|
|
||||||
if (
|
|
||||||
semanticToken.modifiers === undefined ||
|
|
||||||
semanticToken.modifiers === null ||
|
|
||||||
semanticToken.modifiers.length === 0
|
|
||||||
) {
|
|
||||||
return tokenType
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let modifier of semanticToken.modifiers) {
|
|
||||||
tokenType = `${tokenType}.${modifier}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return tokenType
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertSemanticTokenTypeToCodeMirrorTag(
|
|
||||||
tokenType: string
|
|
||||||
): Tag | null {
|
|
||||||
switch (tokenType) {
|
|
||||||
case 'keyword':
|
|
||||||
return tags.keyword
|
|
||||||
case 'variable':
|
|
||||||
return tags.variableName
|
|
||||||
case 'string':
|
|
||||||
return tags.string
|
|
||||||
case 'number':
|
|
||||||
return tags.number
|
|
||||||
case 'comment':
|
|
||||||
return tags.comment
|
|
||||||
case 'operator':
|
|
||||||
return tags.operator
|
|
||||||
case 'function':
|
|
||||||
return tags.function(tags.name)
|
|
||||||
case 'type':
|
|
||||||
return tags.typeName
|
|
||||||
case 'property':
|
|
||||||
return tags.propertyName
|
|
||||||
case 'parameter':
|
|
||||||
return tags.local(tags.name)
|
|
||||||
default:
|
|
||||||
console.error('Unknown token type:', tokenType)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertSemanticTokenToCodeMirrorTag(
|
|
||||||
tokenType: string,
|
|
||||||
tokenModifier: string,
|
|
||||||
givenTag?: Tag
|
|
||||||
): Tag | null {
|
|
||||||
let tag = givenTag
|
|
||||||
? givenTag
|
|
||||||
: convertSemanticTokenTypeToCodeMirrorTag(tokenType)
|
|
||||||
|
|
||||||
if (!tag) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tokenModifier) {
|
|
||||||
switch (tokenModifier) {
|
|
||||||
case 'definition':
|
|
||||||
return tags.definition(tag)
|
|
||||||
case 'declaration':
|
|
||||||
return tags.definition(tag)
|
|
||||||
case 'readonly':
|
|
||||||
return tags.constant(tag)
|
|
||||||
case 'static':
|
|
||||||
return tags.constant(tag)
|
|
||||||
case 'defaultLibrary':
|
|
||||||
return tags.standard(tag)
|
|
||||||
default:
|
|
||||||
console.error('Unknown token modifier:', tokenModifier)
|
|
||||||
return tag
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tag
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
import { Text } from '@codemirror/state'
|
|
||||||
import { Marked } from '@ts-stack/markdown'
|
|
||||||
|
|
||||||
import type * as LSP from 'vscode-languageserver-protocol'
|
|
||||||
|
|
||||||
// takes a function and executes it after the wait time, if the function is called again before the wait time is up, the timer is reset
|
|
||||||
export function deferExecution<T>(func: (args: T) => any, wait: number) {
|
|
||||||
let timeout: ReturnType<typeof setTimeout> | null
|
|
||||||
let latestArgs: T
|
|
||||||
|
|
||||||
function later() {
|
|
||||||
timeout = null
|
|
||||||
func(latestArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
function deferred(args: T) {
|
|
||||||
latestArgs = args
|
|
||||||
if (timeout) {
|
|
||||||
clearTimeout(timeout)
|
|
||||||
}
|
|
||||||
timeout = setTimeout(later, wait)
|
|
||||||
}
|
|
||||||
|
|
||||||
return deferred
|
|
||||||
}
|
|
||||||
|
|
||||||
export function posToOffset(
|
|
||||||
doc: Text,
|
|
||||||
pos: { line: number; character: number }
|
|
||||||
): number | undefined {
|
|
||||||
if (pos.line >= doc.lines) return
|
|
||||||
const offset = doc.line(pos.line + 1).from + pos.character
|
|
||||||
if (offset > doc.length) return
|
|
||||||
return offset
|
|
||||||
}
|
|
||||||
|
|
||||||
export function offsetToPos(doc: Text, offset: number) {
|
|
||||||
const line = doc.lineAt(offset)
|
|
||||||
return {
|
|
||||||
line: line.number - 1,
|
|
||||||
character: offset - line.from,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatMarkdownContents(
|
|
||||||
contents: LSP.MarkupContent | LSP.MarkedString | LSP.MarkedString[]
|
|
||||||
): string {
|
|
||||||
if (Array.isArray(contents)) {
|
|
||||||
return contents.map((c) => formatMarkdownContents(c) + '\n\n').join('')
|
|
||||||
} else if (typeof contents === 'string') {
|
|
||||||
return Marked.parse(contents)
|
|
||||||
} else {
|
|
||||||
return Marked.parse(contents.value)
|
|
||||||
}
|
|
||||||
}
|
|