Compare commits
1 Commits
more-sketc
...
franknoiro
Author | SHA1 | Date | |
---|---|---|---|
58b643cedd |
@ -1,298 +0,0 @@
|
|||||||
import type { Page, Locator } from '@playwright/test'
|
|
||||||
import { expect, test as base } from '@playwright/test'
|
|
||||||
import { getUtils, setup, tearDown } from './test-utils'
|
|
||||||
import fsp from 'fs/promises'
|
|
||||||
import { join } from 'path'
|
|
||||||
import { uuidv4 } from 'lib/utils'
|
|
||||||
|
|
||||||
type CmdBarSerilised =
|
|
||||||
| {
|
|
||||||
stage: 'commandBarClosed'
|
|
||||||
// TODO no more properties needed but needs to be implemented in _serialiseCmdBar
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
stage: 'pickCommand'
|
|
||||||
// TODO this will need more properties when implemented in _serialiseCmdBar
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
stage: 'arguments'
|
|
||||||
currentArgKey: string
|
|
||||||
currentArgValue: string
|
|
||||||
headerArguments: Record<string, string>
|
|
||||||
highlightedHeaderArg: string
|
|
||||||
commandName: string
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
stage: 'review'
|
|
||||||
headerArguments: Record<string, string>
|
|
||||||
commandName: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AuthenticatedApp {
|
|
||||||
private readonly exeIndicator: Locator
|
|
||||||
|
|
||||||
private readonly diagnosticsTooltip: Locator
|
|
||||||
private readonly diagnosticsGutterIcon: Locator
|
|
||||||
|
|
||||||
private readonly codeContent: Locator
|
|
||||||
private readonly extrudeButton: Locator
|
|
||||||
readonly startSketchBtn: Locator
|
|
||||||
readonly rectangleBtn: Locator
|
|
||||||
readonly exitSketchBtn: Locator
|
|
||||||
u: Awaited<ReturnType<typeof getUtils>>
|
|
||||||
|
|
||||||
constructor(public readonly page: Page) {
|
|
||||||
this.codeContent = page.locator('.cm-content')
|
|
||||||
this.extrudeButton = page.getByTestId('extrude')
|
|
||||||
this.startSketchBtn = page.getByTestId('sketch')
|
|
||||||
this.rectangleBtn = page.getByTestId('corner-rectangle')
|
|
||||||
this.exitSketchBtn = page.getByTestId('sketch-exit')
|
|
||||||
this.exeIndicator = page.getByTestId('model-state-indicator-execution-done')
|
|
||||||
this.diagnosticsTooltip = page.locator('.cm-tooltip-lint')
|
|
||||||
// this.diagnosticsTooltip = page.locator('.cm-tooltip')
|
|
||||||
this.diagnosticsGutterIcon = page.locator('.cm-lint-marker-error')
|
|
||||||
|
|
||||||
this.u = {} as any
|
|
||||||
}
|
|
||||||
|
|
||||||
async initialise(code = '') {
|
|
||||||
const u = await getUtils(this.page)
|
|
||||||
this.u = u
|
|
||||||
|
|
||||||
await this.page.addInitScript(async (code) => {
|
|
||||||
localStorage.setItem('persistCode', code)
|
|
||||||
;(window as any).playwrightSkipFilePicker = true
|
|
||||||
}, code)
|
|
||||||
|
|
||||||
await this.page.setViewportSize({ width: 1000, height: 500 })
|
|
||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
|
||||||
}
|
|
||||||
getInputFile = (fileName: string) => {
|
|
||||||
return fsp.readFile(
|
|
||||||
join('src', 'wasm-lib', 'tests', 'executor', 'inputs', fileName),
|
|
||||||
'utf-8'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
makeMouseHelpers = (
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
{ steps }: { steps: number } = { steps: 5000 }
|
|
||||||
) => [
|
|
||||||
() => this.page.mouse.click(x, y),
|
|
||||||
() => this.page.mouse.move(x, y, { steps }),
|
|
||||||
]
|
|
||||||
|
|
||||||
/** Likely no where, there's a chance it will click something in the scene, depending what you have in the scene.
|
|
||||||
*
|
|
||||||
* Expects the viewPort to be 1000x500 */
|
|
||||||
clickNoWhere = () => this.page.mouse.click(998, 60)
|
|
||||||
|
|
||||||
// Toolbars
|
|
||||||
expectExtrudeButtonToBeDisabled = async () =>
|
|
||||||
await expect(this.extrudeButton).toBeDisabled()
|
|
||||||
expectExtrudeButtonToBeEnabled = async () =>
|
|
||||||
await expect(this.extrudeButton).not.toBeDisabled()
|
|
||||||
clickExtrudeButton = async () => await this.extrudeButton.click()
|
|
||||||
|
|
||||||
private _serialiseCmdBar = async (): Promise<CmdBarSerilised> => {
|
|
||||||
const reviewForm = await this.page.locator('#review-form')
|
|
||||||
const getHeaderArgs = async () => {
|
|
||||||
const inputs = await this.page.getByTestId('cmd-bar-input-tab').all()
|
|
||||||
const entries = await Promise.all(
|
|
||||||
inputs.map((input) => {
|
|
||||||
const key = input
|
|
||||||
.locator('[data-test-name="arg-name"]')
|
|
||||||
.innerText()
|
|
||||||
.then((a) => a.trim())
|
|
||||||
const value = input
|
|
||||||
.getByTestId('header-arg-value')
|
|
||||||
.innerText()
|
|
||||||
.then((a) => a.trim())
|
|
||||||
return Promise.all([key, value])
|
|
||||||
})
|
|
||||||
)
|
|
||||||
return Object.fromEntries(entries)
|
|
||||||
}
|
|
||||||
const getCommandName = () =>
|
|
||||||
this.page.getByTestId('command-name').textContent()
|
|
||||||
if (await reviewForm.isVisible()) {
|
|
||||||
const [headerArguments, commandName] = await Promise.all([
|
|
||||||
getHeaderArgs(),
|
|
||||||
getCommandName(),
|
|
||||||
])
|
|
||||||
return {
|
|
||||||
stage: 'review',
|
|
||||||
headerArguments,
|
|
||||||
commandName: commandName || '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const [
|
|
||||||
currentArgKey,
|
|
||||||
currentArgValue,
|
|
||||||
headerArguments,
|
|
||||||
highlightedHeaderArg,
|
|
||||||
commandName,
|
|
||||||
] = await Promise.all([
|
|
||||||
this.page.getByTestId('cmd-bar-arg-name').textContent(),
|
|
||||||
this.page.getByTestId('cmd-bar-arg-value').textContent(),
|
|
||||||
getHeaderArgs(),
|
|
||||||
this.page
|
|
||||||
.locator('[data-is-current-arg="true"]')
|
|
||||||
.locator('[data-test-name="arg-name"]')
|
|
||||||
.textContent(),
|
|
||||||
getCommandName(),
|
|
||||||
])
|
|
||||||
return {
|
|
||||||
stage: 'arguments',
|
|
||||||
currentArgKey: currentArgKey || '',
|
|
||||||
currentArgValue: currentArgValue || '',
|
|
||||||
headerArguments,
|
|
||||||
highlightedHeaderArg: highlightedHeaderArg || '',
|
|
||||||
commandName: commandName || '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expectCmdBarToBe = async (expected: CmdBarSerilised) => {
|
|
||||||
return expect.poll(() => this._serialiseCmdBar()).toEqual(expected)
|
|
||||||
}
|
|
||||||
progressCmdBar = async () => {
|
|
||||||
if (Math.random() > 0.5) {
|
|
||||||
const arrowButton = this.page.getByRole('button', {
|
|
||||||
name: 'arrow right Continue',
|
|
||||||
})
|
|
||||||
if (await arrowButton.isVisible()) {
|
|
||||||
await arrowButton.click()
|
|
||||||
} else {
|
|
||||||
await this.page
|
|
||||||
.getByRole('button', { name: 'checkmark Submit command' })
|
|
||||||
.click()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await this.page.keyboard.press('Enter')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expectCodeHighlightedToBe = async (
|
|
||||||
code: string,
|
|
||||||
{ timeout }: { timeout: number } = { timeout: 5000 }
|
|
||||||
) =>
|
|
||||||
await expect
|
|
||||||
.poll(
|
|
||||||
async () => {
|
|
||||||
const texts = (
|
|
||||||
await this.page.getByTestId('hover-highlight').allInnerTexts()
|
|
||||||
).map((s) => s.replace(/\s+/g, '').trim())
|
|
||||||
return texts.join('')
|
|
||||||
},
|
|
||||||
{ timeout }
|
|
||||||
)
|
|
||||||
.toBe(code.replace(/\s+/g, '').trim())
|
|
||||||
expectActiveLinesToBe = async (lines: Array<string>) => {
|
|
||||||
await expect
|
|
||||||
.poll(async () => {
|
|
||||||
return (await this.page.locator('.cm-activeLine').allInnerTexts()).map(
|
|
||||||
(l) => l.trim()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.toEqual(lines.map((l) => l.trim()))
|
|
||||||
}
|
|
||||||
private _expectEditorToContain =
|
|
||||||
(not = false) =>
|
|
||||||
(
|
|
||||||
code: string,
|
|
||||||
{
|
|
||||||
shouldNormalise = false,
|
|
||||||
timeout = 5_000,
|
|
||||||
}: { shouldNormalise?: boolean; timeout?: number } = {}
|
|
||||||
) => {
|
|
||||||
if (!shouldNormalise) {
|
|
||||||
const expectStart = expect(this.codeContent)
|
|
||||||
if (not) {
|
|
||||||
return expectStart.not.toContainText(code, { timeout })
|
|
||||||
}
|
|
||||||
return expectStart.toContainText(code, { timeout })
|
|
||||||
}
|
|
||||||
const normalisedCode = code.replaceAll(/\s+/g, '').trim()
|
|
||||||
const expectStart = expect.poll(
|
|
||||||
async () => {
|
|
||||||
const editorText = await this.codeContent.textContent()
|
|
||||||
return editorText?.replaceAll(/\s+/g, '').trim()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timeout,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (not) {
|
|
||||||
return expectStart.not.toContain(normalisedCode)
|
|
||||||
}
|
|
||||||
return expectStart.toContain(normalisedCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectEditor = {
|
|
||||||
toContain: this._expectEditorToContain(),
|
|
||||||
not: { toContain: this._expectEditorToContain(true) },
|
|
||||||
}
|
|
||||||
|
|
||||||
moveCameraTo = async (
|
|
||||||
pos: { x: number; y: number; z: number },
|
|
||||||
target: { x: number; y: number; z: number } = { x: 0, y: 0, z: 0 }
|
|
||||||
) => {
|
|
||||||
await this.u.openAndClearDebugPanel()
|
|
||||||
await this.u.doAndWaitForImageDiff(
|
|
||||||
() =>
|
|
||||||
this.u.sendCustomCmd({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'default_camera_look_at',
|
|
||||||
vantage: pos,
|
|
||||||
center: target,
|
|
||||||
up: { x: 0, y: 0, z: 1 },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
300
|
|
||||||
)
|
|
||||||
await this.u.closeDebugPanel()
|
|
||||||
}
|
|
||||||
waitForExecutionDone = async () => {
|
|
||||||
await expect(this.exeIndicator).toBeVisible()
|
|
||||||
}
|
|
||||||
private _serialiseDiagnostics = async (): Promise<Array<string>> => {
|
|
||||||
const diagnostics = await this.diagnosticsGutterIcon.all()
|
|
||||||
const diagnosticsContent: string[] = []
|
|
||||||
for (const diag of diagnostics) {
|
|
||||||
await diag.hover()
|
|
||||||
// await expect(this.diagnosticsTooltip)
|
|
||||||
const content = await this.diagnosticsTooltip.allTextContents()
|
|
||||||
diagnosticsContent.push(content.join(''))
|
|
||||||
}
|
|
||||||
return [...new Set(diagnosticsContent)].map((d) => d.trim())
|
|
||||||
}
|
|
||||||
expectDiagnosticsToBe = async (expected: Array<string>) =>
|
|
||||||
await expect
|
|
||||||
.poll(async () => {
|
|
||||||
const result = await this._serialiseDiagnostics()
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
.toEqual(expected.map((e) => e.trim()))
|
|
||||||
startSketchPlaneSelection = async () =>
|
|
||||||
this.u.doAndWaitForImageDiff(() => this.startSketchBtn.click(), 500)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const test = base.extend<{
|
|
||||||
app: AuthenticatedApp
|
|
||||||
}>({
|
|
||||||
app: async ({ page }, use) => {
|
|
||||||
const authenticatedApp = new AuthenticatedApp(page)
|
|
||||||
await use(authenticatedApp)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
test.beforeEach(async ({ context, page }, testInfo) => {
|
|
||||||
await setup(context, page, testInfo)
|
|
||||||
})
|
|
||||||
|
|
||||||
test.afterEach(async ({ page }, testInfo) => {
|
|
||||||
await tearDown(page, testInfo)
|
|
||||||
})
|
|
||||||
|
|
||||||
export { expect } from '@playwright/test'
|
|
@ -1,312 +0,0 @@
|
|||||||
import { test, expect, AuthenticatedApp } from './authenticatedAppFixture'
|
|
||||||
|
|
||||||
// test file is for testing point an click code gen functionality that's not sketch mode related
|
|
||||||
|
|
||||||
test.describe('verify sketch on chamfer works', () => {
|
|
||||||
const _sketchOnAChamfer =
|
|
||||||
(app: AuthenticatedApp) =>
|
|
||||||
async ({
|
|
||||||
clickCoords,
|
|
||||||
cameraPos,
|
|
||||||
cameraTarget,
|
|
||||||
beforeChamferSnippet,
|
|
||||||
afterChamferSelectSnippet,
|
|
||||||
afterRectangle1stClickSnippet,
|
|
||||||
afterRectangle2ndClickSnippet,
|
|
||||||
}: {
|
|
||||||
clickCoords: { x: number; y: number }
|
|
||||||
cameraPos: { x: number; y: number; z: number }
|
|
||||||
cameraTarget: { x: number; y: number; z: number }
|
|
||||||
beforeChamferSnippet: string
|
|
||||||
afterChamferSelectSnippet: string
|
|
||||||
afterRectangle1stClickSnippet: string
|
|
||||||
afterRectangle2ndClickSnippet: string
|
|
||||||
}) => {
|
|
||||||
const [clickChamfer] = app.makeMouseHelpers(clickCoords.x, clickCoords.y)
|
|
||||||
const [rectangle1stClick] = app.makeMouseHelpers(573, 149)
|
|
||||||
const [rectangle2ndClick, rectangle2ndMove] = app.makeMouseHelpers(
|
|
||||||
598,
|
|
||||||
380,
|
|
||||||
{ steps: 5 }
|
|
||||||
)
|
|
||||||
|
|
||||||
await app.moveCameraTo(cameraPos, cameraTarget)
|
|
||||||
|
|
||||||
await test.step('check chamfer selection changes cursor positon', async () => {
|
|
||||||
await expect(async () => {
|
|
||||||
// sometimes initial click doesn't register
|
|
||||||
await clickChamfer()
|
|
||||||
await app.expectActiveLinesToBe([beforeChamferSnippet.slice(-5)])
|
|
||||||
}).toPass({ timeout: 40_000, intervals: [500] })
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('starting a new and selecting a chamfer should animate to the new sketch and possible break up the initial chamfer if it had one than more tag', async () => {
|
|
||||||
await app.startSketchPlaneSelection()
|
|
||||||
await clickChamfer()
|
|
||||||
// timeout wait for engine animation is unavoidable
|
|
||||||
await app.page.waitForTimeout(600)
|
|
||||||
await app.expectEditor.toContain(afterChamferSelectSnippet)
|
|
||||||
})
|
|
||||||
await test.step('make sure a basic sketch can be added', async () => {
|
|
||||||
await app.rectangleBtn.click()
|
|
||||||
await rectangle1stClick()
|
|
||||||
await app.expectEditor.toContain(afterRectangle1stClickSnippet)
|
|
||||||
await app.u.doAndWaitForImageDiff(() => rectangle2ndMove(), 50)
|
|
||||||
await rectangle2ndClick()
|
|
||||||
await app.expectEditor.toContain(afterRectangle2ndClickSnippet)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('Clean up so that `_sketchOnAChamfer` util can be called again', async () => {
|
|
||||||
await app.exitSketchBtn.click()
|
|
||||||
await app.waitForExecutionDone()
|
|
||||||
})
|
|
||||||
await test.step('Check there is no errors after code created in previous steps executes', async () => {
|
|
||||||
await app.expectDiagnosticsToBe([])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
test('works on all edge selections and can break up multi edges in a chamfer array', async ({
|
|
||||||
app,
|
|
||||||
}) => {
|
|
||||||
test.skip(
|
|
||||||
process.platform === 'win32',
|
|
||||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
|
||||||
)
|
|
||||||
const file = await app.getInputFile('e2e-can-sketch-on-chamfer.kcl')
|
|
||||||
await app.initialise(file)
|
|
||||||
|
|
||||||
const sketchOnAChamfer = _sketchOnAChamfer(app)
|
|
||||||
|
|
||||||
await sketchOnAChamfer({
|
|
||||||
clickCoords: { x: 570, y: 220 },
|
|
||||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
|
||||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
|
||||||
beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)
|
|
||||||
chamfer({length:30,tags:[
|
|
||||||
seg01,
|
|
||||||
getNextAdjacentEdge(yo),
|
|
||||||
getNextAdjacentEdge(seg02),
|
|
||||||
getOppositeEdge(seg01)
|
|
||||||
]}, %)`,
|
|
||||||
afterChamferSelectSnippet:
|
|
||||||
'const sketch002 = startSketchOn(extrude001, seg03)',
|
|
||||||
afterRectangle1stClickSnippet: 'startProfileAt([205.96, 254.59], %)',
|
|
||||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA002) - 90,
|
|
||||||
105.26
|
|
||||||
], %, $rectangleSegmentB001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA002),
|
|
||||||
-segLen(rectangleSegmentA002)
|
|
||||||
], %, $rectangleSegmentC001)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)`,
|
|
||||||
})
|
|
||||||
|
|
||||||
await sketchOnAChamfer({
|
|
||||||
clickCoords: { x: 690, y: 250 },
|
|
||||||
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
|
||||||
cameraTarget: { x: -150, y: -4500, z: -80 },
|
|
||||||
beforeChamferSnippet: `angledLine([
|
|
||||||
segAng(rectangleSegmentA001) - 90,
|
|
||||||
217.26
|
|
||||||
], %, $seg01)chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [
|
|
||||||
seg01,
|
|
||||||
getNextAdjacentEdge(yo),
|
|
||||||
getNextAdjacentEdge(seg02)
|
|
||||||
]
|
|
||||||
}, %)`,
|
|
||||||
afterChamferSelectSnippet:
|
|
||||||
'const sketch003 = startSketchOn(extrude001, seg04)',
|
|
||||||
afterRectangle1stClickSnippet: 'startProfileAt([-209.64, 255.28], %)',
|
|
||||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA003) - 90,
|
|
||||||
106.84
|
|
||||||
], %, $rectangleSegmentB002)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA003),
|
|
||||||
-segLen(rectangleSegmentA003)
|
|
||||||
], %, $rectangleSegmentC002)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)`,
|
|
||||||
})
|
|
||||||
await sketchOnAChamfer({
|
|
||||||
clickCoords: { x: 677, y: 87 },
|
|
||||||
cameraPos: { x: -6200, y: 1500, z: 6200 },
|
|
||||||
cameraTarget: { x: 8300, y: 1100, z: 4800 },
|
|
||||||
beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [
|
|
||||||
getNextAdjacentEdge(yo),
|
|
||||||
getNextAdjacentEdge(seg02)
|
|
||||||
]
|
|
||||||
}, %)`,
|
|
||||||
afterChamferSelectSnippet:
|
|
||||||
'const sketch003 = startSketchOn(extrude001, seg04)',
|
|
||||||
afterRectangle1stClickSnippet: 'startProfileAt([-209.64, 255.28], %)',
|
|
||||||
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA003) - 90,
|
|
||||||
106.84
|
|
||||||
], %, $rectangleSegmentB002)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA003),
|
|
||||||
-segLen(rectangleSegmentA003)
|
|
||||||
], %, $rectangleSegmentC002)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)`,
|
|
||||||
})
|
|
||||||
/// last one
|
|
||||||
await sketchOnAChamfer({
|
|
||||||
clickCoords: { x: 620, y: 300 },
|
|
||||||
cameraPos: { x: -1100, y: -7700, z: 1600 },
|
|
||||||
cameraTarget: { x: 1450, y: 670, z: 4000 },
|
|
||||||
beforeChamferSnippet: `chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [getNextAdjacentEdge(yo)]
|
|
||||||
}, %)`,
|
|
||||||
afterChamferSelectSnippet:
|
|
||||||
'const sketch005 = startSketchOn(extrude001, seg06)',
|
|
||||||
afterRectangle1stClickSnippet: 'startProfileAt([-23.43, 19.69], %)',
|
|
||||||
afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA005) - 90,
|
|
||||||
84.07
|
|
||||||
], %, $rectangleSegmentB004)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA005),
|
|
||||||
-segLen(rectangleSegmentA005)
|
|
||||||
], %, $rectangleSegmentC004)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)`,
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('verif at the end of the test that final code is what is expected', async () => {
|
|
||||||
await app.expectEditor.toContain(
|
|
||||||
`const sketch001 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
|
||||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001) - 90,
|
|
||||||
217.26
|
|
||||||
], %, $seg01)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001),
|
|
||||||
-segLen(rectangleSegmentA001)
|
|
||||||
], %, $yo)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg02)
|
|
||||||
|> close(%)
|
|
||||||
const extrude001 = extrude(100, sketch001)
|
|
||||||
|> chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [getOppositeEdge(seg01)]
|
|
||||||
}, %, $seg03)
|
|
||||||
|> chamfer({ length: 30, tags: [seg01] }, %, $seg04)
|
|
||||||
|> chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [getNextAdjacentEdge(seg02)]
|
|
||||||
}, %, $seg05)
|
|
||||||
|> chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [getNextAdjacentEdge(yo)]
|
|
||||||
}, %, $seg06)
|
|
||||||
const sketch005 = startSketchOn(extrude001, seg06)
|
|
||||||
|> startProfileAt([-23.43, 19.69], %)
|
|
||||||
|> angledLine([0, 9.1], %, $rectangleSegmentA005)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA005) - 90,
|
|
||||||
84.07
|
|
||||||
], %, $rectangleSegmentB004)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA005),
|
|
||||||
-segLen(rectangleSegmentA005)
|
|
||||||
], %, $rectangleSegmentC004)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
const sketch004 = startSketchOn(extrude001, seg05)
|
|
||||||
|> startProfileAt([82.57, 322.96], %)
|
|
||||||
|> angledLine([0, 11.16], %, $rectangleSegmentA004)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA004) - 90,
|
|
||||||
103.07
|
|
||||||
], %, $rectangleSegmentB003)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA004),
|
|
||||||
-segLen(rectangleSegmentA004)
|
|
||||||
], %, $rectangleSegmentC003)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
const sketch003 = startSketchOn(extrude001, seg04)
|
|
||||||
|> startProfileAt([-209.64, 255.28], %)
|
|
||||||
|> angledLine([0, 11.56], %, $rectangleSegmentA003)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA003) - 90,
|
|
||||||
106.84
|
|
||||||
], %, $rectangleSegmentB002)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA003),
|
|
||||||
-segLen(rectangleSegmentA003)
|
|
||||||
], %, $rectangleSegmentC002)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
const sketch002 = startSketchOn(extrude001, seg03)
|
|
||||||
|> startProfileAt([205.96, 254.59], %)
|
|
||||||
|> angledLine([0, 11.39], %, $rectangleSegmentA002)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA002) - 90,
|
|
||||||
105.26
|
|
||||||
], %, $rectangleSegmentB001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA002),
|
|
||||||
-segLen(rectangleSegmentA002)
|
|
||||||
], %, $rectangleSegmentC001)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
`,
|
|
||||||
{ shouldNormalise: true }
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
test('works on chamfers on sketchOnFace extrudes', async ({ app, page }) => {
|
|
||||||
test.skip(
|
|
||||||
process.platform === 'win32',
|
|
||||||
'Fails on windows in CI, can not be replicated locally on windows.'
|
|
||||||
)
|
|
||||||
const file = await app.getInputFile(
|
|
||||||
'e2e-can-sketch-on-sketchOnFace-chamfers.kcl'
|
|
||||||
)
|
|
||||||
await app.initialise(file)
|
|
||||||
|
|
||||||
const sketchOnAChamfer = _sketchOnAChamfer(app)
|
|
||||||
|
|
||||||
// clickCoords: { x: 627, y: 287 },
|
|
||||||
await sketchOnAChamfer({
|
|
||||||
clickCoords: { x: 858, y: 194 },
|
|
||||||
cameraPos: { x: 8822, y: 1223, z: 9140 },
|
|
||||||
cameraTarget: { x: 10856, y: -7390, z: 2832 },
|
|
||||||
beforeChamferSnippet: `chamfer({
|
|
||||||
length: 18,
|
|
||||||
tags: [getNextAdjacentEdge(seg01), seg02]
|
|
||||||
}, %)`,
|
|
||||||
afterChamferSelectSnippet:
|
|
||||||
'const sketch005 = startSketchOn(extrude004, seg05)',
|
|
||||||
afterRectangle1stClickSnippet: 'startProfileAt([-23.43, 19.69], %)',
|
|
||||||
afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA005) - 90,
|
|
||||||
84.07
|
|
||||||
], %, $rectangleSegmentB004)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA005),
|
|
||||||
-segLen(rectangleSegmentA005)
|
|
||||||
], %, $rectangleSegmentC004)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)`,
|
|
||||||
})
|
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
})
|
|
||||||
})
|
|
@ -477,9 +477,7 @@ const sketch002 = startSketchOn(launderExtrudeThroughVar, seg02)
|
|||||||
|
|
||||||
await expect(page.getByText('Unable to delete part')).toBeVisible()
|
await expect(page.getByText('Unable to delete part')).toBeVisible()
|
||||||
})
|
})
|
||||||
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engin', async ({
|
test('Hovering over 3d features highlights code', async ({ page }) => {
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -544,16 +542,16 @@ const sketch002 = startSketchOn(launderExtrudeThroughVar, seg02)
|
|||||||
const close: Coords2d = [720, 200]
|
const close: Coords2d = [720, 200]
|
||||||
const nothing: Coords2d = [600, 200]
|
const nothing: Coords2d = [600, 200]
|
||||||
const closeEdge: Coords2d = [744, 233]
|
const closeEdge: Coords2d = [744, 233]
|
||||||
const closeAdjacentEdge: Coords2d = [743, 277]
|
const closeAdjacentEdge: Coords2d = [688, 123]
|
||||||
const closeOppositeEdge: Coords2d = [687, 169]
|
const closeOppositeEdge: Coords2d = [687, 169]
|
||||||
|
|
||||||
const tangentialArcEdge: Coords2d = [811, 142]
|
const tangentialArcEdge: Coords2d = [811, 142]
|
||||||
const tangentialArcOppositeEdge: Coords2d = [820, 180]
|
const tangentialArcOppositeEdge: Coords2d = [820, 180]
|
||||||
const tangentialArcAdjacentEdge: Coords2d = [688, 123]
|
const tangentialArcAdjacentEdge: Coords2d = [893, 165]
|
||||||
|
|
||||||
const straightSegmentEdge: Coords2d = [819, 369]
|
const straightSegmentEdge: Coords2d = [819, 369]
|
||||||
const straightSegmentOppositeEdge: Coords2d = [822, 368]
|
const straightSegmentOppositeEdge: Coords2d = [635, 394]
|
||||||
const straightSegmentAdjacentEdge: Coords2d = [893, 165]
|
const straightSegmentAdjacentEdge: Coords2d = [679, 329]
|
||||||
|
|
||||||
await page.mouse.move(nothing[0], nothing[1])
|
await page.mouse.move(nothing[0], nothing[1])
|
||||||
await page.mouse.click(nothing[0], nothing[1])
|
await page.mouse.click(nothing[0], nothing[1])
|
||||||
@ -571,27 +569,19 @@ const sketch002 = startSketchOn(launderExtrudeThroughVar, seg02)
|
|||||||
const highlightedLocator = page.getByTestId('hover-highlight')
|
const highlightedLocator = page.getByTestId('hover-highlight')
|
||||||
const activeLineLocator = page.locator('.cm-activeLine')
|
const activeLineLocator = page.locator('.cm-activeLine')
|
||||||
|
|
||||||
await test.step(`hover should highlight correct code, clicking should put the cursor in the right place, and send selection to engine`, async () => {
|
await test.step(`hover should highlight correct code`, async () => {
|
||||||
await expect(async () => {
|
|
||||||
await page.mouse.move(nothing[0], nothing[1])
|
|
||||||
await page.mouse.move(coord[0], coord[1])
|
await page.mouse.move(coord[0], coord[1])
|
||||||
await expect(highlightedLocator.first()).toBeVisible()
|
await expect(highlightedLocator.first()).toBeVisible()
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => {
|
.poll(async () => {
|
||||||
let textContents = await highlightedLocator.allTextContents()
|
const textContents = await highlightedLocator.allTextContents()
|
||||||
const textContentsStr = textContents
|
return textContents.join('').replace(/\s+/g, '')
|
||||||
.join('')
|
|
||||||
.replace(/\s+/g, '')
|
|
||||||
console.log(textContentsStr)
|
|
||||||
return textContentsStr
|
|
||||||
})
|
})
|
||||||
.toBe(highlightCode)
|
.toBe(highlightCode)
|
||||||
await page.mouse.move(nothing[0], nothing[1])
|
await page.mouse.move(nothing[0], nothing[1])
|
||||||
}).toPass({ timeout: 40_000, intervals: [500] })
|
|
||||||
})
|
})
|
||||||
await test.step(`click should put the cursor in the right place`, async () => {
|
await test.step(`click should put the cursor in the right place`, async () => {
|
||||||
// await page.mouse.move(nothing[0], nothing[1], { steps: 5 })
|
await expect(highlightedLocator.first()).not.toBeVisible()
|
||||||
// await expect(highlightedLocator.first()).not.toBeVisible()
|
|
||||||
await page.mouse.click(coord[0], coord[1])
|
await page.mouse.click(coord[0], coord[1])
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => {
|
.poll(async () => {
|
||||||
@ -699,122 +689,10 @@ const sketch002 = startSketchOn(launderExtrudeThroughVar, seg02)
|
|||||||
'angledLineToY({ angle: 30, to: 11.14 }, %)'
|
'angledLineToY({ angle: 30, to: 11.14 }, %)'
|
||||||
)
|
)
|
||||||
await checkCodeAtHoverPosition(
|
await checkCodeAtHoverPosition(
|
||||||
'straightSegmentAdjacentEdge',
|
'straightSegmentAdjancentEdge',
|
||||||
straightSegmentAdjacentEdge,
|
straightSegmentAdjacentEdge,
|
||||||
`angledLineThatIntersects({angle:3.14,intersectTag:a,offset:0},%)`,
|
`angledLineToY({angle:30,to:11.14},%)`,
|
||||||
'}, %)'
|
'angledLineToY({ angle: 30, to: 11.14 }, %)'
|
||||||
)
|
|
||||||
|
|
||||||
await page.waitForTimeout(200)
|
|
||||||
|
|
||||||
await u.removeCurrentCode()
|
|
||||||
await u.codeLocator.fill(`const sketch001 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
|
||||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001) - 90,
|
|
||||||
217.26
|
|
||||||
], %, $seg01)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001),
|
|
||||||
-segLen(rectangleSegmentA001)
|
|
||||||
], %, $yo)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg02)
|
|
||||||
|> close(%)
|
|
||||||
const extrude001 = extrude(100, sketch001)
|
|
||||||
|> chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [
|
|
||||||
seg01,
|
|
||||||
getNextAdjacentEdge(yo),
|
|
||||||
getNextAdjacentEdge(seg02),
|
|
||||||
getOppositeEdge(seg01)
|
|
||||||
]
|
|
||||||
}, %)
|
|
||||||
`)
|
|
||||||
await expect(
|
|
||||||
page.getByTestId('model-state-indicator-execution-done')
|
|
||||||
).toBeVisible()
|
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
|
||||||
await u.sendCustomCmd({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'default_camera_look_at',
|
|
||||||
vantage: { x: 16118, y: -1654, z: 5855 },
|
|
||||||
center: { x: 4915, y: -3893, z: 4874 },
|
|
||||||
up: { x: 0, y: 0, z: 1 },
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await u.sendCustomCmd({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'default_camera_get_settings',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
|
|
||||||
await page.mouse.click(nothing[0], nothing[1])
|
|
||||||
|
|
||||||
const oppositeChamfer: Coords2d = [577, 230]
|
|
||||||
const baseChamfer: Coords2d = [726, 258]
|
|
||||||
const adjacentChamfer1: Coords2d = [653, 99]
|
|
||||||
const adjacentChamfer2: Coords2d = [653, 430]
|
|
||||||
|
|
||||||
await checkCodeAtHoverPosition(
|
|
||||||
'oppositeChamfer',
|
|
||||||
oppositeChamfer,
|
|
||||||
`angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)chamfer({length:30,tags:[seg01,getNextAdjacentEdge(yo),getNextAdjacentEdge(seg02),getOppositeEdge(seg01)]},%)`,
|
|
||||||
'}, %)'
|
|
||||||
)
|
|
||||||
|
|
||||||
await checkCodeAtHoverPosition(
|
|
||||||
'baseChamfer',
|
|
||||||
baseChamfer,
|
|
||||||
`angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)chamfer({length:30,tags:[seg01,getNextAdjacentEdge(yo),getNextAdjacentEdge(seg02),getOppositeEdge(seg01)]},%)`,
|
|
||||||
'}, %)'
|
|
||||||
)
|
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
|
||||||
await u.sendCustomCmd({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'default_camera_look_at',
|
|
||||||
vantage: { x: -6414, y: 160, z: 6145 },
|
|
||||||
center: { x: 5919, y: 1236, z: 5251 },
|
|
||||||
up: { x: 0, y: 0, z: 1 },
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await u.sendCustomCmd({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'default_camera_get_settings',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
|
|
||||||
await page.mouse.click(nothing[0], nothing[1])
|
|
||||||
|
|
||||||
await checkCodeAtHoverPosition(
|
|
||||||
'adjacentChamfer1',
|
|
||||||
adjacentChamfer1,
|
|
||||||
`lineTo([profileStartX(%),profileStartY(%)],%,$seg02)chamfer({length:30,tags:[seg01,getNextAdjacentEdge(yo),getNextAdjacentEdge(seg02),getOppositeEdge(seg01)]},%)`,
|
|
||||||
'}, %)'
|
|
||||||
)
|
|
||||||
|
|
||||||
await checkCodeAtHoverPosition(
|
|
||||||
'adjacentChamfer2',
|
|
||||||
adjacentChamfer2,
|
|
||||||
`angledLine([segAng(rectangleSegmentA001),-segLen(rectangleSegmentA001)],%,$yo)chamfer({length:30,tags:[seg01,getNextAdjacentEdge(yo),getNextAdjacentEdge(seg02),getOppositeEdge(seg01)]},%)`,
|
|
||||||
'}, %)'
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
test("Extrude button should be disabled if there's no extrudable geometry when nothing is selected", async ({
|
test("Extrude button should be disabled if there's no extrudable geometry when nothing is selected", async ({
|
||||||
|
@ -277,6 +277,8 @@ test.describe('Testing settings', () => {
|
|||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
|
page.on('console', console.log)
|
||||||
|
|
||||||
// Selectors and constants
|
// Selectors and constants
|
||||||
const userThemeColor = '120'
|
const userThemeColor = '120'
|
||||||
const projectThemeColor = '50'
|
const projectThemeColor = '50'
|
||||||
@ -290,6 +292,7 @@ test.describe('Testing settings', () => {
|
|||||||
const projectLink = page.getByText('bracket')
|
const projectLink = page.getByText('bracket')
|
||||||
const logoLink = page.getByTestId('app-logo')
|
const logoLink = page.getByTestId('app-logo')
|
||||||
|
|
||||||
|
// Open the app and set the user theme color
|
||||||
await test.step('Set user theme color on home', async () => {
|
await test.step('Set user theme color on home', async () => {
|
||||||
await expect(settingsOpenButton).toBeVisible()
|
await expect(settingsOpenButton).toBeVisible()
|
||||||
await settingsOpenButton.click()
|
await settingsOpenButton.click()
|
||||||
@ -308,15 +311,13 @@ test.describe('Testing settings', () => {
|
|||||||
await expect(projectSettingsTab).toBeChecked()
|
await expect(projectSettingsTab).toBeChecked()
|
||||||
await themeColorSetting.fill(projectThemeColor)
|
await themeColorSetting.fill(projectThemeColor)
|
||||||
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
||||||
await settingsCloseButton.click()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Refresh the application and see project setting applied', async () => {
|
await test.step('Refresh the application and see project setting applied', async () => {
|
||||||
// Make sure we're done navigating before we reload
|
|
||||||
await expect(settingsCloseButton).not.toBeVisible()
|
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' })
|
await page.reload({ waitUntil: 'domcontentloaded' })
|
||||||
|
|
||||||
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
||||||
|
await settingsCloseButton.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Navigate back to the home view and see user setting applied`, async () => {
|
await test.step(`Navigate back to the home view and see user setting applied`, async () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "zoo-modeling-app",
|
"name": "zoo-modeling-app",
|
||||||
"version": "0.25.3",
|
"version": "0.25.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"productName": "Zoo Modeling App",
|
"productName": "Zoo Modeling App",
|
||||||
"author": {
|
"author": {
|
||||||
@ -183,7 +183,7 @@
|
|||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"ts-node": "^10.0.0",
|
"ts-node": "^10.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"vite": "^5.4.6",
|
"vite": "^5.4.3",
|
||||||
"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",
|
||||||
|
@ -605,15 +605,9 @@ export const ModelingMachineProvider = ({
|
|||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
input.sketchPathToNode,
|
input.sketchPathToNode,
|
||||||
input.extrudePathToNode,
|
input.extrudePathToNode,
|
||||||
input.faceInfo
|
input.cap
|
||||||
)
|
)
|
||||||
if (err(sketched)) {
|
if (trap(sketched)) return Promise.reject(sketched)
|
||||||
const sketchedError = new Error(
|
|
||||||
'Incompatible face, please try another'
|
|
||||||
)
|
|
||||||
trap(sketchedError)
|
|
||||||
return Promise.reject(sketchedError)
|
|
||||||
}
|
|
||||||
const { modifiedAst, pathToNode: pathToNewSketchNode } = sketched
|
const { modifiedAst, pathToNode: pathToNewSketchNode } = sketched
|
||||||
|
|
||||||
await kclManager.executeAstMock(modifiedAst)
|
await kclManager.executeAstMock(modifiedAst)
|
||||||
|
@ -11,17 +11,12 @@ import {
|
|||||||
getCapCodeRef,
|
getCapCodeRef,
|
||||||
getSweepEdgeCodeRef,
|
getSweepEdgeCodeRef,
|
||||||
getSweepFromSuspectedSweepSurface,
|
getSweepFromSuspectedSweepSurface,
|
||||||
getEdgeCuteConsumedCodeRef,
|
|
||||||
getSolid2dCodeRef,
|
getSolid2dCodeRef,
|
||||||
getWallCodeRef,
|
getWallCodeRef,
|
||||||
getArtifactOfTypes,
|
|
||||||
SegmentArtifact,
|
|
||||||
} from 'lang/std/artifactGraph'
|
} from 'lang/std/artifactGraph'
|
||||||
import { err, reportRejection } from 'lib/trap'
|
import { err, reportRejection } from 'lib/trap'
|
||||||
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
|
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
|
||||||
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
|
import { getNodePathFromSourceRange } from 'lang/queryAst'
|
||||||
import { CallExpression } from 'lang/wasm'
|
|
||||||
import { EdgeCutInfo, ExtrudeFacePlane } from 'machines/modelingMachine'
|
|
||||||
|
|
||||||
export function useEngineConnectionSubscriptions() {
|
export function useEngineConnectionSubscriptions() {
|
||||||
const { send, context, state } = useModelingContext()
|
const { send, context, state } = useModelingContext()
|
||||||
@ -77,17 +72,6 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
editorManager.setHighlightRange([
|
editorManager.setHighlightRange([
|
||||||
artifact?.codeRef?.range || [0, 0],
|
artifact?.codeRef?.range || [0, 0],
|
||||||
])
|
])
|
||||||
} else if (artifact?.type === 'edgeCut') {
|
|
||||||
const codeRef = artifact.codeRef
|
|
||||||
const consumedCodeRef = getEdgeCuteConsumedCodeRef(
|
|
||||||
artifact,
|
|
||||||
engineCommandManager.artifactGraph
|
|
||||||
)
|
|
||||||
editorManager.setHighlightRange(
|
|
||||||
err(consumedCodeRef)
|
|
||||||
? [codeRef.range]
|
|
||||||
: [codeRef.range, consumedCodeRef.range]
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
editorManager.setHighlightRange([[0, 0]])
|
editorManager.setHighlightRange([[0, 0]])
|
||||||
}
|
}
|
||||||
@ -193,21 +177,12 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
engineCommandManager.artifactGraph
|
engineCommandManager.artifactGraph
|
||||||
)
|
)
|
||||||
|
|
||||||
if (
|
if (artifact?.type !== 'cap' && artifact?.type !== 'wall') return
|
||||||
artifact?.type !== 'cap' &&
|
|
||||||
artifact?.type !== 'wall' &&
|
|
||||||
!(
|
|
||||||
artifact?.type === 'edgeCut' && artifact.subType === 'chamfer'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
const codeRef =
|
const codeRef =
|
||||||
artifact.type === 'cap'
|
artifact.type === 'cap'
|
||||||
? getCapCodeRef(artifact, engineCommandManager.artifactGraph)
|
? getCapCodeRef(artifact, engineCommandManager.artifactGraph)
|
||||||
: artifact.type === 'wall'
|
: getWallCodeRef(artifact, engineCommandManager.artifactGraph)
|
||||||
? getWallCodeRef(artifact, engineCommandManager.artifactGraph)
|
|
||||||
: artifact.codeRef
|
|
||||||
|
|
||||||
const faceInfo = await getFaceDetails(faceId)
|
const faceInfo = await getFaceDetails(faceId)
|
||||||
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis)
|
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis)
|
||||||
@ -218,72 +193,6 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
err(codeRef) ? [0, 0] : codeRef.range
|
err(codeRef) ? [0, 0] : codeRef.range
|
||||||
)
|
)
|
||||||
|
|
||||||
const getEdgeCutMeta = (): null | EdgeCutInfo => {
|
|
||||||
let chamferInfo: {
|
|
||||||
segment: SegmentArtifact
|
|
||||||
type: EdgeCutInfo['subType']
|
|
||||||
} | null = null
|
|
||||||
if (
|
|
||||||
artifact?.type === 'edgeCut' &&
|
|
||||||
artifact.subType === 'chamfer'
|
|
||||||
) {
|
|
||||||
const consumedArtifact = getArtifactOfTypes(
|
|
||||||
{
|
|
||||||
key: artifact.consumedEdgeId,
|
|
||||||
types: ['segment', 'sweepEdge'],
|
|
||||||
},
|
|
||||||
engineCommandManager.artifactGraph
|
|
||||||
)
|
|
||||||
if (err(consumedArtifact)) return null
|
|
||||||
if (consumedArtifact.type === 'segment') {
|
|
||||||
chamferInfo = {
|
|
||||||
type: 'base',
|
|
||||||
segment: consumedArtifact,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const segment = getArtifactOfTypes(
|
|
||||||
{ key: consumedArtifact.segId, types: ['segment'] },
|
|
||||||
engineCommandManager.artifactGraph
|
|
||||||
)
|
|
||||||
if (err(segment)) return null
|
|
||||||
chamferInfo = {
|
|
||||||
type: consumedArtifact.subType,
|
|
||||||
segment,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!chamferInfo) return null
|
|
||||||
const segmentCallExpr = getNodeFromPath<CallExpression>(
|
|
||||||
kclManager.ast,
|
|
||||||
chamferInfo?.segment.codeRef.pathToNode || [],
|
|
||||||
'CallExpression'
|
|
||||||
)
|
|
||||||
if (err(segmentCallExpr)) return null
|
|
||||||
if (segmentCallExpr.node.type !== 'CallExpression') return null
|
|
||||||
const sketchNodeArgs = segmentCallExpr.node.arguments
|
|
||||||
const tagDeclarator = sketchNodeArgs.find(
|
|
||||||
({ type }) => type === 'TagDeclarator'
|
|
||||||
)
|
|
||||||
if (!tagDeclarator || tagDeclarator.type !== 'TagDeclarator')
|
|
||||||
return null
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: 'edgeCut',
|
|
||||||
subType: chamferInfo.type,
|
|
||||||
tagName: tagDeclarator.value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const edgeCutMeta = getEdgeCutMeta()
|
|
||||||
|
|
||||||
const _faceInfo: ExtrudeFacePlane['faceInfo'] = edgeCutMeta
|
|
||||||
? edgeCutMeta
|
|
||||||
: artifact.type === 'cap'
|
|
||||||
? {
|
|
||||||
type: 'cap',
|
|
||||||
subType: artifact.subType,
|
|
||||||
}
|
|
||||||
: { type: 'wall' }
|
|
||||||
|
|
||||||
const extrudePathToNode = !err(extrusion)
|
const extrudePathToNode = !err(extrusion)
|
||||||
? getNodePathFromSourceRange(
|
? getNodePathFromSourceRange(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
@ -302,7 +211,7 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
) as [number, number, number],
|
) as [number, number, number],
|
||||||
sketchPathToNode,
|
sketchPathToNode,
|
||||||
extrudePathToNode,
|
extrudePathToNode,
|
||||||
faceInfo: _faceInfo,
|
cap: artifact.type === 'cap' ? artifact.subType : 'none',
|
||||||
faceId: faceId,
|
faceId: faceId,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -416,7 +416,7 @@ export class KclManager {
|
|||||||
ast: Program,
|
ast: Program,
|
||||||
execute: boolean,
|
execute: boolean,
|
||||||
optionalParams?: {
|
optionalParams?: {
|
||||||
focusPath?: Array<PathToNode>
|
focusPath?: PathToNode
|
||||||
zoomToFit?: boolean
|
zoomToFit?: boolean
|
||||||
zoomOnRangeAndType?: {
|
zoomOnRangeAndType?: {
|
||||||
range: SourceRange
|
range: SourceRange
|
||||||
@ -435,34 +435,27 @@ export class KclManager {
|
|||||||
let returnVal: Selections | undefined = undefined
|
let returnVal: Selections | undefined = undefined
|
||||||
|
|
||||||
if (optionalParams?.focusPath) {
|
if (optionalParams?.focusPath) {
|
||||||
returnVal = {
|
const _node1 = getNodeFromPath<any>(
|
||||||
codeBasedSelections: [],
|
|
||||||
otherSelections: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const path of optionalParams.focusPath) {
|
|
||||||
const getNodeFromPathResult = getNodeFromPath<any>(
|
|
||||||
astWithUpdatedSource,
|
astWithUpdatedSource,
|
||||||
path
|
optionalParams?.focusPath
|
||||||
)
|
)
|
||||||
if (err(getNodeFromPathResult))
|
if (err(_node1)) return Promise.reject(_node1)
|
||||||
return Promise.reject(getNodeFromPathResult)
|
const { node } = _node1
|
||||||
const { node } = getNodeFromPathResult
|
|
||||||
|
|
||||||
const { start, end } = node
|
const { start, end } = node
|
||||||
|
|
||||||
if (!start || !end)
|
if (!start || !end)
|
||||||
return {
|
return {
|
||||||
selections: undefined,
|
selections: undefined,
|
||||||
newAst: astWithUpdatedSource,
|
newAst: astWithUpdatedSource,
|
||||||
}
|
}
|
||||||
|
returnVal = {
|
||||||
if (start && end) {
|
codeBasedSelections: [
|
||||||
returnVal.codeBasedSelections.push({
|
{
|
||||||
type: 'default',
|
type: 'default',
|
||||||
range: [start, end],
|
range: [start, end],
|
||||||
})
|
},
|
||||||
}
|
],
|
||||||
|
otherSelections: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1766,17 +1766,17 @@ const key = 'c'`
|
|||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const { nonCodeMeta } = ast
|
const { nonCodeMeta } = ast
|
||||||
expect(nonCodeMeta.nonCodeNodes[0]?.[0]).toEqual(nonCodeMetaInstance)
|
expect(nonCodeMeta.nonCodeNodes[0][0]).toEqual(nonCodeMetaInstance)
|
||||||
|
|
||||||
// extra whitespace won't change it's position (0) or value (NB the start end would have changed though)
|
// extra whitespace won't change it's position (0) or value (NB the start end would have changed though)
|
||||||
const codeWithExtraStartWhitespace = '\n\n\n' + code
|
const codeWithExtraStartWhitespace = '\n\n\n' + code
|
||||||
const ast2 = parse(codeWithExtraStartWhitespace)
|
const ast2 = parse(codeWithExtraStartWhitespace)
|
||||||
if (err(ast2)) throw ast2
|
if (err(ast2)) throw ast2
|
||||||
const { nonCodeMeta: nonCodeMeta2 } = ast2
|
const { nonCodeMeta: nonCodeMeta2 } = ast2
|
||||||
expect(nonCodeMeta2.nonCodeNodes[0]?.[0].value).toStrictEqual(
|
expect(nonCodeMeta2.nonCodeNodes[0][0].value).toStrictEqual(
|
||||||
nonCodeMetaInstance.value
|
nonCodeMetaInstance.value
|
||||||
)
|
)
|
||||||
expect(nonCodeMeta2.nonCodeNodes[0]?.[0].start).not.toBe(
|
expect(nonCodeMeta2.nonCodeNodes[0][0].start).not.toBe(
|
||||||
nonCodeMetaInstance.start
|
nonCodeMetaInstance.start
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -400,7 +400,7 @@ const sketch001 = startSketchOn(part001, seg01)`)
|
|||||||
ast,
|
ast,
|
||||||
sketchPathToNode,
|
sketchPathToNode,
|
||||||
extrudePathToNode,
|
extrudePathToNode,
|
||||||
{ type: 'cap', subType: 'end' }
|
'end'
|
||||||
)
|
)
|
||||||
if (err(extruded)) throw extruded
|
if (err(extruded)) throw extruded
|
||||||
const { modifiedAst } = extruded
|
const { modifiedAst } = extruded
|
||||||
|
@ -41,7 +41,6 @@ import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
|
|||||||
import { SimplifiedArgDetails } from './std/stdTypes'
|
import { SimplifiedArgDetails } from './std/stdTypes'
|
||||||
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import { ExtrudeFacePlane } from 'machines/modelingMachine'
|
|
||||||
|
|
||||||
export function startSketchOnDefault(
|
export function startSketchOnDefault(
|
||||||
node: Program,
|
node: Program,
|
||||||
@ -443,7 +442,7 @@ export function sketchOnExtrudedFace(
|
|||||||
node: Program,
|
node: Program,
|
||||||
sketchPathToNode: PathToNode,
|
sketchPathToNode: PathToNode,
|
||||||
extrudePathToNode: PathToNode,
|
extrudePathToNode: PathToNode,
|
||||||
info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' }
|
cap: 'none' | 'start' | 'end' = 'none'
|
||||||
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
|
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
|
||||||
let _node = { ...node }
|
let _node = { ...node }
|
||||||
const newSketchName = findUniqueName(
|
const newSketchName = findUniqueName(
|
||||||
@ -477,22 +476,21 @@ export function sketchOnExtrudedFace(
|
|||||||
const { node: extrudeVarDec } = _node3
|
const { node: extrudeVarDec } = _node3
|
||||||
const extrudeName = extrudeVarDec.id?.name
|
const extrudeName = extrudeVarDec.id?.name
|
||||||
|
|
||||||
let _tag
|
let _tag = null
|
||||||
if (info.type !== 'cap') {
|
if (cap === 'none') {
|
||||||
const __tag = addTagForSketchOnFace(
|
const __tag = addTagForSketchOnFace(
|
||||||
{
|
{
|
||||||
pathToNode: sketchPathToNode,
|
pathToNode: sketchPathToNode,
|
||||||
node: _node,
|
node: _node,
|
||||||
},
|
},
|
||||||
expression.callee.name,
|
expression.callee.name
|
||||||
info.type === 'edgeCut' ? info : null
|
|
||||||
)
|
)
|
||||||
if (err(__tag)) return __tag
|
if (err(__tag)) return __tag
|
||||||
const { modifiedAst, tag } = __tag
|
const { modifiedAst, tag } = __tag
|
||||||
_tag = createIdentifier(tag)
|
_tag = createIdentifier(tag)
|
||||||
_node = modifiedAst
|
_node = modifiedAst
|
||||||
} else {
|
} else {
|
||||||
_tag = createLiteral(info.subType.toUpperCase())
|
_tag = createLiteral(cap.toUpperCase())
|
||||||
}
|
}
|
||||||
|
|
||||||
const newSketch = createVariableDeclaration(
|
const newSketch = createVariableDeclaration(
|
||||||
|
@ -65,7 +65,7 @@ export function modifyAstWithFilletAndTag(
|
|||||||
ast: Program,
|
ast: Program,
|
||||||
selection: Selections,
|
selection: Selections,
|
||||||
radius: KclCommandValue
|
radius: KclCommandValue
|
||||||
): { modifiedAst: Program; pathToFilletNode: Array<PathToNode> } | Error {
|
): { modifiedAst: Program; pathToFilletNode: PathToNode } | Error {
|
||||||
const astResult = insertRadiusIntoAst(ast, radius)
|
const astResult = insertRadiusIntoAst(ast, radius)
|
||||||
if (err(astResult)) return astResult
|
if (err(astResult)) return astResult
|
||||||
|
|
||||||
@ -73,8 +73,7 @@ export function modifyAstWithFilletAndTag(
|
|||||||
const artifactGraph = engineCommandManager.artifactGraph
|
const artifactGraph = engineCommandManager.artifactGraph
|
||||||
|
|
||||||
let clonedAst = structuredClone(ast)
|
let clonedAst = structuredClone(ast)
|
||||||
const clonedAstForGetExtrude = structuredClone(ast)
|
let lastPathToFilletNode: PathToNode = []
|
||||||
let pathToFilletNodes: Array<PathToNode> = []
|
|
||||||
|
|
||||||
for (const selectionRange of selection.codeBasedSelections) {
|
for (const selectionRange of selection.codeBasedSelections) {
|
||||||
const singleSelection = {
|
const singleSelection = {
|
||||||
@ -83,7 +82,7 @@ export function modifyAstWithFilletAndTag(
|
|||||||
}
|
}
|
||||||
const getPathToExtrudeForSegmentSelectionResult =
|
const getPathToExtrudeForSegmentSelectionResult =
|
||||||
getPathToExtrudeForSegmentSelection(
|
getPathToExtrudeForSegmentSelection(
|
||||||
clonedAstForGetExtrude,
|
clonedAst,
|
||||||
singleSelection,
|
singleSelection,
|
||||||
programMemory,
|
programMemory,
|
||||||
artifactGraph
|
artifactGraph
|
||||||
@ -102,9 +101,9 @@ export function modifyAstWithFilletAndTag(
|
|||||||
if (trap(addFilletResult)) return addFilletResult
|
if (trap(addFilletResult)) return addFilletResult
|
||||||
const { modifiedAst, pathToFilletNode } = addFilletResult
|
const { modifiedAst, pathToFilletNode } = addFilletResult
|
||||||
clonedAst = modifiedAst
|
clonedAst = modifiedAst
|
||||||
pathToFilletNodes.push(pathToFilletNode)
|
lastPathToFilletNode = pathToFilletNode
|
||||||
}
|
}
|
||||||
return { modifiedAst: clonedAst, pathToFilletNode: pathToFilletNodes }
|
return { modifiedAst: clonedAst, pathToFilletNode: lastPathToFilletNode }
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertRadiusIntoAst(
|
function insertRadiusIntoAst(
|
||||||
@ -167,7 +166,7 @@ export function getPathToExtrudeForSegmentSelection(
|
|||||||
|
|
||||||
async function updateAstAndFocus(
|
async function updateAstAndFocus(
|
||||||
modifiedAst: Program,
|
modifiedAst: Program,
|
||||||
pathToFilletNode: Array<PathToNode>
|
pathToFilletNode: PathToNode
|
||||||
) {
|
) {
|
||||||
const updatedAst = await kclManager.updateAst(modifiedAst, true, {
|
const updatedAst = await kclManager.updateAst(modifiedAst, true, {
|
||||||
focusPath: pathToFilletNode,
|
focusPath: pathToFilletNode,
|
||||||
@ -234,8 +233,7 @@ function mutateAstWithTagForSketchSegment(
|
|||||||
pathToNode: pathToSegmentNode,
|
pathToNode: pathToSegmentNode,
|
||||||
node: astClone,
|
node: astClone,
|
||||||
},
|
},
|
||||||
segmentNode.node.callee.name,
|
segmentNode.node.callee.name
|
||||||
null
|
|
||||||
)
|
)
|
||||||
if (err(taggedSegment)) return taggedSegment
|
if (err(taggedSegment)) return taggedSegment
|
||||||
const { tag } = taggedSegment
|
const { tag } = taggedSegment
|
||||||
|
@ -42,7 +42,7 @@ export interface PathArtifactRich {
|
|||||||
codeRef: CommonCommandProperties
|
codeRef: CommonCommandProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SegmentArtifact {
|
interface SegmentArtifact {
|
||||||
type: 'segment'
|
type: 'segment'
|
||||||
pathId: ArtifactId
|
pathId: ArtifactId
|
||||||
surfaceId: ArtifactId
|
surfaceId: ArtifactId
|
||||||
@ -436,10 +436,10 @@ export function getArtifactsToUpdate({
|
|||||||
response.data.modeling_response.type === 'solid3d_get_opposite_edge' &&
|
response.data.modeling_response.type === 'solid3d_get_opposite_edge' &&
|
||||||
response.data.modeling_response.data.edge) ||
|
response.data.modeling_response.data.edge) ||
|
||||||
// or is adjacent edge
|
// or is adjacent edge
|
||||||
(cmd.type === 'solid3d_get_next_adjacent_edge' &&
|
(cmd.type === 'solid3d_get_prev_adjacent_edge' &&
|
||||||
response.type === 'modeling' &&
|
response.type === 'modeling' &&
|
||||||
response.data.modeling_response.type ===
|
response.data.modeling_response.type ===
|
||||||
'solid3d_get_next_adjacent_edge' &&
|
'solid3d_get_prev_adjacent_edge' &&
|
||||||
response.data.modeling_response.data.edge)
|
response.data.modeling_response.data.edge)
|
||||||
) {
|
) {
|
||||||
const wall = getArtifact(cmd.face_id)
|
const wall = getArtifact(cmd.face_id)
|
||||||
@ -457,7 +457,7 @@ export function getArtifactsToUpdate({
|
|||||||
artifact: {
|
artifact: {
|
||||||
type: 'sweepEdge',
|
type: 'sweepEdge',
|
||||||
subType:
|
subType:
|
||||||
cmd.type === 'solid3d_get_next_adjacent_edge'
|
cmd.type === 'solid3d_get_prev_adjacent_edge'
|
||||||
? 'adjacent'
|
? 'adjacent'
|
||||||
: 'opposite',
|
: 'opposite',
|
||||||
segId: cmd.edge_id,
|
segId: cmd.edge_id,
|
||||||
@ -724,55 +724,21 @@ export function getSweepEdgeCodeRef(
|
|||||||
if (err(seg)) return seg
|
if (err(seg)) return seg
|
||||||
return seg.codeRef
|
return seg.codeRef
|
||||||
}
|
}
|
||||||
export function getEdgeCuteConsumedCodeRef(
|
|
||||||
edge: EdgeCut,
|
|
||||||
artifactGraph: ArtifactGraph
|
|
||||||
): CommonCommandProperties | Error {
|
|
||||||
const seg = getArtifactOfTypes(
|
|
||||||
{ key: edge.consumedEdgeId, types: ['segment', 'sweepEdge'] },
|
|
||||||
artifactGraph
|
|
||||||
)
|
|
||||||
if (err(seg)) return seg
|
|
||||||
if (seg.type === 'segment') return seg.codeRef
|
|
||||||
return getSweepEdgeCodeRef(seg, artifactGraph)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getSweepFromSuspectedSweepSurface(
|
export function getSweepFromSuspectedSweepSurface(
|
||||||
id: ArtifactId,
|
id: ArtifactId,
|
||||||
artifactGraph: ArtifactGraph
|
artifactGraph: ArtifactGraph
|
||||||
): SweepArtifact | Error {
|
): SweepArtifact | Error {
|
||||||
const artifact = getArtifactOfTypes(
|
const artifact = getArtifactOfTypes(
|
||||||
{ key: id, types: ['wall', 'cap', 'edgeCut'] },
|
{ key: id, types: ['wall', 'cap'] },
|
||||||
artifactGraph
|
artifactGraph
|
||||||
)
|
)
|
||||||
if (err(artifact)) return artifact
|
if (err(artifact)) return artifact
|
||||||
if (artifact.type === 'wall' || artifact.type === 'cap') {
|
|
||||||
return getArtifactOfTypes(
|
return getArtifactOfTypes(
|
||||||
{ key: artifact.sweepId, types: ['sweep'] },
|
{ key: artifact.sweepId, types: ['sweep'] },
|
||||||
artifactGraph
|
artifactGraph
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const segOrEdge = getArtifactOfTypes(
|
|
||||||
{ key: artifact.consumedEdgeId, types: ['segment', 'sweepEdge'] },
|
|
||||||
artifactGraph
|
|
||||||
)
|
|
||||||
if (err(segOrEdge)) return segOrEdge
|
|
||||||
if (segOrEdge.type === 'segment') {
|
|
||||||
const path = getArtifactOfTypes(
|
|
||||||
{ key: segOrEdge.pathId, types: ['path'] },
|
|
||||||
artifactGraph
|
|
||||||
)
|
|
||||||
if (err(path)) return path
|
|
||||||
return getArtifactOfTypes(
|
|
||||||
{ key: path.sweepId, types: ['sweep'] },
|
|
||||||
artifactGraph
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return getArtifactOfTypes(
|
|
||||||
{ key: segOrEdge.sweepId, types: ['sweep'] },
|
|
||||||
artifactGraph
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getSweepFromSuspectedPath(
|
export function getSweepFromSuspectedPath(
|
||||||
id: ArtifactId,
|
id: ArtifactId,
|
||||||
|
@ -231,8 +231,7 @@ describe('testing addTagForSketchOnFace', () => {
|
|||||||
pathToNode,
|
pathToNode,
|
||||||
node: ast,
|
node: ast,
|
||||||
},
|
},
|
||||||
'lineTo',
|
'lineTo'
|
||||||
null
|
|
||||||
)
|
)
|
||||||
if (err(sketchOnFaceRetVal)) return sketchOnFaceRetVal
|
if (err(sketchOnFaceRetVal)) return sketchOnFaceRetVal
|
||||||
|
|
||||||
@ -240,62 +239,6 @@ describe('testing addTagForSketchOnFace', () => {
|
|||||||
const expectedCode = genCode('lineTo([-1.59, -1.54], %, $seg01)')
|
const expectedCode = genCode('lineTo([-1.59, -1.54], %, $seg01)')
|
||||||
expect(recast(modifiedAst)).toBe(expectedCode)
|
expect(recast(modifiedAst)).toBe(expectedCode)
|
||||||
})
|
})
|
||||||
it('can break up chamfers in order to add tags', async () => {
|
|
||||||
const originalChamfer = `|> chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [seg01, getOppositeEdge(seg01)]
|
|
||||||
}, %)`
|
|
||||||
const genCode = (
|
|
||||||
insertCode: string
|
|
||||||
) => `const sketch001 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
|
||||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001) - 90,
|
|
||||||
217.26
|
|
||||||
], %, $seg01)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001),
|
|
||||||
-segLen(rectangleSegmentA001)
|
|
||||||
], %)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg02)
|
|
||||||
|> close(%)
|
|
||||||
const extrude001 = extrude(100, sketch001)
|
|
||||||
${insertCode}
|
|
||||||
`
|
|
||||||
const code = genCode(originalChamfer)
|
|
||||||
const ast = parse(code)
|
|
||||||
await enginelessExecutor(ast)
|
|
||||||
const sourceStart = code.indexOf(originalChamfer)
|
|
||||||
const sourceRange: [number, number] = [
|
|
||||||
sourceStart + 3,
|
|
||||||
sourceStart + originalChamfer.length - 3,
|
|
||||||
]
|
|
||||||
|
|
||||||
if (err(ast)) throw ast
|
|
||||||
const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
|
|
||||||
console.log('pathToNode', pathToNode)
|
|
||||||
const sketchOnFaceRetVal = addTagForSketchOnFace(
|
|
||||||
{
|
|
||||||
pathToNode,
|
|
||||||
node: ast,
|
|
||||||
},
|
|
||||||
'chamfer',
|
|
||||||
{
|
|
||||||
type: 'edgeCut',
|
|
||||||
subType: 'opposite',
|
|
||||||
tagName: 'seg01',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (err(sketchOnFaceRetVal)) throw sketchOnFaceRetVal
|
|
||||||
expect(recast(sketchOnFaceRetVal.modifiedAst)).toBe(
|
|
||||||
genCode(`|> chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [getOppositeEdge(seg01)]
|
|
||||||
}, %, $seg03)
|
|
||||||
|> chamfer({ length: 30, tags: [seg01] }, %)`)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('testing getConstraintInfo', () => {
|
describe('testing getConstraintInfo', () => {
|
||||||
|
@ -53,7 +53,6 @@ import { roundOff, getLength, getAngle } from 'lib/utils'
|
|||||||
import { err } from 'lib/trap'
|
import { err } from 'lib/trap'
|
||||||
import { perpendicularDistance } from 'sketch-helpers'
|
import { perpendicularDistance } from 'sketch-helpers'
|
||||||
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
||||||
import { EdgeCutInfo } from 'machines/modelingMachine'
|
|
||||||
|
|
||||||
const STRAIGHT_SEGMENT_ERR = new Error(
|
const STRAIGHT_SEGMENT_ERR = new Error(
|
||||||
'Invalid input, expected "straight-segment"'
|
'Invalid input, expected "straight-segment"'
|
||||||
@ -1896,131 +1895,13 @@ export function replaceSketchLine({
|
|||||||
return { modifiedAst, valueUsedInTransform, pathToNode }
|
return { modifiedAst, valueUsedInTransform, pathToNode }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ostensibly should be used to add a chamfer tag to a chamfer call expression
|
|
||||||
*
|
|
||||||
* However things get complicated in situations like:
|
|
||||||
* ```ts
|
|
||||||
* |> chamfer({
|
|
||||||
* length: 1,
|
|
||||||
* tags: [tag1, tagOfInterest]
|
|
||||||
* }, %)
|
|
||||||
* ```
|
|
||||||
* Because tag declarator is not allowed on a chamfer with more than one tag,
|
|
||||||
* They must be pulled apart into separate chamfer calls:
|
|
||||||
* ```ts
|
|
||||||
* |> chamfer({
|
|
||||||
* length: 1,
|
|
||||||
* tags: [tag1]
|
|
||||||
* }, %)
|
|
||||||
* |> chamfer({
|
|
||||||
* length: 1,
|
|
||||||
* tags: [tagOfInterest]
|
|
||||||
* }, %, $newTagDeclarator)
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
function addTagToChamfer(
|
|
||||||
tagInfo: AddTagInfo,
|
|
||||||
edgeCutMeta: EdgeCutInfo | null
|
|
||||||
):
|
|
||||||
| {
|
|
||||||
modifiedAst: Program
|
|
||||||
tag: string
|
|
||||||
}
|
|
||||||
| Error {
|
|
||||||
const _node = structuredClone(tagInfo.node)
|
|
||||||
let pipeIndex = 0
|
|
||||||
for (let i = 0; i < tagInfo.pathToNode.length; i++) {
|
|
||||||
if (tagInfo.pathToNode[i][1] === 'PipeExpression') {
|
|
||||||
pipeIndex = Number(tagInfo.pathToNode[i + 1][0])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const pipeExpr = getNodeFromPath<PipeExpression>(
|
|
||||||
_node,
|
|
||||||
tagInfo.pathToNode,
|
|
||||||
'PipeExpression'
|
|
||||||
)
|
|
||||||
if (err(pipeExpr)) return pipeExpr
|
|
||||||
const callExpr = pipeExpr.node.body[pipeIndex]
|
|
||||||
if (callExpr.type !== 'CallExpression')
|
|
||||||
return new Error('no chamfer call Expr')
|
|
||||||
const obj = callExpr.arguments[0]
|
|
||||||
if (obj.type !== 'ObjectExpression')
|
|
||||||
return new Error('first argument should be an object expression')
|
|
||||||
const tags = obj.properties.find((a) => {
|
|
||||||
return a.key.name === 'tags'
|
|
||||||
})
|
|
||||||
if (!tags) return new Error('no tags property')
|
|
||||||
if (tags.value.type !== 'ArrayExpression')
|
|
||||||
return new Error('tags should be an array expression')
|
|
||||||
if (tags.value.elements.length < 2) {
|
|
||||||
return addTag(2)(tagInfo)
|
|
||||||
}
|
|
||||||
const tagIndexToPullOut = tags.value.elements.findIndex((element) => {
|
|
||||||
if (
|
|
||||||
edgeCutMeta?.subType === 'base' &&
|
|
||||||
element.type === 'Identifier' &&
|
|
||||||
element.name === edgeCutMeta.tagName
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
if (
|
|
||||||
edgeCutMeta?.subType === 'opposite' &&
|
|
||||||
element.type === 'CallExpression' &&
|
|
||||||
element.callee.name === 'getOppositeEdge' &&
|
|
||||||
element.arguments[0].type === 'Identifier' &&
|
|
||||||
element.arguments[0].name === edgeCutMeta.tagName
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
if (
|
|
||||||
edgeCutMeta?.subType === 'adjacent' &&
|
|
||||||
element.type === 'CallExpression' &&
|
|
||||||
(element.callee.name === 'getNextAdjacentEdge' ||
|
|
||||||
element.callee.name === 'getPrevAdjacentEdge') &&
|
|
||||||
element.arguments[0].type === 'Identifier' &&
|
|
||||||
element.arguments[0].name === edgeCutMeta.tagName
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
if (tagIndexToPullOut === -1) return new Error('tag not found')
|
|
||||||
const tagToPullOut = tags.value.elements[tagIndexToPullOut]
|
|
||||||
tags.value.elements.splice(tagIndexToPullOut, 1)
|
|
||||||
const chamferLength = obj.properties.find(
|
|
||||||
(a) => a.key.name === 'length'
|
|
||||||
)?.value
|
|
||||||
if (!chamferLength) return new Error('no chamfer length')
|
|
||||||
const tagDec = createTagDeclarator(findUniqueName(_node, 'seg', 2))
|
|
||||||
const newExpressionToInsert = createCallExpression('chamfer', [
|
|
||||||
createObjectExpression({
|
|
||||||
length: chamferLength,
|
|
||||||
tags: createArrayExpression([tagToPullOut]),
|
|
||||||
}),
|
|
||||||
createPipeSubstitution(),
|
|
||||||
tagDec,
|
|
||||||
])
|
|
||||||
pipeExpr.node.body.splice(pipeIndex, 0, newExpressionToInsert)
|
|
||||||
return {
|
|
||||||
modifiedAst: _node,
|
|
||||||
tag: tagDec.value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addTagForSketchOnFace(
|
export function addTagForSketchOnFace(
|
||||||
tagInfo: AddTagInfo,
|
tagInfo: AddTagInfo,
|
||||||
expressionName: string,
|
expressionName: string
|
||||||
edgeCutMeta: EdgeCutInfo | null
|
) {
|
||||||
):
|
|
||||||
| {
|
|
||||||
modifiedAst: Program
|
|
||||||
tag: string
|
|
||||||
}
|
|
||||||
| Error {
|
|
||||||
if (expressionName === 'close') {
|
if (expressionName === 'close') {
|
||||||
return addTag(1)(tagInfo)
|
return addTag(1)(tagInfo)
|
||||||
}
|
}
|
||||||
if (expressionName === 'chamfer') {
|
|
||||||
return addTagToChamfer(tagInfo, edgeCutMeta)
|
|
||||||
}
|
|
||||||
if (expressionName in sketchLineHelperMap) {
|
if (expressionName in sketchLineHelperMap) {
|
||||||
const { addTag } = sketchLineHelperMap[expressionName]
|
const { addTag } = sketchLineHelperMap[expressionName]
|
||||||
return addTag(tagInfo)
|
return addTag(tagInfo)
|
||||||
|
@ -18,24 +18,12 @@ export function pathMapToSelections(
|
|||||||
const nodeMeta = getNodeFromPath<any>(ast, path)
|
const nodeMeta = getNodeFromPath<any>(ast, path)
|
||||||
if (err(nodeMeta)) return
|
if (err(nodeMeta)) return
|
||||||
const node = nodeMeta.node as any
|
const node = nodeMeta.node as any
|
||||||
const selection = prevSelections.codeBasedSelections[Number(index)]
|
const type = prevSelections.codeBasedSelections[Number(index)].type
|
||||||
if (node) {
|
if (node) {
|
||||||
if (
|
|
||||||
selection.type === 'base-edgeCut' ||
|
|
||||||
selection.type === 'adjacent-edgeCut' ||
|
|
||||||
selection.type === 'opposite-edgeCut'
|
|
||||||
) {
|
|
||||||
newSelections.codeBasedSelections.push({
|
newSelections.codeBasedSelections.push({
|
||||||
range: [node.start, node.end],
|
range: [node.start, node.end],
|
||||||
type: selection.type,
|
type: type || 'default',
|
||||||
secondaryRange: selection.secondaryRange,
|
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
newSelections.codeBasedSelections.push({
|
|
||||||
range: [node.start, node.end],
|
|
||||||
type: selection.type,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return newSelections
|
return newSelections
|
||||||
|
@ -41,8 +41,7 @@ export const Y_AXIS_UUID = '680fd157-266f-4b8a-984f-cdf46b8bdf01'
|
|||||||
|
|
||||||
export type Axis = 'y-axis' | 'x-axis' | 'z-axis'
|
export type Axis = 'y-axis' | 'x-axis' | 'z-axis'
|
||||||
|
|
||||||
export type Selection =
|
export type Selection = {
|
||||||
| {
|
|
||||||
type:
|
type:
|
||||||
| 'default'
|
| 'default'
|
||||||
| 'line-end'
|
| 'line-end'
|
||||||
@ -59,12 +58,6 @@ export type Selection =
|
|||||||
| 'all'
|
| 'all'
|
||||||
range: SourceRange
|
range: SourceRange
|
||||||
}
|
}
|
||||||
| {
|
|
||||||
type: 'opposite-edgeCut' | 'adjacent-edgeCut' | 'base-edgeCut'
|
|
||||||
range: SourceRange
|
|
||||||
// TODO this is a temporary measure that well be made redundant with: https://github.com/KittyCAD/modeling-app/pull/3836
|
|
||||||
secondaryRange: SourceRange
|
|
||||||
}
|
|
||||||
export type Selections = {
|
export type Selections = {
|
||||||
otherSelections: Axis[]
|
otherSelections: Axis[]
|
||||||
codeBasedSelections: Selection[]
|
codeBasedSelections: Selection[]
|
||||||
@ -171,52 +164,6 @@ export async function getEventForSelectWithPoint({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_artifact.type === 'edgeCut') {
|
|
||||||
const consumedEdge = getArtifactOfTypes(
|
|
||||||
{ key: _artifact.consumedEdgeId, types: ['segment', 'sweepEdge'] },
|
|
||||||
engineCommandManager.artifactGraph
|
|
||||||
)
|
|
||||||
if (err(consumedEdge))
|
|
||||||
return {
|
|
||||||
type: 'Set selection',
|
|
||||||
data: {
|
|
||||||
selectionType: 'singleCodeCursor',
|
|
||||||
selection: { range: _artifact.codeRef.range, type: 'default' },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if (consumedEdge.type === 'segment') {
|
|
||||||
return {
|
|
||||||
type: 'Set selection',
|
|
||||||
data: {
|
|
||||||
selectionType: 'singleCodeCursor',
|
|
||||||
selection: {
|
|
||||||
range: _artifact.codeRef.range,
|
|
||||||
type: 'base-edgeCut',
|
|
||||||
secondaryRange: consumedEdge.codeRef.range,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const segment = getArtifactOfTypes(
|
|
||||||
{ key: consumedEdge.segId, types: ['segment'] },
|
|
||||||
engineCommandManager.artifactGraph
|
|
||||||
)
|
|
||||||
if (err(segment)) return null
|
|
||||||
return {
|
|
||||||
type: 'Set selection',
|
|
||||||
data: {
|
|
||||||
selectionType: 'singleCodeCursor',
|
|
||||||
selection: {
|
|
||||||
range: _artifact.codeRef.range,
|
|
||||||
type:
|
|
||||||
consumedEdge.subType === 'adjacent'
|
|
||||||
? 'adjacent-edgeCut'
|
|
||||||
: 'opposite-edgeCut',
|
|
||||||
secondaryRange: segment.codeRef.range,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,54 +625,6 @@ function codeToIdSelections(
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (entry.artifact.type === 'edgeCut') {
|
|
||||||
const consumedEdge = getArtifactOfTypes(
|
|
||||||
{
|
|
||||||
key: entry.artifact.consumedEdgeId,
|
|
||||||
types: ['segment', 'sweepEdge'],
|
|
||||||
},
|
|
||||||
engineCommandManager.artifactGraph
|
|
||||||
)
|
|
||||||
if (err(consumedEdge)) return
|
|
||||||
if (
|
|
||||||
consumedEdge.type === 'segment' &&
|
|
||||||
type === 'base-edgeCut' &&
|
|
||||||
isOverlap(
|
|
||||||
consumedEdge.codeRef.range,
|
|
||||||
entry.selection?.secondaryRange || [0, 0]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
bestCandidate = {
|
|
||||||
artifact: entry.artifact,
|
|
||||||
selection: { type, range, ...rest },
|
|
||||||
id: entry.id,
|
|
||||||
}
|
|
||||||
} else if (
|
|
||||||
consumedEdge.type === 'sweepEdge' &&
|
|
||||||
((type === 'adjacent-edgeCut' &&
|
|
||||||
consumedEdge.subType === 'adjacent') ||
|
|
||||||
(type === 'opposite-edgeCut' &&
|
|
||||||
consumedEdge.subType === 'opposite'))
|
|
||||||
) {
|
|
||||||
const seg = getArtifactOfTypes(
|
|
||||||
{ key: consumedEdge.segId, types: ['segment'] },
|
|
||||||
engineCommandManager.artifactGraph
|
|
||||||
)
|
|
||||||
if (err(seg)) return
|
|
||||||
if (
|
|
||||||
isOverlap(
|
|
||||||
seg.codeRef.range,
|
|
||||||
entry.selection?.secondaryRange || [0, 0]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
bestCandidate = {
|
|
||||||
artifact: entry.artifact,
|
|
||||||
selection: { type, range, ...rest },
|
|
||||||
id: entry.id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (bestCandidate) {
|
if (bestCandidate) {
|
||||||
@ -787,20 +686,9 @@ export function updateSelections(
|
|||||||
const nodeMeta = getNodeFromPath<Expr>(ast, pathToNode)
|
const nodeMeta = getNodeFromPath<Expr>(ast, pathToNode)
|
||||||
if (err(nodeMeta)) return undefined
|
if (err(nodeMeta)) return undefined
|
||||||
const node = nodeMeta.node
|
const node = nodeMeta.node
|
||||||
const selection = prevSelectionRanges.codeBasedSelections[Number(index)]
|
|
||||||
if (
|
|
||||||
selection?.type === 'base-edgeCut' ||
|
|
||||||
selection?.type === 'adjacent-edgeCut' ||
|
|
||||||
selection?.type === 'opposite-edgeCut'
|
|
||||||
)
|
|
||||||
return {
|
return {
|
||||||
range: [node.start, node.end],
|
range: [node.start, node.end],
|
||||||
type: selection?.type,
|
type: prevSelectionRanges.codeBasedSelections[Number(index)]?.type,
|
||||||
secondaryRange: selection?.secondaryRange,
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
range: [node.start, node.end],
|
|
||||||
type: selection?.type,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter((x?: Selection) => x !== undefined) as Selection[]
|
.filter((x?: Selection) => x !== undefined) as Selection[]
|
||||||
|
File diff suppressed because one or more lines are too long
19
src/wasm-lib/Cargo.lock
generated
19
src/wasm-lib/Cargo.lock
generated
@ -255,9 +255,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bson"
|
name = "bson"
|
||||||
version = "2.13.0"
|
version = "2.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "068208f2b6fcfa27a7f1ee37488d2bb8ba2640f68f5475d08e1d9130696aba59"
|
checksum = "80cf6f7806607bd58ad490bab34bf60e25455ea4aaf995f897a13324d41ea580"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
@ -1400,7 +1400,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.2.17"
|
version = "0.2.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx 0.5.1",
|
"approx 0.5.1",
|
||||||
@ -1526,9 +1526,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad-modeling-cmds"
|
name = "kittycad-modeling-cmds"
|
||||||
version = "0.2.61"
|
version = "0.2.59"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5128ba683e849388cac4214b65911c343842d559bec10827575c840a47733786"
|
checksum = "ee900033a5804ca2354f0760478e851a0ab04d32b38a9117d0bd4f87a8867110"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -3427,12 +3427,11 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ts-rs"
|
name = "ts-rs"
|
||||||
version = "10.0.0"
|
version = "9.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a2f31991cee3dce1ca4f929a8a04fdd11fd8801aac0f2030b0fa8a0a3fef6b9"
|
checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"lazy_static",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"ts-rs-macros",
|
"ts-rs-macros",
|
||||||
@ -3442,9 +3441,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ts-rs-macros"
|
name = "ts-rs-macros"
|
||||||
version = "10.0.0"
|
version = "9.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ea0b99e8ec44abd6f94a18f28f7934437809dd062820797c52401298116f70e"
|
checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -10,7 +10,7 @@ rust-version = "1.73"
|
|||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bson = { version = "2.13.0", features = ["uuid-1", "chrono"] }
|
bson = { version = "2.12.0", features = ["uuid-1", "chrono"] }
|
||||||
data-encoding = "2.6.0"
|
data-encoding = "2.6.0"
|
||||||
gloo-utils = "0.2.0"
|
gloo-utils = "0.2.0"
|
||||||
kcl-lib = { path = "kcl" }
|
kcl-lib = { path = "kcl" }
|
||||||
@ -73,7 +73,7 @@ members = [
|
|||||||
http = "0.2.12"
|
http = "0.2.12"
|
||||||
kittycad = { version = "0.3.20", default-features = false, features = ["js", "requests"] }
|
kittycad = { version = "0.3.20", default-features = false, features = ["js", "requests"] }
|
||||||
kittycad-modeling-session = "0.1.4"
|
kittycad-modeling-session = "0.1.4"
|
||||||
kittycad-modeling-cmds = { version = "0.2.61", features = ["websocket"] }
|
kittycad-modeling-cmds = { version = "0.2.59", features = ["websocket"] }
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "executor"
|
name = "executor"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language implementation and tools"
|
description = "KittyCAD Language implementation and tools"
|
||||||
version = "0.2.17"
|
version = "0.2.16"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
@ -44,7 +44,7 @@ sha2 = "0.10.8"
|
|||||||
tabled = { version = "0.15.0", optional = true }
|
tabled = { version = "0.15.0", optional = true }
|
||||||
thiserror = "1.0.63"
|
thiserror = "1.0.63"
|
||||||
toml = "0.8.19"
|
toml = "0.8.19"
|
||||||
ts-rs = { version = "10.0.0", features = ["uuid-impl", "url-impl", "chrono-impl", "no-serde-warnings", "serde-json-impl"] }
|
ts-rs = { version = "9.0.1", features = ["uuid-impl", "url-impl", "chrono-impl", "no-serde-warnings", "serde-json-impl"] }
|
||||||
url = { version = "2.5.2", features = ["serde"] }
|
url = { version = "2.5.2", features = ["serde"] }
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
uuid = { version = "1.10.0", features = ["v4", "js", "serde"] }
|
uuid = { version = "1.10.0", features = ["v4", "js", "serde"] }
|
||||||
@ -62,7 +62,7 @@ web-sys = { version = "0.3.69", features = ["console"] }
|
|||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
approx = "0.5"
|
approx = "0.5"
|
||||||
bson = { version = "2.13.0", features = ["uuid-1", "chrono"] }
|
bson = { version = "2.12.0", features = ["uuid-1", "chrono"] }
|
||||||
tokio = { version = "1.39.3", features = ["full"] }
|
tokio = { version = "1.39.3", features = ["full"] }
|
||||||
tokio-tungstenite = { version = "0.24.0", features = ["rustls-tls-native-roots"] }
|
tokio-tungstenite = { version = "0.24.0", features = ["rustls-tls-native-roots"] }
|
||||||
tower-lsp = { version = "0.20.0", features = ["proposed"] }
|
tower-lsp = { version = "0.20.0", features = ["proposed"] }
|
||||||
|
@ -40,8 +40,7 @@ pub struct StdLibFnData {
|
|||||||
|
|
||||||
/// This struct defines a single argument to a stdlib function.
|
/// This struct defines a single argument to a stdlib function.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
|
||||||
// There's a bug in ts_rs where this isn't correctly imported by StdLibFnData.
|
#[ts(export)]
|
||||||
#[ts(export_to = "StdLibFnData.ts")]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct StdLibFnArg {
|
pub struct StdLibFnArg {
|
||||||
/// The name of the argument.
|
/// The name of the argument.
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
//! Functions for setting up our WebSocket and WebRTC connections for communications with the
|
//! Functions for setting up our WebSocket and WebRTC connections for communications with the
|
||||||
//! engine.
|
//! engine.
|
||||||
use std::sync::{Arc, Mutex};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -216,7 +216,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
|
|
||||||
args.batch_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
|
ModelingCmd::from(mcmd::Solid3dGetPrevAdjacentEdge {
|
||||||
edge_id: curve_id,
|
edge_id: curve_id,
|
||||||
object_id: sketch_group.id,
|
object_id: sketch_group.id,
|
||||||
face_id,
|
face_id,
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
const sketch001 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
|
||||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001) - 90,
|
|
||||||
217.26
|
|
||||||
], %, $seg01)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001),
|
|
||||||
-segLen(rectangleSegmentA001)
|
|
||||||
], %, $yo)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg02)
|
|
||||||
|> close(%)
|
|
||||||
const extrude001 = extrude(100, sketch001)
|
|
||||||
|> chamfer({
|
|
||||||
length: 30,
|
|
||||||
tags: [
|
|
||||||
seg01,
|
|
||||||
getNextAdjacentEdge(yo),
|
|
||||||
getNextAdjacentEdge(seg02),
|
|
||||||
getOppositeEdge(seg01)
|
|
||||||
]
|
|
||||||
}, %)
|
|
@ -1,51 +0,0 @@
|
|||||||
const sketch001 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([23.53, 152.5], %)
|
|
||||||
|> angledLine([0, 172.25], %, $rectangleSegmentA001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001) - 90,
|
|
||||||
110.07
|
|
||||||
], %, $rectangleSegmentB001)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA001),
|
|
||||||
-segLen(rectangleSegmentA001)
|
|
||||||
], %, $rectangleSegmentC001)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
const extrude001 = extrude(100, sketch001)
|
|
||||||
const sketch004 = startSketchOn(extrude001, 'END')
|
|
||||||
|> startProfileAt([81.71, 89.86], %)
|
|
||||||
|> line([26.96, 39.72], %)
|
|
||||||
|> line([37.27, -41.68], %, $seg03)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg04)
|
|
||||||
|> close(%)
|
|
||||||
const extrude003 = extrude(100, sketch004)
|
|
||||||
|> chamfer({
|
|
||||||
length: 22,
|
|
||||||
tags: [getNextAdjacentEdge(seg04), getOppositeEdge(seg03)]
|
|
||||||
}, %)
|
|
||||||
const sketch002 = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([272.24, 46.63], %)
|
|
||||||
|> angledLine([0, 150.77], %, $rectangleSegmentA002)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA002) + 90,
|
|
||||||
215.94
|
|
||||||
], %, $rectangleSegmentB002)
|
|
||||||
|> angledLine([
|
|
||||||
segAng(rectangleSegmentA002),
|
|
||||||
-segLen(rectangleSegmentA002)
|
|
||||||
], %, $rectangleSegmentC002)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
const extrude002 = extrude(160, sketch002)
|
|
||||||
const sketch003 = startSketchOn(extrude002, rectangleSegmentC002)
|
|
||||||
|> startProfileAt([-340.96, 50.64], %)
|
|
||||||
|> line([29.12, 77.97], %, $seg02)
|
|
||||||
|> line([19.74, -70.08], %, $seg01)
|
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
||||||
|> close(%)
|
|
||||||
const extrude004 = extrude(100, sketch003)
|
|
||||||
|> chamfer({
|
|
||||||
length: 18,
|
|
||||||
tags: [getNextAdjacentEdge(seg01), seg02]
|
|
||||||
}, %)
|
|
||||||
|
|
131
yarn.lock
131
yarn.lock
@ -3503,10 +3503,10 @@ bluebird@^3.1.1, bluebird@^3.5.5:
|
|||||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||||
|
|
||||||
body-parser@1.20.3:
|
body-parser@1.20.2:
|
||||||
version "1.20.3"
|
version "1.20.2"
|
||||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
|
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
|
||||||
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
|
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes "3.1.2"
|
bytes "3.1.2"
|
||||||
content-type "~1.0.5"
|
content-type "~1.0.5"
|
||||||
@ -3516,7 +3516,7 @@ body-parser@1.20.3:
|
|||||||
http-errors "2.0.0"
|
http-errors "2.0.0"
|
||||||
iconv-lite "0.4.24"
|
iconv-lite "0.4.24"
|
||||||
on-finished "2.4.1"
|
on-finished "2.4.1"
|
||||||
qs "6.13.0"
|
qs "6.11.0"
|
||||||
raw-body "2.5.2"
|
raw-body "2.5.2"
|
||||||
type-is "~1.6.18"
|
type-is "~1.6.18"
|
||||||
unpipe "1.0.0"
|
unpipe "1.0.0"
|
||||||
@ -4627,11 +4627,6 @@ encodeurl@~1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||||
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
||||||
|
|
||||||
encodeurl@~2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
|
|
||||||
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
|
|
||||||
|
|
||||||
encoding@^0.1.13:
|
encoding@^0.1.13:
|
||||||
version "0.1.13"
|
version "0.1.13"
|
||||||
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
|
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
|
||||||
@ -5208,36 +5203,36 @@ express-ws@^5.0.2:
|
|||||||
ws "^7.4.6"
|
ws "^7.4.6"
|
||||||
|
|
||||||
express@^4.17.1:
|
express@^4.17.1:
|
||||||
version "4.21.0"
|
version "4.19.2"
|
||||||
resolved "https://registry.yarnpkg.com/express/-/express-4.21.0.tgz#d57cb706d49623d4ac27833f1cbc466b668eb915"
|
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
|
||||||
integrity sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==
|
integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
accepts "~1.3.8"
|
accepts "~1.3.8"
|
||||||
array-flatten "1.1.1"
|
array-flatten "1.1.1"
|
||||||
body-parser "1.20.3"
|
body-parser "1.20.2"
|
||||||
content-disposition "0.5.4"
|
content-disposition "0.5.4"
|
||||||
content-type "~1.0.4"
|
content-type "~1.0.4"
|
||||||
cookie "0.6.0"
|
cookie "0.6.0"
|
||||||
cookie-signature "1.0.6"
|
cookie-signature "1.0.6"
|
||||||
debug "2.6.9"
|
debug "2.6.9"
|
||||||
depd "2.0.0"
|
depd "2.0.0"
|
||||||
encodeurl "~2.0.0"
|
encodeurl "~1.0.2"
|
||||||
escape-html "~1.0.3"
|
escape-html "~1.0.3"
|
||||||
etag "~1.8.1"
|
etag "~1.8.1"
|
||||||
finalhandler "1.3.1"
|
finalhandler "1.2.0"
|
||||||
fresh "0.5.2"
|
fresh "0.5.2"
|
||||||
http-errors "2.0.0"
|
http-errors "2.0.0"
|
||||||
merge-descriptors "1.0.3"
|
merge-descriptors "1.0.1"
|
||||||
methods "~1.1.2"
|
methods "~1.1.2"
|
||||||
on-finished "2.4.1"
|
on-finished "2.4.1"
|
||||||
parseurl "~1.3.3"
|
parseurl "~1.3.3"
|
||||||
path-to-regexp "0.1.10"
|
path-to-regexp "0.1.7"
|
||||||
proxy-addr "~2.0.7"
|
proxy-addr "~2.0.7"
|
||||||
qs "6.13.0"
|
qs "6.11.0"
|
||||||
range-parser "~1.2.1"
|
range-parser "~1.2.1"
|
||||||
safe-buffer "5.2.1"
|
safe-buffer "5.2.1"
|
||||||
send "0.19.0"
|
send "0.18.0"
|
||||||
serve-static "1.16.2"
|
serve-static "1.15.0"
|
||||||
setprototypeof "1.2.0"
|
setprototypeof "1.2.0"
|
||||||
statuses "2.0.1"
|
statuses "2.0.1"
|
||||||
type-is "~1.6.18"
|
type-is "~1.6.18"
|
||||||
@ -5378,13 +5373,13 @@ fill-range@^7.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range "^5.0.1"
|
to-regex-range "^5.0.1"
|
||||||
|
|
||||||
finalhandler@1.3.1:
|
finalhandler@1.2.0:
|
||||||
version "1.3.1"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019"
|
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
|
||||||
integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==
|
integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "2.6.9"
|
debug "2.6.9"
|
||||||
encodeurl "~2.0.0"
|
encodeurl "~1.0.2"
|
||||||
escape-html "~1.0.3"
|
escape-html "~1.0.3"
|
||||||
on-finished "2.4.1"
|
on-finished "2.4.1"
|
||||||
parseurl "~1.3.3"
|
parseurl "~1.3.3"
|
||||||
@ -6918,10 +6913,10 @@ mem@^4.3.0:
|
|||||||
mimic-fn "^2.0.0"
|
mimic-fn "^2.0.0"
|
||||||
p-is-promise "^2.0.0"
|
p-is-promise "^2.0.0"
|
||||||
|
|
||||||
merge-descriptors@1.0.3:
|
merge-descriptors@1.0.1:
|
||||||
version "1.0.3"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
|
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||||
integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
|
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
|
||||||
|
|
||||||
merge-stream@^2.0.0:
|
merge-stream@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -7632,10 +7627,10 @@ path-scurry@^1.11.1:
|
|||||||
lru-cache "^10.2.0"
|
lru-cache "^10.2.0"
|
||||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||||
|
|
||||||
path-to-regexp@0.1.10:
|
path-to-regexp@0.1.7:
|
||||||
version "0.1.10"
|
version "0.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b"
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||||
integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==
|
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
||||||
|
|
||||||
path-type@^2.0.0:
|
path-type@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -7917,7 +7912,14 @@ pure-color@^1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
|
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
|
||||||
integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==
|
integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==
|
||||||
|
|
||||||
qs@6.13.0, qs@^6.4.0:
|
qs@6.11.0:
|
||||||
|
version "6.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||||
|
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
|
||||||
|
dependencies:
|
||||||
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
|
qs@^6.4.0:
|
||||||
version "6.13.0"
|
version "6.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
||||||
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
|
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
|
||||||
@ -8482,10 +8484,10 @@ semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semve
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
||||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||||
|
|
||||||
send@0.19.0:
|
send@0.18.0:
|
||||||
version "0.19.0"
|
version "0.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
|
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
|
||||||
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
|
integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "2.6.9"
|
debug "2.6.9"
|
||||||
depd "2.0.0"
|
depd "2.0.0"
|
||||||
@ -8508,15 +8510,15 @@ serialize-error@^7.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.13.1"
|
type-fest "^0.13.1"
|
||||||
|
|
||||||
serve-static@1.16.2:
|
serve-static@1.15.0:
|
||||||
version "1.16.2"
|
version "1.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
|
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
|
||||||
integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
|
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
|
||||||
dependencies:
|
dependencies:
|
||||||
encodeurl "~2.0.0"
|
encodeurl "~1.0.2"
|
||||||
escape-html "~1.0.3"
|
escape-html "~1.0.3"
|
||||||
parseurl "~1.3.3"
|
parseurl "~1.3.3"
|
||||||
send "0.19.0"
|
send "0.18.0"
|
||||||
|
|
||||||
set-blocking@^2.0.0:
|
set-blocking@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -8755,16 +8757,7 @@ string-natural-compare@^3.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
|
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
|
||||||
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
|
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0":
|
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
|
||||||
dependencies:
|
|
||||||
emoji-regex "^8.0.0"
|
|
||||||
is-fullwidth-code-point "^3.0.0"
|
|
||||||
strip-ansi "^6.0.1"
|
|
||||||
|
|
||||||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
@ -8858,14 +8851,7 @@ string_decoder@~1.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^5.0.1"
|
|
||||||
|
|
||||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
@ -9511,10 +9497,10 @@ vite-tsconfig-paths@^4.3.2:
|
|||||||
globrex "^0.1.2"
|
globrex "^0.1.2"
|
||||||
tsconfck "^3.0.3"
|
tsconfck "^3.0.3"
|
||||||
|
|
||||||
vite@^5.0.0, vite@^5.4.6:
|
vite@^5.0.0, vite@^5.4.3:
|
||||||
version "5.4.6"
|
version "5.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.6.tgz#85a93a1228a7fb5a723ca1743e337a2588ed008f"
|
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.3.tgz#771c470e808cb6732f204e1ee96c2ed65b97a0eb"
|
||||||
integrity sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==
|
integrity sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild "^0.21.3"
|
esbuild "^0.21.3"
|
||||||
postcss "^8.4.43"
|
postcss "^8.4.43"
|
||||||
@ -9739,16 +9725,7 @@ word-wrap@^1.2.3, word-wrap@^1.2.5:
|
|||||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
|
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
|
||||||
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
|
||||||
dependencies:
|
|
||||||
ansi-styles "^4.0.0"
|
|
||||||
string-width "^4.1.0"
|
|
||||||
strip-ansi "^6.0.0"
|
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
|
Reference in New Issue
Block a user