circuitscript 0.0.7 → 0.0.12

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/.gitlab-ci.yml CHANGED
@@ -10,7 +10,8 @@ variables:
10
10
 
11
11
  stages:
12
12
  - prepare
13
- # - verify
13
+ - test_jest
14
+ - test_build
14
15
  - publish
15
16
 
16
17
  # Installs all dependencies.
@@ -26,27 +27,32 @@ install:
26
27
  when: on_success
27
28
  expire_in: 12h
28
29
  script:
29
- - npm config set -- '//registry.npmjs.org/:_authToken' "${NPM_AUTH_TOKEN}"
30
30
  - npm install --no-progress --no-audit --no-fund --verbose
31
- - npm run build:release || true
32
31
  # only:
33
32
  # - merge_requests
34
33
  # - develop
35
34
  # - main
36
35
 
37
- # Lints the codebase.
38
- # lint:
39
- # stage: verify
40
- # interruptible: true
41
- # retry: 1
42
- # dependencies:
43
- # - install
44
- # script:
45
- # - npm run lint
46
- # # only:
47
- # - merge_requests
48
- # - develop
49
- # - main
36
+ test_jest:
37
+ stage: test_jest
38
+ interruptible: true
39
+ retry: 1
40
+ dependencies:
41
+ - install
42
+ script:
43
+ - npm run test
44
+
45
+ test_build:
46
+ stage: test_build
47
+ interruptible: true
48
+ retry: 1
49
+ dependencies:
50
+ - install
51
+ script:
52
+ - npm run build:release || true
53
+ - ls
54
+ - ls build
55
+ - node build/src/main.js
50
56
 
51
57
  # Publishes the package to npm.
52
58
  publish:
@@ -57,7 +63,6 @@ publish:
57
63
  script:
58
64
  - npm config set -- '//registry.npmjs.org/:_authToken' "${NPM_AUTH_TOKEN}"
59
65
  - npm run build:release || true
60
- - ls build/src
61
66
  - npm publish --verbose
62
67
  resource_group: 'deployment-$CI_COMMIT_REF_SLUG'
63
68
  # rules:
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # circuitscript
2
2
 
