diff --git a/.github/workflows/formatbot.yml b/.github/workflows/formatbot.yml deleted file mode 100644 index 99c6eb58..00000000 --- a/.github/workflows/formatbot.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Format PR - -on: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - -jobs: - format: - name: Format code - runs-on: ubuntu-latest - if: github.event.pull_request.draft == false - - steps: - - name: Determine if fork - id: check_fork - run: | - if [ "${{ github.event.pull_request.head.repo.full_name }}" = "${{ github.repository }}" ]; then - echo "is_fork=false" >> $GITHUB_OUTPUT - else - echo "is_fork=true" >> $GITHUB_OUTPUT - fi - - name: Checkout code - uses: actions/checkout@v3 - if: steps.check_fork.outputs.is_fork == 'false' - with: - token: ${{ secrets.TSCIRCUIT_BOT_GITHUB_TOKEN }} - - - name: Setup Node.js - uses: actions/setup-node@v3 - if: steps.check_fork.outputs.is_fork == 'false' - with: - node-version: "20" - - - run: npm install - - - name: Run formatter - if: steps.check_fork.outputs.is_fork == 'false' - run: npx prettier -w . - - - name: Commit changes - if: steps.check_fork.outputs.is_fork == 'false' - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "formatbot: Automatically format code" - branch: ${{ github.head_ref }} - commit_user_name: tscircuitbot - commit_user_email: tscircuitbot@users.noreply.github.com - commit_author: tscircuitbot diff --git a/package-lock.json b/package-lock.json index e44a4f33..cb9a8ceb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "@tscircuit/builder", - "version": "1.11.4", + "version": "1.11.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tscircuit/builder", - "version": "1.11.4", + "version": "1.11.6", "license": "MIT", "dependencies": { "@lume/kiwi": "^0.1.0", "@tscircuit/layout": "^0.0.25", "@tscircuit/routing": "1.3.1", "@tscircuit/schematic-autolayout": "^0.0.5", + "circuit-json-to-gerber": "^0.0.5", "convert-units": "^2.3.4", "fast-json-stable-stringify": "^2.1.0", "format-si-prefix": "^0.3.2", @@ -159,9 +160,9 @@ } }, "node_modules/@biomejs/biome": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.3.tgz", - "integrity": "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.0.tgz", + "integrity": "sha512-NlWh2F1wbxB3O/wE+aohGL0BziTS6e+6+dyFvpdeqLsbQZY7EsiklFb9W5Xs41U4vEmY7ANgdNp+oVDij6sQdA==", "dev": true, "hasInstallScript": true, "bin": { @@ -175,20 +176,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "1.8.3", - "@biomejs/cli-darwin-x64": "1.8.3", - "@biomejs/cli-linux-arm64": "1.8.3", - "@biomejs/cli-linux-arm64-musl": "1.8.3", - "@biomejs/cli-linux-x64": "1.8.3", - "@biomejs/cli-linux-x64-musl": "1.8.3", - "@biomejs/cli-win32-arm64": "1.8.3", - "@biomejs/cli-win32-x64": "1.8.3" + "@biomejs/cli-darwin-arm64": "1.9.0", + "@biomejs/cli-darwin-x64": "1.9.0", + "@biomejs/cli-linux-arm64": "1.9.0", + "@biomejs/cli-linux-arm64-musl": "1.9.0", + "@biomejs/cli-linux-x64": "1.9.0", + "@biomejs/cli-linux-x64-musl": "1.9.0", + "@biomejs/cli-win32-arm64": "1.9.0", + "@biomejs/cli-win32-x64": "1.9.0" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.3.tgz", - "integrity": "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.0.tgz", + "integrity": "sha512-2w9v/NRtYSmodx5QWQ49OGcyGKSECdWKbzc7n532Iq5sBhkKk996fd19icT6BuL54f01KFKRCRibAW+A2rg1Kw==", "cpu": [ "arm64" ], @@ -202,9 +203,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.3.tgz", - "integrity": "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.0.tgz", + "integrity": "sha512-fBVt8jJQi0zX0SJ1C+tdzUbRpuX/07sgtBXEhunWRkPjdi6W/2S1sYHQ1wKn4OKiRAKfHM2Cf2FNO7hQvY61dA==", "cpu": [ "x64" ], @@ -218,9 +219,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.3.tgz", - "integrity": "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.0.tgz", + "integrity": "sha512-l8U2lcqsl9yKPP5WUdIrKH//C1pWyM2cSUfcTBn6GSvXmsSjBNEdGSdM4Wfne777Oe/9ONaD1Ga53U2HksHHLw==", "cpu": [ "arm64" ], @@ -234,9 +235,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.3.tgz", - "integrity": "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.0.tgz", + "integrity": "sha512-Jy84mZ4vcppdmWMgQWOCfd8qIVC/vHmlaS5gy7GXkdWlBKSQ56YxEXTU58MHTbZ16LwJQpK2IulqRCC/rqWLBA==", "cpu": [ "arm64" ], @@ -250,9 +251,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.3.tgz", - "integrity": "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.0.tgz", + "integrity": "sha512-8jAzjrrJTj510pwq4aVs7ZKkOvEy1D+nzl9DKvrPh4TOyUw5Ie+0EDwXGE2RAkCKHkGNOQBZ78WtIdsATgz5sA==", "cpu": [ "x64" ], @@ -266,9 +267,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.3.tgz", - "integrity": "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.0.tgz", + "integrity": "sha512-N3enoFoIrkB6qJWyYfTiYmFdB1R/Mrij1dd1xBHqxxCKZY9GRkEswRX3F1Uqzo5T+9Iu8nAQobDqI/ygicYy/Q==", "cpu": [ "x64" ], @@ -282,9 +283,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.3.tgz", - "integrity": "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.0.tgz", + "integrity": "sha512-AIjwJTGfdWGMRluSQ9pDB29nzce077dfHh0/HMqzztKzgD3spyuo2R9VoaFpbR0hLHPWEH6g6OxxDO7hfkXNkQ==", "cpu": [ "arm64" ], @@ -298,9 +299,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz", - "integrity": "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.0.tgz", + "integrity": "sha512-4/4wTjNSoyNkm1SzcUaStDx46baX1VJRXtUoeEHjX9LfedR5N3qwZz5KfrRUnCd2fl5bmXK1CwMqKBkoF6zEiA==", "cpu": [ "x64" ], @@ -1243,9 +1244,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz", - "integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", + "integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==", "cpu": [ "arm" ], @@ -1256,9 +1257,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz", - "integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz", + "integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==", "cpu": [ "arm64" ], @@ -1269,9 +1270,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz", - "integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz", + "integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==", "cpu": [ "arm64" ], @@ -1282,9 +1283,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz", - "integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz", + "integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==", "cpu": [ "x64" ], @@ -1295,9 +1296,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz", - "integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz", + "integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==", "cpu": [ "arm" ], @@ -1308,9 +1309,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz", - "integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz", + "integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==", "cpu": [ "arm" ], @@ -1321,9 +1322,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz", - "integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz", + "integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==", "cpu": [ "arm64" ], @@ -1334,9 +1335,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz", - "integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz", + "integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==", "cpu": [ "arm64" ], @@ -1347,9 +1348,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz", - "integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz", + "integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==", "cpu": [ "ppc64" ], @@ -1360,9 +1361,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz", - "integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz", + "integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==", "cpu": [ "riscv64" ], @@ -1373,9 +1374,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz", - "integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz", + "integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==", "cpu": [ "s390x" ], @@ -1386,9 +1387,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz", - "integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz", + "integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==", "cpu": [ "x64" ], @@ -1399,9 +1400,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz", - "integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz", + "integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==", "cpu": [ "x64" ], @@ -1412,9 +1413,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz", - "integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz", + "integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==", "cpu": [ "arm64" ], @@ -1425,9 +1426,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz", - "integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz", + "integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==", "cpu": [ "ia32" ], @@ -1438,9 +1439,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz", - "integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", + "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", "cpu": [ "x64" ], @@ -1510,9 +1511,9 @@ } }, "node_modules/@semantic-release/github": { - "version": "10.1.7", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-10.1.7.tgz", - "integrity": "sha512-QnhP4k1eqzYLz6a4kpWrUQeKJYXqHggveMykvUFbSquq07GF85BXvr/QLhpOD7bpDcmEfL8VnphRA7KT5i9lzQ==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-10.3.3.tgz", + "integrity": "sha512-zrEdwRZ7ZTEM2JYhF4E+ZgApIfv6iHfQBnnAP1g2LqYZtj56+qWEUo/xW36cbZRDOweejxU40PGZckx6TZzFmg==", "dev": true, "peer": true, "dependencies": { @@ -1843,9 +1844,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", - "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -1882,9 +1883,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "dependencies": { "acorn": "^8.11.0" @@ -1936,9 +1937,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" @@ -2397,6 +2398,17 @@ "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", "dev": true }, + "node_modules/circuit-json-to-gerber": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/circuit-json-to-gerber/-/circuit-json-to-gerber-0.0.5.tgz", + "integrity": "sha512-FpxgkFKYkbhHPREQPWBpc+IEvOoGjOOG4K1ItjB5JQCRJNRJUtqzM5S6lhB/FU9Ye8QaAgkzJoo8M28wBYemhA==", + "dependencies": { + "fast-json-stable-stringify": "^2.1.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } + }, "node_modules/circuit-to-png": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/circuit-to-png/-/circuit-to-png-0.0.3.tgz", @@ -3163,12 +3175,12 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3179,12 +3191,6 @@ } } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -8884,9 +8890,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, "node_modules/picomatch": { @@ -9235,9 +9241,9 @@ } }, "node_modules/read-package-up/node_modules/type-fest": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.0.tgz", - "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "peer": true, "engines": { @@ -9587,9 +9593,9 @@ } }, "node_modules/rollup": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", - "integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", + "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -9602,22 +9608,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.2", - "@rollup/rollup-android-arm64": "4.21.2", - "@rollup/rollup-darwin-arm64": "4.21.2", - "@rollup/rollup-darwin-x64": "4.21.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", - "@rollup/rollup-linux-arm-musleabihf": "4.21.2", - "@rollup/rollup-linux-arm64-gnu": "4.21.2", - "@rollup/rollup-linux-arm64-musl": "4.21.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", - "@rollup/rollup-linux-riscv64-gnu": "4.21.2", - "@rollup/rollup-linux-s390x-gnu": "4.21.2", - "@rollup/rollup-linux-x64-gnu": "4.21.2", - "@rollup/rollup-linux-x64-musl": "4.21.2", - "@rollup/rollup-win32-arm64-msvc": "4.21.2", - "@rollup/rollup-win32-ia32-msvc": "4.21.2", - "@rollup/rollup-win32-x64-msvc": "4.21.2", + "@rollup/rollup-android-arm-eabi": "4.21.3", + "@rollup/rollup-android-arm64": "4.21.3", + "@rollup/rollup-darwin-arm64": "4.21.3", + "@rollup/rollup-darwin-x64": "4.21.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", + "@rollup/rollup-linux-arm-musleabihf": "4.21.3", + "@rollup/rollup-linux-arm64-gnu": "4.21.3", + "@rollup/rollup-linux-arm64-musl": "4.21.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", + "@rollup/rollup-linux-riscv64-gnu": "4.21.3", + "@rollup/rollup-linux-s390x-gnu": "4.21.3", + "@rollup/rollup-linux-x64-gnu": "4.21.3", + "@rollup/rollup-linux-x64-musl": "4.21.3", + "@rollup/rollup-win32-arm64-msvc": "4.21.3", + "@rollup/rollup-win32-ia32-msvc": "4.21.3", + "@rollup/rollup-win32-x64-msvc": "4.21.3", "fsevents": "~2.3.2" } }, @@ -9667,9 +9673,9 @@ } }, "node_modules/semantic-release": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.1.0.tgz", - "integrity": "sha512-FwaE2hKDHQn9G6GA7xmqsc9WnsjaFD/ppLM5PUg56Do9oKSCf+vH6cPeb3hEBV/m06n8Sh9vbVqPjHu/1onzQw==", + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.1.1.tgz", + "integrity": "sha512-4Ax2GxD411jUe9IdhOjMLuN+6wAj+aKjvOGngByrpD/iKL+UKN/2puQglhyI4gxNyy9XzEBMzBwbqpnEwbXGEg==", "dev": true, "peer": true, "dependencies": { @@ -9688,7 +9694,7 @@ "get-stream": "^6.0.0", "git-log-parser": "^1.2.0", "hook-std": "^3.0.0", - "hosted-git-info": "^7.0.0", + "hosted-git-info": "^8.0.0", "import-from-esm": "^1.3.1", "lodash-es": "^4.17.21", "marked": "^12.0.0", @@ -10004,16 +10010,16 @@ } }, "node_modules/semantic-release/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.0.tgz", + "integrity": "sha512-4nw3vOVR+vHUOT8+U4giwe2tcGv+R3pwwRidUe67DoMBTjhrfr6rZYJVVwdkBE+Um050SG+X9tf0Jo4fOpn01w==", "dev": true, "peer": true, "dependencies": { "lru-cache": "^10.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/semantic-release/node_modules/human-signals": { @@ -10083,9 +10089,9 @@ } }, "node_modules/semantic-release/node_modules/is-unicode-supported": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", - "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "peer": true, "engines": { @@ -10130,6 +10136,19 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/semantic-release/node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "peer": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/semantic-release/node_modules/normalize-url": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", @@ -12926,9 +12945,9 @@ } }, "node_modules/semantic-release/node_modules/parse-json/node_modules/type-fest": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.0.tgz", - "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "peer": true, "engines": { @@ -13001,9 +13020,9 @@ } }, "node_modules/semantic-release/node_modules/read-pkg/node_modules/type-fest": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.0.tgz", - "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "peer": true, "engines": { @@ -14244,10 +14263,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 22b2904b..bf591784 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@tscircuit/layout": "^0.0.25", "@tscircuit/routing": "1.3.1", "@tscircuit/schematic-autolayout": "^0.0.5", + "circuit-json-to-gerber": "^0.0.5", "convert-units": "^2.3.4", "fast-json-stable-stringify": "^2.1.0", "format-si-prefix": "^0.3.2", diff --git a/src/index.ts b/src/index.ts index e449cb58..5e926c68 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,8 +3,7 @@ export * from "./lib/builder" export * from "./lib/apply-selector" export * from "./lib/types" export * from "./lib/utils" -export * from "./lib/gerber" -export * from "./lib/excellon-drill" +export * from "circuit-json-to-gerber" export * from "./lib/bom-csv" export * from "./lib/pick-and-place-csv" export { buildPcbTraceElements } from "./lib/builder/trace-builder/build-pcb-trace-elements" diff --git a/src/lib/excellon-drill/any-excellon-drill-command-map.ts b/src/lib/excellon-drill/any-excellon-drill-command-map.ts deleted file mode 100644 index 69e92082..00000000 --- a/src/lib/excellon-drill/any-excellon-drill-command-map.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { z } from "zod" -import { ExcellonDrillCommandDef } from "./define-excellon-drill-command" -import * as EDCMD from "./commands" - -export const excellon_drill_command_map = { - M48: EDCMD.M48, - M95: EDCMD.M95, - FMAT: EDCMD.FMAT, - unit_format: EDCMD.unit_format, - aper_function_header: EDCMD.aper_function_header, - percent_sign: EDCMD.percent_sign, - T: EDCMD.define_tool, - define_tool: EDCMD.define_tool, - use_tool: EDCMD.use_tool, - G90: EDCMD.G90, - G05: EDCMD.G05, - M30: EDCMD.M30, - drill_at: EDCMD.drill_at, - header_comment: EDCMD.header_comment, - header_attribute: EDCMD.header_attribute, - rewind: EDCMD.rewind, -} satisfies Record> - -export type AnyExcellonDrillCommand = z.infer< - (typeof excellon_drill_command_map)[keyof typeof excellon_drill_command_map]["schema"] -> diff --git a/src/lib/excellon-drill/commands/FMAT.ts b/src/lib/excellon-drill/commands/FMAT.ts deleted file mode 100644 index 7f636d8f..00000000 --- a/src/lib/excellon-drill/commands/FMAT.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const FMAT = defineExcellonDrillCommand({ - command_code: "FMAT", - schema: z.object({ - command_code: z.literal("FMAT").default("FMAT"), - format: z.number(), - }), - stringify: (c) => `FMAT,${c.format}`, -}) diff --git a/src/lib/excellon-drill/commands/G05.ts b/src/lib/excellon-drill/commands/G05.ts deleted file mode 100644 index 173003df..00000000 --- a/src/lib/excellon-drill/commands/G05.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const G05 = defineExcellonDrillCommand({ - command_code: "G05", - schema: z.object({ - command_code: z.literal("G05").default("G05"), - }), - stringify: () => "G05", -}) diff --git a/src/lib/excellon-drill/commands/G90.ts b/src/lib/excellon-drill/commands/G90.ts deleted file mode 100644 index 308a67a9..00000000 --- a/src/lib/excellon-drill/commands/G90.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const G90 = defineExcellonDrillCommand({ - command_code: "G90", - schema: z.object({ - command_code: z.literal("G90").default("G90"), - }), - stringify: () => "G90", -}) diff --git a/src/lib/excellon-drill/commands/M30.ts b/src/lib/excellon-drill/commands/M30.ts deleted file mode 100644 index 775e2e28..00000000 --- a/src/lib/excellon-drill/commands/M30.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const M30 = defineExcellonDrillCommand({ - command_code: "M30", - schema: z.object({ - command_code: z.literal("M30").default("M30"), - }), - stringify: () => "M30", -}) diff --git a/src/lib/excellon-drill/commands/M48.ts b/src/lib/excellon-drill/commands/M48.ts deleted file mode 100644 index 1be99c30..00000000 --- a/src/lib/excellon-drill/commands/M48.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const M48 = defineExcellonDrillCommand({ - command_code: "M48", - schema: z.object({ - command_code: z.literal("M48").default("M48"), - }), - stringify: () => "M48", -}) diff --git a/src/lib/excellon-drill/commands/M95.ts b/src/lib/excellon-drill/commands/M95.ts deleted file mode 100644 index fc0f22b4..00000000 --- a/src/lib/excellon-drill/commands/M95.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const M95 = defineExcellonDrillCommand({ - command_code: "M95", - schema: z.object({ - command_code: z.literal("M95").default("M95"), - }), - stringify: () => "M95", -}) diff --git a/src/lib/excellon-drill/commands/aper_function_header.ts b/src/lib/excellon-drill/commands/aper_function_header.ts deleted file mode 100644 index 3663a7cd..00000000 --- a/src/lib/excellon-drill/commands/aper_function_header.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const aper_function_header = defineExcellonDrillCommand({ - command_code: "aper_function_header", - schema: z.object({ - command_code: z - .literal("aper_function_header") - .default("aper_function_header"), - is_plated: z.boolean(), - }), - stringify({ is_plated }) { - if (!is_plated) { - throw new Error("not implemented") - } - return `; #@! TA.AperFunction,Plated,PTH,ComponentDrill` - }, -}) diff --git a/src/lib/excellon-drill/commands/define_tool.ts b/src/lib/excellon-drill/commands/define_tool.ts deleted file mode 100644 index 9a1f8495..00000000 --- a/src/lib/excellon-drill/commands/define_tool.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const define_tool = defineExcellonDrillCommand({ - command_code: "define_tool", - schema: z.object({ - command_code: z.literal("define_tool").default("define_tool"), - tool_number: z.number(), - diameter: z.number(), - }), - stringify: (c) => `T${c.tool_number}C${c.diameter.toFixed(6)}`, -}) diff --git a/src/lib/excellon-drill/commands/drill_at.ts b/src/lib/excellon-drill/commands/drill_at.ts deleted file mode 100644 index 6c2dd965..00000000 --- a/src/lib/excellon-drill/commands/drill_at.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const drill_at = defineExcellonDrillCommand({ - command_code: "drill_at", - schema: z.object({ - command_code: z.literal("drill_at").default("drill_at"), - x: z.number(), - y: z.number(), - }), - stringify: (c) => `X${c.x.toFixed(4)}Y${c.y.toFixed(4)}`, -}) diff --git a/src/lib/excellon-drill/commands/header_attribute.ts b/src/lib/excellon-drill/commands/header_attribute.ts deleted file mode 100644 index 0ff7d531..00000000 --- a/src/lib/excellon-drill/commands/header_attribute.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const header_attribute = defineExcellonDrillCommand({ - command_code: "header_attribute", - schema: z.object({ - command_code: z.literal("header_attribute").default("header_attribute"), - attribute_name: z.string(), - attribute_value: z.string(), - }), - stringify({ attribute_name, attribute_value }) { - return `; #@! ${attribute_name},${attribute_value}` - }, -}) diff --git a/src/lib/excellon-drill/commands/header_comment.ts b/src/lib/excellon-drill/commands/header_comment.ts deleted file mode 100644 index c1cbebcc..00000000 --- a/src/lib/excellon-drill/commands/header_comment.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const header_comment = defineExcellonDrillCommand({ - command_code: "header_comment", - schema: z.object({ - command_code: z.literal("header_comment").default("header_comment"), - text: z.string(), - }), - stringify({ text }) { - return `; ${text}` - }, -}) diff --git a/src/lib/excellon-drill/commands/index.ts b/src/lib/excellon-drill/commands/index.ts deleted file mode 100644 index 5cd4d94b..00000000 --- a/src/lib/excellon-drill/commands/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export * from "./FMAT" -export * from "./G05" -export * from "./G90" -export * from "./M30" -export * from "./M48" -export * from "./M95" -export * from "./define_tool" -export * from "./drill_at" -export * from "./header_attribute" -export * from "./header_comment" -export * from "./rewind" -export * from "./unit_format" -export * from "./use_tool" -export * from "./aper_function_header" -export * from "./percent_sign" diff --git a/src/lib/excellon-drill/commands/percent_sign.ts b/src/lib/excellon-drill/commands/percent_sign.ts deleted file mode 100644 index 33a0fbab..00000000 --- a/src/lib/excellon-drill/commands/percent_sign.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const percent_sign = defineExcellonDrillCommand({ - command_code: "percent_sign", - schema: z.object({ - command_code: z.literal("percent_sign").default("percent_sign"), - }), - stringify: () => "%", -}) diff --git a/src/lib/excellon-drill/commands/rewind.ts b/src/lib/excellon-drill/commands/rewind.ts deleted file mode 100644 index ff7371a3..00000000 --- a/src/lib/excellon-drill/commands/rewind.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const rewind = defineExcellonDrillCommand({ - command_code: "rewind", - schema: z.object({ - command_code: z.literal("rewind").default("rewind"), - }), - stringify: () => "%", -}) diff --git a/src/lib/excellon-drill/commands/unit_format.ts b/src/lib/excellon-drill/commands/unit_format.ts deleted file mode 100644 index e56b45e9..00000000 --- a/src/lib/excellon-drill/commands/unit_format.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const unit_format = defineExcellonDrillCommand({ - command_code: "unit_format", - schema: z.object({ - command_code: z.literal("unit_format").default("unit_format"), - unit: z.union([z.literal("INCH"), z.literal("METRIC")]), - lz: z - .union([z.literal("LZ"), z.literal("TZ")]) - .nullable() - .default(null), - }), - stringify(c) { - return `${c.unit}${!c.lz ? "" : `,${c.lz}`}` - }, -}) diff --git a/src/lib/excellon-drill/commands/use_tool.ts b/src/lib/excellon-drill/commands/use_tool.ts deleted file mode 100644 index 4c49d5ee..00000000 --- a/src/lib/excellon-drill/commands/use_tool.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { z } from "zod" -import { defineExcellonDrillCommand } from "../define-excellon-drill-command" - -export const use_tool = defineExcellonDrillCommand({ - command_code: "use_tool", - schema: z.object({ - command_code: z.literal("use_tool").default("use_tool"), - tool_number: z.number(), - }), - stringify: (c) => `T${c.tool_number}`, -}) diff --git a/src/lib/excellon-drill/convert-soup-to-excellon-drill-commands.ts b/src/lib/excellon-drill/convert-soup-to-excellon-drill-commands.ts deleted file mode 100644 index 5d2c4c6f..00000000 --- a/src/lib/excellon-drill/convert-soup-to-excellon-drill-commands.ts +++ /dev/null @@ -1,106 +0,0 @@ -import type { AnySoupElement } from "@tscircuit/soup" -import type { AnyExcellonDrillCommand } from "./any-excellon-drill-command-map" -import { excellonDrill } from "./excellon-drill-builder" - -export const inchToMm = (mm: number) => { - return mm * 25.4 -} - -export const convertSoupToExcellonDrillCommands = ({ - soup, - is_plated, - flip_y_axis = false, -}: { - soup: Array - is_plated: boolean - flip_y_axis?: boolean -}): Array => { - const builder = excellonDrill() - - // Start sequence commands - builder.add("M48", {}) - - // Add header comments - const date_str = new Date().toISOString() - builder - .add("header_comment", { - text: `DRILL file {tscircuit} date ${date_str}`, - }) - .add("header_comment", { - text: "FORMAT={-:-/ absolute / metric / decimal}", - }) - .add("header_attribute", { - attribute_name: "TF.CreationDate", - attribute_value: date_str, - }) - .add("header_attribute", { - attribute_name: "TF.GenerationSoftware", - attribute_value: "tscircuit", - }) - .add("header_attribute", { - attribute_name: "TF.FileFunction", - attribute_value: "Plated,1,2,PTH", - }) - .add("FMAT", { format: 2 }) // Assuming format 2 for the example - .add("unit_format", { unit: "METRIC", lz: null }) - - let tool_counter = 10 // Start tool numbering from 10 for example - - const diameterToToolNumber: Record = {} - - // Define tools - for (const element of soup) { - if ( - element.type === "pcb_plated_hole" || - element.type === "pcb_hole" || - element.type === "pcb_via" - ) { - if (!("hole_diameter" in element)) continue - if (!diameterToToolNumber[element.hole_diameter]) { - builder.add("aper_function_header", { - is_plated: true, - }) - builder.add("define_tool", { - tool_number: tool_counter, - diameter: inchToMm(element.hole_diameter), - }) - diameterToToolNumber[element.hole_diameter] = tool_counter - tool_counter++ - } - } - } - - builder.add("percent_sign", {}) - builder.add("G90", {}) - builder.add("G05", {}) - - // Execute drills for tool N - for (let i = 10; i < tool_counter; i++) { - builder.add("use_tool", { tool_number: i }) - for (const element of soup) { - if ( - element.type === "pcb_plated_hole" || - element.type === "pcb_hole" || - element.type === "pcb_via" - ) { - if (is_plated && element.type === "pcb_hole") continue - if ( - !is_plated && - (element.type === "pcb_plated_hole" || element.type === "pcb_via") - ) - continue - if (!("hole_diameter" in element)) continue - if (diameterToToolNumber[element.hole_diameter] === i) { - builder.add("drill_at", { - x: inchToMm(element.x), - y: inchToMm(element.y) * (flip_y_axis ? -1 : 1), - }) - } - } - } - } - - builder.add("M30", {}) - - return builder.build() -} diff --git a/src/lib/excellon-drill/define-excellon-drill-command.ts b/src/lib/excellon-drill/define-excellon-drill-command.ts deleted file mode 100644 index 8aa6721d..00000000 --- a/src/lib/excellon-drill/define-excellon-drill-command.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AnyZodObject, z } from "zod" - -export interface ExcellonDrillCommandDef< - K extends string, - T extends AnyZodObject | z.ZodIntersection -> { - command_code: K - schema: T - stringify: (c: z.infer) => string -} - -export const defineExcellonDrillCommand = < - K extends string, - T extends AnyZodObject | z.ZodIntersection ->({ - command_code, - schema, - stringify, -}: { - command_code: K - schema: T - stringify: (c: z.infer) => string -}): ExcellonDrillCommandDef => { - return { - command_code, - schema, - stringify, - } -} diff --git a/src/lib/excellon-drill/excellon-drill-builder.ts b/src/lib/excellon-drill/excellon-drill-builder.ts deleted file mode 100644 index bf3ff96f..00000000 --- a/src/lib/excellon-drill/excellon-drill-builder.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { z } from "zod" -import { - AnyExcellonDrillCommand, - excellon_drill_command_map, -} from "./any-excellon-drill-command-map" - -class ExcellonDrillBuilder { - commands: Array - - constructor() { - this.commands = [] - } - - add( - cmd: T, - props: z.input<(typeof excellon_drill_command_map)[T]["schema"]> - ): ExcellonDrillBuilder { - this.commands.push({ - ...({ - command_code: excellon_drill_command_map[cmd].command_code, - } as any), - ...props, - }) - return this - } - - build(): Array { - return this.commands - } -} - -export const excellonDrill = () => new ExcellonDrillBuilder() diff --git a/src/lib/excellon-drill/index.ts b/src/lib/excellon-drill/index.ts deleted file mode 100644 index 6e808695..00000000 --- a/src/lib/excellon-drill/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { stringifyExcellonDrill } from "./stringify-excellon-drill" -export { convertSoupToExcellonDrillCommands } from "./convert-soup-to-excellon-drill-commands" diff --git a/src/lib/excellon-drill/stringify-excellon-drill.ts b/src/lib/excellon-drill/stringify-excellon-drill.ts deleted file mode 100644 index d777fc14..00000000 --- a/src/lib/excellon-drill/stringify-excellon-drill.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { - AnyExcellonDrillCommand, - excellon_drill_command_map, -} from "./any-excellon-drill-command-map" - -export const stringifyExcellonDrill = ( - commands: Array -) => { - return commands - .map((c) => { - const def = excellon_drill_command_map[c.command_code] - return def.stringify(c as any) - }) - .join("\n") -} diff --git a/src/lib/gerber/README.md b/src/lib/gerber/README.md deleted file mode 100644 index d41c5161..00000000 --- a/src/lib/gerber/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Gerber Stringification - -Some components of this gerber system: - -- A JSON command representation (defined in part with zod), all gerber command - definitions are in [./commands](./commands) - - Each command features a stringification function -- A function that converts soup to the Gerber commands [./convert-soup-to-gerber-commands](./convert-soup-to-gerber-commands) - -## References - -- [Gerber Format Specification (2022)](https://www.ucamco.com/files/downloads/file_en/456/gerber-layer-format-specification-revision-2022-02_en.pdf?7b3ca7f0753aa2d77f5f9afe31b9f826) diff --git a/src/lib/gerber/any_gerber_command.ts b/src/lib/gerber/any_gerber_command.ts deleted file mode 100644 index b480746e..00000000 --- a/src/lib/gerber/any_gerber_command.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { GerberCommandDef } from "./define-gerber-command" -import { z } from "zod" - -import { add_attribute_on_aperture } from "./commands/add_attribute_on_aperture" -import { add_attribute_on_file } from "./commands/add_attribute_on_file" -import { add_attribute_on_object } from "./commands/add_attribute_on_object" -import { aperture_block } from "./commands/aperture_block" -import { comment } from "./commands/comment" -import { create_arc } from "./commands/create_arc" -import { define_aperture } from "./commands/define_aperture" -import { define_macro_aperture_template } from "./commands/define_macro_aperture_template" -import { delete_attribute } from "./commands/delete_attribute" -import { end_of_file } from "./commands/end_of_file" -import { end_region_statement } from "./commands/end_region_statement" -import { flash_operation } from "./commands/flash_operation" -import { load_mirroring } from "./commands/load_mirroring" -import { load_polarity } from "./commands/load_polarity" -import { load_rotation } from "./commands/load_rotation" -import { load_scaling } from "./commands/load_scaling" -import { move_operation } from "./commands/move_operation" -import { plot_operation } from "./commands/plot_operation" -import { set_coordinate_format } from "./commands/set_coordinate_format" -import { set_current_aperture_d_code } from "./commands/set_current_aperture_d_code" -import { set_movement_mode_to_clockwise_circular } from "./commands/set_movement_mode_to_clockwise_circular" -import { set_movement_mode_to_counterclockwise_circular } from "./commands/set_movement_mode_to_counterclockwise_circular" -import { set_movement_mode_to_linear } from "./commands/set_movement_mode_to_linear" -import { set_unit } from "./commands/set_unit" -import { start_region_statement } from "./commands/start_region_statement" -import { step_and_repeat } from "./commands/step_and_repeat" -import { format_specification } from "./commands/format_specification" -import { set_layer_polarity } from "./commands/set_layer_polarity" -import { define_aperture_template } from "./commands/define_aperture_template" -import { select_aperture } from "./commands/select_aperture" - -export const gerber_command_map = { - add_attribute_on_aperture, - add_attribute_on_file, - add_attribute_on_object, - aperture_block, - comment, - create_arc, - define_aperture, - define_macro_aperture_template, - delete_attribute, - end_of_file, - move_operation, - flash_operation, - // end_region_statement, - // flash_operation, - format_specification, - // load_mirroring, - // load_polarity, - // load_rotation, - // load_scaling, - plot_operation, - // set_coordinate_format, - // set_current_aperture_d_code, - define_aperture_template, - set_movement_mode_to_clockwise_circular, - set_movement_mode_to_counterclockwise_circular, - set_movement_mode_to_linear, - select_aperture, - set_unit, - set_layer_polarity, - // start_region_statement, - // step_and_repeat, -} as const satisfies Record> - -export type AnyGerberCommand = z.infer< - (typeof gerber_command_map)[keyof typeof gerber_command_map]["schema"] -> diff --git a/src/lib/gerber/commands/add_attribute_on_aperture.ts b/src/lib/gerber/commands/add_attribute_on_aperture.ts deleted file mode 100644 index 57d8c47e..00000000 --- a/src/lib/gerber/commands/add_attribute_on_aperture.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const add_attribute_on_aperture = defineGerberCommand({ - command_code: "TA", - schema: z - .object({ - command_code: z.literal("TA").default("TA"), - attribute_name: z.string(), - attribute_value: z.string(), - }) - .describe( - "Add attribute on aperture: Add an aperture attribute to the dictionary or modify it." - ), - stringify: ({ attribute_name, attribute_value }) => { - return `%TA${attribute_name},${attribute_value}*%` - }, -}) diff --git a/src/lib/gerber/commands/add_attribute_on_file.ts b/src/lib/gerber/commands/add_attribute_on_file.ts deleted file mode 100644 index e21d27f8..00000000 --- a/src/lib/gerber/commands/add_attribute_on_file.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const add_attribute_on_file = defineGerberCommand({ - command_code: "TF", - schema: z - .object({ - command_code: z.literal("TF").default("TF"), - attribute_name: z.string(), - attribute_value: z.string(), - }) - .describe("Add attribute on file: Set a file attribute."), - stringify: ({ attribute_name, attribute_value }) => { - return `%TF.${attribute_name},${attribute_value}*%` - }, -}) diff --git a/src/lib/gerber/commands/add_attribute_on_object.ts b/src/lib/gerber/commands/add_attribute_on_object.ts deleted file mode 100644 index 24a9e7c9..00000000 --- a/src/lib/gerber/commands/add_attribute_on_object.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const add_attribute_on_object = defineGerberCommand({ - command_code: "TO", - schema: z - .object({ - command_code: z.literal("TO").default("TO"), - attribute_name: z.string(), - attribute_value: z.string(), - }) - .describe( - "Add attribute on object: Add an object attribute to the dictionary or modify it." - ), - stringify: ({ attribute_name, attribute_value }) => { - return `%TO${attribute_name},${attribute_value}*%` - }, -}) - -export type AddAttributeOnObject = z.infer< - typeof add_attribute_on_object.schema -> diff --git a/src/lib/gerber/commands/aperture_block.ts b/src/lib/gerber/commands/aperture_block.ts deleted file mode 100644 index 4426444a..00000000 --- a/src/lib/gerber/commands/aperture_block.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const aperture_block = defineGerberCommand({ - command_code: "AB", - schema: z - .object({ - command_code: z.literal("AB").default("AB"), - block: z.string(), - }) - .describe( - "Aperture block: Opens a block aperture statement and assigns its aperture number or closes a block aperture statement" - ), - stringify() { - return "" - }, -}) - -export type ApertureBlock = z.infer diff --git a/src/lib/gerber/commands/comment.ts b/src/lib/gerber/commands/comment.ts deleted file mode 100644 index c83d0291..00000000 --- a/src/lib/gerber/commands/comment.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const comment = defineGerberCommand({ - command_code: "G04", - schema: z - .object({ - command_code: z.literal("G04").default("G04"), - comment: z.string(), - }) - .describe( - "Comment: A human readable comment, does not affect the image. 4.1" - ), - stringify: (c) => { - return `G04 ${c.comment}*` - }, -}) - -export type Comment = z.infer diff --git a/src/lib/gerber/commands/create_arc.ts b/src/lib/gerber/commands/create_arc.ts deleted file mode 100644 index b6f01c16..00000000 --- a/src/lib/gerber/commands/create_arc.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const create_arc = defineGerberCommand({ - command_code: "G75", - schema: z - .object({ - command_code: z.literal("G75").default("G75"), - arc_parameters: z.string(), - }) - .describe( - "Create arc: A G75 must be called before creating the first arc." - ), - stringify() { - return "" - }, -}) - -export type CreateArc = z.infer diff --git a/src/lib/gerber/commands/define_aperture.ts b/src/lib/gerber/commands/define_aperture.ts deleted file mode 100644 index 88104760..00000000 --- a/src/lib/gerber/commands/define_aperture.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const define_aperture = defineGerberCommand({ - command_code: "AD", - schema: z - .object({ - command_code: z.literal("AD").default("AD"), - aperture_code: z.string(), - }) - .describe( - "Aperture define: Defines a template-based aperture, assigns a D code to it. 4.3" - ), - stringify() { - return "" - }, -}) - -export type DefineAperture = z.infer diff --git a/src/lib/gerber/commands/define_aperture_template.ts b/src/lib/gerber/commands/define_aperture_template.ts deleted file mode 100644 index 9312df9c..00000000 --- a/src/lib/gerber/commands/define_aperture_template.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" -import { getGerberCoordinateWithPadding } from "../stringify-gerber/get-gerber-coordinate-with-padding" - -const circle_template = z.object({ - standard_template_code: z.literal("C").describe("circle"), - diameter: z.number(), - hole_diameter: z.number().optional(), -}) - -const rectangle_template = z.object({ - standard_template_code: z.literal("R").describe("rectangle"), - x_size: z.number(), - y_size: z.number(), - hole_diameter: z.number().optional(), -}) - -const obround_template = z.object({ - standard_template_code: z.literal("O").describe("obround"), - x_size: z.number(), - y_size: z.number(), - hole_diameter: z.number().optional(), -}) - -const polygon_template = z.object({ - standard_template_code: z.literal("P").describe("polygon"), - outer_diameter: z.number(), - number_of_vertices: z.number().int(), - rotation: z.number().optional(), - hole_diameter: z.number().optional(), -}) - -const aperture_template_config = z.discriminatedUnion( - "standard_template_code", - [circle_template, rectangle_template, obround_template, polygon_template] -) - -export const define_aperture_template = defineGerberCommand({ - command_code: "ADD", - schema: aperture_template_config.and( - z.object({ - command_code: z.literal("ADD").default("ADD"), - aperture_number: z.number().int(), - }) - ), - stringify(props) { - const { aperture_number, standard_template_code } = props - let commandString = `%ADD${aperture_number}${standard_template_code},` - - if (standard_template_code === "C") { - commandString += `${props.diameter.toFixed(6)}` - } else if ( - standard_template_code === "R" || - standard_template_code === "O" - ) { - commandString += `${props.x_size.toFixed(6)}X${props.y_size.toFixed(6)}` - } else if (standard_template_code === "P") { - commandString += `${props.outer_diameter}X${props.number_of_vertices}X${ - props.rotation ? `X${props.rotation}` : "" - }` - } - - if (props.hole_diameter) { - commandString += `X${props.hole_diameter.toFixed(6)}` - } - - commandString += "*%" - - return commandString - }, -}) - -export type DefineAperatureTemplateCommand = z.infer< - typeof define_aperture_template.schema -> - -export type ApertureTemplateConfig = z.infer diff --git a/src/lib/gerber/commands/define_macro_aperture_template.ts b/src/lib/gerber/commands/define_macro_aperture_template.ts deleted file mode 100644 index 2d4f100f..00000000 --- a/src/lib/gerber/commands/define_macro_aperture_template.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const define_macro_aperture_template = defineGerberCommand({ - command_code: "AM", - schema: z - .object({ - command_code: z.literal("AM").default("AM"), - macro_name: z.string(), - template_code: z.string(), - }) - .describe("Aperture macro: Defines a macro aperture template. 4.5"), - stringify({ macro_name, template_code }) { - return `%AM${macro_name}*\n${template_code}%` - }, -}) - -export type DefineMacroApertureTemplate = z.infer< - typeof define_macro_aperture_template.schema -> diff --git a/src/lib/gerber/commands/delete_attribute.ts b/src/lib/gerber/commands/delete_attribute.ts deleted file mode 100644 index 1fd01911..00000000 --- a/src/lib/gerber/commands/delete_attribute.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const delete_attribute = defineGerberCommand({ - command_code: "TD", - schema: z - .object({ - command_code: z.literal("TD").default("TD"), - attribute: z.string().optional(), - }) - .describe( - "Delete attribute: Attribute delete Delete one or all attributes in the dictionary." - ), - stringify({ attribute }) { - if (!attribute) { - return `%TD*%` - } - return `%TD${attribute}*%` - }, -}) diff --git a/src/lib/gerber/commands/end_of_file.ts b/src/lib/gerber/commands/end_of_file.ts deleted file mode 100644 index 8a5b75db..00000000 --- a/src/lib/gerber/commands/end_of_file.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const end_of_file = defineGerberCommand({ - command_code: "M02", - schema: z - .object({ - command_code: z.literal("M02").default("M02"), - }) - .describe("End of file: 4.13"), - stringify() { - return "M02*" - }, -}) diff --git a/src/lib/gerber/commands/end_region_statement.ts b/src/lib/gerber/commands/end_region_statement.ts deleted file mode 100644 index e8f85c22..00000000 --- a/src/lib/gerber/commands/end_region_statement.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" - -export const end_region_statement = z - .object({ - command_code: z.literal("G37"), - statement: z.string(), - }) - .describe("End region statement: Ends the region statement") - -export type EndRegionStatement = z.infer diff --git a/src/lib/gerber/commands/flash_operation.ts b/src/lib/gerber/commands/flash_operation.ts deleted file mode 100644 index 45bdf6f5..00000000 --- a/src/lib/gerber/commands/flash_operation.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" -import { getGerberCoordinateWithPadding } from "../stringify-gerber/get-gerber-coordinate-with-padding" - -export const flash_operation = defineGerberCommand({ - command_code: "D03", - schema: z - .object({ - command_code: z.literal("D03").default("D03"), - x: z.number(), - y: z.number(), - }) - .describe( - "Flash operation: Creates a flash object with the current aperture. The current point is moved to the flash point." - ), - stringify({ x, y }) { - const [gx, gy] = [x, y].map((coord) => - getGerberCoordinateWithPadding(coord) - ) - return `X${gx}Y${gy}D03*` - }, -}) - -export type FlashOperation = z.infer diff --git a/src/lib/gerber/commands/format_specification.ts b/src/lib/gerber/commands/format_specification.ts deleted file mode 100644 index c92e5f0b..00000000 --- a/src/lib/gerber/commands/format_specification.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const format_specification = defineGerberCommand({ - command_code: "FS", - schema: z.object({ - command_code: z.literal("FS").default("FS"), - zero_omission_mode: z - .union([z.literal("L").describe("leading zeros omitted"), z.literal("T")]) - .nullable() - .default(null), - coordinate_notation: z - .union([ - z.literal("A").describe("absolute notation"), - z.literal("I").describe("incremental notation"), - ]) - .default("A"), - x_integer_digits: z.number().int().default(4), - x_decimal_digits: z.number().int().default(6), - y_integer_digits: z.number().int().default(4), - y_decimal_digits: z.number().int().default(6), - }), - stringify: () => { - return "%FSLAX46Y46*%" - }, -}) - -export type FormatSpecification = z.infer diff --git a/src/lib/gerber/commands/index.ts b/src/lib/gerber/commands/index.ts deleted file mode 100644 index 2dcd421a..00000000 --- a/src/lib/gerber/commands/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -export * from "./add_attribute_on_aperture" -export * from "./add_attribute_on_file" -export * from "./add_attribute_on_object" -export * from "./aperture_block" -export * from "./comment" -export * from "./create_arc" -export * from "./define_aperture" -export * from "./define_macro_aperture_template" -export * from "./delete_attribute" -export * from "./end_of_file" -export * from "./end_region_statement" -export * from "./flash_operation" -export * from "./load_mirroring" -export * from "./load_polarity" -export * from "./load_rotation" -export * from "./load_scaling" -export * from "./move_operation" -export * from "./plot_operation" -export * from "./set_coordinate_format" -export * from "./set_current_aperture_d_code" -export * from "./set_movement_mode_to_clockwise_circular" -export * from "./set_movement_mode_to_counterclockwise_circular" -export * from "./set_movement_mode_to_linear" -export * from "./set_unit" -export * from "./start_region_statement" -export * from "./step_and_repeat" diff --git a/src/lib/gerber/commands/load_mirroring.ts b/src/lib/gerber/commands/load_mirroring.ts deleted file mode 100644 index d249983b..00000000 --- a/src/lib/gerber/commands/load_mirroring.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" - -export const load_mirroring = z - .object({ - command_code: z.literal("LM"), - mirroring: z.string(), - }) - .describe("Load mirroring: Loads the mirror object transformation parameter.") - -export type LoadMirroring = z.infer diff --git a/src/lib/gerber/commands/load_polarity.ts b/src/lib/gerber/commands/load_polarity.ts deleted file mode 100644 index a02dbaef..00000000 --- a/src/lib/gerber/commands/load_polarity.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { z } from "zod" - -export const load_polarity = z - .object({ - command_code: z.literal("LP"), - polarity: z.string(), - }) - .describe( - "Load polarity: Loads the polarity object transformation parameter." - ) - -export type LoadPolarity = z.infer diff --git a/src/lib/gerber/commands/load_rotation.ts b/src/lib/gerber/commands/load_rotation.ts deleted file mode 100644 index 9f28a1ad..00000000 --- a/src/lib/gerber/commands/load_rotation.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { z } from "zod" - -export const load_rotation = z - .object({ - command_code: z.literal("LR"), - rotation: z.string(), - }) - .describe( - "Load rotation: Loads the rotation object transformation parameter." - ) - -export type LoadRotation = z.infer diff --git a/src/lib/gerber/commands/load_scaling.ts b/src/lib/gerber/commands/load_scaling.ts deleted file mode 100644 index 988f003a..00000000 --- a/src/lib/gerber/commands/load_scaling.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" - -export const load_scaling = z - .object({ - command_code: z.literal("LS"), - scaling: z.string(), - }) - .describe("Load scaling: Loads the scale object transformation parameter.") - -export type LoadScaling = z.infer diff --git a/src/lib/gerber/commands/move_operation.ts b/src/lib/gerber/commands/move_operation.ts deleted file mode 100644 index 95983d63..00000000 --- a/src/lib/gerber/commands/move_operation.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { getGerberCoordinateWithPadding } from "./../stringify-gerber/get-gerber-coordinate-with-padding" -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const move_operation = defineGerberCommand({ - command_code: "D02", - schema: z - .object({ - command_code: z.literal("D02").default("D02"), - x: z.number(), - y: z.number(), - }) - .describe( - "Move operation: D02 moves the current point to the coordinate in the command. It does not create an object." - ), - stringify({ x, y }) { - const [gx, gy] = [x, y].map((coord) => - getGerberCoordinateWithPadding(coord) - ) - return `X${gx}Y${gy}D02*` - }, -}) diff --git a/src/lib/gerber/commands/plot_operation.ts b/src/lib/gerber/commands/plot_operation.ts deleted file mode 100644 index 4c982231..00000000 --- a/src/lib/gerber/commands/plot_operation.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" -import { getGerberCoordinateWithPadding } from "../stringify-gerber/get-gerber-coordinate-with-padding" - -export const plot_operation = defineGerberCommand({ - command_code: "D01", - schema: z - .object({ - command_code: z.literal("D01").default("D01"), - x: z.number(), - y: z.number(), - }) - .describe( - "Plot operation: Outside a region statement D01 creates a draw or arc object with the current aperture. Inside it adds a draw/arc segment to the contour under construction. The current point is moved to draw/arc end point after the creation of the draw/arc." - ), - stringify({ x, y }) { - const [gx, gy] = [x, y].map((coord) => - getGerberCoordinateWithPadding(coord) - ) - return `X${gx}Y${gy}D01*` - }, -}) diff --git a/src/lib/gerber/commands/select_aperture.ts b/src/lib/gerber/commands/select_aperture.ts deleted file mode 100644 index 5cf5e7ae..00000000 --- a/src/lib/gerber/commands/select_aperture.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const select_aperture = defineGerberCommand({ - command_code: "D", - schema: z.object({ - command_code: z.literal("D").default("D"), - aperture_number: z.number().int(), - }), - stringify({ aperture_number }) { - return `D${aperture_number}*` - }, -}) diff --git a/src/lib/gerber/commands/set_coordinate_format.ts b/src/lib/gerber/commands/set_coordinate_format.ts deleted file mode 100644 index 4d64e301..00000000 --- a/src/lib/gerber/commands/set_coordinate_format.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { z } from "zod" - -export const set_coordinate_format = z - .object({ - command_code: z.literal("FS"), - format: z.string(), - }) - .describe("Sets the coordinate format, e.g. the number of decimals.") -export type SetCoordinateFormat = z.infer diff --git a/src/lib/gerber/commands/set_current_aperture_d_code.ts b/src/lib/gerber/commands/set_current_aperture_d_code.ts deleted file mode 100644 index 47f6e7fb..00000000 --- a/src/lib/gerber/commands/set_current_aperture_d_code.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { z } from "zod" - -export const set_current_aperture_d_code = z - .object({ - command_code: z.literal("Dnn"), - d_code: z.string(), - }) - .describe("(nn≥10) Sets the current aperture to D code nn. 4.6") - -export type SetCurrentApertureDCode = z.infer< - typeof set_current_aperture_d_code -> diff --git a/src/lib/gerber/commands/set_layer_polarity.ts b/src/lib/gerber/commands/set_layer_polarity.ts deleted file mode 100644 index abf6b456..00000000 --- a/src/lib/gerber/commands/set_layer_polarity.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const set_layer_polarity = defineGerberCommand({ - command_code: "LP", - schema: z - .object({ - command_code: z.literal("LP").default("LP"), - polarity: z.enum(["D", "C"]), - }) - .describe( - "Layer Polarity: Sets the layer polarity to dark or clear. 4.2.1" - ), - stringify({ polarity }) { - return `%LP${polarity}*%` - }, -}) diff --git a/src/lib/gerber/commands/set_movement_mode_to_clockwise_circular.ts b/src/lib/gerber/commands/set_movement_mode_to_clockwise_circular.ts deleted file mode 100644 index eb13eb7f..00000000 --- a/src/lib/gerber/commands/set_movement_mode_to_clockwise_circular.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const set_movement_mode_to_clockwise_circular = defineGerberCommand({ - command_code: "G02", - schema: z - .object({ - command_code: z.literal("G02"), - }) - .describe( - "Set movement mode to clockwise circular: Sets linear/circular mode to clockwise circular." - ), - stringify() { - return `G02*` - }, -}) diff --git a/src/lib/gerber/commands/set_movement_mode_to_counterclockwise_circular.ts b/src/lib/gerber/commands/set_movement_mode_to_counterclockwise_circular.ts deleted file mode 100644 index 48aca54a..00000000 --- a/src/lib/gerber/commands/set_movement_mode_to_counterclockwise_circular.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const set_movement_mode_to_counterclockwise_circular = - defineGerberCommand({ - command_code: "G03", // Add the missing command_code property - schema: z - .object({ - command_code: z.literal("G03"), - }) - .describe( - "Set movement mode to counterclockwise circular: Sets linear/circular mode to counterclockwise circular." - ), - stringify() { - return `G03*` - }, - }) diff --git a/src/lib/gerber/commands/set_movement_mode_to_linear.ts b/src/lib/gerber/commands/set_movement_mode_to_linear.ts deleted file mode 100644 index 29a0db08..00000000 --- a/src/lib/gerber/commands/set_movement_mode_to_linear.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const set_movement_mode_to_linear = defineGerberCommand({ - command_code: "G01", - schema: z - .object({ - command_code: z.literal("G01").default("G01"), - }) - .describe( - "Set movement mode to linear: Sets linear/circular mode to linear." - ), - stringify() { - return `G01*` - }, -}) diff --git a/src/lib/gerber/commands/set_unit.ts b/src/lib/gerber/commands/set_unit.ts deleted file mode 100644 index 39f03dde..00000000 --- a/src/lib/gerber/commands/set_unit.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { z } from "zod" -import { defineGerberCommand } from "../define-gerber-command" - -export const set_unit = defineGerberCommand({ - command_code: "MO", - schema: z - .object({ - command_code: z.literal("MO").default("MO"), - unit: z.enum(["mm", "in"]), - }) - .describe("Mode: Sets the unit to mm or inch. 4.2.1"), - stringify({ unit }) { - return `%MO${unit}*%` - }, -}) diff --git a/src/lib/gerber/commands/start_region_statement.ts b/src/lib/gerber/commands/start_region_statement.ts deleted file mode 100644 index 08e378f9..00000000 --- a/src/lib/gerber/commands/start_region_statement.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { z } from "zod" - -export const start_region_statement = z - .object({ - command_code: z.literal("G36"), - statement: z.string(), - }) - .describe( - "Start region statement: Starts a region statement which creates a region by defining its contours." - ) - -export type StartRegionStatement = z.infer diff --git a/src/lib/gerber/commands/step_and_repeat.ts b/src/lib/gerber/commands/step_and_repeat.ts deleted file mode 100644 index 351d8dd0..00000000 --- a/src/lib/gerber/commands/step_and_repeat.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from "zod" - -export const step_and_repeat = z - .object({ - command_code: z.literal("SR"), - statement: z.string(), - }) - .describe("Step and repeat: Open or closes a step and repeat statement.") - -export type StepAndRepeat = z.infer diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/GerberLayerName.ts b/src/lib/gerber/convert-soup-to-gerber-commands/GerberLayerName.ts deleted file mode 100644 index 6de2a6ea..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/GerberLayerName.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { AnyGerberCommand } from "../any_gerber_command" -import { GerberJobJson } from "./gerber-job-json" - -export type LayerToGerberCommandsMap = { - F_Cu: AnyGerberCommand[] - F_SilkScreen: AnyGerberCommand[] - F_Mask: AnyGerberCommand[] - F_Paste: AnyGerberCommand[] - B_Cu: AnyGerberCommand[] - B_SilkScreen: AnyGerberCommand[] - B_Mask: AnyGerberCommand[] - B_Paste: AnyGerberCommand[] - Edge_Cuts: AnyGerberCommand[] -} - -export type GerberLayerName = keyof LayerToGerberCommandsMap diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/define-common-macros.ts b/src/lib/gerber/convert-soup-to-gerber-commands/define-common-macros.ts deleted file mode 100644 index 0916e248..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/define-common-macros.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { AnyGerberCommand } from "../any_gerber_command" -import { gerberBuilder } from "../gerber-builder" - -export const defineCommonMacros = (glayer: Array) => { - glayer.push( - ...gerberBuilder() - .add("comment", { comment: "APERTURE MACROS START" }) - .add("define_macro_aperture_template", { - macro_name: "RoundRect", - template_code: ` -0 Rectangle with rounded corners* -0 $1 Corner radius* -0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y Position of each corner* -0 Polygon box body* -4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0* -0 Circles for rounded corners* -1,1,$1+$1,$2,$3* -1,1,$1+$1,$4,$5* -1,1,$1+$1,$6,$7* -1,1,$1+$1,$8,$9* -0 Rectangles between the rounded corners* -20,1,$1+$1,$2,$3,$4,$5,0* -20,1,$1+$1,$4,$5,$6,$7,0* -20,1,$1+$1,$6,$7,$8,$9,0* -20,1,$1+$1,$8,$9,$2,$3,0*% -`.trim(), - }) - .add("comment", { comment: "APERTURE MACROS END" }) - .build() - ) -} diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/defineAperturesForLayer.ts b/src/lib/gerber/convert-soup-to-gerber-commands/defineAperturesForLayer.ts deleted file mode 100644 index 994427d8..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/defineAperturesForLayer.ts +++ /dev/null @@ -1,150 +0,0 @@ -import type { - AnySoupElement, - LayerRef, - PCBPlatedHole, - PCBSMTPad, -} from "@tscircuit/soup" -import stableStringify from "fast-json-stable-stringify" -import type { AnyGerberCommand } from "../any_gerber_command" -import type { ApertureTemplateConfig } from "../commands/define_aperture_template" -import { gerberBuilder } from "../gerber-builder" -import type { GerberLayerName } from "./GerberLayerName" -import { getAllTraceWidths } from "./getAllTraceWidths" - -export function defineAperturesForLayer({ - glayer, - soup, - glayer_name, -}: { - glayer: AnyGerberCommand[] - soup: AnySoupElement[] - glayer_name: GerberLayerName -}) { - const getNextApertureNumber = () => { - const highest_aperture_number = glayer.reduce((acc, command) => { - if (command.command_code === "ADD") { - return Math.max(acc, command.aperture_number) - } - return acc - }, 0) - if (highest_aperture_number === 0) { - return 10 - } - return highest_aperture_number + 1 - } - - glayer.push( - ...gerberBuilder() - .add("comment", { comment: "aperture START LIST" }) - .build() - ) - - // Add all trace width apertures - const traceWidths: Record = getAllTraceWidths(soup) - for (const width of traceWidths[ - glayer_name.startsWith("F_") ? "top" : "bottom" - ]) { - glayer.push( - ...gerberBuilder() - .add("define_aperture_template", { - aperture_number: getNextApertureNumber(), - standard_template_code: "C", - diameter: width, - }) - .build() - ) - } - - // Add all pcb smtpad, plated hole etc. aperatures - const apertureConfigs = getAllApertureTemplateConfigsForLayer( - soup, - glayer_name.startsWith("F_") ? "top" : "bottom" - ) - - for (const apertureConfig of apertureConfigs) { - glayer.push( - ...gerberBuilder() - .add("define_aperture_template", { - aperture_number: getNextApertureNumber(), - ...apertureConfig, - }) - .build() - ) - } - - glayer.push( - ...gerberBuilder() - .add("delete_attribute", {}) - .add("comment", { comment: "aperture END LIST" }) - .build() - ) -} - -export const getApertureConfigFromPcbSmtpad = ( - elm: PCBSMTPad -): ApertureTemplateConfig => { - if (elm.shape === "rect") { - return { - standard_template_code: "R", - x_size: elm.width, - y_size: elm.height, - } - } else if (elm.shape === "circle") { - return { - standard_template_code: "C", - diameter: elm.radius * 2, - } - } else { - throw new Error(`Unsupported shape ${(elm as any).shape}`) - } -} -export const getApertureConfigFromCirclePcbPlatedHole = ( - elm: PCBPlatedHole -): ApertureTemplateConfig => { - if (!("outer_diameter" in elm && "hole_diameter" in elm)) { - throw new Error( - `Invalid shape called in getApertureConfigFromCirclePcbPlatedHole: ${elm.shape}` - ) - } - return { - standard_template_code: "C", - diameter: elm.outer_diameter, - hole_diameter: elm.hole_diameter, - } -} - -function getAllApertureTemplateConfigsForLayer( - soup: AnySoupElement[], - layer: "top" | "bottom" -): ApertureTemplateConfig[] { - const configs: ApertureTemplateConfig[] = [] - const configHashMap = new Set() - - const addConfigIfNew = (config: ApertureTemplateConfig) => { - const hash = stableStringify(config) - if (!configHashMap.has(hash)) { - configs.push(config) - configHashMap.add(hash) - } - } - - for (const elm of soup) { - if (elm.type === "pcb_smtpad") { - if (elm.layer === layer) { - addConfigIfNew(getApertureConfigFromPcbSmtpad(elm)) - } - } else if (elm.type === "pcb_plated_hole") { - if (elm.layers.includes(layer)) { - if (elm.shape === "circle") { - addConfigIfNew(getApertureConfigFromCirclePcbPlatedHole(elm)) - } else if (elm.shape === "oval") { - console.warn("NOT IMPLEMENTED: drawing gerber for oval plated hole") - } else if (elm.shape === "pill") { - console.warn("NOT IMPLEMENTED: drawing gerber for oval plated pill") - } - } - } - } - - return configs -} diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/findApertureNumber.ts b/src/lib/gerber/convert-soup-to-gerber-commands/findApertureNumber.ts deleted file mode 100644 index 6457758a..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/findApertureNumber.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { - ApertureTemplateConfig, - DefineAperatureTemplateCommand, -} from "../commands/define_aperture_template" -import { AnyGerberCommand } from "../any_gerber_command" - -export const findApertureNumber = ( - glayer: AnyGerberCommand[], - search_params: - | { - trace_width?: number - } - | ApertureTemplateConfig -): number => { - let aperture - if ("trace_width" in search_params) { - const trace_width = search_params.trace_width - aperture = glayer.find( - (command): command is DefineAperatureTemplateCommand => - command.command_code === "ADD" && - command.standard_template_code === "C" && - command.diameter === trace_width - ) - } else if ("standard_template_code" in search_params) { - aperture = glayer.find( - (command): command is DefineAperatureTemplateCommand => - command.command_code === "ADD" && - Object.keys(search_params).every( - (param_name) => command[param_name] === search_params[param_name] - ) - ) - } - - if (!aperture) { - // TODO add FileFunction/layer name to this error to help narrow it - throw new Error( - `Aperture not found for search params ${JSON.stringify(search_params)}` - ) - } - return aperture.aperture_number -} diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/gerber-job-json.ts b/src/lib/gerber/convert-soup-to-gerber-commands/gerber-job-json.ts deleted file mode 100644 index cbf5adb6..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/gerber-job-json.ts +++ /dev/null @@ -1,164 +0,0 @@ -/** - * job.gbrjob file format - * - * { - * "Header": { - * "GenerationSoftware": { - * "Vendor": "KiCad", - * "Application": "Pcbnew", - * "Version": "8.0.1" - * }, - * "CreationDate": "2024-04-08T11:14:22-07:00" - * }, - * "GeneralSpecs": { - * "ProjectId": { - * "Name": "", - * "GUID": "58585858-5858-4585-9858-585858585858", - * "Revision": "rev?" - * }, - * "Size": { - * "X": 0.0, - * "Y": 0.0 - * }, - * "LayerNumber": 2, - * "BoardThickness": 1.6, - * "Finish": "None" - * }, - * "DesignRules": [ - * { - * "Layers": "Outer", - * "PadToPad": 0.2, - * "PadToTrack": 0.2, - * "TrackToTrack": 0.2 - * } - * ], - * "FilesAttributes": [ - * { - * "Path": "-F_Cu.gbr", - * "FileFunction": "Copper,L1,Top", - * "FilePolarity": "Positive" - * }, - * { - * "Path": "-B_Cu.gbr", - * "FileFunction": "Copper,L2,Bot", - * "FilePolarity": "Positive" - * }, - * { - * "Path": "-F_Paste.gbr", - * "FileFunction": "SolderPaste,Top", - * "FilePolarity": "Positive" - * }, - * { - * "Path": "-B_Paste.gbr", - * "FileFunction": "SolderPaste,Bot", - * "FilePolarity": "Positive" - * }, - * { - * "Path": "-F_Silkscreen.gbr", - * "FileFunction": "Legend,Top", - * "FilePolarity": "Positive" - * }, - * { - * "Path": "-B_Silkscreen.gbr", - * "FileFunction": "Legend,Bot", - * "FilePolarity": "Positive" - * }, - * { - * "Path": "-F_Mask.gbr", - * "FileFunction": "SolderMask,Top", - * "FilePolarity": "Negative" - * }, - * { - * "Path": "-B_Mask.gbr", - * "FileFunction": "SolderMask,Bot", - * "FilePolarity": "Negative" - * }, - * { - * "Path": "-Edge_Cuts.gbr", - * "FileFunction": "Profile", - * "FilePolarity": "Positive" - * } - * ], - * "MaterialStackup": [ - * { - * "Type": "Legend", - * "Name": "Top Silk Screen" - * }, - * { - * "Type": "SolderPaste", - * "Name": "Top Solder Paste" - * }, - * { - * "Type": "SolderMask", - * "Name": "Top Solder Mask" - * }, - * { - * "Type": "Copper", - * "Name": "F.Cu" - * }, - * { - * "Type": "Dielectric", - * "Material": "FR4", - * "Name": "F.Cu/B.Cu", - * "Notes": "Type: dielectric layer 1 (from F.Cu to B.Cu)" - * }, - * { - * "Type": "Copper", - * "Name": "B.Cu" - * }, - * { - * "Type": "SolderMask", - * "Name": "Bottom Solder Mask" - * }, - * { - * "Type": "SolderPaste", - * "Name": "Bottom Solder Paste" - * }, - * { - * "Type": "Legend", - * "Name": "Bottom Silk Screen" - * } - * ] - * } - */ -export interface GerberJobJson { - Header: { - GenerationSoftware: { - Vendor: string - Application: string - Version: string - } - CreationDate: string - } - GeneralSpecs: { - ProjectId: { - Name: string - GUID: string - Revision: string - } - Size: { - X: number - Y: number - } - LayerNumber: number - BoardThickness: number - Finish: string - } - DesignRules: { - Layers: string - PadToPad: number - PadToTrack: number - TrackToTrack: number - }[] - FilesAttributes: { - Path: string - FileFunction: string - FilePolarity: string - }[] - MaterialStackup: { - Type: string - Name: string - Material?: string - Notes?: string - }[] -} diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/getAllTraceWidths.ts b/src/lib/gerber/convert-soup-to-gerber-commands/getAllTraceWidths.ts deleted file mode 100644 index 160b0dbf..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/getAllTraceWidths.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { AnySoupElement, LayerRef, PCBTrace } from "@tscircuit/soup" - -export function getAllTraceWidths( - soup: AnySoupElement[] -): Record { - const pcb_traces = soup.filter( - (elm): elm is PCBTrace => elm.type === "pcb_trace" - ) - - const widths: Record> = {} as any - - for (const trace of pcb_traces) { - for (const segment of trace.route) { - if (segment.route_type === "wire") { - widths[segment.layer] = widths[segment.layer] || new Set() - widths[segment.layer].add(segment.width) - } - } - } - - return { - top: Array.from(widths.top || []), - bottom: Array.from(widths.bottom || []), - } as any -} diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/getCommandHeaders.ts b/src/lib/gerber/convert-soup-to-gerber-commands/getCommandHeaders.ts deleted file mode 100644 index 93aa2055..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/getCommandHeaders.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { AnyGerberCommand } from "../any_gerber_command" -import { gerberBuilder } from "../gerber-builder" -import packageJson from "../../../../package.json" - -const layerAndTypeToFileFunction = { - "top-copper": "Copper,L1,Top", - "bottom-copper": "Copper,L2,Bot", - "top-soldermask": "Soldermask,Top", - "bottom-soldermask": "Soldermask,Bot", - "top-silkscreen": "Legend,Top", - "bottom-silkscreen": "Legend,Bot", - "top-paste": "Paste,Top", - "bottom-paste": "Paste,Bot", - edgecut: "Profile,NP", - // TODO inner layers -} - -/** - * Returns headers for a Gerber file. Here's a typical header: - * - * %TF.GenerationSoftware,KiCad,Pcbnew,8.0.1*% - * %TF.CreationDate,2024-04-08T11:14:22-07:00*% - * %TF.ProjectId,,58585858-5858-4585-9858-585858585858,rev?*% - * %TF.SameCoordinates,Original*% - * %TF.FileFunction,Copper,L1,Top*% - * %TF.FilePolarity,Positive*% - * %FSLAX46Y46*% - * G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* - * G04 Created by KiCad (PCBNEW 8.0.1) date 2024-04-08 11:14:22* - * %MOMM*% - * %LPD*% - */ -export const getCommandHeaders = (opts: { - layer: - | "edgecut" - | "top" - | "bottom" - | "inner1" - | "inner2" - | "inner3" - | "inner4" - layer_type?: "copper" | "soldermask" | "silkscreen" | "paste" -}): AnyGerberCommand[] => { - const file_function = - layerAndTypeToFileFunction[ - opts.layer_type ? `${opts.layer}-${opts.layer_type}` : opts.layer - ] - return ( - gerberBuilder() - .add("add_attribute_on_file", { - attribute_name: "GenerationSoftware", - attribute_value: `tscircuit,builder,${packageJson.version}`, - }) - .add("add_attribute_on_file", { - attribute_name: "CreationDate", - attribute_value: new Date().toISOString(), - }) - // .add("add_attribute_on_file", { - // attribute_name: "ProjectId", - // attribute_value: "", - // }) - .add("add_attribute_on_file", { - attribute_name: "SameCoordinates", - attribute_value: "Original", - }) - .add("add_attribute_on_file", { - attribute_name: "FileFunction", - attribute_value: file_function, - }) - .$if(opts.layer !== "edgecut", (gb) => - gb.add("add_attribute_on_file", { - attribute_name: "FilePolarity", - attribute_value: - opts.layer_type === "soldermask" ? "Negative" : "Positive", - }) - ) - .add("format_specification", {}) - .add("set_unit", { - unit: "mm", - }) - .add("comment", { - comment: `Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)`, - }) - .add("comment", { - comment: `Created by tscircuit (builder) date ${new Date().toISOString()}`, - }) - .add("set_movement_mode_to_linear", {}) - .build() - ) -} diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/getGerberLayerName.ts b/src/lib/gerber/convert-soup-to-gerber-commands/getGerberLayerName.ts deleted file mode 100644 index c5c00139..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/getGerberLayerName.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { LayerRef } from "@tscircuit/soup" -import type { GerberLayerName } from "./GerberLayerName" - -const layerRefToGerberPrefix = { - top: "F_", - bottom: "B_", -} as const -const layerTypeToGerberSuffix = { - copper: "Cu", - silkscreen: "SilkScreen", - soldermask: "Mask", - mask: "Mask", - paste: "Paste", -} as const - -export const getGerberLayerName = ( - layer_ref: LayerRef | "edgecut", - layer_type: "copper" | "silkscreen" | "soldermask" | "paste" -): GerberLayerName => { - if (layer_ref === "edgecut") return "Edge_Cuts" - return `${layerRefToGerberPrefix[layer_ref]}${layerTypeToGerberSuffix[layer_type]}` as any -} diff --git a/src/lib/gerber/convert-soup-to-gerber-commands/index.ts b/src/lib/gerber/convert-soup-to-gerber-commands/index.ts deleted file mode 100644 index 82292cf7..00000000 --- a/src/lib/gerber/convert-soup-to-gerber-commands/index.ts +++ /dev/null @@ -1,201 +0,0 @@ -import type { AnySoupElement } from "@tscircuit/soup" -import { pairs } from "lib/utils/pairs" -import { gerberBuilder } from "../gerber-builder" -import type { LayerToGerberCommandsMap } from "./GerberLayerName" -import { - defineAperturesForLayer, - getApertureConfigFromCirclePcbPlatedHole, - getApertureConfigFromPcbSmtpad, -} from "./defineAperturesForLayer" -import { findApertureNumber } from "./findApertureNumber" -import { getCommandHeaders } from "./getCommandHeaders" -import { getGerberLayerName } from "./getGerberLayerName" - -/** - * Converts tscircuit soup to arrays of Gerber commands for each layer - */ -export const convertSoupToGerberCommands = ( - soup: AnySoupElement[], - opts: { flip_y_axis?: boolean } = {} -): LayerToGerberCommandsMap => { - opts.flip_y_axis ??= false - const glayers: LayerToGerberCommandsMap = { - F_Cu: getCommandHeaders({ - layer: "top", - layer_type: "copper", - }), - F_SilkScreen: [], - F_Mask: getCommandHeaders({ - layer: "top", - layer_type: "soldermask", - }), - F_Paste: [], - B_Cu: getCommandHeaders({ - layer: "bottom", - layer_type: "copper", - }), - B_SilkScreen: [], - B_Mask: getCommandHeaders({ - layer: "bottom", - layer_type: "soldermask", - }), - B_Paste: [], - Edge_Cuts: getCommandHeaders({ - layer: "edgecut", - }), - } - - for (const glayer_name of ["F_Cu", "B_Cu", "F_Mask", "B_Mask"] as const) { - const glayer = glayers[glayer_name] - // defineCommonMacros(glayer) - defineAperturesForLayer({ - soup, - glayer, - glayer_name, - }) - } - - // Edgecuts has a single aperature - glayers["Edge_Cuts"].push( - ...gerberBuilder() - .add("define_aperture_template", { - aperture_number: 10, - standard_template_code: "C", - diameter: 0.05, //mm - }) - .build() - ) - - /** - * "maybe flip y axis" to handle y axis negating - */ - const mfy = (y: number) => (opts.flip_y_axis ? -y : y) - - for (const layer of ["top", "bottom", "edgecut"] as const) { - for (const element of soup) { - if (element.type === "pcb_trace") { - const { route } = element - for (const [a, b] of pairs(route)) { - // TODO b kind of matters here, this doesn't handle a bunch of cases - // but the definition of a route is also kind of broken, a "wire" is - // a relationship between two points and can't really be a type of - // point - if (a.route_type === "wire") { - if (a.layer === layer) { - const glayer = glayers[getGerberLayerName(layer, "copper")] - glayer.push( - ...gerberBuilder() - .add("select_aperture", { - aperture_number: findApertureNumber(glayer, { - trace_width: a.width, - }), - }) - .add("move_operation", { x: a.x, y: mfy(a.y) }) - .add("plot_operation", { x: b.x, y: mfy(b.y) }) - .build() - ) - } - } - } - } else if (element.type === "pcb_smtpad") { - if (element.layer === layer) { - for (const glayer of [ - glayers[getGerberLayerName(layer, "copper")], - glayers[getGerberLayerName(layer, "soldermask")], - ]) { - glayer.push( - ...gerberBuilder() - .add("select_aperture", { - aperture_number: findApertureNumber( - glayer, - getApertureConfigFromPcbSmtpad(element) - ), - }) - .add("flash_operation", { x: element.x, y: mfy(element.y) }) - .build() - ) - } - } - } else if (element.type === "pcb_plated_hole") { - if (element.layers.includes(layer as any)) { - for (const glayer of [ - glayers[getGerberLayerName(layer, "copper")], - glayers[getGerberLayerName(layer, "soldermask")], - ]) { - if (element.shape !== "circle") { - console.warn( - "NOT IMPLEMENTED: drawing gerber for non-circle plated hole" - ) - continue - } - glayer.push( - ...gerberBuilder() - .add("select_aperture", { - aperture_number: findApertureNumber( - glayer, - getApertureConfigFromCirclePcbPlatedHole(element) - ), - }) - .add("flash_operation", { x: element.x, y: mfy(element.y) }) - .build() - ) - } - } - } else if (element.type === "pcb_board" && layer === "edgecut") { - const glayer = glayers.Edge_Cuts - const { width, height, center, outline } = element - const gerberBuild = gerberBuilder().add("select_aperture", { - aperture_number: 10, - }) - if (outline && outline.length > 2) { - gerberBuild.add("move_operation", outline[0]) - for (let i = 1; i < outline.length; i++) { - gerberBuild.add("plot_operation", outline[i]) - } - } else { - gerberBuild - .add("move_operation", { - x: center.x - width / 2, - y: mfy(center.y - height / 2), - }) - .add("plot_operation", { - x: center.x + width / 2, - y: mfy(center.y - height / 2), - }) - // .add("move_operation", { - // x: center.x + width / 2, - // y: center.y - height / 2, - // }) - .add("plot_operation", { - x: center.x + width / 2, - y: mfy(center.y + height / 2), - }) - // .add("move_operation", { - // x: center.x + width / 2, - // y: center.y + height / 2, - // }) - .add("plot_operation", { - x: center.x - width / 2, - y: mfy(center.y + height / 2), - }) - // .add("move_operation", { - // x: center.x - width / 2, - // y: center.y + height / 2, - // }) - .add("plot_operation", { - x: center.x - width / 2, - y: mfy(center.y - height / 2), - }) - } - - glayer.push(...gerberBuild.build()) - } - } - } - - for (const key of Object.keys(glayers)) { - glayers[key].push(...gerberBuilder().add("end_of_file", {}).build()) - } - - return glayers -} diff --git a/src/lib/gerber/define-gerber-command.ts b/src/lib/gerber/define-gerber-command.ts deleted file mode 100644 index 51f9c315..00000000 --- a/src/lib/gerber/define-gerber-command.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AnyZodObject, z, ZodObject, ZodUnion } from "zod" - -export interface GerberCommandDef< - K extends string, - T extends AnyZodObject | z.ZodIntersection -> { - command_code: K - schema: T - stringify: (c: z.infer) => string -} - -export const defineGerberCommand = < - K extends string, - T extends AnyZodObject | z.ZodIntersection ->({ - command_code, - schema, - stringify, -}: { - command_code: K - schema: T - stringify: (c: z.infer) => string -}): GerberCommandDef => { - return { - command_code, - schema, - stringify, - } -} diff --git a/src/lib/gerber/gerber-builder.ts b/src/lib/gerber/gerber-builder.ts deleted file mode 100644 index 780016ba..00000000 --- a/src/lib/gerber/gerber-builder.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { AnyGerberCommand } from "./any_gerber_command" -import { z } from "zod" -import { gerber_command_map } from "./any_gerber_command" - -export const gerberBuilder = () => new GerberBuilder() - -class GerberBuilder { - commands: Array - - constructor() { - this.commands = [] - } - - $if( - condition: boolean, - fn: (gb: GerberBuilder) => GerberBuilder - ): GerberBuilder { - if (condition) { - return fn(this) - } - return this - } - - add( - cmd: T, - props: z.input<(typeof gerber_command_map)[T]["schema"]> - ): GerberBuilder { - this.commands.push({ - ...({ command_code: gerber_command_map[cmd].command_code } as any), - ...props, - }) - return this - } - - build(): Array { - return this.commands - } -} - -// Type test: -// gerber() -// .add("add_attribute_on_aperture", { -// attribute_name: "foo", -// attribute_value: "bar", -// }) -// .add("end_of_file", {}) -// .build() diff --git a/src/lib/gerber/index.ts b/src/lib/gerber/index.ts deleted file mode 100644 index fb7f8c60..00000000 --- a/src/lib/gerber/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./gerber-builder" -export * from "./stringify-gerber" -export * from "./convert-soup-to-gerber-commands" diff --git a/src/lib/gerber/stringify-gerber/get-gerber-coordinate-with-padding.ts b/src/lib/gerber/stringify-gerber/get-gerber-coordinate-with-padding.ts deleted file mode 100644 index 2f22ebae..00000000 --- a/src/lib/gerber/stringify-gerber/get-gerber-coordinate-with-padding.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Retrieves the Gerber coordinate with padding. - * - * Example Gerber coordinate strings: - * full string: X110550000Y-85000000D03* - * formatted coordinate for X: 110550000 - * - * Example inputs/outputs: - * input: 110.55 - * output: 110550000 - * - * @param coordinate_mm - The coordinate value in millimeters. - * @returns The Gerber coordinate with padding. - */ -export const getGerberCoordinateWithPadding = ( - coordinate_mm: number -): string => { - const coordinate_um = coordinate_mm * 1000000 // Convert millimeters to micrometers - let coordinate_str = coordinate_um.toFixed(0) // Convert to string without decimal places - // add left padding - while (coordinate_str.length < 9) { - if (coordinate_um < 0) { - coordinate_str = "-0" + coordinate_str.slice(1) - } else { - coordinate_str = "0" + coordinate_str - } - } - return coordinate_str -} diff --git a/src/lib/gerber/stringify-gerber/index.ts b/src/lib/gerber/stringify-gerber/index.ts deleted file mode 100644 index 92e7f255..00000000 --- a/src/lib/gerber/stringify-gerber/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./stringify-gerber-command-layers" -export * from "./stringify-gerber-command" -export * from "./stringify-gerber-commands" diff --git a/src/lib/gerber/stringify-gerber/stringify-gerber-command-layers.ts b/src/lib/gerber/stringify-gerber/stringify-gerber-command-layers.ts deleted file mode 100644 index 7feb3af8..00000000 --- a/src/lib/gerber/stringify-gerber/stringify-gerber-command-layers.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AnyGerberCommand } from "../any_gerber_command" -import { GerberLayerName } from "../convert-soup-to-gerber-commands/GerberLayerName" -import { stringifyGerberCommand } from "./stringify-gerber-command" - -export const stringifyGerberCommandLayers = ( - commandLayers: Record -): Record => { - const stringifiedCommandLayers: Record = {} as any - for (const layerName of Object.keys(commandLayers) as GerberLayerName[]) { - stringifiedCommandLayers[layerName] = commandLayers[layerName] - .map((command) => { - return stringifyGerberCommand(command) - }) - .join("\n") - } - return stringifiedCommandLayers -} diff --git a/src/lib/gerber/stringify-gerber/stringify-gerber-command.ts b/src/lib/gerber/stringify-gerber/stringify-gerber-command.ts deleted file mode 100644 index 08271d47..00000000 --- a/src/lib/gerber/stringify-gerber/stringify-gerber-command.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AnyGerberCommand, gerber_command_map } from "../any_gerber_command" - -export const stringifyGerberCommand = (command: AnyGerberCommand): string => { - const command_def = Object.values(gerber_command_map).find( - (cmd) => cmd.command_code === command.command_code - ) - - if (!command_def) { - throw new Error( - `Command for command_code:"${command.command_code}" not found` - ) - } - - if (!command_def.stringify) { - throw new Error( - `Command for command_code:"${command.command_code}" does not have a stringify method` - ) - } - - return command_def.stringify(command as any) -} diff --git a/src/lib/gerber/stringify-gerber/stringify-gerber-commands.ts b/src/lib/gerber/stringify-gerber/stringify-gerber-commands.ts deleted file mode 100644 index d22ee530..00000000 --- a/src/lib/gerber/stringify-gerber/stringify-gerber-commands.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { AnyGerberCommand } from "../any_gerber_command" -import { stringifyGerberCommand } from "./stringify-gerber-command" - -export const stringifyGerberCommands = ( - commands: AnyGerberCommand[] -): string => { - return commands - .map((command) => { - return stringifyGerberCommand(command) - }) - .join("\n") -} diff --git a/tests/excellon-drill/convert-soup-to-excellon-drill.test.ts b/tests/excellon-drill/convert-soup-to-excellon-drill.test.ts deleted file mode 100644 index 688d6a5c..00000000 --- a/tests/excellon-drill/convert-soup-to-excellon-drill.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import test from "ava" -import { convertSoupToExcellonDrillCommands } from "lib/excellon-drill/convert-soup-to-excellon-drill-commands" -import { stringifyExcellonDrill } from "lib/excellon-drill/stringify-excellon-drill" -import { getTestFixture } from "tests/fixtures/get-test-fixture" - -test("generate excellon drill text from axial resistor", async (t) => { - const { logSoup, pb } = await getTestFixture(t) - - const soup = await pb - .add("resistor", (rb) => - rb.modifyFootprint((fb) => - fb - .add("platedhole", (phb) => - phb.setProps({ - shape: "circle", - hole_diameter: "0.0394in", - outer_diameter: "0.05in", - x: 0, - y: 0, - }) - ) - .add("platedhole", (phb) => - phb.setProps({ - shape: "circle", - hole_diameter: "0.0394in", - outer_diameter: "0.05in", - x: "0.3in", - y: 0, - }) - ) - .add("pcb_via", (pv) => - pv.setProps({ - hole_diameter: "0.05in", - x: "0.6in", - y: 0, - layers: ["top", "bottom"], - }) - ) - ) - ) - .build() - - await logSoup(soup) - - const excellon_drill_cmds = convertSoupToExcellonDrillCommands({ - soup: soup as any, - is_plated: true, - }) - - const excellon_drill_file_content = - stringifyExcellonDrill(excellon_drill_cmds) - - t.truthy(excellon_drill_file_content.includes("X0.3000Y0.0000")) - t.truthy(excellon_drill_file_content.includes("T11C0.050000")) - t.truthy(excellon_drill_file_content.includes("G90")) - t.truthy(excellon_drill_file_content.includes("G05")) -}) diff --git a/tests/excellon-drill/excellon-drill-builder.test.ts b/tests/excellon-drill/excellon-drill-builder.test.ts deleted file mode 100644 index f66fce81..00000000 --- a/tests/excellon-drill/excellon-drill-builder.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -import test from "ava" -import { excellonDrill } from "lib/excellon-drill/excellon-drill-builder" - -test("test that we can recreate an example drill file", (t) => { - const output_commands = excellonDrill() - .add("M48", {}) - .add("header_comment", { - text: "DRILL file {tscircuit} date 2024-04-09T20:34:41-0700", - }) - .add("header_comment", { - text: "FORMAT={-:-/ absolute / inch / decimal}", - }) - .add("header_attribute", { - attribute_name: "TF.CreationDate", - attribute_value: "2024-04-09T20:34:41-07:00", - }) - .add("header_attribute", { - attribute_name: "TF.GenerationSoftware", - attribute_value: "Kicad,Pcbnew,8.0.1", - }) - .add("header_attribute", { - attribute_name: "TF.FileFunction", - attribute_value: "Plated,1,2,PTH", - }) - .add("FMAT", { format: 2 }) - .add("header_comment", { - text: "TA.AperFunction,Plated,PTH,ComponentDrill", - }) - .add("T", { tool_number: 1, diameter: 0.0394 }) - .add("header_comment", { text: "End of header" }) - .add("G90", {}) - .add("G05", {}) - .add("T", { tool_number: 1, diameter: 0.0394 }) - .add("drill_at", { x: 4.9197, y: -2.9724 }) - .add("drill_at", { x: 5.0197, y: -2.9724 }) - .add("M30", {}) - .build() - - t.snapshot(output_commands) - // t.is( - // output_text, - // `M48 - // ; DRILL file {tscircuit} date 2024-04-09T20:34:41-0700 - // ; FORMAT={-:-/ absolute / inch / decimal} - // ; #@! TF.CreationDate,2024-04-09T20:34:41-07:00 - // ; #@! TF.GenerationSoftware,Kicad,Pcbnew,8.0.1 - // ; #@! TF.FileFunction,Plated,1,2,PTH - // FMAT,2 - // INCH - // ; #@! TA.AperFunction,Plated,PTH,ComponentDrill - // T1C0.0394 - // % - // G90 - // G05 - // T1 - // X4.9197Y-2.9724 - // X5.0197Y-2.9724 - // M30` - // ) -}) diff --git a/tests/excellon-drill/excellon-drill-stringification.test.ts b/tests/excellon-drill/excellon-drill-stringification.test.ts deleted file mode 100644 index f89599ed..00000000 --- a/tests/excellon-drill/excellon-drill-stringification.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import test from "ava" -import { stringifyExcellonDrill } from "lib/excellon-drill/stringify-excellon-drill" -import { excellonDrill } from "lib/excellon-drill/excellon-drill-builder" - -test("test that we can recreate an example drill file", (t) => { - const output_commands = excellonDrill() - .add("M48", {}) - .add("header_comment", { - text: "DRILL file {tscircuit} date 2024-04-09T20:34:41-0700", - }) - .add("header_comment", { - text: "FORMAT={-:-/ absolute / inch / decimal}", - }) - .add("header_attribute", { - attribute_name: "TF.CreationDate", - attribute_value: "2024-04-09T20:34:41-07:00", - }) - .add("header_attribute", { - attribute_name: "TF.GenerationSoftware", - attribute_value: "Kicad,Pcbnew,8.0.1", - }) - .add("header_attribute", { - attribute_name: "TF.FileFunction", - attribute_value: "Plated,1,2,PTH", - }) - .add("FMAT", { format: 2 }) - .add("unit_format", { unit: "INCH" }) - .add("header_attribute", { - attribute_name: "TA.AperFunction", - attribute_value: "Plated,PTH,ComponentDrill", - }) - .add("define_tool", { tool_number: 1, diameter: 0.0394 }) - .add("rewind", {}) - .add("G90", {}) - .add("G05", {}) - .add("use_tool", { tool_number: 1 }) - .add("drill_at", { x: 4.9197, y: -2.9724 }) - .add("drill_at", { x: 5.0197, y: -2.9724 }) - .add("M30", {}) - .build() - - const output_text = stringifyExcellonDrill(output_commands) - const target_output = `M48 - ; DRILL file {tscircuit} date 2024-04-09T20:34:41-0700 - ; FORMAT={-:-/ absolute / inch / decimal} - ; #@! TF.CreationDate,2024-04-09T20:34:41-07:00 - ; #@! TF.GenerationSoftware,Kicad,Pcbnew,8.0.1 - ; #@! TF.FileFunction,Plated,1,2,PTH - FMAT,2 - INCH - ; #@! TA.AperFunction,Plated,PTH,ComponentDrill - T1C0.039400 - % - G90 - G05 - T1 - X4.9197Y-2.9724 - X5.0197Y-2.9724 - M30` - - const output_lines = output_text.split("\n") - const target_lines = target_output.split("\n") - - for (let i = 0; i < output_lines.length; i++) { - t.is( - output_lines[i].trim(), - target_lines[i].trim(), - `Line ${i} did not match\n\nExpected:\n${target_lines - .slice(i - 3, i + 1) - .join("\n")}\n\nGot:\n${output_lines.slice(i - 3, i + 1).join("\n")}` - ) - } -}) diff --git a/tests/excellon-drill/snapshots/excellon-drill-builder.test.ts.md b/tests/excellon-drill/snapshots/excellon-drill-builder.test.ts.md deleted file mode 100644 index 9225e466..00000000 --- a/tests/excellon-drill/snapshots/excellon-drill-builder.test.ts.md +++ /dev/null @@ -1,79 +0,0 @@ -# Snapshot report for `tests/excellon-drill/excellon-drill-builder.test.ts` - -The actual snapshot is saved in `excellon-drill-builder.test.ts.snap`. - -Generated by [AVA](https://avajs.dev). - -## test that we can recreate an example drill file - -> Snapshot 1 - - [ - { - command_code: 'M48', - }, - { - command_code: 'header_comment', - text: 'DRILL file {tscircuit} date 2024-04-09T20:34:41-0700', - }, - { - command_code: 'header_comment', - text: 'FORMAT={-:-/ absolute / inch / decimal}', - }, - { - attribute_name: 'TF.CreationDate', - attribute_value: '2024-04-09T20:34:41-07:00', - command_code: 'header_attribute', - }, - { - attribute_name: 'TF.GenerationSoftware', - attribute_value: 'Kicad,Pcbnew,8.0.1', - command_code: 'header_attribute', - }, - { - attribute_name: 'TF.FileFunction', - attribute_value: 'Plated,1,2,PTH', - command_code: 'header_attribute', - }, - { - command_code: 'FMAT', - format: 2, - }, - { - command_code: 'header_comment', - text: 'TA.AperFunction,Plated,PTH,ComponentDrill', - }, - { - command_code: 'define_tool', - diameter: 0.0394, - tool_number: 1, - }, - { - command_code: 'header_comment', - text: 'End of header', - }, - { - command_code: 'G90', - }, - { - command_code: 'G05', - }, - { - command_code: 'define_tool', - diameter: 0.0394, - tool_number: 1, - }, - { - command_code: 'drill_at', - x: 4.9197, - y: -2.9724, - }, - { - command_code: 'drill_at', - x: 5.0197, - y: -2.9724, - }, - { - command_code: 'M30', - }, - ] diff --git a/tests/excellon-drill/snapshots/excellon-drill-builder.test.ts.snap b/tests/excellon-drill/snapshots/excellon-drill-builder.test.ts.snap deleted file mode 100644 index e90d546b..00000000 Binary files a/tests/excellon-drill/snapshots/excellon-drill-builder.test.ts.snap and /dev/null differ diff --git a/tests/fixtures/maybe-output-gerber.ts b/tests/fixtures/maybe-output-gerber.ts deleted file mode 100644 index 7b617011..00000000 --- a/tests/fixtures/maybe-output-gerber.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const maybeOutputGerber = async (gerber_map: Record) => { - // @ts-ignore - if (process.env.OUTPUT_GERBER) { - // @ts-ignore - const fs = await import("fs") - fs.mkdirSync("./gerber-output", { recursive: true }) - for (const filename of Object.keys(gerber_map)) { - const fp = `./gerber-output/${filename}.gbr` - // console.log(`Writing ${fp}`) - fs.writeFileSync(fp, gerber_map[filename]) - } - } -} diff --git a/tests/gerber/generate-board-outline-gerber.test.ts b/tests/gerber/generate-board-outline-gerber.test.ts deleted file mode 100644 index 32e9be0e..00000000 --- a/tests/gerber/generate-board-outline-gerber.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import test from "ava" -import { convertSoupToGerberCommands } from "lib/gerber/convert-soup-to-gerber-commands" -import { - stringifyGerberCommandLayers, - stringifyGerberCommands, -} from "lib/gerber/stringify-gerber" -import { maybeOutputGerber } from "tests/fixtures/maybe-output-gerber" - -// If you're trying to test this, I would recommend opening up Kicad's Gerber -// Viewer and loading in the files from the generated directory "gerber-output" -// that's produced if OUTPUT_GERBER=1 when you do `npx ava ./tests/gerber/generate-gerber-with-trace.test.ts` -// You can generate the files then hit reload in the Gerber Viewer to see that -// everything looks approximately correct -test("Generate simple gerber with a single trace", async (t) => { - const gerber_cmds = convertSoupToGerberCommands([ - { - type: "pcb_board", - width: 20, - height: 20, - center: { x: 10, y: -10 }, - outline: [ - { x: -22.5, y: 24.5 }, - { x: 22.5, y: 24.5 }, - { x: 22.5, y: 16.5 }, - { x: 20.5, y: 16.5 }, - { x: 20.5, y: 12.5 }, - { x: 22.5, y: 12.5 }, - { x: 22.5, y: 2.5 }, - { x: 18, y: -1.5 }, - { x: 18, y: -18 }, - { x: -18, y: -18 }, - { x: -18, y: -1.5 }, - { x: -22.5, y: 2.5 }, - { x: -22.5, y: 12.5 }, - { x: -20.5, y: 12.5 }, - { x: -20.5, y: 16.5 }, - { x: -22.5, y: 16.5 }, - { x: -22.5, y: 24.5 }, - ], - }, - { - type: "pcb_trace", - source_trace_id: "source_trace_1", - pcb_trace_id: "pcb_trace_1", - route: [ - { - x: -10, - y: 0, - width: 0.1, - route_type: "wire", - layer: "top", - }, - { - x: 10, - y: 0, - width: 0.1, - route_type: "wire", - layer: "top", - }, - ], - }, - ]) - const edgecut_gerber = stringifyGerberCommands(gerber_cmds.Edge_Cuts) - // console.log("Gerber") - // console.log("----------------------------------------------") - // console.log(edgecut_gerber) - - // TODO parse gerber to check for correctness - - await maybeOutputGerber(stringifyGerberCommandLayers(gerber_cmds)) - t.pass() -}) diff --git a/tests/gerber/generate-gerber-with-basic-elements.test.ts b/tests/gerber/generate-gerber-with-basic-elements.test.ts deleted file mode 100644 index 77bf361b..00000000 --- a/tests/gerber/generate-gerber-with-basic-elements.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import test from "ava" -import { convertSoupToGerberCommands } from "lib/gerber/convert-soup-to-gerber-commands" -import { - stringifyGerberCommandLayers, - stringifyGerberCommands, -} from "lib/gerber/stringify-gerber" -import { maybeOutputGerber } from "tests/fixtures/maybe-output-gerber" - -// If you're trying to test this, I would recommend opening up Kicad's Gerber -// Viewer and loading in the files from the generated directory "gerber-output" -// that's produced if OUTPUT_GERBER=1 when you do `npx ava ./tests/gerber/generate-gerber-with-trace.test.ts` -// You can generate the files then hit reload in the Gerber Viewer to see that -// everything looks approximately correct -test("Generate simple gerber with basic elements", async (t) => { - const gerber_cmds = convertSoupToGerberCommands([ - { - type: "pcb_board", - width: 20, - height: 20, - center: { x: 0, y: 0 }, - }, - { - type: "pcb_trace", - source_trace_id: "source_trace_1", - pcb_trace_id: "pcb_trace_1", - route: [ - { - x: 0, - y: 0, - width: 0.1, - route_type: "wire", - layer: "top", - }, - { - x: 1, - y: 0, - width: 0.1, - route_type: "wire", - layer: "top", - }, - ], - }, - { - pcb_smtpad_id: "smtpad_1", - type: "pcb_smtpad", - shape: "rect", - height: 1, - width: 1, - x: 1, - y: 1, - layer: "top", - }, - { - pcb_smtpad_id: "smtpad_2", - type: "pcb_smtpad", - shape: "rect", - height: 1, - width: 1, - x: 2, - y: -1, - layer: "bottom", - }, - { - type: "pcb_plated_hole", - shape: "circle", - x: 4, - y: 1, - hole_diameter: 0.8, - layers: ["top", "bottom"], - outer_diameter: 2, - }, - ]) - const fu_cp = stringifyGerberCommands(gerber_cmds.F_Cu) - // console.log("Gerber") - // console.log("----------------------------------------------") - // console.log(fu_cp) - // console.log(stringifyGerberCommands(gerber_cmds.B_Mask)) - - // TODO parse gerber to check for correctness - - await maybeOutputGerber(stringifyGerberCommandLayers(gerber_cmds)) - t.pass() -}) diff --git a/tests/net-builder/__snapshots__/net-builder-1-pcb.snapshot.png b/tests/net-builder/__snapshots__/net-builder-1-pcb.snapshot.png new file mode 100644 index 00000000..4f6cc8b3 Binary files /dev/null and b/tests/net-builder/__snapshots__/net-builder-1-pcb.snapshot.png differ diff --git a/tests/trace-builder/__snapshots__/multi-layer-route-2-pcb.snapshot.png b/tests/trace-builder/__snapshots__/multi-layer-route-2-pcb.snapshot.png new file mode 100644 index 00000000..7471e54b Binary files /dev/null and b/tests/trace-builder/__snapshots__/multi-layer-route-2-pcb.snapshot.png differ