Compare commits
10 Commits
kcl-0.2.7
...
kcl-0.2.10
Author | SHA1 | Date | |
---|---|---|---|
6e10f75ff6 | |||
03e289af20 | |||
efc140abbf | |||
4dfad19b7e | |||
e56c634b35 | |||
00292abc98 | |||
483d6903d6 | |||
3780996374 | |||
2fde71228a | |||
5cd8ab3812 |
835
docs/kcl/hollow.md
Normal file
@ -44,6 +44,7 @@ layout: manual
|
||||
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
|
||||
* [`helix`](kcl/helix)
|
||||
* [`hole`](kcl/hole)
|
||||
* [`hollow`](kcl/hollow)
|
||||
* [`import`](kcl/import)
|
||||
* [`inch`](kcl/inch)
|
||||
* [`int`](kcl/int)
|
||||
|
5173
docs/kcl/std.json
@ -6,7 +6,39 @@ test.afterEach(async ({ page }, testInfo) => {
|
||||
await tearDown(page, testInfo)
|
||||
})
|
||||
|
||||
test.describe('Electron user sidebar menu tests', () => {
|
||||
test.describe('Electron app header tests', () => {
|
||||
test(
|
||||
'Open Command Palette button has correct shortcut',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async () => {},
|
||||
})
|
||||
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
||||
// No space before the shortcut since it checks textContent.
|
||||
let text
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
text = 'Commands⌘K'
|
||||
break
|
||||
case 'win32':
|
||||
text = 'CommandsCtrl+K'
|
||||
break
|
||||
default: // 'linux' etc.
|
||||
text = 'CommandsCtrl+K'
|
||||
break
|
||||
}
|
||||
const commandsButton = page.getByRole('button', { name: 'Commands' })
|
||||
await expect(commandsButton).toBeVisible()
|
||||
await expect(commandsButton).toHaveText(text)
|
||||
|
||||
await electronApp.close()
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'User settings has correct shortcut',
|
||||
{ tag: '@electron' },
|
@ -1,6 +1,13 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
import { getUtils, setup, setupElectron, tearDown } from './test-utils'
|
||||
import {
|
||||
getUtils,
|
||||
setup,
|
||||
setupElectron,
|
||||
tearDown,
|
||||
executorInputPath,
|
||||
} from './test-utils'
|
||||
import { join } from 'path'
|
||||
import { bracket } from 'lib/exampleKcl'
|
||||
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from './storageStates'
|
||||
import fsp from 'fs/promises'
|
||||
@ -223,26 +230,24 @@ test(
|
||||
'Opening multiple panes persists when switching projects',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
// Setup multiple projects.
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
const routerTemplateDir = join(dir, 'router-template-slate')
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await Promise.all([
|
||||
fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }),
|
||||
fsp.mkdir(`${dir}/bracket`, { recursive: true }),
|
||||
fsp.mkdir(routerTemplateDir, { recursive: true }),
|
||||
fsp.mkdir(bracketDir, { recursive: true }),
|
||||
])
|
||||
await Promise.all([
|
||||
fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl',
|
||||
`${dir}/router-template-slate/main.kcl`
|
||||
executorInputPath('router-template-slate.kcl'),
|
||||
join(routerTemplateDir, 'main.kcl')
|
||||
),
|
||||
fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
|
||||
`${dir}/bracket/main.kcl`
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
),
|
||||
])
|
||||
},
|
||||
|
@ -1,5 +1,11 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { getUtils, setupElectron, tearDown } from './test-utils'
|
||||
import { join } from 'path'
|
||||
import {
|
||||
getUtils,
|
||||
setupElectron,
|
||||
tearDown,
|
||||
executorInputPath,
|
||||
} from './test-utils'
|
||||
import fsp from 'fs/promises'
|
||||
|
||||
test.afterEach(async ({ page }, testInfo) => {
|
||||
@ -10,22 +16,19 @@ test(
|
||||
'export works on the first try',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await Promise.all([fsp.mkdir(`${dir}/bracket`, { recursive: true })])
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
|
||||
await Promise.all([
|
||||
fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl',
|
||||
`${dir}/bracket/other.kcl`
|
||||
executorInputPath('router-template-slate.kcl'),
|
||||
join(bracketDir, 'other.kcl')
|
||||
),
|
||||
fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
|
||||
`${dir}/bracket/main.kcl`
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
),
|
||||
])
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { setupElectron, tearDown } from './test-utils'
|
||||
import { setupElectron, tearDown, executorInputPath } from './test-utils'
|
||||
import { join } from 'path'
|
||||
import fsp from 'fs/promises'
|
||||
|
||||
test.afterEach(async ({ page }, testInfo) => {
|
||||
@ -10,17 +11,14 @@ test(
|
||||
'When machine-api server not found butt is disabled and shows the reason',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/bracket`, { recursive: true })
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
|
||||
`${dir}/bracket/main.kcl`
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
@ -58,17 +56,14 @@ test(
|
||||
'When machine-api server not found home screen & project status shows the reason',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/bracket`, { recursive: true })
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
|
||||
`${dir}/bracket/main.kcl`
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
|
@ -1,6 +1,13 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { join } from 'path'
|
||||
import fsp from 'fs/promises'
|
||||
import { getUtils, setup, setupElectron, tearDown } from './test-utils'
|
||||
import {
|
||||
getUtils,
|
||||
setup,
|
||||
setupElectron,
|
||||
tearDown,
|
||||
executorInputPath,
|
||||
} from './test-utils'
|
||||
import { bracket } from 'lib/exampleKcl'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import {
|
||||
@ -347,17 +354,14 @@ test(
|
||||
'Restarting onboarding on desktop takes one attempt',
|
||||
{ tag: '@electron' },
|
||||
async ({ browser: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
|
||||
const routerTemplateDir = join(dir, 'router-template-slate')
|
||||
await fsp.mkdir(routerTemplateDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl',
|
||||
`${dir}/router-template-slate/main.kcl`
|
||||
executorInputPath('router-template-slate.kcl'),
|
||||
join(routerTemplateDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { test, expect, Page } from '@playwright/test'
|
||||
import {
|
||||
doExport,
|
||||
executorInputPath,
|
||||
getUtils,
|
||||
isOutOfViewInScrollContainer,
|
||||
Paths,
|
||||
@ -49,17 +50,11 @@ test(
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'bracket'), { recursive: true })
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
join(
|
||||
'src',
|
||||
'wasm-lib',
|
||||
'tests',
|
||||
'executor',
|
||||
'inputs',
|
||||
'focusrite_scarlett_mounting_braket.kcl'
|
||||
),
|
||||
join(dir, 'bracket', 'main.kcl')
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
@ -99,14 +94,7 @@ test(
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'broken-code'), { recursive: true })
|
||||
await fsp.copyFile(
|
||||
join(
|
||||
'src',
|
||||
'wasm-lib',
|
||||
'tests',
|
||||
'executor',
|
||||
'inputs',
|
||||
'broken-code-test.kcl'
|
||||
),
|
||||
executorInputPath('broken-code-test.kcl'),
|
||||
join(dir, 'broken-code', 'main.kcl')
|
||||
)
|
||||
},
|
||||
@ -143,17 +131,14 @@ test.describe('Can export from electron app', () => {
|
||||
`Can export using ${method}`,
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/bracket`, { recursive: true })
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
|
||||
`${dir}/bracket/main.kcl`
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
@ -605,6 +590,48 @@ test(
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'Can load a file with CRLF line endings',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
const routerTemplateDir = join(dir, 'router-template-slate')
|
||||
await fsp.mkdir(routerTemplateDir, { recursive: true })
|
||||
|
||||
const file = await fsp.readFile(
|
||||
executorInputPath('router-template-slate.kcl'),
|
||||
'utf-8'
|
||||
)
|
||||
// Replace both \r optionally so we don't end up with \r\r\n
|
||||
const fileWithCRLF = file.replace(/\r?\n/g, '\r\n')
|
||||
await fsp.writeFile(
|
||||
join(routerTemplateDir, 'main.kcl'),
|
||||
fileWithCRLF,
|
||||
'utf-8'
|
||||
)
|
||||
},
|
||||
})
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
||||
page.on('console', console.log)
|
||||
|
||||
await page.getByText('router-template-slate').click()
|
||||
await expect(page.getByTestId('loading')).toBeAttached()
|
||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
||||
timeout: 20_000,
|
||||
})
|
||||
|
||||
await expect(u.codeLocator).toContainText('routerDiameter')
|
||||
await expect(u.codeLocator).toContainText('templateGap')
|
||||
await expect(u.codeLocator).toContainText('minClampingDistance')
|
||||
|
||||
await electronApp.close()
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'Can sort projects on home page',
|
||||
{ tag: '@electron' },
|
||||
@ -1032,10 +1059,6 @@ test(
|
||||
'Search projects on desktop home',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const projectData = [
|
||||
['basic bracket', 'focusrite_scarlett_mounting_braket.kcl'],
|
||||
['basic-cube', 'basic_fillet_cube_end.kcl'],
|
||||
@ -1050,7 +1073,7 @@ test(
|
||||
for (const [name, file] of projectData) {
|
||||
await fsp.mkdir(join(dir, name), { recursive: true })
|
||||
await fsp.copyFile(
|
||||
join('src', 'wasm-lib', 'tests', 'executor', 'inputs', file),
|
||||
executorInputPath(file),
|
||||
join(dir, name, `main.kcl`)
|
||||
)
|
||||
}
|
||||
@ -1097,14 +1120,11 @@ test(
|
||||
'file pane is scrollable when there are many files',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/testProject`, { recursive: true })
|
||||
const testDir = join(dir, 'testProject')
|
||||
await fsp.mkdir(testDir, { recursive: true })
|
||||
const fileNames = [
|
||||
'angled_line.kcl',
|
||||
'basic_fillet_cube_close_opposite.kcl',
|
||||
@ -1168,8 +1188,8 @@ test(
|
||||
]
|
||||
for (const fileName of fileNames) {
|
||||
await fsp.copyFile(
|
||||
`src/wasm-lib/tests/executor/inputs/${fileName}`,
|
||||
`${dir}/testProject/${fileName}`
|
||||
executorInputPath(fileName),
|
||||
join(testDir, fileName)
|
||||
)
|
||||
}
|
||||
},
|
||||
@ -1210,19 +1230,16 @@ test(
|
||||
'select all in code editor does not actually select all, just what is visible (regression)',
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
// src/wasm-lib/tests/executor/inputs/mike_stress_test.kcl
|
||||
const name = 'mike_stress_test'
|
||||
await fsp.mkdir(`${dir}/${name}`, { recursive: true })
|
||||
const testDir = join(dir, name)
|
||||
await fsp.mkdir(testDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
`src/wasm-lib/tests/executor/inputs/${name}.kcl`,
|
||||
`${dir}/${name}/main.kcl`
|
||||
executorInputPath(`${name}.kcl`),
|
||||
join(testDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
@ -1320,27 +1337,16 @@ test.describe('Renaming in the file tree', () => {
|
||||
'A file you have open',
|
||||
{ tag: '@electron' },
|
||||
async ({ browser: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page, dir } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
const exampleDir = join(
|
||||
'src',
|
||||
'wasm-lib',
|
||||
'tests',
|
||||
'executor',
|
||||
'inputs'
|
||||
)
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'basic_fillet_cube_end.kcl'),
|
||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||
join(dir, 'Test Project', 'main.kcl')
|
||||
)
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'cylinder.kcl'),
|
||||
executorInputPath('cylinder.kcl'),
|
||||
join(dir, 'Test Project', 'fileToRename.kcl')
|
||||
)
|
||||
},
|
||||
@ -1425,27 +1431,16 @@ test.describe('Renaming in the file tree', () => {
|
||||
'A file you do not have open',
|
||||
{ tag: '@electron' },
|
||||
async ({ browser: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page, dir } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
const exampleDir = join(
|
||||
'src',
|
||||
'wasm-lib',
|
||||
'tests',
|
||||
'executor',
|
||||
'inputs'
|
||||
)
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'basic_fillet_cube_end.kcl'),
|
||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||
join(dir, 'Test Project', 'main.kcl')
|
||||
)
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'cylinder.kcl'),
|
||||
executorInputPath('cylinder.kcl'),
|
||||
join(dir, 'Test Project', 'fileToRename.kcl')
|
||||
)
|
||||
},
|
||||
@ -1527,10 +1522,6 @@ test.describe('Renaming in the file tree', () => {
|
||||
`A folder you're not inside`,
|
||||
{ tag: '@electron' },
|
||||
async ({ browser: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page, dir } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
@ -1538,19 +1529,12 @@ test.describe('Renaming in the file tree', () => {
|
||||
await fsp.mkdir(join(dir, 'Test Project', 'folderToRename'), {
|
||||
recursive: true,
|
||||
})
|
||||
const exampleDir = join(
|
||||
'src',
|
||||
'wasm-lib',
|
||||
'tests',
|
||||
'executor',
|
||||
'inputs'
|
||||
)
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'basic_fillet_cube_end.kcl'),
|
||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||
join(dir, 'Test Project', 'main.kcl')
|
||||
)
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'cylinder.kcl'),
|
||||
executorInputPath('cylinder.kcl'),
|
||||
join(dir, 'Test Project', 'folderToRename', 'someFileWithin.kcl')
|
||||
)
|
||||
},
|
||||
@ -1625,11 +1609,6 @@ test.describe('Renaming in the file tree', () => {
|
||||
`A folder you are inside`,
|
||||
{ tag: '@electron' },
|
||||
async ({ browser: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const exampleDir = join('src', 'wasm-lib', 'tests', 'executor', 'inputs')
|
||||
const { electronApp, page, dir } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
@ -1638,11 +1617,11 @@ test.describe('Renaming in the file tree', () => {
|
||||
recursive: true,
|
||||
})
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'basic_fillet_cube_end.kcl'),
|
||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||
join(dir, 'Test Project', 'main.kcl')
|
||||
)
|
||||
await fsp.copyFile(
|
||||
join(exampleDir, 'cylinder.kcl'),
|
||||
executorInputPath('cylinder.kcl'),
|
||||
join(dir, 'Test Project', 'folderToRename', 'someFileWithin.kcl')
|
||||
)
|
||||
},
|
||||
@ -1738,21 +1717,18 @@ test.describe('Deleting files from the file pane', () => {
|
||||
`when main.kcl exists, navigate to main.kcl`,
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/testProject`, { recursive: true })
|
||||
const testDir = join(dir, 'testProject')
|
||||
await fsp.mkdir(testDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/cylinder.kcl',
|
||||
`${dir}/testProject/main.kcl`
|
||||
executorInputPath('cylinder.kcl'),
|
||||
join(testDir, 'main.kcl')
|
||||
)
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/basic_fillet_cube_end.kcl',
|
||||
`${dir}/testProject/fileToDelete.kcl`
|
||||
executorInputPath('basic_fillet_cube_end.kcl'),
|
||||
join(testDir, 'fileToDelete.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
|
@ -1,6 +1,13 @@
|
||||
import { test, expect, Page } from '@playwright/test'
|
||||
import { join } from 'path'
|
||||
import * as fsp from 'fs/promises'
|
||||
import { getUtils, setup, setupElectron, tearDown } from './test-utils'
|
||||
import {
|
||||
getUtils,
|
||||
setup,
|
||||
setupElectron,
|
||||
tearDown,
|
||||
executorInputPath,
|
||||
} from './test-utils'
|
||||
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
|
||||
import { bracket } from 'lib/exampleKcl'
|
||||
|
||||
@ -425,17 +432,14 @@ const sketch001 = startSketchAt([-0, -0])
|
||||
`Network health indicator only appears in modeling view`,
|
||||
{ tag: '@electron' },
|
||||
async ({ browserName: _ }, testInfo) => {
|
||||
test.skip(
|
||||
process.platform === 'win32',
|
||||
'TODO: remove this skip https://github.com/KittyCAD/modeling-app/issues/3557'
|
||||
)
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/bracket`, { recursive: true })
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
|
||||
`${dir}/bracket/main.kcl`
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@ -912,3 +912,7 @@ export async function createProjectAndRenameIt({
|
||||
|
||||
await page.getByLabel('checkmark').last().click()
|
||||
}
|
||||
|
||||
export function executorInputPath(fileName: string): string {
|
||||
return join('src', 'wasm-lib', 'tests', 'executor', 'inputs', fileName)
|
||||
}
|
||||
|
@ -174,168 +174,166 @@ test.describe('Testing Camera Movement', () => {
|
||||
}, [0, -85, -85])
|
||||
})
|
||||
|
||||
// TODO fixme something is wrong with sketch here
|
||||
test.fixme(
|
||||
'Zoom should be consistent when exiting or entering sketches',
|
||||
async ({ page }) => {
|
||||
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
|
||||
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
|
||||
// than again for sketching
|
||||
test('Zoom should be consistent when exiting or entering sketches', async ({
|
||||
page,
|
||||
}) => {
|
||||
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
|
||||
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
|
||||
// than again for sketching
|
||||
|
||||
test.skip(process.platform !== 'darwin', 'Zoom should be consistent')
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
test.skip(process.platform !== 'darwin', 'Zoom should be consistent')
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await u.openDebugPanel()
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await u.openDebugPanel()
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).not.toBeDisabled()
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).toBeVisible()
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).not.toBeDisabled()
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).toBeVisible()
|
||||
|
||||
// click on "Start Sketch" button
|
||||
await u.clearCommandLogs()
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
// click on "Start Sketch" button
|
||||
await u.clearCommandLogs()
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
// select a plane
|
||||
await page.mouse.click(700, 325)
|
||||
|
||||
let code = `const sketch001 = startSketchOn('XY')`
|
||||
await expect(u.codeLocator).toHaveText(code)
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
|
||||
|
||||
// move the camera slightly
|
||||
await page.keyboard.down('Shift')
|
||||
await page.mouse.move(700, 300)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
await page.mouse.move(800, 200)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
await page.keyboard.up('Shift')
|
||||
|
||||
let y = 350,
|
||||
x = 948
|
||||
|
||||
await u.canvasLocator.click({ position: { x: 783, y } })
|
||||
code += `\n |> startProfileAt([8.12, -12.98], %)`
|
||||
// await expect(u.codeLocator).toHaveText(code)
|
||||
await u.canvasLocator.click({ position: { x, y } })
|
||||
code += `\n |> line([11.18, 0], %)`
|
||||
// await expect(u.codeLocator).toHaveText(code)
|
||||
await u.canvasLocator.click({ position: { x, y: 275 } })
|
||||
code += `\n |> line([0, 6.99], %)`
|
||||
// await expect(u.codeLocator).toHaveText(code)
|
||||
|
||||
// click the line button
|
||||
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||
|
||||
const hoverOverNothing = async () => {
|
||||
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
|
||||
await page.mouse.move(700, 325)
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
// select a plane
|
||||
await page.mouse.click(700, 325)
|
||||
|
||||
let code = `const sketch001 = startSketchOn('XY')`
|
||||
await expect(u.codeLocator).toHaveText(code)
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
|
||||
|
||||
// move the camera slightly
|
||||
await page.keyboard.down('Shift')
|
||||
await page.mouse.move(700, 300)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
await page.mouse.move(800, 200)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
await page.keyboard.up('Shift')
|
||||
|
||||
let y = 350,
|
||||
x = 948
|
||||
|
||||
await u.canvasLocator.click({ position: { x: 783, y } })
|
||||
code += `\n |> startProfileAt([8.12, -12.98], %)`
|
||||
// await expect(u.codeLocator).toHaveText(code)
|
||||
await u.canvasLocator.click({ position: { x, y } })
|
||||
code += `\n |> line([11.18, 0], %)`
|
||||
// await expect(u.codeLocator).toHaveText(code)
|
||||
await u.canvasLocator.click({ position: { x, y: 275 } })
|
||||
code += `\n |> line([0, 6.99], %)`
|
||||
// await expect(u.codeLocator).toHaveText(code)
|
||||
|
||||
// click the line button
|
||||
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||
|
||||
const hoverOverNothing = async () => {
|
||||
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
|
||||
await page.mouse.move(700, 325)
|
||||
await page.waitForTimeout(100)
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
}
|
||||
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
|
||||
|
||||
await page.waitForTimeout(200)
|
||||
// hover over horizontal line
|
||||
await u.canvasLocator.hover({ position: { x: 800, y } })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await hoverOverNothing()
|
||||
await page.waitForTimeout(200)
|
||||
// hover over vertical line
|
||||
await u.canvasLocator.hover({ position: { x, y: 325 } })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
// click exit sketch
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
await page.waitForTimeout(400)
|
||||
|
||||
await hoverOverNothing()
|
||||
await page.waitForTimeout(200)
|
||||
// hover over horizontal line
|
||||
await page.mouse.move(858, y, { steps: 5 })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
// hover over vertical line
|
||||
await page.mouse.move(x, 325)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
// hover over vertical line
|
||||
await page.mouse.move(857, y)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
// now click it
|
||||
await page.mouse.click(857, y)
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Edit Sketch' })
|
||||
).toBeVisible()
|
||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||
|
||||
await page.waitForTimeout(400)
|
||||
|
||||
await hoverOverNothing()
|
||||
x = 975
|
||||
y = 468
|
||||
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.move(x, 419, { steps: 5 })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
await page.mouse.move(855, y)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await hoverOverNothing()
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await page.mouse.move(x, 419)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
await page.mouse.move(855, y)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
|
||||
|
||||
await page.waitForTimeout(200)
|
||||
// hover over horizontal line
|
||||
await u.canvasLocator.hover({ position: { x: 800, y } })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await hoverOverNothing()
|
||||
await page.waitForTimeout(200)
|
||||
// hover over vertical line
|
||||
await u.canvasLocator.hover({ position: { x, y: 325 } })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
// click exit sketch
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
await page.waitForTimeout(400)
|
||||
|
||||
await hoverOverNothing()
|
||||
await page.waitForTimeout(200)
|
||||
// hover over horizontal line
|
||||
await page.mouse.move(858, y, { steps: 5 })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
// hover over vertical line
|
||||
await page.mouse.move(x, 325)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
// hover over vertical line
|
||||
await page.mouse.move(857, y)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
// now click it
|
||||
await page.mouse.click(857, y)
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Edit Sketch' })
|
||||
).toBeVisible()
|
||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||
|
||||
await page.waitForTimeout(400)
|
||||
|
||||
await hoverOverNothing()
|
||||
x = 975
|
||||
y = 468
|
||||
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.move(x, 419, { steps: 5 })
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
await page.mouse.move(855, y)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await hoverOverNothing()
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await page.mouse.move(x, 419)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
await hoverOverNothing()
|
||||
|
||||
await page.mouse.move(855, y)
|
||||
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,13 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import * as fsp from 'fs/promises'
|
||||
import { getUtils, setup, setupElectron, tearDown } from './test-utils'
|
||||
import { join } from 'path'
|
||||
import {
|
||||
getUtils,
|
||||
setup,
|
||||
setupElectron,
|
||||
tearDown,
|
||||
executorInputPath,
|
||||
} from './test-utils'
|
||||
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
|
||||
import { TEST_SETTINGS_KEY, TEST_SETTINGS_CORRUPTED } from './storageStates'
|
||||
import * as TOML from '@iarna/toml'
|
||||
@ -115,6 +122,36 @@ test.describe('Testing settings', () => {
|
||||
).not.toBeChecked()
|
||||
})
|
||||
|
||||
test('Keybindings display the correct hotkey for Command Palette', async ({
|
||||
page,
|
||||
}) => {
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
await u.waitForAuthSkipAppStart()
|
||||
|
||||
await test.step('Open keybindings settings', async () => {
|
||||
// Open the settings modal with the browser keyboard shortcut
|
||||
await page.keyboard.press('ControlOrMeta+Shift+,')
|
||||
|
||||
// Go to Keybindings tab.
|
||||
const keybindingsTab = page.getByRole('radio', { name: 'Keybindings' })
|
||||
await keybindingsTab.click()
|
||||
})
|
||||
|
||||
// Go to the hotkey for Command Palette.
|
||||
const commandPalette = page.getByText('Toggle Command Palette')
|
||||
await commandPalette.scrollIntoViewIfNeeded()
|
||||
|
||||
// The heading is above it and should be in view now.
|
||||
const commandPaletteHeading = page.getByRole('heading', {
|
||||
name: 'Command Palette',
|
||||
})
|
||||
// The hotkey is in a kbd element next to the heading.
|
||||
const hotkey = commandPaletteHeading.locator('+ div kbd')
|
||||
const text = process.platform === 'darwin' ? 'Command+K' : 'Control+K'
|
||||
await expect(hotkey).toHaveText(text)
|
||||
})
|
||||
|
||||
test('Project and user settings can be reset', async ({ page }) => {
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
@ -203,10 +240,11 @@ test.describe('Testing settings', () => {
|
||||
const { electronApp, page } = await setupElectron({
|
||||
testInfo,
|
||||
folderSetupFn: async (dir) => {
|
||||
await fsp.mkdir(`${dir}/bracket`, { recursive: true })
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await fsp.copyFile(
|
||||
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
|
||||
`${dir}/bracket/main.kcl`
|
||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
||||
join(bracketDir, 'main.kcl')
|
||||
)
|
||||
},
|
||||
})
|
||||
|
@ -26,7 +26,7 @@
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.19",
|
||||
"@headlessui/tailwindcss": "^0.2.0",
|
||||
"@kittycad/lib": "^2.0.0",
|
||||
"@kittycad/lib": "^2.0.1",
|
||||
"@lezer/highlight": "^1.2.1",
|
||||
"@lezer/lr": "^1.4.1",
|
||||
"@react-hook/resize-observer": "^2.0.1",
|
||||
@ -119,7 +119,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@babel/preset-env": "^7.24.3",
|
||||
"@babel/preset-env": "^7.25.4",
|
||||
"@electron-forge/cli": "^7.4.0",
|
||||
"@electron-forge/maker-deb": "^7.4.0",
|
||||
"@electron-forge/maker-rpm": "^7.4.0",
|
||||
|
@ -9,6 +9,8 @@ import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||
import { CustomIcon } from 'components/CustomIcon'
|
||||
import Tooltip from 'components/Tooltip'
|
||||
|
||||
export const COMMAND_PALETTE_HOTKEY = 'mod+k'
|
||||
|
||||
export const CommandBar = () => {
|
||||
const { pathname } = useLocation()
|
||||
const { commandBarState, commandBarSend } = useCommandsContext()
|
||||
@ -24,7 +26,7 @@ export const CommandBar = () => {
|
||||
}, [pathname])
|
||||
|
||||
// Hook up keyboard shortcuts
|
||||
useHotkeyWrapper(['mod+k'], () => {
|
||||
useHotkeyWrapper([COMMAND_PALETTE_HOTKEY], () => {
|
||||
if (commandBarState.context.commands.length === 0) return
|
||||
if (commandBarState.matches('Closed')) {
|
||||
commandBarSend({ type: 'Open' })
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||
import usePlatform from 'hooks/usePlatform'
|
||||
import { hotkeyDisplay } from 'lib/hotkeyWrapper'
|
||||
import { COMMAND_PALETTE_HOTKEY } from './CommandBar/CommandBar'
|
||||
|
||||
export function CommandBarOpenButton() {
|
||||
const { commandBarSend } = useCommandsContext()
|
||||
@ -12,7 +14,7 @@ export function CommandBarOpenButton() {
|
||||
>
|
||||
<span>Commands</span>
|
||||
<kbd className="bg-primary/10 dark:bg-chalkboard-80 dark:group-hover:bg-primary font-mono rounded-sm dark:text-inherit inline-block px-1 border-primary dark:border-chalkboard-90">
|
||||
{platform === 'macos' ? '⌘K' : '^/'}
|
||||
{hotkeyDisplay(COMMAND_PALETTE_HOTKEY, platform)}
|
||||
</kbd>
|
||||
</button>
|
||||
)
|
||||
|
@ -9,7 +9,7 @@ import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
|
||||
import { coreDump } from 'lang/wasm'
|
||||
import toast from 'react-hot-toast'
|
||||
import { CoreDumpManager } from 'lib/coredump'
|
||||
import openWindow from 'lib/openWindow'
|
||||
import openWindow, { openExternalBrowserIfDesktop } from 'lib/openWindow'
|
||||
import { NetworkMachineIndicator } from './NetworkMachineIndicator'
|
||||
|
||||
export function LowerRightControls({
|
||||
@ -66,6 +66,9 @@ export function LowerRightControls({
|
||||
{children}
|
||||
<menu className="flex items-center justify-end gap-3 pointer-events-auto">
|
||||
<a
|
||||
onClick={openExternalBrowserIfDesktop(
|
||||
`https://github.com/KittyCAD/modeling-app/releases/tag/v${APP_VERSION}`
|
||||
)}
|
||||
href={`https://github.com/KittyCAD/modeling-app/releases/tag/v${APP_VERSION}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
35
src/lib/hotkeyWrapper.test.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { hotkeyDisplay } from './hotkeyWrapper'
|
||||
|
||||
describe('hotkeyDisplay', () => {
|
||||
it('displays mod', async () => {
|
||||
expect(hotkeyDisplay('mod+c', 'macos')).toEqual('⌘C')
|
||||
expect(hotkeyDisplay('mod+c', 'windows')).toEqual('Ctrl+C')
|
||||
expect(hotkeyDisplay('mod+c', 'linux')).toEqual('Ctrl+C')
|
||||
})
|
||||
it('displays shift', async () => {
|
||||
expect(hotkeyDisplay('shift+c', 'macos')).toEqual('⬆C')
|
||||
expect(hotkeyDisplay('shift+c', 'windows')).toEqual('Shift+C')
|
||||
expect(hotkeyDisplay('shift+c', 'linux')).toEqual('Shift+C')
|
||||
})
|
||||
it('displays meta', async () => {
|
||||
expect(hotkeyDisplay('meta+c', 'macos')).toEqual('⌘C')
|
||||
expect(hotkeyDisplay('meta+c', 'windows')).toEqual('Win+C')
|
||||
// That's correct. What browsers call meta is actually super.
|
||||
expect(hotkeyDisplay('meta+c', 'linux')).toEqual('Super+C')
|
||||
})
|
||||
it('displays alt', async () => {
|
||||
expect(hotkeyDisplay('alt+c', 'macos')).toEqual('⌥C')
|
||||
expect(hotkeyDisplay('alt+c', 'windows')).toEqual('Alt+C')
|
||||
expect(hotkeyDisplay('alt+c', 'linux')).toEqual('Alt+C')
|
||||
})
|
||||
it('displays ctrl', async () => {
|
||||
expect(hotkeyDisplay('ctrl+c', 'macos')).toEqual('^C')
|
||||
expect(hotkeyDisplay('ctrl+c', 'windows')).toEqual('Ctrl+C')
|
||||
expect(hotkeyDisplay('ctrl+c', 'linux')).toEqual('Ctrl+C')
|
||||
})
|
||||
it('displays multiple modifiers', async () => {
|
||||
expect(hotkeyDisplay('shift+alt+ctrl+c', 'windows')).toEqual(
|
||||
'Shift+Alt+Ctrl+C'
|
||||
)
|
||||
})
|
||||
})
|
@ -1,9 +1,10 @@
|
||||
import { Options, useHotkeys } from 'react-hotkeys-hook'
|
||||
import { useEffect } from 'react'
|
||||
import { codeManager } from './singletons'
|
||||
import { Platform } from './utils'
|
||||
|
||||
// Hotkey wrapper wraps hotkeys for the app (outside of the editor)
|
||||
// With hotkeys inside the editor.
|
||||
// with hotkeys inside the editor.
|
||||
// This way we can have hotkeys defined in one place and not have to worry about
|
||||
// conflicting hotkeys, or them only being implemented for the app but not
|
||||
// inside the editor.
|
||||
@ -37,3 +38,48 @@ function mapHotkeyToCodeMirrorHotkey(hotkey: string): string {
|
||||
.replaceAll('shift', 'Shift')
|
||||
.replaceAll('alt', 'Alt')
|
||||
}
|
||||
|
||||
const LOWER_CASE_LETTER = /[a-z]/
|
||||
const WHITESPACE = /\s+/g
|
||||
|
||||
/**
|
||||
* Convert hotkey to display text.
|
||||
*
|
||||
* TODO: We should handle capitalized single letter hotkeys like K as Shift+K,
|
||||
* but we don't.
|
||||
*/
|
||||
export function hotkeyDisplay(hotkey: string, platform: Platform): string {
|
||||
const isMac = platform === 'macos'
|
||||
const isWindows = platform === 'windows'
|
||||
// Browsers call it metaKey, but that's a misnomer.
|
||||
const meta = isWindows ? 'Win' : 'Super'
|
||||
const outputSeparator = isMac ? '' : '+'
|
||||
const display = hotkey
|
||||
// Capitalize letters. We want Ctrl+K, not Ctrl+k, since Shift should be
|
||||
// shown as a separate modifier.
|
||||
.split('+')
|
||||
.map((word) => {
|
||||
if (word.length === 1 && LOWER_CASE_LETTER.test(word)) {
|
||||
return word.toUpperCase()
|
||||
}
|
||||
return word
|
||||
})
|
||||
.join(outputSeparator)
|
||||
// Collapse multiple spaces into one.
|
||||
.replaceAll(WHITESPACE, ' ')
|
||||
.replaceAll('mod', isMac ? '⌘' : 'Ctrl')
|
||||
.replaceAll('meta', isMac ? '⌘' : meta)
|
||||
// This is technically the wrong arrow for control, but it's more visible
|
||||
// and recognizable. May want to change this in the future.
|
||||
//
|
||||
// The correct arrow is ⌃ "UP ARROWHEAD" Unicode: U+2303
|
||||
.replaceAll('ctrl', isMac ? '^' : 'Ctrl')
|
||||
// This is technically the wrong arrow for shift, but it's more visible and
|
||||
// recognizable. May want to change this in the future.
|
||||
//
|
||||
// The correct arrow is ⇧ "UPWARDS WHITE ARROW" Unicode: U+21E7
|
||||
.replaceAll('shift', isMac ? '⬆' : 'Shift')
|
||||
.replaceAll('alt', isMac ? '⌥' : 'Alt')
|
||||
|
||||
return display
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ export const interactionMap: Record<
|
||||
name: 'toggle-command-palette',
|
||||
sequence: `${PRIMARY}+K`,
|
||||
title: 'Toggle Command Palette',
|
||||
description: 'Always available. Use Ctrl+/ on Windows/Linux.',
|
||||
description: 'Always available.',
|
||||
},
|
||||
],
|
||||
Panes: [
|
||||
|
@ -151,6 +151,32 @@ export function platform(): Platform {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
// navigator.platform is deprecated, but many browsers still support it, and
|
||||
// it's more accurate than userAgent and userAgentData in Playwright.
|
||||
if (
|
||||
navigator.platform?.indexOf('Mac') === 0 ||
|
||||
navigator.platform === 'iPhone'
|
||||
) {
|
||||
return 'macos'
|
||||
}
|
||||
if (navigator.platform === 'Win32') {
|
||||
return 'windows'
|
||||
}
|
||||
|
||||
// Chrome only, but more accurate than userAgent.
|
||||
let userAgentDataPlatform: unknown
|
||||
if (
|
||||
'userAgentData' in navigator &&
|
||||
navigator.userAgentData &&
|
||||
typeof navigator.userAgentData === 'object' &&
|
||||
'platform' in navigator.userAgentData
|
||||
) {
|
||||
userAgentDataPlatform = navigator.userAgentData.platform
|
||||
if (userAgentDataPlatform === 'macOS') return 'macos'
|
||||
if (userAgentDataPlatform === 'Windows') return 'windows'
|
||||
}
|
||||
|
||||
if (navigator.userAgent.indexOf('Mac') !== -1) {
|
||||
return 'macos'
|
||||
} else if (navigator.userAgent.indexOf('Win') !== -1) {
|
||||
@ -158,7 +184,12 @@ export function platform(): Platform {
|
||||
} else if (navigator.userAgent.indexOf('Linux') !== -1) {
|
||||
return 'linux'
|
||||
}
|
||||
console.error('Unknown platform userAgent:', navigator.userAgent)
|
||||
console.error(
|
||||
'Unknown platform userAgent:',
|
||||
navigator.platform,
|
||||
userAgentDataPlatform,
|
||||
navigator.userAgent
|
||||
)
|
||||
return ''
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@ import usePlatform from 'hooks/usePlatform'
|
||||
import { OnboardingButtons, kbdClasses, useDismiss, useNextClick } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
import { hotkeyDisplay } from 'lib/hotkeyWrapper'
|
||||
import { COMMAND_PALETTE_HOTKEY } from 'components/CommandBar/CommandBar'
|
||||
|
||||
export default function CmdK() {
|
||||
const { context } = useModelingContext()
|
||||
@ -20,15 +22,9 @@ export default function CmdK() {
|
||||
<h2 className="text-2xl font-bold">Command Bar</h2>
|
||||
<p className="my-4">
|
||||
Press{' '}
|
||||
{platformName === 'macos' ? (
|
||||
<>
|
||||
<kbd className={kbdClasses}>⌘K</kbd>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<kbd className={kbdClasses}>Ctrl + /</kbd>
|
||||
</>
|
||||
)}{' '}
|
||||
<kbd className={kbdClasses}>
|
||||
{hotkeyDisplay(COMMAND_PALETTE_HOTKEY, platformName)}
|
||||
</kbd>{' '}
|
||||
to open the command bar. Try changing your theme with it.
|
||||
</p>
|
||||
<p className="my-4">
|
||||
|
16
src/wasm-lib/Cargo.lock
generated
@ -724,7 +724,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive-docs"
|
||||
version = "0.1.24"
|
||||
version = "0.1.25"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
@ -1397,7 +1397,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.7"
|
||||
version = "0.2.10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx",
|
||||
@ -1469,7 +1469,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper",
|
||||
@ -1482,9 +1482,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kittycad"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a9621df809fa105ae28b01586c52ce46561e166702babb50e5bcc5097a8ce62"
|
||||
checksum = "fbb7c076d64ad00a29ae900108707d1bbb583944d4b2d005e1eca9914a18c7c2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1870,7 +1870,7 @@ dependencies = [
|
||||
"bincode",
|
||||
"either",
|
||||
"fnv",
|
||||
"itertools 0.12.1",
|
||||
"itertools 0.10.5",
|
||||
"lazy_static",
|
||||
"nom",
|
||||
"quick-xml",
|
||||
@ -2096,9 +2096,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -71,7 +71,7 @@ members = [
|
||||
|
||||
[workspace.dependencies]
|
||||
http = "0.2.12"
|
||||
kittycad = { version = "0.3.16", default-features = false, features = ["js", "requests"] }
|
||||
kittycad = { version = "0.3.17", default-features = false, features = ["js", "requests"] }
|
||||
kittycad-modeling-session = "0.1.4"
|
||||
|
||||
[[test]]
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.24"
|
||||
version = "0.1.25"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-test-server"
|
||||
description = "A test server for KCL"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.7"
|
||||
version = "0.2.10"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -9,7 +9,7 @@ use std::{
|
||||
use anyhow::{anyhow, Result};
|
||||
use dashmap::DashMap;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use kittycad::types::{WebSocketRequest, WebSocketResponse};
|
||||
use kittycad::types::{ModelingSessionData, WebSocketRequest, WebSocketResponse};
|
||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
||||
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
||||
|
||||
@ -27,10 +27,10 @@ enum SocketHealth {
|
||||
|
||||
type WebSocketTcpWrite = futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>;
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)] // for the TcpReadHandle
|
||||
pub struct EngineConnection {
|
||||
engine_req_tx: mpsc::Sender<ToEngineReq>,
|
||||
responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>,
|
||||
#[allow(dead_code)]
|
||||
tcp_read_handle: Arc<TcpReadHandle>,
|
||||
socket_health: Arc<Mutex<SocketHealth>>,
|
||||
batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>,
|
||||
@ -38,6 +38,8 @@ pub struct EngineConnection {
|
||||
|
||||
/// The default planes for the scene.
|
||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||
/// If the server sends session data, it'll be copied to here.
|
||||
session_data: Arc<Mutex<Option<ModelingSessionData>>>,
|
||||
}
|
||||
|
||||
pub struct TcpRead {
|
||||
@ -181,6 +183,8 @@ impl EngineConnection {
|
||||
|
||||
let mut tcp_read = TcpRead { stream: tcp_read };
|
||||
|
||||
let session_data: Arc<Mutex<Option<ModelingSessionData>>> = Arc::new(Mutex::new(None));
|
||||
let session_data2 = session_data.clone();
|
||||
let responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>> = Arc::new(DashMap::new());
|
||||
let responses_clone = responses.clone();
|
||||
let socket_health = Arc::new(Mutex::new(SocketHealth::Active));
|
||||
@ -192,35 +196,40 @@ impl EngineConnection {
|
||||
match tcp_read.read().await {
|
||||
Ok(ws_resp) => {
|
||||
// If we got a batch response, add all the inner responses.
|
||||
if let Some(kittycad::types::OkWebSocketResponseData::ModelingBatch { responses }) =
|
||||
&ws_resp.resp
|
||||
{
|
||||
for (resp_id, batch_response) in responses {
|
||||
let id: uuid::Uuid = resp_id.parse().unwrap();
|
||||
if let Some(response) = &batch_response.response {
|
||||
responses_clone.insert(
|
||||
id,
|
||||
kittycad::types::WebSocketResponse {
|
||||
request_id: Some(id),
|
||||
resp: Some(kittycad::types::OkWebSocketResponseData::Modeling {
|
||||
modeling_response: response.clone(),
|
||||
}),
|
||||
errors: None,
|
||||
success: Some(true),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
responses_clone.insert(
|
||||
id,
|
||||
kittycad::types::WebSocketResponse {
|
||||
request_id: Some(id),
|
||||
resp: None,
|
||||
errors: batch_response.errors.clone(),
|
||||
success: Some(false),
|
||||
},
|
||||
);
|
||||
match &ws_resp.resp {
|
||||
Some(kittycad::types::OkWebSocketResponseData::ModelingBatch { responses }) => {
|
||||
for (resp_id, batch_response) in responses {
|
||||
let id: uuid::Uuid = resp_id.parse().unwrap();
|
||||
if let Some(response) = &batch_response.response {
|
||||
responses_clone.insert(
|
||||
id,
|
||||
kittycad::types::WebSocketResponse {
|
||||
request_id: Some(id),
|
||||
resp: Some(kittycad::types::OkWebSocketResponseData::Modeling {
|
||||
modeling_response: response.clone(),
|
||||
}),
|
||||
errors: None,
|
||||
success: Some(true),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
responses_clone.insert(
|
||||
id,
|
||||
kittycad::types::WebSocketResponse {
|
||||
request_id: Some(id),
|
||||
resp: None,
|
||||
errors: batch_response.errors.clone(),
|
||||
success: Some(false),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(kittycad::types::OkWebSocketResponseData::ModelingSessionData { session }) => {
|
||||
let mut sd = session_data2.lock().unwrap();
|
||||
sd.replace(session.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(id) = ws_resp.request_id {
|
||||
@ -249,6 +258,7 @@ impl EngineConnection {
|
||||
batch: Arc::new(Mutex::new(Vec::new())),
|
||||
batch_end: Arc::new(Mutex::new(HashMap::new())),
|
||||
default_planes: Default::default(),
|
||||
session_data,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -345,4 +355,8 @@ impl EngineManager for EngineConnection {
|
||||
source_ranges: vec![source_range],
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_session_data(&self) -> Option<ModelingSessionData> {
|
||||
self.session_data.lock().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ use std::{
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use kittycad::types::{Color, ModelingCmd, ModelingCmdReq, OkWebSocketResponseData, WebSocketRequest};
|
||||
use kittycad::types::{
|
||||
Color, ModelingCmd, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -490,6 +492,12 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get session data, if it has been received.
|
||||
/// Returns None if the server never sent it.
|
||||
fn get_session_data(&self) -> Option<ModelingSessionData> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, Eq, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
|
@ -4,6 +4,7 @@ use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use async_recursion::async_recursion;
|
||||
use kittycad::types::ModelingSessionData;
|
||||
use parse_display::{Display, FromStr};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -1613,8 +1614,11 @@ pub struct ExecutorSettings {
|
||||
pub highlight_edges: bool,
|
||||
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
|
||||
pub enable_ssao: bool,
|
||||
// Show grid?
|
||||
/// Show grid?
|
||||
pub show_grid: bool,
|
||||
/// Should engine store this for replay?
|
||||
/// If so, under what name?
|
||||
pub replay: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for ExecutorSettings {
|
||||
@ -1624,6 +1628,7 @@ impl Default for ExecutorSettings {
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
replay: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1635,6 +1640,7 @@ impl From<crate::settings::types::Configuration> for ExecutorSettings {
|
||||
highlight_edges: config.settings.modeling.highlight_edges.into(),
|
||||
enable_ssao: config.settings.modeling.enable_ssao.into(),
|
||||
show_grid: config.settings.modeling.show_scale_grid,
|
||||
replay: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1646,6 +1652,7 @@ impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSet
|
||||
highlight_edges: config.settings.modeling.highlight_edges.into(),
|
||||
enable_ssao: config.settings.modeling.enable_ssao.into(),
|
||||
show_grid: config.settings.modeling.show_scale_grid,
|
||||
replay: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1657,6 +1664,7 @@ impl From<crate::settings::types::ModelingSettings> for ExecutorSettings {
|
||||
highlight_edges: modeling.highlight_edges.into(),
|
||||
enable_ssao: modeling.enable_ssao.into(),
|
||||
show_grid: modeling.show_scale_grid,
|
||||
replay: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1665,11 +1673,8 @@ impl ExecutorContext {
|
||||
/// Create a new default executor context.
|
||||
/// Also returns the response HTTP headers from the server.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn new_with_headers(
|
||||
client: &kittycad::Client,
|
||||
settings: ExecutorSettings,
|
||||
) -> Result<(Self, http::HeaderMap)> {
|
||||
let (ws, headers) = client
|
||||
pub async fn new(client: &kittycad::Client, settings: ExecutorSettings) -> Result<Self> {
|
||||
let (ws, _headers) = client
|
||||
.modeling()
|
||||
.commands_ws(
|
||||
None,
|
||||
@ -1679,6 +1684,7 @@ impl ExecutorContext {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
settings.replay.clone(),
|
||||
if settings.show_grid { Some(true) } else { None },
|
||||
None,
|
||||
None,
|
||||
@ -1701,21 +1707,13 @@ impl ExecutorContext {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let slf = Self {
|
||||
Ok(Self {
|
||||
engine,
|
||||
fs: Arc::new(FileManager::new()),
|
||||
stdlib: Arc::new(StdLib::new()),
|
||||
settings,
|
||||
is_mock: false,
|
||||
};
|
||||
Ok((slf, headers))
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
/// Create a new default executor context.
|
||||
pub async fn new(client: &kittycad::Client, settings: ExecutorSettings) -> Result<Self> {
|
||||
let (slf, _headers) = Self::new_with_headers(client, settings).await?;
|
||||
Ok(slf)
|
||||
})
|
||||
}
|
||||
|
||||
/// For executing unit tests.
|
||||
@ -1755,6 +1753,7 @@ impl ExecutorContext {
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
replay: None,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
@ -1774,6 +1773,16 @@ impl ExecutorContext {
|
||||
program: &crate::ast::types::Program,
|
||||
memory: Option<ProgramMemory>,
|
||||
) -> Result<ProgramMemory, KclError> {
|
||||
self.run_with_session_data(program, memory).await.map(|x| x.0)
|
||||
}
|
||||
/// Perform the execution of a program.
|
||||
/// You can optionally pass in some initialization memory.
|
||||
/// Kurt uses this for partial execution.
|
||||
pub async fn run_with_session_data(
|
||||
&self,
|
||||
program: &crate::ast::types::Program,
|
||||
memory: Option<ProgramMemory>,
|
||||
) -> Result<(ProgramMemory, Option<ModelingSessionData>), KclError> {
|
||||
// Before we even start executing the program, set the units.
|
||||
self.engine
|
||||
.batch_modeling_cmd(
|
||||
@ -1790,13 +1799,16 @@ impl ExecutorContext {
|
||||
Default::default()
|
||||
};
|
||||
let mut dynamic_state = DynamicState::default();
|
||||
self.inner_execute(
|
||||
program,
|
||||
&mut memory,
|
||||
&mut dynamic_state,
|
||||
crate::executor::BodyType::Root,
|
||||
)
|
||||
.await
|
||||
let final_memory = self
|
||||
.inner_execute(
|
||||
program,
|
||||
&mut memory,
|
||||
&mut dynamic_state,
|
||||
crate::executor::BodyType::Root,
|
||||
)
|
||||
.await?;
|
||||
let session_data = self.engine.get_session_data();
|
||||
Ok((final_memory, session_data))
|
||||
}
|
||||
|
||||
/// Execute an AST's program.
|
||||
|
@ -95,6 +95,7 @@ lazy_static! {
|
||||
Box::new(crate::std::fillet::GetPreviousAdjacentEdge),
|
||||
Box::new(crate::std::helix::Helix),
|
||||
Box::new(crate::std::shell::Shell),
|
||||
Box::new(crate::std::shell::Hollow),
|
||||
Box::new(crate::std::revolve::Revolve),
|
||||
Box::new(crate::std::import::Import),
|
||||
Box::new(crate::std::math::Cos),
|
||||
|
@ -129,3 +129,64 @@ async fn inner_shell(
|
||||
|
||||
Ok(extrude_group)
|
||||
}
|
||||
|
||||
/// Make the inside of a 3D object hollow.
|
||||
pub async fn hollow(args: Args) -> Result<KclValue, KclError> {
|
||||
let (thickness, extrude_group): (f64, Box<ExtrudeGroup>) = args.get_data_and_extrude_group()?;
|
||||
|
||||
let extrude_group = inner_hollow(thickness, extrude_group, args).await?;
|
||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||
}
|
||||
|
||||
/// Make the inside of a 3D object hollow.
|
||||
///
|
||||
/// Remove volume from a 3-dimensional shape such that a wall of the
|
||||
/// provided thickness remains around the exterior of the shape.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const firstSketch = startSketchOn('XY')
|
||||
/// |> startProfileAt([-12, 12], %)
|
||||
/// |> line([24, 0], %)
|
||||
/// |> line([0, -24], %)
|
||||
/// |> line([-24, 0], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(6, %)
|
||||
/// |> hollow (0.25, %)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// const firstSketch = startSketchOn('-XZ')
|
||||
/// |> startProfileAt([-12, 12], %)
|
||||
/// |> line([24, 0], %)
|
||||
/// |> line([0, -24], %)
|
||||
/// |> line([-24, 0], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(6, %)
|
||||
/// |> hollow (0.5, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "hollow",
|
||||
}]
|
||||
async fn inner_hollow(
|
||||
thickness: f64,
|
||||
extrude_group: Box<ExtrudeGroup>,
|
||||
args: Args,
|
||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||
// Flush the batch for our fillets/chamfers if there are any.
|
||||
// If we do not do these for sketch on face, things will fail with face does not exist.
|
||||
args.flush_batch_for_extrude_group_set(extrude_group.clone().into())
|
||||
.await?;
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
ModelingCmd::Solid3DShellFace {
|
||||
hollow: true,
|
||||
face_ids: Vec::new(), // This is empty because we want to hollow the entire object.
|
||||
object_id: extrude_group.id,
|
||||
shell_thickness: thickness,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(extrude_group)
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ async fn new_context(units: UnitLength) -> anyhow::Result<ExecutorContext> {
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
replay: None,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
BIN
src/wasm-lib/kcl/tests/outputs/serial_test_example_hollow0.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
src/wasm-lib/kcl/tests/outputs/serial_test_example_hollow1.png
Normal file
After Width: | Height: | Size: 96 KiB |
196
yarn.lock
@ -28,10 +28,10 @@
|
||||
"@babel/highlight" "^7.24.7"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.2.tgz#e41928bd33475305c586f6acbbb7e3ade7a6f7f5"
|
||||
integrity sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==
|
||||
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2", "@babel/compat-data@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb"
|
||||
integrity sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==
|
||||
|
||||
"@babel/core@^7.16.0", "@babel/core@^7.21.4", "@babel/core@^7.24.5":
|
||||
version "7.25.2"
|
||||
@ -73,6 +73,16 @@
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.4.tgz#1dc63c1c9caae9e6dc24e264eac254eb25005669"
|
||||
integrity sha512-NFtZmZsyzDPJnk9Zg3BbTfKKc9UlHYzD0E//p2Z3B9nCwwtJW9T0gVbCz8+fBngnn4zf1Dr3IK8PHQQHq0lDQw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.25.4"
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab"
|
||||
@ -112,7 +122,20 @@
|
||||
"@babel/traverse" "^7.25.0"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.0":
|
||||
"@babel/helper-create-class-features-plugin@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz#57eaf1af38be4224a9d9dd01ddde05b741f50e14"
|
||||
integrity sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.24.7"
|
||||
"@babel/helper-member-expression-to-functions" "^7.24.8"
|
||||
"@babel/helper-optimise-call-expression" "^7.24.7"
|
||||
"@babel/helper-replace-supers" "^7.25.0"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.24.7"
|
||||
"@babel/traverse" "^7.25.4"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.0", "@babel/helper-create-regexp-features-plugin@^7.25.2":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz#24c75974ed74183797ffd5f134169316cd1808d9"
|
||||
integrity sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==
|
||||
@ -121,7 +144,7 @@
|
||||
regexpu-core "^5.3.1"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2":
|
||||
"@babel/helper-define-polyfill-provider@^0.6.2":
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d"
|
||||
integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==
|
||||
@ -253,6 +276,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.25.2"
|
||||
|
||||
"@babel/parser@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.4.tgz#af4f2df7d02440286b7de57b1c21acfb2a6f257a"
|
||||
integrity sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.25.4"
|
||||
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3":
|
||||
version "7.25.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz#dca427b45a6c0f5c095a1c639dfe2476a3daba7f"
|
||||
@ -519,15 +549,15 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
|
||||
"@babel/plugin-transform-async-generator-functions@^7.25.0":
|
||||
version "7.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz#b785cf35d73437f6276b1e30439a57a50747bddf"
|
||||
integrity sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==
|
||||
"@babel/plugin-transform-async-generator-functions@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz#2afd4e639e2d055776c9f091b6c0c180ed8cf083"
|
||||
integrity sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
"@babel/helper-remap-async-to-generator" "^7.25.0"
|
||||
"@babel/plugin-syntax-async-generators" "^7.8.4"
|
||||
"@babel/traverse" "^7.25.0"
|
||||
"@babel/traverse" "^7.25.4"
|
||||
|
||||
"@babel/plugin-transform-async-to-generator@^7.24.7":
|
||||
version "7.24.7"
|
||||
@ -552,13 +582,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
|
||||
"@babel/plugin-transform-class-properties@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834"
|
||||
integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==
|
||||
"@babel/plugin-transform-class-properties@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz#bae7dbfcdcc2e8667355cd1fb5eda298f05189fd"
|
||||
integrity sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.24.7"
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
"@babel/helper-create-class-features-plugin" "^7.25.4"
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
|
||||
"@babel/plugin-transform-class-static-block@^7.24.7":
|
||||
version "7.24.7"
|
||||
@ -569,16 +599,16 @@
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
"@babel/plugin-syntax-class-static-block" "^7.14.5"
|
||||
|
||||
"@babel/plugin-transform-classes@^7.25.0":
|
||||
version "7.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz#63122366527d88e0ef61b612554fe3f8c793991e"
|
||||
integrity sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==
|
||||
"@babel/plugin-transform-classes@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz#d29dbb6a72d79f359952ad0b66d88518d65ef89a"
|
||||
integrity sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.24.7"
|
||||
"@babel/helper-compilation-targets" "^7.24.8"
|
||||
"@babel/helper-compilation-targets" "^7.25.2"
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
"@babel/helper-replace-supers" "^7.25.0"
|
||||
"@babel/traverse" "^7.25.0"
|
||||
"@babel/traverse" "^7.25.4"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/plugin-transform-computed-properties@^7.24.7":
|
||||
@ -806,13 +836,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
|
||||
"@babel/plugin-transform-private-methods@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e"
|
||||
integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==
|
||||
"@babel/plugin-transform-private-methods@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz#9bbefbe3649f470d681997e0b64a4b254d877242"
|
||||
integrity sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.24.7"
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
"@babel/helper-create-class-features-plugin" "^7.25.4"
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
|
||||
"@babel/plugin-transform-private-property-in-object@^7.24.7":
|
||||
version "7.24.7"
|
||||
@ -975,20 +1005,20 @@
|
||||
"@babel/helper-create-regexp-features-plugin" "^7.24.7"
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
|
||||
"@babel/plugin-transform-unicode-sets-regex@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9"
|
||||
integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==
|
||||
"@babel/plugin-transform-unicode-sets-regex@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz#be664c2a0697ffacd3423595d5edef6049e8946c"
|
||||
integrity sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==
|
||||
dependencies:
|
||||
"@babel/helper-create-regexp-features-plugin" "^7.24.7"
|
||||
"@babel/helper-plugin-utils" "^7.24.7"
|
||||
"@babel/helper-create-regexp-features-plugin" "^7.25.2"
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
|
||||
"@babel/preset-env@^7.16.4", "@babel/preset-env@^7.24.3":
|
||||
version "7.25.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.25.3.tgz#0bf4769d84ac51d1073ab4a86f00f30a3a83c67c"
|
||||
integrity sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==
|
||||
"@babel/preset-env@^7.16.4", "@babel/preset-env@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.25.4.tgz#be23043d43a34a2721cd0f676c7ba6f1481f6af6"
|
||||
integrity sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.25.2"
|
||||
"@babel/compat-data" "^7.25.4"
|
||||
"@babel/helper-compilation-targets" "^7.25.2"
|
||||
"@babel/helper-plugin-utils" "^7.24.8"
|
||||
"@babel/helper-validator-option" "^7.24.8"
|
||||
@ -1017,13 +1047,13 @@
|
||||
"@babel/plugin-syntax-top-level-await" "^7.14.5"
|
||||
"@babel/plugin-syntax-unicode-sets-regex" "^7.18.6"
|
||||
"@babel/plugin-transform-arrow-functions" "^7.24.7"
|
||||
"@babel/plugin-transform-async-generator-functions" "^7.25.0"
|
||||
"@babel/plugin-transform-async-generator-functions" "^7.25.4"
|
||||
"@babel/plugin-transform-async-to-generator" "^7.24.7"
|
||||
"@babel/plugin-transform-block-scoped-functions" "^7.24.7"
|
||||
"@babel/plugin-transform-block-scoping" "^7.25.0"
|
||||
"@babel/plugin-transform-class-properties" "^7.24.7"
|
||||
"@babel/plugin-transform-class-properties" "^7.25.4"
|
||||
"@babel/plugin-transform-class-static-block" "^7.24.7"
|
||||
"@babel/plugin-transform-classes" "^7.25.0"
|
||||
"@babel/plugin-transform-classes" "^7.25.4"
|
||||
"@babel/plugin-transform-computed-properties" "^7.24.7"
|
||||
"@babel/plugin-transform-destructuring" "^7.24.8"
|
||||
"@babel/plugin-transform-dotall-regex" "^7.24.7"
|
||||
@ -1051,7 +1081,7 @@
|
||||
"@babel/plugin-transform-optional-catch-binding" "^7.24.7"
|
||||
"@babel/plugin-transform-optional-chaining" "^7.24.8"
|
||||
"@babel/plugin-transform-parameters" "^7.24.7"
|
||||
"@babel/plugin-transform-private-methods" "^7.24.7"
|
||||
"@babel/plugin-transform-private-methods" "^7.25.4"
|
||||
"@babel/plugin-transform-private-property-in-object" "^7.24.7"
|
||||
"@babel/plugin-transform-property-literals" "^7.24.7"
|
||||
"@babel/plugin-transform-regenerator" "^7.24.7"
|
||||
@ -1064,10 +1094,10 @@
|
||||
"@babel/plugin-transform-unicode-escapes" "^7.24.7"
|
||||
"@babel/plugin-transform-unicode-property-regex" "^7.24.7"
|
||||
"@babel/plugin-transform-unicode-regex" "^7.24.7"
|
||||
"@babel/plugin-transform-unicode-sets-regex" "^7.24.7"
|
||||
"@babel/plugin-transform-unicode-sets-regex" "^7.25.4"
|
||||
"@babel/preset-modules" "0.1.6-no-external-plugins"
|
||||
babel-plugin-polyfill-corejs2 "^0.4.10"
|
||||
babel-plugin-polyfill-corejs3 "^0.10.4"
|
||||
babel-plugin-polyfill-corejs3 "^0.10.6"
|
||||
babel-plugin-polyfill-regenerator "^0.6.1"
|
||||
core-js-compat "^3.37.1"
|
||||
semver "^6.3.1"
|
||||
@ -1138,6 +1168,19 @@
|
||||
debug "^4.3.1"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/traverse@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.4.tgz#648678046990f2957407e3086e97044f13c3e18e"
|
||||
integrity sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.24.7"
|
||||
"@babel/generator" "^7.25.4"
|
||||
"@babel/parser" "^7.25.4"
|
||||
"@babel/template" "^7.25.0"
|
||||
"@babel/types" "^7.25.4"
|
||||
debug "^4.3.1"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.21.4", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.4.4":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.2.tgz#55fb231f7dc958cd69ea141a4c2997e819646125"
|
||||
@ -1147,6 +1190,15 @@
|
||||
"@babel/helper-validator-identifier" "^7.24.7"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.4.tgz#6bcb46c72fdf1012a209d016c07f769e10adcb5f"
|
||||
integrity sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.24.8"
|
||||
"@babel/helper-validator-identifier" "^7.24.7"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.17.0":
|
||||
version "6.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz#24ff5fc37fd91f6439df6f4ff9c8e910cde1b053"
|
||||
@ -1971,10 +2023,10 @@
|
||||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@kittycad/lib@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-2.0.0.tgz#c7808f47546f5b85371899b0b82989a4049d258d"
|
||||
integrity sha512-iJCifdt7C+gHCH7xomNhynUmhy4rvM+J3Skxm3vxJR+zMWludm1bSCd+LgUpgk6kZOvkHJ755Y0gfMDYz1IVxw==
|
||||
"@kittycad/lib@^2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-2.0.1.tgz#d3f1c80d9903452b0b9df378c72ed1e83b19a73d"
|
||||
integrity sha512-VYunezWS+cNZbdKfVkB3zg2YbDCQEb/AjzER85+yyDAlTU5PL4paQDpNlEI6icSglDGRUIR4Er/bRFj68r3UQg==
|
||||
dependencies:
|
||||
openapi-types "^12.0.0"
|
||||
ts-node "^10.9.1"
|
||||
@ -3220,13 +3272,13 @@ babel-plugin-polyfill-corejs2@^0.4.10:
|
||||
"@babel/helper-define-polyfill-provider" "^0.6.2"
|
||||
semver "^6.3.1"
|
||||
|
||||
babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4:
|
||||
version "0.10.4"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77"
|
||||
integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==
|
||||
babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.6:
|
||||
version "0.10.6"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7"
|
||||
integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==
|
||||
dependencies:
|
||||
"@babel/helper-define-polyfill-provider" "^0.6.1"
|
||||
core-js-compat "^3.36.1"
|
||||
"@babel/helper-define-polyfill-provider" "^0.6.2"
|
||||
core-js-compat "^3.38.0"
|
||||
|
||||
babel-plugin-polyfill-regenerator@^0.6.1:
|
||||
version "0.6.2"
|
||||
@ -3380,6 +3432,16 @@ browserslist@^4.23.0, browserslist@^4.23.1:
|
||||
node-releases "^2.0.14"
|
||||
update-browserslist-db "^1.1.0"
|
||||
|
||||
browserslist@^4.23.3:
|
||||
version "4.23.3"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800"
|
||||
integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001646"
|
||||
electron-to-chromium "^1.5.4"
|
||||
node-releases "^2.0.18"
|
||||
update-browserslist-db "^1.1.0"
|
||||
|
||||
buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
@ -3476,6 +3538,11 @@ caniuse-lite@^1.0.30001599, caniuse-lite@^1.0.30001640:
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001646.tgz#d472f2882259ba032dd73ee069ff01bfd059b25d"
|
||||
integrity sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==
|
||||
|
||||
caniuse-lite@^1.0.30001646:
|
||||
version "1.0.30001651"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz#52de59529e8b02b1aedcaaf5c05d9e23c0c28138"
|
||||
integrity sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==
|
||||
|
||||
chai@^4.3.10:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8"
|
||||
@ -3754,12 +3821,12 @@ cookie@0.6.0:
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
|
||||
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
|
||||
|
||||
core-js-compat@^3.36.1, core-js-compat@^3.37.1:
|
||||
version "3.37.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee"
|
||||
integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==
|
||||
core-js-compat@^3.37.1, core-js-compat@^3.38.0:
|
||||
version "3.38.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.38.1.tgz#2bc7a298746ca5a7bcb9c164bcb120f2ebc09a09"
|
||||
integrity sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==
|
||||
dependencies:
|
||||
browserslist "^4.23.0"
|
||||
browserslist "^4.23.3"
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
@ -4183,6 +4250,11 @@ electron-to-chromium@^1.4.820:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz#cd477c830dd6fca41fbd5465c1ff6ce08ac22343"
|
||||
integrity sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==
|
||||
|
||||
electron-to-chromium@^1.5.4:
|
||||
version "1.5.13"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6"
|
||||
integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==
|
||||
|
||||
electron-winstaller@^5.3.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-winstaller/-/electron-winstaller-5.4.0.tgz#f0660d476d5c4f579fdf7edd2f0cf01d54c4d0b2"
|
||||
@ -6731,7 +6803,7 @@ node-gyp@^9.0.0:
|
||||
tar "^6.1.2"
|
||||
which "^2.0.2"
|
||||
|
||||
node-releases@^2.0.14:
|
||||
node-releases@^2.0.14, node-releases@^2.0.18:
|
||||
version "2.0.18"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f"
|
||||
integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==
|
||||
|