sysml-diagram 0.23.0 → 0.24.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/out/main.js +304 -29
- package/out/main.js.map +3 -3
- package/package.json +1 -1
- package/resources/sysml.dimension-table.json +1 -1
package/out/main.js
CHANGED
|
@@ -162474,6 +162474,35 @@ function connectionEndMultiplicity(node) {
|
|
|
162474
162474
|
return void 0;
|
|
162475
162475
|
return hi == null || hi === lo ? `[${lo}]` : `[${lo}..${hi}]`;
|
|
162476
162476
|
}
|
|
162477
|
+
function isEmptyPrefixFlow(node) {
|
|
162478
|
+
const fm = node;
|
|
162479
|
+
return node.$type === "FlowStmt" && fm.target !== void 0 && fm.source === void 0;
|
|
162480
|
+
}
|
|
162481
|
+
function flowStmtName(node) {
|
|
162482
|
+
return isEmptyPrefixFlow(node) ? void 0 : effectiveNameOf(node);
|
|
162483
|
+
}
|
|
162484
|
+
function flowKeyword(fm) {
|
|
162485
|
+
return `${fm.succession === true ? "succession " : ""}${fm.flowKind === "message" ? "message" : "flow"}`;
|
|
162486
|
+
}
|
|
162487
|
+
function flowTransferredFeature(ends) {
|
|
162488
|
+
const sourceFeature = ends.source ? lastSeg(ends.source) : void 0;
|
|
162489
|
+
const targetFeature = ends.target ? lastSeg(ends.target) : void 0;
|
|
162490
|
+
return sourceFeature === targetFeature ? sourceFeature : sourceFeature ?? targetFeature;
|
|
162491
|
+
}
|
|
162492
|
+
function flowDecorationMeta(carried) {
|
|
162493
|
+
const drawn = carried.filter((flow) => !flow.message);
|
|
162494
|
+
if (!drawn.length)
|
|
162495
|
+
return {};
|
|
162496
|
+
return {
|
|
162497
|
+
flowDecorations: drawn.map(({ keyword, label, name, reversed, row }) => ({
|
|
162498
|
+
keyword,
|
|
162499
|
+
...label ? { label } : {},
|
|
162500
|
+
...name ? { name } : {},
|
|
162501
|
+
reversed,
|
|
162502
|
+
...row.source ? { source: row.source } : {}
|
|
162503
|
+
}))
|
|
162504
|
+
};
|
|
162505
|
+
}
|
|
162477
162506
|
var END_PROPERTY_ADORNMENTS = /* @__PURE__ */ new Set(["abstract", "derived", "readonly", "ordered", "nonunique"]);
|
|
162478
162507
|
var uniqueStrings = (values2) => [...new Set([...values2].filter((value) => !!value))];
|
|
162479
162508
|
function formatConnectionEndAdornment(notation) {
|
|
@@ -164919,6 +164948,27 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
164919
164948
|
}
|
|
164920
164949
|
return { source: void 0, target: fm.target ? String(fm.target) : void 0 };
|
|
164921
164950
|
}
|
|
164951
|
+
// REQ-401 — the `flows-compartment` row of one flow or message usage (OMG
|
|
164952
|
+
// SysML 8.2.3.16). Rebuilt from the declaration instead of copied from the
|
|
164953
|
+
// source text, because a flow may carry a BODY (`flow a.x to b.y { doc ... }`)
|
|
164954
|
+
// whose whole text would otherwise be inlined into one compartment row.
|
|
164955
|
+
// `ends` overrides the declared endpoints with the concrete ones a relationship
|
|
164956
|
+
// usage rebinds them to (REQ-402).
|
|
164957
|
+
// REQ-401 — Flow notation: on-connection decoration, port docking, and the flow usage node
|
|
164958
|
+
flowRowText(flow, ends) {
|
|
164959
|
+
const fm = flow;
|
|
164960
|
+
const declared = ends ?? this.flowStmtEnds(fm);
|
|
164961
|
+
const type = typeText(flow);
|
|
164962
|
+
const payload = this.flowPayloadText(fm);
|
|
164963
|
+
return [
|
|
164964
|
+
flowKeyword(fm),
|
|
164965
|
+
flowStmtName(flow),
|
|
164966
|
+
type ? `: ${type}` : void 0,
|
|
164967
|
+
payload ? `of ${payload}` : void 0,
|
|
164968
|
+
declared.source ? `from ${declared.source}` : void 0,
|
|
164969
|
+
declared.target ? `to ${declared.target}` : void 0
|
|
164970
|
+
].filter(Boolean).join(" ");
|
|
164971
|
+
}
|
|
164922
164972
|
// Payload text of a flow/message (`of Fuel` / `of f : Fuel`) per OMG SysML
|
|
164923
164973
|
// 8.2.2.16 PayloadFeature.
|
|
164924
164974
|
flowPayloadText(fm) {
|
|
@@ -164928,6 +164978,87 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
164928
164978
|
const typeRef = p.type?.$refText ?? p.typing?.type?.$refText;
|
|
164929
164979
|
return typeRef ? lastSeg(typeRef) : p.name;
|
|
164930
164980
|
}
|
|
164981
|
+
// REQ-402 — the flows a connection or interface usage CARRIES. A flow declared
|
|
164982
|
+
// in a `connection def` / `interface def` body (OMG SysML 8.2.3.16, and the
|
|
164983
|
+
// `Flow Interface Example` of the training corpus) is transported by every
|
|
164984
|
+
// usage of that definition; it is not a transfer of its own between two
|
|
164985
|
+
// unrelated features. Each end path is rebound through the usage's own end
|
|
164986
|
+
// bindings, so the definition-local `supplierPort.fuelSupply` reads as the
|
|
164987
|
+
// concrete `tankAssy.fuelTankPort.fuelSupply` this usage connects, and the
|
|
164988
|
+
// transfer direction is expressed relative to the usage's own end ordinals so
|
|
164989
|
+
// it survives whichever notation the relationship is drawn in.
|
|
164990
|
+
// REQ-402 — Flows carried by a connection or interface usage
|
|
164991
|
+
carriedFlowsOf(usage, ends, index2, uri) {
|
|
164992
|
+
const ordinalByRole = /* @__PURE__ */ new Map();
|
|
164993
|
+
const pathByRole = /* @__PURE__ */ new Map();
|
|
164994
|
+
for (const end of ends) {
|
|
164995
|
+
const role = end.notation.role;
|
|
164996
|
+
if (!role)
|
|
164997
|
+
continue;
|
|
164998
|
+
if (!ordinalByRole.has(role))
|
|
164999
|
+
ordinalByRole.set(role, end.ordinal);
|
|
165000
|
+
if (end.path && !pathByRole.has(role))
|
|
165001
|
+
pathByRole.set(role, end.path);
|
|
165002
|
+
}
|
|
165003
|
+
const rebind = (path10) => {
|
|
165004
|
+
if (!path10)
|
|
165005
|
+
return void 0;
|
|
165006
|
+
const segs = path10.split(".");
|
|
165007
|
+
const bound = pathByRole.get(segs[0]);
|
|
165008
|
+
return bound ? [bound, ...segs.slice(1)].join(".") : path10;
|
|
165009
|
+
};
|
|
165010
|
+
const carried = [];
|
|
165011
|
+
const seen = /* @__PURE__ */ new Set();
|
|
165012
|
+
for (const source of [usage, ...this.inheritedFeatureOwnersOf(usage, index2)]) {
|
|
165013
|
+
for (const member of membersOf(source)) {
|
|
165014
|
+
if (member.$type !== "FlowStmt" || member.isDef === true)
|
|
165015
|
+
continue;
|
|
165016
|
+
const fm = member;
|
|
165017
|
+
const flowEnds = this.flowStmtEnds(fm);
|
|
165018
|
+
const name = flowStmtName(member);
|
|
165019
|
+
const payload = this.flowPayloadText(fm);
|
|
165020
|
+
const key = name ?? `\0${flowEnds.source ?? ""}\0${flowEnds.target ?? ""}\0${payload ?? typeText(member) ?? ""}`;
|
|
165021
|
+
if (seen.has(key))
|
|
165022
|
+
continue;
|
|
165023
|
+
seen.add(key);
|
|
165024
|
+
const fromOrdinal = flowEnds.source ? ordinalByRole.get(flowEnds.source.split(".")[0]) : void 0;
|
|
165025
|
+
const from = rebind(flowEnds.source);
|
|
165026
|
+
const to = rebind(flowEnds.target);
|
|
165027
|
+
carried.push({
|
|
165028
|
+
flow: member,
|
|
165029
|
+
keyword: flowKeyword(fm),
|
|
165030
|
+
label: payload ?? typeText(member) ?? flowTransferredFeature(flowEnds),
|
|
165031
|
+
name,
|
|
165032
|
+
// The decoration rides the relationship, whose drawn direction
|
|
165033
|
+
// runs from its first end to its second.
|
|
165034
|
+
reversed: fromOrdinal !== void 0 && fromOrdinal > 0,
|
|
165035
|
+
inherited: source !== usage,
|
|
165036
|
+
message: fm.flowKind === "message",
|
|
165037
|
+
row: {
|
|
165038
|
+
text: this.flowRowText(member, { source: from, target: to }),
|
|
165039
|
+
source: sourceOf2(member, uri)
|
|
165040
|
+
}
|
|
165041
|
+
});
|
|
165042
|
+
}
|
|
165043
|
+
}
|
|
165044
|
+
return carried;
|
|
165045
|
+
}
|
|
165046
|
+
// REQ-402 — merge the transfers a relationship usage carries from its
|
|
165047
|
+
// definitions into the `flows` compartment its own body already contributes,
|
|
165048
|
+
// so one heading holds every transfer the usage transports.
|
|
165049
|
+
// REQ-402 — Flows carried by a connection or interface usage
|
|
165050
|
+
withCarriedFlowRows(compartments, carried) {
|
|
165051
|
+
const rows = carried.filter((flow) => flow.inherited).map((flow) => flow.row);
|
|
165052
|
+
if (!rows.length)
|
|
165053
|
+
return compartments;
|
|
165054
|
+
const out = [...compartments ?? []];
|
|
165055
|
+
const existing = out.findIndex((compartment) => compartment.title === "flows");
|
|
165056
|
+
if (existing >= 0)
|
|
165057
|
+
out[existing] = { ...out[existing], items: [...out[existing].items, ...rows] };
|
|
165058
|
+
else
|
|
165059
|
+
out.push({ title: "flows", items: rows });
|
|
165060
|
+
return out;
|
|
165061
|
+
}
|
|
164931
165062
|
// REQ-192/360/363 — the ONE recursive Interconnection View renderer. Given the
|
|
164932
165063
|
// top-level `roots` to draw, it renders each part instance and nests its
|
|
164933
165064
|
// internals recursively, drilling into a usage's type DEFINITION (+
|
|
@@ -164976,7 +165107,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
164976
165107
|
for (const source of [part, ...this.inheritedFeatureOwnersOf(part, index2)]) {
|
|
164977
165108
|
for (const member of membersOf(source)) {
|
|
164978
165109
|
const relationship = member;
|
|
164979
|
-
const emptyPrefixFlow = member
|
|
165110
|
+
const emptyPrefixFlow = isEmptyPrefixFlow(member);
|
|
164980
165111
|
const emptyPrefixInterface = isInterfaceDecl(member) && relationship.target !== void 0 && relationship.connect === void 0;
|
|
164981
165112
|
const namedRelationship = isConnectorDecl(member) || isConnectionDecl(member) || isInterfaceDecl(member) && !emptyPrefixInterface || member.$type === "BindingDecl" || member.$type === "FlowStmt" && !emptyPrefixFlow;
|
|
164982
165113
|
if (namedRelationship) {
|
|
@@ -165334,6 +165465,8 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165334
165465
|
// synthetic n-ary dot with that container's frame id).
|
|
165335
165466
|
emitInterconnectEdges(members, resolveEnd, parts, index2, uri, nodes, edges, eRef, frameId, actionPinIds = /* @__PURE__ */ new Set(), structuralPortIds = /* @__PURE__ */ new Set(), memberOwner, memberOwnerInherited = false, endpointProvenance = /* @__PURE__ */ new Map()) {
|
|
165336
165467
|
const memberList2 = [...members];
|
|
165468
|
+
const pendingFlows = [];
|
|
165469
|
+
const firstEdge = edges.length;
|
|
165337
165470
|
const relationshipFields = (source) => {
|
|
165338
165471
|
let directMember = source;
|
|
165339
165472
|
while (directMember.$container && directMember.$container !== memberOwner) {
|
|
@@ -165488,22 +165621,8 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165488
165621
|
}
|
|
165489
165622
|
}
|
|
165490
165623
|
} else if (m.$type === "FlowStmt") {
|
|
165491
|
-
|
|
165492
|
-
|
|
165493
|
-
continue;
|
|
165494
|
-
const { source, target } = this.flowStmtEnds(fm);
|
|
165495
|
-
const from = resolveEnd(source ?? "");
|
|
165496
|
-
const to = resolveEnd(target ?? "");
|
|
165497
|
-
if (from && to && supportsEndpoints("flow", [from, to])) {
|
|
165498
|
-
edges.push({
|
|
165499
|
-
id: `e${eRef.n++}`,
|
|
165500
|
-
from,
|
|
165501
|
-
to,
|
|
165502
|
-
kind: "flow",
|
|
165503
|
-
label: this.flowPayloadText(fm) ?? typeText(m) ?? nameOf2(m),
|
|
165504
|
-
...relationshipFields(m)
|
|
165505
|
-
});
|
|
165506
|
-
}
|
|
165624
|
+
if (m.isDef !== true)
|
|
165625
|
+
pendingFlows.push(m);
|
|
165507
165626
|
} else if (m.$type === "BindStmt" || m.$type === "BindingConnectorStmt" || m.$type === "BindingDecl") {
|
|
165508
165627
|
const bn = m;
|
|
165509
165628
|
const leftEnd = bn.left ?? bn.source;
|
|
@@ -165591,6 +165710,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165591
165710
|
}
|
|
165592
165711
|
};
|
|
165593
165712
|
});
|
|
165713
|
+
const carriedFlows = this.carriedFlowsOf(m, usageEnds, index2, uri);
|
|
165594
165714
|
nodes.push({
|
|
165595
165715
|
id: usageId,
|
|
165596
165716
|
name: name ?? ANONYMOUS_INTERFACE_NAME,
|
|
@@ -165601,12 +165721,13 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165601
165721
|
multiplicity: multText(m),
|
|
165602
165722
|
ports,
|
|
165603
165723
|
...usageFrame ? { frame: usageFrame } : {},
|
|
165604
|
-
compartments: this.compartmentsFor(m, uri, index2),
|
|
165724
|
+
compartments: this.withCarriedFlowRows(this.compartmentsFor(m, uri, index2), carriedFlows),
|
|
165605
165725
|
source: usageSource,
|
|
165606
165726
|
meta: {
|
|
165607
165727
|
...relationship.meta ?? {},
|
|
165608
165728
|
interfaceUsage: true,
|
|
165609
|
-
...name ? { explicitRelationshipName: name } : {}
|
|
165729
|
+
...name ? { explicitRelationshipName: name } : {},
|
|
165730
|
+
...flowDecorationMeta(carriedFlows)
|
|
165610
165731
|
}
|
|
165611
165732
|
});
|
|
165612
165733
|
for (const { end, ordinal, targetId } of visibleUsageEnds) {
|
|
@@ -165675,6 +165796,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165675
165796
|
}
|
|
165676
165797
|
};
|
|
165677
165798
|
});
|
|
165799
|
+
const carriedFlows = this.carriedFlowsOf(m, usageEnds, index2, uri);
|
|
165678
165800
|
nodes.push({
|
|
165679
165801
|
id: usageId,
|
|
165680
165802
|
name: name ?? "connection",
|
|
@@ -165684,12 +165806,13 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165684
165806
|
type,
|
|
165685
165807
|
ports,
|
|
165686
165808
|
...usageFrame ? { frame: usageFrame } : {},
|
|
165687
|
-
compartments: this.compartmentsFor(m, uri, index2),
|
|
165809
|
+
compartments: this.withCarriedFlowRows(this.compartmentsFor(m, uri, index2), carriedFlows),
|
|
165688
165810
|
source: usageSource,
|
|
165689
165811
|
meta: {
|
|
165690
165812
|
...relationship.meta ?? {},
|
|
165691
165813
|
connectionUsage: true,
|
|
165692
|
-
...name ? { explicitRelationshipName: name } : {}
|
|
165814
|
+
...name ? { explicitRelationshipName: name } : {},
|
|
165815
|
+
...flowDecorationMeta(carriedFlows)
|
|
165693
165816
|
}
|
|
165694
165817
|
});
|
|
165695
165818
|
for (const { end, ordinal, targetId } of visibleUsageEnds) {
|
|
@@ -165717,6 +165840,92 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
165717
165840
|
}
|
|
165718
165841
|
}
|
|
165719
165842
|
}
|
|
165843
|
+
const resolveFlowEnd = (pathText) => {
|
|
165844
|
+
const direct = resolveEnd(pathText);
|
|
165845
|
+
if (direct)
|
|
165846
|
+
return { id: direct, docked: false };
|
|
165847
|
+
const parts2 = pathText.split(/(::|\.)/u).filter((part) => part.length > 0);
|
|
165848
|
+
for (let length2 = parts2.length - 2; length2 >= 1; length2 -= 2) {
|
|
165849
|
+
const carrier = resolveEnd(parts2.slice(0, length2).join(""));
|
|
165850
|
+
if (carrier)
|
|
165851
|
+
return { id: carrier, docked: true };
|
|
165852
|
+
}
|
|
165853
|
+
return void 0;
|
|
165854
|
+
};
|
|
165855
|
+
const transportFor = (from, to) => edges.slice(firstEdge).find((edge) => (edge.kind === "connect" || edge.kind === "interface") && (edge.from === from && edge.to === to || edge.from === to && edge.to === from));
|
|
165856
|
+
const flowUsageNodeId = (flow) => {
|
|
165857
|
+
const src = sourceOf2(flow, uri);
|
|
165858
|
+
const ownerId = frameId ?? (qnameOf(memberOwner ?? flow) || "iv");
|
|
165859
|
+
const suffix = (frameId ? flowStmtName(flow) : qnameOf(flow)) ?? (src ? `${src.range.start.line}_${src.range.start.character}` : `${eRef.n}`);
|
|
165860
|
+
return `${ownerId}::__flow_${suffix}`;
|
|
165861
|
+
};
|
|
165862
|
+
for (const m of pendingFlows) {
|
|
165863
|
+
const fm = m;
|
|
165864
|
+
const message = fm.flowKind === "message";
|
|
165865
|
+
const keyword = flowKeyword(fm);
|
|
165866
|
+
const { source, target } = this.flowStmtEnds(fm);
|
|
165867
|
+
const flowName = flowStmtName(m);
|
|
165868
|
+
const sourceEnd = message ? void 0 : resolveFlowEnd(source ?? "");
|
|
165869
|
+
const targetEnd = message ? void 0 : resolveFlowEnd(target ?? "");
|
|
165870
|
+
const selfDock = sourceEnd !== void 0 && sourceEnd.id === targetEnd?.id && (sourceEnd.docked || targetEnd.docked);
|
|
165871
|
+
const from = selfDock ? void 0 : sourceEnd?.id;
|
|
165872
|
+
const to = selfDock ? void 0 : targetEnd?.id;
|
|
165873
|
+
const transferred = flowTransferredFeature({ source, target });
|
|
165874
|
+
const label = this.flowPayloadText(fm) ?? typeText(m) ?? transferred ?? flowName;
|
|
165875
|
+
if (from && to && supportsEndpoints("flow", [from, to])) {
|
|
165876
|
+
const transport = transportFor(from, to);
|
|
165877
|
+
if (transport) {
|
|
165878
|
+
const decorations = Array.isArray(transport.meta?.flowDecorations) ? transport.meta.flowDecorations : [];
|
|
165879
|
+
transport.meta = {
|
|
165880
|
+
...transport.meta ?? {},
|
|
165881
|
+
flowDecorations: [...decorations, {
|
|
165882
|
+
keyword,
|
|
165883
|
+
label,
|
|
165884
|
+
...flowName ? { name: flowName } : {},
|
|
165885
|
+
reversed: transport.from === to,
|
|
165886
|
+
source: sourceOf2(m, uri)
|
|
165887
|
+
}]
|
|
165888
|
+
};
|
|
165889
|
+
continue;
|
|
165890
|
+
}
|
|
165891
|
+
edges.push({
|
|
165892
|
+
id: `e${eRef.n++}`,
|
|
165893
|
+
from,
|
|
165894
|
+
to,
|
|
165895
|
+
kind: "flow",
|
|
165896
|
+
label,
|
|
165897
|
+
...relationshipFields(m)
|
|
165898
|
+
});
|
|
165899
|
+
continue;
|
|
165900
|
+
}
|
|
165901
|
+
if (message || !flowName)
|
|
165902
|
+
continue;
|
|
165903
|
+
const ownerNode = frameId ? nodes.find((node) => node.id === frameId) : void 0;
|
|
165904
|
+
const ends = [
|
|
165905
|
+
...source ? [{ text: `from ${source}` }] : [],
|
|
165906
|
+
...target ? [{ text: `to ${target}` }] : []
|
|
165907
|
+
];
|
|
165908
|
+
nodes.push({
|
|
165909
|
+
id: flowUsageNodeId(m),
|
|
165910
|
+
name: flowName,
|
|
165911
|
+
keyword,
|
|
165912
|
+
isDef: false,
|
|
165913
|
+
shape: "box",
|
|
165914
|
+
type: typeText(m),
|
|
165915
|
+
multiplicity: multText(m),
|
|
165916
|
+
...ownerNode ? { frame: ownerNode.frame } : frameId ? { frame: frameId } : {},
|
|
165917
|
+
compartments: [
|
|
165918
|
+
...label ? [{ title: "payload", items: [{ text: label }] }] : [],
|
|
165919
|
+
...ends.length ? [{ title: "ends", items: ends }] : []
|
|
165920
|
+
],
|
|
165921
|
+
source: sourceOf2(m, uri),
|
|
165922
|
+
meta: {
|
|
165923
|
+
...relationshipFields(m).meta ?? {},
|
|
165924
|
+
flowUsage: true,
|
|
165925
|
+
explicitRelationshipName: flowName
|
|
165926
|
+
}
|
|
165927
|
+
});
|
|
165928
|
+
}
|
|
165720
165929
|
}
|
|
165721
165930
|
// ── iv overview (REQ-360) — recursive nested Interconnection View over a
|
|
165722
165931
|
// package. The hierarchy follows COMPOSITION, not text layout: the roots are
|
|
@@ -167077,9 +167286,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
167077
167286
|
const to = resolvePin(ends.target, occurrenceContext);
|
|
167078
167287
|
if (from && to) {
|
|
167079
167288
|
const kind = fm.succession === true ? "successionFlow" : "flow";
|
|
167080
|
-
const
|
|
167081
|
-
const targetFeature = ends.target ? lastSeg(ends.target) : void 0;
|
|
167082
|
-
const transferredFeature = sourceFeature === targetFeature ? sourceFeature : sourceFeature ?? targetFeature;
|
|
167289
|
+
const transferredFeature = flowTransferredFeature(ends);
|
|
167083
167290
|
edges.push({
|
|
167084
167291
|
id: `e${e++}`,
|
|
167085
167292
|
from,
|
|
@@ -169777,6 +169984,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
169777
169984
|
}
|
|
169778
169985
|
add("connections", members.filter((member) => isConnectionDecl(member) && member.isDef !== true && isOrdinaryMember(member)).map((member) => item(member, this.featureText(member) || "(anonymous connection)")));
|
|
169779
169986
|
add("interfaces", members.filter((m) => isInterfaceDecl(m) && m.isDef !== true && isOrdinaryMember(m)).map((m) => item(m, this.interfaceRowText(m))));
|
|
169987
|
+
add("flows", members.filter((m) => m.$type === "FlowStmt" && m.isDef !== true && isOrdinaryMember(m)).map((m) => item(m, this.flowRowText(m))));
|
|
169780
169988
|
add("features", members.filter((m) => m.$type === "FeatureShorthand" || m.$type === "FeatureRedefinitionShorthand").filter(isOrdinaryMember).filter((m) => !isOccurrenceModified(m)).map((m) => item(m, canonicalFeatureText(m))));
|
|
169781
169989
|
const undirected = (guard) => usages(guard);
|
|
169782
169990
|
add("items", undirected(isItemDecl).filter(notPortion).map((m) => item(m)));
|
|
@@ -183835,7 +184043,7 @@ function compartmentWidth(node) {
|
|
|
183835
184043
|
}
|
|
183836
184044
|
function nodeForCanvas(node) {
|
|
183837
184045
|
if (node.meta?.connectionUsage === true || node.meta?.interfaceUsage === true) {
|
|
183838
|
-
const compartments2 = node.compartments?.filter((compartment) => compartment.title === "doc");
|
|
184046
|
+
const compartments2 = node.compartments?.filter((compartment) => compartment.title === "doc" || compartment.title === "flows");
|
|
183839
184047
|
return {
|
|
183840
184048
|
...node,
|
|
183841
184049
|
compartments: compartments2?.length ? compartments2 : void 0
|
|
@@ -184367,7 +184575,8 @@ function hideExplicitRelationshipBoxes(model, relationship) {
|
|
|
184367
184575
|
bindings: explicitRelationshipBindings(usage, model),
|
|
184368
184576
|
endCount: usage.ports?.length ?? 0
|
|
184369
184577
|
}));
|
|
184370
|
-
const
|
|
184578
|
+
const blocksCompaction = ({ usage, endCount }) => (nodeForCanvas(usage).compartments ?? []).some((compartment) => endCount !== 2 || compartment.title !== "flows");
|
|
184579
|
+
const retainedIds = new Set(projections.filter((projection2) => blocksCompaction(projection2) || annotatedUsageIds.has(projection2.usage.id) || projection2.endCount < 2 || projection2.bindings.length !== projection2.endCount).map(({ usage }) => usage.id));
|
|
184371
184580
|
const hiddenIds = /* @__PURE__ */ new Set();
|
|
184372
184581
|
for (const { usage } of projections) {
|
|
184373
184582
|
if (retainedIds.has(usage.id)) continue;
|
|
@@ -184424,6 +184633,8 @@ function hideExplicitRelationshipBoxes(model, relationship) {
|
|
|
184424
184633
|
});
|
|
184425
184634
|
continue;
|
|
184426
184635
|
}
|
|
184636
|
+
const hubMeta = { ...baseMeta };
|
|
184637
|
+
delete hubMeta.flowDecorations;
|
|
184427
184638
|
const hubId = `${usage.id}::__compact_hub`;
|
|
184428
184639
|
compactNodes.push({
|
|
184429
184640
|
id: hubId,
|
|
@@ -184434,7 +184645,7 @@ function hideExplicitRelationshipBoxes(model, relationship) {
|
|
|
184434
184645
|
...usage.frame ? { frame: usage.frame } : {},
|
|
184435
184646
|
source: usage.source,
|
|
184436
184647
|
meta: {
|
|
184437
|
-
...
|
|
184648
|
+
...hubMeta,
|
|
184438
184649
|
naryConnectionHub: true,
|
|
184439
184650
|
...relationship === "connection" ? { compactConnectionUsageHub: true } : { compactInterfaceUsageHub: true }
|
|
184440
184651
|
}
|
|
@@ -184454,7 +184665,7 @@ function hideExplicitRelationshipBoxes(model, relationship) {
|
|
|
184454
184665
|
endAdornmentTo: binding.adornment,
|
|
184455
184666
|
source: usage.source ?? binding.edge.source,
|
|
184456
184667
|
meta: {
|
|
184457
|
-
...
|
|
184668
|
+
...hubMeta,
|
|
184458
184669
|
...relationship === "connection" ? { compactConnectionUsageEnd: true } : { compactInterfaceUsageEnd: true },
|
|
184459
184670
|
connectionEndOrdinal: binding.ordinal,
|
|
184460
184671
|
...binding.role ? { connectionEndRole: binding.role } : {}
|
|
@@ -198165,6 +198376,45 @@ function successionFlowLabelPoint(centre, mark) {
|
|
|
198165
198376
|
y: markCoordinate(centre.y - mark.normal.y * 16)
|
|
198166
198377
|
};
|
|
198167
198378
|
}
|
|
198379
|
+
function flowDecorationsOf(edge) {
|
|
198380
|
+
const raw = edge.meta?.flowDecorations;
|
|
198381
|
+
if (!Array.isArray(raw)) return [];
|
|
198382
|
+
return raw.flatMap((entry) => {
|
|
198383
|
+
if (!entry || typeof entry !== "object") return [];
|
|
198384
|
+
const decoration = entry;
|
|
198385
|
+
return [{
|
|
198386
|
+
keyword: typeof decoration.keyword === "string" ? decoration.keyword : "flow",
|
|
198387
|
+
label: typeof decoration.label === "string" ? decoration.label : void 0,
|
|
198388
|
+
name: typeof decoration.name === "string" ? decoration.name : void 0,
|
|
198389
|
+
reversed: decoration.reversed === true
|
|
198390
|
+
}];
|
|
198391
|
+
});
|
|
198392
|
+
}
|
|
198393
|
+
var FLOW_DECORATION_STEP = 26;
|
|
198394
|
+
function flowDecorationGeometry(centre, points, source, target, index2, count, reversed) {
|
|
198395
|
+
const raw = midpointTangent(points?.length ? points : [source, target]) ?? { x: target.x - source.x, y: target.y - source.y };
|
|
198396
|
+
const length2 = Math.hypot(raw.x, raw.y);
|
|
198397
|
+
if (length2 <= 0) return void 0;
|
|
198398
|
+
const tangent = { x: raw.x / length2, y: raw.y / length2 };
|
|
198399
|
+
const normal = { x: -tangent.y, y: tangent.x };
|
|
198400
|
+
const shift = (index2 - (count - 1) / 2) * FLOW_DECORATION_STEP;
|
|
198401
|
+
const at = { x: centre.x + tangent.x * shift, y: centre.y + tangent.y * shift };
|
|
198402
|
+
const sign = reversed ? -1 : 1;
|
|
198403
|
+
const tip = { x: at.x + tangent.x * 5 * sign, y: at.y + tangent.y * 5 * sign };
|
|
198404
|
+
const back = { x: at.x - tangent.x * 4 * sign, y: at.y - tangent.y * 4 * sign };
|
|
198405
|
+
const corner = (side) => ({
|
|
198406
|
+
x: back.x + normal.x * 4 * side,
|
|
198407
|
+
y: back.y + normal.y * 4 * side
|
|
198408
|
+
});
|
|
198409
|
+
const wing = [corner(1), corner(-1)];
|
|
198410
|
+
return {
|
|
198411
|
+
chevron: [tip, wing[0], wing[1]].map((point) => `${markCoordinate(point.x)},${markCoordinate(point.y)}`).join(" "),
|
|
198412
|
+
label: {
|
|
198413
|
+
x: markCoordinate(at.x + normal.x * 13),
|
|
198414
|
+
y: markCoordinate(at.y + normal.y * 13)
|
|
198415
|
+
}
|
|
198416
|
+
};
|
|
198417
|
+
}
|
|
198168
198418
|
function routePointNearSource(points, source, target, distance2) {
|
|
198169
198419
|
const route = [source, ...points ?? [], target].filter((point, index2, all) => index2 === 0 || point.x !== all[index2 - 1].x || point.y !== all[index2 - 1].y);
|
|
198170
198420
|
let remaining = distance2;
|
|
@@ -199194,6 +199444,13 @@ body {
|
|
|
199194
199444
|
.dlink { stroke: var(--diagram-line-structural); stroke-width: 1.2; fill: none; }
|
|
199195
199445
|
.dlink.successionFlow { stroke-width: 2; }
|
|
199196
199446
|
.dsuccession-flow-mark { pointer-events: none; stroke-linecap: butt; }
|
|
199447
|
+
/* REQ-401 \u2014 OMG 8.2.3.16 flow-on-connection: the payload chevron rides the
|
|
199448
|
+
connector that transports it, in the item-flow hue, and never takes pointer
|
|
199449
|
+
events away from the connector it decorates. */
|
|
199450
|
+
.dflow-decoration {
|
|
199451
|
+
pointer-events: none; stroke: none;
|
|
199452
|
+
fill: var(--diagram-line-connection, #6cd1d9);
|
|
199453
|
+
}
|
|
199197
199454
|
/* REQ-196: AFV control transitions (IR succession) use a dotted route so
|
|
199198
199455
|
they remain visually distinct from continuous item and succession flows. */
|
|
199199
199456
|
.dlink.succession { stroke-dasharray: 1 3; stroke-linecap: round; }
|
|
@@ -200373,6 +200630,24 @@ function buildDiagramSvg(options) {
|
|
|
200373
200630
|
extendPoint(sequencingMark.x1, sequencingMark.y1, 2);
|
|
200374
200631
|
extendPoint(sequencingMark.x2, sequencingMark.y2, 2);
|
|
200375
200632
|
}
|
|
200633
|
+
const decorations = semantic ? flowDecorationsOf(semantic) : [];
|
|
200634
|
+
decorations.forEach((decoration, index2) => {
|
|
200635
|
+
const placement = flowDecorationGeometry(
|
|
200636
|
+
geometry.label,
|
|
200637
|
+
geometry.points ?? geometry.anchors,
|
|
200638
|
+
geometry.source,
|
|
200639
|
+
geometry.target,
|
|
200640
|
+
index2,
|
|
200641
|
+
decorations.length,
|
|
200642
|
+
decoration.reversed === true
|
|
200643
|
+
);
|
|
200644
|
+
if (!placement) return;
|
|
200645
|
+
edgeParts.push(`<polygon class="dflow-decoration ${decoration.keyword.replace(/\s+/gu, "-")}" points="${placement.chevron}"/>`);
|
|
200646
|
+
const text = [decoration.name, decoration.label].filter(Boolean).join(" : ");
|
|
200647
|
+
if (!text) return;
|
|
200648
|
+
labelParts.push(labelSvg(text, placement.label.x, placement.label.y, "elabel flow"));
|
|
200649
|
+
extendLabel(text, placement.label.x, placement.label.y);
|
|
200650
|
+
});
|
|
200376
200651
|
extendPoint(geometry.source.x, geometry.source.y, MARKER_ALLOWANCE);
|
|
200377
200652
|
extendPoint(geometry.target.x, geometry.target.y, MARKER_ALLOWANCE);
|
|
200378
200653
|
for (const point of geometry.points ?? geometry.anchors) extendPoint(point.x, point.y, MARKER_ALLOWANCE);
|
|
@@ -203682,7 +203957,7 @@ async function runExport(command) {
|
|
|
203682
203957
|
}
|
|
203683
203958
|
|
|
203684
203959
|
// src/main.ts
|
|
203685
|
-
var VERSION2 = true ? "0.
|
|
203960
|
+
var VERSION2 = true ? "0.24.0" : "dev";
|
|
203686
203961
|
function display(file) {
|
|
203687
203962
|
const rel2 = path9.relative(process.cwd(), file);
|
|
203688
203963
|
return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;
|