circuitscript 0.5.5 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -2
- package/dist/cjs/execute.js +6 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/regenerate-tests.js +12 -3
- package/dist/esm/execute.js +6 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/regenerate-tests.js +12 -3
- package/dist/types/index.d.ts +1 -0
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -1,3 +1,106 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Circuitscript
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A code-based language for creating electronic schematics. Instead of clicking through GUI tools, you write Circuitscript to describe circuits — and get SVG/PDF schematics and KiCAD-compatible netlists as output.
|
|
4
|
+
|
|
5
|
+
**Homepage:** https://circuitscript.net
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Code-first design** — capture schematics using a simple scripting language
|
|
12
|
+
- **Version control friendly** — plain text files work naturally with git
|
|
13
|
+
- **SVG and PDF output** — high-quality schematic diagrams
|
|
14
|
+
- **KiCAD netlist export** — use generated netlists directly in KiCAD layout
|
|
15
|
+
- **Bill of Materials** — export BOM as CSV
|
|
16
|
+
- **Programmatic constructs** — loops, functions, conditionals, and modules for reusable circuit blocks
|
|
17
|
+
- **Standard library of components** — resistors, capacitors, inductors, LEDs, etc.
|
|
18
|
+
- **Custom components** — define components with arbitrary pin layouts and graphics
|
|
19
|
+
- **ERC** — basic electrical rules check (more to be added)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Requires Node.js 16 or later.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install -g circuitscript
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or install locally as a library:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install circuitscript
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
Create a file `circuit.cst`:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
from "std" import *
|
|
45
|
+
|
|
46
|
+
v5 = supply("5V")
|
|
47
|
+
gnd = dgnd()
|
|
48
|
+
|
|
49
|
+
at v5
|
|
50
|
+
wire down 100
|
|
51
|
+
add res(100k)
|
|
52
|
+
wire down 100
|
|
53
|
+
to gnd
|
|
54
|
+
|
|
55
|
+
at v5
|
|
56
|
+
wire down 100
|
|
57
|
+
add cap(100n)
|
|
58
|
+
wire down 100
|
|
59
|
+
to gnd
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Generate a schematic:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
circuitscript circuit.cst output.svg
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## CLI Usage
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
circuitscript [input path] [output path] [options]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Options
|
|
77
|
+
|
|
78
|
+
| Option | Description |
|
|
79
|
+
|--------|-------------|
|
|
80
|
+
| `-w, --watch` | Watch for file changes and regenerate |
|
|
81
|
+
| `-u, --update-source` | Update source file with reference designator annotation |
|
|
82
|
+
| `-j, --annotated-path [file]` | Save annotated source file at given path |
|
|
83
|
+
| `-n, --dump-nets` | Print net information |
|
|
84
|
+
| `-d, --dump-data` | Dump data during parsing |
|
|
85
|
+
| `-s, --stats` | Show stats during generation |
|
|
86
|
+
| `-x, --skip-output` | Skip output generation |
|
|
87
|
+
| `-e, --erc` | Enable ERC output |
|
|
88
|
+
| `-b, --bom [output-path]` | Generate Bill of Materials as CSV |
|
|
89
|
+
| `-i, --input text <text>` | Provide input text directly instead of a file |
|
|
90
|
+
| `--version` | Show version |
|
|
91
|
+
|
|
92
|
+
### Examples
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Generate SVG
|
|
96
|
+
circuitscript schematic.cst schematic.svg
|
|
97
|
+
|
|
98
|
+
# Generate PDF
|
|
99
|
+
circuitscript schematic.cst schematic.pdf
|
|
100
|
+
|
|
101
|
+
# Generate BOM
|
|
102
|
+
circuitscript schematic.cst schematic.svg --bom bom.csv
|
|
103
|
+
|
|
104
|
+
# Print to stdout
|
|
105
|
+
circuitscript schematic.cst
|
|
106
|
+
```
|
package/dist/cjs/execute.js
CHANGED
|
@@ -374,6 +374,7 @@ class ExecutionContext {
|
|
|
374
374
|
this.applyComponentAngleFromWire(component, pinId);
|
|
375
375
|
this.scope.setCurrent(component, pinId);
|
|
376
376
|
this.scope.clearActive();
|
|
377
|
+
this.log('clear active wire/frame (to component)');
|
|
377
378
|
if (addSequence) {
|
|
378
379
|
if (this.scope.sequence.length > 0) {
|
|
379
380
|
const [entryType, , segments] = this.scope.sequence[this.scope.sequence.length - 1];
|
|
@@ -410,6 +411,7 @@ class ExecutionContext {
|
|
|
410
411
|
this.scope.setNet(component, usePinId, tmpNet);
|
|
411
412
|
}
|
|
412
413
|
this.scope.clearActive();
|
|
414
|
+
this.log('clear active wire/frame (at component)');
|
|
413
415
|
if (addSequence) {
|
|
414
416
|
this.scope.sequence.push([ExecutionScope_js_1.SequenceAction.At,
|
|
415
417
|
component, usePinId]);
|
|
@@ -448,8 +450,12 @@ class ExecutionContext {
|
|
|
448
450
|
|| blockType === BlockTypes_js_1.BlockTypes.Parallel
|
|
449
451
|
|| blockType === BlockTypes_js_1.BlockTypes.Branch) {
|
|
450
452
|
const key = (0, utils_js_1.getBlockTypeString)(blockType);
|
|
453
|
+
const wireIdBefore = this.scope.currentWireId;
|
|
451
454
|
this.addPoint(`${globals_js_1.Delimiter1}${key}.${this.name}.${this.tmpPointId}`, false);
|
|
452
455
|
this.tmpPointId += 1;
|
|
456
|
+
if (wireIdBefore !== -1) {
|
|
457
|
+
this.scope.currentWireId = wireIdBefore;
|
|
458
|
+
}
|
|
453
459
|
}
|
|
454
460
|
this.scope.blockStack.set(this.scope.scopeLevel, {
|
|
455
461
|
start_point: [
|
package/dist/cjs/index.js
CHANGED
|
@@ -31,6 +31,7 @@ __exportStar(require("./parser.js"), exports);
|
|
|
31
31
|
__exportStar(require("./utils.js"), exports);
|
|
32
32
|
__exportStar(require("./visitor.js"), exports);
|
|
33
33
|
__exportStar(require("./sizing.js"), exports);
|
|
34
|
+
__exportStar(require("./errors.js"), exports);
|
|
34
35
|
__exportStar(require("./objects/types.js"), exports);
|
|
35
36
|
__exportStar(require("./builtinMethods.js"), exports);
|
|
36
37
|
__exportStar(require("./validate/SymbolTable.js"), exports);
|
|
@@ -9,13 +9,15 @@ const environment_js_1 = require("./environment/environment.js");
|
|
|
9
9
|
const mainDir = './__tests__/testData/renderData/';
|
|
10
10
|
const env = new environment_js_1.NodeScriptEnvironment();
|
|
11
11
|
environment_js_1.NodeScriptEnvironment.setInstance(env);
|
|
12
|
-
async function regenerateTests(extra = "") {
|
|
12
|
+
async function regenerateTests(extra = "", fileList = []) {
|
|
13
13
|
await env.prepareSVGEnvironment();
|
|
14
14
|
const cstFiles = [];
|
|
15
15
|
const files = fs_1.default.readdirSync(mainDir);
|
|
16
16
|
files.forEach(file => {
|
|
17
17
|
if (file.endsWith('.cst') && file.startsWith('script')) {
|
|
18
|
-
|
|
18
|
+
if (fileList.length === 0 || fileList.includes(file)) {
|
|
19
|
+
cstFiles.push(file);
|
|
20
|
+
}
|
|
19
21
|
}
|
|
20
22
|
});
|
|
21
23
|
for (let i = 0; i < cstFiles.length; i++) {
|
|
@@ -38,8 +40,15 @@ async function regenerateTests(extra = "") {
|
|
|
38
40
|
(async () => {
|
|
39
41
|
const generateDiff = (process.argv.indexOf('-diff') !== -1);
|
|
40
42
|
console.log('diff flag: ', generateDiff);
|
|
43
|
+
const listIndex = process.argv.indexOf('--list');
|
|
44
|
+
const fileList = listIndex !== -1 && process.argv[listIndex + 1]
|
|
45
|
+
? process.argv[listIndex + 1].split(',').map(f => f.trim())
|
|
46
|
+
: [];
|
|
47
|
+
if (fileList.length > 0) {
|
|
48
|
+
console.log('filtering to files: ', fileList);
|
|
49
|
+
}
|
|
41
50
|
const nextExtra = generateDiff ? '.next' : '';
|
|
42
|
-
const cstFiles = await regenerateTests(nextExtra);
|
|
51
|
+
const cstFiles = await regenerateTests(nextExtra, fileList);
|
|
43
52
|
const allFiles = [];
|
|
44
53
|
if (generateDiff) {
|
|
45
54
|
cstFiles.forEach(file => {
|
package/dist/esm/execute.js
CHANGED
|
@@ -379,6 +379,7 @@ export class ExecutionContext {
|
|
|
379
379
|
this.applyComponentAngleFromWire(component, pinId);
|
|
380
380
|
this.scope.setCurrent(component, pinId);
|
|
381
381
|
this.scope.clearActive();
|
|
382
|
+
this.log('clear active wire/frame (to component)');
|
|
382
383
|
if (addSequence) {
|
|
383
384
|
if (this.scope.sequence.length > 0) {
|
|
384
385
|
const [entryType, , segments] = this.scope.sequence[this.scope.sequence.length - 1];
|
|
@@ -415,6 +416,7 @@ export class ExecutionContext {
|
|
|
415
416
|
this.scope.setNet(component, usePinId, tmpNet);
|
|
416
417
|
}
|
|
417
418
|
this.scope.clearActive();
|
|
419
|
+
this.log('clear active wire/frame (at component)');
|
|
418
420
|
if (addSequence) {
|
|
419
421
|
this.scope.sequence.push([SequenceAction.At,
|
|
420
422
|
component, usePinId]);
|
|
@@ -453,8 +455,12 @@ export class ExecutionContext {
|
|
|
453
455
|
|| blockType === BlockTypes.Parallel
|
|
454
456
|
|| blockType === BlockTypes.Branch) {
|
|
455
457
|
const key = getBlockTypeString(blockType);
|
|
458
|
+
const wireIdBefore = this.scope.currentWireId;
|
|
456
459
|
this.addPoint(`${Delimiter1}${key}.${this.name}.${this.tmpPointId}`, false);
|
|
457
460
|
this.tmpPointId += 1;
|
|
461
|
+
if (wireIdBefore !== -1) {
|
|
462
|
+
this.scope.currentWireId = wireIdBefore;
|
|
463
|
+
}
|
|
458
464
|
}
|
|
459
465
|
this.scope.blockStack.set(this.scope.scopeLevel, {
|
|
460
466
|
start_point: [
|
package/dist/esm/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export * from './parser.js';
|
|
|
15
15
|
export * from './utils.js';
|
|
16
16
|
export * from './visitor.js';
|
|
17
17
|
export * from './sizing.js';
|
|
18
|
+
export * from './errors.js';
|
|
18
19
|
export * from './objects/types.js';
|
|
19
20
|
export * from './builtinMethods.js';
|
|
20
21
|
export * from './validate/SymbolTable.js';
|
|
@@ -4,13 +4,15 @@ import { NodeScriptEnvironment } from "./environment/environment.js";
|
|
|
4
4
|
const mainDir = './__tests__/testData/renderData/';
|
|
5
5
|
const env = new NodeScriptEnvironment();
|
|
6
6
|
NodeScriptEnvironment.setInstance(env);
|
|
7
|
-
async function regenerateTests(extra = "") {
|
|
7
|
+
async function regenerateTests(extra = "", fileList = []) {
|
|
8
8
|
await env.prepareSVGEnvironment();
|
|
9
9
|
const cstFiles = [];
|
|
10
10
|
const files = fs.readdirSync(mainDir);
|
|
11
11
|
files.forEach(file => {
|
|
12
12
|
if (file.endsWith('.cst') && file.startsWith('script')) {
|
|
13
|
-
|
|
13
|
+
if (fileList.length === 0 || fileList.includes(file)) {
|
|
14
|
+
cstFiles.push(file);
|
|
15
|
+
}
|
|
14
16
|
}
|
|
15
17
|
});
|
|
16
18
|
for (let i = 0; i < cstFiles.length; i++) {
|
|
@@ -33,8 +35,15 @@ async function regenerateTests(extra = "") {
|
|
|
33
35
|
(async () => {
|
|
34
36
|
const generateDiff = (process.argv.indexOf('-diff') !== -1);
|
|
35
37
|
console.log('diff flag: ', generateDiff);
|
|
38
|
+
const listIndex = process.argv.indexOf('--list');
|
|
39
|
+
const fileList = listIndex !== -1 && process.argv[listIndex + 1]
|
|
40
|
+
? process.argv[listIndex + 1].split(',').map(f => f.trim())
|
|
41
|
+
: [];
|
|
42
|
+
if (fileList.length > 0) {
|
|
43
|
+
console.log('filtering to files: ', fileList);
|
|
44
|
+
}
|
|
36
45
|
const nextExtra = generateDiff ? '.next' : '';
|
|
37
|
-
const cstFiles = await regenerateTests(nextExtra);
|
|
46
|
+
const cstFiles = await regenerateTests(nextExtra, fileList);
|
|
38
47
|
const allFiles = [];
|
|
39
48
|
if (generateDiff) {
|
|
40
49
|
cstFiles.forEach(file => {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './parser.js';
|
|
|
15
15
|
export * from './utils.js';
|
|
16
16
|
export * from './visitor.js';
|
|
17
17
|
export * from './sizing.js';
|
|
18
|
+
export * from './errors.js';
|
|
18
19
|
export * from './objects/types.js';
|
|
19
20
|
export * from './builtinMethods.js';
|
|
20
21
|
export * from './validate/SymbolTable.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circuitscript",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"description": "Interpreter for the circuitscript language",
|
|
5
5
|
"homepage": "https://circuitscript.net",
|
|
6
6
|
"engines": {
|
|
@@ -24,12 +24,14 @@
|
|
|
24
24
|
"libs"
|
|
25
25
|
],
|
|
26
26
|
"devDependencies": {
|
|
27
|
+
"@resvg/resvg-js": "^2.6.2",
|
|
27
28
|
"@types/big.js": "^6.2.2",
|
|
28
29
|
"@types/crypto-js": "^4.2.2",
|
|
29
30
|
"@types/figlet": "^1.5.8",
|
|
30
31
|
"@types/jest": "~29.5",
|
|
31
32
|
"@types/node": "~18",
|
|
32
33
|
"@types/pdfkit": "^0.13.6",
|
|
34
|
+
"@types/pngjs": "^6.0.5",
|
|
33
35
|
"@types/svg-to-pdfkit": "^0.1.3",
|
|
34
36
|
"@types/svgdom": "^0.1.2",
|
|
35
37
|
"@typescript-eslint/eslint-plugin": "~5.59",
|
|
@@ -39,6 +41,9 @@
|
|
|
39
41
|
"eslint-config-prettier": "~8.8",
|
|
40
42
|
"eslint-plugin-jest": "~27.2",
|
|
41
43
|
"jest": "~29.5",
|
|
44
|
+
"license-check-and-add": "^4.0.5",
|
|
45
|
+
"pixelmatch": "^7.1.0",
|
|
46
|
+
"pngjs": "^7.0.0",
|
|
42
47
|
"prettier": "~2.8",
|
|
43
48
|
"rimraf": "~5.0",
|
|
44
49
|
"source-map-support": "^0.5.21",
|
|
@@ -76,7 +81,9 @@
|
|
|
76
81
|
"changelog": "auto-changelog --handlebars-setup ../changelog/helper.js -p",
|
|
77
82
|
"preversion": "npm run test",
|
|
78
83
|
"version": "npm run changelog && git add CHANGELOG.md",
|
|
79
|
-
"copy-assets": "mkdir -p dist/fonts && mkdir -p dist/libs && cp -r fonts dist/ && cp -r libs dist/"
|
|
84
|
+
"copy-assets": "mkdir -p dist/fonts && mkdir -p dist/libs && cp -r fonts dist/ && cp -r libs dist/",
|
|
85
|
+
"license:check": "license-check-and-add check -f licensecheck.json",
|
|
86
|
+
"license:add": "license-check-and-add add -f licensecheck.json"
|
|
80
87
|
},
|
|
81
88
|
"boilerplate_author": "Jakub Synowiec <jsynowiec@users.noreply.github.com>",
|
|
82
89
|
"license": "MIT",
|