@miragon/modeler-api 1.2.0 → 1.3.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 +51 -8
- package/dist/{chunk-E6KJB7QH.js → chunk-JK23ZTVG.js} +2 -2
- package/dist/chunk-JK23ZTVG.js.map +1 -0
- package/dist/conformance.cjs +99 -1
- package/dist/conformance.cjs.map +1 -1
- package/dist/conformance.js +99 -1
- package/dist/conformance.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -6
- package/dist/index.d.ts +47 -6
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-E6KJB7QH.js.map +0 -1
package/dist/conformance.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MODELER_API_VERSION,
|
|
3
3
|
apiVersionsCompatible
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JK23ZTVG.js";
|
|
5
5
|
|
|
6
6
|
// src/conformance.ts
|
|
7
7
|
function attachedHost(width = 800, height = 600) {
|
|
@@ -28,6 +28,52 @@ var same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
|
28
28
|
var hasBounds = (elements) => typeof elements.bounds === "function";
|
|
29
29
|
var isFiniteBox = (box) => box !== void 0 && [box.x, box.y, box.width, box.height].every((n) => typeof n === "number" && Number.isFinite(n)) && box.width >= 0 && box.height >= 0;
|
|
30
30
|
var describeBox = (box) => box === void 0 ? "undefined" : `{ x: ${box.x}, y: ${box.y}, width: ${box.width}, height: ${box.height} }`;
|
|
31
|
+
var hasContentBounds = (m) => typeof m.contentBounds === "function";
|
|
32
|
+
var edgeTolerance = (edge) => Math.max(1e-3, Math.abs(edge) * 2 ** -20);
|
|
33
|
+
var covers = (outer, inner) => {
|
|
34
|
+
const right = outer.x + outer.width;
|
|
35
|
+
const bottom = outer.y + outer.height;
|
|
36
|
+
return inner.x >= outer.x - edgeTolerance(outer.x) && inner.y >= outer.y - edgeTolerance(outer.y) && inner.x + inner.width <= right + edgeTolerance(right) && inner.y + inner.height <= bottom + edgeTolerance(bottom);
|
|
37
|
+
};
|
|
38
|
+
function contentBoxOf(m, when) {
|
|
39
|
+
let box;
|
|
40
|
+
try {
|
|
41
|
+
box = m.contentBounds();
|
|
42
|
+
} catch (e) {
|
|
43
|
+
fail(`contentBounds() threw ${when}: ${String(e)}`);
|
|
44
|
+
}
|
|
45
|
+
if (box === void 0) return void 0;
|
|
46
|
+
if (!isFiniteBox(box)) {
|
|
47
|
+
fail(
|
|
48
|
+
`contentBounds() ${when} is ${describeBox(box)} \u2014 the content box must be finite with a non-negative size, or undefined when there is nothing to fit`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return { x: box.x, y: box.y, width: box.width, height: box.height };
|
|
52
|
+
}
|
|
53
|
+
function expectContentAroundElements(m, when) {
|
|
54
|
+
const box = contentBoxOf(m, when);
|
|
55
|
+
const listed = m.elements?.list() ?? [];
|
|
56
|
+
if (box === void 0) {
|
|
57
|
+
if (listed.length > 0) {
|
|
58
|
+
fail(
|
|
59
|
+
`contentBounds() ${when} is undefined while elements.list() reports ${listed.length} element(s) \u2014 undefined means there is nothing to fit`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
if (m.elements && hasBounds(m.elements)) {
|
|
65
|
+
for (const { id } of listed) {
|
|
66
|
+
const element = m.elements.bounds(id);
|
|
67
|
+
if (!isFiniteBox(element)) continue;
|
|
68
|
+
if (!covers(box, element)) {
|
|
69
|
+
fail(
|
|
70
|
+
`contentBounds() ${when} is ${describeBox(box)}, which does not cover elements.bounds('${id}') = ${describeBox(element)} \u2014 the content box holds every element (and reads the live canvas)`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return box;
|
|
76
|
+
}
|
|
31
77
|
function boxesOf(elements, when) {
|
|
32
78
|
const boxes = /* @__PURE__ */ new Map();
|
|
33
79
|
for (const { id } of elements.list()) {
|
|
@@ -903,6 +949,58 @@ ${out}`;
|
|
|
903
949
|
}
|
|
904
950
|
}
|
|
905
951
|
},
|
|
952
|
+
{
|
|
953
|
+
name: "contentBounds (when present): a finite box in diagram coordinates around every listed element, live after a new element, unchanged by zoom and scroll",
|
|
954
|
+
async run(h) {
|
|
955
|
+
const settle = h.settle ?? defaultSettle;
|
|
956
|
+
const m = await h.create();
|
|
957
|
+
let viewer;
|
|
958
|
+
try {
|
|
959
|
+
if (!hasContentBounds(m))
|
|
960
|
+
return skip("the modeler exposes no contentBounds (optional, 1.3) \u2014 nothing to verify");
|
|
961
|
+
contentBoxOf(m, "before the first import");
|
|
962
|
+
for (const [index, text] of h.canonicalTexts.entries()) {
|
|
963
|
+
await importOrFail(m, text, `importText(canonicalTexts[${index}]) rejected`);
|
|
964
|
+
expectContentAroundElements(m, `after importing canonicalTexts[${index}]`);
|
|
965
|
+
}
|
|
966
|
+
await importOrFail(m, h.canonicalTexts[0] ?? "", "importText(canonicalTexts[0]) rejected");
|
|
967
|
+
await h.mutate(m);
|
|
968
|
+
await settle();
|
|
969
|
+
const atRest = expectContentAroundElements(m, "after a user mutation added an element");
|
|
970
|
+
const unverified = [];
|
|
971
|
+
if (h.viewState !== void 0) {
|
|
972
|
+
m.setViewState(h.viewState);
|
|
973
|
+
const viewed = contentBoxOf(m, "after setViewState");
|
|
974
|
+
if (!same(viewed, atRest)) {
|
|
975
|
+
fail(
|
|
976
|
+
`contentBounds() changed with the view (${describeBox(atRest)} \u2192 ${describeBox(viewed)}) \u2014 the content box is in diagram coordinates, which zoom and scroll leave alone`
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
} else {
|
|
980
|
+
unverified.push(
|
|
981
|
+
"viewState is undefined \u2014 that the content box is independent of the view was not verified"
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
if (!m.elements || !hasBounds(m.elements)) {
|
|
985
|
+
unverified.push(
|
|
986
|
+
"the modeler exposes no elements.bounds \u2014 that the content box covers every element was not verified"
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
if (h.createReadonly) {
|
|
990
|
+
viewer = await h.createReadonly();
|
|
991
|
+
if (hasContentBounds(viewer)) {
|
|
992
|
+
contentBoxOf(viewer, "on the viewer before the first import");
|
|
993
|
+
await importOrFail(viewer, h.canonicalTexts[0] ?? "", "the viewer rejected canonicalTexts[0]");
|
|
994
|
+
expectContentAroundElements(viewer, "on the viewer after an import");
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
if (unverified.length > 0) return skip(unverified.join("; "));
|
|
998
|
+
} finally {
|
|
999
|
+
m.destroy();
|
|
1000
|
+
viewer?.destroy();
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
906
1004
|
{
|
|
907
1005
|
name: "L6: export is total after imports, user mutations and undo",
|
|
908
1006
|
async run(h) {
|