@schemd/core 0.1.1 → 0.1.2
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 +23 -82
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/layout.d.ts +14 -4
- package/dist/layout.js +510 -138
- package/dist/limits.d.ts +3 -0
- 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 +147 -27
- package/dist/types.d.ts +58 -3
- package/dist/types.js +33 -1
- package/package.json +33 -3
package/dist/renderer.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { classicalGateHeight, componentTextAnchors, distributedCoordinate, enumerateComponentPorts, positionIcPin, PORT_HOTSPOT_RADIUS, routeConnections, validateDocumentGeometry } from './layout.js';
|
|
2
2
|
import { MAX_SCHEMATIC_SVG_OUTPUT_BYTES, utf8ByteLength } from './limits.js';
|
|
3
3
|
import { assertParsedSchematicDocument } from './parser.js';
|
|
4
|
-
import { CLASSICAL_GATE_KINDS, SCHEMD_OUTPUT_MODES, SchematicSyntaxError } from './types.js';
|
|
5
|
-
import { renderMathLabelTspans } from './math-label.js';
|
|
4
|
+
import { CLASSICAL_GATE_KINDS, SCHEMD_OUTPUT_MODES, UML_COMPONENT_KINDS, SchematicSyntaxError } from './types.js';
|
|
5
|
+
import { mathLabelTextWidth, renderMathLabelTspans } from './math-label.js';
|
|
6
6
|
export const MAX_SVG_OUTPUT_BYTES = MAX_SCHEMATIC_SVG_OUTPUT_BYTES;
|
|
7
|
-
const STATIC_SVG_STYLES = '.schematic-token{fill:none;stroke:var(--schematic-vector,var(--schematic-vector-fallback,currentColor));stroke-linecap:round;stroke-linejoin:round;stroke-width:var(--schematic-stroke-width,1.65);vector-effect:non-scaling-stroke}.schematic-node-fill{fill:var(--schematic-vector,var(--schematic-vector-fallback,currentColor))}.schematic-designator,.schematic-label,.schematic-gate-symbol,.schematic-quantum-detail,.schematic-pin-label{fill:currentColor}.schematic-surface{fill:var(--schematic-surface,transparent)}.schematic-grid-line{fill:none;stroke:var(--schematic-grid,currentColor);stroke-width:1;opacity:.12;vector-effect:non-scaling-stroke}';
|
|
7
|
+
const STATIC_SVG_STYLES = '.schematic-token{fill:none;stroke:var(--schematic-vector,var(--schematic-vector-fallback,currentColor));stroke-linecap:round;stroke-linejoin:round;stroke-width:var(--schematic-stroke-width,1.65);vector-effect:non-scaling-stroke}.schematic-node-fill{fill:var(--schematic-vector,var(--schematic-vector-fallback,currentColor))}.schematic-designator,.schematic-label,.schematic-gate-symbol,.schematic-quantum-detail,.schematic-pin-label,.schematic-uml-text,.schematic-connection-label{fill:currentColor}.schematic-uml-row{font-size:12px}.schematic-uml-stereotype{font-size:11px}.schematic-connection-label{font-size:11px;paint-order:stroke;stroke:var(--schematic-surface,#fff);stroke-width:4;stroke-linejoin:round}.schematic-surface{fill:var(--schematic-surface,transparent)}.schematic-grid-line{fill:none;stroke:var(--schematic-grid,currentColor);stroke-width:1;opacity:.12;vector-effect:non-scaling-stroke}';
|
|
8
8
|
const HOOK_SVG_STYLES = '.schematic-port-hotspot{fill:transparent!important;stroke:transparent!important;stroke-width:8;vector-effect:non-scaling-stroke;pointer-events:all;outline:none}.schematic-port-hotspot:focus-visible{fill:var(--schematic-vector,var(--schematic-vector-fallback,currentColor))!important;fill-opacity:.22!important;stroke:var(--schematic-vector,var(--schematic-vector-fallback,currentColor))!important;stroke-width:2}';
|
|
9
9
|
const INTERACTIVE_SVG_STYLES = '.schematic-component,.schematic-wire{outline:none;transition:opacity .2s ease,filter .2s ease}.schematic-component .schematic-token,.schematic-wire .schematic-token{transition:stroke .2s ease,fill .2s ease,color .2s ease,opacity .2s ease,stroke-width .2s ease}.schematic-glow-layer{opacity:0;pointer-events:none;transition:opacity .2s ease}.schematic-component:hover>.schematic-glow-layer,.schematic-component:focus>.schematic-glow-layer,.schematic-component:focus-within>.schematic-glow-layer,.schematic-component.is-hovered>.schematic-glow-layer,.schematic-component.is-active>.schematic-glow-layer,.schematic-component.is-selected>.schematic-glow-layer,.schematic-wire:hover>.schematic-glow-layer,.schematic-wire:focus>.schematic-glow-layer,.schematic-wire.is-hovered>.schematic-glow-layer,.schematic-wire.is-active>.schematic-glow-layer,.schematic-wire.is-selected>.schematic-glow-layer{opacity:1}.schematic-component.is-degraded,.schematic-wire.is-degraded{opacity:.45}.schematic-component.is-degraded>.schematic-glow-layer,.schematic-wire.is-degraded>.schematic-glow-layer{opacity:0}.schematic-component:hover .schematic-token,.schematic-component:focus .schematic-token,.schematic-component:focus-within .schematic-token,.schematic-component.is-hovered .schematic-token,.schematic-component.is-active .schematic-token,.schematic-component.is-selected .schematic-token,.schematic-wire:hover .schematic-token,.schematic-wire:focus .schematic-token,.schematic-wire.is-hovered .schematic-token,.schematic-wire.is-active .schematic-token,.schematic-wire.is-selected .schematic-token{stroke-width:var(--schematic-interactive-stroke-width,2.25)}.schematic-port-hotspot{fill:var(--schematic-vector,var(--schematic-vector-fallback,currentColor))!important;fill-opacity:0;transition:fill-opacity .2s ease,opacity .2s ease}.schematic-port-hotspot:hover,.schematic-port-hotspot:focus,.schematic-port-hotspot.is-hovered,.schematic-port-hotspot.is-active,.schematic-port-hotspot.is-selected{fill-opacity:.2}.schematic-port-hotspot.is-degraded{opacity:.45}@media(prefers-reduced-motion:reduce){.schematic-component,.schematic-wire,.schematic-token,.schematic-glow-layer,.schematic-port-hotspot{transition:none}}';
|
|
10
10
|
function validXmlCodePoint(codePoint) {
|
|
@@ -90,7 +90,7 @@ function svgNumber(value) {
|
|
|
90
90
|
return String(Number(value.toFixed(3)));
|
|
91
91
|
}
|
|
92
92
|
function fittedTextLength(value, maximum, advance) {
|
|
93
|
-
return Math.max(1, Math.min(
|
|
93
|
+
return Math.max(1, Math.min(Math.ceil(mathLabelTextWidth(value, advance)), maximum));
|
|
94
94
|
}
|
|
95
95
|
function stableHash(value) {
|
|
96
96
|
let hash = 2166136261;
|
|
@@ -103,6 +103,9 @@ function stableHash(value) {
|
|
|
103
103
|
function isClassicalGate(component) {
|
|
104
104
|
return CLASSICAL_GATE_KINDS.includes(component.kind);
|
|
105
105
|
}
|
|
106
|
+
function isUmlComponent(component) {
|
|
107
|
+
return UML_COMPONENT_KINDS.includes(component.kind);
|
|
108
|
+
}
|
|
106
109
|
function colorAttributes(color, extraClass = '') {
|
|
107
110
|
const suffix = extraClass === '' ? '' : ` ${extraClass}`;
|
|
108
111
|
const fill = extraClass.split(' ').includes('schematic-node-fill') ? ' fill="currentColor"' : '';
|
|
@@ -183,7 +186,7 @@ function iecGate(component, paint) {
|
|
|
183
186
|
xor: '=1',
|
|
184
187
|
not: '1'
|
|
185
188
|
};
|
|
186
|
-
return `<rect ${paint} x="-32" y="${-height / 2}" width="64" height="${height}" rx="2" /><text class="schematic-gate-symbol" fill="currentColor" stroke="none" x="0" y="4">${symbol[component.kind]}</text>${inversionBubbles(component, paint)}${gateStubs(component, paint)}`;
|
|
189
|
+
return `<rect ${paint} x="-32" y="${-height / 2}" width="64" height="${height}" rx="2" /><text class="schematic-gate-symbol" fill="currentColor" stroke="none" x="0" y="4" text-anchor="middle" font-size="14">${symbol[component.kind]}</text>${inversionBubbles(component, paint)}${gateStubs(component, paint)}`;
|
|
187
190
|
}
|
|
188
191
|
function ieeeGate(component, paint) {
|
|
189
192
|
const height = classicalGateHeight(component);
|
|
@@ -205,9 +208,9 @@ function ieeeGate(component, paint) {
|
|
|
205
208
|
function quantumText(component) {
|
|
206
209
|
const details = [component.parameter, component.phase, component.matrix].filter((value) => value !== undefined && value !== '');
|
|
207
210
|
const rows = [component.label, ...details];
|
|
208
|
-
const start = -((rows.length - 1) *
|
|
211
|
+
const start = -((rows.length - 1) * 12) / 2 + 4;
|
|
209
212
|
return rows
|
|
210
|
-
.map((value, index) => `<text class="${index === 0 ? 'schematic-gate-symbol' : 'schematic-quantum-detail'}" fill="currentColor" stroke="none" x="0" y="${start + index * 10}" textLength="${fittedTextLength(value, 56, index === 0 ? 7 : 5)}" lengthAdjust="spacingAndGlyphs">${renderMathLabelTspans(value)}</text>`)
|
|
213
|
+
.map((value, index) => `<text class="${index === 0 ? 'schematic-gate-symbol' : 'schematic-quantum-detail'}" fill="currentColor" stroke="none" x="0" y="${start + index * 12}" text-anchor="middle" font-size="${index === 0 ? 14 : 10}" textLength="${fittedTextLength(value, 56, index === 0 ? 7 : 5)}" lengthAdjust="spacingAndGlyphs">${renderMathLabelTspans(value)}</text>`)
|
|
211
214
|
.join('');
|
|
212
215
|
}
|
|
213
216
|
function diodeShape(component, paint) {
|
|
@@ -261,29 +264,94 @@ function icPinMarkup(component, side, paint) {
|
|
|
261
264
|
const horizontalTextLength = fittedTextLength(pin, Math.max(8, component.bodyWidth / 2 - 10), 4);
|
|
262
265
|
const verticalTextLength = fittedTextLength(pin, Math.max(8, component.bodyHeight / 2 - 10), 4);
|
|
263
266
|
if (side === 'left') {
|
|
264
|
-
return `<path ${paint} d="M ${x} ${y} H ${-component.bodyWidth / 2}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${-component.bodyWidth / 2 + 5}" y="${y + 3}" text-anchor="start" textLength="${horizontalTextLength}" lengthAdjust="spacingAndGlyphs">${escapeXml(pin)}</text>`;
|
|
267
|
+
return `<path ${paint} d="M ${x} ${y} H ${-component.bodyWidth / 2}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${-component.bodyWidth / 2 + 5}" y="${y + 3}" text-anchor="start" font-size="10" textLength="${horizontalTextLength}" lengthAdjust="spacingAndGlyphs">${escapeXml(pin)}</text>`;
|
|
265
268
|
}
|
|
266
269
|
if (side === 'right') {
|
|
267
|
-
return `<path ${paint} d="M ${component.bodyWidth / 2} ${y} H ${x}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${component.bodyWidth / 2 - 5}" y="${y + 3}" text-anchor="end" textLength="${horizontalTextLength}" lengthAdjust="spacingAndGlyphs">${escapeXml(pin)}</text>`;
|
|
270
|
+
return `<path ${paint} d="M ${component.bodyWidth / 2} ${y} H ${x}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${component.bodyWidth / 2 - 5}" y="${y + 3}" text-anchor="end" font-size="10" textLength="${horizontalTextLength}" lengthAdjust="spacingAndGlyphs">${escapeXml(pin)}</text>`;
|
|
268
271
|
}
|
|
269
272
|
if (side === 'top') {
|
|
270
273
|
const labelY = -component.bodyHeight / 2 + 5;
|
|
271
|
-
return `<path ${paint} d="M ${x} ${y} V ${-component.bodyHeight / 2}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${x}" y="${labelY}" text-anchor="start" textLength="${verticalTextLength}" lengthAdjust="spacingAndGlyphs" transform="rotate(90 ${x} ${labelY})">${escapeXml(pin)}</text>`;
|
|
274
|
+
return `<path ${paint} d="M ${x} ${y} V ${-component.bodyHeight / 2}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${x}" y="${labelY}" text-anchor="start" font-size="10" textLength="${verticalTextLength}" lengthAdjust="spacingAndGlyphs" transform="rotate(90 ${x} ${labelY})">${escapeXml(pin)}</text>`;
|
|
272
275
|
}
|
|
273
276
|
const labelY = component.bodyHeight / 2 - 5;
|
|
274
|
-
return `<path ${paint} d="M ${x} ${component.bodyHeight / 2} V ${y}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${x}" y="${labelY}" text-anchor="start" textLength="${verticalTextLength}" lengthAdjust="spacingAndGlyphs" transform="rotate(-90 ${x} ${labelY})">${escapeXml(pin)}</text>`;
|
|
277
|
+
return `<path ${paint} d="M ${x} ${component.bodyHeight / 2} V ${y}" /><text class="schematic-pin-label" fill="currentColor" stroke="none" x="${x}" y="${labelY}" text-anchor="start" font-size="10" textLength="${verticalTextLength}" lengthAdjust="spacingAndGlyphs" transform="rotate(-90 ${x} ${labelY})">${escapeXml(pin)}</text>`;
|
|
275
278
|
})
|
|
276
279
|
.join('');
|
|
277
280
|
}
|
|
278
281
|
function integratedCircuitShape(component, paint) {
|
|
279
282
|
const left = -component.bodyWidth / 2;
|
|
280
283
|
const top = -component.bodyHeight / 2;
|
|
281
|
-
return `<rect ${paint} x="${left}" y="${top}" width="${component.bodyWidth}" height="${component.bodyHeight}" rx="3" />${icPinMarkup(component, 'left', paint)}${icPinMarkup(component, 'right', paint)}${icPinMarkup(component, 'top', paint)}${icPinMarkup(component, 'bottom', paint)}<text class="schematic-gate-symbol" fill="currentColor" stroke="none" x="0" y="4" textLength="${fittedTextLength(component.label, component.bodyWidth - 12, 7)}" lengthAdjust="spacingAndGlyphs">${renderMathLabelTspans(component.label)}</text>`;
|
|
284
|
+
return `<rect ${paint} x="${left}" y="${top}" width="${component.bodyWidth}" height="${component.bodyHeight}" rx="3" />${icPinMarkup(component, 'left', paint)}${icPinMarkup(component, 'right', paint)}${icPinMarkup(component, 'top', paint)}${icPinMarkup(component, 'bottom', paint)}<text class="schematic-gate-symbol" fill="currentColor" stroke="none" x="0" y="4" text-anchor="middle" font-size="12" textLength="${fittedTextLength(component.label, component.bodyWidth - 12, 7)}" lengthAdjust="spacingAndGlyphs">${renderMathLabelTspans(component.label)}</text>`;
|
|
285
|
+
}
|
|
286
|
+
function umlRow(value, x, y) {
|
|
287
|
+
return `<text class="schematic-uml-text schematic-uml-row" fill="currentColor" stroke="none" x="${svgNumber(x)}" y="${svgNumber(y)}" font-size="12">${escapeXml(value)}</text>`;
|
|
288
|
+
}
|
|
289
|
+
function umlClassShape(component, paint) {
|
|
290
|
+
const left = -component.bodyWidth / 2;
|
|
291
|
+
const top = -component.bodyHeight / 2;
|
|
292
|
+
const headerHeight = 36 + (component.stereotype === undefined ? 0 : 14);
|
|
293
|
+
const attributeHeight = Math.max(24, component.attributes.length * 16 + 8);
|
|
294
|
+
const attributeSeparator = top + headerHeight;
|
|
295
|
+
const operationSeparator = attributeSeparator + attributeHeight;
|
|
296
|
+
const stereotype = component.stereotype === undefined
|
|
297
|
+
? ''
|
|
298
|
+
: `<text class="schematic-uml-text schematic-uml-stereotype" fill="currentColor" stroke="none" x="0" y="${svgNumber(top + 13)}" text-anchor="middle" font-size="11">«${escapeXml(component.stereotype)}»</text>`;
|
|
299
|
+
const nameY = top + (component.stereotype === undefined ? 23 : 32);
|
|
300
|
+
const attributes = component.attributes
|
|
301
|
+
.map((row, index) => umlRow(row, left + 8, attributeSeparator + 17 + index * 16))
|
|
302
|
+
.join('');
|
|
303
|
+
const operations = component.operations
|
|
304
|
+
.map((row, index) => umlRow(row, left + 8, operationSeparator + 17 + index * 16))
|
|
305
|
+
.join('');
|
|
306
|
+
return `<rect ${paint} x="${svgNumber(left)}" y="${svgNumber(top)}" width="${svgNumber(component.bodyWidth)}" height="${svgNumber(component.bodyHeight)}" rx="2" /><path ${paint} d="M ${svgNumber(left)} ${svgNumber(attributeSeparator)} H ${svgNumber(-left)} M ${svgNumber(left)} ${svgNumber(operationSeparator)} H ${svgNumber(-left)}" />${stereotype}<text class="schematic-uml-text" fill="currentColor" stroke="none" x="0" y="${svgNumber(nameY)}" text-anchor="middle" font-size="13" font-weight="600">${renderMathLabelTspans(component.label)}</text>${attributes}${operations}`;
|
|
307
|
+
}
|
|
308
|
+
function umlStateShape(component, paint) {
|
|
309
|
+
const left = -component.bodyWidth / 2;
|
|
310
|
+
const top = -component.bodyHeight / 2;
|
|
311
|
+
const separator = top + 32;
|
|
312
|
+
const rows = component.details
|
|
313
|
+
.map((row, index) => umlRow(row, left + 8, separator + 17 + index * 16))
|
|
314
|
+
.join('');
|
|
315
|
+
return `<rect ${paint} x="${svgNumber(left)}" y="${svgNumber(top)}" width="${svgNumber(component.bodyWidth)}" height="${svgNumber(component.bodyHeight)}" rx="10" />${component.details.length === 0 ? '' : `<path ${paint} d="M ${svgNumber(left)} ${svgNumber(separator)} H ${svgNumber(-left)}" />`}<text class="schematic-uml-text" fill="currentColor" stroke="none" x="0" y="${svgNumber(top + 21)}" text-anchor="middle" font-size="13" font-weight="600">${renderMathLabelTspans(component.label)}</text>${rows}`;
|
|
316
|
+
}
|
|
317
|
+
function umlComponentShape(component, paint, nodePaint) {
|
|
318
|
+
if (component.kind === 'class')
|
|
319
|
+
return umlClassShape(component, paint);
|
|
320
|
+
if (component.kind === 'state')
|
|
321
|
+
return umlStateShape(component, paint);
|
|
322
|
+
switch (component.kind) {
|
|
323
|
+
case 'actor':
|
|
324
|
+
return `<circle ${paint} cx="0" cy="-28" r="9" /><path ${paint} d="M 0 -19 V 12 M -20 -5 H 20 M 0 12 L -17 37 M 0 12 L 17 37" /><text class="schematic-uml-text" fill="currentColor" stroke="none" x="0" y="49" text-anchor="middle" font-size="12">${renderMathLabelTspans(component.label)}</text>`;
|
|
325
|
+
case 'usecase':
|
|
326
|
+
return `<ellipse ${paint} cx="0" cy="0" rx="${svgNumber(component.bodyWidth / 2)}" ry="${svgNumber(component.bodyHeight / 2)}" /><text class="schematic-uml-text" fill="currentColor" stroke="none" x="0" y="4" text-anchor="middle" font-size="13">${renderMathLabelTspans(component.label)}</text>`;
|
|
327
|
+
case 'lifeline': {
|
|
328
|
+
const top = -component.bodyHeight / 2;
|
|
329
|
+
const left = -component.bodyWidth / 2;
|
|
330
|
+
return `<rect ${paint} x="${svgNumber(left)}" y="${svgNumber(top)}" width="${svgNumber(component.bodyWidth)}" height="32" rx="2" /><text class="schematic-uml-text" fill="currentColor" stroke="none" x="0" y="${svgNumber(top + 21)}" text-anchor="middle" font-size="12">${renderMathLabelTspans(component.label)}</text><path ${paint} stroke-dasharray="6 5" d="M 0 ${svgNumber(top + 32)} V ${svgNumber(component.bodyHeight / 2)}" />`;
|
|
331
|
+
}
|
|
332
|
+
case 'note': {
|
|
333
|
+
const left = -component.bodyWidth / 2;
|
|
334
|
+
const top = -component.bodyHeight / 2;
|
|
335
|
+
const right = component.bodyWidth / 2;
|
|
336
|
+
return `<path ${paint} d="M ${svgNumber(left)} ${svgNumber(top)} H ${svgNumber(right - 14)} L ${svgNumber(right)} ${svgNumber(top + 14)} V ${svgNumber(-top)} H ${svgNumber(left)} Z M ${svgNumber(right - 14)} ${svgNumber(top)} V ${svgNumber(top + 14)} H ${svgNumber(right)}" /><text class="schematic-uml-text" fill="currentColor" stroke="none" x="0" y="4" text-anchor="middle" font-size="12">${renderMathLabelTspans(component.label)}</text>`;
|
|
337
|
+
}
|
|
338
|
+
case 'package': {
|
|
339
|
+
const left = -component.bodyWidth / 2;
|
|
340
|
+
const top = -component.bodyHeight / 2;
|
|
341
|
+
return `<path ${paint} d="M ${svgNumber(left)} ${svgNumber(top + 12)} V ${svgNumber(-top)} H ${svgNumber(-left)} V ${svgNumber(top)} H ${svgNumber(left + Math.min(54, component.bodyWidth / 2))} L ${svgNumber(left + Math.min(64, component.bodyWidth / 2 + 10))} ${svgNumber(top + 12)} Z" /><text class="schematic-uml-text" fill="currentColor" stroke="none" x="0" y="4" text-anchor="middle" font-size="13">${renderMathLabelTspans(component.label)}</text>`;
|
|
342
|
+
}
|
|
343
|
+
case 'initial':
|
|
344
|
+
return `<circle ${nodePaint} cx="0" cy="0" r="10" />`;
|
|
345
|
+
case 'final':
|
|
346
|
+
return `<circle ${paint} cx="0" cy="0" r="11" /><circle ${nodePaint} cx="0" cy="0" r="6" />`;
|
|
347
|
+
}
|
|
282
348
|
}
|
|
283
349
|
function componentShape(component, paint = colorAttributes(component.color), nodePaint = colorAttributes(component.color, 'schematic-node-fill')) {
|
|
284
350
|
if (isClassicalGate(component)) {
|
|
285
351
|
return component.standard === 'iec' ? iecGate(component, paint) : ieeeGate(component, paint);
|
|
286
352
|
}
|
|
353
|
+
if (isUmlComponent(component))
|
|
354
|
+
return umlComponentShape(component, paint, nodePaint);
|
|
287
355
|
switch (component.kind) {
|
|
288
356
|
case 'resistor':
|
|
289
357
|
return `<path ${paint} d="M -42 0 H -26 L -20 -12 L -10 12 L 0 -12 L 10 12 L 20 -12 L 26 0 H 42" />`;
|
|
@@ -310,7 +378,10 @@ function componentShape(component, paint = colorAttributes(component.color), nod
|
|
|
310
378
|
}
|
|
311
379
|
}
|
|
312
380
|
function reusableSymbolKey(component) {
|
|
313
|
-
if (isClassicalGate(component) ||
|
|
381
|
+
if (isClassicalGate(component) ||
|
|
382
|
+
isUmlComponent(component) ||
|
|
383
|
+
component.kind === 'qgate' ||
|
|
384
|
+
component.kind === 'ic') {
|
|
314
385
|
return undefined;
|
|
315
386
|
}
|
|
316
387
|
if (component.kind === 'diode')
|
|
@@ -332,16 +403,56 @@ function connectionMarkup(connection, routed, index, idPrefix, glowId) {
|
|
|
332
403
|
const target = escapeXml(`${connection.to.componentId}.${connection.to.port}`);
|
|
333
404
|
const traceId = `${idPrefix}-wire-${index}-vector`;
|
|
334
405
|
const dataAttributes = ` data-wire-source="${source}" data-wire-target="${target}"`;
|
|
335
|
-
const
|
|
406
|
+
const relation = connection.relation ?? 'signal';
|
|
407
|
+
const accessibility = ` tabindex="0" role="group" aria-label="${escapeXml(relation)} from ${source} to ${target}"`;
|
|
336
408
|
const vectorId = ` id="${traceId}"`;
|
|
337
409
|
const markerAttributes = connectionMarkerAttributes(connection, idPrefix);
|
|
338
410
|
const glow = `<use class="schematic-glow-layer" href="#${traceId}" filter="url(#${glowId})" aria-hidden="true" pointer-events="none" />`;
|
|
339
|
-
|
|
411
|
+
const endpoint = relation === 'signal' && connection.markerEnd === 'none'
|
|
412
|
+
? `<circle ${colorAttributes(connection.color, 'schematic-node-fill')} cx="${svgNumber(end.x)}" cy="${svgNumber(end.y)}" r="3" />`
|
|
413
|
+
: '';
|
|
414
|
+
return `<g class="schematic-wire"${dataAttributes}${accessibility}><path${vectorId} ${colorAttributes(connection.color, 'schematic-trace')} d="${routed.d}"${markerAttributes} />${glow}${endpoint}${connectionLabelMarkup(connection, routed)}</g>`;
|
|
340
415
|
}
|
|
341
416
|
function connectionMarkerAttributes(connection, idPrefix) {
|
|
342
417
|
const start = connection.markerStart;
|
|
343
418
|
const end = connection.markerEnd;
|
|
344
|
-
return `${start === 'none' ? '' : ` marker-start="url(#${idPrefix}-marker-${start})"`}${end === 'none' ? '' : ` marker-end="url(#${idPrefix}-marker-${end})"`}`;
|
|
419
|
+
return `${start === 'none' ? '' : ` marker-start="url(#${idPrefix}-marker-${start})"`}${end === 'none' ? '' : ` marker-end="url(#${idPrefix}-marker-${end})"`}${connection.dashed === true ? ' stroke-dasharray="7 5"' : ''}`;
|
|
420
|
+
}
|
|
421
|
+
function connectionLabelPoint(route) {
|
|
422
|
+
if (route.curve === 'bezier' && route.points.length >= 4) {
|
|
423
|
+
const a = route.points[0];
|
|
424
|
+
const b = route.points[1];
|
|
425
|
+
const c = route.points[2];
|
|
426
|
+
const d = route.points[3];
|
|
427
|
+
return {
|
|
428
|
+
x: (a.x + 3 * b.x + 3 * c.x + d.x) / 8,
|
|
429
|
+
y: (a.y + 3 * b.y + 3 * c.y + d.y) / 8
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
let total = 0;
|
|
433
|
+
for (let index = 1; index < route.points.length; index += 1) {
|
|
434
|
+
total +=
|
|
435
|
+
Math.abs(route.points[index].x - route.points[index - 1].x) +
|
|
436
|
+
Math.abs(route.points[index].y - route.points[index - 1].y);
|
|
437
|
+
}
|
|
438
|
+
let remaining = total / 2;
|
|
439
|
+
for (let index = 1; index < route.points.length; index += 1) {
|
|
440
|
+
const start = route.points[index - 1];
|
|
441
|
+
const end = route.points[index];
|
|
442
|
+
const length = Math.abs(end.x - start.x) + Math.abs(end.y - start.y);
|
|
443
|
+
if (remaining <= length) {
|
|
444
|
+
const ratio = length === 0 ? 0 : remaining / length;
|
|
445
|
+
return { x: start.x + (end.x - start.x) * ratio, y: start.y + (end.y - start.y) * ratio };
|
|
446
|
+
}
|
|
447
|
+
remaining -= length;
|
|
448
|
+
}
|
|
449
|
+
return route.points.at(-1);
|
|
450
|
+
}
|
|
451
|
+
function connectionLabelMarkup(connection, route) {
|
|
452
|
+
if (connection.label === undefined)
|
|
453
|
+
return '';
|
|
454
|
+
const point = connectionLabelPoint(route);
|
|
455
|
+
return `<text class="schematic-connection-label" fill="currentColor" stroke="none" x="${svgNumber(point.x)}" y="${svgNumber(point.y - 7)}" text-anchor="middle" font-size="11">${renderMathLabelTspans(connection.label)}</text>`;
|
|
345
456
|
}
|
|
346
457
|
function colorKey(color) {
|
|
347
458
|
return `${color.kind}:${color.value}`;
|
|
@@ -353,23 +464,29 @@ function compactConnectionMarkup(connections, routes, idPrefix, embedVisuals, gl
|
|
|
353
464
|
const key = `${colorKey(connection.color)}|${markerAttributes}`;
|
|
354
465
|
let batch = batches.get(key);
|
|
355
466
|
if (batch === undefined) {
|
|
356
|
-
batch = { color: connection.color, markerAttributes, traces: [], endpoints: [] };
|
|
467
|
+
batch = { color: connection.color, markerAttributes, traces: [], endpoints: [], labels: [] };
|
|
357
468
|
batches.set(key, batch);
|
|
358
469
|
}
|
|
359
470
|
const routed = routes[index];
|
|
360
471
|
const end = routed.points.at(-1);
|
|
361
472
|
batch.traces.push(routed.d);
|
|
362
|
-
|
|
473
|
+
if ((connection.relation ?? 'signal') === 'signal' && connection.markerEnd === 'none') {
|
|
474
|
+
batch.endpoints.push(`M ${svgNumber(end.x - 3)} ${svgNumber(end.y)} a 3 3 0 1 0 6 0 a 3 3 0 1 0 -6 0`);
|
|
475
|
+
}
|
|
476
|
+
const label = connectionLabelMarkup(connection, routed);
|
|
477
|
+
if (label !== '')
|
|
478
|
+
batch.labels.push(label);
|
|
363
479
|
}
|
|
364
480
|
return Array.from(batches.values(), (batch, index) => {
|
|
365
481
|
const tracePaint = colorAttributes(batch.color, 'schematic-trace');
|
|
366
482
|
const nodePaint = colorAttributes(batch.color, 'schematic-node-fill');
|
|
367
483
|
const traceId = `${idPrefix}-wire-batch-${index}-vector`;
|
|
368
484
|
const trace = `<path${embedVisuals ? ` id="${traceId}"` : ''} ${tracePaint} d="${batch.traces.join(' ')}"${batch.markerAttributes} />`;
|
|
369
|
-
const endpoints = `<path ${nodePaint} d="${batch.endpoints.join(' ')}" />`;
|
|
485
|
+
const endpoints = batch.endpoints.length === 0 ? '' : `<path ${nodePaint} d="${batch.endpoints.join(' ')}" />`;
|
|
486
|
+
const labels = batch.labels.join('');
|
|
370
487
|
if (!embedVisuals)
|
|
371
|
-
return trace + endpoints;
|
|
372
|
-
return `<g class="schematic-wire" tabindex="0" role="group" aria-label="${batch.traces.length} grouped
|
|
488
|
+
return trace + endpoints + labels;
|
|
489
|
+
return `<g class="schematic-wire" tabindex="0" role="group" aria-label="${batch.traces.length} grouped connection${batch.traces.length === 1 ? '' : 's'}">${trace}<use class="schematic-glow-layer" href="#${traceId}" filter="url(#${glowId})" aria-hidden="true" pointer-events="none" />${endpoints}${labels}</g>`;
|
|
373
490
|
}).join('');
|
|
374
491
|
}
|
|
375
492
|
function componentMetadata(component) {
|
|
@@ -424,12 +541,17 @@ function componentMarkup(component, index, idPrefix, glowId, mode, symbolId) {
|
|
|
424
541
|
const vector = symbolId === undefined
|
|
425
542
|
? `<g${vectorIdAttribute} class="schematic-component-vector">${componentShape(component)}</g>`
|
|
426
543
|
: `<use${vectorIdAttribute} ${colorAttributes(component.color, 'schematic-component-vector')} href="#${symbolId}" />`;
|
|
427
|
-
|
|
544
|
+
const externalLabels = isUmlComponent(component)
|
|
545
|
+
? ''
|
|
546
|
+
: `<text class="schematic-designator" fill="currentColor" stroke="none" x="0" y="${anchors.designatorY}" text-anchor="middle" font-size="12" textLength="${anchors.designatorWidth}" lengthAdjust="spacingAndGlyphs">${id}</text><text class="schematic-label" fill="currentColor" stroke="none" x="0" y="${anchors.labelY}" text-anchor="middle" font-size="12" textLength="${anchors.labelWidth}" lengthAdjust="spacingAndGlyphs">${renderedLabel}</text>`;
|
|
547
|
+
return `<g class="schematic-component"${dataAttributes} transform="translate(${svgNumber(component.x)} ${svgNumber(component.y)})"${accessibility}>${vector}${glow}${externalLabels}${hotspots}</g>`;
|
|
428
548
|
}
|
|
429
549
|
export function renderSchematic(document, options) {
|
|
430
550
|
assertParsedSchematicDocument(document);
|
|
431
551
|
const normalized = normalizeCompileOptions(options);
|
|
432
|
-
|
|
552
|
+
const components = new Map(document.components.map((component) => [component.id, component]));
|
|
553
|
+
const routedConnections = routeConnections(document.connections, components, normalized.bounds);
|
|
554
|
+
validateDocumentGeometry(document, normalized, routedConnections);
|
|
433
555
|
const signature = `${normalized.bounds.width}x${normalized.bounds.height}:${normalized.title}:${JSON.stringify(document)}`;
|
|
434
556
|
const candidatePrefix = (normalized.idPrefix ?? `schematic-${stableHash(signature)}`).replace(/[^A-Za-z0-9_-]/g, '-');
|
|
435
557
|
const safePrefix = /[A-Za-z0-9]/.test(candidatePrefix)
|
|
@@ -441,8 +563,6 @@ export function renderSchematic(document, options) {
|
|
|
441
563
|
const glowId = `${safePrefix}-schematic-glow-filter`;
|
|
442
564
|
const styles = normalized.mode === 'embedded-css' || normalized.mode === 'full';
|
|
443
565
|
const hooks = normalized.mode === 'full';
|
|
444
|
-
const components = new Map(document.components.map((component) => [component.id, component]));
|
|
445
|
-
const routedConnections = routeConnections(document.connections, components);
|
|
446
566
|
const reusableSymbols = new Map();
|
|
447
567
|
for (const component of document.components) {
|
|
448
568
|
const key = reusableSymbolKey(component);
|
|
@@ -452,7 +572,7 @@ export function renderSchematic(document, options) {
|
|
|
452
572
|
}
|
|
453
573
|
const title = escapeXml(normalized.title);
|
|
454
574
|
const componentCount = document.components.length;
|
|
455
|
-
const description = `${componentCount} component${componentCount === 1 ? '' : 's'} and ${document.connections.length}
|
|
575
|
+
const description = `${componentCount} component${componentCount === 1 ? '' : 's'} and ${document.connections.length} connection${document.connections.length === 1 ? '' : 's'}.`;
|
|
456
576
|
const writer = new BoundedSvgWriter();
|
|
457
577
|
const hookStyles = hooks ? HOOK_SVG_STYLES : '';
|
|
458
578
|
const interactionStyles = styles ? INTERACTIVE_SVG_STYLES : '';
|
|
@@ -461,7 +581,7 @@ export function renderSchematic(document, options) {
|
|
|
461
581
|
: '';
|
|
462
582
|
const symbolDefinitions = Array.from(reusableSymbols.values(), ({ id, component }) => reusableSymbolDefinition(component, id)).join('');
|
|
463
583
|
const usedMarkers = new Set(document.connections.flatMap((connection) => [connection.markerStart, connection.markerEnd]));
|
|
464
|
-
const markerDefinitions = `${usedMarkers.has('arrow') ? `<marker id="${safePrefix}-marker-arrow" viewBox="0 0 8 8" refX="
|
|
584
|
+
const markerDefinitions = `${usedMarkers.has('arrow') ? `<marker id="${safePrefix}-marker-arrow" viewBox="0 0 8 8" refX="8" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto-start-reverse" overflow="visible"><path d="M0 0 8 4 0 8Z" fill="context-stroke" /></marker>` : ''}${usedMarkers.has('open-arrow') ? `<marker id="${safePrefix}-marker-open-arrow" viewBox="0 0 9 10" refX="9" refY="5" markerWidth="9" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto-start-reverse" overflow="visible"><path d="M0 0 9 5 0 10" fill="none" stroke="context-stroke" stroke-width="1.5" /></marker>` : ''}${usedMarkers.has('dot') ? `<marker id="${safePrefix}-marker-dot" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse"><circle cx="4" cy="4" r="3" fill="context-stroke" /></marker>` : ''}${usedMarkers.has('triangle') ? `<marker id="${safePrefix}-marker-triangle" viewBox="0 0 12 12" refX="11" refY="6" markerWidth="12" markerHeight="12" markerUnits="userSpaceOnUse" orient="auto-start-reverse" overflow="visible"><path d="M0 1 11 6 0 11Z" fill="var(--schematic-surface,#fff)" stroke="context-stroke" stroke-width="1.5" /></marker>` : ''}${usedMarkers.has('diamond') ? `<marker id="${safePrefix}-marker-diamond" viewBox="0 0 13 12" refX="12" refY="6" markerWidth="13" markerHeight="12" markerUnits="userSpaceOnUse" orient="auto-start-reverse" overflow="visible"><path d="M0 6 6 1 12 6 6 11Z" fill="var(--schematic-surface,#fff)" stroke="context-stroke" stroke-width="1.5" /></marker>` : ''}${usedMarkers.has('diamond-filled') ? `<marker id="${safePrefix}-marker-diamond-filled" viewBox="0 0 13 12" refX="12" refY="6" markerWidth="13" markerHeight="12" markerUnits="userSpaceOnUse" orient="auto-start-reverse" overflow="visible"><path d="M0 6 6 1 12 6 6 11Z" fill="context-stroke" stroke="context-stroke" /></marker>` : ''}`;
|
|
465
585
|
const embeddedDefinitions = styles
|
|
466
586
|
? `<style>${STATIC_SVG_STYLES}${hookStyles}${interactionStyles}</style><pattern id="${gridId}" width="20" height="20" patternUnits="userSpaceOnUse"><path class="schematic-grid-line" d="M20 0H0V20" /></pattern>${glowFilter}`
|
|
467
587
|
: '';
|
package/dist/types.d.ts
CHANGED
|
@@ -35,8 +35,12 @@ export type ClassicalGateKind = (typeof CLASSICAL_GATE_KINDS)[number];
|
|
|
35
35
|
export declare const QUANTUM_GATE_KINDS: readonly ["hadamard", "cnot", "qgate"];
|
|
36
36
|
/** A supported native or polymorphic quantum gate keyword. */
|
|
37
37
|
export type QuantumGateKind = (typeof QUANTUM_GATE_KINDS)[number];
|
|
38
|
+
/** First-class UML node keywords spanning structural and behavioral diagrams. */
|
|
39
|
+
export declare const UML_COMPONENT_KINDS: readonly ["class", "actor", "usecase", "state", "lifeline", "note", "package", "initial", "final"];
|
|
40
|
+
/** A supported UML node keyword. */
|
|
41
|
+
export type UmlComponentKind = (typeof UML_COMPONENT_KINDS)[number];
|
|
38
42
|
/** Complete, collision-free component keyword registry. */
|
|
39
|
-
export declare const COMPONENT_KINDS: readonly ["resistor", "capacitor", "inductor", "diode", "transistor", "port", "ground", "nand", "nor", "xor", "and", "or", "not", "hadamard", "cnot", "qgate", "ic"];
|
|
43
|
+
export declare const COMPONENT_KINDS: readonly ["resistor", "capacitor", "inductor", "diode", "transistor", "port", "ground", "nand", "nor", "xor", "and", "or", "not", "hadamard", "cnot", "qgate", "class", "actor", "usecase", "state", "lifeline", "note", "package", "initial", "final", "ic"];
|
|
40
44
|
/** Any component keyword that can begin a declaration. */
|
|
41
45
|
export type ComponentKind = (typeof COMPONENT_KINDS)[number];
|
|
42
46
|
/** Built-in semantic color tokens that hosts can theme through CSS. */
|
|
@@ -169,8 +173,53 @@ export interface IcComponent extends ComponentBase {
|
|
|
169
173
|
}
|
|
170
174
|
/** Descriptive alias for a parsed integrated-circuit block. */
|
|
171
175
|
export type IntegratedCircuitComponent = IcComponent;
|
|
176
|
+
/** Parsed UML class with independently sized attribute and operation compartments. */
|
|
177
|
+
export interface UmlClassComponent extends ComponentBase {
|
|
178
|
+
/** UML class node discriminant. */
|
|
179
|
+
kind: 'class';
|
|
180
|
+
/** Optional stereotype displayed above the class name. */
|
|
181
|
+
stereotype?: string;
|
|
182
|
+
/** Attribute declarations in source order. */
|
|
183
|
+
attributes: readonly string[];
|
|
184
|
+
/** Operation declarations in source order. */
|
|
185
|
+
operations: readonly string[];
|
|
186
|
+
/** Deterministic box width derived from all visible rows. */
|
|
187
|
+
bodyWidth: number;
|
|
188
|
+
/** Deterministic three-compartment box height. */
|
|
189
|
+
bodyHeight: number;
|
|
190
|
+
}
|
|
191
|
+
/** Parsed UML state with optional behavior rows. */
|
|
192
|
+
export interface UmlStateComponent extends ComponentBase {
|
|
193
|
+
kind: 'state';
|
|
194
|
+
/** Entry, do, exit, or author-defined behavior rows. */
|
|
195
|
+
details: readonly string[];
|
|
196
|
+
bodyWidth: number;
|
|
197
|
+
bodyHeight: number;
|
|
198
|
+
}
|
|
199
|
+
/** Parsed UML ellipse, note, package, or sequence lifeline. */
|
|
200
|
+
export interface UmlSizedComponent extends ComponentBase {
|
|
201
|
+
kind: 'usecase' | 'lifeline' | 'note' | 'package';
|
|
202
|
+
bodyWidth: number;
|
|
203
|
+
bodyHeight: number;
|
|
204
|
+
}
|
|
205
|
+
/** Parsed UML actor figure. */
|
|
206
|
+
export interface UmlActorComponent extends ComponentBase {
|
|
207
|
+
kind: 'actor';
|
|
208
|
+
}
|
|
209
|
+
/** Parsed UML initial or final pseudostate. */
|
|
210
|
+
export interface UmlPseudostateComponent extends ComponentBase {
|
|
211
|
+
kind: 'initial' | 'final';
|
|
212
|
+
}
|
|
213
|
+
/** Every UML component accepted by the compiler. */
|
|
214
|
+
export type UmlComponent = UmlClassComponent | UmlStateComponent | UmlSizedComponent | UmlActorComponent | UmlPseudostateComponent;
|
|
172
215
|
/** Discriminated union of every component node accepted by the renderer. */
|
|
173
|
-
export type SchematicComponent = PassiveComponent | DiodeComponent | TransistorComponent | PortComponent | GroundComponent | ClassicalGateComponent | QuantumGateComponent | IcComponent;
|
|
216
|
+
export type SchematicComponent = PassiveComponent | DiodeComponent | TransistorComponent | PortComponent | GroundComponent | ClassicalGateComponent | QuantumGateComponent | IcComponent | UmlComponent;
|
|
217
|
+
/** UML relationship semantics used to derive line style and endpoint markers. */
|
|
218
|
+
export declare const UML_RELATION_KINDS: readonly ["association", "dependency", "generalization", "realization", "aggregation", "composition", "message", "transition", "include", "extend"];
|
|
219
|
+
/** A supported UML relationship. */
|
|
220
|
+
export type UmlRelationKind = (typeof UML_RELATION_KINDS)[number];
|
|
221
|
+
/** Electrical signal or a first-class UML relationship. */
|
|
222
|
+
export type SchematicRelationKind = 'signal' | UmlRelationKind;
|
|
174
223
|
/** Address of one component terminal in a connection declaration. */
|
|
175
224
|
export interface SchematicEndpoint {
|
|
176
225
|
/** Document-local component identifier. */
|
|
@@ -192,6 +241,12 @@ export interface SchematicConnection {
|
|
|
192
241
|
markerStart: SchematicSignalMarker;
|
|
193
242
|
/** Optional marker drawn at the destination terminal. */
|
|
194
243
|
markerEnd: SchematicSignalMarker;
|
|
244
|
+
/** Electrical or UML relationship semantics. */
|
|
245
|
+
relation?: SchematicRelationKind;
|
|
246
|
+
/** Optional text centered beside the routed connector. */
|
|
247
|
+
label?: string;
|
|
248
|
+
/** Whether the trace uses the UML dependency dash pattern. */
|
|
249
|
+
dashed?: boolean;
|
|
195
250
|
/** One-based source line used for routing diagnostics. */
|
|
196
251
|
line: number;
|
|
197
252
|
}
|
|
@@ -207,7 +262,7 @@ export declare const SCHEMD_OUTPUT_MODES: readonly ["default", "embedded-css", "
|
|
|
207
262
|
/** Static, CSS-enhanced, or fully attributed SVG output mode. */
|
|
208
263
|
export type SchemdOutputMode = (typeof SCHEMD_OUTPUT_MODES)[number];
|
|
209
264
|
/** Marker primitives that can terminate or originate a signal trace. */
|
|
210
|
-
export declare const SCHEMATIC_SIGNAL_MARKERS: readonly ["none", "arrow", "dot"];
|
|
265
|
+
export declare const SCHEMATIC_SIGNAL_MARKERS: readonly ["none", "arrow", "open-arrow", "dot", "triangle", "diamond", "diamond-filled"];
|
|
211
266
|
/** A validated connection marker selection. */
|
|
212
267
|
export type SchematicSignalMarker = (typeof SCHEMATIC_SIGNAL_MARKERS)[number];
|
|
213
268
|
/** Per-render options extending the fence's intrinsic layout contract. */
|
package/dist/types.js
CHANGED
|
@@ -5,16 +5,48 @@ export const TRANSISTOR_TYPES = ['npn', 'pnp', 'nmos', 'pmos'];
|
|
|
5
5
|
export const GROUND_STYLES = ['chassis', 'earth', 'signal'];
|
|
6
6
|
export const CLASSICAL_GATE_KINDS = ['nand', 'nor', 'xor', 'and', 'or', 'not'];
|
|
7
7
|
export const QUANTUM_GATE_KINDS = ['hadamard', 'cnot', 'qgate'];
|
|
8
|
+
export const UML_COMPONENT_KINDS = [
|
|
9
|
+
'class',
|
|
10
|
+
'actor',
|
|
11
|
+
'usecase',
|
|
12
|
+
'state',
|
|
13
|
+
'lifeline',
|
|
14
|
+
'note',
|
|
15
|
+
'package',
|
|
16
|
+
'initial',
|
|
17
|
+
'final'
|
|
18
|
+
];
|
|
8
19
|
export const COMPONENT_KINDS = [
|
|
9
20
|
...PASSIVE_KINDS,
|
|
10
21
|
...ANALOG_KINDS,
|
|
11
22
|
...CLASSICAL_GATE_KINDS,
|
|
12
23
|
...QUANTUM_GATE_KINDS,
|
|
24
|
+
...UML_COMPONENT_KINDS,
|
|
13
25
|
'ic'
|
|
14
26
|
];
|
|
15
27
|
export const SEMANTIC_COLORS = ['amber', 'blue', 'cyan', 'purple', 'slate', 'emerald'];
|
|
28
|
+
export const UML_RELATION_KINDS = [
|
|
29
|
+
'association',
|
|
30
|
+
'dependency',
|
|
31
|
+
'generalization',
|
|
32
|
+
'realization',
|
|
33
|
+
'aggregation',
|
|
34
|
+
'composition',
|
|
35
|
+
'message',
|
|
36
|
+
'transition',
|
|
37
|
+
'include',
|
|
38
|
+
'extend'
|
|
39
|
+
];
|
|
16
40
|
export const SCHEMD_OUTPUT_MODES = ['default', 'embedded-css', 'full'];
|
|
17
|
-
export const SCHEMATIC_SIGNAL_MARKERS = [
|
|
41
|
+
export const SCHEMATIC_SIGNAL_MARKERS = [
|
|
42
|
+
'none',
|
|
43
|
+
'arrow',
|
|
44
|
+
'open-arrow',
|
|
45
|
+
'dot',
|
|
46
|
+
'triangle',
|
|
47
|
+
'diamond',
|
|
48
|
+
'diamond-filled'
|
|
49
|
+
];
|
|
18
50
|
export class SchematicSyntaxError extends Error {
|
|
19
51
|
line;
|
|
20
52
|
constructor(message, line) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schemd/core",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Zero-dependency text-to-SVG compiler for schematics and UML.",
|
|
5
5
|
"homepage": "https://johnowolabiidogun.dev/tools/schemd/docs/overview",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/Sirneij/schemd/issues"
|
|
@@ -23,6 +23,30 @@
|
|
|
23
23
|
".": {
|
|
24
24
|
"types": "./dist/index.d.ts",
|
|
25
25
|
"import": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./parser": {
|
|
28
|
+
"types": "./dist/parser.d.ts",
|
|
29
|
+
"import": "./dist/parser.js"
|
|
30
|
+
},
|
|
31
|
+
"./renderer": {
|
|
32
|
+
"types": "./dist/renderer.d.ts",
|
|
33
|
+
"import": "./dist/renderer.js"
|
|
34
|
+
},
|
|
35
|
+
"./layout": {
|
|
36
|
+
"types": "./dist/layout.d.ts",
|
|
37
|
+
"import": "./dist/layout.js"
|
|
38
|
+
},
|
|
39
|
+
"./math-label": {
|
|
40
|
+
"types": "./dist/math-label.d.ts",
|
|
41
|
+
"import": "./dist/math-label.js"
|
|
42
|
+
},
|
|
43
|
+
"./marked": {
|
|
44
|
+
"types": "./dist/marked-extension.d.ts",
|
|
45
|
+
"import": "./dist/marked-extension.js"
|
|
46
|
+
},
|
|
47
|
+
"./types": {
|
|
48
|
+
"types": "./dist/types.d.ts",
|
|
49
|
+
"import": "./dist/types.js"
|
|
26
50
|
}
|
|
27
51
|
},
|
|
28
52
|
"scripts": {
|
|
@@ -35,6 +59,11 @@
|
|
|
35
59
|
"peerDependencies": {
|
|
36
60
|
"marked": ">=17 <19"
|
|
37
61
|
},
|
|
62
|
+
"peerDependenciesMeta": {
|
|
63
|
+
"marked": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
66
|
+
},
|
|
38
67
|
"devDependencies": {
|
|
39
68
|
"@vitest/coverage-v8": "^4.1.10",
|
|
40
69
|
"marked": "^18.0.6",
|
|
@@ -50,7 +79,8 @@
|
|
|
50
79
|
"schematic",
|
|
51
80
|
"svg",
|
|
52
81
|
"compiler",
|
|
53
|
-
"engineering"
|
|
82
|
+
"engineering",
|
|
83
|
+
"uml"
|
|
54
84
|
],
|
|
55
85
|
"license": "MIT"
|
|
56
86
|
}
|