@vessel-dsp/core 0.6.4 → 0.6.6
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 +10 -2
- package/dist/editor/commands.d.ts +13 -13
- package/dist/editor/commands.d.ts.map +1 -1
- package/dist/editor/commands.js +44 -29
- package/dist/editor/commands.js.map +1 -1
- package/dist/editor/factory.d.ts +1 -1
- package/dist/editor/factory.d.ts.map +1 -1
- package/dist/editor/factory.js +51 -51
- package/dist/editor/factory.js.map +1 -1
- package/dist/editor/history.d.ts +7 -7
- package/dist/editor/history.d.ts.map +1 -1
- package/dist/editor/history.js +20 -12
- package/dist/editor/history.js.map +1 -1
- package/dist/editor/index.d.ts +8 -8
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js +4 -4
- package/dist/editor/index.js.map +1 -1
- package/dist/editor/layout.d.ts +1 -1
- package/dist/editor/layout.d.ts.map +1 -1
- package/dist/editor/layout.js +11 -6
- package/dist/editor/layout.js.map +1 -1
- package/dist/formats/circuit-json/serializer.d.ts +15 -15
- package/dist/formats/circuit-json/serializer.d.ts.map +1 -1
- package/dist/formats/circuit-json/serializer.js +486 -394
- package/dist/formats/circuit-json/serializer.js.map +1 -1
- package/dist/formats/document.d.ts +6 -6
- package/dist/formats/document.d.ts.map +1 -1
- package/dist/formats/document.js +112 -92
- package/dist/formats/document.js.map +1 -1
- package/dist/formats/interchange/parser.d.ts +1 -1
- package/dist/formats/interchange/parser.d.ts.map +1 -1
- package/dist/formats/interchange/parser.js +463 -286
- package/dist/formats/interchange/parser.js.map +1 -1
- package/dist/formats/interchange/serializer.d.ts +1 -1
- package/dist/formats/interchange/serializer.d.ts.map +1 -1
- package/dist/formats/interchange/serializer.js +41 -28
- package/dist/formats/interchange/serializer.js.map +1 -1
- package/dist/formats/ltspice/catalog.d.ts +1 -1
- package/dist/formats/ltspice/catalog.d.ts.map +1 -1
- package/dist/formats/ltspice/catalog.js +150 -48
- package/dist/formats/ltspice/catalog.js.map +1 -1
- package/dist/formats/ltspice/encoding.js +12 -40
- package/dist/formats/ltspice/encoding.js.map +1 -1
- package/dist/formats/ltspice/parser.d.ts +1 -1
- package/dist/formats/ltspice/parser.d.ts.map +1 -1
- package/dist/formats/ltspice/parser.js +122 -75
- package/dist/formats/ltspice/parser.js.map +1 -1
- package/dist/formats/ltspice/serializer.d.ts +1 -1
- package/dist/formats/ltspice/serializer.d.ts.map +1 -1
- package/dist/formats/ltspice/serializer.js +69 -47
- package/dist/formats/ltspice/serializer.js.map +1 -1
- package/dist/formats/schx/catalog.d.ts +1 -1
- package/dist/formats/schx/catalog.d.ts.map +1 -1
- package/dist/formats/schx/catalog.js +499 -254
- package/dist/formats/schx/catalog.js.map +1 -1
- package/dist/formats/schx/parser.d.ts +1 -1
- package/dist/formats/schx/parser.d.ts.map +1 -1
- package/dist/formats/schx/parser.js +40 -38
- package/dist/formats/schx/parser.js.map +1 -1
- package/dist/formats/schx/runtime-descriptors.d.ts +1 -1
- package/dist/formats/schx/runtime-descriptors.d.ts.map +1 -1
- package/dist/formats/schx/runtime-descriptors.js +239 -201
- package/dist/formats/schx/runtime-descriptors.js.map +1 -1
- package/dist/formats/schx/serializer.d.ts +2 -2
- package/dist/formats/schx/serializer.d.ts.map +1 -1
- package/dist/formats/schx/serializer.js +106 -106
- package/dist/formats/schx/serializer.js.map +1 -1
- package/dist/formats/schx/transforms.d.ts +1 -1
- package/dist/formats/schx/transforms.d.ts.map +1 -1
- package/dist/formats/schx/transforms.js +16 -8
- package/dist/formats/schx/transforms.js.map +1 -1
- package/dist/formats/spice/parser.d.ts +1 -1
- package/dist/formats/spice/parser.d.ts.map +1 -1
- package/dist/formats/spice/parser.js +105 -56
- package/dist/formats/spice/parser.js.map +1 -1
- package/dist/formats/spice/serializer.d.ts +1 -1
- package/dist/formats/spice/serializer.js +14 -12
- package/dist/formats/spice/serializer.js.map +1 -1
- package/dist/index.d.ts +47 -46
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -31
- package/dist/index.js.map +1 -1
- package/dist/model/connectivity.d.ts +1 -1
- package/dist/model/connectivity.d.ts.map +1 -1
- package/dist/model/connectivity.js +22 -7
- package/dist/model/connectivity.js.map +1 -1
- package/dist/model/netlist.d.ts +3 -3
- package/dist/model/netlist.d.ts.map +1 -1
- package/dist/model/netlist.js +117 -100
- package/dist/model/netlist.js.map +1 -1
- package/dist/model/properties.d.ts +1 -1
- package/dist/model/properties.d.ts.map +1 -1
- package/dist/model/properties.js +16 -16
- package/dist/model/properties.js.map +1 -1
- package/dist/model/quantity.d.ts +1 -1
- package/dist/model/quantity.d.ts.map +1 -1
- package/dist/model/quantity.js +35 -35
- package/dist/model/quantity.js.map +1 -1
- package/dist/model/types.d.ts +61 -33
- package/dist/model/types.d.ts.map +1 -1
- package/dist/model/types.js +1 -1
- package/dist/model/types.js.map +1 -1
- package/dist/model/validation.d.ts +5 -5
- package/dist/model/validation.d.ts.map +1 -1
- package/dist/model/validation.js +668 -331
- package/dist/model/validation.js.map +1 -1
- package/dist/model/wires.d.ts +1 -1
- package/dist/model/wires.d.ts.map +1 -1
- package/dist/model/wires.js +4 -1
- package/dist/model/wires.js.map +1 -1
- package/dist/panel/extract.d.ts +2 -2
- package/dist/panel/extract.d.ts.map +1 -1
- package/dist/panel/extract.js +327 -225
- package/dist/panel/extract.js.map +1 -1
- package/dist/panel/index.d.ts +7 -7
- package/dist/panel/index.d.ts.map +1 -1
- package/dist/panel/index.js +5 -5
- package/dist/panel/index.js.map +1 -1
- package/dist/panel/knobs.d.ts +4 -4
- package/dist/panel/knobs.d.ts.map +1 -1
- package/dist/panel/knobs.js +1 -1
- package/dist/panel/knobs.js.map +1 -1
- package/dist/panel/placement.d.ts +1 -1
- package/dist/panel/placement.d.ts.map +1 -1
- package/dist/panel/placement.js +11 -9
- package/dist/panel/placement.js.map +1 -1
- package/dist/panel/protocol.d.ts +1 -1
- package/dist/panel/protocol.d.ts.map +1 -1
- package/dist/panel/protocol.js +32 -23
- package/dist/panel/protocol.js.map +1 -1
- package/dist/panel/types.d.ts +18 -18
- package/dist/panel/types.d.ts.map +1 -1
- package/dist/panel/types.js.map +1 -1
- package/dist/preview/bounds.d.ts +1 -1
- package/dist/preview/bounds.d.ts.map +1 -1
- package/dist/preview/bounds.js +3 -3
- package/dist/preview/bounds.js.map +1 -1
- package/dist/preview/box-layout.d.ts +2 -2
- package/dist/preview/box-layout.js.map +1 -1
- package/dist/preview/colors.d.ts +1 -1
- package/dist/preview/colors.js +35 -35
- package/dist/preview/colors.js.map +1 -1
- package/dist/preview/hanging.d.ts +1 -1
- package/dist/preview/hanging.d.ts.map +1 -1
- package/dist/preview/hanging.js +4 -1
- package/dist/preview/hanging.js.map +1 -1
- package/dist/preview/junctions.d.ts +1 -1
- package/dist/preview/junctions.d.ts.map +1 -1
- package/dist/preview/junctions.js.map +1 -1
- package/dist/preview/label-layout.d.ts.map +1 -1
- package/dist/preview/label-layout.js +4 -4
- package/dist/preview/label-layout.js.map +1 -1
- package/dist/preview/ports.d.ts +1 -1
- package/dist/preview/ports.d.ts.map +1 -1
- package/dist/preview/ports.js +2 -1
- package/dist/preview/ports.js.map +1 -1
- package/dist/preview/renderable-wires.d.ts +1 -1
- package/dist/preview/renderable-wires.d.ts.map +1 -1
- package/dist/preview/renderable-wires.js +3 -1
- package/dist/preview/renderable-wires.js.map +1 -1
- package/dist/preview/routing.d.ts +1 -1
- package/dist/preview/routing.js +1 -1
- package/dist/preview/routing.js.map +1 -1
- package/dist/preview/snap.d.ts +1 -1
- package/dist/preview/snap.d.ts.map +1 -1
- package/dist/preview/snap.js +11 -3
- package/dist/preview/snap.js.map +1 -1
- package/dist/preview/symbols/svg-content.d.ts.map +1 -1
- package/dist/preview/symbols/svg-content.js +200 -50
- package/dist/preview/symbols/svg-content.js.map +1 -1
- package/dist/preview/symbols.d.ts +2 -2
- package/dist/preview/symbols.d.ts.map +1 -1
- package/dist/preview/symbols.js +100 -97
- package/dist/preview/symbols.js.map +1 -1
- package/dist/preview/wire-chains.d.ts +1 -1
- package/dist/preview/wire-chains.d.ts.map +1 -1
- package/dist/preview/wire-chains.js.map +1 -1
- package/dist/profiles.d.ts +600 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +118 -0
- package/dist/profiles.js.map +1 -0
- package/package.json +54 -54
|
@@ -1,54 +1,51 @@
|
|
|
1
|
-
import { any_circuit_element, } from
|
|
2
|
-
import { getPinNode, resolveConnectivity } from
|
|
3
|
-
import { propertyQuantityValue, propertyStringValue } from
|
|
4
|
-
import { parseQuantity } from
|
|
1
|
+
import { any_circuit_element, } from "circuit-json";
|
|
2
|
+
import { getPinNode, resolveConnectivity, } from "../../model/connectivity.js";
|
|
3
|
+
import { propertyQuantityValue, propertyStringValue, } from "../../model/properties.js";
|
|
4
|
+
import { parseQuantity } from "../../model/quantity.js";
|
|
5
5
|
const VALUE_PROPERTY_NAMES = {
|
|
6
|
-
resistance: [
|
|
7
|
-
capacitance: [
|
|
8
|
-
inductance: [
|
|
9
|
-
voltage: [
|
|
10
|
-
current: [
|
|
6
|
+
resistance: ["R", "Resistance", "resistance", "value", "Value"],
|
|
7
|
+
capacitance: ["C", "Capacitance", "capacitance", "value", "Value"],
|
|
8
|
+
inductance: ["L", "Inductance", "inductance", "value", "Value"],
|
|
9
|
+
voltage: ["V", "Voltage", "voltage", "value", "Value"],
|
|
10
|
+
current: ["I", "Current", "current", "value", "Value"],
|
|
11
11
|
};
|
|
12
12
|
const MODEL_PROPERTY_NAMES = [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
"manufacturerPartNumber",
|
|
14
|
+
"ManufacturerPartNumber",
|
|
15
|
+
"manufacturer_part_number",
|
|
16
|
+
"partNumber",
|
|
17
|
+
"PartNumber",
|
|
18
|
+
"model",
|
|
19
|
+
"Model",
|
|
20
|
+
"modelName",
|
|
21
|
+
"ModelName",
|
|
22
22
|
];
|
|
23
23
|
const DIRECT_EXPORT_KINDS = new Set([
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
24
|
+
"resistor",
|
|
25
|
+
"variable-resistor",
|
|
26
|
+
"capacitor",
|
|
27
|
+
"inductor",
|
|
28
|
+
"diode",
|
|
29
|
+
"led",
|
|
30
|
+
"bjt",
|
|
31
|
+
"jfet",
|
|
32
|
+
"mosfet",
|
|
33
|
+
"opamp",
|
|
34
|
+
"potentiometer",
|
|
35
|
+
"switch",
|
|
36
|
+
"voltage-source",
|
|
37
|
+
"current-source",
|
|
38
|
+
"battery",
|
|
39
|
+
"ground",
|
|
40
|
+
"rail",
|
|
41
|
+
"jack",
|
|
42
|
+
"port",
|
|
43
|
+
"ic",
|
|
44
44
|
]);
|
|
45
|
-
const SOURCE_ONLY_NET_NAME_KINDS = new Set([
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const VESSEL_CAN_CAP_SOURCE_GROUP_PREFIX = 'source_group:vessel-dsp-can-cap:';
|
|
50
|
-
const VESSEL_DSP_PROPERTY_JSON_PREFIX = 'vessel-dsp-property-json:';
|
|
51
|
-
const VESSEL_DSP_PROPERTY_SIDECAR_ID_PREFIX = 'vessel_dsp_property:';
|
|
45
|
+
const SOURCE_ONLY_NET_NAME_KINDS = new Set(["label", "named-wire"]);
|
|
46
|
+
const VESSEL_CAN_CAP_SOURCE_GROUP_PREFIX = "source_group:vessel-dsp-can-cap:";
|
|
47
|
+
const VESSEL_DSP_PROPERTY_JSON_PREFIX = "vessel-dsp-property-json:";
|
|
48
|
+
const VESSEL_DSP_PROPERTY_SIDECAR_ID_PREFIX = "vessel_dsp_property:";
|
|
52
49
|
const TSCIRCUIT_SCHEMATIC_COORD_SCALE = 0.02;
|
|
53
50
|
const DEFAULT_SCHEMATIC_COMPONENT_SIZE = { width: 1.2, height: 0.8 };
|
|
54
51
|
export function serializeCircuitJsonDocument(doc, _options = {}) {
|
|
@@ -84,9 +81,20 @@ export function serializeCircuitJsonDocument(doc, _options = {}) {
|
|
|
84
81
|
const traces = sourceTraceElements(connectivity, names, sourcePortIdsByNode, warnings);
|
|
85
82
|
warnings.push(...sourceOnlyWarnings(doc, exportedComponentIds));
|
|
86
83
|
const sidecars = sourcePropertySidecarElements(doc, exportedComponentIds);
|
|
87
|
-
const sourceElements = [
|
|
84
|
+
const sourceElements = [
|
|
85
|
+
...sourceProjectMetadataElements(doc),
|
|
86
|
+
...nets,
|
|
87
|
+
...groups,
|
|
88
|
+
...components,
|
|
89
|
+
...ports,
|
|
90
|
+
...traces,
|
|
91
|
+
...sidecars,
|
|
92
|
+
];
|
|
88
93
|
return {
|
|
89
|
-
elements: normalizeCircuitJsonElements([
|
|
94
|
+
elements: normalizeCircuitJsonElements([
|
|
95
|
+
...sourceElements,
|
|
96
|
+
...schematicElements(doc, traces),
|
|
97
|
+
]),
|
|
90
98
|
warnings,
|
|
91
99
|
};
|
|
92
100
|
}
|
|
@@ -94,10 +102,12 @@ export function validateCircuitJsonDocument(source) {
|
|
|
94
102
|
if (!Array.isArray(source)) {
|
|
95
103
|
return {
|
|
96
104
|
valid: false,
|
|
97
|
-
errors: [
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
errors: [
|
|
106
|
+
{
|
|
107
|
+
code: "circuit-json-schema-invalid",
|
|
108
|
+
message: "Circuit JSON document must be an array of elements",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
101
111
|
};
|
|
102
112
|
}
|
|
103
113
|
const elements = [];
|
|
@@ -106,7 +116,7 @@ export function validateCircuitJsonDocument(source) {
|
|
|
106
116
|
const shallowIssue = shallowSchemaIssue(element);
|
|
107
117
|
if (shallowIssue !== null) {
|
|
108
118
|
errors.push({
|
|
109
|
-
code:
|
|
119
|
+
code: "circuit-json-schema-invalid",
|
|
110
120
|
message: shallowIssue,
|
|
111
121
|
path: `[${index}]`,
|
|
112
122
|
});
|
|
@@ -118,7 +128,7 @@ export function validateCircuitJsonDocument(source) {
|
|
|
118
128
|
continue;
|
|
119
129
|
}
|
|
120
130
|
errors.push({
|
|
121
|
-
code:
|
|
131
|
+
code: "circuit-json-schema-invalid",
|
|
122
132
|
message: summarizeSchemaIssues(result.error.issues),
|
|
123
133
|
path: `[${index}]`,
|
|
124
134
|
});
|
|
@@ -131,7 +141,9 @@ export function validateCircuitJsonDocument(source) {
|
|
|
131
141
|
export function parseCircuitJsonDocument(source, options = {}) {
|
|
132
142
|
const result = validateCircuitJsonDocument(source);
|
|
133
143
|
if (!result.valid) {
|
|
134
|
-
throw new Error(result.errors
|
|
144
|
+
throw new Error(result.errors
|
|
145
|
+
.map((error) => `${error.path ?? "<root>"}: ${error.message}`)
|
|
146
|
+
.join("; "));
|
|
135
147
|
}
|
|
136
148
|
const sourceComponents = new Map();
|
|
137
149
|
const sourcePorts = new Map();
|
|
@@ -146,34 +158,37 @@ export function parseCircuitJsonDocument(source, options = {}) {
|
|
|
146
158
|
let metadataName = null;
|
|
147
159
|
for (const element of result.elements) {
|
|
148
160
|
const record = checkedRecord(element);
|
|
149
|
-
const type = stringField(record,
|
|
161
|
+
const type = stringField(record, "type");
|
|
150
162
|
switch (type) {
|
|
151
|
-
case
|
|
152
|
-
const sourceComponentId = requiredStringField(record,
|
|
163
|
+
case "source_component": {
|
|
164
|
+
const sourceComponentId = requiredStringField(record, "source_component_id");
|
|
153
165
|
sourceComponents.set(sourceComponentId, {
|
|
154
166
|
sourceComponentId,
|
|
155
|
-
componentId: stripKnownPrefix(sourceComponentId,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
167
|
+
componentId: stripKnownPrefix(sourceComponentId, "source_component:") ??
|
|
168
|
+
sanitizeId(stringField(record, "name") ?? sourceComponentId),
|
|
169
|
+
name: stringField(record, "name") ??
|
|
170
|
+
stripKnownPrefix(sourceComponentId, "source_component:") ??
|
|
171
|
+
sourceComponentId,
|
|
172
|
+
ftype: stringField(record, "ftype"),
|
|
173
|
+
sourceGroupId: stringField(record, "source_group_id"),
|
|
159
174
|
record,
|
|
160
175
|
});
|
|
161
176
|
break;
|
|
162
177
|
}
|
|
163
|
-
case
|
|
164
|
-
const sourceGroupId = requiredStringField(record,
|
|
178
|
+
case "source_group": {
|
|
179
|
+
const sourceGroupId = requiredStringField(record, "source_group_id");
|
|
165
180
|
sourceGroups.set(sourceGroupId, {
|
|
166
181
|
sourceGroupId,
|
|
167
|
-
name: stringField(record,
|
|
182
|
+
name: stringField(record, "name"),
|
|
168
183
|
});
|
|
169
184
|
break;
|
|
170
185
|
}
|
|
171
|
-
case
|
|
186
|
+
case "source_property_ignored_warning": {
|
|
172
187
|
const sidecar = vesselDspPropertySidecar(record);
|
|
173
188
|
if (sidecar === null) {
|
|
174
189
|
warnings.push({
|
|
175
|
-
code:
|
|
176
|
-
message: `Circuit JSON source property "${stringField(record,
|
|
190
|
+
code: "circuit-json-source-property-ignored",
|
|
191
|
+
message: `Circuit JSON source property "${stringField(record, "property_name") ?? ""}" was ignored`,
|
|
177
192
|
});
|
|
178
193
|
break;
|
|
179
194
|
}
|
|
@@ -186,54 +201,58 @@ export function parseCircuitJsonDocument(source, options = {}) {
|
|
|
186
201
|
}
|
|
187
202
|
break;
|
|
188
203
|
}
|
|
189
|
-
case
|
|
190
|
-
const sourcePortId = requiredStringField(record,
|
|
191
|
-
const componentSourceId = requiredStringField(record,
|
|
204
|
+
case "source_port": {
|
|
205
|
+
const sourcePortId = requiredStringField(record, "source_port_id");
|
|
206
|
+
const componentSourceId = requiredStringField(record, "source_component_id");
|
|
192
207
|
sourcePorts.set(sourcePortId, {
|
|
193
208
|
sourcePortId,
|
|
194
209
|
componentSourceId,
|
|
195
|
-
terminalName: stringField(record,
|
|
210
|
+
terminalName: stringField(record, "name") ??
|
|
211
|
+
terminalNameFromSourcePortId(sourcePortId),
|
|
196
212
|
record,
|
|
197
213
|
});
|
|
198
214
|
break;
|
|
199
215
|
}
|
|
200
|
-
case
|
|
216
|
+
case "source_trace":
|
|
201
217
|
sourceTraces.push(record);
|
|
202
218
|
break;
|
|
203
|
-
case
|
|
204
|
-
sourceNets.set(requiredStringField(record,
|
|
219
|
+
case "source_net": {
|
|
220
|
+
sourceNets.set(requiredStringField(record, "source_net_id"), record);
|
|
205
221
|
break;
|
|
206
222
|
}
|
|
207
|
-
case
|
|
208
|
-
metadataName = stringField(record,
|
|
223
|
+
case "source_project_metadata":
|
|
224
|
+
metadataName = stringField(record, "name");
|
|
209
225
|
break;
|
|
210
|
-
case
|
|
211
|
-
const sourceComponentId = stringField(record,
|
|
212
|
-
const center = pointField(record,
|
|
226
|
+
case "schematic_component": {
|
|
227
|
+
const sourceComponentId = stringField(record, "source_component_id");
|
|
228
|
+
const center = pointField(record, "center");
|
|
213
229
|
if (sourceComponentId !== null && center !== null) {
|
|
214
|
-
schematicComponents.set(sourceComponentId, {
|
|
230
|
+
schematicComponents.set(sourceComponentId, {
|
|
231
|
+
sourceComponentId,
|
|
232
|
+
center,
|
|
233
|
+
});
|
|
215
234
|
}
|
|
216
235
|
break;
|
|
217
236
|
}
|
|
218
|
-
case
|
|
219
|
-
const sourcePortId = requiredStringField(record,
|
|
220
|
-
const center = pointField(record,
|
|
237
|
+
case "schematic_port": {
|
|
238
|
+
const sourcePortId = requiredStringField(record, "source_port_id");
|
|
239
|
+
const center = pointField(record, "center");
|
|
221
240
|
if (center !== null) {
|
|
222
241
|
schematicPorts.set(sourcePortId, { sourcePortId, center });
|
|
223
242
|
}
|
|
224
243
|
break;
|
|
225
244
|
}
|
|
226
|
-
case
|
|
227
|
-
const text = stringField(record,
|
|
228
|
-
if (text?.startsWith(
|
|
245
|
+
case "schematic_text": {
|
|
246
|
+
const text = stringField(record, "text");
|
|
247
|
+
if (text?.startsWith("!") === true) {
|
|
229
248
|
directives.push(text.slice(1).trim());
|
|
230
249
|
}
|
|
231
250
|
break;
|
|
232
251
|
}
|
|
233
252
|
default:
|
|
234
|
-
if (type !== null && !type.startsWith(
|
|
253
|
+
if (type !== null && !type.startsWith("schematic_")) {
|
|
235
254
|
warnings.push({
|
|
236
|
-
code:
|
|
255
|
+
code: "circuit-json-element-unsupported",
|
|
237
256
|
message: `Circuit JSON element type "${type}" is not represented in CircuitDocument`,
|
|
238
257
|
});
|
|
239
258
|
}
|
|
@@ -244,8 +263,8 @@ export function parseCircuitJsonDocument(source, options = {}) {
|
|
|
244
263
|
const hasSchematicGeometry = schematicComponents.size > 0 || schematicPorts.size > 0;
|
|
245
264
|
if (!hasSchematicGeometry && sourceComponents.size > 0) {
|
|
246
265
|
warnings.push({
|
|
247
|
-
code:
|
|
248
|
-
message:
|
|
266
|
+
code: "circuit-json-layout-synthesized",
|
|
267
|
+
message: "Circuit JSON source elements did not include schematic geometry; generated deterministic component and terminal positions",
|
|
249
268
|
});
|
|
250
269
|
}
|
|
251
270
|
const componentBuilds = Array.from(sourceComponents.values()).map((sourceComponent, index) => {
|
|
@@ -259,39 +278,42 @@ export function parseCircuitJsonDocument(source, options = {}) {
|
|
|
259
278
|
const netWarnings = warningsForUnconnectedNets(sourceNets, sourceTraces);
|
|
260
279
|
return {
|
|
261
280
|
metadata: {
|
|
262
|
-
name: metadataName ??
|
|
263
|
-
|
|
264
|
-
|
|
281
|
+
name: metadataName ??
|
|
282
|
+
filenameWithoutCircuitJsonExtension(options.filename ?? "Circuit JSON Import"),
|
|
283
|
+
description: "",
|
|
284
|
+
partNumber: "",
|
|
265
285
|
},
|
|
266
286
|
source: {
|
|
267
|
-
format:
|
|
287
|
+
format: "circuit-json",
|
|
268
288
|
...(options.filename !== undefined ? { filename: options.filename } : {}),
|
|
269
289
|
},
|
|
270
290
|
components,
|
|
271
291
|
wires,
|
|
272
292
|
directives,
|
|
273
293
|
warnings: [...warnings, ...netWarnings],
|
|
274
|
-
rawAttributes: { format:
|
|
294
|
+
rawAttributes: { format: "circuit-json" },
|
|
275
295
|
};
|
|
276
296
|
}
|
|
277
297
|
function sourceProjectMetadataElements(doc) {
|
|
278
298
|
if (doc.metadata.name.trim().length === 0) {
|
|
279
299
|
return [];
|
|
280
300
|
}
|
|
281
|
-
return [
|
|
282
|
-
|
|
301
|
+
return [
|
|
302
|
+
{
|
|
303
|
+
type: "source_project_metadata",
|
|
283
304
|
name: doc.metadata.name,
|
|
284
|
-
software_used_string:
|
|
285
|
-
}
|
|
305
|
+
software_used_string: "@vessel-dsp/core",
|
|
306
|
+
},
|
|
307
|
+
];
|
|
286
308
|
}
|
|
287
309
|
function sourceNetElements(connectivity, names, powerNodes) {
|
|
288
310
|
const elements = [];
|
|
289
311
|
for (let nodeId = 0; nodeId < connectivity.nodeCount; nodeId += 1) {
|
|
290
312
|
const isGround = connectivity.groundNodeId === nodeId;
|
|
291
313
|
const isPower = powerNodes.has(nodeId);
|
|
292
|
-
const name = names.get(nodeId) ?? (isGround ?
|
|
314
|
+
const name = names.get(nodeId) ?? (isGround ? "GND" : `N${nodeId}`);
|
|
293
315
|
elements.push({
|
|
294
|
-
type:
|
|
316
|
+
type: "source_net",
|
|
295
317
|
source_net_id: sourceNetId(nodeId),
|
|
296
318
|
name,
|
|
297
319
|
member_source_group_ids: [],
|
|
@@ -309,9 +331,12 @@ function sourceGroupElements(doc) {
|
|
|
309
331
|
if (groupId === null || byGroupId.has(groupId)) {
|
|
310
332
|
continue;
|
|
311
333
|
}
|
|
312
|
-
const packageName = firstStringProperty(component, [
|
|
334
|
+
const packageName = firstStringProperty(component, [
|
|
335
|
+
"CanCapPackageName",
|
|
336
|
+
"PackageName",
|
|
337
|
+
]);
|
|
313
338
|
byGroupId.set(groupId, {
|
|
314
|
-
type:
|
|
339
|
+
type: "source_group",
|
|
315
340
|
source_group_id: canCapSourceGroupId(groupId),
|
|
316
341
|
show_as_schematic_box: true,
|
|
317
342
|
name: packageName ?? groupId,
|
|
@@ -320,8 +345,8 @@ function sourceGroupElements(doc) {
|
|
|
320
345
|
return Array.from(byGroupId.values());
|
|
321
346
|
}
|
|
322
347
|
function sourceComponentElement(component, warnings) {
|
|
323
|
-
if (component.kind ===
|
|
324
|
-
warnings.push(`${component.id} (unsupported): unsupported source type ${component.sourceTypeName ??
|
|
348
|
+
if (component.kind === "unsupported") {
|
|
349
|
+
warnings.push(`${component.id} (unsupported): unsupported source type ${component.sourceTypeName ?? "unknown"} skipped from Circuit JSON export`);
|
|
325
350
|
return null;
|
|
326
351
|
}
|
|
327
352
|
if (SOURCE_ONLY_NET_NAME_KINDS.has(component.kind)) {
|
|
@@ -334,171 +359,193 @@ function sourceComponentElement(component, warnings) {
|
|
|
334
359
|
const base = sourceComponentBase(component);
|
|
335
360
|
const manufacturerPartNumber = firstStringProperty(component, MODEL_PROPERTY_NAMES);
|
|
336
361
|
switch (component.kind) {
|
|
337
|
-
case
|
|
338
|
-
case
|
|
339
|
-
const resistance = quantity(component,
|
|
362
|
+
case "resistor":
|
|
363
|
+
case "variable-resistor": {
|
|
364
|
+
const resistance = quantity(component, "resistance");
|
|
340
365
|
if (resistance === null) {
|
|
341
|
-
return missingQuantityComponent(component,
|
|
366
|
+
return missingQuantityComponent(component, "resistance", warnings, manufacturerPartNumber);
|
|
342
367
|
}
|
|
343
368
|
return {
|
|
344
369
|
...base,
|
|
345
|
-
ftype:
|
|
346
|
-
...(manufacturerPartNumber !== null
|
|
370
|
+
ftype: "simple_resistor",
|
|
371
|
+
...(manufacturerPartNumber !== null
|
|
372
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
373
|
+
: {}),
|
|
347
374
|
resistance: resistance.value.value,
|
|
348
375
|
display_resistance: resistance.value.raw,
|
|
349
376
|
display_value: resistance.value.raw,
|
|
350
377
|
};
|
|
351
378
|
}
|
|
352
|
-
case
|
|
353
|
-
const capacitance = quantity(component,
|
|
379
|
+
case "capacitor": {
|
|
380
|
+
const capacitance = quantity(component, "capacitance");
|
|
354
381
|
if (capacitance === null) {
|
|
355
|
-
return missingQuantityComponent(component,
|
|
382
|
+
return missingQuantityComponent(component, "capacitance", warnings, manufacturerPartNumber);
|
|
356
383
|
}
|
|
357
384
|
return {
|
|
358
385
|
...base,
|
|
359
|
-
ftype:
|
|
360
|
-
...(manufacturerPartNumber !== null
|
|
386
|
+
ftype: "simple_capacitor",
|
|
387
|
+
...(manufacturerPartNumber !== null
|
|
388
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
389
|
+
: {}),
|
|
361
390
|
capacitance: capacitance.value.value,
|
|
362
391
|
display_capacitance: capacitance.value.raw,
|
|
363
392
|
display_value: capacitance.value.raw,
|
|
364
393
|
};
|
|
365
394
|
}
|
|
366
|
-
case
|
|
367
|
-
const inductance = quantity(component,
|
|
395
|
+
case "inductor": {
|
|
396
|
+
const inductance = quantity(component, "inductance");
|
|
368
397
|
if (inductance === null) {
|
|
369
|
-
return missingQuantityComponent(component,
|
|
398
|
+
return missingQuantityComponent(component, "inductance", warnings, manufacturerPartNumber);
|
|
370
399
|
}
|
|
371
400
|
return {
|
|
372
401
|
...base,
|
|
373
|
-
ftype:
|
|
374
|
-
...(manufacturerPartNumber !== null
|
|
402
|
+
ftype: "simple_inductor",
|
|
403
|
+
...(manufacturerPartNumber !== null
|
|
404
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
405
|
+
: {}),
|
|
375
406
|
inductance: inductance.value.value,
|
|
376
407
|
display_inductance: inductance.value.raw,
|
|
377
408
|
display_value: inductance.value.raw,
|
|
378
409
|
};
|
|
379
410
|
}
|
|
380
|
-
case
|
|
411
|
+
case "diode":
|
|
381
412
|
return {
|
|
382
413
|
...base,
|
|
383
|
-
ftype:
|
|
384
|
-
...(manufacturerPartNumber !== null
|
|
414
|
+
ftype: "simple_diode",
|
|
415
|
+
...(manufacturerPartNumber !== null
|
|
416
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
417
|
+
: {}),
|
|
385
418
|
};
|
|
386
|
-
case
|
|
419
|
+
case "led":
|
|
387
420
|
return {
|
|
388
421
|
...base,
|
|
389
|
-
ftype:
|
|
390
|
-
...(manufacturerPartNumber !== null
|
|
422
|
+
ftype: "simple_led",
|
|
423
|
+
...(manufacturerPartNumber !== null
|
|
424
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
425
|
+
: {}),
|
|
391
426
|
};
|
|
392
|
-
case
|
|
427
|
+
case "bjt":
|
|
393
428
|
return {
|
|
394
429
|
...base,
|
|
395
|
-
ftype:
|
|
430
|
+
ftype: "simple_transistor",
|
|
396
431
|
transistor_type: inferTransistorType(component),
|
|
397
|
-
...(manufacturerPartNumber !== null
|
|
432
|
+
...(manufacturerPartNumber !== null
|
|
433
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
434
|
+
: {}),
|
|
398
435
|
};
|
|
399
|
-
case
|
|
436
|
+
case "jfet":
|
|
400
437
|
warnings.push(`${component.id} (jfet): Circuit JSON has no simple_jfet ftype; emitted simple_mosfet depletion-mode source metadata`);
|
|
401
438
|
return {
|
|
402
439
|
...base,
|
|
403
|
-
ftype:
|
|
440
|
+
ftype: "simple_mosfet",
|
|
404
441
|
channel_type: inferJfetChannel(component),
|
|
405
|
-
mosfet_mode:
|
|
406
|
-
...(manufacturerPartNumber !== null
|
|
442
|
+
mosfet_mode: "depletion",
|
|
443
|
+
...(manufacturerPartNumber !== null
|
|
444
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
445
|
+
: {}),
|
|
407
446
|
};
|
|
408
|
-
case
|
|
447
|
+
case "mosfet":
|
|
409
448
|
return {
|
|
410
449
|
...base,
|
|
411
|
-
ftype:
|
|
450
|
+
ftype: "simple_mosfet",
|
|
412
451
|
channel_type: inferMosfetChannel(component),
|
|
413
452
|
mosfet_mode: inferMosfetMode(component),
|
|
414
|
-
...(manufacturerPartNumber !== null
|
|
453
|
+
...(manufacturerPartNumber !== null
|
|
454
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
455
|
+
: {}),
|
|
415
456
|
};
|
|
416
|
-
case
|
|
457
|
+
case "opamp":
|
|
417
458
|
return {
|
|
418
459
|
...base,
|
|
419
|
-
ftype:
|
|
420
|
-
...(manufacturerPartNumber !== null
|
|
460
|
+
ftype: "simple_op_amp",
|
|
461
|
+
...(manufacturerPartNumber !== null
|
|
462
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
463
|
+
: {}),
|
|
421
464
|
};
|
|
422
|
-
case
|
|
423
|
-
const resistance = quantity(component,
|
|
465
|
+
case "potentiometer": {
|
|
466
|
+
const resistance = quantity(component, "resistance");
|
|
424
467
|
if (resistance === null) {
|
|
425
|
-
return missingQuantityComponent(component,
|
|
468
|
+
return missingQuantityComponent(component, "resistance", warnings, manufacturerPartNumber);
|
|
426
469
|
}
|
|
427
470
|
return {
|
|
428
471
|
...base,
|
|
429
|
-
ftype:
|
|
430
|
-
...(manufacturerPartNumber !== null
|
|
472
|
+
ftype: "simple_potentiometer",
|
|
473
|
+
...(manufacturerPartNumber !== null
|
|
474
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
475
|
+
: {}),
|
|
431
476
|
max_resistance: resistance.value.value,
|
|
432
477
|
display_max_resistance: resistance.value.raw,
|
|
433
478
|
display_value: resistance.value.raw,
|
|
434
479
|
};
|
|
435
480
|
}
|
|
436
|
-
case
|
|
437
|
-
return { ...base, ftype:
|
|
438
|
-
case
|
|
439
|
-
case
|
|
440
|
-
const voltage = quantity(component,
|
|
481
|
+
case "switch":
|
|
482
|
+
return { ...base, ftype: "simple_switch" };
|
|
483
|
+
case "voltage-source":
|
|
484
|
+
case "battery": {
|
|
485
|
+
const voltage = quantity(component, "voltage");
|
|
441
486
|
if (voltage === null) {
|
|
442
|
-
return missingQuantityComponent(component,
|
|
487
|
+
return missingQuantityComponent(component, "voltage", warnings, null);
|
|
443
488
|
}
|
|
444
489
|
return {
|
|
445
490
|
...base,
|
|
446
|
-
ftype:
|
|
491
|
+
ftype: "simple_voltage_source",
|
|
447
492
|
voltage: voltage.value.value,
|
|
448
493
|
display_value: voltage.value.raw,
|
|
449
494
|
};
|
|
450
495
|
}
|
|
451
|
-
case
|
|
452
|
-
const voltage = quantity(component,
|
|
496
|
+
case "rail": {
|
|
497
|
+
const voltage = quantity(component, "voltage");
|
|
453
498
|
if (voltage === null) {
|
|
454
|
-
return missingQuantityComponent(component,
|
|
499
|
+
return missingQuantityComponent(component, "voltage", warnings, null);
|
|
455
500
|
}
|
|
456
501
|
return {
|
|
457
502
|
...base,
|
|
458
|
-
ftype:
|
|
503
|
+
ftype: "simple_power_source",
|
|
459
504
|
voltage: voltage.value.value,
|
|
460
505
|
display_value: voltage.value.raw,
|
|
461
506
|
};
|
|
462
507
|
}
|
|
463
|
-
case
|
|
464
|
-
const current = quantity(component,
|
|
508
|
+
case "current-source": {
|
|
509
|
+
const current = quantity(component, "current");
|
|
465
510
|
if (current === null) {
|
|
466
|
-
return missingQuantityComponent(component,
|
|
511
|
+
return missingQuantityComponent(component, "current", warnings, null);
|
|
467
512
|
}
|
|
468
513
|
return {
|
|
469
514
|
...base,
|
|
470
|
-
ftype:
|
|
471
|
-
wave_shape:
|
|
515
|
+
ftype: "simple_current_source",
|
|
516
|
+
wave_shape: "dc",
|
|
472
517
|
current: current.value.value,
|
|
473
518
|
display_value: current.value.raw,
|
|
474
519
|
};
|
|
475
520
|
}
|
|
476
|
-
case
|
|
477
|
-
return { ...base, ftype:
|
|
478
|
-
case
|
|
479
|
-
return { ...base, ftype:
|
|
480
|
-
case
|
|
481
|
-
return { ...base, ftype:
|
|
482
|
-
case
|
|
521
|
+
case "ground":
|
|
522
|
+
return { ...base, ftype: "simple_ground" };
|
|
523
|
+
case "jack":
|
|
524
|
+
return { ...base, ftype: "simple_connector" };
|
|
525
|
+
case "port":
|
|
526
|
+
return { ...base, ftype: "simple_test_point" };
|
|
527
|
+
case "ic":
|
|
483
528
|
return {
|
|
484
529
|
...base,
|
|
485
|
-
ftype:
|
|
486
|
-
...(manufacturerPartNumber !== null
|
|
530
|
+
ftype: "simple_chip",
|
|
531
|
+
...(manufacturerPartNumber !== null
|
|
532
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
533
|
+
: {}),
|
|
487
534
|
};
|
|
488
|
-
case
|
|
489
|
-
case
|
|
490
|
-
case
|
|
491
|
-
case
|
|
492
|
-
case
|
|
493
|
-
case
|
|
494
|
-
case
|
|
495
|
-
case
|
|
496
|
-
case
|
|
497
|
-
case
|
|
498
|
-
case
|
|
499
|
-
case
|
|
500
|
-
case
|
|
501
|
-
case
|
|
535
|
+
case "ota":
|
|
536
|
+
case "triode":
|
|
537
|
+
case "pentode":
|
|
538
|
+
case "tube-diode":
|
|
539
|
+
case "transformer":
|
|
540
|
+
case "optocoupler":
|
|
541
|
+
case "bbd":
|
|
542
|
+
case "delay-ic":
|
|
543
|
+
case "power-amp":
|
|
544
|
+
case "regulator":
|
|
545
|
+
case "analog-switch":
|
|
546
|
+
case "flipflop":
|
|
547
|
+
case "label":
|
|
548
|
+
case "named-wire":
|
|
502
549
|
warnings.push(`${component.id} (${component.kind}): no Circuit JSON source-component mapping; skipped`);
|
|
503
550
|
return null;
|
|
504
551
|
}
|
|
@@ -506,15 +553,17 @@ function sourceComponentElement(component, warnings) {
|
|
|
506
553
|
function sourceComponentBase(component) {
|
|
507
554
|
const groupId = canCapGroupProperty(component);
|
|
508
555
|
return {
|
|
509
|
-
type:
|
|
556
|
+
type: "source_component",
|
|
510
557
|
source_component_id: sourceComponentId(component.id),
|
|
511
558
|
name: component.name,
|
|
512
559
|
display_name: component.name,
|
|
513
|
-
...(groupId === null
|
|
560
|
+
...(groupId === null
|
|
561
|
+
? {}
|
|
562
|
+
: { source_group_id: canCapSourceGroupId(groupId) }),
|
|
514
563
|
};
|
|
515
564
|
}
|
|
516
565
|
function canCapGroupProperty(component) {
|
|
517
|
-
if (component.kind !==
|
|
566
|
+
if (component.kind !== "capacitor") {
|
|
518
567
|
return null;
|
|
519
568
|
}
|
|
520
569
|
const value = propertyStringValue(component.properties.CanCapGroupId);
|
|
@@ -539,11 +588,11 @@ function sourcePropertySidecarElements(doc, exportedComponentIds) {
|
|
|
539
588
|
}
|
|
540
589
|
const sourceComponentIdValue = sourceComponentId(component.id);
|
|
541
590
|
sidecars.push({
|
|
542
|
-
type:
|
|
591
|
+
type: "source_property_ignored_warning",
|
|
543
592
|
source_property_ignored_warning_id: `${VESSEL_DSP_PROPERTY_SIDECAR_ID_PREFIX}${sourceComponentIdValue}:${propertyName}`,
|
|
544
593
|
source_component_id: sourceComponentIdValue,
|
|
545
594
|
property_name: propertyName,
|
|
546
|
-
error_type:
|
|
595
|
+
error_type: "source_property_ignored_warning",
|
|
547
596
|
message: `${VESSEL_DSP_PROPERTY_JSON_PREFIX}${stableJsonStringify({
|
|
548
597
|
property: propertyName,
|
|
549
598
|
value,
|
|
@@ -564,44 +613,44 @@ function circuitJsonConsumedPropertyKeys(component) {
|
|
|
564
613
|
for (const name of MODEL_PROPERTY_NAMES) {
|
|
565
614
|
consumed.add(name);
|
|
566
615
|
}
|
|
567
|
-
consumed.add(
|
|
616
|
+
consumed.add("ftype");
|
|
568
617
|
if (canCapGroupProperty(component) !== null) {
|
|
569
|
-
consumed.add(
|
|
570
|
-
consumed.add(
|
|
571
|
-
consumed.add(
|
|
618
|
+
consumed.add("CanCapGroupId");
|
|
619
|
+
consumed.add("CanCapPackageName");
|
|
620
|
+
consumed.add("PackageName");
|
|
572
621
|
}
|
|
573
622
|
return consumed;
|
|
574
623
|
}
|
|
575
624
|
function quantityKeyForComponent(kind) {
|
|
576
625
|
switch (kind) {
|
|
577
|
-
case
|
|
578
|
-
case
|
|
579
|
-
case
|
|
580
|
-
return
|
|
581
|
-
case
|
|
582
|
-
return
|
|
583
|
-
case
|
|
584
|
-
return
|
|
585
|
-
case
|
|
586
|
-
case
|
|
587
|
-
case
|
|
588
|
-
return
|
|
589
|
-
case
|
|
590
|
-
return
|
|
626
|
+
case "resistor":
|
|
627
|
+
case "variable-resistor":
|
|
628
|
+
case "potentiometer":
|
|
629
|
+
return "resistance";
|
|
630
|
+
case "capacitor":
|
|
631
|
+
return "capacitance";
|
|
632
|
+
case "inductor":
|
|
633
|
+
return "inductance";
|
|
634
|
+
case "voltage-source":
|
|
635
|
+
case "battery":
|
|
636
|
+
case "rail":
|
|
637
|
+
return "voltage";
|
|
638
|
+
case "current-source":
|
|
639
|
+
return "current";
|
|
591
640
|
default:
|
|
592
641
|
return null;
|
|
593
642
|
}
|
|
594
643
|
}
|
|
595
644
|
function sourcePortElement(component, terminalName) {
|
|
596
|
-
const voltage = component.kind ===
|
|
645
|
+
const voltage = component.kind === "rail" ? quantity(component, "voltage") : null;
|
|
597
646
|
return {
|
|
598
|
-
type:
|
|
647
|
+
type: "source_port",
|
|
599
648
|
source_port_id: sourcePortId(component.id, terminalName),
|
|
600
649
|
source_component_id: sourceComponentId(component.id),
|
|
601
650
|
name: terminalName,
|
|
602
651
|
port_hints: [terminalName],
|
|
603
|
-
...(component.kind ===
|
|
604
|
-
...(component.kind ===
|
|
652
|
+
...(component.kind === "ground" ? { provides_ground: true } : {}),
|
|
653
|
+
...(component.kind === "rail" ? { provides_power: true } : {}),
|
|
605
654
|
...(voltage !== null ? { provides_voltage: voltage.value.value } : {}),
|
|
606
655
|
};
|
|
607
656
|
}
|
|
@@ -614,11 +663,12 @@ function sourceTraceElements(connectivity, names, sourcePortIdsByNode, warnings)
|
|
|
614
663
|
continue;
|
|
615
664
|
}
|
|
616
665
|
traces.push({
|
|
617
|
-
type:
|
|
666
|
+
type: "source_trace",
|
|
618
667
|
source_trace_id: sourceTraceId(nodeId),
|
|
619
668
|
connected_source_port_ids: [...sourcePortIds],
|
|
620
669
|
connected_source_net_ids: [sourceNetId(nodeId)],
|
|
621
|
-
display_name: names.get(nodeId) ??
|
|
670
|
+
display_name: names.get(nodeId) ??
|
|
671
|
+
(connectivity.groundNodeId === nodeId ? "GND" : `N${nodeId}`),
|
|
622
672
|
});
|
|
623
673
|
}
|
|
624
674
|
return traces;
|
|
@@ -632,13 +682,15 @@ function schematicElements(doc, sourceTraces) {
|
|
|
632
682
|
}
|
|
633
683
|
const schematicComponentId = `schematic_component:${component.id}`;
|
|
634
684
|
elements.push({
|
|
635
|
-
type:
|
|
685
|
+
type: "schematic_component",
|
|
636
686
|
schematic_component_id: schematicComponentId,
|
|
637
687
|
source_component_id: sourceComponentId(component.id),
|
|
638
688
|
center: toTscircuitSchematicPoint(component.origin),
|
|
639
689
|
size: schematicComponentSize(component),
|
|
640
690
|
symbol_name: schematicSymbolName(component),
|
|
641
|
-
...(schematicDisplayValue(component) === undefined
|
|
691
|
+
...(schematicDisplayValue(component) === undefined
|
|
692
|
+
? {}
|
|
693
|
+
: { symbol_display_value: schematicDisplayValue(component) }),
|
|
642
694
|
is_box_with_pins: true,
|
|
643
695
|
});
|
|
644
696
|
for (const [terminalIndex, terminal] of component.terminals.entries()) {
|
|
@@ -646,7 +698,7 @@ function schematicElements(doc, sourceTraces) {
|
|
|
646
698
|
const schematicPortId = `schematic_port:${component.id}:${terminal.name}`;
|
|
647
699
|
schematicPortBySourcePortId.set(sourcePortIdValue, schematicPortId);
|
|
648
700
|
elements.push({
|
|
649
|
-
type:
|
|
701
|
+
type: "schematic_port",
|
|
650
702
|
schematic_port_id: schematicPortId,
|
|
651
703
|
source_port_id: sourcePortIdValue,
|
|
652
704
|
schematic_component_id: schematicComponentId,
|
|
@@ -675,7 +727,7 @@ function schematicElements(doc, sourceTraces) {
|
|
|
675
727
|
to_schematic_port_id: schematicPortBySourcePortId.get(sourcePortIdValue),
|
|
676
728
|
}));
|
|
677
729
|
elements.push({
|
|
678
|
-
type:
|
|
730
|
+
type: "schematic_trace",
|
|
679
731
|
schematic_trace_id: `schematic_${trace.source_trace_id}`,
|
|
680
732
|
source_trace_id: trace.source_trace_id,
|
|
681
733
|
junctions: [],
|
|
@@ -684,14 +736,14 @@ function schematicElements(doc, sourceTraces) {
|
|
|
684
736
|
}
|
|
685
737
|
for (const [index, directive] of doc.directives.entries()) {
|
|
686
738
|
elements.push({
|
|
687
|
-
type:
|
|
739
|
+
type: "schematic_text",
|
|
688
740
|
schematic_text_id: `schematic_text:directive:${index + 1}`,
|
|
689
741
|
text: `!${directive}`,
|
|
690
742
|
font_size: 0.6,
|
|
691
743
|
position: toTscircuitSchematicPoint({ x: 0, y: 40 + index * 12 }),
|
|
692
744
|
rotation: 0,
|
|
693
|
-
color:
|
|
694
|
-
anchor:
|
|
745
|
+
color: "#000000",
|
|
746
|
+
anchor: "left",
|
|
695
747
|
});
|
|
696
748
|
}
|
|
697
749
|
return elements;
|
|
@@ -699,127 +751,144 @@ function schematicElements(doc, sourceTraces) {
|
|
|
699
751
|
function normalizeCircuitJsonElements(elements) {
|
|
700
752
|
const result = validateCircuitJsonDocument(elements);
|
|
701
753
|
if (!result.valid) {
|
|
702
|
-
throw new Error(`generated invalid Circuit JSON: ${result.errors.map((error) => `${error.path ??
|
|
754
|
+
throw new Error(`generated invalid Circuit JSON: ${result.errors.map((error) => `${error.path ?? "<root>"}: ${error.message}`).join("; ")}`);
|
|
703
755
|
}
|
|
704
756
|
return result.elements;
|
|
705
757
|
}
|
|
706
758
|
function schematicSymbolName(component) {
|
|
707
759
|
switch (component.kind) {
|
|
708
|
-
case
|
|
709
|
-
case
|
|
710
|
-
return
|
|
711
|
-
case
|
|
712
|
-
return isPolarizedCapacitor(component)
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
case
|
|
760
|
+
case "resistor":
|
|
761
|
+
case "variable-resistor":
|
|
762
|
+
return "boxresistor_right";
|
|
763
|
+
case "capacitor":
|
|
764
|
+
return isPolarizedCapacitor(component)
|
|
765
|
+
? "capacitor_polarized_right"
|
|
766
|
+
: "capacitor_right";
|
|
767
|
+
case "inductor":
|
|
768
|
+
return "inductor_right";
|
|
769
|
+
case "diode":
|
|
716
770
|
return diodeSymbolName(component);
|
|
717
|
-
case
|
|
718
|
-
return
|
|
719
|
-
case
|
|
720
|
-
return inferTransistorType(component) ===
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
case
|
|
771
|
+
case "led":
|
|
772
|
+
return "led_right";
|
|
773
|
+
case "bjt":
|
|
774
|
+
return inferTransistorType(component) === "pnp"
|
|
775
|
+
? "pnp_bipolar_transistor_right"
|
|
776
|
+
: "npn_bipolar_transistor_right";
|
|
777
|
+
case "jfet":
|
|
778
|
+
return inferJfetChannel(component) === "p"
|
|
779
|
+
? "pjfet_transistor_horz"
|
|
780
|
+
: "njfet_transistor_horz";
|
|
781
|
+
case "mosfet":
|
|
724
782
|
return mosfetSymbolName(component);
|
|
725
|
-
case
|
|
726
|
-
return
|
|
727
|
-
case
|
|
728
|
-
return
|
|
729
|
-
case
|
|
730
|
-
return
|
|
731
|
-
case
|
|
732
|
-
return
|
|
733
|
-
case
|
|
734
|
-
return
|
|
735
|
-
case
|
|
736
|
-
case
|
|
737
|
-
return
|
|
738
|
-
case
|
|
739
|
-
return
|
|
740
|
-
case
|
|
741
|
-
return
|
|
742
|
-
case
|
|
743
|
-
case
|
|
744
|
-
case
|
|
745
|
-
case
|
|
746
|
-
case
|
|
747
|
-
case
|
|
748
|
-
case
|
|
749
|
-
case
|
|
750
|
-
case
|
|
751
|
-
case
|
|
752
|
-
case
|
|
753
|
-
case
|
|
754
|
-
case
|
|
755
|
-
case
|
|
756
|
-
case
|
|
757
|
-
case
|
|
758
|
-
case
|
|
759
|
-
return
|
|
783
|
+
case "opamp":
|
|
784
|
+
return "opamp_no_power_right";
|
|
785
|
+
case "potentiometer":
|
|
786
|
+
return "potentiometer2_right";
|
|
787
|
+
case "switch":
|
|
788
|
+
return "spst_switch_right";
|
|
789
|
+
case "ground":
|
|
790
|
+
return "ground_down";
|
|
791
|
+
case "rail":
|
|
792
|
+
return "vcc_down";
|
|
793
|
+
case "voltage-source":
|
|
794
|
+
case "battery":
|
|
795
|
+
return "battery_vert";
|
|
796
|
+
case "current-source":
|
|
797
|
+
return "current_source_right";
|
|
798
|
+
case "port":
|
|
799
|
+
return "testpoint_right";
|
|
800
|
+
case "jack":
|
|
801
|
+
case "ic":
|
|
802
|
+
case "ota":
|
|
803
|
+
case "triode":
|
|
804
|
+
case "pentode":
|
|
805
|
+
case "tube-diode":
|
|
806
|
+
case "transformer":
|
|
807
|
+
case "optocoupler":
|
|
808
|
+
case "bbd":
|
|
809
|
+
case "delay-ic":
|
|
810
|
+
case "power-amp":
|
|
811
|
+
case "regulator":
|
|
812
|
+
case "analog-switch":
|
|
813
|
+
case "flipflop":
|
|
814
|
+
case "unsupported":
|
|
815
|
+
case "label":
|
|
816
|
+
case "named-wire":
|
|
817
|
+
return "testpoint_right";
|
|
760
818
|
}
|
|
761
819
|
}
|
|
762
820
|
function schematicComponentSize(component) {
|
|
763
821
|
switch (component.kind) {
|
|
764
|
-
case
|
|
765
|
-
case
|
|
822
|
+
case "resistor":
|
|
823
|
+
case "variable-resistor":
|
|
766
824
|
return { width: 1.1, height: 0.39 };
|
|
767
|
-
case
|
|
825
|
+
case "capacitor":
|
|
768
826
|
return { width: 1.1, height: 0.84 };
|
|
769
|
-
case
|
|
827
|
+
case "inductor":
|
|
770
828
|
return { width: 1.16, height: 0.46 };
|
|
771
|
-
case
|
|
829
|
+
case "diode":
|
|
772
830
|
return { width: 1.04, height: 0.54 };
|
|
773
|
-
case
|
|
831
|
+
case "led":
|
|
774
832
|
return { width: 1.13, height: 0.65 };
|
|
775
|
-
case
|
|
776
|
-
return {
|
|
777
|
-
|
|
833
|
+
case "bjt":
|
|
834
|
+
return {
|
|
835
|
+
width: 1.1,
|
|
836
|
+
height: inferTransistorType(component) === "pnp" ? 0.83 : 0.95,
|
|
837
|
+
};
|
|
838
|
+
case "opamp":
|
|
778
839
|
return { width: 1, height: 0.72 };
|
|
779
|
-
case
|
|
840
|
+
case "potentiometer":
|
|
780
841
|
return { width: 1.18, height: 0.58 };
|
|
781
|
-
case
|
|
782
|
-
case
|
|
783
|
-
case
|
|
784
|
-
case
|
|
842
|
+
case "ground":
|
|
843
|
+
case "rail":
|
|
844
|
+
case "port":
|
|
845
|
+
case "jack":
|
|
785
846
|
return { width: 0.8, height: 0.6 };
|
|
786
847
|
default:
|
|
787
848
|
return DEFAULT_SCHEMATIC_COMPONENT_SIZE;
|
|
788
849
|
}
|
|
789
850
|
}
|
|
790
851
|
function schematicDisplayValue(component) {
|
|
791
|
-
const value = quantity(component,
|
|
852
|
+
const value = quantity(component, "resistance") ??
|
|
853
|
+
quantity(component, "capacitance") ??
|
|
854
|
+
quantity(component, "inductance") ??
|
|
855
|
+
quantity(component, "voltage") ??
|
|
856
|
+
quantity(component, "current");
|
|
792
857
|
return value?.value.raw;
|
|
793
858
|
}
|
|
794
859
|
function schematicPortFacingDirection(origin, terminalPosition) {
|
|
795
860
|
const dx = terminalPosition.x - origin.x;
|
|
796
861
|
const dy = terminalPosition.y - origin.y;
|
|
797
862
|
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
798
|
-
return dx < 0 ?
|
|
863
|
+
return dx < 0 ? "left" : "right";
|
|
799
864
|
}
|
|
800
|
-
return dy < 0 ?
|
|
865
|
+
return dy < 0 ? "up" : "down";
|
|
801
866
|
}
|
|
802
867
|
function isPolarizedCapacitor(component) {
|
|
803
868
|
const text = searchablePropertyText(component);
|
|
804
|
-
return text.includes(
|
|
869
|
+
return text.includes("electrolytic") || text.includes("polar");
|
|
805
870
|
}
|
|
806
871
|
function diodeSymbolName(component) {
|
|
807
872
|
const text = searchablePropertyText(component);
|
|
808
|
-
if (text.includes(
|
|
809
|
-
return
|
|
873
|
+
if (text.includes("zener")) {
|
|
874
|
+
return "zener_diode_horz";
|
|
810
875
|
}
|
|
811
|
-
if (text.includes(
|
|
812
|
-
return
|
|
876
|
+
if (text.includes("schottky")) {
|
|
877
|
+
return "schottky_diode_right";
|
|
813
878
|
}
|
|
814
|
-
return
|
|
879
|
+
return "diode_right";
|
|
815
880
|
}
|
|
816
881
|
function mosfetSymbolName(component) {
|
|
817
882
|
const channel = inferMosfetChannel(component);
|
|
818
883
|
const mode = inferMosfetMode(component);
|
|
819
|
-
if (channel ===
|
|
820
|
-
return mode ===
|
|
884
|
+
if (channel === "p") {
|
|
885
|
+
return mode === "depletion"
|
|
886
|
+
? "p_channel_d_mosfet_transistor_horz"
|
|
887
|
+
: "p_channel_e_mosfet_transistor_horz";
|
|
821
888
|
}
|
|
822
|
-
return mode ===
|
|
889
|
+
return mode === "depletion"
|
|
890
|
+
? "n_channel_d_mosfet_transistor_horz"
|
|
891
|
+
: "n_channel_e_mosfet_transistor_horz";
|
|
823
892
|
}
|
|
824
893
|
function netNames(doc, connectivity) {
|
|
825
894
|
const names = new Map();
|
|
@@ -827,7 +896,9 @@ function netNames(doc, connectivity) {
|
|
|
827
896
|
if (component.terminals.length === 0) {
|
|
828
897
|
continue;
|
|
829
898
|
}
|
|
830
|
-
if (component.kind !==
|
|
899
|
+
if (component.kind !== "rail" &&
|
|
900
|
+
component.kind !== "named-wire" &&
|
|
901
|
+
component.kind !== "label") {
|
|
831
902
|
continue;
|
|
832
903
|
}
|
|
833
904
|
const terminal = component.terminals[0];
|
|
@@ -843,14 +914,14 @@ function netNames(doc, connectivity) {
|
|
|
843
914
|
}
|
|
844
915
|
}
|
|
845
916
|
if (connectivity.groundNodeId !== null) {
|
|
846
|
-
names.set(connectivity.groundNodeId,
|
|
917
|
+
names.set(connectivity.groundNodeId, "GND");
|
|
847
918
|
}
|
|
848
919
|
return names;
|
|
849
920
|
}
|
|
850
921
|
function railNodeIds(doc, connectivity) {
|
|
851
922
|
const ids = new Set();
|
|
852
923
|
for (const component of doc.components) {
|
|
853
|
-
if (component.kind !==
|
|
924
|
+
if (component.kind !== "rail") {
|
|
854
925
|
continue;
|
|
855
926
|
}
|
|
856
927
|
for (const terminal of component.terminals) {
|
|
@@ -903,8 +974,10 @@ function missingQuantityComponent(component, quantityName, warnings, manufacture
|
|
|
903
974
|
warnings.push(`${component.id} (${component.kind}): missing ${quantityName}; emitted opaque simple_chip source component metadata only`);
|
|
904
975
|
return {
|
|
905
976
|
...sourceComponentBase(component),
|
|
906
|
-
ftype:
|
|
907
|
-
...(manufacturerPartNumber !== null
|
|
977
|
+
ftype: "simple_chip",
|
|
978
|
+
...(manufacturerPartNumber !== null
|
|
979
|
+
? { manufacturer_part_number: manufacturerPartNumber }
|
|
980
|
+
: {}),
|
|
908
981
|
};
|
|
909
982
|
}
|
|
910
983
|
function firstStringProperty(component, names) {
|
|
@@ -919,29 +992,37 @@ function firstStringProperty(component, names) {
|
|
|
919
992
|
}
|
|
920
993
|
function inferTransistorType(component) {
|
|
921
994
|
const searchable = searchablePropertyText(component);
|
|
922
|
-
return searchable.includes(
|
|
995
|
+
return searchable.includes("pnp") ? "pnp" : "npn";
|
|
923
996
|
}
|
|
924
997
|
function inferMosfetChannel(component) {
|
|
925
998
|
const searchable = searchablePropertyText(component);
|
|
926
|
-
return searchable.includes(
|
|
999
|
+
return searchable.includes("pmos") ||
|
|
1000
|
+
searchable.includes("p-channel") ||
|
|
1001
|
+
searchable.includes("p channel")
|
|
1002
|
+
? "p"
|
|
1003
|
+
: "n";
|
|
927
1004
|
}
|
|
928
1005
|
function inferJfetChannel(component) {
|
|
929
1006
|
const searchable = searchablePropertyText(component);
|
|
930
|
-
return searchable.includes(
|
|
1007
|
+
return searchable.includes("pjf") ||
|
|
1008
|
+
searchable.includes("p-channel") ||
|
|
1009
|
+
searchable.includes("p channel")
|
|
1010
|
+
? "p"
|
|
1011
|
+
: "n";
|
|
931
1012
|
}
|
|
932
1013
|
function inferMosfetMode(component) {
|
|
933
1014
|
const searchable = searchablePropertyText(component);
|
|
934
|
-
return searchable.includes(
|
|
1015
|
+
return searchable.includes("depletion") ? "depletion" : "enhancement";
|
|
935
1016
|
}
|
|
936
1017
|
function searchablePropertyText(component) {
|
|
937
|
-
const values = [component.name, component.sourceTypeName ??
|
|
1018
|
+
const values = [component.name, component.sourceTypeName ?? ""];
|
|
938
1019
|
for (const value of Object.values(component.properties)) {
|
|
939
1020
|
const text = propertyStringValue(value);
|
|
940
1021
|
if (text !== null) {
|
|
941
1022
|
values.push(text);
|
|
942
1023
|
}
|
|
943
1024
|
}
|
|
944
|
-
return values.join(
|
|
1025
|
+
return values.join(" ").toLowerCase();
|
|
945
1026
|
}
|
|
946
1027
|
function sourceComponentId(componentId) {
|
|
947
1028
|
return `source_component:${componentId}`;
|
|
@@ -974,12 +1055,12 @@ function roundTscircuitSchematicCoordinate(value) {
|
|
|
974
1055
|
return Math.round(value * 1000) / 1000;
|
|
975
1056
|
}
|
|
976
1057
|
function parseSourcePortId(sourcePortIdValue) {
|
|
977
|
-
const prefix =
|
|
1058
|
+
const prefix = "source_port:";
|
|
978
1059
|
if (!sourcePortIdValue.startsWith(prefix)) {
|
|
979
1060
|
return null;
|
|
980
1061
|
}
|
|
981
1062
|
const rest = sourcePortIdValue.slice(prefix.length);
|
|
982
|
-
const separator = rest.lastIndexOf(
|
|
1063
|
+
const separator = rest.lastIndexOf(":");
|
|
983
1064
|
if (separator < 0) {
|
|
984
1065
|
return null;
|
|
985
1066
|
}
|
|
@@ -992,33 +1073,36 @@ function summarizeSchemaIssues(issues) {
|
|
|
992
1073
|
return issues
|
|
993
1074
|
.slice(0, 3)
|
|
994
1075
|
.map((issue) => {
|
|
995
|
-
const path = issue.path.length === 0 ?
|
|
1076
|
+
const path = issue.path.length === 0 ? "<root>" : issue.path.join(".");
|
|
996
1077
|
return `${path}: ${issue.message}`;
|
|
997
1078
|
})
|
|
998
|
-
.join(
|
|
1079
|
+
.join("; ");
|
|
999
1080
|
}
|
|
1000
1081
|
function shallowSchemaIssue(value) {
|
|
1001
|
-
if (typeof value !==
|
|
1002
|
-
return
|
|
1082
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1083
|
+
return "Circuit JSON element must be an object";
|
|
1003
1084
|
}
|
|
1004
1085
|
const record = Object.fromEntries(Object.entries(value));
|
|
1005
1086
|
const type = record.type;
|
|
1006
|
-
if (type ===
|
|
1007
|
-
|
|
1087
|
+
if (type === "source_component" &&
|
|
1088
|
+
typeof record.source_component_id !== "string") {
|
|
1089
|
+
return "source_component_id: Expected string";
|
|
1008
1090
|
}
|
|
1009
1091
|
return null;
|
|
1010
1092
|
}
|
|
1011
1093
|
function checkedRecord(value) {
|
|
1012
|
-
if (typeof value !==
|
|
1013
|
-
throw new Error(
|
|
1094
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1095
|
+
throw new Error("expected Circuit JSON element object");
|
|
1014
1096
|
}
|
|
1015
1097
|
return Object.fromEntries(Object.entries(value));
|
|
1016
1098
|
}
|
|
1017
1099
|
function vesselDspPropertySidecar(record) {
|
|
1018
|
-
const sourceComponentIdValue = stringField(record,
|
|
1019
|
-
const propertyName = stringField(record,
|
|
1020
|
-
const message = stringField(record,
|
|
1021
|
-
if (sourceComponentIdValue === null ||
|
|
1100
|
+
const sourceComponentIdValue = stringField(record, "source_component_id");
|
|
1101
|
+
const propertyName = stringField(record, "property_name");
|
|
1102
|
+
const message = stringField(record, "message");
|
|
1103
|
+
if (sourceComponentIdValue === null ||
|
|
1104
|
+
propertyName === null ||
|
|
1105
|
+
message === null) {
|
|
1022
1106
|
return null;
|
|
1023
1107
|
}
|
|
1024
1108
|
if (!message.startsWith(VESSEL_DSP_PROPERTY_JSON_PREFIX)) {
|
|
@@ -1049,7 +1133,7 @@ function parseJsonRecord(source) {
|
|
|
1049
1133
|
}
|
|
1050
1134
|
function stringField(record, key) {
|
|
1051
1135
|
const value = record[key];
|
|
1052
|
-
return typeof value ===
|
|
1136
|
+
return typeof value === "string" ? value : null;
|
|
1053
1137
|
}
|
|
1054
1138
|
function requiredStringField(record, key) {
|
|
1055
1139
|
const value = stringField(record, key);
|
|
@@ -1060,31 +1144,33 @@ function requiredStringField(record, key) {
|
|
|
1060
1144
|
}
|
|
1061
1145
|
function numericField(record, key) {
|
|
1062
1146
|
const value = record[key];
|
|
1063
|
-
return typeof value ===
|
|
1147
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1064
1148
|
}
|
|
1065
1149
|
function pointField(record, key) {
|
|
1066
1150
|
const value = record[key];
|
|
1067
|
-
if (typeof value !==
|
|
1151
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1068
1152
|
return null;
|
|
1069
1153
|
}
|
|
1070
1154
|
const pointRecord = checkedRecord(value);
|
|
1071
1155
|
const x = pointRecord.x;
|
|
1072
1156
|
const y = pointRecord.y;
|
|
1073
|
-
return typeof x ===
|
|
1157
|
+
return typeof x === "number" && typeof y === "number" ? { x, y } : null;
|
|
1074
1158
|
}
|
|
1075
1159
|
function stringArrayField(record, key) {
|
|
1076
1160
|
const value = record[key];
|
|
1077
|
-
return Array.isArray(value)
|
|
1161
|
+
return Array.isArray(value)
|
|
1162
|
+
? value.filter((entry) => typeof entry === "string")
|
|
1163
|
+
: [];
|
|
1078
1164
|
}
|
|
1079
1165
|
function stripKnownPrefix(value, prefix) {
|
|
1080
1166
|
return value.startsWith(prefix) ? value.slice(prefix.length) : null;
|
|
1081
1167
|
}
|
|
1082
1168
|
function sanitizeId(value) {
|
|
1083
|
-
const sanitized = value.replace(/\s+/g,
|
|
1084
|
-
return sanitized.length > 0 ? sanitized :
|
|
1169
|
+
const sanitized = value.replace(/\s+/g, "-").replace(/[^A-Za-z0-9_-]/g, "");
|
|
1170
|
+
return sanitized.length > 0 ? sanitized : "component";
|
|
1085
1171
|
}
|
|
1086
1172
|
function stableJsonStringify(value) {
|
|
1087
|
-
return JSON.stringify(stableJsonValue(value)) ??
|
|
1173
|
+
return JSON.stringify(stableJsonValue(value)) ?? "null";
|
|
1088
1174
|
}
|
|
1089
1175
|
function stableJsonValue(value) {
|
|
1090
1176
|
if (Array.isArray(value)) {
|
|
@@ -1101,9 +1187,9 @@ function stableJsonValue(value) {
|
|
|
1101
1187
|
}
|
|
1102
1188
|
function isPropertyValue(value) {
|
|
1103
1189
|
if (value === null ||
|
|
1104
|
-
typeof value ===
|
|
1105
|
-
typeof value ===
|
|
1106
|
-
(typeof value ===
|
|
1190
|
+
typeof value === "string" ||
|
|
1191
|
+
typeof value === "boolean" ||
|
|
1192
|
+
(typeof value === "number" && Number.isFinite(value))) {
|
|
1107
1193
|
return true;
|
|
1108
1194
|
}
|
|
1109
1195
|
if (Array.isArray(value)) {
|
|
@@ -1115,7 +1201,7 @@ function isPropertyValue(value) {
|
|
|
1115
1201
|
return Object.values(value).every(isPropertyValue);
|
|
1116
1202
|
}
|
|
1117
1203
|
function isJsonRecord(value) {
|
|
1118
|
-
return typeof value ===
|
|
1204
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1119
1205
|
}
|
|
1120
1206
|
function terminalNameFromSourcePortId(sourcePortIdValue) {
|
|
1121
1207
|
const parsed = parseSourcePortId(sourcePortIdValue);
|
|
@@ -1134,10 +1220,12 @@ function groupPortsByComponent(sourcePorts) {
|
|
|
1134
1220
|
return map;
|
|
1135
1221
|
}
|
|
1136
1222
|
function buildComponentFromCircuitJson(sourceComponent, ports, schematicComponents, schematicPorts, sourceGroups, sidecars, index) {
|
|
1137
|
-
const origin = schematicComponents.get(sourceComponent.sourceComponentId)?.center ??
|
|
1223
|
+
const origin = schematicComponents.get(sourceComponent.sourceComponentId)?.center ??
|
|
1224
|
+
synthesizedOrigin(index);
|
|
1138
1225
|
const terminals = ports.map((port, portIndex) => ({
|
|
1139
1226
|
name: port.terminalName,
|
|
1140
|
-
position: schematicPorts.get(port.sourcePortId)?.center ??
|
|
1227
|
+
position: schematicPorts.get(port.sourcePortId)?.center ??
|
|
1228
|
+
synthesizedTerminalPosition(origin, ports.length, portIndex),
|
|
1141
1229
|
}));
|
|
1142
1230
|
const sidecarProperties = propertiesFromSidecars(sidecars);
|
|
1143
1231
|
const groupedProperties = canCapPropertiesFromSourceGroup(sourceComponent, sourceGroups, sidecarProperties);
|
|
@@ -1154,7 +1242,9 @@ function buildComponentFromCircuitJson(sourceComponent, ports, schematicComponen
|
|
|
1154
1242
|
...sidecarProperties,
|
|
1155
1243
|
...groupedProperties,
|
|
1156
1244
|
},
|
|
1157
|
-
sourceTypeName: sourceComponent.ftype === null
|
|
1245
|
+
sourceTypeName: sourceComponent.ftype === null
|
|
1246
|
+
? "circuit-json:source_component"
|
|
1247
|
+
: `circuit-json:${sourceComponent.ftype}`,
|
|
1158
1248
|
};
|
|
1159
1249
|
return { sourceComponent, ports, origin, terminals, component };
|
|
1160
1250
|
}
|
|
@@ -1170,7 +1260,7 @@ function canCapPropertiesFromSourceGroup(sourceComponent, sourceGroups, sidecarP
|
|
|
1170
1260
|
if (sourceGroupId === null) {
|
|
1171
1261
|
return {};
|
|
1172
1262
|
}
|
|
1173
|
-
if (kindFromCircuitJsonFtype(sourceComponent.ftype) !==
|
|
1263
|
+
if (kindFromCircuitJsonFtype(sourceComponent.ftype) !== "capacitor") {
|
|
1174
1264
|
return {};
|
|
1175
1265
|
}
|
|
1176
1266
|
const discriminatorGroupId = canCapGroupIdFromSourceGroupId(sourceGroupId);
|
|
@@ -1179,11 +1269,13 @@ function canCapPropertiesFromSourceGroup(sourceComponent, sourceGroups, sidecarP
|
|
|
1179
1269
|
return {};
|
|
1180
1270
|
}
|
|
1181
1271
|
const group = sourceGroups.get(sourceGroupId);
|
|
1182
|
-
const fallbackGroupId = stripKnownPrefix(sourceGroupId,
|
|
1272
|
+
const fallbackGroupId = stripKnownPrefix(sourceGroupId, "source_group:") ?? sourceGroupId;
|
|
1183
1273
|
const canCapGroupId = discriminatorGroupId ?? fallbackGroupId;
|
|
1184
1274
|
return {
|
|
1185
1275
|
CanCapGroupId: canCapGroupId,
|
|
1186
|
-
...(group?.name === null || group?.name === undefined
|
|
1276
|
+
...(group?.name === null || group?.name === undefined
|
|
1277
|
+
? {}
|
|
1278
|
+
: { CanCapPackageName: group.name }),
|
|
1187
1279
|
};
|
|
1188
1280
|
}
|
|
1189
1281
|
function synthesizedOrigin(index) {
|
|
@@ -1205,64 +1297,64 @@ function synthesizedTerminalPosition(origin, terminalCount, index) {
|
|
|
1205
1297
|
}
|
|
1206
1298
|
function kindFromCircuitJsonFtype(ftype) {
|
|
1207
1299
|
switch (ftype) {
|
|
1208
|
-
case
|
|
1209
|
-
return
|
|
1210
|
-
case
|
|
1211
|
-
return
|
|
1212
|
-
case
|
|
1213
|
-
return
|
|
1214
|
-
case
|
|
1215
|
-
return
|
|
1216
|
-
case
|
|
1217
|
-
return
|
|
1218
|
-
case
|
|
1219
|
-
return
|
|
1220
|
-
case
|
|
1221
|
-
return
|
|
1222
|
-
case
|
|
1223
|
-
return
|
|
1224
|
-
case
|
|
1225
|
-
return
|
|
1226
|
-
case
|
|
1227
|
-
case
|
|
1228
|
-
return
|
|
1229
|
-
case
|
|
1230
|
-
return
|
|
1231
|
-
case
|
|
1232
|
-
return
|
|
1233
|
-
case
|
|
1234
|
-
return
|
|
1235
|
-
case
|
|
1236
|
-
return
|
|
1237
|
-
case
|
|
1238
|
-
return
|
|
1239
|
-
case
|
|
1240
|
-
return
|
|
1241
|
-
case
|
|
1242
|
-
return
|
|
1243
|
-
case
|
|
1244
|
-
return
|
|
1300
|
+
case "simple_resistor":
|
|
1301
|
+
return "resistor";
|
|
1302
|
+
case "simple_capacitor":
|
|
1303
|
+
return "capacitor";
|
|
1304
|
+
case "simple_inductor":
|
|
1305
|
+
return "inductor";
|
|
1306
|
+
case "simple_diode":
|
|
1307
|
+
return "diode";
|
|
1308
|
+
case "simple_led":
|
|
1309
|
+
return "led";
|
|
1310
|
+
case "simple_transistor":
|
|
1311
|
+
return "bjt";
|
|
1312
|
+
case "simple_mosfet":
|
|
1313
|
+
return "mosfet";
|
|
1314
|
+
case "simple_op_amp":
|
|
1315
|
+
return "opamp";
|
|
1316
|
+
case "simple_potentiometer":
|
|
1317
|
+
return "potentiometer";
|
|
1318
|
+
case "simple_switch":
|
|
1319
|
+
case "simple_push_button":
|
|
1320
|
+
return "switch";
|
|
1321
|
+
case "simple_voltage_source":
|
|
1322
|
+
return "voltage-source";
|
|
1323
|
+
case "simple_current_source":
|
|
1324
|
+
return "current-source";
|
|
1325
|
+
case "simple_battery":
|
|
1326
|
+
return "battery";
|
|
1327
|
+
case "simple_ground":
|
|
1328
|
+
return "ground";
|
|
1329
|
+
case "simple_power_source":
|
|
1330
|
+
return "rail";
|
|
1331
|
+
case "simple_connector":
|
|
1332
|
+
return "jack";
|
|
1333
|
+
case "simple_test_point":
|
|
1334
|
+
return "port";
|
|
1335
|
+
case "simple_chip":
|
|
1336
|
+
return "ic";
|
|
1245
1337
|
default:
|
|
1246
|
-
return
|
|
1338
|
+
return "unsupported";
|
|
1247
1339
|
}
|
|
1248
1340
|
}
|
|
1249
1341
|
function propertiesFromCircuitJsonComponent(record) {
|
|
1250
1342
|
const properties = {};
|
|
1251
|
-
const ftype = stringField(record,
|
|
1252
|
-
const displayValue = stringField(record,
|
|
1343
|
+
const ftype = stringField(record, "ftype");
|
|
1344
|
+
const displayValue = stringField(record, "display_value");
|
|
1253
1345
|
if (displayValue !== null) {
|
|
1254
1346
|
properties.Value = displayValue;
|
|
1255
1347
|
}
|
|
1256
|
-
const manufacturerPartNumber = stringField(record,
|
|
1348
|
+
const manufacturerPartNumber = stringField(record, "manufacturer_part_number");
|
|
1257
1349
|
if (manufacturerPartNumber !== null) {
|
|
1258
1350
|
properties.manufacturerPartNumber = manufacturerPartNumber;
|
|
1259
1351
|
}
|
|
1260
|
-
addQuantityProperty(properties,
|
|
1261
|
-
addQuantityProperty(properties,
|
|
1262
|
-
addQuantityProperty(properties,
|
|
1263
|
-
addQuantityProperty(properties,
|
|
1264
|
-
addQuantityProperty(properties,
|
|
1265
|
-
addQuantityProperty(properties,
|
|
1352
|
+
addQuantityProperty(properties, "R", record, "display_resistance", "resistance");
|
|
1353
|
+
addQuantityProperty(properties, "C", record, "display_capacitance", "capacitance");
|
|
1354
|
+
addQuantityProperty(properties, "L", record, "display_inductance", "inductance");
|
|
1355
|
+
addQuantityProperty(properties, "V", record, null, "voltage");
|
|
1356
|
+
addQuantityProperty(properties, "I", record, null, "current");
|
|
1357
|
+
addQuantityProperty(properties, "Resistance", record, "display_max_resistance", "max_resistance");
|
|
1266
1358
|
if (ftype !== null) {
|
|
1267
1359
|
properties.ftype = ftype;
|
|
1268
1360
|
}
|
|
@@ -1294,7 +1386,7 @@ function terminalPositionMap(builds) {
|
|
|
1294
1386
|
function wireElementsFromSourceTraces(sourceTraces, terminalPositions) {
|
|
1295
1387
|
const wires = [];
|
|
1296
1388
|
for (const trace of sourceTraces) {
|
|
1297
|
-
const ports = stringArrayField(trace,
|
|
1389
|
+
const ports = stringArrayField(trace, "connected_source_port_ids");
|
|
1298
1390
|
if (ports.length < 2) {
|
|
1299
1391
|
continue;
|
|
1300
1392
|
}
|
|
@@ -1319,7 +1411,7 @@ function wireElementsFromSourceTraces(sourceTraces, terminalPositions) {
|
|
|
1319
1411
|
function warningsForUnconnectedNets(sourceNets, sourceTraces) {
|
|
1320
1412
|
const referencedNetIds = new Set();
|
|
1321
1413
|
for (const trace of sourceTraces) {
|
|
1322
|
-
for (const netId of stringArrayField(trace,
|
|
1414
|
+
for (const netId of stringArrayField(trace, "connected_source_net_ids")) {
|
|
1323
1415
|
referencedNetIds.add(netId);
|
|
1324
1416
|
}
|
|
1325
1417
|
}
|
|
@@ -1327,8 +1419,8 @@ function warningsForUnconnectedNets(sourceNets, sourceTraces) {
|
|
|
1327
1419
|
for (const [netId, net] of sourceNets) {
|
|
1328
1420
|
if (!referencedNetIds.has(netId)) {
|
|
1329
1421
|
warnings.push({
|
|
1330
|
-
code:
|
|
1331
|
-
message: `${stringField(net,
|
|
1422
|
+
code: "circuit-json-net-unconnected",
|
|
1423
|
+
message: `${stringField(net, "name") ?? netId}: Circuit JSON source net is not referenced by a source trace`,
|
|
1332
1424
|
});
|
|
1333
1425
|
}
|
|
1334
1426
|
}
|
|
@@ -1336,9 +1428,9 @@ function warningsForUnconnectedNets(sourceNets, sourceTraces) {
|
|
|
1336
1428
|
}
|
|
1337
1429
|
function filenameWithoutCircuitJsonExtension(filename) {
|
|
1338
1430
|
return filename
|
|
1339
|
-
.replace(/\.circuit\.json$/i,
|
|
1340
|
-
.replace(/\.json$/i,
|
|
1341
|
-
.replace(/[-_]+/g,
|
|
1431
|
+
.replace(/\.circuit\.json$/i, "")
|
|
1432
|
+
.replace(/\.json$/i, "")
|
|
1433
|
+
.replace(/[-_]+/g, " ")
|
|
1342
1434
|
.trim();
|
|
1343
1435
|
}
|
|
1344
1436
|
//# sourceMappingURL=serializer.js.map
|