forma-diagrams 0.5.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/Dockerfile +16 -0
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/THIRD_PARTY_NOTICES.md +20 -0
- package/bin/forma +3 -0
- package/deploy/.env.example +11 -0
- package/deploy/Caddyfile +4 -0
- package/deploy/compose.yml +38 -0
- package/dist/assets/IBMPlexSans-Regular-Bl2SjS7V.ttf +0 -0
- package/dist/assets/IBMPlexSans-SemiBold-B9auKknr.ttf +0 -0
- package/dist/assets/elk.bundled-Y7ymokgr.js +24 -0
- package/dist/assets/index-_kg9cdik.css +1 -0
- package/dist/assets/index-al0xDdTG.js +452 -0
- package/dist/fonts/IBMPlexSans-Regular.ttf +0 -0
- package/dist/fonts/IBMPlexSans-SemiBold.ttf +0 -0
- package/dist/fonts/OFL.txt +93 -0
- package/dist/index.html +14 -0
- package/dist/licenses/FORMA_LICENSE.txt +21 -0
- package/dist/licenses/THIRD_PARTY_LICENSES.txt +11601 -0
- package/docs/api.md +41 -0
- package/docs/decisions/001-foundation.md +57 -0
- package/docs/decisions/002-composition-and-human-edits.md +47 -0
- package/docs/decisions/003-general-composition.md +30 -0
- package/docs/decisions/004-library-and-distribution.md +33 -0
- package/docs/decisions/005-organizational-hosting.md +33 -0
- package/docs/decisions/006-hosted-agent-access.md +25 -0
- package/docs/format.md +132 -0
- package/docs/gallery.md +73 -0
- package/docs/images/architecture.png +0 -0
- package/docs/images/editor.png +0 -0
- package/docs/images/gallery/architecture.png +0 -0
- package/docs/images/gallery/decision.png +0 -0
- package/docs/images/gallery/development-signal.png +0 -0
- package/docs/images/gallery/development.png +0 -0
- package/docs/images/gallery/editor-roundtrip.png +0 -0
- package/docs/images/gallery/entities.png +0 -0
- package/docs/images/gallery/mindmap.png +0 -0
- package/docs/images/gallery/organization.png +0 -0
- package/docs/images/gallery/timeline.png +0 -0
- package/docs/images/release.png +0 -0
- package/docs/install.md +50 -0
- package/docs/plans/mvp.md +24 -0
- package/docs/self-hosting.md +167 -0
- package/docs/verification-v2.md +41 -0
- package/docs/verification-v3.md +16 -0
- package/docs/verification-v4.1.md +35 -0
- package/docs/verification-v4.2.md +20 -0
- package/docs/verification-v4.3.md +5 -0
- package/docs/verification-v4.md +31 -0
- package/docs/verification-v5.1.md +7 -0
- package/docs/verification-v5.2.md +7 -0
- package/docs/verification-v5.md +7 -0
- package/docs/verification.md +91 -0
- package/examples/design-systems/atelier.json +53 -0
- package/examples/design-systems/signal.json +53 -0
- package/examples/gallery/architecture.forma.json +178 -0
- package/examples/gallery/decision.forma.json +182 -0
- package/examples/gallery/development-signal.forma.json +299 -0
- package/examples/gallery/development.forma.json +299 -0
- package/examples/gallery/entities.forma.json +123 -0
- package/examples/gallery/mindmap.forma.json +158 -0
- package/examples/gallery/organization.forma.json +151 -0
- package/examples/gallery/timeline.forma.json +138 -0
- package/examples/platform.forma.json +116 -0
- package/examples/release.forma.json +58 -0
- package/examples/roundtrip/agent-continued.forma.json +310 -0
- package/examples/roundtrip/agent-patch.json +7 -0
- package/examples/roundtrip/human-edited.forma.json +309 -0
- package/package.json +81 -0
- package/packages/cli/bin.mjs +3 -0
- package/packages/cli/src/agent-access.ts +232 -0
- package/packages/cli/src/blob-store.ts +241 -0
- package/packages/cli/src/file-library.ts +179 -0
- package/packages/cli/src/google.ts +51 -0
- package/packages/cli/src/hosted.ts +498 -0
- package/packages/cli/src/http.ts +67 -0
- package/packages/cli/src/index.ts +397 -0
- package/packages/cli/src/mcp.ts +114 -0
- package/packages/cli/src/remote.ts +228 -0
- package/packages/cli/src/server.ts +69 -0
- package/packages/cli/src/signed-cookie.ts +42 -0
- package/packages/core/src/align.ts +237 -0
- package/packages/core/src/document.ts +408 -0
- package/packages/core/src/font-metrics.json +1 -0
- package/packages/core/src/geometry.ts +463 -0
- package/packages/core/src/index.ts +12 -0
- package/packages/core/src/inspect.ts +230 -0
- package/packages/core/src/layout.ts +450 -0
- package/packages/core/src/render.ts +182 -0
- package/packages/core/src/resolve-style.ts +29 -0
- package/packages/core/src/scene.ts +40 -0
- package/packages/core/src/styles.ts +122 -0
- package/packages/core/src/text.ts +81 -0
- package/packages/core/src/theme.ts +33 -0
- package/public/fonts/IBMPlexSans-Regular.ttf +0 -0
- package/public/fonts/IBMPlexSans-SemiBold.ttf +0 -0
- package/public/fonts/OFL.txt +93 -0
- package/schema/design-system.v1.schema.json +734 -0
- package/schema/forma.v1.schema.json +273 -0
- package/schema/forma.v2.schema.json +1756 -0
- package/skills/forma/SKILL.md +20 -0
- package/skills/forma/references/composition.md +11 -0
- package/skills/forma/references/hosted.md +28 -0
- package/skills/forma-architecture/SKILL.md +14 -0
- package/skills/forma-entities/SKILL.md +14 -0
- package/skills/forma-flow/SKILL.md +14 -0
- package/skills/forma-mindmap/SKILL.md +14 -0
- package/skills/forma-organization/SKILL.md +14 -0
- package/skills/forma-timeline/SKILL.md +14 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { elementStyleSchema, designSystemSchema, type PortSide } from './styles';
|
|
3
|
+
|
|
4
|
+
const id = z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,79}$/);
|
|
5
|
+
const text = z.string().max(2000);
|
|
6
|
+
const color = z.enum(['slate', 'blue', 'teal', 'amber', 'violet']);
|
|
7
|
+
const position = z
|
|
8
|
+
.object({
|
|
9
|
+
x: z.number().finite().min(-10000).max(10000),
|
|
10
|
+
y: z.number().finite().min(-10000).max(10000),
|
|
11
|
+
})
|
|
12
|
+
.strict();
|
|
13
|
+
const portCount = z.number().int().min(1).max(12);
|
|
14
|
+
export const portCountsSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
top: portCount.optional(),
|
|
17
|
+
right: portCount.optional(),
|
|
18
|
+
bottom: portCount.optional(),
|
|
19
|
+
left: portCount.optional(),
|
|
20
|
+
})
|
|
21
|
+
.strict();
|
|
22
|
+
export type PortCounts = z.infer<typeof portCountsSchema>;
|
|
23
|
+
export const nodeSchema = z
|
|
24
|
+
.object({
|
|
25
|
+
id,
|
|
26
|
+
label: z.string().min(1).max(240),
|
|
27
|
+
description: text.optional(),
|
|
28
|
+
kind: z.string().min(1).max(80).default('service'),
|
|
29
|
+
role: id.optional(),
|
|
30
|
+
style: elementStyleSchema.optional(),
|
|
31
|
+
placement: z
|
|
32
|
+
.object({ column: z.number().int().min(0).max(50), row: z.number().int().min(0).max(50) })
|
|
33
|
+
.strict()
|
|
34
|
+
.optional(),
|
|
35
|
+
group: id.optional(),
|
|
36
|
+
emphasis: z.enum(['normal', 'primary', 'muted']).default('normal'),
|
|
37
|
+
ports: portCountsSchema.optional(),
|
|
38
|
+
})
|
|
39
|
+
.strict();
|
|
40
|
+
export const edgeSchema = z
|
|
41
|
+
.object({
|
|
42
|
+
id,
|
|
43
|
+
source: id,
|
|
44
|
+
target: id,
|
|
45
|
+
label: z.string().max(120).optional(),
|
|
46
|
+
style: z.enum(['solid', 'dashed']).default('solid'),
|
|
47
|
+
role: id.optional(),
|
|
48
|
+
appearance: elementStyleSchema.optional(),
|
|
49
|
+
path: z.array(position).min(1).max(24).optional(),
|
|
50
|
+
})
|
|
51
|
+
.strict();
|
|
52
|
+
export const groupSchema = z
|
|
53
|
+
.object({
|
|
54
|
+
id,
|
|
55
|
+
label: z.string().min(1).max(120),
|
|
56
|
+
parent: id.optional(),
|
|
57
|
+
role: id.optional(),
|
|
58
|
+
style: elementStyleSchema.optional(),
|
|
59
|
+
description: text.optional(),
|
|
60
|
+
color: color.default('slate'),
|
|
61
|
+
})
|
|
62
|
+
.strict();
|
|
63
|
+
export const documentSchema = z
|
|
64
|
+
.object({
|
|
65
|
+
version: z.union([z.literal(1), z.literal(2)]),
|
|
66
|
+
title: z.string().min(1).max(200),
|
|
67
|
+
description: text.optional(),
|
|
68
|
+
type: z.string().min(1).max(80).default('diagram'),
|
|
69
|
+
nodes: z.array(nodeSchema).max(200),
|
|
70
|
+
edges: z.array(edgeSchema).max(600),
|
|
71
|
+
groups: z.array(groupSchema).max(40).default([]),
|
|
72
|
+
layout: z
|
|
73
|
+
.object({
|
|
74
|
+
mode: z.enum(['layered', 'grid']).optional(),
|
|
75
|
+
direction: z.enum(['RIGHT', 'DOWN']).default('RIGHT'),
|
|
76
|
+
spacing: z.enum(['comfortable', 'compact']).default('comfortable'),
|
|
77
|
+
})
|
|
78
|
+
.strict()
|
|
79
|
+
.default({ direction: 'RIGHT', spacing: 'comfortable' }),
|
|
80
|
+
presentation: z
|
|
81
|
+
.object({
|
|
82
|
+
theme: z.enum(['paper', 'midnight']).default('paper'),
|
|
83
|
+
designSystem: designSystemSchema.optional(),
|
|
84
|
+
nodes: z
|
|
85
|
+
.record(
|
|
86
|
+
id,
|
|
87
|
+
z
|
|
88
|
+
.object({
|
|
89
|
+
position: position.optional(),
|
|
90
|
+
color: color.optional(),
|
|
91
|
+
style: elementStyleSchema.optional(),
|
|
92
|
+
})
|
|
93
|
+
.strict(),
|
|
94
|
+
)
|
|
95
|
+
.default({}),
|
|
96
|
+
footer: z
|
|
97
|
+
.object({
|
|
98
|
+
hidden: z.boolean().optional(),
|
|
99
|
+
label: z.string().max(80).optional(),
|
|
100
|
+
detail: z.string().max(80).optional(),
|
|
101
|
+
})
|
|
102
|
+
.strict()
|
|
103
|
+
.optional(),
|
|
104
|
+
})
|
|
105
|
+
.strict()
|
|
106
|
+
.default({ theme: 'paper', nodes: {} }),
|
|
107
|
+
})
|
|
108
|
+
.strict();
|
|
109
|
+
export type Diagram = z.infer<typeof documentSchema>;
|
|
110
|
+
export type DiagramNode = Diagram['nodes'][number];
|
|
111
|
+
export type DiagramEdge = Diagram['edges'][number];
|
|
112
|
+
export type DiagramGroup = Diagram['groups'][number];
|
|
113
|
+
export type Accent = z.infer<typeof color>;
|
|
114
|
+
export type Point = z.infer<typeof position>;
|
|
115
|
+
export type NodeOverride = Diagram['presentation']['nodes'][string];
|
|
116
|
+
export class DocumentError extends Error {
|
|
117
|
+
constructor(public issues: { path: string; message: string }[]) {
|
|
118
|
+
super(issues.map((i) => `${i.path}: ${i.message}`).join('\n'));
|
|
119
|
+
this.name = 'DocumentError';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function parseDocument(input: unknown): Diagram {
|
|
123
|
+
const source =
|
|
124
|
+
input &&
|
|
125
|
+
typeof input === 'object' &&
|
|
126
|
+
(input as Record<string, unknown>).version === 1 &&
|
|
127
|
+
!('type' in input)
|
|
128
|
+
? { ...input, type: 'architecture' }
|
|
129
|
+
: input;
|
|
130
|
+
const result = documentSchema.safeParse(source);
|
|
131
|
+
if (!result.success)
|
|
132
|
+
throw new DocumentError(
|
|
133
|
+
result.error.issues.map((i) => ({ path: i.path.join('.'), message: i.message })),
|
|
134
|
+
);
|
|
135
|
+
const doc = result.data;
|
|
136
|
+
const issues: { path: string; message: string }[] = [];
|
|
137
|
+
if (doc.version === 1 && hasV2Features(doc))
|
|
138
|
+
issues.push({
|
|
139
|
+
path: 'version',
|
|
140
|
+
message: 'General composition and styles require version 2. Use forma migrate.',
|
|
141
|
+
});
|
|
142
|
+
if (doc.layout.mode === 'grid') {
|
|
143
|
+
const cells = new Set<string>();
|
|
144
|
+
for (const [i, n] of doc.nodes.entries()) {
|
|
145
|
+
const p = n.placement ?? { column: i, row: 0 };
|
|
146
|
+
const cell = `${p.column}:${p.row}`;
|
|
147
|
+
if (cells.has(cell))
|
|
148
|
+
issues.push({ path: `nodes.${n.id}.placement`, message: 'Grid cell already occupied' });
|
|
149
|
+
cells.add(cell);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const seen = new Set<string>();
|
|
153
|
+
for (const [collection, values] of Object.entries({
|
|
154
|
+
nodes: doc.nodes,
|
|
155
|
+
edges: doc.edges,
|
|
156
|
+
groups: doc.groups,
|
|
157
|
+
})) {
|
|
158
|
+
for (const item of values) {
|
|
159
|
+
if (seen.has(item.id)) issues.push({ path: collection, message: `Duplicate ID: ${item.id}` });
|
|
160
|
+
seen.add(item.id);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const nodes = new Set(doc.nodes.map((n) => n.id));
|
|
164
|
+
const groups = new Map(doc.groups.map((g) => [g.id, g]));
|
|
165
|
+
for (const n of doc.nodes)
|
|
166
|
+
if (n.group && !groups.has(n.group))
|
|
167
|
+
issues.push({ path: `nodes.${n.id}.group`, message: 'Unknown group' });
|
|
168
|
+
const nodeById = new Map(doc.nodes.map((n) => [n.id, n]));
|
|
169
|
+
for (const e of doc.edges) {
|
|
170
|
+
for (const side of ['source', 'target'] as const)
|
|
171
|
+
if (!nodes.has(e[side]))
|
|
172
|
+
issues.push({ path: `edges.${e.id}.${side}`, message: `Unknown node: ${e[side]}` });
|
|
173
|
+
const source = nodeById.get(e.source),
|
|
174
|
+
target = nodeById.get(e.target);
|
|
175
|
+
if (source)
|
|
176
|
+
checkPortIndex(
|
|
177
|
+
issues,
|
|
178
|
+
e.id,
|
|
179
|
+
'source',
|
|
180
|
+
e.appearance?.sourcePort,
|
|
181
|
+
e.appearance?.sourceIndex,
|
|
182
|
+
source.ports,
|
|
183
|
+
doc.layout.direction,
|
|
184
|
+
);
|
|
185
|
+
if (target)
|
|
186
|
+
checkPortIndex(
|
|
187
|
+
issues,
|
|
188
|
+
e.id,
|
|
189
|
+
'target',
|
|
190
|
+
e.appearance?.targetPort,
|
|
191
|
+
e.appearance?.targetIndex,
|
|
192
|
+
target.ports,
|
|
193
|
+
doc.layout.direction,
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
for (const g of doc.groups) {
|
|
197
|
+
if (g.parent && !groups.has(g.parent))
|
|
198
|
+
issues.push({ path: `groups.${g.id}.parent`, message: 'Unknown parent' });
|
|
199
|
+
const chain = new Set([g.id]);
|
|
200
|
+
let parent = g.parent;
|
|
201
|
+
while (parent && groups.has(parent)) {
|
|
202
|
+
if (chain.has(parent)) {
|
|
203
|
+
issues.push({ path: `groups.${g.id}.parent`, message: 'Group hierarchy cycle' });
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
chain.add(parent);
|
|
207
|
+
parent = groups.get(parent)?.parent;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
for (const key of Object.keys(doc.presentation.nodes))
|
|
211
|
+
if (!nodes.has(key))
|
|
212
|
+
issues.push({
|
|
213
|
+
path: `presentation.nodes.${key}`,
|
|
214
|
+
message: 'Override references unknown node',
|
|
215
|
+
});
|
|
216
|
+
if (issues.length) throw new DocumentError(issues);
|
|
217
|
+
return doc;
|
|
218
|
+
}
|
|
219
|
+
export const patchSchema = z
|
|
220
|
+
.object({
|
|
221
|
+
title: z.string().min(1).max(200).optional(),
|
|
222
|
+
description: text.optional(),
|
|
223
|
+
nodes: z.array(z.object({ id }).passthrough()).optional(),
|
|
224
|
+
edges: z.array(z.object({ id }).passthrough()).optional(),
|
|
225
|
+
groups: z.array(z.object({ id }).passthrough()).optional(),
|
|
226
|
+
remove: z
|
|
227
|
+
.object({
|
|
228
|
+
nodes: z.array(id).optional(),
|
|
229
|
+
edges: z.array(id).optional(),
|
|
230
|
+
groups: z.array(id).optional(),
|
|
231
|
+
})
|
|
232
|
+
.strict()
|
|
233
|
+
.optional(),
|
|
234
|
+
layout: z
|
|
235
|
+
.object({
|
|
236
|
+
mode: z.enum(['layered', 'grid']).optional(),
|
|
237
|
+
direction: z.enum(['RIGHT', 'DOWN']).optional(),
|
|
238
|
+
spacing: z.enum(['comfortable', 'compact']).optional(),
|
|
239
|
+
})
|
|
240
|
+
.strict()
|
|
241
|
+
.optional(),
|
|
242
|
+
theme: z.enum(['paper', 'midnight']).optional(),
|
|
243
|
+
designSystem: designSystemSchema.nullable().optional(),
|
|
244
|
+
footer: z
|
|
245
|
+
.object({
|
|
246
|
+
hidden: z.boolean().nullable().optional(),
|
|
247
|
+
label: z.string().max(80).nullable().optional(),
|
|
248
|
+
detail: z.string().max(80).nullable().optional(),
|
|
249
|
+
})
|
|
250
|
+
.strict()
|
|
251
|
+
.nullable()
|
|
252
|
+
.optional(),
|
|
253
|
+
overrides: z
|
|
254
|
+
.record(
|
|
255
|
+
id,
|
|
256
|
+
z
|
|
257
|
+
.object({
|
|
258
|
+
position: position.nullable().optional(),
|
|
259
|
+
color: color.nullable().optional(),
|
|
260
|
+
style: elementStyleSchema.nullable().optional(),
|
|
261
|
+
})
|
|
262
|
+
.strict()
|
|
263
|
+
.nullable(),
|
|
264
|
+
)
|
|
265
|
+
.optional(),
|
|
266
|
+
})
|
|
267
|
+
.strict();
|
|
268
|
+
export type Patch = z.input<typeof patchSchema>;
|
|
269
|
+
/** Transactional: validate the entire result; input is never mutated. */
|
|
270
|
+
export function patchDocument(input: Diagram, raw: unknown): Diagram {
|
|
271
|
+
const doc = structuredClone(parseDocument(input));
|
|
272
|
+
const patch = patchSchema.parse(raw);
|
|
273
|
+
if (patch.title !== undefined) doc.title = patch.title;
|
|
274
|
+
if (patch.description !== undefined) doc.description = patch.description;
|
|
275
|
+
if (patch.layout) Object.assign(doc.layout, patch.layout);
|
|
276
|
+
if (patch.theme) doc.presentation.theme = patch.theme;
|
|
277
|
+
if (patch.designSystem === null) delete doc.presentation.designSystem;
|
|
278
|
+
else if (patch.designSystem) doc.presentation.designSystem = patch.designSystem;
|
|
279
|
+
if (patch.footer === null) delete doc.presentation.footer;
|
|
280
|
+
else if (patch.footer) {
|
|
281
|
+
const merged: Record<string, unknown> = { ...doc.presentation.footer, ...patch.footer };
|
|
282
|
+
for (const [key, value] of Object.entries(merged)) if (value === null) delete merged[key];
|
|
283
|
+
if (Object.keys(merged).length)
|
|
284
|
+
doc.presentation.footer = merged as Diagram['presentation']['footer'];
|
|
285
|
+
else delete doc.presentation.footer;
|
|
286
|
+
}
|
|
287
|
+
for (const key of ['nodes', 'edges', 'groups'] as const) {
|
|
288
|
+
const map = new Map<string, Record<string, unknown>>(doc[key].map((n) => [n.id, { ...n }]));
|
|
289
|
+
for (const item of patch[key] ?? []) {
|
|
290
|
+
const prior = map.get(item.id);
|
|
291
|
+
const next = { ...prior, ...item };
|
|
292
|
+
for (const field of ['style', 'appearance', 'ports'] as const) {
|
|
293
|
+
if (item[field] === null) {
|
|
294
|
+
delete next[field];
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (item[field] && typeof item[field] === 'object') {
|
|
298
|
+
const merged: Record<string, unknown> = {
|
|
299
|
+
...((prior?.[field] as Record<string, unknown>) ?? {}),
|
|
300
|
+
...(item[field] as Record<string, unknown>),
|
|
301
|
+
};
|
|
302
|
+
for (const [key, value] of Object.entries(merged)) if (value === null) delete merged[key];
|
|
303
|
+
if (Object.keys(merged).length) next[field] = merged;
|
|
304
|
+
else delete next[field];
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (next.path === null) delete next.path;
|
|
308
|
+
map.set(item.id, next);
|
|
309
|
+
}
|
|
310
|
+
for (const keyToRemove of patch.remove?.[key] ?? []) map.delete(keyToRemove);
|
|
311
|
+
(doc[key] as unknown) = [...map.values()];
|
|
312
|
+
}
|
|
313
|
+
const removedNodes = new Set(patch.remove?.nodes ?? []);
|
|
314
|
+
doc.edges = doc.edges.filter((e) => !removedNodes.has(e.source) && !removedNodes.has(e.target));
|
|
315
|
+
for (const key of removedNodes) delete doc.presentation.nodes[key];
|
|
316
|
+
const removedGroups = new Set(patch.remove?.groups ?? []);
|
|
317
|
+
for (const n of doc.nodes) if (n.group && removedGroups.has(n.group)) delete n.group;
|
|
318
|
+
for (const g of doc.groups) if (g.parent && removedGroups.has(g.parent)) delete g.parent;
|
|
319
|
+
for (const [key, value] of Object.entries(patch.overrides ?? {})) {
|
|
320
|
+
if (value === null) {
|
|
321
|
+
delete doc.presentation.nodes[key];
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
const merged: Record<string, unknown> = { ...doc.presentation.nodes[key] };
|
|
325
|
+
for (const [k, v] of Object.entries(value)) {
|
|
326
|
+
if (v === null) delete merged[k];
|
|
327
|
+
else merged[k] = k === 'style' ? { ...((merged[k] as object) ?? {}), ...(v as object) } : v;
|
|
328
|
+
}
|
|
329
|
+
if (Object.keys(merged).length) doc.presentation.nodes[key] = merged as NodeOverride;
|
|
330
|
+
else delete doc.presentation.nodes[key];
|
|
331
|
+
}
|
|
332
|
+
if (hasV2Features(doc)) doc.version = 2;
|
|
333
|
+
return parseDocument(doc);
|
|
334
|
+
}
|
|
335
|
+
function stable(value: unknown): unknown {
|
|
336
|
+
if (Array.isArray(value)) return value.map(stable);
|
|
337
|
+
if (value && typeof value === 'object')
|
|
338
|
+
return Object.fromEntries(
|
|
339
|
+
Object.entries(value)
|
|
340
|
+
.sort(([a], [b]) => a.localeCompare(b, 'en'))
|
|
341
|
+
.map(([k, v]) => [k, stable(v)]),
|
|
342
|
+
);
|
|
343
|
+
return value;
|
|
344
|
+
}
|
|
345
|
+
export function serializeDocument(doc: Diagram): string {
|
|
346
|
+
return JSON.stringify(stable(parseDocument(doc)), null, 2) + '\n';
|
|
347
|
+
}
|
|
348
|
+
export function fingerprint(doc: Diagram): string {
|
|
349
|
+
let hash = 2166136261;
|
|
350
|
+
for (const ch of serializeDocument(doc)) hash = Math.imul(hash ^ ch.charCodeAt(0), 16777619);
|
|
351
|
+
return (hash >>> 0).toString(16).padStart(8, '0');
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function portCountOn(ports: PortCounts | undefined, side: PortSide) {
|
|
355
|
+
return ports?.[side] ?? 1;
|
|
356
|
+
}
|
|
357
|
+
function checkPortIndex(
|
|
358
|
+
issues: { path: string; message: string }[],
|
|
359
|
+
edgeId: string,
|
|
360
|
+
end: 'source' | 'target',
|
|
361
|
+
side: PortSide | undefined,
|
|
362
|
+
index: number | undefined,
|
|
363
|
+
ports: PortCounts | undefined,
|
|
364
|
+
direction: 'RIGHT' | 'DOWN',
|
|
365
|
+
) {
|
|
366
|
+
if (index === undefined) return;
|
|
367
|
+
const chosen =
|
|
368
|
+
side ??
|
|
369
|
+
(direction === 'DOWN'
|
|
370
|
+
? end === 'source'
|
|
371
|
+
? 'bottom'
|
|
372
|
+
: 'top'
|
|
373
|
+
: end === 'source'
|
|
374
|
+
? 'right'
|
|
375
|
+
: 'left');
|
|
376
|
+
const count = portCountOn(ports, chosen);
|
|
377
|
+
if (index >= count)
|
|
378
|
+
issues.push({
|
|
379
|
+
path: `edges.${edgeId}.appearance.${end}Index`,
|
|
380
|
+
message: `Port ${index} is outside ${chosen} (${count} ${count === 1 ? 'point' : 'points'})`,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
function hasV2Features(doc: Diagram): boolean {
|
|
384
|
+
return !!(
|
|
385
|
+
!['architecture', 'flow'].includes(doc.type) ||
|
|
386
|
+
doc.presentation.designSystem ||
|
|
387
|
+
doc.presentation.footer ||
|
|
388
|
+
doc.layout.mode ||
|
|
389
|
+
doc.nodes.some(
|
|
390
|
+
(n) =>
|
|
391
|
+
n.style ||
|
|
392
|
+
n.role ||
|
|
393
|
+
n.placement ||
|
|
394
|
+
n.ports ||
|
|
395
|
+
!['service', 'database', 'queue', 'person', 'process', 'decision', 'client'].includes(
|
|
396
|
+
n.kind,
|
|
397
|
+
),
|
|
398
|
+
) ||
|
|
399
|
+
doc.edges.some((e) => e.appearance || e.role || e.path) ||
|
|
400
|
+
doc.groups.some((g) => g.style || g.role) ||
|
|
401
|
+
Object.values(doc.presentation.nodes).some((n) => n.style)
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
/** Explicit, lossless upgrade. v1 files remain v1 until migration or use of a v2 feature. */
|
|
405
|
+
export function migrateDocument(input: unknown): Diagram {
|
|
406
|
+
const doc = parseDocument(input);
|
|
407
|
+
return parseDocument({ ...doc, version: 2 });
|
|
408
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"regular":{"32":0.236,"33":0.284,"34":0.419,"35":0.713,"36":0.598,"37":0.927,"38":0.694,"39":0.242,"40":0.335,"41":0.335,"42":0.45,"43":0.6,"44":0.272,"45":0.399,"46":0.272,"47":0.383,"48":0.6,"49":0.6,"50":0.6,"51":0.6,"52":0.6,"53":0.6,"54":0.6,"55":0.6,"56":0.6,"57":0.6,"58":0.292,"59":0.292,"60":0.6,"61":0.6,"62":0.6,"63":0.477,"64":0.891,"65":0.641,"66":0.653,"67":0.621,"68":0.671,"69":0.583,"70":0.559,"71":0.695,"72":0.707,"73":0.4,"74":0.51,"75":0.634,"76":0.501,"77":0.812,"78":0.707,"79":0.708,"80":0.606,"81":0.708,"82":0.64,"83":0.581,"84":0.572,"85":0.678,"86":0.609,"87":0.891,"88":0.613,"89":0.593,"90":0.58,"91":0.317,"92":0.383,"93":0.317,"94":0.6,"95":0.565,"96":0.6,"97":0.534,"98":0.58,"99":0.503,"100":0.58,"101":0.549,"102":0.324,"103":0.528,"104":0.568,"105":0.25,"106":0.25,"107":0.527,"108":0.272,"109":0.873,"110":0.568,"111":0.56,"112":0.58,"113":0.58,"114":0.367,"115":0.487,"116":0.351,"117":0.568,"118":0.492,"119":0.768,"120":0.507,"121":0.499,"122":0.464,"123":0.343,"124":0.314,"125":0.343,"126":0.6,"160":0.236,"161":0.284,"162":0.514,"163":0.595,"164":0.612,"165":0.605,"166":0.314,"167":0.586,"168":0.6,"169":0.776,"170":0.399,"171":0.513,"172":0.6,"173":0.0,"174":0.476,"175":0.6,"176":0.468,"177":0.6,"178":0.346,"179":0.346,"180":0.6,"181":0.573,"182":0.652,"183":0.326,"184":0.6,"185":0.359,"186":0.398,"187":0.513,"188":0.847,"189":0.872,"190":0.824,"191":0.467,"192":0.641,"193":0.641,"194":0.641,"195":0.641,"196":0.641,"197":0.641,"198":0.907,"199":0.621,"200":0.583,"201":0.583,"202":0.583,"203":0.583,"204":0.4,"205":0.4,"206":0.4,"207":0.4,"208":0.674,"209":0.707,"210":0.708,"211":0.708,"212":0.708,"213":0.708,"214":0.708,"215":0.6,"216":0.708,"217":0.678,"218":0.678,"219":0.678,"220":0.678,"221":0.593,"222":0.606,"223":0.64,"224":0.534,"225":0.534,"226":0.534,"227":0.534,"228":0.534,"229":0.534,"230":0.864,"231":0.503,"232":0.549,"233":0.549,"234":0.549,"235":0.549,"236":0.25,"237":0.25,"238":0.25,"239":0.25,"240":0.555,"241":0.568,"242":0.56,"243":0.56,"244":0.56,"245":0.56,"246":0.56,"247":0.6,"248":0.568,"249":0.568,"250":0.568,"251":0.568,"252":0.568,"253":0.499,"254":0.58,"255":0.499,"256":0.641,"257":0.534,"258":0.641,"259":0.534,"260":0.641,"261":0.534,"262":0.621,"263":0.503,"264":0.621,"265":0.503,"266":0.621,"267":0.503,"268":0.621,"269":0.503,"270":0.671,"271":0.603,"272":0.674,"273":0.583,"274":0.583,"275":0.549,"276":0.583,"277":0.549,"278":0.583,"279":0.549,"280":0.583,"281":0.549,"282":0.583,"283":0.549,"284":0.695,"285":0.531,"286":0.695,"287":0.531,"288":0.695,"289":0.531,"290":0.695,"291":0.531,"292":0.707,"293":0.568,"294":0.713,"295":0.568,"296":0.4,"297":0.25,"298":0.4,"299":0.25,"300":0.4,"301":0.25,"302":0.4,"303":0.25,"304":0.4,"305":0.25,"306":0.645,"307":0.496,"308":0.51,"309":0.25,"310":0.634,"311":0.527,"312":0.527,"313":0.501,"314":0.272,"315":0.501,"316":0.272,"317":0.501,"318":0.274,"319":0.501,"320":0.358,"321":0.508,"322":0.278,"323":0.707,"324":0.568,"325":0.707,"326":0.568,"327":0.707,"328":0.568,"329":0.811,"330":0.707,"331":0.568,"332":0.708,"333":0.56,"334":0.708,"335":0.56,"336":0.708,"337":0.56,"338":0.985,"339":0.931,"340":0.64,"341":0.367,"342":0.64,"343":0.367,"344":0.64,"345":0.367,"346":0.581,"347":0.487,"348":0.581,"349":0.487,"350":0.581,"351":0.487,"352":0.581,"353":0.487,"354":0.572,"355":0.351,"356":0.572,"357":0.351,"358":0.582,"359":0.357,"360":0.678,"361":0.568,"362":0.678,"363":0.568,"364":0.678,"365":0.568,"366":0.678,"367":0.568,"368":0.678,"369":0.568,"370":0.678,"371":0.568,"372":0.891,"373":0.768,"374":0.593,"375":0.499,"376":0.593,"377":0.58,"378":0.464,"379":0.58,"380":0.464,"381":0.58,"382":0.464,"383":0.278,"399":0.708,"402":0.485,"416":0.708,"417":0.56,"431":0.678,"432":0.568,"461":0.641,"462":0.534,"463":0.4,"464":0.25,"465":0.708,"466":0.56,"467":0.678,"468":0.568,"469":0.678,"470":0.568,"471":0.678,"472":0.568,"473":0.678,"474":0.568,"475":0.678,"476":0.568,"506":0.641,"507":0.534,"508":0.907,"509":0.864,"510":0.708,"511":0.568,"536":0.581,"537":0.487,"538":0.572,"539":0.351,"567":0.25,"601":0.549,"699":0.6,"700":0.6,"710":0.6,"711":0.6,"728":0.6,"729":0.6,"730":0.6,"731":0.6,"732":0.6,"733":0.6,"768":0.0,"769":0.0,"770":0.0,"771":0.0,"772":0.0,"774":0.0,"775":0.0,"776":0.0,"777":0.0,"778":0.0,"779":0.0,"780":0.0,"786":0.0,"789":0.0,"795":0.0,"803":0.0,"806":0.0,"807":0.0,"808":0.0,"894":0.292,"900":0.6,"901":0.6,"902":0.641,"903":0.292,"904":0.609,"905":0.733,"906":0.459,"908":0.712,"910":0.677,"911":0.716,"912":0.295,"913":0.641,"914":0.653,"915":0.499,"916":0.643,"917":0.583,"918":0.58,"919":0.707,"920":0.708,"921":0.4,"922":0.634,"923":0.629,"924":0.812,"925":0.707,"926":0.584,"927":0.708,"928":0.693,"929":0.606,"931":0.569,"932":0.572,"933":0.593,"934":0.852,"935":0.613,"936":0.79,"937":0.716,"938":0.4,"939":0.593,"940":0.644,"941":0.518,"942":0.573,"943":0.295,"944":0.568,"945":0.644,"946":0.584,"947":0.502,"948":0.56,"949":0.518,"950":0.428,"951":0.573,"952":0.562,"953":0.295,"954":0.527,"955":0.509,"956":0.578,"957":0.511,"958":0.456,"959":0.56,"960":0.622,"961":0.552,"962":0.483,"963":0.583,"964":0.477,"965":0.568,"966":0.715,"967":0.496,"968":0.726,"969":0.736,"970":0.295,"971":0.568,"972":0.56,"973":0.568,"974":0.736,"1024":0.583,"1025":0.583,"1026":0.786,"1027":0.499,"1028":0.631,"1029":0.581,"1030":0.4,"1031":0.4,"1032":0.51,"1033":1.014,"1034":1.037,"1035":0.796,"1036":0.662,"1037":0.707,"1038":0.595,"1039":0.693,"1040":0.641,"1041":0.636,"1042":0.653,"1043":0.499,"1044":0.726,"1045":0.583,"1046":0.978,"1047":0.593,"1048":0.707,"1049":0.707,"1050":0.662,"1051":0.684,"1052":0.812,"1053":0.707,"1054":0.708,"1055":0.693,"1056":0.606,"1057":0.621,"1058":0.572,"1059":0.595,"1060":0.844,"1061":0.613,"1062":0.73,"1063":0.645,"1064":0.956,"1065":0.993,"1066":0.741,"1067":0.875,"1068":0.63,"1069":0.631,"1070":0.96,"1071":0.64,"1072":0.534,"1073":0.564,"1074":0.558,"1075":0.435,"1076":0.597,"1077":0.549,"1078":0.77,"1079":0.501,"1080":0.588,"1081":0.588,"1082":0.55,"1083":0.565,"1084":0.696,"1085":0.588,"1086":0.56,"1087":0.573,"1088":0.58,"1089":0.503,"1090":0.472,"1091":0.499,"1092":0.75,"1093":0.507,"1094":0.6,"1095":0.538,"1096":0.798,"1097":0.825,"1098":0.59,"1099":0.724,"1100":0.52,"1101":0.511,"1102":0.781,"1103":0.535,"1104":0.549,"1105":0.549,"1106":0.568,"1107":0.435,"1108":0.511,"1109":0.487,"1110":0.25,"1111":0.25,"1112":0.25,"1113":0.805,"1114":0.832,"1115":0.568,"1116":0.55,"1117":0.588,"1118":0.499,"1119":0.573,"1122":0.673,"1123":0.549,"1130":0.92,"1131":0.731,"1138":0.708,"1139":0.56,"1140":0.685,"1141":0.537,"1168":0.499,"1169":0.435,"1170":0.519,"1171":0.453,"1172":0.635,"1173":0.538,"1174":0.986,"1175":0.775,"1176":0.593,"1177":0.501,"1178":0.67,"1179":0.556,"1180":0.692,"1181":0.58,"1182":0.705,"1183":0.55,"1184":0.773,"1185":0.62,"1186":0.744,"1187":0.615,"1188":0.916,"1189":0.757,"1190":1.008,"1191":0.836,"1192":0.876,"1193":0.67,"1194":0.621,"1195":0.503,"1196":0.572,"1197":0.472,"1198":0.593,"1199":0.492,"1200":0.593,"1201":0.492,"1202":0.644,"1203":0.531,"1204":0.871,"1205":0.711,"1206":0.682,"1207":0.565,"1208":0.645,"1209":0.538,"1210":0.645,"1211":0.568,"1212":0.798,"1213":0.645,"1214":0.798,"1215":0.645,"1216":0.4,"1217":0.978,"1218":0.77,"1231":0.25,"1232":0.641,"1233":0.534,"1234":0.641,"1235":0.534,"1236":0.907,"1237":0.864,"1238":0.583,"1239":0.549,"1240":0.708,"1241":0.549,"1244":0.978,"1245":0.77,"1246":0.593,"1247":0.501,"1248":0.593,"1249":0.501,"1250":0.707,"1251":0.588,"1252":0.707,"1253":0.588,"1254":0.708,"1255":0.56,"1256":0.708,"1257":0.56,"1262":0.595,"1263":0.499,"1264":0.595,"1265":0.499,"1266":0.595,"1267":0.499,"1268":0.645,"1269":0.538,"1270":0.499,"1271":0.435,"1272":0.875,"1273":0.724,"1316":0.73,"1317":0.6,"3647":0.644,"7808":0.891,"7809":0.768,"7810":0.891,"7811":0.768,"7812":0.891,"7813":0.768,"7838":0.7,"7840":0.641,"7841":0.534,"7842":0.641,"7843":0.534,"7844":0.641,"7845":0.534,"7846":0.641,"7847":0.534,"7848":0.641,"7849":0.534,"7850":0.641,"7851":0.534,"7852":0.641,"7853":0.534,"7854":0.641,"7855":0.534,"7856":0.641,"7857":0.534,"7858":0.641,"7859":0.534,"7860":0.641,"7861":0.534,"7862":0.641,"7863":0.534,"7864":0.583,"7865":0.549,"7866":0.583,"7867":0.549,"7868":0.583,"7869":0.549,"7870":0.583,"7871":0.549,"7872":0.583,"7873":0.549,"7874":0.583,"7875":0.549,"7876":0.583,"7877":0.549,"7878":0.583,"7879":0.549,"7880":0.4,"7881":0.25,"7882":0.4,"7883":0.25,"7884":0.708,"7885":0.56,"7886":0.708,"7887":0.56,"7888":0.708,"7889":0.56,"7890":0.708,"7891":0.56,"7892":0.708,"7893":0.56,"7894":0.708,"7895":0.56,"7896":0.708,"7897":0.56,"7898":0.708,"7899":0.56,"7900":0.708,"7901":0.56,"7902":0.708,"7903":0.56,"7904":0.708,"7905":0.56,"7906":0.708,"7907":0.56,"7908":0.678,"7909":0.568,"7910":0.678,"7911":0.568,"7912":0.678,"7913":0.568,"7914":0.678,"7915":0.568,"7916":0.678,"7917":0.568,"7918":0.678,"7919":0.568,"7920":0.678,"7921":0.568,"7922":0.593,"7923":0.499,"7924":0.593,"7925":0.499,"7926":0.593,"7927":0.499,"7928":0.593,"7929":0.499,"8192":0.5,"8193":1.0,"8194":0.5,"8195":1.0,"8196":0.333,"8197":0.25,"8198":0.167,"8199":0.6,"8200":0.272,"8201":0.118,"8202":0.059,"8203":0.0,"8204":0.0,"8205":0.0,"8208":0.399,"8209":0.399,"8210":0.588,"8211":0.588,"8212":0.78,"8213":1.0,"8216":0.273,"8217":0.273,"8218":0.274,"8220":0.475,"8221":0.474,"8222":0.475,"8224":0.552,"8225":0.552,"8226":0.396,"8230":0.803,"8232":0.0,"8233":0.0,"8239":0.118,"8240":1.306,"8242":0.242,"8243":0.419,"8249":0.304,"8250":0.304,"8260":0.147,"8304":0.378,"8308":0.346,"8309":0.348,"8310":0.359,"8311":0.335,"8312":0.376,"8313":0.359,"8320":0.378,"8321":0.359,"8322":0.346,"8323":0.346,"8324":0.346,"8325":0.348,"8326":0.359,"8327":0.335,"8328":0.376,"8329":0.359,"8353":0.628,"8356":0.595,"8358":0.696,"8360":0.713,"8361":0.952,"8362":0.77,"8363":0.58,"8364":0.625,"8365":0.617,"8366":0.608,"8369":0.628,"8370":0.676,"8372":0.628,"8373":0.628,"8376":0.608,"8377":0.605,"8378":0.606,"8381":0.623,"8383":0.643,"8467":0.488,"8470":1.027,"8482":0.658,"8486":0.716,"8494":0.726,"8528":0.861,"8529":0.88,"8531":0.872,"8532":0.859,"8533":0.869,"8534":0.856,"8535":0.846,"8536":0.851,"8537":0.86,"8538":0.839,"8539":0.897,"8540":0.874,"8541":0.876,"8542":0.843,"8592":0.82,"8593":0.82,"8594":0.82,"8595":0.82,"8596":0.82,"8597":0.82,"8598":0.82,"8599":0.82,"8600":0.82,"8601":0.82,"8617":0.82,"8618":0.82,"8624":0.82,"8625":0.82,"8626":0.82,"8627":0.82,"8630":0.82,"8631":0.82,"8634":0.82,"8635":0.82,"8644":0.82,"8646":0.82,"8706":0.591,"8710":0.643,"8719":0.706,"8721":0.504,"8722":0.6,"8725":0.147,"8729":0.326,"8730":0.6,"8734":0.74,"8747":0.426,"8758":0.292,"8776":0.6,"8800":0.6,"8804":0.6,"8805":0.6,"9674":0.6,"10003":0.912,"10060":0.912,"11022":0.82,"11023":0.82,"11024":0.82,"11025":0.82,"60640":1.177,"61388":1.046,"63191":0.0,"63192":0.0,"64257":0.567,"64258":0.596,"65279":0.0,"65533":1.0},"semibold":{"32":0.236,"33":0.309,"34":0.471,"35":0.656,"36":0.6,"37":0.96,"38":0.713,"39":0.26,"40":0.337,"41":0.337,"42":0.556,"43":0.6,"44":0.298,"45":0.402,"46":0.298,"47":0.437,"48":0.6,"49":0.6,"50":0.6,"51":0.6,"52":0.6,"53":0.6,"54":0.6,"55":0.6,"56":0.6,"57":0.6,"58":0.318,"59":0.318,"60":0.6,"61":0.6,"62":0.6,"63":0.493,"64":0.899,"65":0.672,"66":0.663,"67":0.642,"68":0.689,"69":0.6,"70":0.577,"71":0.712,"72":0.719,"73":0.423,"74":0.545,"75":0.678,"76":0.521,"77":0.816,"78":0.719,"79":0.712,"80":0.641,"81":0.712,"82":0.664,"83":0.611,"84":0.58,"85":0.69,"86":0.638,"87":0.949,"88":0.655,"89":0.632,"90":0.599,"91":0.329,"92":0.437,"93":0.329,"94":0.6,"95":0.559,"96":0.6,"97":0.559,"98":0.6,"99":0.513,"100":0.6,"101":0.558,"102":0.35,"103":0.545,"104":0.588,"105":0.276,"106":0.276,"107":0.562,"108":0.294,"109":0.888,"110":0.588,"111":0.563,"112":0.6,"113":0.6,"114":0.393,"115":0.499,"116":0.374,"117":0.588,"118":0.524,"119":0.819,"120":0.544,"121":0.524,"122":0.502,"123":0.363,"124":0.376,"125":0.363,"126":0.6,"160":0.236,"161":0.309,"162":0.541,"163":0.586,"164":0.624,"165":0.615,"166":0.376,"167":0.574,"168":0.6,"169":0.788,"170":0.434,"171":0.545,"172":0.6,"173":0.0,"174":0.468,"175":0.6,"176":0.47,"177":0.6,"178":0.347,"179":0.345,"180":0.6,"181":0.593,"182":0.67,"183":0.35,"184":0.6,"185":0.348,"186":0.424,"187":0.545,"188":0.84,"189":0.863,"190":0.827,"191":0.486,"192":0.672,"193":0.672,"194":0.672,"195":0.672,"196":0.672,"197":0.672,"198":0.95,"199":0.642,"200":0.6,"201":0.6,"202":0.6,"203":0.6,"204":0.423,"205":0.423,"206":0.423,"207":0.423,"208":0.694,"209":0.719,"210":0.712,"211":0.712,"212":0.712,"213":0.712,"214":0.712,"215":0.6,"216":0.712,"217":0.69,"218":0.69,"219":0.69,"220":0.69,"221":0.632,"222":0.641,"223":0.677,"224":0.559,"225":0.559,"226":0.559,"227":0.559,"228":0.559,"229":0.559,"230":0.864,"231":0.513,"232":0.558,"233":0.558,"234":0.558,"235":0.558,"236":0.276,"237":0.276,"238":0.276,"239":0.276,"240":0.589,"241":0.588,"242":0.563,"243":0.563,"244":0.563,"245":0.563,"246":0.563,"247":0.6,"248":0.571,"249":0.588,"250":0.588,"251":0.588,"252":0.588,"253":0.524,"254":0.6,"255":0.524,"256":0.672,"257":0.559,"258":0.672,"259":0.559,"260":0.672,"261":0.559,"262":0.642,"263":0.513,"264":0.642,"265":0.513,"266":0.642,"267":0.513,"268":0.642,"269":0.513,"270":0.689,"271":0.6,"272":0.694,"273":0.603,"274":0.6,"275":0.558,"276":0.6,"277":0.558,"278":0.6,"279":0.558,"280":0.6,"281":0.558,"282":0.6,"283":0.558,"284":0.712,"285":0.553,"286":0.712,"287":0.553,"288":0.712,"289":0.553,"290":0.712,"291":0.553,"292":0.719,"293":0.588,"294":0.728,"295":0.588,"296":0.423,"297":0.276,"298":0.423,"299":0.276,"300":0.423,"301":0.276,"302":0.423,"303":0.276,"304":0.423,"305":0.276,"306":0.653,"307":0.546,"308":0.545,"309":0.276,"310":0.678,"311":0.562,"312":0.562,"313":0.521,"314":0.294,"315":0.521,"316":0.294,"317":0.521,"318":0.294,"319":0.521,"320":0.421,"321":0.531,"322":0.303,"323":0.719,"324":0.588,"325":0.719,"326":0.588,"327":0.719,"328":0.588,"329":0.864,"330":0.719,"331":0.588,"332":0.712,"333":0.563,"334":0.712,"335":0.563,"336":0.712,"337":0.563,"338":0.994,"339":0.91,"340":0.664,"341":0.393,"342":0.664,"343":0.393,"344":0.664,"345":0.393,"346":0.611,"347":0.499,"348":0.611,"349":0.499,"350":0.611,"351":0.499,"352":0.611,"353":0.499,"354":0.58,"355":0.374,"356":0.58,"357":0.377,"358":0.59,"359":0.381,"360":0.69,"361":0.588,"362":0.69,"363":0.588,"364":0.69,"365":0.588,"366":0.69,"367":0.588,"368":0.69,"369":0.588,"370":0.69,"371":0.588,"372":0.949,"373":0.819,"374":0.632,"375":0.524,"376":0.632,"377":0.599,"378":0.502,"379":0.599,"380":0.502,"381":0.599,"382":0.502,"383":0.302,"399":0.712,"402":0.484,"416":0.712,"417":0.563,"431":0.69,"432":0.588,"461":0.672,"462":0.559,"463":0.423,"464":0.276,"465":0.712,"466":0.563,"467":0.69,"468":0.588,"469":0.69,"470":0.588,"471":0.69,"472":0.588,"473":0.69,"474":0.588,"475":0.69,"476":0.588,"506":0.672,"507":0.559,"508":0.95,"509":0.864,"510":0.712,"511":0.571,"536":0.611,"537":0.499,"538":0.58,"539":0.374,"567":0.276,"601":0.558,"699":0.6,"700":0.6,"710":0.6,"711":0.6,"728":0.6,"729":0.6,"730":0.6,"731":0.6,"732":0.6,"733":0.6,"768":0.0,"769":0.0,"770":0.0,"771":0.0,"772":0.0,"774":0.0,"775":0.0,"776":0.0,"777":0.0,"778":0.0,"779":0.0,"780":0.0,"786":0.0,"789":0.0,"795":0.0,"803":0.0,"806":0.0,"807":0.0,"808":0.0,"894":0.318,"900":0.6,"901":0.6,"902":0.672,"903":0.318,"904":0.675,"905":0.794,"906":0.527,"908":0.742,"910":0.758,"911":0.751,"912":0.32,"913":0.672,"914":0.663,"915":0.51,"916":0.672,"917":0.6,"918":0.599,"919":0.719,"920":0.719,"921":0.423,"922":0.678,"923":0.659,"924":0.816,"925":0.719,"926":0.599,"927":0.712,"928":0.704,"929":0.641,"931":0.598,"932":0.58,"933":0.632,"934":0.849,"935":0.655,"936":0.825,"937":0.721,"938":0.423,"939":0.632,"940":0.66,"941":0.525,"942":0.599,"943":0.32,"944":0.578,"945":0.66,"946":0.602,"947":0.529,"948":0.563,"949":0.525,"950":0.435,"951":0.599,"952":0.572,"953":0.32,"954":0.564,"955":0.529,"956":0.605,"957":0.531,"958":0.445,"959":0.563,"960":0.645,"961":0.57,"962":0.5,"963":0.585,"964":0.493,"965":0.578,"966":0.756,"967":0.531,"968":0.749,"969":0.76,"970":0.32,"971":0.578,"972":0.563,"973":0.578,"974":0.76,"1024":0.6,"1025":0.6,"1026":0.801,"1027":0.51,"1028":0.659,"1029":0.611,"1030":0.423,"1031":0.423,"1032":0.545,"1033":1.038,"1034":1.04,"1035":0.811,"1036":0.671,"1037":0.719,"1038":0.621,"1039":0.704,"1040":0.672,"1041":0.651,"1042":0.663,"1043":0.51,"1044":0.789,"1045":0.6,"1046":0.998,"1047":0.604,"1048":0.719,"1049":0.719,"1050":0.671,"1051":0.723,"1052":0.816,"1053":0.719,"1054":0.712,"1055":0.704,"1056":0.641,"1057":0.642,"1058":0.58,"1059":0.621,"1060":0.886,"1061":0.655,"1062":0.759,"1063":0.669,"1064":1.008,"1065":1.064,"1066":0.753,"1067":0.916,"1068":0.653,"1069":0.659,"1070":1.0,"1071":0.667,"1072":0.559,"1073":0.566,"1074":0.571,"1075":0.441,"1076":0.64,"1077":0.558,"1078":0.838,"1079":0.522,"1080":0.605,"1081":0.605,"1082":0.579,"1083":0.597,"1084":0.716,"1085":0.605,"1086":0.563,"1087":0.59,"1088":0.6,"1089":0.513,"1090":0.486,"1091":0.524,"1092":0.788,"1093":0.544,"1094":0.623,"1095":0.567,"1096":0.83,"1097":0.864,"1098":0.624,"1099":0.784,"1100":0.549,"1101":0.527,"1102":0.81,"1103":0.57,"1104":0.558,"1105":0.558,"1106":0.592,"1107":0.441,"1108":0.528,"1109":0.499,"1110":0.276,"1111":0.276,"1112":0.276,"1113":0.846,"1114":0.858,"1115":0.588,"1116":0.579,"1117":0.605,"1118":0.524,"1119":0.59,"1122":0.689,"1123":0.557,"1130":0.988,"1131":0.756,"1138":0.712,"1139":0.562,"1140":0.671,"1141":0.545,"1168":0.51,"1169":0.441,"1170":0.537,"1171":0.459,"1172":0.658,"1173":0.563,"1174":1.016,"1175":0.845,"1176":0.604,"1177":0.522,"1178":0.69,"1179":0.588,"1180":0.736,"1181":0.644,"1182":0.707,"1183":0.579,"1184":0.772,"1185":0.655,"1186":0.774,"1187":0.638,"1188":0.913,"1189":0.761,"1190":1.027,"1191":0.852,"1192":0.899,"1193":0.714,"1194":0.642,"1195":0.513,"1196":0.58,"1197":0.486,"1198":0.632,"1199":0.525,"1200":0.632,"1201":0.525,"1202":0.68,"1203":0.561,"1204":0.892,"1205":0.725,"1206":0.724,"1207":0.6,"1208":0.683,"1209":0.581,"1210":0.668,"1211":0.588,"1212":0.854,"1213":0.689,"1214":0.854,"1215":0.689,"1216":0.423,"1217":0.998,"1218":0.838,"1231":0.276,"1232":0.672,"1233":0.559,"1234":0.672,"1235":0.559,"1236":0.95,"1237":0.864,"1238":0.6,"1239":0.558,"1240":0.712,"1241":0.558,"1244":0.998,"1245":0.838,"1246":0.604,"1247":0.522,"1248":0.593,"1249":0.501,"1250":0.719,"1251":0.605,"1252":0.719,"1253":0.605,"1254":0.712,"1255":0.563,"1256":0.712,"1257":0.562,"1262":0.621,"1263":0.524,"1264":0.621,"1265":0.524,"1266":0.621,"1267":0.524,"1268":0.669,"1269":0.567,"1270":0.51,"1271":0.441,"1272":0.916,"1273":0.784,"1316":0.76,"1317":0.623,"3647":0.659,"7808":0.949,"7809":0.819,"7810":0.949,"7811":0.819,"7812":0.949,"7813":0.819,"7838":0.722,"7840":0.672,"7841":0.559,"7842":0.672,"7843":0.559,"7844":0.672,"7845":0.559,"7846":0.672,"7847":0.559,"7848":0.672,"7849":0.559,"7850":0.672,"7851":0.559,"7852":0.672,"7853":0.559,"7854":0.672,"7855":0.559,"7856":0.672,"7857":0.559,"7858":0.672,"7859":0.559,"7860":0.672,"7861":0.559,"7862":0.672,"7863":0.559,"7864":0.6,"7865":0.558,"7866":0.6,"7867":0.558,"7868":0.6,"7869":0.558,"7870":0.6,"7871":0.558,"7872":0.6,"7873":0.558,"7874":0.6,"7875":0.558,"7876":0.6,"7877":0.558,"7878":0.6,"7879":0.558,"7880":0.423,"7881":0.276,"7882":0.423,"7883":0.276,"7884":0.712,"7885":0.563,"7886":0.712,"7887":0.563,"7888":0.712,"7889":0.563,"7890":0.712,"7891":0.563,"7892":0.712,"7893":0.563,"7894":0.712,"7895":0.563,"7896":0.712,"7897":0.563,"7898":0.712,"7899":0.563,"7900":0.712,"7901":0.563,"7902":0.712,"7903":0.563,"7904":0.712,"7905":0.563,"7906":0.712,"7907":0.563,"7908":0.69,"7909":0.588,"7910":0.69,"7911":0.588,"7912":0.69,"7913":0.588,"7914":0.69,"7915":0.588,"7916":0.69,"7917":0.588,"7918":0.69,"7919":0.588,"7920":0.69,"7921":0.588,"7922":0.632,"7923":0.524,"7924":0.632,"7925":0.524,"7926":0.632,"7927":0.524,"7928":0.632,"7929":0.524,"8192":0.5,"8193":1.0,"8194":0.5,"8195":1.0,"8196":0.333,"8197":0.25,"8198":0.167,"8199":0.6,"8200":0.298,"8201":0.118,"8202":0.059,"8203":0.0,"8204":0.0,"8205":0.0,"8208":0.402,"8209":0.402,"8210":0.588,"8211":0.588,"8212":0.78,"8213":1.0,"8216":0.292,"8217":0.292,"8218":0.295,"8220":0.517,"8221":0.517,"8222":0.52,"8224":0.531,"8225":0.545,"8226":0.42,"8230":0.868,"8232":0.0,"8233":0.0,"8239":0.118,"8240":1.359,"8242":0.26,"8243":0.471,"8249":0.313,"8250":0.313,"8260":0.147,"8304":0.372,"8308":0.346,"8309":0.354,"8310":0.357,"8311":0.328,"8312":0.36,"8313":0.357,"8320":0.372,"8321":0.348,"8322":0.347,"8323":0.345,"8324":0.346,"8325":0.354,"8326":0.357,"8327":0.328,"8328":0.36,"8329":0.357,"8353":0.62,"8356":0.586,"8358":0.752,"8360":0.84,"8361":1.002,"8362":0.873,"8363":0.577,"8364":0.627,"8365":0.664,"8366":0.604,"8369":0.677,"8370":0.67,"8372":0.639,"8373":0.613,"8376":0.604,"8377":0.622,"8378":0.61,"8381":0.65,"8383":0.659,"8467":0.534,"8470":1.05,"8482":0.627,"8486":0.721,"8494":0.718,"8528":0.854,"8529":0.871,"8531":0.864,"8532":0.859,"8533":0.868,"8534":0.863,"8535":0.855,"8536":0.861,"8537":0.837,"8538":0.833,"8539":0.87,"8540":0.857,"8541":0.866,"8542":0.823,"8592":0.876,"8593":0.876,"8594":0.876,"8595":0.876,"8596":0.876,"8597":0.876,"8598":0.876,"8599":0.876,"8600":0.876,"8601":0.876,"8617":0.876,"8618":0.876,"8624":0.876,"8625":0.876,"8626":0.876,"8627":0.876,"8630":0.876,"8631":0.876,"8634":0.876,"8635":0.876,"8644":0.876,"8646":0.876,"8706":0.588,"8710":0.672,"8719":0.72,"8721":0.542,"8722":0.6,"8725":0.147,"8729":0.35,"8730":0.6,"8734":0.776,"8747":0.442,"8758":0.318,"8776":0.6,"8800":0.6,"8804":0.6,"8805":0.6,"9674":0.6,"10003":0.912,"10060":0.912,"11022":0.876,"11023":0.876,"11024":0.876,"11025":0.876,"60640":1.177,"61388":1.046,"63191":0.0,"63192":0.0,"64257":0.624,"64258":0.644,"65279":0.0,"65533":1.0}}
|