svgmapviewer-tools-floors 0.0.1
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/LICENSE +15 -0
- package/inkscape/extensions/Attic/fix_guides.inx +17 -0
- package/inkscape/extensions/Attic/fix_guides.py +30 -0
- package/inkscape/extensions/Attic/fix_symbol_links.inx +17 -0
- package/inkscape/extensions/Attic/fix_symbol_links.py +71 -0
- package/inkscape/extensions/Attic/flatten_style.inx +17 -0
- package/inkscape/extensions/Attic/flatten_style.py +31 -0
- package/inkscape/extensions/Attic/load_markers.inx +17 -0
- package/inkscape/extensions/Attic/load_markers.py +117 -0
- package/inkscape/extensions/Attic/load_patterns.inx +17 -0
- package/inkscape/extensions/Attic/load_patterns.py +116 -0
- package/inkscape/extensions/Attic/load_symbols.inx +17 -0
- package/inkscape/extensions/Attic/load_symbols.py +164 -0
- package/inkscape/extensions/Attic/renumber_tree.inx +24 -0
- package/inkscape/extensions/Attic/renumber_tree.py +39 -0
- package/inkscape/extensions/Attic/repeat_path.inx +17 -0
- package/inkscape/extensions/Attic/repeat_path.py +58 -0
- package/inkscape/extensions/Attic/resolve_facility_links.inx +19 -0
- package/inkscape/extensions/Attic/resolve_facility_links.py +16 -0
- package/inkscape/extensions/Attic/sort_symbols.inx +17 -0
- package/inkscape/extensions/Attic/sort_symbols.py +48 -0
- package/inkscape/extensions/Attic/symbol_load.inx +17 -0
- package/inkscape/extensions/Attic/symbol_load.py +99 -0
- package/inkscape/extensions/Attic/tidy_tree.inx +22 -0
- package/inkscape/extensions/Attic/tidy_tree.py +178 -0
- package/inkscape/extensions/Attic/use_shop.inx +22 -0
- package/inkscape/extensions/Attic/use_shop.py +26 -0
- package/inkscape/extensions/README.md +34 -0
- package/inkscape/extensions/daijimaps/__init__.py +72 -0
- package/inkscape/extensions/daijimaps/address_tree.py +231 -0
- package/inkscape/extensions/daijimaps/common.py +49 -0
- package/inkscape/extensions/daijimaps/generate_addresses.py +41 -0
- package/inkscape/extensions/daijimaps/guards.py +47 -0
- package/inkscape/extensions/daijimaps/map_layer.py +47 -0
- package/inkscape/extensions/daijimaps/name.py +167 -0
- package/inkscape/extensions/daijimaps/renumber.py +38 -0
- package/inkscape/extensions/daijimaps/resolve_labels.py +65 -0
- package/inkscape/extensions/daijimaps/resolve_names.py +170 -0
- package/inkscape/extensions/daijimaps/save_addresses.py +274 -0
- package/inkscape/extensions/daijimaps/types.py +128 -0
- package/inkscape/extensions/daijimaps/visit_parents.py +37 -0
- package/inkscape/extensions/extract_labels.py +79 -0
- package/inkscape/extensions/fixup_floor_svg.py +28 -0
- package/inkscape/extensions/fixup_texts.inx +15 -0
- package/inkscape/extensions/fixup_texts.py +110 -0
- package/inkscape/extensions/fixup_tree.inx +15 -0
- package/inkscape/extensions/fixup_tree.py +17 -0
- package/inkscape/extensions/flatten_transform.inx +17 -0
- package/inkscape/extensions/flatten_transform.py +63 -0
- package/inkscape/extensions/import_labels.inx +20 -0
- package/inkscape/extensions/import_labels.py +52 -0
- package/inkscape/extensions/import_shops.inx +20 -0
- package/inkscape/extensions/import_shops.py +47 -0
- package/inkscape/extensions/install.sh +14 -0
- package/inkscape/extensions/load_shops.inx +20 -0
- package/inkscape/extensions/load_shops.py +86 -0
- package/inkscape/extensions/renumber_group.inx +15 -0
- package/inkscape/extensions/renumber_group.py +17 -0
- package/inkscape/extensions/resolve_labels.inx +20 -0
- package/inkscape/extensions/resolve_labels.py +142 -0
- package/inkscape/extensions/resolve_shops.inx +20 -0
- package/inkscape/extensions/resolve_shops.py +73 -0
- package/inkscape/extensions/unresolve_labels.inx +20 -0
- package/inkscape/extensions/unresolve_labels.py +53 -0
- package/inkscape/extensions/unresolve_shops.inx +20 -0
- package/inkscape/extensions/unresolve_shops.py +56 -0
- package/inkscape/templates/floors.svg +665 -0
- package/map-extract-floors.js +821 -0
- package/package.json +19 -0
- package/pyproject.toml +20 -0
- package/scripts/inkex-inkscape +14 -0
- package/scripts/inkex-python +14 -0
- package/scripts/inkex-setup +6 -0
- package/scripts/labels.sh +18 -0
- package/scripts/regen.py +77 -0
- package/scripts/regen.sh +24 -0
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/inkscape/bb.ts
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
var allBoundingBoxes = /* @__PURE__ */ new Map();
|
|
6
|
+
var parseBoundingBoxCSV = (content) => {
|
|
7
|
+
content
|
|
8
|
+
.split(/\n/)
|
|
9
|
+
.filter((s) => s !== "")
|
|
10
|
+
.filter((s) => s.match(/^[A-Z]/))
|
|
11
|
+
.map((s) => {
|
|
12
|
+
const values = s.split(/,/);
|
|
13
|
+
if (values.length === 5) {
|
|
14
|
+
try {
|
|
15
|
+
const nums = values.slice(1).map(parseFloat);
|
|
16
|
+
allBoundingBoxes.set(values[0], {
|
|
17
|
+
x: nums[0],
|
|
18
|
+
y: nums[1],
|
|
19
|
+
width: nums[2],
|
|
20
|
+
height: nums[3],
|
|
21
|
+
});
|
|
22
|
+
} catch (e) {
|
|
23
|
+
console.log(e);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return s;
|
|
27
|
+
});
|
|
28
|
+
console.log("bb:", allBoundingBoxes);
|
|
29
|
+
};
|
|
30
|
+
var generateBoundingBoxCSV = (infile, outdir) => {
|
|
31
|
+
const res = spawnSync("inkscape", ["-S", infile], {
|
|
32
|
+
cwd: outdir,
|
|
33
|
+
});
|
|
34
|
+
return res.stdout.toString();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/lib/transform.ts
|
|
38
|
+
import tp from "@jutaz/transform-parser";
|
|
39
|
+
function parseTransformForAddress(transform) {
|
|
40
|
+
const p = tp.parse(transform);
|
|
41
|
+
if (p) {
|
|
42
|
+
if (p.length === 1) {
|
|
43
|
+
const t = p[0];
|
|
44
|
+
if (t.type === "translate" && t.z === null) {
|
|
45
|
+
if (t.x?.unit === null && t.y?.unit === null) {
|
|
46
|
+
return { x: t.x?.value ?? 0, y: t.y?.value ?? 0 };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/lib/inkscape.ts
|
|
55
|
+
var getLabel = (n) => getStringProperty(n, "inkscape:label");
|
|
56
|
+
var getTransform = (n) => getStringProperty(n, "transform");
|
|
57
|
+
function getName(n) {
|
|
58
|
+
const a = "name" in n ? n?.name : void 0;
|
|
59
|
+
return typeof a === "string" ? a : null;
|
|
60
|
+
}
|
|
61
|
+
function getHref(n) {
|
|
62
|
+
return getStringProperty(n, "xlink:href") || getStringProperty(n, "href");
|
|
63
|
+
}
|
|
64
|
+
function getStringProperty(n, p) {
|
|
65
|
+
const a = "attributes" in n ? n?.attributes?.[p] : void 0;
|
|
66
|
+
return typeof a === "string" ? a : null;
|
|
67
|
+
}
|
|
68
|
+
function getPoint(e) {
|
|
69
|
+
const name = getName(e);
|
|
70
|
+
if (name === "use") {
|
|
71
|
+
const x2 = getTransform(e);
|
|
72
|
+
if (x2 !== null) {
|
|
73
|
+
const p = parseTransformForAddress(x2);
|
|
74
|
+
if (p !== null) {
|
|
75
|
+
const href = getHref(e);
|
|
76
|
+
if (href) {
|
|
77
|
+
const id = href.replace(/^#/, "");
|
|
78
|
+
const bb = allBoundingBoxes.get(id);
|
|
79
|
+
if (bb !== void 0) {
|
|
80
|
+
const r = bb.width / 2;
|
|
81
|
+
return { ...p, r };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} else if (name === "circle" || name === "ellipse") {
|
|
87
|
+
const cx = getStringProperty(e, "cx");
|
|
88
|
+
const cy = getStringProperty(e, "cy");
|
|
89
|
+
if (typeof cx === "string" && typeof cy === "string") {
|
|
90
|
+
try {
|
|
91
|
+
const x2 = parseFloat(cx);
|
|
92
|
+
const y = parseFloat(cy);
|
|
93
|
+
if (name === "circle") {
|
|
94
|
+
const r = parseFloat(getStringProperty(e, "r") || "");
|
|
95
|
+
if (typeof r === "number") {
|
|
96
|
+
return { x: x2, y, r };
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
const rx = parseFloat(getStringProperty(e, "rx") || "");
|
|
100
|
+
const ry = parseFloat(getStringProperty(e, "ry") || "");
|
|
101
|
+
if (typeof rx === "number" && typeof ry === "number") {
|
|
102
|
+
return { x: x2, y, r: (rx + ry) / 2 };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} catch (e2) {
|
|
106
|
+
console.log(e2);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
function isPoint(e) {
|
|
113
|
+
const label = getLabel(e);
|
|
114
|
+
if (label !== null) {
|
|
115
|
+
if (label.match(/^[1-9][0-9]*$/)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
function buildAddress(n, parents) {
|
|
122
|
+
const suffix = getLabel(n);
|
|
123
|
+
if (suffix === null) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const prefix = parents
|
|
127
|
+
.filter(getLabel)
|
|
128
|
+
.map(getLabel)
|
|
129
|
+
.join("-")
|
|
130
|
+
.replace(/-Content-/, "-")
|
|
131
|
+
.replace(/^/, "A");
|
|
132
|
+
const address = prefix && suffix ? `${prefix}-${suffix}` : "";
|
|
133
|
+
return checkAddress(address) ? address : null;
|
|
134
|
+
}
|
|
135
|
+
function checkAddress(address) {
|
|
136
|
+
return address !== "" && /^.*-[0-9]+$/.test(address);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/lib/utils/snake-to-camel.ts
|
|
140
|
+
var capitalize = (s) => {
|
|
141
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
142
|
+
};
|
|
143
|
+
var snakeToCamel = (k) => {
|
|
144
|
+
if (k.match(/^.*-.*$/)) {
|
|
145
|
+
return k
|
|
146
|
+
.split(/-/)
|
|
147
|
+
.map((s, i) => (i === 0 ? s : capitalize(s)))
|
|
148
|
+
.join("");
|
|
149
|
+
}
|
|
150
|
+
return k;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// src/lib/inkscape/svg.ts
|
|
154
|
+
import { pipe } from "effect";
|
|
155
|
+
import { filter } from "unist-util-filter";
|
|
156
|
+
import { convert, is } from "unist-util-is";
|
|
157
|
+
import { map } from "unist-util-map";
|
|
158
|
+
import { x } from "xastscript";
|
|
159
|
+
var HIDDEN_GROUPS_RE =
|
|
160
|
+
/(\(Background\)|\(Names\)|\(Unresolved Names\)|Shops|Facilities)/;
|
|
161
|
+
var testRemoveHiddenNodes = convert((n) => {
|
|
162
|
+
if (is(n, "cdata")) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
if (is(n, "comment")) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
if (is(n, "instruction")) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
if (is(n, "text")) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
if ("attributes" in n) {
|
|
175
|
+
if (n.attributes["inkscape:label"]?.match(HIDDEN_GROUPS_RE)) return false;
|
|
176
|
+
}
|
|
177
|
+
if ("children" in n && n.children.length === 0 && n.name === "g") {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
return true;
|
|
181
|
+
});
|
|
182
|
+
var fixupRemoveHiddenNodes = (tree) => {
|
|
183
|
+
return filter(tree, { cascade: false }, testRemoveHiddenNodes);
|
|
184
|
+
};
|
|
185
|
+
var fixupId = (a) => {
|
|
186
|
+
if (a["id"]?.match(/^[a-z]/)) {
|
|
187
|
+
delete a["id"];
|
|
188
|
+
}
|
|
189
|
+
return a;
|
|
190
|
+
};
|
|
191
|
+
var fixupHref = (a) => {
|
|
192
|
+
const xlinkHref = a["xlink:href"];
|
|
193
|
+
if (xlinkHref) {
|
|
194
|
+
delete a["xlink:href"];
|
|
195
|
+
a["href"] = xlinkHref;
|
|
196
|
+
return a;
|
|
197
|
+
}
|
|
198
|
+
return a;
|
|
199
|
+
};
|
|
200
|
+
var conv = (a) => {
|
|
201
|
+
const patterns = [/^style$/, /^inkscape:.*$/, /^sodipodi:.*$/];
|
|
202
|
+
for (const [k] of Object.entries(a)) {
|
|
203
|
+
for (const p of patterns) {
|
|
204
|
+
if (k.match(p)) {
|
|
205
|
+
delete a[k];
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return a;
|
|
210
|
+
};
|
|
211
|
+
var fixupSnake = (a) => {
|
|
212
|
+
for (const [k, v] of Object.entries(a)) {
|
|
213
|
+
if (k.match(/-/)) {
|
|
214
|
+
const kk = snakeToCamel(k);
|
|
215
|
+
delete a[k];
|
|
216
|
+
a[kk] = v;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return a;
|
|
220
|
+
};
|
|
221
|
+
var fixupAttributes = (tree) => {
|
|
222
|
+
return tree === void 0
|
|
223
|
+
? tree
|
|
224
|
+
: map(tree, (x2) => {
|
|
225
|
+
if (is(x2, "element")) {
|
|
226
|
+
return {
|
|
227
|
+
...x2,
|
|
228
|
+
attributes: pipe(
|
|
229
|
+
x2.attributes,
|
|
230
|
+
conv,
|
|
231
|
+
fixupId,
|
|
232
|
+
fixupHref,
|
|
233
|
+
fixupSnake,
|
|
234
|
+
),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
return x2;
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
var fixupElements = (tree) =>
|
|
241
|
+
// XXX call fixupRemoveHiddenNodes twise
|
|
242
|
+
pipe(tree, fixupRemoveHiddenNodes, fixupRemoveHiddenNodes, fixupAttributes);
|
|
243
|
+
|
|
244
|
+
// src/lib/inkscape/floors-floors.ts
|
|
245
|
+
import * as Doc from "@effect/printer/Doc";
|
|
246
|
+
import { pipe as pipe2 } from "effect";
|
|
247
|
+
import * as fs from "fs";
|
|
248
|
+
import { is as is2 } from "unist-util-is";
|
|
249
|
+
import { visitParents } from "unist-util-visit-parents";
|
|
250
|
+
import { toXml } from "xast-util-to-xml";
|
|
251
|
+
var allLayerNames = new Array();
|
|
252
|
+
var saveAllFloorLayerNames = (ast) => {
|
|
253
|
+
visitParents(ast, (n) => {
|
|
254
|
+
if (is2(n, "element") && n.name === "g") {
|
|
255
|
+
const label = n.attributes["inkscape:label"];
|
|
256
|
+
if (
|
|
257
|
+
n.attributes["inkscape:groupmode"] === "layer" && // exclude e.g. (Assets)
|
|
258
|
+
label?.match(/[^(]/)
|
|
259
|
+
) {
|
|
260
|
+
allLayerNames.push(label);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
};
|
|
265
|
+
var renderFloorTsx = (layer) => {
|
|
266
|
+
const jsx = pipe2(layer.element, fixupElements, (e) =>
|
|
267
|
+
e === void 0
|
|
268
|
+
? "<g/>"
|
|
269
|
+
: toXml(e, {
|
|
270
|
+
allowDangerousXml: true,
|
|
271
|
+
closeEmptyElements: true,
|
|
272
|
+
}),
|
|
273
|
+
);
|
|
274
|
+
const doc = Doc.vsep([
|
|
275
|
+
Doc.text(`export const Floor${layer.name} = () => {`),
|
|
276
|
+
Doc.text(` return <>`),
|
|
277
|
+
Doc.text(jsx),
|
|
278
|
+
Doc.text(` </>`),
|
|
279
|
+
Doc.text(`}`),
|
|
280
|
+
]);
|
|
281
|
+
return Doc.render(doc, { style: "pretty" });
|
|
282
|
+
};
|
|
283
|
+
var handleFloors = (layers, dir) => {
|
|
284
|
+
for (const layer of layers) {
|
|
285
|
+
const text7 = renderFloorTsx(layer);
|
|
286
|
+
try {
|
|
287
|
+
if (!fs.statSync(`${dir}/floors`)) {
|
|
288
|
+
fs.mkdirSync(`${dir}/floors`);
|
|
289
|
+
}
|
|
290
|
+
} catch (e) {
|
|
291
|
+
console.log(e);
|
|
292
|
+
}
|
|
293
|
+
fs.writeFileSync(`${dir}/floors/floor_${layer.name}.tsx`, text7, "utf8");
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// src/lib/inkscape/addresses-addresses.ts
|
|
298
|
+
import * as fs2 from "fs";
|
|
299
|
+
import { is as is3 } from "unist-util-is";
|
|
300
|
+
import { visitParents as visitParents2 } from "unist-util-visit-parents";
|
|
301
|
+
var allAddresses = /* @__PURE__ */ new Map();
|
|
302
|
+
var allPoints = /* @__PURE__ */ new Map();
|
|
303
|
+
var saveAllAddressesAndPoints = (ast) => {
|
|
304
|
+
visitParents2(ast, (e, parents) => {
|
|
305
|
+
if (is3(e, "element")) {
|
|
306
|
+
if (isPoint(e)) {
|
|
307
|
+
const a = buildAddress(e, parents);
|
|
308
|
+
const p = getPoint(e);
|
|
309
|
+
if (a !== null && p !== null) {
|
|
310
|
+
allAddresses.set(a, p);
|
|
311
|
+
const s = `${p.x},${p.y}`;
|
|
312
|
+
let xs = allPoints.get(s);
|
|
313
|
+
if (xs === void 0) {
|
|
314
|
+
xs = [];
|
|
315
|
+
}
|
|
316
|
+
xs.push(a);
|
|
317
|
+
allPoints.set(s, xs);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
console.log("allAddresses:", allAddresses);
|
|
323
|
+
console.log("allPoints:", allPoints);
|
|
324
|
+
};
|
|
325
|
+
var Addresses = class extends Map {};
|
|
326
|
+
var saveAddrresses = (name) => {
|
|
327
|
+
const addresses = new Addresses();
|
|
328
|
+
for (const [k, v] of allAddresses.entries()) {
|
|
329
|
+
if (k.match(`^A${name}-.*$`)) {
|
|
330
|
+
addresses.set(k, v);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
console.log("saveAddresses:", name, "->", addresses);
|
|
334
|
+
return addresses;
|
|
335
|
+
};
|
|
336
|
+
var renderAddresses = (addresses) => {
|
|
337
|
+
const replacer = (k, v) => {
|
|
338
|
+
if (v instanceof Map) {
|
|
339
|
+
const m = {};
|
|
340
|
+
for (const [mk, mv] of v.entries()) {
|
|
341
|
+
if (
|
|
342
|
+
typeof mk === "string" &&
|
|
343
|
+
typeof mv === "object" &&
|
|
344
|
+
"x" in mv &&
|
|
345
|
+
typeof mv.x === "number" &&
|
|
346
|
+
"y" in mv &&
|
|
347
|
+
typeof mv.y === "number" &&
|
|
348
|
+
"r" in mv &&
|
|
349
|
+
typeof mv.r === "number"
|
|
350
|
+
) {
|
|
351
|
+
m[mk] = { x: mv.x, y: mv.y, w: mv.r * 2 };
|
|
352
|
+
} else {
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return m;
|
|
356
|
+
} else {
|
|
357
|
+
return v;
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
return JSON.stringify(addresses, replacer, 2);
|
|
361
|
+
};
|
|
362
|
+
var handleAddrresses = (ast, dir) => {
|
|
363
|
+
for (const name of allLayerNames.filter((n) => n.match(/^[^()]/))) {
|
|
364
|
+
const addresses = saveAddrresses(name);
|
|
365
|
+
const text7 = renderAddresses(addresses);
|
|
366
|
+
try {
|
|
367
|
+
if (!fs2.statSync(`${dir}/addresses`)) {
|
|
368
|
+
fs2.mkdirSync(`${dir}/addresses`);
|
|
369
|
+
}
|
|
370
|
+
} catch (e) {
|
|
371
|
+
console.log(e);
|
|
372
|
+
}
|
|
373
|
+
fs2.writeFileSync(`${dir}/addresses/addresses_${name}.json`, text7, "utf8");
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
// src/lib/inkscape/addresses-resolved_addresses.ts
|
|
378
|
+
import * as fs3 from "fs";
|
|
379
|
+
import { is as is4 } from "unist-util-is";
|
|
380
|
+
import { visitParents as visitParents3 } from "unist-util-visit-parents";
|
|
381
|
+
var Addresses2 = class extends Map {};
|
|
382
|
+
var saveResolvedAddrresses = (ast) => {
|
|
383
|
+
const addresses = new Addresses2();
|
|
384
|
+
visitParents3(ast, (n) => {
|
|
385
|
+
if (is4(n, "element")) {
|
|
386
|
+
const label = n.attributes["inkscape:label"];
|
|
387
|
+
if (label?.match(/ @ /)) {
|
|
388
|
+
const [a, b] = label.split(/ @ /);
|
|
389
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
390
|
+
addresses.set(b, a);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
return addresses;
|
|
396
|
+
};
|
|
397
|
+
var renderResolvedAddresses = (addresses) => {
|
|
398
|
+
const o = Object.fromEntries(addresses.entries());
|
|
399
|
+
return JSON.stringify(o, null, 2);
|
|
400
|
+
};
|
|
401
|
+
var handleResolvedAddrresses = (ast, dir) => {
|
|
402
|
+
const resolvedAddresses = saveResolvedAddrresses(ast);
|
|
403
|
+
const text7 = renderResolvedAddresses(resolvedAddresses);
|
|
404
|
+
try {
|
|
405
|
+
if (!fs3.statSync(`${dir}/addresses`)) {
|
|
406
|
+
fs3.mkdirSync(`${dir}/addresses`);
|
|
407
|
+
}
|
|
408
|
+
} catch (e) {
|
|
409
|
+
console.log(e);
|
|
410
|
+
}
|
|
411
|
+
fs3.writeFileSync(`${dir}/addresses/resolved_addresses.json`, text7, "utf8");
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// src/lib/inkscape/assets.ts
|
|
415
|
+
import * as Doc2 from "@effect/printer/Doc";
|
|
416
|
+
import { pipe as pipe3 } from "effect";
|
|
417
|
+
import * as fs4 from "fs";
|
|
418
|
+
import { is as is5 } from "unist-util-is";
|
|
419
|
+
import { visitParents as visitParents4 } from "unist-util-visit-parents";
|
|
420
|
+
import { toXml as toXml2 } from "xast-util-to-xml";
|
|
421
|
+
var allAssets = [];
|
|
422
|
+
var saveAllAssets = (ast) => {
|
|
423
|
+
const subtrees = [];
|
|
424
|
+
visitParents4(ast, (n) => {
|
|
425
|
+
if (is5(n, "element")) {
|
|
426
|
+
const groupmode = n.attributes["inkscape:groupmode"];
|
|
427
|
+
const label = n.attributes["inkscape:label"];
|
|
428
|
+
if (groupmode && groupmode === "layer" && label && label === "(Assets)") {
|
|
429
|
+
subtrees.push(n);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
if (subtrees.length !== 1) {
|
|
434
|
+
return [];
|
|
435
|
+
}
|
|
436
|
+
const subtree = subtrees[0];
|
|
437
|
+
visitParents4(subtree, (n) => {
|
|
438
|
+
if (is5(n, "element") && n.name === "g") {
|
|
439
|
+
const id = n.attributes["id"];
|
|
440
|
+
if (id) {
|
|
441
|
+
if (id.match(/^[^A-Z].*$/)) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
if (id.match(/^XShop.*$/)) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
allAssets.push(n);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
};
|
|
452
|
+
var renderAssets = (assets) => {
|
|
453
|
+
const jsx = pipe3(
|
|
454
|
+
assets,
|
|
455
|
+
(elems) => elems.map(fixupElements),
|
|
456
|
+
(elems) =>
|
|
457
|
+
toXml2(elems, {
|
|
458
|
+
allowDangerousXml: true,
|
|
459
|
+
closeEmptyElements: true,
|
|
460
|
+
}),
|
|
461
|
+
);
|
|
462
|
+
const doc = Doc2.vsep([
|
|
463
|
+
Doc2.text(`export const assets = () => {`),
|
|
464
|
+
Doc2.text(` return <>`),
|
|
465
|
+
Doc2.text(jsx),
|
|
466
|
+
Doc2.text(` </>`),
|
|
467
|
+
Doc2.text(`}`),
|
|
468
|
+
]);
|
|
469
|
+
return Doc2.render(doc, { style: "pretty" });
|
|
470
|
+
};
|
|
471
|
+
var handleAssets = (ast, dir) => {
|
|
472
|
+
const assets = allAssets;
|
|
473
|
+
const text7 = renderAssets(assets);
|
|
474
|
+
fs4.writeFileSync(`${dir}/assets.tsx`, text7, "utf8");
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
// src/lib/inkscape/facilities.ts
|
|
478
|
+
import * as fs5 from "fs";
|
|
479
|
+
var allLinks = /* @__PURE__ */ new Map();
|
|
480
|
+
var saveFacilities = () => {
|
|
481
|
+
let n = 1;
|
|
482
|
+
for (const [, v] of allPoints.entries()) {
|
|
483
|
+
if (v.length < 2) {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
const xs = v.filter((a) => a.match(/^.*-Facilities-.*$/));
|
|
487
|
+
if (xs.length < 2) {
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
const xxs = xs.filter((a) => a.match(/^.*(Elevator|Stairs).*$/));
|
|
491
|
+
if (xxs.length < 2) {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
allLinks.set(n, xxs);
|
|
495
|
+
n = n + 1;
|
|
496
|
+
}
|
|
497
|
+
console.log("allLinks:", allLinks);
|
|
498
|
+
return {
|
|
499
|
+
biLinks: allLinks,
|
|
500
|
+
};
|
|
501
|
+
};
|
|
502
|
+
var renderFacilities = (m) => {
|
|
503
|
+
const replacer = (k, v) => {
|
|
504
|
+
if (v instanceof Map) {
|
|
505
|
+
const m2 = {};
|
|
506
|
+
for (const [mk, mv] of v.entries()) {
|
|
507
|
+
if (typeof mk === "number") {
|
|
508
|
+
m2[`${mk}`] = mv;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return m2;
|
|
512
|
+
} else {
|
|
513
|
+
return v;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
return JSON.stringify(m, replacer, 2);
|
|
517
|
+
};
|
|
518
|
+
var handleFacilities = (ast, dir) => {
|
|
519
|
+
const facilities = saveFacilities();
|
|
520
|
+
const text7 = renderFacilities(facilities);
|
|
521
|
+
fs5.writeFileSync(`${dir}/facilities.json`, text7, "utf8");
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// src/lib/inkscape/floors-addresses.ts
|
|
525
|
+
import * as Doc3 from "@effect/printer/Doc";
|
|
526
|
+
import * as fs6 from "fs";
|
|
527
|
+
var renderAddressesTs = (layers) => {
|
|
528
|
+
const names = layers.map((l) => l.name);
|
|
529
|
+
const doc = Doc3.vsep([
|
|
530
|
+
Doc3.text(`import { FloorName } from '../floors/names'`),
|
|
531
|
+
Doc3.vsep(
|
|
532
|
+
names.map((n) =>
|
|
533
|
+
Doc3.text(`import addresses${n}Json from './addresses_${n}.json'`),
|
|
534
|
+
),
|
|
535
|
+
),
|
|
536
|
+
Doc3.text(``),
|
|
537
|
+
Doc3.text(`export type Address =`),
|
|
538
|
+
Doc3.vsep(
|
|
539
|
+
names.map((x2) => Doc3.text(` | keyof typeof addresses${x2}Json`)),
|
|
540
|
+
),
|
|
541
|
+
Doc3.text(``),
|
|
542
|
+
Doc3.text(`interface Point {`),
|
|
543
|
+
Doc3.text(` x: number`),
|
|
544
|
+
Doc3.text(` y: number`),
|
|
545
|
+
Doc3.text(` w: number`),
|
|
546
|
+
Doc3.text(`}`),
|
|
547
|
+
Doc3.text(``),
|
|
548
|
+
Doc3.text(`type Addresses = Partial<Record<Address, Point>>`),
|
|
549
|
+
Doc3.text(``),
|
|
550
|
+
Doc3.text(`export const floorAddresses: Record<FloorName, Addresses> = {`),
|
|
551
|
+
Doc3.vsep(names.map((x2) => Doc3.text(` '${x2}': addresses${x2}Json,`))),
|
|
552
|
+
Doc3.text(`}`),
|
|
553
|
+
]);
|
|
554
|
+
return Doc3.render(doc, { style: "pretty" });
|
|
555
|
+
};
|
|
556
|
+
var handleFloorAddresses = (layers, dir) => {
|
|
557
|
+
const text7 = renderAddressesTs(layers);
|
|
558
|
+
try {
|
|
559
|
+
if (!fs6.statSync(`${dir}/addresses`)) {
|
|
560
|
+
fs6.mkdirSync(`${dir}/addresses`);
|
|
561
|
+
}
|
|
562
|
+
} catch (e) {
|
|
563
|
+
console.log(e);
|
|
564
|
+
}
|
|
565
|
+
fs6.writeFileSync(`${dir}/addresses/addresses.ts`, text7, "utf8");
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
// src/lib/inkscape/floors-names.ts
|
|
569
|
+
import * as Doc4 from "@effect/printer/Doc";
|
|
570
|
+
import * as fs7 from "fs";
|
|
571
|
+
var renderNamesTs = (layers) => {
|
|
572
|
+
const names = layers.map((l) => l.name);
|
|
573
|
+
const doc = Doc4.vsep([
|
|
574
|
+
Doc4.text(`export type FloorName = string`),
|
|
575
|
+
Doc4.text(``),
|
|
576
|
+
Doc4.text(`type NonEmptyReadonlyArray<T> = [T, ...Array<T>]`),
|
|
577
|
+
Doc4.text(``),
|
|
578
|
+
Doc4.text(`export type FloorNames = NonEmptyReadonlyArray<FloorName>`),
|
|
579
|
+
Doc4.text(``),
|
|
580
|
+
Doc4.text(`export const FloorNames: FloorNames = [`),
|
|
581
|
+
Doc4.vsep(names.map((x2) => Doc4.text(` '${x2}',`))),
|
|
582
|
+
Doc4.text(`]`),
|
|
583
|
+
]);
|
|
584
|
+
return Doc4.render(doc, { style: "pretty" });
|
|
585
|
+
};
|
|
586
|
+
var handleFloorNames = (layers, dir) => {
|
|
587
|
+
const text7 = renderNamesTs(layers);
|
|
588
|
+
try {
|
|
589
|
+
if (!fs7.statSync(`${dir}/floors`)) {
|
|
590
|
+
fs7.mkdirSync(`${dir}/floors`);
|
|
591
|
+
}
|
|
592
|
+
} catch (e) {
|
|
593
|
+
console.log(e);
|
|
594
|
+
}
|
|
595
|
+
fs7.writeFileSync(`${dir}/floors/names.ts`, text7, "utf8");
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
// src/lib/inkscape/floors-renderers.ts
|
|
599
|
+
import * as Doc5 from "@effect/printer/Doc";
|
|
600
|
+
import * as fs8 from "fs";
|
|
601
|
+
var renderRenderersTs = (layers) => {
|
|
602
|
+
const names = layers.map((l) => l.name);
|
|
603
|
+
const doc = Doc5.vsep([
|
|
604
|
+
Doc5.vsep(
|
|
605
|
+
names.map((n) => Doc5.text(`import { Floor${n} } from './floor_${n}'`)),
|
|
606
|
+
),
|
|
607
|
+
Doc5.text(``),
|
|
608
|
+
Doc5.text(`export const renderers = {`),
|
|
609
|
+
Doc5.vsep(names.map((x2) => Doc5.text(` '${x2}': Floor${x2},`))),
|
|
610
|
+
Doc5.text(`}`),
|
|
611
|
+
]);
|
|
612
|
+
return Doc5.render(doc, { style: "pretty" });
|
|
613
|
+
};
|
|
614
|
+
var handleFloorRenderers = (layers, dir) => {
|
|
615
|
+
const text7 = renderRenderersTs(layers);
|
|
616
|
+
try {
|
|
617
|
+
if (!fs8.statSync(`${dir}/floors`)) {
|
|
618
|
+
fs8.mkdirSync(`${dir}/floors`);
|
|
619
|
+
}
|
|
620
|
+
} catch (e) {
|
|
621
|
+
console.log(e);
|
|
622
|
+
}
|
|
623
|
+
fs8.writeFileSync(`${dir}/floors/renderers.ts`, text7, "utf8");
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
// src/lib/inkscape/layers.ts
|
|
627
|
+
import { is as is6 } from "unist-util-is";
|
|
628
|
+
import { visitParents as visitParents5 } from "unist-util-visit-parents";
|
|
629
|
+
var saveFloorLayers = (ast, layerNames) => {
|
|
630
|
+
const layers = [];
|
|
631
|
+
layerNames.forEach((layerName) => {
|
|
632
|
+
const trees = [];
|
|
633
|
+
visitParents5(ast, (n) => {
|
|
634
|
+
if (is6(n, "element")) {
|
|
635
|
+
if (n.attributes["inkscape:label"] === layerName) {
|
|
636
|
+
trees.push({ name: layerName, element: n });
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
if (trees.length !== 1) {
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
const layer = trees[0];
|
|
644
|
+
layer.element.children.forEach((child) => {
|
|
645
|
+
if (is6(child, "element")) {
|
|
646
|
+
if (child.attributes["inkscape:label"] === "Content") {
|
|
647
|
+
layers.push({ name: layer.name, element: child });
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
return layers;
|
|
653
|
+
};
|
|
654
|
+
var handleFloorLayers = (ast, dir) => {
|
|
655
|
+
const layers = saveFloorLayers(ast, allLayerNames);
|
|
656
|
+
handleFloorNames(layers, dir);
|
|
657
|
+
handleFloorAddresses(layers, dir);
|
|
658
|
+
handleFloors(layers, dir);
|
|
659
|
+
handleFloorRenderers(layers, dir);
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
// src/lib/inkscape/markers.ts
|
|
663
|
+
import * as Doc6 from "@effect/printer/Doc";
|
|
664
|
+
import { pipe as pipe4 } from "effect";
|
|
665
|
+
import * as fs9 from "fs";
|
|
666
|
+
import { is as is7 } from "unist-util-is";
|
|
667
|
+
import { visitParents as visitParents6 } from "unist-util-visit-parents";
|
|
668
|
+
import { toXml as toXml3 } from "xast-util-to-xml";
|
|
669
|
+
var saveMarkers = (ast) => {
|
|
670
|
+
const markers = [];
|
|
671
|
+
const colors = /* @__PURE__ */ new Set();
|
|
672
|
+
visitParents6(ast, (n) => {
|
|
673
|
+
if (is7(n, "element") && n.name === "path") {
|
|
674
|
+
const start = n.attributes["marker-start"];
|
|
675
|
+
const end = n.attributes["marker-end"];
|
|
676
|
+
const stroke = n.attributes["stroke"];
|
|
677
|
+
if (typeof stroke === "string") {
|
|
678
|
+
colors.add(stroke);
|
|
679
|
+
const s = stroke.replace(/#/, "");
|
|
680
|
+
if (typeof start === "string") {
|
|
681
|
+
n.attributes["marker-start"] = `url(\\#Triangle-${s})`;
|
|
682
|
+
}
|
|
683
|
+
if (typeof end === "string") {
|
|
684
|
+
n.attributes["marker-end"] = `url(\\#Triangle-${s})`;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
visitParents6(ast, (n) => {
|
|
690
|
+
if (is7(n, "element") && n.name === "marker") {
|
|
691
|
+
markers.push(n);
|
|
692
|
+
const id = n.attributes["id"];
|
|
693
|
+
for (const color of colors) {
|
|
694
|
+
const s = color.replace(/#/, "");
|
|
695
|
+
const m = structuredClone(n);
|
|
696
|
+
m.attributes["id"] = `${id}-${s}`;
|
|
697
|
+
visitParents6(m, (mm) => {
|
|
698
|
+
if (is7(mm, "element") && mm.name === "path") {
|
|
699
|
+
mm.attributes["fill"] = `${color}`;
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
markers.push(m);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
return markers;
|
|
707
|
+
};
|
|
708
|
+
var renderMarkersTsx = (markers) => {
|
|
709
|
+
const jsx = pipe4(
|
|
710
|
+
markers,
|
|
711
|
+
(elems) => elems.map(fixupElements),
|
|
712
|
+
(elems) =>
|
|
713
|
+
toXml3(elems, {
|
|
714
|
+
allowDangerousXml: true,
|
|
715
|
+
closeEmptyElements: true,
|
|
716
|
+
}),
|
|
717
|
+
);
|
|
718
|
+
const doc = Doc6.vsep([
|
|
719
|
+
Doc6.text(`export const markers = () => {`),
|
|
720
|
+
Doc6.text(` return <>`),
|
|
721
|
+
Doc6.text(jsx),
|
|
722
|
+
Doc6.text(` </>`),
|
|
723
|
+
Doc6.text(`}`),
|
|
724
|
+
]);
|
|
725
|
+
return Doc6.render(doc, { style: "pretty" });
|
|
726
|
+
};
|
|
727
|
+
var handleMarkers = (ast, dir) => {
|
|
728
|
+
const markers = saveMarkers(ast);
|
|
729
|
+
const text7 = renderMarkersTsx(markers);
|
|
730
|
+
fs9.writeFileSync(`${dir}/markers.tsx`, text7, "utf8");
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
// src/lib/inkscape/viewbox.ts
|
|
734
|
+
import * as fs10 from "fs";
|
|
735
|
+
import { is as is8 } from "unist-util-is";
|
|
736
|
+
import { visitParents as visitParents7 } from "unist-util-visit-parents";
|
|
737
|
+
var ParseError = class {
|
|
738
|
+
_tag = "ParseError";
|
|
739
|
+
};
|
|
740
|
+
var parseViewBox = (s) => {
|
|
741
|
+
const xs = s.split(/ +/).map((x2) => parseFloat(x2));
|
|
742
|
+
if (xs.length !== 4) {
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
for (const x2 of xs) {
|
|
746
|
+
if (isNaN(x2)) {
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
return {
|
|
751
|
+
x: xs[0],
|
|
752
|
+
y: xs[1],
|
|
753
|
+
width: xs[2],
|
|
754
|
+
height: xs[3],
|
|
755
|
+
};
|
|
756
|
+
};
|
|
757
|
+
var saveViewBox = (ast) => {
|
|
758
|
+
const foundViewBoxes = [];
|
|
759
|
+
visitParents7(ast, (n, parents) => {
|
|
760
|
+
if (
|
|
761
|
+
parents.length === 1 &&
|
|
762
|
+
is8(parents[0], "root") &&
|
|
763
|
+
is8(n, "element") &&
|
|
764
|
+
n.name === "svg"
|
|
765
|
+
) {
|
|
766
|
+
const viewBox = n.attributes["viewBox"];
|
|
767
|
+
if (viewBox) {
|
|
768
|
+
const found = parseViewBox(viewBox);
|
|
769
|
+
if (found !== null) {
|
|
770
|
+
foundViewBoxes.push(found);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
return foundViewBoxes;
|
|
776
|
+
};
|
|
777
|
+
var renderViewBox = (viewBox) => {
|
|
778
|
+
return JSON.stringify(viewBox, null, 2);
|
|
779
|
+
};
|
|
780
|
+
var handleViewBox = (ast, dir) => {
|
|
781
|
+
const foundViewBoxes = saveViewBox(ast);
|
|
782
|
+
if (foundViewBoxes.length !== 1) {
|
|
783
|
+
throw new ParseError();
|
|
784
|
+
}
|
|
785
|
+
fs10.writeFileSync(
|
|
786
|
+
`${dir}/viewBox.json`,
|
|
787
|
+
renderViewBox(foundViewBoxes[0]),
|
|
788
|
+
"utf8",
|
|
789
|
+
);
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
// src/map-extract-floors.ts
|
|
793
|
+
import * as fs11 from "fs";
|
|
794
|
+
import { resolve } from "path";
|
|
795
|
+
import { fromXml } from "xast-util-from-xml";
|
|
796
|
+
var handleInkscapeSvg = (ast, dir) => {
|
|
797
|
+
saveAllFloorLayerNames(ast);
|
|
798
|
+
saveAllAssets(ast);
|
|
799
|
+
saveAllAddressesAndPoints(ast);
|
|
800
|
+
handleViewBox(ast, dir);
|
|
801
|
+
handleAddrresses(ast, dir);
|
|
802
|
+
handleResolvedAddrresses(ast, dir);
|
|
803
|
+
handleAssets(ast, dir);
|
|
804
|
+
handleMarkers(ast, dir);
|
|
805
|
+
handleFacilities(ast, dir);
|
|
806
|
+
handleFloorLayers(ast, dir);
|
|
807
|
+
};
|
|
808
|
+
var main = async (args) => {
|
|
809
|
+
if (args.length < 1) {
|
|
810
|
+
throw new Error();
|
|
811
|
+
}
|
|
812
|
+
const infile = resolve(args[0]);
|
|
813
|
+
const outdir = resolve(args.length === 2 ? args[1] : ".");
|
|
814
|
+
const bb = generateBoundingBoxCSV(infile, outdir);
|
|
815
|
+
parseBoundingBoxCSV(bb);
|
|
816
|
+
const svg = await fs11.readFileSync(infile);
|
|
817
|
+
const ast = fromXml(svg);
|
|
818
|
+
handleInkscapeSvg(ast, outdir);
|
|
819
|
+
};
|
|
820
|
+
main(process.argv.slice(2));
|
|
821
|
+
//# sourceMappingURL=map-extract-floors.js.map
|