@schemd/core 0.1.1 → 0.2.0
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 +22 -83
- package/dist/compiler.d.ts +16 -0
- package/dist/compiler.js +17 -0
- package/dist/index.d.ts +6 -8
- package/dist/index.js +5 -5
- package/dist/layout.d.ts +14 -4
- package/dist/layout.js +510 -138
- package/dist/limits.d.ts +4 -3
- package/dist/limits.js +2 -0
- package/dist/math-label.d.ts +20 -3
- package/dist/math-label.js +149 -56
- package/dist/parser.js +248 -27
- package/dist/renderer.js +184 -37
- package/dist/types.d.ts +64 -14
- package/dist/types.js +34 -1
- package/package.json +28 -8
- package/dist/marked-extension.d.ts +0 -23
- package/dist/marked-extension.js +0 -75
package/README.md
CHANGED
|
@@ -1,119 +1,58 @@
|
|
|
1
1
|
# @schemd/core
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://github.com/Sirneij/schemd/actions/workflows/ci.yml)
|
|
5
|
-
[](https://github.com/Sirneij/schemd/blob/main/LICENSE)
|
|
3
|
+
Write schematics and UML as text. Get accessible, deterministic SVG.
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Schemd supports electrical components, logic gates, quantum gates, and general system diagrams. It runs on the server or during a build, so the browser only receives SVG—no diagram runtime, DOM, or layout engine.
|
|
10
|
-
|
|
11
|
-
## Why Schemd?
|
|
12
|
-
|
|
13
|
-
- Small, readable text format
|
|
14
|
-
- Deterministic SVG output with fixed dimensions
|
|
15
|
-
- Straight, curved, and obstacle-aware orthogonal connections
|
|
16
|
-
- Accessible titles and descriptions
|
|
17
|
-
- No runtime dependencies
|
|
5
|
+
Schemd has no runtime dependencies, browser layout pass, or DOM requirement. It works on a server or during a build.
|
|
18
6
|
|
|
19
7
|
## Install
|
|
20
8
|
|
|
21
|
-
Schemd requires Node.js 24 or newer. Install `marked` if you want to use Markdown fences.
|
|
22
|
-
|
|
23
9
|
```sh
|
|
24
|
-
npm install @schemd/core
|
|
10
|
+
npm install @schemd/core
|
|
25
11
|
```
|
|
26
12
|
|
|
27
|
-
|
|
13
|
+
Node.js 24+ is required.
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
28
16
|
|
|
29
17
|
```ts
|
|
30
|
-
import {
|
|
31
|
-
import { schematicMarkedExtension } from "@schemd/core";
|
|
18
|
+
import { compileSchematic, parseSchematicFence } from "@schemd/core";
|
|
32
19
|
|
|
33
|
-
const
|
|
34
|
-
|
|
20
|
+
const fence = parseSchematicFence(
|
|
21
|
+
'schemd bounds="640x260" title="Sensor input"',
|
|
22
|
+
)!;
|
|
35
23
|
|
|
36
|
-
const
|
|
37
|
-
\`\`\`schemd bounds="640x260" title="Sensor input"
|
|
24
|
+
const { svg, document, metrics } = compileSchematic(`
|
|
38
25
|
port:VIN "Input" at (60, 130) #blue
|
|
39
26
|
resistor:R1 "10 k\\Omega" at (220, 130) #amber
|
|
40
27
|
capacitor:C1 "100 nF" at (400, 130) #cyan
|
|
41
28
|
|
|
42
29
|
VIN.out -> R1.in #blue [ortho]
|
|
43
30
|
R1.out -> C1.in #amber [ortho]
|
|
44
|
-
|
|
45
|
-
`);
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Use the compiler directly
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
import {
|
|
52
|
-
parseSchematic,
|
|
53
|
-
parseSchematicFence,
|
|
54
|
-
renderSchematic,
|
|
55
|
-
} from "@schemd/core";
|
|
56
|
-
|
|
57
|
-
const fence = parseSchematicFence(
|
|
58
|
-
'schemd bounds="640x260" title="Sensor input"',
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
if (!fence) throw new Error("Expected a schemd fence");
|
|
62
|
-
|
|
63
|
-
const diagram = parseSchematic(
|
|
64
|
-
`port:VIN "Input" at (60, 130) #blue
|
|
65
|
-
resistor:R1 "10 k\\Omega" at (220, 130) #amber
|
|
66
|
-
VIN.out -> R1.in #blue [ortho]`,
|
|
67
|
-
fence,
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const svg = renderSchematic(diagram, fence);
|
|
31
|
+
`, fence);
|
|
71
32
|
```
|
|
72
33
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
A diagram has component declarations and connections:
|
|
34
|
+
The DSL is intentionally small:
|
|
76
35
|
|
|
77
36
|
```text
|
|
78
37
|
kind:ID "label" at (x, y) color [options]
|
|
79
38
|
ID.port -> ID.port color [line|bezier|ortho]
|
|
80
39
|
```
|
|
81
40
|
|
|
82
|
-
|
|
41
|
+
It includes electrical parts, analog devices, logic and quantum gates, configurable ICs, math labels, collision-aware routing, and wire bridges.
|
|
83
42
|
|
|
84
|
-
|
|
43
|
+
UML nodes and relations use the same syntax:
|
|
85
44
|
|
|
86
45
|
```text
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
See the [full documentation](https://johnowolabiidogun.dev/tools/schemd/docs/overview) for component ports, options, colors, math labels, and framework integrations.
|
|
46
|
+
class:User "User" at (160, 120) #slate [attributes="- id: UUID" operations="+ save(): void"]
|
|
47
|
+
class:Admin "Admin" at (460, 120) #blue
|
|
91
48
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
| Mode | Use it for |
|
|
95
|
-
| --- | --- |
|
|
96
|
-
| `default` | Small, static SVG |
|
|
97
|
-
| `embedded-css` | Built-in styles and responsive visuals |
|
|
98
|
-
| `full` | Interactive diagrams with node and wire metadata |
|
|
99
|
-
|
|
100
|
-
Pass a mode to `renderSchematic` or `schematicMarkedExtension`:
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
const svg = renderSchematic(diagram, { ...fence, mode: "embedded-css" });
|
|
49
|
+
Admin.left -> User.right #blue [ortho generalization]
|
|
104
50
|
```
|
|
105
51
|
|
|
106
|
-
|
|
52
|
+
Class, actor, use-case, state, lifeline, note, package, initial, and final nodes are built in. Relations include association, dependency, generalization, realization, aggregation, composition, message, transition, include, and extend.
|
|
107
53
|
|
|
108
|
-
|
|
54
|
+
Use `mode: "embedded-css"` for built-in styling or `mode: "full"` for interaction metadata. The default output stays compact and static.
|
|
109
55
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
```sh
|
|
113
|
-
npm install
|
|
114
|
-
npm run check
|
|
115
|
-
npm test
|
|
116
|
-
npm run build
|
|
117
|
-
```
|
|
56
|
+
Markdown belongs at the host boundary. Detect `schemd` fences in your server-side Markdown renderer and pass their text to `compileSchematic`; core does not ship or require a Markdown parser.
|
|
118
57
|
|
|
119
|
-
|
|
58
|
+
[Documentation](https://johnowolabiidogun.dev/tools/schemd/docs/overview) · [Issues](https://github.com/Sirneij/schemd/issues) · [MIT](https://github.com/Sirneij/schemd/blob/main/LICENSE)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CompileSchematicOptions, SchematicDocument } from './types.js';
|
|
2
|
+
/** Small, allocation-bounded compilation counters. */
|
|
3
|
+
export interface SchematicCompilationMetrics {
|
|
4
|
+
readonly sourceCharacters: number;
|
|
5
|
+
readonly components: number;
|
|
6
|
+
readonly connections: number;
|
|
7
|
+
readonly svgBytes: number;
|
|
8
|
+
}
|
|
9
|
+
/** Validated AST, rendered SVG, and useful host-side counters. */
|
|
10
|
+
export interface SchematicCompilation {
|
|
11
|
+
readonly document: SchematicDocument;
|
|
12
|
+
readonly svg: string;
|
|
13
|
+
readonly metrics: SchematicCompilationMetrics;
|
|
14
|
+
}
|
|
15
|
+
/** Parse and render a schematic with one stable public call. */
|
|
16
|
+
export declare function compileSchematic(source: string, options: CompileSchematicOptions): SchematicCompilation;
|
package/dist/compiler.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { utf8ByteLength } from './limits.js';
|
|
2
|
+
import { parseSchematic } from './parser.js';
|
|
3
|
+
import { renderSchematic } from './renderer.js';
|
|
4
|
+
export function compileSchematic(source, options) {
|
|
5
|
+
const document = parseSchematic(source, options);
|
|
6
|
+
const svg = renderSchematic(document, options);
|
|
7
|
+
return {
|
|
8
|
+
document,
|
|
9
|
+
svg,
|
|
10
|
+
metrics: {
|
|
11
|
+
sourceCharacters: source.length,
|
|
12
|
+
components: document.components.length,
|
|
13
|
+
connections: document.connections.length,
|
|
14
|
+
svgBytes: utf8ByteLength(svg)
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stable public entry point for the `schemd` server-side compiler.
|
|
3
3
|
*
|
|
4
|
-
* All runtime exports are dependency-free
|
|
5
|
-
* Marked contracts as types only, so applications pay for no Markdown runtime
|
|
6
|
-
* unless they already provide one at the host boundary.
|
|
4
|
+
* All runtime exports are dependency-free and safe to run without a DOM.
|
|
7
5
|
*
|
|
8
6
|
* @packageDocumentation
|
|
9
7
|
*/
|
|
10
8
|
export { parseSchematic, parseSchematicColor, parseSchematicFence } from './parser.js';
|
|
11
9
|
export { renderSchematic } from './renderer.js';
|
|
12
|
-
export {
|
|
13
|
-
export { mathLabelGlyphLength, mathLabelText, parseMathLabel, renderMathLabelTspans, type MathLabelSegment, type MathLabelSegmentKind } from './math-label.js';
|
|
14
|
-
export { MAX_SCHEMATIC_COMPONENTS, MAX_SCHEMATIC_CONNECTIONS, MAX_SCHEMATIC_SOURCE_CHARACTERS, MAX_SCHEMATIC_SVG_OUTPUT_BYTES, SCHEMATIC_LIMITS } from './limits.js';
|
|
15
|
-
export { classicalGateHeight, componentObstacleRectangle, componentRectangle, componentTextAnchors, distributedCoordinate, enumerateComponentPorts, positionIcPin, PORT_HOTSPOT_RADIUS, resolvePortPoint, routeConnections, routeConnection, SCHEMATIC_BRIDGE_RADIUS, SCHEMATIC_OBSTACLE_CLEARANCE, validateDocumentGeometry, type RoutedConnection, type ComponentTextAnchors, type ComponentPort, type IcPinSide, type SchematicRectangle } from './layout.js';
|
|
16
|
-
export { ANALOG_KINDS, COMPONENT_KINDS, CLASSICAL_GATE_KINDS, DIODE_TYPES, GROUND_STYLES, PASSIVE_KINDS, QUANTUM_GATE_KINDS, SCHEMATIC_SIGNAL_MARKERS, SEMANTIC_COLORS, TRANSISTOR_TYPES, SCHEMD_OUTPUT_MODES, SchematicSyntaxError, type AnalogKind, type CompileSchematicOptions, type ClassicalGateComponent, type ClassicalGateKind, type ComponentKind, type DiodeComponent, type DiodeType, type GroundComponent, type GroundStyle, type IcComponent, type IntegratedCircuitComponent, type IntegratedCircuitPins, type PassiveComponent, type PassiveKind, type PortComponent, type SemanticColor, type SchematicBounds, type SchematicComponent, type SchematicConnection, type SchematicColor, type SchematicDocument, type SchematicEndpoint, type SchematicFence, type SchematicSignalMarker, type
|
|
10
|
+
export { compileSchematic, type SchematicCompilation, type SchematicCompilationMetrics } from './compiler.js';
|
|
11
|
+
export { mathLabelGlyphLength, mathLabelTextWidth, mathLabelText, parseMathLabel, renderMathLabelTspans, type MathLabelSegment, type MathLabelSegmentKind } from './math-label.js';
|
|
12
|
+
export { MAX_SCHEMATIC_COMPONENTS, MAX_SCHEMATIC_CONNECTIONS, MAX_SCHEMATIC_WIRE_CROSSINGS, MAX_SCHEMATIC_SOURCE_CHARACTERS, MAX_SCHEMATIC_SVG_OUTPUT_BYTES, SCHEMATIC_LIMITS } from './limits.js';
|
|
13
|
+
export { classicalGateHeight, componentObstacleRectangle, componentRectangle, componentTextAnchors, distributedCoordinate, enumerateComponentPorts, positionIcPin, PORT_HOTSPOT_RADIUS, resolvePortPoint, resolvePortGeometry, routeConnections, routeConnection, SCHEMATIC_BRIDGE_RADIUS, SCHEMATIC_OBSTACLE_CLEARANCE, validateDocumentGeometry, type RoutedConnection, type ComponentTextAnchors, type ComponentPort, type IcPinSide, type SchematicRectangle } from './layout.js';
|
|
14
|
+
export { ANALOG_KINDS, COMPONENT_KINDS, CLASSICAL_GATE_KINDS, DIODE_TYPES, GROUND_STYLES, PASSIVE_KINDS, QUANTUM_GATE_KINDS, SCHEMATIC_SIGNAL_MARKERS, SEMANTIC_COLORS, TRANSISTOR_TYPES, UML_COMPONENT_KINDS, UML_RELATION_KINDS, SCHEMD_OUTPUT_MODES, SCHEMD_SEMANTIC_HOOKS, SchematicSyntaxError, type AnalogKind, type CompileSchematicOptions, type ClassicalGateComponent, type ClassicalGateKind, type ComponentKind, type DiodeComponent, type DiodeType, type GroundComponent, type GroundStyle, type IcComponent, type IntegratedCircuitComponent, type IntegratedCircuitPins, type PassiveComponent, type PassiveKind, type PortComponent, type SemanticColor, type SchematicBounds, type SchematicComponent, type SchematicConnection, type SchematicColor, type SchematicDocument, type SchematicEndpoint, type SchematicFence, type SchematicSignalMarker, type SchematicSemanticHook, type SchematicPoint, type SchemdOutputMode, type TransistorComponent, type TransistorType, type QuantumGateComponent, type QuantumGateKind, type SchematicRelationKind, type UmlActorComponent, type UmlClassComponent, type UmlComponent, type UmlComponentKind, type UmlPseudostateComponent, type UmlRelationKind, type UmlSizedComponent, type UmlStateComponent } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { parseSchematic, parseSchematicColor, parseSchematicFence } from './parser.js';
|
|
2
2
|
export { renderSchematic } from './renderer.js';
|
|
3
|
-
export {
|
|
4
|
-
export { mathLabelGlyphLength, mathLabelText, parseMathLabel, renderMathLabelTspans } from './math-label.js';
|
|
5
|
-
export { MAX_SCHEMATIC_COMPONENTS, MAX_SCHEMATIC_CONNECTIONS, MAX_SCHEMATIC_SOURCE_CHARACTERS, MAX_SCHEMATIC_SVG_OUTPUT_BYTES, SCHEMATIC_LIMITS } from './limits.js';
|
|
6
|
-
export { classicalGateHeight, componentObstacleRectangle, componentRectangle, componentTextAnchors, distributedCoordinate, enumerateComponentPorts, positionIcPin, PORT_HOTSPOT_RADIUS, resolvePortPoint, routeConnections, routeConnection, SCHEMATIC_BRIDGE_RADIUS, SCHEMATIC_OBSTACLE_CLEARANCE, validateDocumentGeometry } from './layout.js';
|
|
7
|
-
export { ANALOG_KINDS, COMPONENT_KINDS, CLASSICAL_GATE_KINDS, DIODE_TYPES, GROUND_STYLES, PASSIVE_KINDS, QUANTUM_GATE_KINDS, SCHEMATIC_SIGNAL_MARKERS, SEMANTIC_COLORS, TRANSISTOR_TYPES, SCHEMD_OUTPUT_MODES, SchematicSyntaxError } from './types.js';
|
|
3
|
+
export { compileSchematic } from './compiler.js';
|
|
4
|
+
export { mathLabelGlyphLength, mathLabelTextWidth, mathLabelText, parseMathLabel, renderMathLabelTspans } from './math-label.js';
|
|
5
|
+
export { MAX_SCHEMATIC_COMPONENTS, MAX_SCHEMATIC_CONNECTIONS, MAX_SCHEMATIC_WIRE_CROSSINGS, MAX_SCHEMATIC_SOURCE_CHARACTERS, MAX_SCHEMATIC_SVG_OUTPUT_BYTES, SCHEMATIC_LIMITS } from './limits.js';
|
|
6
|
+
export { classicalGateHeight, componentObstacleRectangle, componentRectangle, componentTextAnchors, distributedCoordinate, enumerateComponentPorts, positionIcPin, PORT_HOTSPOT_RADIUS, resolvePortPoint, resolvePortGeometry, routeConnections, routeConnection, SCHEMATIC_BRIDGE_RADIUS, SCHEMATIC_OBSTACLE_CLEARANCE, validateDocumentGeometry } from './layout.js';
|
|
7
|
+
export { ANALOG_KINDS, COMPONENT_KINDS, CLASSICAL_GATE_KINDS, DIODE_TYPES, GROUND_STYLES, PASSIVE_KINDS, QUANTUM_GATE_KINDS, SCHEMATIC_SIGNAL_MARKERS, SEMANTIC_COLORS, TRANSISTOR_TYPES, UML_COMPONENT_KINDS, UML_RELATION_KINDS, SCHEMD_OUTPUT_MODES, SCHEMD_SEMANTIC_HOOKS, SchematicSyntaxError } from './types.js';
|
package/dist/layout.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @packageDocumentation
|
|
10
10
|
*/
|
|
11
|
-
import { type ClassicalGateComponent, type IntegratedCircuitComponent, type SchematicComponent, type SchematicConnection, type SchematicDocument, type SchematicFence, type SchematicPoint } from './types.js';
|
|
11
|
+
import { type ClassicalGateComponent, type IntegratedCircuitComponent, type SchematicBounds, type SchematicComponent, type SchematicConnection, type SchematicDocument, type SchematicFence, type SchematicPoint } from './types.js';
|
|
12
12
|
/** Axis-aligned rectangle expressed in absolute schematic coordinates. */
|
|
13
13
|
export interface SchematicRectangle {
|
|
14
14
|
/** Inclusive left extent. */
|
|
@@ -22,6 +22,8 @@ export interface SchematicRectangle {
|
|
|
22
22
|
}
|
|
23
23
|
/** Render-ready connection path and the points used for bounds validation. */
|
|
24
24
|
export interface RoutedConnection {
|
|
25
|
+
/** Original routing strategy; crossing passes must never infer it from control points. */
|
|
26
|
+
readonly curve: SchematicConnection['curve'];
|
|
25
27
|
/** Compact SVG path-data string. */
|
|
26
28
|
d: string;
|
|
27
29
|
/** At least two absolute points spanning endpoints, controls, corners, and bridge extrema. */
|
|
@@ -44,6 +46,8 @@ export interface ComponentPort {
|
|
|
44
46
|
readonly id: string;
|
|
45
47
|
/** Absolute center of the physical terminal. */
|
|
46
48
|
readonly point: SchematicPoint;
|
|
49
|
+
/** Unit outward normal used to leave the owning component without crossing its body. */
|
|
50
|
+
readonly normal: SchematicPoint;
|
|
47
51
|
}
|
|
48
52
|
/** One edge of a polymorphic integrated-circuit body. */
|
|
49
53
|
export type IcPinSide = 'left' | 'right' | 'top' | 'bottom';
|
|
@@ -88,6 +92,11 @@ export declare function positionIcPin(component: IntegratedCircuitComponent, sid
|
|
|
88
92
|
* @throws {Error} When called with an endpoint the semantic parser did not validate.
|
|
89
93
|
*/
|
|
90
94
|
export declare function resolvePortPoint(component: SchematicComponent, port: string): SchematicPoint;
|
|
95
|
+
/** Resolve a port coordinate together with the direction a route must initially travel. */
|
|
96
|
+
export declare function resolvePortGeometry(component: SchematicComponent, port: string): {
|
|
97
|
+
readonly point: SchematicPoint;
|
|
98
|
+
readonly normal: SchematicPoint;
|
|
99
|
+
};
|
|
91
100
|
/**
|
|
92
101
|
* Enumerate each physical terminal exactly once. Alias spellings deliberately resolve through
|
|
93
102
|
* `resolvePortPoint` but do not create duplicate interactive targets.
|
|
@@ -110,9 +119,10 @@ export declare function componentObstacleRectangle(component: SchematicComponent
|
|
|
110
119
|
*
|
|
111
120
|
* @param connection - Validated directed connection.
|
|
112
121
|
* @param components - Complete component map used for endpoint and obstacle lookup.
|
|
122
|
+
* @param bounds - Optional intrinsic routing bounds.
|
|
113
123
|
* @returns SVG path data plus control/corner points for later bounds checks.
|
|
114
124
|
*/
|
|
115
|
-
export declare function routeConnection(connection: SchematicConnection, components: ReadonlyMap<string, SchematicComponent
|
|
125
|
+
export declare function routeConnection(connection: SchematicConnection, components: ReadonlyMap<string, SchematicComponent>, bounds?: SchematicBounds): RoutedConnection;
|
|
116
126
|
/**
|
|
117
127
|
* Route connections in source order and bridge only the later trace at a true crossing.
|
|
118
128
|
*
|
|
@@ -123,7 +133,7 @@ export declare function routeConnection(connection: SchematicConnection, compone
|
|
|
123
133
|
* @param components - Complete component map.
|
|
124
134
|
* @returns Routes in the same order, with crossings applied to later orthogonal traces.
|
|
125
135
|
*/
|
|
126
|
-
export declare function routeConnections(connections: readonly SchematicConnection[], components: ReadonlyMap<string, SchematicComponent
|
|
136
|
+
export declare function routeConnections(connections: readonly SchematicConnection[], components: ReadonlyMap<string, SchematicComponent>, bounds?: SchematicBounds): readonly RoutedConnection[];
|
|
127
137
|
/**
|
|
128
138
|
* Calculate external designator and label fitting metrics.
|
|
129
139
|
*
|
|
@@ -148,4 +158,4 @@ export declare function componentRectangle(component: SchematicComponent): Schem
|
|
|
148
158
|
* @param fence - Intrinsic canvas contract.
|
|
149
159
|
* @throws {SchematicSyntaxError} At the originating component or connection line.
|
|
150
160
|
*/
|
|
151
|
-
export declare function validateDocumentGeometry(document: SchematicDocument, fence: SchematicFence): void;
|
|
161
|
+
export declare function validateDocumentGeometry(document: SchematicDocument, fence: SchematicFence, routedConnections?: readonly RoutedConnection[]): void;
|