3
-
3
+ CLI tool for the [circuitscript language](https://circuitscript.net)
@@ -1,20 +1,21 @@
1
- import path from 'path';
2
- import fs from 'fs';
1
+ import { dirname } from 'path';
3
2
 
4
- import CircuitScriptParser from '../src/antlr/CircuitScriptParser';
3
+ import CircuitScriptParser from '../src/antlr/CircuitScriptParser.js';
5
4
 
6
5
  import { CharStream, CommonTokenStream } from 'antlr4';
7
- import { MainVisitor } from '../src/visitor';
8
- import { ComponentPinNet } from '../src/objects/types';
9
- import { CircuitscriptParserErrorListener, parseFileWithVisitor } from '../src/parser';
10
- import { ClassComponent } from '../src/objects/ClassComponent';
11
- import { MainLexer } from '../src/lexer';
6
+ import { MainVisitor } from '../src/visitor.js';
7
+ import { ComponentPinNet } from '../src/objects/types.js';
8
+ import { CircuitscriptParserErrorListener } from '../src/parser.js';
9
+ import { ClassComponent } from '../src/objects/ClassComponent.js';
10
+ import { MainLexer } from '../src/lexer.js';
12
11
 
13
12
 
14
- export async function runScript(script: string): Promise<{visitor: MainVisitor,
15
- hasError: boolean,
16
- componentPinNets:ComponentPinNet[]}> {
17
-
13
+ export async function runScript(script: string): Promise<{
14
+ visitor: MainVisitor,
15
+ hasError: boolean,
16
+ componentPinNets: ComponentPinNet[]
17
+ }> {
18
+
18
19
  const chars = new CharStream(script);
19
20
  const lexer = new MainLexer(chars);
20
21
  const tokens = new CommonTokenStream(lexer);
@@ -25,21 +26,22 @@ export async function runScript(script: string): Promise<{visitor: MainVisitor,
25
26
 
26
27
  const errorListener = new CircuitscriptParserErrorListener();
27
28
  parser.addErrorListener(errorListener);
28
-
29
+
29
30
  const tree = parser.script();
30
31
 
31
32
  const scriptPath = "./examples/helpers.ts";
33
+ const defaultLibsPath = "./libs";
32
34
 
33
35
  const visitor = new MainVisitor(true);
34
36
  visitor.printToConsole = false; // do not clutter the console log
35
37
 
36
- const currentDirectory = path.dirname(scriptPath);
37
- visitor.onImportFile = visitor.createImportFileHandler(currentDirectory);
38
+ const currentDirectory = dirname(scriptPath);
39
+ visitor.onImportFile = visitor.createImportFileHandler(currentDirectory, defaultLibsPath);
38
40
 
39
41
  let hasError = false;
40
42
  try {
41
43
  visitor.visit(tree);
42
- } catch (err){
44
+ } catch (err) {
43
45
  // Error should be internally handled in visitor
44
46
  err.print(script);
45
47
  hasError = true;
@@ -1,4 +1,4 @@
1
- import { runScript } from "./helpers";
1
+ import { runScript } from "./helpers.js";
2
2
 
3
3
  const script1 = `
4
4
  b = 10
@@ -1,8 +1,8 @@
1
- import fs from 'fs';
1
+ import { readFileSync } from 'fs';
2
2
 
3
- import { LayoutEngine } from "../src/layout";
4
- import { generateSVG2 } from "../src/render";
5
- import { runScript } from "./helpers";
3
+ import { LayoutEngine } from "../src/layout.js";
4
+ import { generateSVG2 } from "../src/render.js";
5
+ import { runScript } from "./helpers.js";
6
6
 
7
7
  const mainPath = '__tests__/renderData/';
8
8
 
@@ -13,11 +13,11 @@ describe('Render tests', () => {
13
13
  ['simple function', 'script2.cst'],
14
14
  ['simple frame', 'script3.cst'],
15
15
  ['drawing functions for graphics', 'script4.cst']
16
-
16
+
17
17
  ])('render - %s (%s)', async (title, scriptPath) => {
18
18
 
19
- const script = fs.readFileSync(mainPath + scriptPath, { encoding: 'utf8' });
20
- const {hasError, visitor} = await runScript(script);
19
+ const script = readFileSync(mainPath + scriptPath, { encoding: 'utf8' });
20
+ const { hasError, visitor } = await runScript(script);
21
21
  expect(hasError).toBe(false);
22
22
  visitor.annotateComponents();
23
23
 
@@ -28,7 +28,7 @@ describe('Render tests', () => {
28
28
 
29
29
  const svgOutput = generateSVG2(graph);
30
30
 
31
- const expectedSvgOutput = fs.readFileSync(mainPath + scriptPath + ".svg", { encoding: 'utf8' });
31
+ const expectedSvgOutput = readFileSync(mainPath + scriptPath + ".svg", { encoding: 'utf8' });
32
32
  expect(svgOutput).toBe(expectedSvgOutput);
33
33
  });
34
34
  });
package/build/src/main.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #! /usr/bin/env node
2
2
  import { program } from 'commander';
3
3
  import figlet from 'figlet';
4
- import fs from 'fs';
5
4
  import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { readFileSync, watch, writeFileSync } from 'fs';
6
7
  import { MainVisitor } from './visitor.js';
7
8
  import { prepareSizing } from './sizing.js';
8
9
  import { LayoutEngine } from './layout.js';
@@ -12,9 +13,14 @@ import { parseFileWithVisitor } from './parser.js';
12
13
  import { generateKiCADNetList } from './export.js';
13
14
  import { SimpleStopwatch } from './utils.js';
14
15
  export default async function main() {
16
+ const toolSrcPath = fileURLToPath(import.meta.url);
17
+ const toolDirectory = path.dirname(toolSrcPath) + '/../../';
18
+ const packageJson = JSON.parse(readFileSync(toolDirectory + 'package.json').toString());
19
+ ;
20
+ const { version } = packageJson;
15
21
  program
16
22
  .description('generate graphical output from circuitscript files')
17
- .version('0.0.6')
23
+ .version(version)
18
24
  .option('-i, --input text <input text>', 'Input text directly')
19
25
  .option('-f, --input-file <path>', 'Input file')
20
26
  .option('-o, --output <path>', 'Output path')
@@ -38,10 +44,12 @@ export default async function main() {
38
44
  const dumpData = options.dumpData;
39
45
  const kicadNetlist = options.kicadNetlist;
40
46
  let currentDirectory = options.currentDirectory ?? null;
47
+ const fontsPath = toolDirectory + '/fonts';
48
+ const defaultLibsPath = toolDirectory + '/libs';
41
49
  if (watchFileChanges) {
42
50
  console.log('watching for file changes...');
43
51
  }
44
- await prepareSizing();
52
+ await prepareSizing(fontsPath);
45
53
  let inputFilePath = null;
46
54
  let scriptData;
47
55
  if (options.input) {
@@ -49,13 +57,14 @@ export default async function main() {
49
57
  }
50
58
  else {
51
59
  inputFilePath = options.inputFile;
52
- scriptData = fs.readFileSync(inputFilePath, { encoding: 'utf-8' });
60
+ scriptData = readFileSync(inputFilePath, { encoding: 'utf-8' });
53
61
  if (currentDirectory === null) {
54
62
  currentDirectory = path.dirname(inputFilePath);
55
63
  }
56
64
  }
57
65
  const renderOptions = {
58
66
  currentDirectory,
67
+ defaultLibsPath,
59
68
  dumpNets,
60
69
  dumpData,
61
70
  kicadNetlistPath: kicadNetlist,
@@ -66,9 +75,9 @@ export default async function main() {
66
75
  console.log(output);
67
76
  }
68
77
  if (watchFileChanges) {
69
- fs.watch(inputFilePath, (event, targetFile) => {
78
+ watch(inputFilePath, (event, targetFile) => {
70
79
  if (event === 'change') {
71
- const scriptData = fs.readFileSync(inputFilePath, { encoding: 'utf-8' });
80
+ const scriptData = readFileSync(inputFilePath, { encoding: 'utf-8' });
72
81
  renderScript(scriptData, outputPath, renderOptions);
73
82
  console.log('done');
74
83
  }
@@ -76,9 +85,9 @@ export default async function main() {
76
85
  }
77
86
  }
78
87
  export function renderScript(scriptData, outputPath, options) {
79
- const { currentDirectory = null, dumpNets = false, dumpData = false, kicadNetlistPath = null, showStats = false } = options;
88
+ const { currentDirectory = null, defaultLibsPath, dumpNets = false, dumpData = false, kicadNetlistPath = null, showStats = false } = options;
80
89
  const visitor = new MainVisitor(true);
81
- visitor.onImportFile = visitor.createImportFileHandler(currentDirectory);
90
+ visitor.onImportFile = visitor.createImportFileHandler(currentDirectory, defaultLibsPath);
82
91
  visitor.print('reading file');
83
92
  visitor.print('done reading file');
84
93
  const { tree, parser, hasParseError, hasError, parserTimeTaken, lexerTimeTaken } = parseFileWithVisitor(visitor, scriptData);
@@ -87,8 +96,8 @@ export function renderScript(scriptData, outputPath, options) {
87
96
  if (dumpNets) {
88
97
  console.log(visitor.dumpNets());
89
98
  }
90
- dumpData && fs.writeFileSync('dump/tree.lisp', tree.toStringTree(null, parser));
91
- dumpData && fs.writeFileSync('dump/raw-parser.txt', visitor.logger.dump());
99
+ dumpData && writeFileSync('dump/tree.lisp', tree.toStringTree(null, parser));
100
+ dumpData && writeFileSync('dump/raw-parser.txt', visitor.logger.dump());
92
101
  if (hasError || hasParseError) {
93
102
  console.log('Error while parsing');
94
103
  return;
@@ -96,7 +105,7 @@ export function renderScript(scriptData, outputPath, options) {
96
105
  visitor.annotateComponents();
97
106
  if (kicadNetlistPath) {
98
107
  const kicadNetList = generateKiCADNetList(visitor.getNetList());
99
- fs.writeFileSync(kicadNetlistPath, kicadNetList);
108
+ writeFileSync(kicadNetlistPath, kicadNetList);
100
109
  console.log('Generated KiCad netlist file');
101
110
  }
102
111
  const { sequence, nets } = visitor.getGraph();
@@ -116,7 +125,7 @@ export function renderScript(scriptData, outputPath, options) {
116
125
  }
117
126
  return tmp.join(" | ");
118
127
  });
119
- dumpData && fs.writeFileSync('dump/raw-sequence.txt', tmpSequence.join('\n'));
128
+ dumpData && writeFileSync('dump/raw-sequence.txt', tmpSequence.join('\n'));
120
129
  let svgOutput = null;
121
130
  try {
122
131
  const layoutEngine = new LayoutEngine();
@@ -124,12 +133,12 @@ export function renderScript(scriptData, outputPath, options) {
124
133
  const graph = layoutEngine.runLayout(sequence, nets);
125
134
  layoutEngine.printWarnings();
126
135
  showStats && console.log('Layout took:', layoutTimer.lap());
127
- dumpData && fs.writeFileSync('dump/raw-layout.txt', layoutEngine.logger.dump());
136
+ dumpData && writeFileSync('dump/raw-layout.txt', layoutEngine.logger.dump());
128
137
  const generateSvgTimer = new SimpleStopwatch();
129
138
  svgOutput = generateSVG2(graph);
130
139
  showStats && console.log('Render took:', generateSvgTimer.lap());
131
140
  if (outputPath) {
132
- fs.writeFileSync(outputPath, svgOutput);
141
+ writeFileSync(outputPath, svgOutput);
133
142
  }
134
143
  }
135
144
  catch (err) {
@@ -6,8 +6,8 @@ const supportedFonts = {
6
6
  'Inter': 'Inter-Regular.ttf',
7
7
  'Inter-Bold': 'Inter-Bold.ttf',
8
8
  };
9
- export async function prepareSizing() {
10
- await config.setFontDir('./fonts')
9
+ export async function prepareSizing(fontsPath) {
10
+ await config.setFontDir(fontsPath)
11
11
  .setFontFamilyMappings(supportedFonts)
12
12
  .preloadFonts();
13
13
  }
@@ -1,6 +1,6 @@
1
1
  import { ParseTreeVisitor } from 'antlr4';
2
- import fs from 'fs';
3
- import path from 'path';
2
+ import { readFileSync } from 'fs';
3
+ import { join } from 'path';
4
4
  import { ExecutionContext } from './execute.js';
5
5
  import { ClassComponent } from './objects/ClassComponent.js';
6
6
  import { NumericValue, ParamDefinition, PercentageValue, PinBlankValue, } from './objects/ParamDefinition.js';
@@ -731,23 +731,42 @@ export class MainVisitor extends ParseTreeVisitor {
731
731
  PinTypes.Output,
732
732
  PinTypes.Power,
733
733
  ];
734
- createImportFileHandler(directory) {
734
+ createImportFileHandler(directory, defaultLibsPath) {
735
735
  return (visitor, importPath) => {
736
- const tmpFilePath = path.join(directory, importPath + ".cst");
737
- visitor.print('importing path:', tmpFilePath);
738
- try {
739
- const fileData = fs.readFileSync(tmpFilePath, { encoding: 'utf8' });
736
+ let importResult;
737
+ importResult = this.importLib(visitor, directory, importPath);
738
+ if (!importResult.pathExists && importPath == 'lib') {
739
+ importResult = this.importLib(visitor, defaultLibsPath, importPath);
740
+ }
741
+ return importResult;
742
+ };
743
+ }
744
+ importLib(visitor, directory, filename) {
745
+ const tmpFilePath = join(directory, filename + ".cst");
746
+ visitor.print('importing path:', tmpFilePath);
747
+ let pathExists = false;
748
+ let fileData = null;
749
+ try {
750
+ fileData = readFileSync(tmpFilePath, { encoding: 'utf8' });
751
+ pathExists = true;
752
+ }
753
+ catch (err) {
754
+ pathExists = false;
755
+ }
756
+ try {
757
+ if (pathExists) {
740
758
  visitor.print('done reading imported file data');
741
759
  const { hasError, hasParseError } = parseFileWithVisitor(visitor, fileData);
742
- return { hasError, hasParseError };
760
+ return { hasError, hasParseError, pathExists };
743
761
  }
744
- catch (err) {
745
- console.log('Failed to import file: ', err.message);
746
- }
747
- return {
748
- hasError: true,
749
- hasParseError: true
750
- };
762
+ }
763
+ catch (err) {
764
+ visitor.print('Failed to import file: ', err.message);
765
+ }
766
+ return {
767
+ hasError: true,
768
+ hasParseError: true,
769
+ pathExists,
751
770
  };
752
771
  }
753
772
  parseCreateComponentPins(pinData) {
package/jest.config.js ADDED
@@ -0,0 +1,23 @@
1
+ export default {
2
+ testEnvironment: 'node',
3
+ preset: 'ts-jest/presets/default-esm',
4
+ transform: {
5
+ '^.+\\.m?[tj]s?$': ['ts-jest', {
6
+ useESM: true,
7
+ diagnostics: false
8
+ }],
9
+ },
10
+ moduleNameMapper: {
11
+ '^(\\.{1,2}/.*)\\.(m)?js$': '$1',
12
+ },
13
+ testMatch: [
14
+ "<rootDir>/__tests__/test**.(ts|tsx)",
15
+ ],
16
+ coverageDirectory: 'coverage',
17
+ collectCoverageFrom: [
18
+ 'src/**/*.ts',
19
+ 'src/**/*.mts',
20
+ '!src/**/*.d.ts',
21
+ '!src/**/*.d.mts',
22
+ ],
23
+ };
package/libs/lib.cst ADDED
@@ -0,0 +1,190 @@
1
+ // Circuitscript default lib
2
+
3
+ def net(net_name):
4
+ return create component:
5
+ pins: 1
6
+ display: create graphic:
7
+ hline: -15, 0, 30
8
+ pin: 1, 0, 10, 0, 0
9
+ label: "net_name", 0, -5, net_name, fontSize=10, anchor="middle"
10
+ type: "net"
11
+ params:
12
+ __is_net: 1
13
+ net_name: net_name
14
+ priority: 10
15
+
16
+ def supply(net_name):
17
+ return create component:
18
+ pins: 1
19
+ display: create graphic:
20
+ hline: -15, 0, 30
21
+ pin: 1, 0, 10, 0, 0
22
+ label: "net_name", 0, -5, net_name, fontSize=10, anchor="middle"
23
+ type: "net"
24
+ params:
25
+ __is_net: 1
26
+ net_name: net_name
27
+ priority: 20
28
+
29
+ def label(value):
30
+ return create component:
31
+ pins: 1
32
+ display: create graphic:
33
+ label: "value", 0, -2, fontSize=10, anchor="left"
34
+ pin: 1, 0, 0, 0, 0
35
+ type: "label"
36
+ params:
37
+ __is_net: 1
38
+ net_name: value
39
+ value: value
40
+ priority: 5
41
+
42
+ def res(value):
43
+ width = 40
44
+ height = 20
45
+
46
+ return create component:
47
+ pins: 2
48
+ display: create graphic:
49
+ rect: 0, 0, width, height
50
+ pin: 1, -width/2 - 20, 0, -width / 2, 0
51
+ pin: 2, width/2 + 20, 0, width/2, 0
52
+ label: ("value", 0, 1, value, fontSize=10, anchor="middle", vanchor="middle")
53
+ label: ("refdes", -width/2, -height/2 -5 , "?", fontSize=10, anchor="left")
54
+
55
+ type: "res"
56
+ params:
57
+ value: value
58
+ size: "0402"
59
+ footprint: "Resistor_SMD:R_0402_1005Metric"
60
+
61
+ def cap(value):
62
+ width = 20
63
+ height = 40
64
+
65
+ return create component:
66
+ pins: 2
67
+ display: create graphic:
68
+ hline: -width/2, -3, width
69
+ hline: -width/2, 3, width
70
+ pin: 1, 0, -height/2, 0, -3
71
+ pin: 2, 0, height/2, 0, 3
72
+ label: "refdes", width/2+2, 0, "?", fontSize = 10, anchor="left"
73
+ label: "value", width/2+2, 5, value, fontSize = 10, anchor = "left", vanchor="top"
74
+ type: "cap"
75
+ params:
76
+ value: value
77
+ size: "0402"
78
+ footprint: "Capacitor_SMD:C_0402_1005Metric"
79
+
80
+ def ind(value):
81
+ width = 40
82
+ height = 20
83
+
84
+ return create component:
85
+ pins: 2
86
+ type: "ind"
87
+ display: create graphic:
88
+ arc: -15, 0, 5, 180, 360
89
+ arc: -5, 0, 5, 180, 360
90
+ arc: 5, 0, 5, 180, 360
91
+ arc: 15, 0, 5, 180, 360
92
+ pin: 1, -width/2 - 20, 0, -width / 2, 0
93
+ pin: 2, width/2 + 20, 0, width/2, 0
94
+ label: ("value", 0, 10, value, fontSize=10, anchor="middle", vanchor="middle")
95
+ label: ("refdes", -width/2, -height/2 -5 , "?", fontSize=10, anchor="left")
96
+ params:
97
+ value: value
98
+
99
+ def diode():
100
+ width = 20
101
+ height = 20
102
+
103
+ # Diode is drawn horizontally
104
+ # -|>|-
105
+ return create component:
106
+ pins: 2
107
+ type: "diode"
108
+ display: create graphic:
109
+ path: ("M", width/2, -height/2, "L", width/2, height/2,
110
+ "M", -width/2, -height/2, "L", -width/2, height/2,
111
+ "L", width/2, 0, "L", -width/2, -height/2)
112
+ pin: 1, -width/2-20, 0, -width/2, 0 # anode
113
+ pin: 2, width/2 + 20, 0, width/2, 0 # cathode
114
+ label: "refdes", width/2 + 5, 5, "?", fontSize=10, anchor="left", vanchor="top"
115
+
116
+ def led(color):
117
+ width = 20
118
+ height = 20
119
+
120
+ return create component:
121
+ pins:
122
+ 1: "cathode"
123
+ 2: "anode"
124
+ type: "diode"
125
+ display: create graphic:
126
+ path: ("M", width/2, -height/2, "L", width/2, height/2,
127
+ "M", -width/2, -height/2, "L", -width/2, height/2,
128
+ "L", width/2, 0, "L", -width/2, -height/2)
129
+ path: ("M", 0, 8, "L", 5, 18,
130
+ "M", 3, 8, "L", 8, 18)
131
+ pin: 1, -width/2-20, 0, -width/2, 0 # anode
132
+ pin: 2, width/2 + 20, 0, width/2, 0 # cathode
133
+ label: "refdes", width/2 + 5, 5, "?", fontSize=10, anchor="left", vanchor="top"
134
+ params:
135
+ size: "0603"
136
+ footprint: "LED_SMD:LED_0603_1608Metric_Pad1.05x0.95mm_HandSolder"
137
+
138
+
139
+ def cgnd():
140
+ net_name = "gnd"
141
+ return create component:
142
+ pins: 1
143
+ display: create graphic:
144
+ hline: -15, 0, 30
145
+ hline: -10, 5, 20
146
+ hline: -5, 10, 10
147
+ pin: 1, 0, -10, 0, 0
148
+ label: "net_name", 0, 22, net_name, fontSize=10, anchor="middle"
149
+ type: "net"
150
+ params:
151
+ __is_net: 1
152
+ net_name: net_name
153
+ priority: 100
154
+
155
+ def dgnd():
156
+ height = 10
157
+ width = 20
158
+
159
+ net_name = "GND"
160
+ return create component:
161
+ pins: 1
162
+ display: create graphic:
163
+ path: ("M", -width/2, 0,
164
+ "L", width/2, 0,
165
+ "L", 0, height,
166
+ "Z")
167
+ pin: 1, 0, -10, 0, 0
168
+ label: "net_name", 0, height + 10, net_name, fontSize=10, anchor="middle"
169
+ type: "net"
170
+ params:
171
+ __is_net: 1
172
+ net_name: net_name
173
+ priority: 100
174
+
175
+ def marker_point():
176
+ return create component:
177
+ pins: 1
178
+ display: create graphic:
179
+ hline: -5, 0, 10
180
+ vline: 0, -5, 10
181
+ pin: 1, 0, 0, 0, 0
182
+ type: "net"
183
+
184
+ def arrow_point():
185
+ return create component:
186
+ pins: 1
187
+ display: create graphic:
188
+ path: ("M", 15, -5, "L", 20, 0, "L", 15, 5)
189
+ pin: 1, 0, 0, 20, 0
190
+ type: "net"
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "circuitscript",
3
- "version": "0.0.7",
3
+ "version": "0.0.12",
4
4
  "description": "Interpreter for the circuitscript language",
5
+ "homepage": "https://circuitscript.net",
5
6
  "engines": {
6
7
  "node": ">=16.0"
7
8
  },
@@ -45,27 +46,6 @@
45
46
  "profile-flame": "node --prof-process --preprocess -j isolate*.log | flamebearer",
46
47
  "server": "node server.js"
47
48
  },
48
- "jest": {
49
- "preset": "ts-jest",
50
- "verbose": true,
51
- "testMatch": [
52
- "**/__tests__/test**.ts"
53
- ],
54
- "transform": {
55
- "^.+\\.tsx?$": [
56
- "ts-jest",
57
- {
58
- "diagnostics": false
59
- }
60
- ]
61
- },
62
- "collectCoverageFrom": [
63
- "src/**/*.ts"
64
- ],
65
- "coveragePathIgnorePatterns": [
66
- "src/antlr"
67
- ]
68
- },
69
49
  "boilerplate_author": "Jakub Synowiec <jsynowiec@users.noreply.github.com>",
70
50
  "license": "MIT",
71
51
  "dependencies": {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
+ // @ts-nocheck
1
3
  // Generated from ./src/antlr/CircuitScript.g4 by ANTLR 4.13.1
2
4
  // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols
3
5
  import {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
+ // @ts-nocheck
1
3
  // Generated from ./src/antlr/CircuitScript.g4 by ANTLR 4.13.1
2
4
  // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols
3
5
 
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
+ // @ts-nocheck
1
3
  // Generated from ./src/antlr/CircuitScript.g4 by ANTLR 4.13.1
2
4
 
3
5
  import {ParseTreeVisitor} from 'antlr4';
package/src/main.ts CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  import { program } from 'commander';
4
4
  import figlet from 'figlet';
5
-
6
- import fs from 'fs';
7
5
  import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { readFileSync, watch, writeFileSync } from 'fs';
8
8
 
9
9
  import { MainVisitor } from './visitor.js';
10
10
  import { prepareSizing } from './sizing.js';
@@ -16,10 +16,15 @@ import { generateKiCADNetList } from './export.js';
16
16
  import { SimpleStopwatch } from './utils.js';
17
17
 
18
18
  export default async function main(): Promise<void> {
19
+ const toolSrcPath = fileURLToPath(import.meta.url);
20
+ const toolDirectory = path.dirname(toolSrcPath) + '/../../';
21
+
22
+ const packageJson = JSON.parse(readFileSync(toolDirectory + 'package.json').toString());;
23
+ const {version} = packageJson;
19
24
 
20
25
  program
21
26
  .description('generate graphical output from circuitscript files')
22
- .version('0.0.6')
27
+ .version(version)
23
28
  .option('-i, --input text <input text>', 'Input text directly')
24
29
  .option('-f, --input-file <path>', 'Input file')
25
30
  .option('-o, --output <path>', 'Output path')
@@ -51,11 +56,15 @@ export default async function main(): Promise<void> {
51
56
 
52
57
  let currentDirectory = options.currentDirectory ?? null;
53
58
 
59
+
60
+ const fontsPath = toolDirectory + '/fonts';
61
+ const defaultLibsPath = toolDirectory + '/libs';
62
+
54
63
  if (watchFileChanges) {
55
64
  console.log('watching for file changes...');
56
65
  }
57
66
 
58
- await prepareSizing();
67
+ await prepareSizing(fontsPath);
59
68
 
60
69
  let inputFilePath: string = null;
61
70
 
@@ -64,7 +73,7 @@ export default async function main(): Promise<void> {
64
73
  scriptData = options.input;
65
74
  } else {
66
75
  inputFilePath = options.inputFile; // this should be provided
67
- scriptData = fs.readFileSync(inputFilePath, { encoding: 'utf-8' });
76
+ scriptData = readFileSync(inputFilePath, { encoding: 'utf-8' });
68
77
 
69
78
  if (currentDirectory === null) {
70
79
  currentDirectory = path.dirname(inputFilePath);
@@ -73,6 +82,7 @@ export default async function main(): Promise<void> {
73
82
 
74
83
  const renderOptions = {
75
84
  currentDirectory,
85
+ defaultLibsPath,
76
86
  dumpNets,
77
87
  dumpData,
78
88
  kicadNetlistPath: kicadNetlist,
@@ -87,9 +97,9 @@ export default async function main(): Promise<void> {
87
97
  }
88
98
 
89
99
  if (watchFileChanges) {
90
- fs.watch(inputFilePath, (event, targetFile) => {
100
+ watch(inputFilePath, (event, targetFile) => {
91
101
  if (event === 'change') {
92
- const scriptData = fs.readFileSync(inputFilePath,
102
+ const scriptData = readFileSync(inputFilePath,
93
103
  {encoding: 'utf-8'});
94
104
 
95
105
  renderScript(scriptData, outputPath, renderOptions);
@@ -104,6 +114,7 @@ export function renderScript(scriptData: string, outputPath: string, options): s
104
114
 
105
115
  const {
106
116
  currentDirectory = null,
117
+ defaultLibsPath,
107
118
  dumpNets = false,
108
119
  dumpData = false,
109
120
  kicadNetlistPath = null,
@@ -111,7 +122,7 @@ export function renderScript(scriptData: string, outputPath: string, options): s
111
122
 
112
123
  const visitor = new MainVisitor(true);
113
124
 
114
- visitor.onImportFile = visitor.createImportFileHandler(currentDirectory);
125
+ visitor.onImportFile = visitor.createImportFileHandler(currentDirectory, defaultLibsPath);
115
126
 
116
127
  visitor.print('reading file');
117
128
  visitor.print('done reading file');
@@ -129,8 +140,8 @@ export function renderScript(scriptData: string, outputPath: string, options): s
129
140
  }
130
141
  // console.log(visitor.dumpUniqueNets());
131
142
 
132
- dumpData && fs.writeFileSync('dump/tree.lisp', tree.toStringTree(null, parser));
133
- dumpData && fs.writeFileSync('dump/raw-parser.txt', visitor.logger.dump());
143
+ dumpData && writeFileSync('dump/tree.lisp', tree.toStringTree(null, parser));
144
+ dumpData && writeFileSync('dump/raw-parser.txt', visitor.logger.dump());
134
145
 
135
146
  if (hasError || hasParseError) {
136
147
  console.log('Error while parsing');
@@ -141,7 +152,7 @@ export function renderScript(scriptData: string, outputPath: string, options): s
141
152
 
142
153
  if(kicadNetlistPath){
143
154
  const kicadNetList = generateKiCADNetList(visitor.getNetList());
144
- fs.writeFileSync(kicadNetlistPath, kicadNetList);
155
+ writeFileSync(kicadNetlistPath, kicadNetList);
145
156
  console.log('Generated KiCad netlist file');
146
157
  }
147
158
 
@@ -176,7 +187,7 @@ export function renderScript(scriptData: string, outputPath: string, options): s
176
187
  return tmp.join(" | ");
177
188
  });
178
189
 
179
- dumpData && fs.writeFileSync('dump/raw-sequence.txt', tmpSequence.join('\n'));
190
+ dumpData && writeFileSync('dump/raw-sequence.txt', tmpSequence.join('\n'));
180
191
  let svgOutput: string = null;
181
192
 
182
193
  try {
@@ -189,14 +200,14 @@ export function renderScript(scriptData: string, outputPath: string, options): s
189
200
 
190
201
  showStats && console.log('Layout took:', layoutTimer.lap());
191
202
 
192
- dumpData && fs.writeFileSync('dump/raw-layout.txt', layoutEngine.logger.dump());
203
+ dumpData && writeFileSync('dump/raw-layout.txt', layoutEngine.logger.dump());
193
204
 
194
205
  const generateSvgTimer = new SimpleStopwatch();
195
206
  svgOutput = generateSVG2(graph);
196
207
  showStats && console.log('Render took:', generateSvgTimer.lap());
197
208
 
198
209
  if (outputPath){
199
- fs.writeFileSync(outputPath, svgOutput);
210
+ writeFileSync(outputPath, svgOutput);
200
211
  }
201
212
  } catch (err) {
202
213
  console.log('Failed to render:');
package/src/sizing.ts CHANGED
@@ -10,8 +10,8 @@ const supportedFonts = {
10
10
  'Inter-Bold': 'Inter-Bold.ttf',
11
11
  }
12
12
 
13
- export async function prepareSizing(): Promise<void> {
14
- await config.setFontDir('./fonts')
13
+ export async function prepareSizing(fontsPath): Promise<void> {
14
+ await config.setFontDir(fontsPath)
15
15
  .setFontFamilyMappings(supportedFonts)
16
16
  .preloadFonts()
17
17
  }
package/src/visitor.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ParseTreeVisitor, ParserRuleContext } from 'antlr4';
2
2
 
3
- import fs from 'fs';
4
- import path from 'path';
3
+ import { readFileSync } from 'fs';
4
+ import { join } from 'path';
5
5
 
6
6
  import {
7
7
  Add_component_exprContext,
@@ -1093,31 +1093,60 @@ export class MainVisitor extends ParseTreeVisitor<any> {
1093
1093
  PinTypes.Power,
1094
1094
  ];
1095
1095
 
1096
- createImportFileHandler(directory: string):
1096
+ createImportFileHandler(directory: string, defaultLibsPath: string):
1097
1097
  ((visitor: MainVisitor, importPath: string) =>
1098
- { hasError: boolean, hasParseError: boolean }) {
1098
+ { hasError: boolean, hasParseError: boolean, pathExists: boolean }) {
1099
+
1099
1100
  return (visitor: MainVisitor, importPath: string) => {
1100
1101
  // Check if different files exist first
1101
- const tmpFilePath = path.join(directory, importPath + ".cst");
1102
- visitor.print('importing path:', tmpFilePath);
1102
+ let importResult: {
1103
+ hasError: boolean,
1104
+ hasParseError: boolean,
1105
+ pathExists: boolean,
1106
+ };
1103
1107
 
1104
- try {
1105
- const fileData = fs.readFileSync(tmpFilePath, { encoding: 'utf8' });
1108
+ importResult = this.importLib(visitor, directory, importPath);
1109
+
1110
+ if (!importResult.pathExists && importPath == 'lib') {
1111
+ // Load default path
1112
+ importResult = this.importLib(visitor, defaultLibsPath, importPath);
1113
+ }
1114
+
1115
+ return importResult;
1116
+ }
1117
+ }
1118
+
1119
+ private importLib(visitor: MainVisitor, directory: string, filename: string): {hasError: boolean, hasParseError: boolean, pathExists: boolean} {
1120
+ const tmpFilePath = join(directory, filename + ".cst");
1121
+ visitor.print('importing path:', tmpFilePath);
1122
+ let pathExists = false;
1123
+
1124
+ let fileData: string = null;
1125
+
1126
+ try {
1127
+ fileData = readFileSync(tmpFilePath, { encoding: 'utf8' });
1128
+ pathExists = true;
1129
+ } catch (err) {
1130
+ pathExists = false;
1131
+ }
1132
+
1133
+ try {
1134
+ if (pathExists){
1106
1135
  visitor.print('done reading imported file data');
1107
1136
 
1108
1137
  const { hasError, hasParseError } =
1109
1138
  parseFileWithVisitor(visitor, fileData);
1110
1139
 
1111
- return { hasError, hasParseError }
1112
-
1113
- } catch (err) {
1114
- console.log('Failed to import file: ', err.message);
1140
+ return { hasError, hasParseError, pathExists }
1115
1141
  }
1142
+ } catch (err) {
1143
+ visitor.print('Failed to import file: ', err.message);
1144
+ }
1116
1145
 
1117
- return {
1118
- hasError: true,
1119
- hasParseError: true
1120
- }
1146
+ return {
1147
+ hasError: true,
1148
+ hasParseError: true,
1149
+ pathExists,
1121
1150
  }
1122
1151
  }
1123
1152
 
package/tsconfig.json CHANGED
@@ -17,7 +17,10 @@
17
17
  "noUnusedParameters": true,
18
18
  "noImplicitAny": false,
19
19
  "noImplicitThis": false,
20
- "strictNullChecks": false
20
+ "strictNullChecks": false,
21
+ "resolveJsonModule": true,
22
+ "skipLibCheck": true,
23
+ "esModuleInterop":true,
21
24
  },
22
25
  "include": ["src/**/*", "__tests__/**/*"]
23
26
  }